|
|
|
@@ -28,7 +28,7 @@ const SYSTEM_DEFAULT_MODEL = "anthropic/claude-sonnet-4-6"
|
|
|
|
|
|
|
|
|
|
const TEST_CONNECTED_PROVIDERS = ["anthropic", "google", "openai"]
|
|
|
|
|
const TEST_AVAILABLE_MODELS = new Set([
|
|
|
|
|
"anthropic/claude-opus-4-6",
|
|
|
|
|
"anthropic/claude-opus-4-7",
|
|
|
|
|
"anthropic/claude-sonnet-4-6",
|
|
|
|
|
"anthropic/claude-haiku-4-5",
|
|
|
|
|
"google/gemini-3.1-pro",
|
|
|
|
@@ -66,7 +66,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(["anthropic", "google", "openai"])
|
|
|
|
|
providerModelsSpy = spyOn(connectedProvidersCache, "readProviderModelsCache").mockReturnValue({
|
|
|
|
|
models: {
|
|
|
|
|
anthropic: ["claude-opus-4-6", "claude-sonnet-4-6", "claude-haiku-4-5"],
|
|
|
|
|
anthropic: ["claude-opus-4-7", "claude-sonnet-4-6", "claude-haiku-4-5"],
|
|
|
|
|
google: ["gemini-3.1-pro", "gemini-3-flash"],
|
|
|
|
|
openai: ["gpt-5.4", "gpt-5.3-codex"],
|
|
|
|
|
},
|
|
|
|
@@ -112,13 +112,13 @@ describe("sisyphus-task", () => {
|
|
|
|
|
expect(category.variant).toBe("medium")
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
test("unspecified-high category uses claude-opus-4-6 max as primary", () => {
|
|
|
|
|
test("unspecified-high category uses claude-opus-4-7 max as primary", () => {
|
|
|
|
|
// given
|
|
|
|
|
const category = DEFAULT_CATEGORIES["unspecified-high"]
|
|
|
|
|
|
|
|
|
|
// when / #then
|
|
|
|
|
expect(category).toBeDefined()
|
|
|
|
|
expect(category.model).toBe("anthropic/claude-opus-4-6")
|
|
|
|
|
expect(category.model).toBe("anthropic/claude-opus-4-7")
|
|
|
|
|
expect(category.variant).toBe("max")
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
@@ -757,7 +757,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
test("blocks requiresModel when availability is known and missing the required model", () => {
|
|
|
|
|
// given - artistry has requiresModel: gemini-3.1-pro
|
|
|
|
|
const categoryName = "artistry"
|
|
|
|
|
const availableModels = new Set<string>(["anthropic/claude-opus-4-6"])
|
|
|
|
|
const availableModels = new Set<string>(["anthropic/claude-opus-4-7"])
|
|
|
|
|
|
|
|
|
|
// when
|
|
|
|
|
const result = resolveCategoryConfig(categoryName, {
|
|
|
|
@@ -787,9 +787,9 @@ describe("sisyphus-task", () => {
|
|
|
|
|
test("bypasses requiresModel when explicit user config provided", () => {
|
|
|
|
|
// #given
|
|
|
|
|
const categoryName = "deep"
|
|
|
|
|
const availableModels = new Set<string>(["anthropic/claude-opus-4-6"])
|
|
|
|
|
const availableModels = new Set<string>(["anthropic/claude-opus-4-7"])
|
|
|
|
|
const userCategories = {
|
|
|
|
|
deep: { model: "anthropic/claude-opus-4-6" },
|
|
|
|
|
deep: { model: "anthropic/claude-opus-4-7" },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// #when
|
|
|
|
@@ -801,7 +801,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
|
|
|
|
|
// #then
|
|
|
|
|
expect(result).not.toBeNull()
|
|
|
|
|
expect(result!.config.model).toBe("anthropic/claude-opus-4-6")
|
|
|
|
|
expect(result!.config.model).toBe("anthropic/claude-opus-4-7")
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
test("bypasses requiresModel when explicit user config provided even with empty availability", () => {
|
|
|
|
@@ -809,7 +809,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
const categoryName = "deep"
|
|
|
|
|
const availableModels = new Set<string>()
|
|
|
|
|
const userCategories = {
|
|
|
|
|
deep: { model: "anthropic/claude-opus-4-6" },
|
|
|
|
|
deep: { model: "anthropic/claude-opus-4-7" },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// #when
|
|
|
|
@@ -821,7 +821,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
|
|
|
|
|
// #then
|
|
|
|
|
expect(result).not.toBeNull()
|
|
|
|
|
expect(result!.config.model).toBe("anthropic/claude-opus-4-6")
|
|
|
|
|
expect(result!.config.model).toBe("anthropic/claude-opus-4-7")
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
test("returns default model from DEFAULT_CATEGORIES for builtin category", () => {
|
|
|
|
@@ -841,7 +841,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
// given
|
|
|
|
|
const categoryName = "visual-engineering"
|
|
|
|
|
const userCategories = {
|
|
|
|
|
"visual-engineering": { model: "anthropic/claude-opus-4-6" },
|
|
|
|
|
"visual-engineering": { model: "anthropic/claude-opus-4-7" },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// when
|
|
|
|
@@ -849,7 +849,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
|
|
|
|
|
// then
|
|
|
|
|
expect(result).not.toBeNull()
|
|
|
|
|
expect(result!.config.model).toBe("anthropic/claude-opus-4-6")
|
|
|
|
|
expect(result!.config.model).toBe("anthropic/claude-opus-4-7")
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
test("user prompt_append is appended to default", () => {
|
|
|
|
@@ -913,7 +913,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
test("category built-in model takes precedence over inheritedModel", () => {
|
|
|
|
|
// given - builtin category with its own model, parent model also provided
|
|
|
|
|
const categoryName = "visual-engineering"
|
|
|
|
|
const inheritedModel = "cliproxy/claude-opus-4-6"
|
|
|
|
|
const inheritedModel = "cliproxy/claude-opus-4-7"
|
|
|
|
|
|
|
|
|
|
// when
|
|
|
|
|
const result = resolveCategoryConfig(categoryName, { inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL })
|
|
|
|
@@ -927,7 +927,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
// given - custom category with no model defined
|
|
|
|
|
const categoryName = "my-custom-no-model"
|
|
|
|
|
const userCategories = { "my-custom-no-model": { temperature: 0.5 } } as unknown as Record<string, CategoryConfig>
|
|
|
|
|
const inheritedModel = "cliproxy/claude-opus-4-6"
|
|
|
|
|
const inheritedModel = "cliproxy/claude-opus-4-7"
|
|
|
|
|
|
|
|
|
|
// when
|
|
|
|
|
const result = resolveCategoryConfig(categoryName, { userCategories, inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL })
|
|
|
|
@@ -943,7 +943,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
const userCategories = {
|
|
|
|
|
"visual-engineering": { model: "my-provider/my-model" },
|
|
|
|
|
}
|
|
|
|
|
const inheritedModel = "cliproxy/claude-opus-4-6"
|
|
|
|
|
const inheritedModel = "cliproxy/claude-opus-4-7"
|
|
|
|
|
|
|
|
|
|
// when
|
|
|
|
|
const result = resolveCategoryConfig(categoryName, { userCategories, inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL })
|
|
|
|
@@ -1054,7 +1054,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
const mockClient = {
|
|
|
|
|
app: { agents: async () => ({ data: [] }) },
|
|
|
|
|
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
|
|
|
|
|
model: { list: async () => [{ provider: "anthropic", id: "claude-opus-4-6" }] },
|
|
|
|
|
model: { list: async () => [{ provider: "anthropic", id: "claude-opus-4-7" }] },
|
|
|
|
|
session: {
|
|
|
|
|
create: async () => ({ data: { id: "test-session" } }),
|
|
|
|
|
prompt: async () => ({ data: {} }),
|
|
|
|
@@ -1078,7 +1078,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
abort: new AbortController().signal,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// when - unspecified-high uses claude-opus-4-6 max in DEFAULT_CATEGORIES
|
|
|
|
|
// when - unspecified-high uses claude-opus-4-7 max in DEFAULT_CATEGORIES
|
|
|
|
|
await tool.execute(
|
|
|
|
|
{
|
|
|
|
|
description: "Test unspecified-high default variant",
|
|
|
|
@@ -1090,10 +1090,10 @@ describe("sisyphus-task", () => {
|
|
|
|
|
toolContext
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// then - claude-opus-4-6 should be passed with max variant
|
|
|
|
|
// then - claude-opus-4-7 should be passed with max variant
|
|
|
|
|
expect(launchInput.model).toEqual({
|
|
|
|
|
providerID: "anthropic",
|
|
|
|
|
modelID: "claude-opus-4-6",
|
|
|
|
|
modelID: "claude-opus-4-7",
|
|
|
|
|
variant: "max",
|
|
|
|
|
})
|
|
|
|
|
}, { timeout: 20000 })
|
|
|
|
@@ -1113,7 +1113,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
const mockClient = {
|
|
|
|
|
app: { agents: async () => ({ data: [] }) },
|
|
|
|
|
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
|
|
|
|
|
model: { list: async () => [{ provider: "anthropic", id: "claude-opus-4-6" }] },
|
|
|
|
|
model: { list: async () => [{ provider: "anthropic", id: "claude-opus-4-7" }] },
|
|
|
|
|
session: {
|
|
|
|
|
get: async () => ({ data: { directory: "/project" } }),
|
|
|
|
|
create: async () => ({ data: { id: "ses_sync_default_variant" } }),
|
|
|
|
@@ -1139,7 +1139,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
abort: new AbortController().signal,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// when - unspecified-high uses claude-opus-4-6 max in DEFAULT_CATEGORIES
|
|
|
|
|
// when - unspecified-high uses claude-opus-4-7 max in DEFAULT_CATEGORIES
|
|
|
|
|
await tool.execute(
|
|
|
|
|
{
|
|
|
|
|
description: "Test unspecified-high sync variant",
|
|
|
|
@@ -1151,10 +1151,10 @@ describe("sisyphus-task", () => {
|
|
|
|
|
toolContext
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// then - claude-opus-4-6 should be passed with max variant
|
|
|
|
|
// then - claude-opus-4-7 should be passed with max variant
|
|
|
|
|
expect(promptBody.model).toEqual({
|
|
|
|
|
providerID: "anthropic",
|
|
|
|
|
modelID: "claude-opus-4-6",
|
|
|
|
|
modelID: "claude-opus-4-7",
|
|
|
|
|
})
|
|
|
|
|
expect(promptBody.variant).toBe("max")
|
|
|
|
|
}, { timeout: 20000 })
|
|
|
|
@@ -1550,7 +1550,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
let promptCalled = false
|
|
|
|
|
const mockManager = { launch: async () => ({}) }
|
|
|
|
|
const mockClient = {
|
|
|
|
|
app: { agents: async () => ({ data: [{ name: "oracle", mode: "subagent", model: { providerID: "anthropic", modelID: "claude-opus-4-6" } }] }) },
|
|
|
|
|
app: { agents: async () => ({ data: [{ name: "oracle", mode: "subagent", model: { providerID: "anthropic", modelID: "claude-opus-4-7" } }] }) },
|
|
|
|
|
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
|
|
|
|
|
session: {
|
|
|
|
|
get: async () => ({ data: { directory: "/project" } }),
|
|
|
|
@@ -1835,7 +1835,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
id: "msg_001",
|
|
|
|
|
role: "user",
|
|
|
|
|
agent: "sisyphus-junior",
|
|
|
|
|
model: { providerID: "anthropic", modelID: "claude-opus-4-6" },
|
|
|
|
|
model: { providerID: "anthropic", modelID: "claude-opus-4-7" },
|
|
|
|
|
variant: "max",
|
|
|
|
|
time: { created: baseTime },
|
|
|
|
|
},
|
|
|
|
@@ -1917,7 +1917,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
const callArgs = promptMock.mock.calls[0][0]
|
|
|
|
|
expect(callArgs.body.variant).toBe("max")
|
|
|
|
|
expect(callArgs.body.agent).toBe("sisyphus-junior")
|
|
|
|
|
expect(callArgs.body.model).toEqual({ providerID: "anthropic", modelID: "claude-opus-4-6" })
|
|
|
|
|
expect(callArgs.body.model).toEqual({ providerID: "anthropic", modelID: "claude-opus-4-7" })
|
|
|
|
|
}, { timeout: 10000 })
|
|
|
|
|
|
|
|
|
|
test("task_id with background=true should return immediately without waiting", async () => {
|
|
|
|
@@ -2551,7 +2551,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
// Override provider cache to include kimi-for-coding provider
|
|
|
|
|
providerModelsSpy.mockReturnValue({
|
|
|
|
|
models: {
|
|
|
|
|
anthropic: ["claude-opus-4-6", "claude-sonnet-4-6", "claude-haiku-4-5"],
|
|
|
|
|
anthropic: ["claude-opus-4-7", "claude-sonnet-4-6", "claude-haiku-4-5"],
|
|
|
|
|
google: ["gemini-3.1-pro", "gemini-3-flash"],
|
|
|
|
|
openai: ["gpt-5.4", "gpt-5.3-codex"],
|
|
|
|
|
"kimi-for-coding": ["k2p5"],
|
|
|
|
@@ -2798,7 +2798,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
manager: mockManager,
|
|
|
|
|
client: mockClient,
|
|
|
|
|
userCategories: {
|
|
|
|
|
"fallback-test": { model: "anthropic/claude-opus-4-6" },
|
|
|
|
|
"fallback-test": { model: "anthropic/claude-opus-4-7" },
|
|
|
|
|
},
|
|
|
|
|
connectedProvidersOverride: TEST_CONNECTED_PROVIDERS,
|
|
|
|
|
availableModelsOverride: createTestAvailableModels(),
|
|
|
|
@@ -3465,7 +3465,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
test("category built-in model takes precedence over inheritedModel for builtin category", () => {
|
|
|
|
|
// given - builtin ultrabrain category with its own model, inherited model also provided
|
|
|
|
|
const categoryName = "ultrabrain"
|
|
|
|
|
const inheritedModel = "cliproxy/claude-opus-4-6"
|
|
|
|
|
const inheritedModel = "cliproxy/claude-opus-4-7"
|
|
|
|
|
|
|
|
|
|
// when
|
|
|
|
|
const resolved = resolveCategoryConfig(categoryName, { inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL })
|
|
|
|
@@ -3480,7 +3480,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
// given
|
|
|
|
|
const categoryName = "ultrabrain"
|
|
|
|
|
const userCategories = { "ultrabrain": { model: "my-provider/custom-model" } }
|
|
|
|
|
const inheritedModel = "cliproxy/claude-opus-4-6"
|
|
|
|
|
const inheritedModel = "cliproxy/claude-opus-4-7"
|
|
|
|
|
|
|
|
|
|
// when
|
|
|
|
|
const resolved = resolveCategoryConfig(categoryName, { userCategories, inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL })
|
|
|
|
@@ -3497,7 +3497,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
// given - This test verifies the fix for PR #770 bug
|
|
|
|
|
// The bug was: checking `if (inheritedModel)` instead of `if (actualModel === inheritedModel)`
|
|
|
|
|
const categoryName = "ultrabrain"
|
|
|
|
|
const inheritedModel = "cliproxy/claude-opus-4-6"
|
|
|
|
|
const inheritedModel = "cliproxy/claude-opus-4-7"
|
|
|
|
|
const userCategories = { "ultrabrain": { model: "user/model" } }
|
|
|
|
|
|
|
|
|
|
// when - user model wins
|
|
|
|
@@ -3525,7 +3525,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
// given a builtin category with its own model, and an inherited model from parent
|
|
|
|
|
// The CORRECT chain: userConfig?.model ?? categoryBuiltIn ?? systemDefaultModel
|
|
|
|
|
const categoryName = "ultrabrain"
|
|
|
|
|
const inheritedModel = "anthropic/claude-opus-4-6"
|
|
|
|
|
const inheritedModel = "anthropic/claude-opus-4-7"
|
|
|
|
|
|
|
|
|
|
// when category has a built-in model (gpt-5.4 for ultrabrain)
|
|
|
|
|
const resolved = resolveCategoryConfig(categoryName, { inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL })
|
|
|
|
@@ -3556,7 +3556,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
// given userConfig.model is explicitly set
|
|
|
|
|
const categoryName = "ultrabrain"
|
|
|
|
|
const userCategories = { "ultrabrain": { model: "custom/user-model" } }
|
|
|
|
|
const inheritedModel = "anthropic/claude-opus-4-6"
|
|
|
|
|
const inheritedModel = "anthropic/claude-opus-4-7"
|
|
|
|
|
const systemDefaultModel = "anthropic/claude-sonnet-4-6"
|
|
|
|
|
|
|
|
|
|
// when resolveCategoryConfig is called with all sources
|
|
|
|
@@ -3575,7 +3575,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
// given userConfig.model is empty string "" for a custom category (no built-in model)
|
|
|
|
|
const categoryName = "custom-empty-model"
|
|
|
|
|
const userCategories = { "custom-empty-model": { model: "", temperature: 0.3 } }
|
|
|
|
|
const inheritedModel = "anthropic/claude-opus-4-6"
|
|
|
|
|
const inheritedModel = "anthropic/claude-opus-4-7"
|
|
|
|
|
|
|
|
|
|
// when resolveCategoryConfig is called
|
|
|
|
|
const resolved = resolveCategoryConfig(categoryName, { userCategories, inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL })
|
|
|
|
@@ -3590,7 +3590,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
const categoryName = "visual-engineering"
|
|
|
|
|
// Using type assertion since we're testing fallback behavior for categories without model
|
|
|
|
|
const userCategories = { "visual-engineering": { temperature: 0.2 } } as unknown as Record<string, CategoryConfig>
|
|
|
|
|
const inheritedModel = "anthropic/claude-opus-4-6"
|
|
|
|
|
const inheritedModel = "anthropic/claude-opus-4-7"
|
|
|
|
|
|
|
|
|
|
// when resolveCategoryConfig is called
|
|
|
|
|
const resolved = resolveCategoryConfig(categoryName, { userCategories, inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL })
|
|
|
|
@@ -3810,7 +3810,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
app: {
|
|
|
|
|
agents: async () => ({
|
|
|
|
|
data: [
|
|
|
|
|
{ name: "oracle", mode: "subagent", model: { providerID: "anthropic", modelID: "claude-opus-4-6" } },
|
|
|
|
|
{ name: "oracle", mode: "subagent", model: { providerID: "anthropic", modelID: "claude-opus-4-7" } },
|
|
|
|
|
],
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
@@ -3854,7 +3854,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
// then - matched agent's model should be passed to session.prompt
|
|
|
|
|
expect(promptBody.model).toEqual({
|
|
|
|
|
providerID: "anthropic",
|
|
|
|
|
modelID: "claude-opus-4-6",
|
|
|
|
|
modelID: "claude-opus-4-7",
|
|
|
|
|
})
|
|
|
|
|
}, { timeout: 20000 })
|
|
|
|
|
|
|
|
|
@@ -3956,7 +3956,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
manager: mockManager,
|
|
|
|
|
client: mockClient,
|
|
|
|
|
agentOverrides: {
|
|
|
|
|
oracle: { model: "anthropic/claude-opus-4-6" },
|
|
|
|
|
oracle: { model: "anthropic/claude-opus-4-7" },
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
@@ -3982,7 +3982,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
// then - user-configured model should take priority over matchedAgent.model
|
|
|
|
|
expect(promptBody.model).toEqual({
|
|
|
|
|
providerID: "anthropic",
|
|
|
|
|
modelID: "claude-opus-4-6",
|
|
|
|
|
modelID: "claude-opus-4-7",
|
|
|
|
|
})
|
|
|
|
|
}, { timeout: 20000 })
|
|
|
|
|
|
|
|
|
@@ -4023,7 +4023,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
manager: mockManager,
|
|
|
|
|
client: mockClient,
|
|
|
|
|
agentOverrides: {
|
|
|
|
|
oracle: { model: "anthropic/claude-opus-4-6", variant: "max" },
|
|
|
|
|
oracle: { model: "anthropic/claude-opus-4-7", variant: "max" },
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
@@ -4111,7 +4111,7 @@ describe("sisyphus-task", () => {
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// then - should resolve via AGENT_MODEL_REQUIREMENTS fallback chain for oracle
|
|
|
|
|
// oracle fallback chain: gpt-5.4 (openai) > gemini-3.1-pro (google) > claude-opus-4-6 (anthropic)
|
|
|
|
|
// oracle fallback chain: gpt-5.4 (openai) > gemini-3.1-pro (google) > claude-opus-4-7 (anthropic)
|
|
|
|
|
// Since openai is in connectedProviders, should resolve to openai/gpt-5.4
|
|
|
|
|
expect(promptBody.model).toBeDefined()
|
|
|
|
|
expect(promptBody.model.providerID).toBe("openai")
|
|
|
|
|