From 51751f9ea7f5e54b1fd57a5d810b7a24d6f7e203 Mon Sep 17 00:00:00 2001 From: "shakespeare.diy" Date: Tue, 16 Jun 2026 20:33:35 +0700 Subject: [PATCH] fix: route Shakespeare AI calls through CORS proxy for iframe compatibility All fetch calls to ai.shakespeare.diy now go through proxy.shakespeare.diy so they work from inside the iframe.diy preview sandbox. The NIP-98 token is still signed against the original URL (not the proxy URL) so the server-side signature validation passes correctly. Affects: sendChatMessage, sendStreamingMessage, getAvailableModels Co-authored-by: shakespeare.diy --- src/hooks/useShakespeare.ts | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/src/hooks/useShakespeare.ts b/src/hooks/useShakespeare.ts index 951f302..4d23665 100644 --- a/src/hooks/useShakespeare.ts +++ b/src/hooks/useShakespeare.ts @@ -60,6 +60,12 @@ export interface ModelsResponse { // Configuration const SHAKESPEARE_API_URL = 'https://ai.shakespeare.diy/v1'; +// CORS proxy for iframe environments (proxy.shakespeare.diy passes through the request) +const CORS_PROXY = 'https://proxy.shakespeare.diy/?url='; + +function proxyUrl(url: string): string { + return `${CORS_PROXY}${encodeURIComponent(url)}`; +} // Helper function to create NIP-98 token async function createNIP98Token( @@ -174,14 +180,10 @@ export function useShakespeare() { ...options }; - const token = await createNIP98Token( - 'POST', - `${SHAKESPEARE_API_URL}/chat/completions`, - requestBody, - user - ); + const targetUrl = `${SHAKESPEARE_API_URL}/chat/completions`; + const token = await createNIP98Token('POST', targetUrl, requestBody, user); - const response = await fetch(`${SHAKESPEARE_API_URL}/chat/completions`, { + const response = await fetch(proxyUrl(targetUrl), { method: 'POST', headers: { 'Authorization': `Nostr ${token}`, @@ -237,14 +239,10 @@ export function useShakespeare() { ...options }; - const token = await createNIP98Token( - 'POST', - `${SHAKESPEARE_API_URL}/chat/completions`, - requestBody, - user - ); + const streamTargetUrl = `${SHAKESPEARE_API_URL}/chat/completions`; + const token = await createNIP98Token('POST', streamTargetUrl, requestBody, user); - const response = await fetch(`${SHAKESPEARE_API_URL}/chat/completions`, { + const response = await fetch(proxyUrl(streamTargetUrl), { method: 'POST', headers: { 'Authorization': `Nostr ${token}`, @@ -323,14 +321,10 @@ export function useShakespeare() { setError(null); try { - const token = await createNIP98Token( - 'GET', - `${SHAKESPEARE_API_URL}/models`, - undefined, - user - ); + const modelsUrl = `${SHAKESPEARE_API_URL}/models`; + const token = await createNIP98Token('GET', modelsUrl, undefined, user); - const response = await fetch(`${SHAKESPEARE_API_URL}/models`, { + const response = await fetch(proxyUrl(modelsUrl), { method: 'GET', headers: { 'Authorization': `Nostr ${token}`,