refactor(core): remove ai sdk option fields (#30581)
This commit is contained in:
@@ -107,10 +107,9 @@ describe("ConfigAgentPlugin.Plugin", () => {
|
||||
hidden: true,
|
||||
color: "warning",
|
||||
steps: 12,
|
||||
options: {
|
||||
request: {
|
||||
headers: { first: "one", shared: "first" },
|
||||
body: { enabled: true },
|
||||
aisdk: { provider: { profile: "review" }, request: { effort: "medium" } },
|
||||
body: { enabled: true, profile: "review", effort: "medium" },
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -121,10 +120,9 @@ describe("ConfigAgentPlugin.Plugin", () => {
|
||||
info: decode({
|
||||
agents: {
|
||||
reviewer: {
|
||||
options: {
|
||||
request: {
|
||||
headers: { shared: "last", second: "two" },
|
||||
body: { retries: 2 },
|
||||
aisdk: { request: { effort: "high" } },
|
||||
body: { retries: 2, effort: "high" },
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -149,10 +147,9 @@ describe("ConfigAgentPlugin.Plugin", () => {
|
||||
steps: 12,
|
||||
model: { providerID: "anthropic", id: "claude-sonnet", variant: undefined },
|
||||
})
|
||||
expect(reviewer.options).toEqual({
|
||||
expect(reviewer.request).toEqual({
|
||||
headers: { first: "one", shared: "last", second: "two" },
|
||||
body: { enabled: true, retries: 2 },
|
||||
aisdk: { provider: { profile: "review" }, request: { effort: "high" } },
|
||||
body: { enabled: true, profile: "review", retries: 2, effort: "high" },
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import path from "path"
|
||||
import fs from "fs/promises"
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { Effect, Layer, Schema } from "effect"
|
||||
import { FastCheck } from "effect/testing"
|
||||
import { Config } from "@opencode-ai/core/config"
|
||||
import { ConfigProvider } from "@opencode-ai/core/config/provider"
|
||||
import { ConfigMigrateV1 } from "@opencode-ai/core/v1/config/migrate"
|
||||
import { ConfigV1 } from "@opencode-ai/core/v1/config/config"
|
||||
import { FSUtil } from "@opencode-ai/core/fs-util"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import { Location } from "@opencode-ai/core/location"
|
||||
@@ -41,14 +43,10 @@ function testLayer(
|
||||
}
|
||||
|
||||
const provider = {
|
||||
endpoint: { type: "unknown" },
|
||||
options: {
|
||||
api: { type: "native", settings: {} },
|
||||
request: {
|
||||
headers: {},
|
||||
body: {},
|
||||
aisdk: {
|
||||
provider: {},
|
||||
request: {},
|
||||
},
|
||||
},
|
||||
models: {},
|
||||
}
|
||||
@@ -62,6 +60,46 @@ describe("Config", () => {
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("migrates arbitrary v1 configuration into valid v2 configuration", () =>
|
||||
Effect.sync(() => {
|
||||
FastCheck.assert(
|
||||
FastCheck.property(Schema.toArbitrary(ConfigV1.Info), (info) => {
|
||||
Schema.decodeUnknownSync(Config.Info)(ConfigMigrateV1.migrate(info), { errors: "all" })
|
||||
}),
|
||||
{ numRuns: 100 },
|
||||
)
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("migrates v1 provider setup options into AISDK settings", () =>
|
||||
Effect.sync(() => {
|
||||
const migrated = ConfigMigrateV1.migrate({
|
||||
provider: {
|
||||
bedrock: {
|
||||
npm: "@ai-sdk/amazon-bedrock",
|
||||
options: {
|
||||
headers: { "x-test": "1" },
|
||||
body: { trace: true },
|
||||
region: "us-east-1",
|
||||
profile: "dev",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(migrated.providers?.bedrock?.api).toEqual({
|
||||
type: "aisdk",
|
||||
package: "@ai-sdk/amazon-bedrock",
|
||||
url: undefined,
|
||||
settings: { region: "us-east-1", profile: "dev" },
|
||||
})
|
||||
expect(migrated.providers?.bedrock?.request).toEqual({
|
||||
headers: { "x-test": "1" },
|
||||
body: { trace: true },
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
it.live("returns an empty configuration when directory files do not exist", () =>
|
||||
Effect.acquireRelease(
|
||||
Effect.promise(() => tmpdir()),
|
||||
@@ -186,9 +224,9 @@ describe("Config", () => {
|
||||
reviewer: {
|
||||
model: "openrouter/openai/gpt-5",
|
||||
variant: "high",
|
||||
options: {
|
||||
request: {
|
||||
headers: { "x-agent": "reviewer" },
|
||||
aisdk: { request: { reasoningEffort: "high" } },
|
||||
body: { reasoningEffort: "high" },
|
||||
},
|
||||
description: "Review changes for correctness",
|
||||
system: "Find regressions.",
|
||||
@@ -266,22 +304,21 @@ describe("Config", () => {
|
||||
{ action: "bash", resource: "*", effect: "ask" },
|
||||
{ action: "bash", resource: "git status", effect: "allow" },
|
||||
])
|
||||
expect(documents[0]?.info.agents?.reviewer).toEqual({
|
||||
model: "openrouter/openai/gpt-5",
|
||||
variant: "high",
|
||||
options: {
|
||||
headers: { "x-agent": "reviewer" },
|
||||
aisdk: { request: { reasoningEffort: "high" } },
|
||||
},
|
||||
description: "Review changes for correctness",
|
||||
system: "Find regressions.",
|
||||
mode: "subagent",
|
||||
hidden: false,
|
||||
color: "warning",
|
||||
steps: 12,
|
||||
disabled: false,
|
||||
permissions: [{ action: "edit", resource: "*", effect: "deny" }],
|
||||
const reviewer = documents[0]?.info.agents?.reviewer
|
||||
expect(reviewer?.model).toBe("openrouter/openai/gpt-5")
|
||||
expect(reviewer?.variant).toBe("high")
|
||||
expect(reviewer?.request).toEqual({
|
||||
headers: { "x-agent": "reviewer" },
|
||||
body: { reasoningEffort: "high" },
|
||||
})
|
||||
expect(reviewer?.description).toBe("Review changes for correctness")
|
||||
expect(reviewer?.system).toBe("Find regressions.")
|
||||
expect(reviewer?.mode).toBe("subagent")
|
||||
expect(reviewer?.hidden).toBe(false)
|
||||
expect(reviewer?.color).toBe("warning")
|
||||
expect(reviewer?.steps).toBe(12)
|
||||
expect(reviewer?.disabled).toBe(false)
|
||||
expect(reviewer?.permissions).toEqual([{ action: "edit", resource: "*", effect: "deny" }])
|
||||
expect(documents[0]?.info.snapshots).toBe(false)
|
||||
expect(documents[0]?.info.watcher).toEqual({ ignore: ["node_modules/**", "dist/**", ".git"] })
|
||||
expect(documents[0]?.info.formatter).toEqual({
|
||||
@@ -379,6 +416,24 @@ describe("Config", () => {
|
||||
skills: { paths: ["./skills"], urls: ["https://example.com/.well-known/skills/"] },
|
||||
reference: { docs: { path: "../docs" } },
|
||||
attachment: { image: { auto_resize: false, max_width: 1200 } },
|
||||
provider: {
|
||||
custom: {
|
||||
options: { apiKey: "secret" },
|
||||
models: {
|
||||
model: {
|
||||
options: { reasoningEffort: "high" },
|
||||
variants: { fast: { temperature: 0.2 } },
|
||||
},
|
||||
},
|
||||
},
|
||||
openai: {
|
||||
npm: "@ai-sdk/openai",
|
||||
options: { apiKey: "secret", organization: "org" },
|
||||
models: {
|
||||
model: { options: { reasoningEffort: "high", serviceTier: "priority" } },
|
||||
},
|
||||
},
|
||||
},
|
||||
compaction: { auto: true, tail_turns: 3, preserve_recent_tokens: 2000, reserved: 10000 },
|
||||
experimental: { mcp_timeout: 5000 },
|
||||
mcp: {
|
||||
@@ -410,7 +465,7 @@ describe("Config", () => {
|
||||
expect(documents[0]?.info.agents?.reviewer).toMatchObject({
|
||||
system: "Review changes.",
|
||||
disabled: true,
|
||||
options: { body: { temperature: 0.2 } },
|
||||
request: { body: { temperature: 0.2 } },
|
||||
permissions: [{ action: "read", resource: "*", effect: "allow" }],
|
||||
})
|
||||
expect(documents[0]?.info.plugins).toEqual([
|
||||
@@ -420,6 +475,20 @@ describe("Config", () => {
|
||||
expect(documents[0]?.info.skills).toEqual(["./skills", "https://example.com/.well-known/skills/"])
|
||||
expect(documents[0]?.info.references).toEqual({ docs: { path: "../docs" } })
|
||||
expect(documents[0]?.info.attachments).toEqual({ image: { auto_resize: false, max_width: 1200 } })
|
||||
expect(documents[0]?.info.providers?.custom).toMatchObject({
|
||||
request: { body: { apiKey: "secret" } },
|
||||
models: {
|
||||
model: {
|
||||
request: { body: { reasoningEffort: "high" } },
|
||||
variants: [{ id: "fast", body: { temperature: 0.2 } }],
|
||||
},
|
||||
},
|
||||
})
|
||||
expect(documents[0]?.info.providers?.openai).toMatchObject({
|
||||
api: { settings: {} },
|
||||
request: { headers: { Authorization: "Bearer secret", "OpenAI-Organization": "org" } },
|
||||
models: { model: { request: { body: { reasoning_effort: "high", service_tier: "priority" } } } },
|
||||
})
|
||||
expect(documents[0]?.info.compaction).toEqual({
|
||||
auto: true,
|
||||
prune: undefined,
|
||||
|
||||
@@ -8,7 +8,7 @@ import { PluginV2 } from "@opencode-ai/core/plugin"
|
||||
import { ProviderV2 } from "@opencode-ai/core/provider"
|
||||
import { it } from "../plugin/provider-helper"
|
||||
|
||||
function options(headers: Record<string, string>, variant?: string) {
|
||||
function request(headers: Record<string, string>, variant?: string) {
|
||||
return {
|
||||
headers,
|
||||
variant,
|
||||
@@ -35,8 +35,8 @@ describe("ConfigProviderPlugin.Plugin", () => {
|
||||
custom: {
|
||||
name: "Configured",
|
||||
env: ["CUSTOM_API_KEY"],
|
||||
endpoint: { type: "unknown" },
|
||||
options: options({ first: "first", shared: "first" }),
|
||||
api: { type: "native", settings: {} },
|
||||
request: request({ first: "first", shared: "first" }),
|
||||
models: {
|
||||
chat: {
|
||||
name: "First",
|
||||
@@ -44,7 +44,7 @@ describe("ConfigProviderPlugin.Plugin", () => {
|
||||
disabled: true,
|
||||
limit: { context: 100, output: 50 },
|
||||
cost: { input: 1, output: 2 },
|
||||
options: options({ first: "first", shared: "first" }, "retained"),
|
||||
request: request({ first: "first", shared: "first" }, "retained"),
|
||||
variants: [
|
||||
{
|
||||
id: "fast",
|
||||
@@ -62,14 +62,14 @@ describe("ConfigProviderPlugin.Plugin", () => {
|
||||
info: decode({
|
||||
providers: {
|
||||
custom: {
|
||||
endpoint: { type: "aisdk", package: "custom-sdk", url: "https://example.test" },
|
||||
options: options({ last: "last", shared: "last" }),
|
||||
api: { type: "aisdk", package: "custom-sdk", url: "https://example.test" },
|
||||
request: request({ last: "last", shared: "last" }),
|
||||
models: {
|
||||
chat: {
|
||||
api_id: "api-chat",
|
||||
name: "Last",
|
||||
limit: { output: 75 },
|
||||
options: options({ last: "last", shared: "last" }),
|
||||
request: request({ last: "last", shared: "last" }),
|
||||
variants: [
|
||||
{
|
||||
id: "fast",
|
||||
@@ -110,16 +110,16 @@ describe("ConfigProviderPlugin.Plugin", () => {
|
||||
expect(provider.name).toBe("Renamed")
|
||||
expect(provider.env).toEqual(["CUSTOM_API_KEY"])
|
||||
expect(provider.enabled).toEqual({ via: "custom", data: {} })
|
||||
expect(provider.endpoint).toEqual({ type: "aisdk", package: "custom-sdk", url: "https://example.test" })
|
||||
expect(provider.options.headers).toEqual({ first: "first", shared: "last", last: "last" })
|
||||
expect(provider.api).toEqual({ type: "aisdk", package: "custom-sdk", url: "https://example.test" })
|
||||
expect(provider.request.headers).toEqual({ first: "first", shared: "last", last: "last" })
|
||||
expect(model.apiID).toBe(ModelV2.ID.make("api-chat"))
|
||||
expect(model.name).toBe("Last")
|
||||
expect(model.capabilities).toEqual({ tools: true, input: ["text"], output: ["text"] })
|
||||
expect(model.enabled).toBe(false)
|
||||
expect(model.limit).toEqual({ context: 100, output: 75 })
|
||||
expect(model.cost).toEqual([{ input: 1, output: 2, cache: { read: 0, write: 0 }, tier: undefined }])
|
||||
expect(model.options.headers).toEqual({ first: "first", shared: "last", last: "last" })
|
||||
expect(model.options.variant).toBe("retained")
|
||||
expect(model.request.headers).toEqual({ first: "first", shared: "last", last: "last" })
|
||||
expect(model.request.variant).toBe("retained")
|
||||
expect(model.variants.map((variant) => variant.id)).toEqual([
|
||||
ModelV2.VariantID.make("fast"),
|
||||
ModelV2.VariantID.make("slow"),
|
||||
|
||||
Reference in New Issue
Block a user