diff --git a/src/catalog.js b/src/catalog.js index 526ac3b..f6194e9 100644 --- a/src/catalog.js +++ b/src/catalog.js @@ -165,6 +165,7 @@ function toCatalogModel(model) { name: model.name, api: model.api, baseUrl: model.baseUrl, + headers: model.headers, compat: model.compat, reasoning: model.reasoning, input: model.input, diff --git a/src/index.js b/src/index.js index c6028a1..99ec003 100644 --- a/src/index.js +++ b/src/index.js @@ -244,6 +244,15 @@ export async function ask(askLlm, options = {}) { return; } + if ( + event.type === "message_end" && + event.message?.role === "assistant" && + event.message.stopReason === "error" + ) { + responseError = new Error(event.message.errorMessage || "The model request failed"); + return; + } + if (event.type === "tool_execution_start") { toolOutputById.set(event.toolCallId, ""); options.onToolStart?.({ @@ -289,8 +298,10 @@ export async function ask(askLlm, options = {}) { } }); + let responseError; try { await session.prompt(text); + if (responseError) throw responseError; return response; } finally { unsubscribe(); diff --git a/test/catalog.test.js b/test/catalog.test.js index dd7f7a0..b54dd68 100644 --- a/test/catalog.test.js +++ b/test/catalog.test.js @@ -21,7 +21,8 @@ test("parses generated catalog index and provider model objects", () => { export const OPENAI_CODEX_MODELS = { "gpt-5.6-terra": { id: "gpt-5.6-terra", name: "GPT-5.6 Terra", api: "openai-codex-responses", - provider: "openai-codex", baseUrl: "https://chatgpt.com/backend-api", compat: { supportsToolSearch: true }, reasoning: true, + provider: "openai-codex", baseUrl: "https://chatgpt.com/backend-api", headers: { "Editor-Version": "vscode/1.107.0" }, + compat: { supportsToolSearch: true }, reasoning: true, thinkingLevelMap: { "xhigh": "xhigh", "max": "max" }, input: ["text", "image"], cost: { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 3.125, tiers: [{ inputTokensAbove: 272000, input: 5, output: 22.5, cacheRead: 0.5, cacheWrite: 6.25 }] }, @@ -44,7 +45,8 @@ test("loads generated compatibility, tiered costs, and future thinking metadata" export const OPENAI_CODEX_MODELS = { terra: { id: "terra", name: "Terra", api: "openai-codex-responses", provider: "openai-codex", - baseUrl: "https://example.test", compat: { supportsToolSearch: true }, reasoning: true, + baseUrl: "https://example.test", headers: { "Editor-Version": "vscode/1.107.0" }, + compat: { supportsToolSearch: true }, reasoning: true, thinkingLevelMap: { xhigh: "xhigh", max: "max" }, input: ["text"], cost: { input: 1, output: 2, cacheRead: 0.1, cacheWrite: 0.2, tiers: [{ inputTokensAbove: 100, input: 2, output: 4, cacheRead: 0.2, cacheWrite: 0.4 }] }, @@ -59,9 +61,12 @@ test("loads generated compatibility, tiered costs, and future thinking metadata" try { await refreshCatalog({ fetchImpl }); - const registry = ModelRegistry.create(AuthStorage.create(), getRegistryCatalogPath()); + const authStorage = AuthStorage.create(); + authStorage.set("openai-codex", { type: "api_key", key: "test-key" }); + const registry = ModelRegistry.create(authStorage, getRegistryCatalogPath()); const model = registry.find("openai-codex", "terra"); assert.equal(registry.getError(), undefined); + assert.deepEqual((await registry.getApiKeyAndHeaders(model)).headers, { "Editor-Version": "vscode/1.107.0" }); assert.deepEqual(model.compat, { supportsToolSearch: true }); assert.equal(model.cost.tiers[0].inputTokensAbove, 100); assert.equal(model.thinkingLevelMap.max, "max");