فهرست منبع

refactor(ai): simplify provider options (#39924)

Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
opencode-agent[bot] 2 هفته پیش
والد
کامیت
b69e51d835

+ 13 - 12
packages/ai/src/providers/openrouter.ts

@@ -143,23 +143,24 @@ const cacheControl = () => {
 
 const bodyOptions = (input: unknown) => {
   const openrouter = isRecord(input) ? input : {}
-  const { promptCacheKey, ...options } = openrouter
+  const { usage, models, provider, plugins, web_search_options, debug, user, reasoning, promptCacheKey, ...options } =
+    openrouter
   return {
     ...options,
-    ...(openrouter.usage === undefined || openrouter.usage === true
+    ...(usage === undefined || usage === true
       ? { usage: { include: true } }
-      : openrouter.usage === false
+      : usage === false
         ? { usage: { include: false } }
-        : isRecord(openrouter.usage)
-          ? { usage: openrouter.usage }
+        : isRecord(usage)
+          ? { usage }
           : {}),
-    ...(Array.isArray(openrouter.models) ? { models: openrouter.models } : {}),
-    ...(isRecord(openrouter.provider) ? { provider: openrouter.provider } : {}),
-    ...(Array.isArray(openrouter.plugins) ? { plugins: openrouter.plugins } : {}),
-    ...(isRecord(openrouter.web_search_options) ? { web_search_options: openrouter.web_search_options } : {}),
-    ...(isRecord(openrouter.debug) ? { debug: openrouter.debug } : {}),
-    ...(typeof openrouter.user === "string" ? { user: openrouter.user } : {}),
-    ...(isRecord(openrouter.reasoning) ? { reasoning: openrouter.reasoning } : {}),
+    ...(Array.isArray(models) ? { models } : {}),
+    ...(isRecord(provider) ? { provider } : {}),
+    ...(Array.isArray(plugins) ? { plugins } : {}),
+    ...(isRecord(web_search_options) ? { web_search_options } : {}),
+    ...(isRecord(debug) ? { debug } : {}),
+    ...(typeof user === "string" ? { user } : {}),
+    ...(isRecord(reasoning) ? { reasoning } : {}),
     ...(typeof promptCacheKey === "string" ? { prompt_cache_key: promptCacheKey } : {}),
   }
 }

+ 37 - 0
packages/ai/test/provider/openrouter.test.ts

@@ -192,6 +192,43 @@ describe("OpenRouter", () => {
     }),
   )
 
+  it.effect("filters invalid known OpenRouter options while preserving extensions", () =>
+    Effect.gen(function* () {
+      const invalid: Record<string, unknown> = {
+        usage: "yes",
+        models: "anthropic/claude-sonnet-4.6",
+        provider: [],
+        plugins: {},
+        web_search_options: [],
+        debug: [],
+        user: 123,
+        reasoning: [],
+        promptCacheKey: 123,
+        future_option: { enabled: true },
+      }
+      const prepared = yield* compileRequest(
+        LLM.request({
+          model: OpenRouter.configure({
+            apiKey: "test-key",
+            providerOptions: { openrouter: invalid },
+          }).model("openai/gpt-4o-mini"),
+          prompt: "Hello",
+        }),
+      )
+
+      expect(prepared.body).toMatchObject({ future_option: { enabled: true } })
+      expect(prepared.body).not.toHaveProperty("usage")
+      expect(prepared.body).not.toHaveProperty("models")
+      expect(prepared.body).not.toHaveProperty("provider")
+      expect(prepared.body).not.toHaveProperty("plugins")
+      expect(prepared.body).not.toHaveProperty("web_search_options")
+      expect(prepared.body).not.toHaveProperty("debug")
+      expect(prepared.body).not.toHaveProperty("user")
+      expect(prepared.body).not.toHaveProperty("reasoning")
+      expect(prepared.body).not.toHaveProperty("prompt_cache_key")
+    }),
+  )
+
   it.effect("preserves the upstream provider finish reason", () =>
     Effect.gen(function* () {
       const model = OpenRouter.configure({ apiKey: "test-key" }).model("anthropic/claude-sonnet-4.6")

+ 1 - 4
packages/core/src/session/generate-node.ts

@@ -71,10 +71,7 @@ export const layer = Layer.effect(
           LLM.request({
             model: model.model,
             http: { headers: SessionModelHeaders.make(selection.session, app) },
-            providerOptions:
-              model.model.route.id === "openrouter"
-                ? { openrouter: { promptCacheKey } }
-                : { openai: { promptCacheKey } },
+            providerOptions: { [providerMetadataKey]: { promptCacheKey } },
             system: contextEvent.system,
             messages: contextEvent.messages,
             tools: hookedTools,

+ 1 - 4
packages/core/src/session/model-request.ts

@@ -158,10 +158,7 @@ export const layer = Layer.effect(
         http: {
           headers: SessionModelHeaders.make(session, app),
         },
-        providerOptions:
-          model.route.id === "openrouter"
-            ? { openrouter: { promptCacheKey } }
-            : { openai: { promptCacheKey } },
+        providerOptions: { [providerMetadataKey]: { promptCacheKey } },
         system: contextEvent.system,
         messages: unsupportedParts(contextEvent.messages, resolved.capabilities),
         tools: hookedTools,