From 9cc5e9875232818afbe5096e8fef45c19db3f90a Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Thu, 24 Sep 2026 11:09:16 +0200 Subject: [PATCH] feat: route plugin external fetches (probe + models) through CORS proxy ai-assistant-fig.dynv6.net; bump 0.1.17 --- package.json | 2 +- src/main.ts | 13 +++++++++++-- src/ui.tsx | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 8559f6f..3c65836 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "figma-ai-plugin", - "version": "0.1.16", + "version": "0.1.17", "private": true, "dependencies": { "@create-figma-plugin/ui": "^4.0.3", diff --git a/src/main.ts b/src/main.ts index 55ab82e..485f624 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,10 +1,19 @@ import { emit, on, showUI } from '@create-figma-plugin/utilities' +// CORS proxy (dev). Figma plugin has origin:null, so direct calls to APIs without +// Access-Control-Allow-Origin fail. Route external requests through this proxy, which +// adds `Access-Control-Allow-Origin: *`. Target host must be in the proxy allowlist +// (api.apinex.bond, apinex.bond, example.com) — no token needed for those. +const CORS_PROXY = 'https://ai-assistant-fig.dynv6.net/proxy' +function viaProxy (target: string): string { + return CORS_PROXY + '?url=' + encodeURIComponent(target) +} + // Probe whether the plugin sandbox can reach the public internet. // Used on plugin open (so the user sees network status immediately) and before each model fetch. async function probeConnectivity () { try { - const pr = await fetch('https://example.com') + const pr = await fetch(viaProxy('https://example.com')) emit('PROBE_RESULT', { msg: 'example.com reachable · status=' + pr.status }) } catch (pe) { emit('PROBE_RESULT', { msg: 'example.com UNREACHABLE · ' + (pe != null ? (typeof pe === 'string' ? pe : JSON.stringify(pe)) : 'unknown') }) @@ -529,7 +538,7 @@ export default function () { .replace(/^@url:\s*/i, '') // drop '@url:' annotation if pasted from chat .trim() .replace(/\/+$/, '') // drop trailing slashes - const res = await fetch(base + '/models', { + const res = await fetch(viaProxy(base + '/models'), { headers: { Authorization: 'Bearer ' + payload.apiKey } }) const raw = await res.text() diff --git a/src/ui.tsx b/src/ui.tsx index 5f955f0..d0d8a52 100644 --- a/src/ui.tsx +++ b/src/ui.tsx @@ -30,7 +30,7 @@ const MIN_WINDOW_SIZE = { width: 320, height: 200 } // very high — actual clamp is done by main via clampWindowSize (bounds*zoom). // Full plugin version shown in the footer status bar. Keep in sync with package.json "version". -const PLUGIN_VERSION = '0.1.16' +const PLUGIN_VERSION = '0.1.17' const fieldStyle = { display: 'flex',