Skip to content

Commit c185882

Browse files
committed
fix(ai): construct OpenAIProvider via openAIClient in SDK Runner to pass proxy auth correctly
1 parent 193a4d8 commit c185882

2 files changed

Lines changed: 481 additions & 139 deletions

File tree

backend/src/ai/agent-sdk.ts

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
Agent as CFAgent,
2424
callable
2525
} from "agents";
26+
import { getOpenaiApiKey, getGeminiApiKey, getAnthropicApiKey } from "@utils/secrets";
2627
import {
2728
getAgentModel,
2829
getAiGatewayUrl as getAiGatewayBaseUrl,
@@ -188,20 +189,65 @@ export async function createRunner(
188189
// Reuse createGatewayClient logic for token/url resolution
189190
// but we need standard OpenAIProvider for Runner
190191

191-
// Get Token
192+
// Get AI Gateway Token
193+
let aigToken = "";
194+
try { aigToken = await env.AI_GATEWAY_TOKEN.get(); } catch (e) { /* ignore */ }
195+
196+
// Resolve Real API Key based on provider
192197
let apiKey = "";
193-
try { apiKey = await env.AI_GATEWAY_TOKEN.get(); } catch (e) { // empty
198+
if (resolvedProvider === 'openai') {
199+
apiKey = await getOpenaiApiKey(env) || "";
200+
} else if (resolvedProvider === 'google-ai-studio' || resolvedProvider === 'gemini') {
201+
apiKey = await getGeminiApiKey(env) || "";
202+
} else if (resolvedProvider === 'anthropic') {
203+
apiKey = await getAnthropicApiKey(env) || "";
194204
}
195-
if (!apiKey) try { apiKey = await env.CLOUDFLARE_API_TOKEN.get(); } catch (e) { // empty
205+
206+
// Fallback if no real key found
207+
if (!apiKey) {
208+
try { apiKey = await env.CLOUDFLARE_API_TOKEN.get(); } catch (e) { /* ignore */ }
196209
}
197210
if (!apiKey) apiKey = "dummy-key";
198211

199212
// Get URL
200213
const baseURL = await getAiGatewayBaseUrl(env, resolvedProvider, 'openai_agents_sdk');
201214

202-
const modelProvider: ModelProvider = new OpenAIProvider({
215+
// Custom fetch wrapper to inject gateway headers and defaults
216+
const wrappedFetch: typeof globalThis.fetch = async (input, init) => {
217+
let newInit = init ? { ...init } : {};
218+
219+
// Inject Gateway Auth Header
220+
if (aigToken) {
221+
newInit.headers = {
222+
...(newInit.headers || {}),
223+
'cf-aig-authorization': `Bearer ${aigToken}`
224+
};
225+
}
226+
227+
// OpenAI Agents SDK has no built-in max_tokens config for Runner, so we inject safely
228+
if (newInit.body && typeof newInit.body === 'string') {
229+
try {
230+
const bodyObj = JSON.parse(newInit.body);
231+
if (!bodyObj.max_tokens) bodyObj.max_tokens = 4096;
232+
if (bodyObj.temperature === undefined) bodyObj.temperature = 0.1;
233+
newInit.body = JSON.stringify(bodyObj);
234+
} catch(e) {
235+
/* ignore parsing errors */
236+
}
237+
}
238+
239+
return globalThis.fetch(input, newInit);
240+
};
241+
242+
const client = new OpenAI({
243+
baseURL,
203244
apiKey,
204-
baseURL,
245+
dangerouslyAllowBrowser: true,
246+
fetch: wrappedFetch,
247+
});
248+
249+
const modelProvider: ModelProvider = new OpenAIProvider({
250+
openAIClient: client, // Use the pre-configured custom client instead of letting it build one
205251
});
206252

207253
return new Runner({

0 commit comments

Comments
 (0)