瀏覽代碼

chore: generate

opencode-agent[bot] 2 月之前
父節點
當前提交
93131b6e4c

+ 19 - 17
packages/core/src/catalog.ts

@@ -132,9 +132,14 @@ export const layer = Layer.effect(
     }
 
     const clone = (input: HashMap.HashMap<ProviderV2.ID, ProviderRecord>) =>
-      HashMap.fromIterable(HashMap.toEntries(input).map(([key, value]) => [key, { ...value, models: new Map(value.models) }] as const))
-
-    const context = (draft: { records: HashMap.HashMap<ProviderV2.ID, ProviderRecord>; data: ProviderRecord[] }): Context => {
+      HashMap.fromIterable(
+        HashMap.toEntries(input).map(([key, value]) => [key, { ...value, models: new Map(value.models) }] as const),
+      )
+
+    const context = (draft: {
+      records: HashMap.HashMap<ProviderV2.ID, ProviderRecord>
+      data: ProviderRecord[]
+    }): Context => {
       const result: Context = {
         data: draft.data,
         updateProvider: (providerID, fn) => result.provider.update(providerID, fn),
@@ -164,13 +169,10 @@ export const layer = Layer.effect(
         model: {
           update: (providerID, modelID, fn) => {
             const current = Option.getOrThrow(HashMap.get(draft.records, providerID))
-            const model = produce(
-              current.models.get(modelID) ?? ModelV2.Info.empty(providerID, modelID),
-              (draft) => {
-                fn(draft)
-                normalizeEndpoint(draft)
-              },
-            )
+            const model = produce(current.models.get(modelID) ?? ModelV2.Info.empty(providerID, modelID), (draft) => {
+              fn(draft)
+              normalizeEndpoint(draft)
+            })
             const next = {
               provider: current.provider,
               models: new Map(current.models).set(modelID, new ModelV2.Info({ ...model, id: modelID, providerID })),
@@ -226,9 +228,12 @@ export const layer = Layer.effect(
         const loader = { update: (_ctx: Context) => {} }
         loaders = [...loaders, loader]
         const scope = yield* Scope.Scope
-        yield* Scope.addFinalizer(scope, Effect.sync(() => {
-          loaders = loaders.filter((item) => item !== loader)
-        }).pipe(Effect.andThen(rebuild())))
+        yield* Scope.addFinalizer(
+          scope,
+          Effect.sync(() => {
+            loaders = loaders.filter((item) => item !== loader)
+          }).pipe(Effect.andThen(rebuild())),
+        )
         return Effect.fnUntraced(function* (update) {
           loader.update = update
           yield* rebuild()
@@ -349,7 +354,4 @@ export const layer = Layer.effect(
 
 const SMALL_MODEL_RE = /\b(nano|flash|lite|mini|haiku|small|fast)\b/
 
-export const defaultLayer = layer.pipe(
-  Layer.provide(EventV2.defaultLayer),
-  Layer.provide(PluginV2.defaultLayer),
-)
+export const defaultLayer = layer.pipe(Layer.provide(EventV2.defaultLayer), Layer.provide(PluginV2.defaultLayer))

+ 2 - 2
packages/core/src/plugin/provider/anthropic.ts

@@ -10,8 +10,8 @@ export const AnthropicPlugin = PluginV2.define({
           if (item.provider.endpoint.type !== "aisdk") continue
           if (item.provider.endpoint.package !== "@ai-sdk/anthropic") continue
           evt.provider.update(item.provider.id, (provider) => {
-          provider.options.headers["anthropic-beta"] =
-            "interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14"
+            provider.options.headers["anthropic-beta"] =
+              "interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14"
           })
         }
       }),

+ 5 - 1
packages/core/src/plugin/provider/google-vertex.ts

@@ -60,7 +60,11 @@ export const GoogleVertexPlugin = PluginV2.define({
       "catalog.transform": Effect.fn(function* (evt) {
         for (const item of evt.data) {
           if (item.provider.endpoint.type !== "aisdk") continue
-          if (item.provider.endpoint.package !== "@ai-sdk/google-vertex" && !item.provider.endpoint.package.includes("@ai-sdk/openai-compatible")) continue
+          if (
+            item.provider.endpoint.package !== "@ai-sdk/google-vertex" &&
+            !item.provider.endpoint.package.includes("@ai-sdk/openai-compatible")
+          )
+            continue
           const project = resolveProject(item.provider.options.aisdk.provider)
           const location = String(resolveLocation(item.provider.options.aisdk.provider))
           evt.provider.update(item.provider.id, (provider) => {

+ 3 - 3
packages/core/src/plugin/provider/nvidia.ts

@@ -11,9 +11,9 @@ export const NvidiaPlugin = PluginV2.define({
           if (item.provider.endpoint.package !== "@ai-sdk/openai-compatible") continue
           if (item.provider.endpoint.url !== "https://integrate.api.nvidia.com/v1") continue
           evt.provider.update(item.provider.id, (provider) => {
-          provider.options.headers["HTTP-Referer"] = "https://opencode.ai/"
-          provider.options.headers["X-Title"] = "opencode"
-          provider.options.headers["X-BILLING-INVOKE-ORIGIN"] ??= "OpenCode"
+            provider.options.headers["HTTP-Referer"] = "https://opencode.ai/"
+            provider.options.headers["X-Title"] = "opencode"
+            provider.options.headers["X-BILLING-INVOKE-ORIGIN"] ??= "OpenCode"
           })
         }
       }),

+ 35 - 8
packages/core/test/catalog.test.ts

@@ -26,7 +26,11 @@ describe("CatalogV2", () => {
 
       yield* load((catalog) =>
         catalog.provider.update(providerID, (provider) => {
-          provider.endpoint = { type: "aisdk", package: "@ai-sdk/openai-compatible", url: "https://default.example.com" }
+          provider.endpoint = {
+            type: "aisdk",
+            package: "@ai-sdk/openai-compatible",
+            url: "https://default.example.com",
+          }
           provider.options.aisdk.provider.baseURL = "https://override.example.com"
         }),
       )
@@ -48,7 +52,11 @@ describe("CatalogV2", () => {
 
       yield* load((catalog) => {
         catalog.provider.update(providerID, (provider) => {
-          provider.endpoint = { type: "aisdk", package: "@ai-sdk/openai-compatible", url: "https://provider.example.com" }
+          provider.endpoint = {
+            type: "aisdk",
+            package: "@ai-sdk/openai-compatible",
+            url: "https://provider.example.com",
+          }
         })
         catalog.model.update(providerID, modelID, (model) => {
           model.endpoint = { type: "aisdk", package: "@ai-sdk/openai-compatible", url: "https://model.example.com" }
@@ -73,7 +81,11 @@ describe("CatalogV2", () => {
 
       yield* load((catalog) => {
         catalog.provider.update(providerID, (provider) => {
-          provider.endpoint = { type: "aisdk", package: "@ai-sdk/openai-compatible", url: "https://provider.example.com" }
+          provider.endpoint = {
+            type: "aisdk",
+            package: "@ai-sdk/openai-compatible",
+            url: "https://provider.example.com",
+          }
         })
         catalog.model.update(providerID, modelID, () => {})
       })
@@ -125,11 +137,20 @@ describe("CatalogV2", () => {
       const providerID = ProviderV2.ID.make("test")
       const load = yield* catalog.loader()
 
-      yield* load((catalog) => catalog.provider.update(providerID, (provider) => { provider.name = "Before" }))
+      yield* load((catalog) =>
+        catalog.provider.update(providerID, (provider) => {
+          provider.name = "Before"
+        }),
+      )
       yield* plugin.add({
         id: PluginV2.ID.make("test-transform"),
         effect: Effect.succeed({
-          "catalog.transform": (evt) => Effect.sync(() => evt.provider.update(providerID, (provider) => { provider.name = "After" })),
+          "catalog.transform": (evt) =>
+            Effect.sync(() =>
+              evt.provider.update(providerID, (provider) => {
+                provider.name = "After"
+              }),
+            ),
         }),
       })
       yield* Effect.yieldNow
@@ -176,9 +197,15 @@ describe("CatalogV2", () => {
       const load = yield* catalog.loader()
 
       yield* load((catalog) => {
-        catalog.provider.update(providerID, (provider) => { provider.enabled = { via: "custom", data: {} } })
-        catalog.model.update(providerID, ModelV2.ID.make("old"), (model) => { model.time.released = DateTime.makeUnsafe(1000) })
-        catalog.model.update(providerID, ModelV2.ID.make("new"), (model) => { model.time.released = DateTime.makeUnsafe(2000) })
+        catalog.provider.update(providerID, (provider) => {
+          provider.enabled = { via: "custom", data: {} }
+        })
+        catalog.model.update(providerID, ModelV2.ID.make("old"), (model) => {
+          model.time.released = DateTime.makeUnsafe(1000)
+        })
+        catalog.model.update(providerID, ModelV2.ID.make("new"), (model) => {
+          model.time.released = DateTime.makeUnsafe(2000)
+        })
       })
 
       expect(Option.getOrUndefined(yield* catalog.model.default())?.id).toMatch("new")

+ 4 - 1
packages/core/test/plugin/provider-cerebras.test.ts

@@ -31,7 +31,10 @@ describe("CerebrasPlugin", () => {
           item.options.headers.Existing = "1"
         })
       })
-      expect((yield* catalog.provider.get(ProviderV2.ID.make("cerebras"))).options.headers).toEqual({ Existing: "1", "X-Cerebras-3rd-Party-Integration": "opencode" })
+      expect((yield* catalog.provider.get(ProviderV2.ID.make("cerebras"))).options.headers).toEqual({
+        Existing: "1",
+        "X-Cerebras-3rd-Party-Integration": "opencode",
+      })
     }),
   )
 

+ 6 - 2
packages/core/test/plugin/provider-github-copilot.test.ts

@@ -157,7 +157,9 @@ describe("GithubCopilotPlugin", () => {
         catalog.provider.update(ProviderV2.ID.make("github-copilot"), () => {})
         catalog.model.update(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5-chat-latest"), () => {})
       })
-      expect((yield* catalog.model.get(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5-chat-latest"))).enabled).toBe(false)
+      expect(
+        (yield* catalog.model.get(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5-chat-latest"))).enabled,
+      ).toBe(false)
     }),
   )
 
@@ -171,7 +173,9 @@ describe("GithubCopilotPlugin", () => {
         catalog.provider.update(ProviderV2.ID.make("custom-copilot"), () => {})
         catalog.model.update(ProviderV2.ID.make("custom-copilot"), ModelV2.ID.make("gpt-5-chat-latest"), () => {})
       })
-      expect((yield* catalog.model.get(ProviderV2.ID.make("custom-copilot"), ModelV2.ID.make("gpt-5-chat-latest"))).enabled).toBe(true)
+      expect(
+        (yield* catalog.model.get(ProviderV2.ID.make("custom-copilot"), ModelV2.ID.make("gpt-5-chat-latest"))).enabled,
+      ).toBe(true)
     }),
   )
 

+ 3 - 1
packages/core/test/plugin/provider-kilo.test.ts

@@ -50,7 +50,9 @@ describe("KiloPlugin", () => {
       yield* plugin.add(KiloPlugin)
       const load = yield* catalog.loader()
       yield* load((catalog) => {
-        const item = provider("kilo", { endpoint: { type: "aisdk", package: "@ai-sdk/openai-compatible", url: "https://api.kilo.ai/api/gateway" } })
+        const item = provider("kilo", {
+          endpoint: { type: "aisdk", package: "@ai-sdk/openai-compatible", url: "https://api.kilo.ai/api/gateway" },
+        })
         catalog.provider.update(item.id, (draft) => {
           draft.endpoint = item.endpoint
         })

+ 3 - 1
packages/core/test/plugin/provider-llmgateway.test.ts

@@ -58,7 +58,9 @@ describe("LLMGatewayPlugin", () => {
       yield* plugin.add(LLMGatewayPlugin)
       const load = yield* catalog.loader()
       yield* load((catalog) => {
-        const item = provider("llmgateway", { endpoint: { type: "aisdk", package: "@ai-sdk/openai-compatible", url: "https://api.llmgateway.io/v1" } })
+        const item = provider("llmgateway", {
+          endpoint: { type: "aisdk", package: "@ai-sdk/openai-compatible", url: "https://api.llmgateway.io/v1" },
+        })
         catalog.provider.update(item.id, (draft) => {
           draft.endpoint = item.endpoint
         })

+ 3 - 1
packages/core/test/plugin/provider-openai.test.ts

@@ -102,7 +102,9 @@ describe("OpenAIPlugin", () => {
         catalog.provider.update(item.id, () => {})
         catalog.model.update(item.id, ModelV2.ID.make("gpt-5-chat-latest"), () => {})
       })
-      expect((yield* catalog.model.get(ProviderV2.ID.make("custom-openai"), ModelV2.ID.make("gpt-5-chat-latest"))).enabled).toBe(true)
+      expect(
+        (yield* catalog.model.get(ProviderV2.ID.make("custom-openai"), ModelV2.ID.make("gpt-5-chat-latest"))).enabled,
+      ).toBe(true)
     }),
   )
 })

+ 11 - 4
packages/core/test/plugin/provider-openrouter.test.ts

@@ -77,7 +77,9 @@ describe("OpenRouterPlugin", () => {
       yield* plugin.add(OpenRouterPlugin)
       const load = yield* catalog.loader()
       yield* load((catalog) => {
-        const openrouter = provider("openrouter", { endpoint: { type: "aisdk", package: "@openrouter/ai-sdk-provider" } })
+        const openrouter = provider("openrouter", {
+          endpoint: { type: "aisdk", package: "@openrouter/ai-sdk-provider" },
+        })
         catalog.provider.update(openrouter.id, (item) => {
           item.endpoint = openrouter.endpoint
         })
@@ -91,8 +93,12 @@ describe("OpenRouterPlugin", () => {
         }
       })
 
-      expect((yield* catalog.model.get(ProviderV2.ID.make("openrouter"), ModelV2.ID.make("openai/gpt-5-chat"))).enabled).toBe(false)
-      expect((yield* catalog.model.get(ProviderV2.ID.make("openrouter"), ModelV2.ID.make("openai/gpt-5"))).enabled).toBe(true)
+      expect(
+        (yield* catalog.model.get(ProviderV2.ID.make("openrouter"), ModelV2.ID.make("openai/gpt-5-chat"))).enabled,
+      ).toBe(false)
+      expect(
+        (yield* catalog.model.get(ProviderV2.ID.make("openrouter"), ModelV2.ID.make("openai/gpt-5"))).enabled,
+      ).toBe(true)
       expect((yield* catalog.model.get(ProviderV2.ID.openai, ModelV2.ID.make("openai/gpt-5-chat"))).enabled).toBe(true)
     }),
   )
@@ -108,7 +114,8 @@ describe("OpenRouterPlugin", () => {
         catalog.model.update(ProviderV2.ID.make("custom-openrouter"), ModelV2.ID.make("gpt-5-chat-latest"), () => {})
       })
       expect(
-        (yield* catalog.model.get(ProviderV2.ID.make("custom-openrouter"), ModelV2.ID.make("gpt-5-chat-latest"))).enabled,
+        (yield* catalog.model.get(ProviderV2.ID.make("custom-openrouter"), ModelV2.ID.make("gpt-5-chat-latest")))
+          .enabled,
       ).toBe(true)
     }),
   )

+ 3 - 1
packages/core/test/plugin/provider-vercel.test.ts

@@ -43,7 +43,9 @@ describe("VercelPlugin", () => {
           draft.endpoint = item.endpoint
         })
       })
-      expect((yield* catalog.provider.get(ProviderV2.ID.make("vercel"))).options.headers).not.toHaveProperty("HTTP-Referer")
+      expect((yield* catalog.provider.get(ProviderV2.ID.make("vercel"))).options.headers).not.toHaveProperty(
+        "HTTP-Referer",
+      )
       expect((yield* catalog.provider.get(ProviderV2.ID.make("vercel"))).options.headers).not.toHaveProperty("X-Title")
     }),
   )

+ 3 - 1
packages/core/test/plugin/provider-zenmux.test.ts

@@ -24,7 +24,9 @@ describe("ZenmuxPlugin", () => {
       yield* plugin.add(ZenmuxPlugin)
       const load = yield* catalog.loader()
       yield* load((catalog) => {
-        const item = provider("zenmux", { endpoint: { type: "aisdk", package: "@ai-sdk/openai-compatible", url: "https://zenmux.ai/api/v1" } })
+        const item = provider("zenmux", {
+          endpoint: { type: "aisdk", package: "@ai-sdk/openai-compatible", url: "https://zenmux.ai/api/v1" },
+        })
         catalog.provider.update(item.id, (draft) => {
           draft.endpoint = item.endpoint
         })

+ 63 - 0
packages/sdk/js/src/v2/gen/types.gen.ts

@@ -78,6 +78,10 @@ export type Event =
   | EventSessionNextCompactionDelta
   | EventSessionNextCompactionEnded
   | EventCatalogModelUpdated
+  | EventModelsDevRefreshed
+  | EventAccountAdded
+  | EventAccountRemoved
+  | EventAccountSwitched
 
 export type OAuth = {
   type: "oauth"
@@ -874,6 +878,7 @@ export type GlobalEvent = {
     | EventSessionNextCompactionDelta
     | EventSessionNextCompactionEnded
     | EventCatalogModelUpdated
+    | EventModelsDevRefreshed
     | SyncEventMessageUpdated
     | SyncEventMessageRemoved
     | SyncEventMessagePartUpdated
@@ -3284,6 +3289,14 @@ export type EventCatalogModelUpdated = {
   }
 }
 
+export type EventModelsDevRefreshed = {
+  id: string
+  type: "models-dev.refreshed"
+  properties: {
+    [key: string]: unknown
+  }
+}
+
 export type SessionInfo = {
   id: string
   parentID?: string
@@ -3695,6 +3708,56 @@ export type ModelV2Info1 = {
   }
 }
 
+export type AccountV2oAuthCredential = {
+  type: "oauth"
+  refresh: string
+  access: string
+  expires: number
+}
+
+export type AccountV2ApiKeyCredential = {
+  type: "api"
+  key: string
+  metadata?: {
+    [key: string]: string
+  }
+}
+
+export type AccountV2Credential = AccountV2oAuthCredential | AccountV2ApiKeyCredential
+
+export type AccountV2Info = {
+  id: string
+  serviceID: string
+  description: string
+  credential: AccountV2Credential
+}
+
+export type EventAccountAdded = {
+  id: string
+  type: "account.added"
+  properties: {
+    account: AccountV2Info
+  }
+}
+
+export type EventAccountRemoved = {
+  id: string
+  type: "account.removed"
+  properties: {
+    account: AccountV2Info
+  }
+}
+
+export type EventAccountSwitched = {
+  id: string
+  type: "account.switched"
+  properties: {
+    serviceID: string
+    from?: string
+    to?: string
+  }
+}
+
 export type BadRequestError = {
   name: "BadRequest"
   data: {

+ 182 - 1
packages/sdk/openapi.json

@@ -10567,6 +10567,18 @@
           },
           {
             "$ref": "#/components/schemas/EventSessionNextCompactionEnded"
+          },
+          {
+            "$ref": "#/components/schemas/EventModels-devRefreshed"
+          },
+          {
+            "$ref": "#/components/schemas/EventAccountAdded"
+          },
+          {
+            "$ref": "#/components/schemas/EventAccountRemoved"
+          },
+          {
+            "$ref": "#/components/schemas/EventAccountSwitched"
           }
         ]
       },
@@ -12979,6 +12991,9 @@
               {
                 "$ref": "#/components/schemas/EventSessionNextCompactionEnded"
               },
+              {
+                "$ref": "#/components/schemas/EventModels-devRefreshed"
+              },
               {
                 "$ref": "#/components/schemas/SyncEventMessageUpdated"
               },
@@ -20308,6 +20323,24 @@
         "required": ["id", "type", "properties"],
         "additionalProperties": false
       },
+      "EventModels-devRefreshed": {
+        "type": "object",
+        "properties": {
+          "id": {
+            "type": "string"
+          },
+          "type": {
+            "type": "string",
+            "enum": ["models-dev.refreshed"]
+          },
+          "properties": {
+            "type": "object",
+            "properties": {}
+          }
+        },
+        "required": ["id", "type", "properties"],
+        "additionalProperties": false
+      },
       "SessionInfo": {
         "type": "object",
         "properties": {
@@ -21021,7 +21054,7 @@
                 "properties": {
                   "via": {
                     "type": "string",
-                    "enum": ["auth"]
+                    "enum": ["account"]
                   },
                   "service": {
                     "type": "string"
@@ -21543,6 +21576,154 @@
         ],
         "additionalProperties": false
       },
+      "AccountV2OAuthCredential": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": ["oauth"]
+          },
+          "refresh": {
+            "type": "string"
+          },
+          "access": {
+            "type": "string"
+          },
+          "expires": {
+            "type": "integer",
+            "minimum": 0
+          }
+        },
+        "required": ["type", "refresh", "access", "expires"],
+        "additionalProperties": false
+      },
+      "AccountV2ApiKeyCredential": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": ["api"]
+          },
+          "key": {
+            "type": "string"
+          },
+          "metadata": {
+            "type": "object",
+            "additionalProperties": {
+              "type": "string"
+            }
+          }
+        },
+        "required": ["type", "key"],
+        "additionalProperties": false
+      },
+      "AccountV2Credential": {
+        "anyOf": [
+          {
+            "$ref": "#/components/schemas/AccountV2OAuthCredential"
+          },
+          {
+            "$ref": "#/components/schemas/AccountV2ApiKeyCredential"
+          }
+        ]
+      },
+      "AccountV2Info": {
+        "type": "object",
+        "properties": {
+          "id": {
+            "type": "string"
+          },
+          "serviceID": {
+            "type": "string"
+          },
+          "description": {
+            "type": "string"
+          },
+          "credential": {
+            "$ref": "#/components/schemas/AccountV2Credential"
+          }
+        },
+        "required": ["id", "serviceID", "description", "credential"],
+        "additionalProperties": false
+      },
+      "EventAccountAdded": {
+        "type": "object",
+        "properties": {
+          "id": {
+            "type": "string"
+          },
+          "type": {
+            "type": "string",
+            "enum": ["account.added"]
+          },
+          "properties": {
+            "type": "object",
+            "properties": {
+              "account": {
+                "$ref": "#/components/schemas/AccountV2Info"
+              }
+            },
+            "required": ["account"],
+            "additionalProperties": false
+          }
+        },
+        "required": ["id", "type", "properties"],
+        "additionalProperties": false
+      },
+      "EventAccountRemoved": {
+        "type": "object",
+        "properties": {
+          "id": {
+            "type": "string"
+          },
+          "type": {
+            "type": "string",
+            "enum": ["account.removed"]
+          },
+          "properties": {
+            "type": "object",
+            "properties": {
+              "account": {
+                "$ref": "#/components/schemas/AccountV2Info"
+              }
+            },
+            "required": ["account"],
+            "additionalProperties": false
+          }
+        },
+        "required": ["id", "type", "properties"],
+        "additionalProperties": false
+      },
+      "EventAccountSwitched": {
+        "type": "object",
+        "properties": {
+          "id": {
+            "type": "string"
+          },
+          "type": {
+            "type": "string",
+            "enum": ["account.switched"]
+          },
+          "properties": {
+            "type": "object",
+            "properties": {
+              "serviceID": {
+                "type": "string"
+              },
+              "from": {
+                "type": "string"
+              },
+              "to": {
+                "type": "string"
+              }
+            },
+            "required": ["serviceID"],
+            "additionalProperties": false
+          }
+        },
+        "required": ["id", "type", "properties"],
+        "additionalProperties": false
+      },
       "BadRequestError": {
         "type": "object",
         "required": ["name", "data"],