chore: merge dev into v2
This commit is contained in:
commit
4a0868d4f2
4 changed files with 122239 additions and 66811 deletions
|
|
@ -303,7 +303,13 @@ export async function CodexAuthPlugin(input: PluginInput, options: CodexAuthPlug
|
||||||
input: 272_000,
|
input: 272_000,
|
||||||
output: 128_000,
|
output: 128_000,
|
||||||
}
|
}
|
||||||
: model.limit,
|
: model.id.includes("gpt-5.6")
|
||||||
|
? {
|
||||||
|
context: 500_000,
|
||||||
|
input: 372_000,
|
||||||
|
output: 128_000,
|
||||||
|
}
|
||||||
|
: model.limit,
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,30 @@ describe("plugin.codex", () => {
|
||||||
await enabled.dispose?.()
|
await enabled.dispose?.()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("uses Codex context limits for OAuth GPT models", async () => {
|
||||||
|
const hooks = await CodexAuthPlugin({} as never)
|
||||||
|
const limit = { context: 1_050_000, input: 922_000, output: 128_000 }
|
||||||
|
const provider = {
|
||||||
|
models: Object.fromEntries(
|
||||||
|
["gpt-5.4", "gpt-5.5", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"].map((id) => [
|
||||||
|
id,
|
||||||
|
{ id, api: { id }, limit, cost: {} },
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
const models = await hooks.provider!.models!(provider as never, { auth: { type: "oauth" } } as never)
|
||||||
|
|
||||||
|
expect(models["gpt-5.4"]?.limit).toEqual(limit)
|
||||||
|
expect(models["gpt-5.5"]?.limit).toEqual({ context: 400_000, input: 272_000, output: 128_000 })
|
||||||
|
expect(models["gpt-5.6-sol"]?.limit).toEqual({ context: 500_000, input: 372_000, output: 128_000 })
|
||||||
|
expect(models["gpt-5.6-terra"]?.limit).toEqual({ context: 500_000, input: 372_000, output: 128_000 })
|
||||||
|
expect(models["gpt-5.6-luna"]?.limit).toEqual({ context: 500_000, input: 372_000, output: 128_000 })
|
||||||
|
expect(await hooks.provider!.models!(provider as never, { auth: { type: "api" } } as never)).toBe(
|
||||||
|
provider.models as never,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
test("deduplicates concurrent Codex token refreshes", async () => {
|
test("deduplicates concurrent Codex token refreshes", async () => {
|
||||||
let auth = {
|
let auth = {
|
||||||
type: "oauth" as const,
|
type: "oauth" as const,
|
||||||
|
|
|
||||||
|
|
@ -161,10 +161,10 @@ it.instance(
|
||||||
const providers = yield* list
|
const providers = yield* list
|
||||||
expect(providers[ProviderV2.ID.anthropic]).toBeDefined()
|
expect(providers[ProviderV2.ID.anthropic]).toBeDefined()
|
||||||
const models = Object.keys(providers[ProviderV2.ID.anthropic].models)
|
const models = Object.keys(providers[ProviderV2.ID.anthropic].models)
|
||||||
expect(models).toContain("claude-sonnet-4-20250514")
|
expect(models).toContain("claude-sonnet-4-6")
|
||||||
expect(models.length).toBe(1)
|
expect(models.length).toBe(1)
|
||||||
}),
|
}),
|
||||||
{ config: { provider: { anthropic: { whitelist: ["claude-sonnet-4-20250514"] } } } },
|
{ config: { provider: { anthropic: { whitelist: ["claude-sonnet-4-6"] } } } },
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance(
|
it.instance(
|
||||||
|
|
@ -303,10 +303,10 @@ it.instance("getModel returns model for valid provider/model", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setProcessEnv("ANTHROPIC_API_KEY", "test-api-key")
|
yield* setProcessEnv("ANTHROPIC_API_KEY", "test-api-key")
|
||||||
const provider = yield* Provider.Service
|
const provider = yield* Provider.Service
|
||||||
const model = yield* provider.getModel(ProviderV2.ID.anthropic, ModelV2.ID.make("claude-sonnet-4-20250514"))
|
const model = yield* provider.getModel(ProviderV2.ID.anthropic, ModelV2.ID.make("claude-sonnet-4-6"))
|
||||||
expect(model).toBeDefined()
|
expect(model).toBeDefined()
|
||||||
expect(String(model.providerID)).toBe("anthropic")
|
expect(String(model.providerID)).toBe("anthropic")
|
||||||
expect(String(model.id)).toBe("claude-sonnet-4-20250514")
|
expect(String(model.id)).toBe("claude-sonnet-4-6")
|
||||||
const language = yield* provider.getLanguage(model)
|
const language = yield* provider.getLanguage(model)
|
||||||
expect(language).toBeDefined()
|
expect(language).toBeDefined()
|
||||||
}),
|
}),
|
||||||
|
|
@ -437,7 +437,7 @@ it.instance(
|
||||||
"model options are merged from existing model",
|
"model options are merged from existing model",
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const providers = yield* list
|
const providers = yield* list
|
||||||
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-20250514"]
|
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-6"]
|
||||||
expect(model.options.customOption).toBe("custom-value")
|
expect(model.options.customOption).toBe("custom-value")
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
|
|
@ -445,7 +445,7 @@ it.instance(
|
||||||
provider: {
|
provider: {
|
||||||
anthropic: {
|
anthropic: {
|
||||||
options: { apiKey: "test-api-key" },
|
options: { apiKey: "test-api-key" },
|
||||||
models: { "claude-sonnet-4-20250514": { options: { customOption: "custom-value" } } },
|
models: { "claude-sonnet-4-6": { options: { customOption: "custom-value" } } },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -551,7 +551,7 @@ it.instance(
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
||||||
const providers = yield* list
|
const providers = yield* list
|
||||||
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-20250514"]
|
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-6"]
|
||||||
expect(model.name).toBe("Custom Name for Sonnet")
|
expect(model.name).toBe("Custom Name for Sonnet")
|
||||||
expect(model.capabilities.toolcall).toBe(true)
|
expect(model.capabilities.toolcall).toBe(true)
|
||||||
expect(model.capabilities.attachment).toBe(true)
|
expect(model.capabilities.attachment).toBe(true)
|
||||||
|
|
@ -559,7 +559,7 @@ it.instance(
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
config: {
|
config: {
|
||||||
provider: { anthropic: { models: { "claude-sonnet-4-20250514": { name: "Custom Name for Sonnet" } } } },
|
provider: { anthropic: { models: { "claude-sonnet-4-6": { name: "Custom Name for Sonnet" } } } },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
@ -592,16 +592,16 @@ it.instance(
|
||||||
const providers = yield* list
|
const providers = yield* list
|
||||||
expect(providers[ProviderV2.ID.anthropic]).toBeDefined()
|
expect(providers[ProviderV2.ID.anthropic]).toBeDefined()
|
||||||
const models = Object.keys(providers[ProviderV2.ID.anthropic].models)
|
const models = Object.keys(providers[ProviderV2.ID.anthropic].models)
|
||||||
expect(models).toContain("claude-sonnet-4-20250514")
|
expect(models).toContain("claude-sonnet-4-6")
|
||||||
expect(models).not.toContain("claude-opus-4-20250514")
|
expect(models).not.toContain("claude-opus-4-6")
|
||||||
expect(models.length).toBe(1)
|
expect(models.length).toBe(1)
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
config: {
|
config: {
|
||||||
provider: {
|
provider: {
|
||||||
anthropic: {
|
anthropic: {
|
||||||
whitelist: ["claude-sonnet-4-20250514", "claude-opus-4-20250514"],
|
whitelist: ["claude-sonnet-4-6", "claude-opus-4-6"],
|
||||||
blacklist: ["claude-opus-4-20250514"],
|
blacklist: ["claude-opus-4-6"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -775,9 +775,9 @@ it.instance(
|
||||||
const model = yield* Provider.use.getSmallModel(ProviderV2.ID.anthropic)
|
const model = yield* Provider.use.getSmallModel(ProviderV2.ID.anthropic)
|
||||||
expect(model).toBeDefined()
|
expect(model).toBeDefined()
|
||||||
expect(String(model?.providerID)).toBe("anthropic")
|
expect(String(model?.providerID)).toBe("anthropic")
|
||||||
expect(String(model?.id)).toBe("claude-sonnet-4-20250514")
|
expect(String(model?.id)).toBe("claude-sonnet-4-6")
|
||||||
}),
|
}),
|
||||||
{ config: { small_model: "anthropic/claude-sonnet-4-20250514" } },
|
{ config: { small_model: "anthropic/claude-sonnet-4-6" } },
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance(
|
it.instance(
|
||||||
|
|
@ -1096,8 +1096,8 @@ it.instance(
|
||||||
it.instance("getModel returns consistent results", () =>
|
it.instance("getModel returns consistent results", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
||||||
const model1 = yield* Provider.use.getModel(ProviderV2.ID.anthropic, ModelV2.ID.make("claude-sonnet-4-20250514"))
|
const model1 = yield* Provider.use.getModel(ProviderV2.ID.anthropic, ModelV2.ID.make("claude-sonnet-4-6"))
|
||||||
const model2 = yield* Provider.use.getModel(ProviderV2.ID.anthropic, ModelV2.ID.make("claude-sonnet-4-20250514"))
|
const model2 = yield* Provider.use.getModel(ProviderV2.ID.anthropic, ModelV2.ID.make("claude-sonnet-4-6"))
|
||||||
expect(model1.providerID).toEqual(model2.providerID)
|
expect(model1.providerID).toEqual(model2.providerID)
|
||||||
expect(model1.id).toEqual(model2.id)
|
expect(model1.id).toEqual(model2.id)
|
||||||
expect(model1).toEqual(model2)
|
expect(model1).toEqual(model2)
|
||||||
|
|
@ -1459,7 +1459,7 @@ it.instance("model variants are generated for reasoning models", () =>
|
||||||
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
||||||
const providers = yield* list
|
const providers = yield* list
|
||||||
// Claude sonnet 4 has reasoning capability
|
// Claude sonnet 4 has reasoning capability
|
||||||
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-20250514"]
|
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-6"]
|
||||||
expect(model.capabilities.reasoning).toBe(true)
|
expect(model.capabilities.reasoning).toBe(true)
|
||||||
expect(model.variants).toBeDefined()
|
expect(model.variants).toBeDefined()
|
||||||
expect(Object.keys(model.variants!).length).toBeGreaterThan(0)
|
expect(Object.keys(model.variants!).length).toBeGreaterThan(0)
|
||||||
|
|
@ -1471,7 +1471,7 @@ it.instance(
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
||||||
const providers = yield* list
|
const providers = yield* list
|
||||||
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-20250514"]
|
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-6"]
|
||||||
expect(model.variants).toBeDefined()
|
expect(model.variants).toBeDefined()
|
||||||
expect(model.variants!["high"]).toBeUndefined()
|
expect(model.variants!["high"]).toBeUndefined()
|
||||||
// max variant should still exist
|
// max variant should still exist
|
||||||
|
|
@ -1481,7 +1481,7 @@ it.instance(
|
||||||
config: {
|
config: {
|
||||||
provider: {
|
provider: {
|
||||||
anthropic: {
|
anthropic: {
|
||||||
models: { "claude-sonnet-4-20250514": { variants: { high: { disabled: true } } } },
|
models: { "claude-sonnet-4-6": { variants: { high: { disabled: true } } } },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -1493,7 +1493,7 @@ it.instance(
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
||||||
const providers = yield* list
|
const providers = yield* list
|
||||||
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-20250514"]
|
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-6"]
|
||||||
expect(model.variants!["high"]).toBeDefined()
|
expect(model.variants!["high"]).toBeDefined()
|
||||||
expect(model.variants!["high"].thinking.budgetTokens).toBe(20000)
|
expect(model.variants!["high"].thinking.budgetTokens).toBe(20000)
|
||||||
}),
|
}),
|
||||||
|
|
@ -1502,7 +1502,7 @@ it.instance(
|
||||||
provider: {
|
provider: {
|
||||||
anthropic: {
|
anthropic: {
|
||||||
models: {
|
models: {
|
||||||
"claude-sonnet-4-20250514": {
|
"claude-sonnet-4-6": {
|
||||||
variants: { high: { thinking: { type: "enabled", budgetTokens: 20000 } } },
|
variants: { high: { thinking: { type: "enabled", budgetTokens: 20000 } } },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -1517,7 +1517,7 @@ it.instance(
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
||||||
const providers = yield* list
|
const providers = yield* list
|
||||||
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-20250514"]
|
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-6"]
|
||||||
expect(model.variants!["max"]).toBeDefined()
|
expect(model.variants!["max"]).toBeDefined()
|
||||||
expect(model.variants!["max"].disabled).toBeUndefined()
|
expect(model.variants!["max"].disabled).toBeUndefined()
|
||||||
expect(model.variants!["max"].customField).toBe("test")
|
expect(model.variants!["max"].customField).toBe("test")
|
||||||
|
|
@ -1527,7 +1527,7 @@ it.instance(
|
||||||
provider: {
|
provider: {
|
||||||
anthropic: {
|
anthropic: {
|
||||||
models: {
|
models: {
|
||||||
"claude-sonnet-4-20250514": {
|
"claude-sonnet-4-6": {
|
||||||
variants: { max: { disabled: false, customField: "test" } },
|
variants: { max: { disabled: false, customField: "test" } },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -1542,7 +1542,7 @@ it.instance(
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
||||||
const providers = yield* list
|
const providers = yield* list
|
||||||
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-20250514"]
|
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-6"]
|
||||||
expect(model.variants).toBeDefined()
|
expect(model.variants).toBeDefined()
|
||||||
expect(Object.keys(model.variants!).length).toBe(0)
|
expect(Object.keys(model.variants!).length).toBe(0)
|
||||||
}),
|
}),
|
||||||
|
|
@ -1551,8 +1551,13 @@ it.instance(
|
||||||
provider: {
|
provider: {
|
||||||
anthropic: {
|
anthropic: {
|
||||||
models: {
|
models: {
|
||||||
"claude-sonnet-4-20250514": {
|
"claude-sonnet-4-6": {
|
||||||
variants: { high: { disabled: true }, max: { disabled: true } },
|
variants: {
|
||||||
|
low: { disabled: true },
|
||||||
|
medium: { disabled: true },
|
||||||
|
high: { disabled: true },
|
||||||
|
max: { disabled: true },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -1566,7 +1571,7 @@ it.instance(
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
yield* set("ANTHROPIC_API_KEY", "test-api-key")
|
||||||
const providers = yield* list
|
const providers = yield* list
|
||||||
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-20250514"]
|
const model = providers[ProviderV2.ID.anthropic].models["claude-sonnet-4-6"]
|
||||||
expect(model.variants!["high"]).toBeDefined()
|
expect(model.variants!["high"]).toBeDefined()
|
||||||
// Should have both the generated thinking config and the custom option
|
// Should have both the generated thinking config and the custom option
|
||||||
expect(model.variants!["high"].thinking).toBeDefined()
|
expect(model.variants!["high"].thinking).toBeDefined()
|
||||||
|
|
@ -1577,7 +1582,7 @@ it.instance(
|
||||||
provider: {
|
provider: {
|
||||||
anthropic: {
|
anthropic: {
|
||||||
models: {
|
models: {
|
||||||
"claude-sonnet-4-20250514": { variants: { high: { extraOption: "custom-value" } } },
|
"claude-sonnet-4-6": { variants: { high: { extraOption: "custom-value" } } },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue