gsd-pi 2.71.0-dev.e17e0ce → 2.72.0-dev.de4c4b3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -1
- package/dist/cli.js +17 -0
- package/dist/mcp-server.js +37 -14
- package/dist/resources/agents/debugger.md +58 -0
- package/dist/resources/agents/doc-writer.md +43 -0
- package/dist/resources/agents/git-ops.md +56 -0
- package/dist/resources/agents/javascript-pro.md +46 -271
- package/dist/resources/agents/planner.md +55 -0
- package/dist/resources/agents/refactorer.md +47 -0
- package/dist/resources/agents/reviewer.md +48 -0
- package/dist/resources/agents/security.md +59 -0
- package/dist/resources/agents/tester.md +50 -0
- package/dist/resources/agents/typescript-pro.md +41 -235
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +103 -6
- package/dist/resources/extensions/gsd/auto/phases.js +4 -0
- package/dist/resources/extensions/gsd/auto-prompts.js +88 -33
- package/dist/resources/extensions/gsd/auto-start.js +24 -4
- package/dist/resources/extensions/gsd/auto.js +4 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -3
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +2 -5
- package/dist/resources/extensions/gsd/doctor-providers.js +23 -0
- package/dist/resources/extensions/gsd/error-classifier.js +4 -1
- package/dist/resources/extensions/gsd/gate-registry.js +208 -0
- package/dist/resources/extensions/gsd/gsd-db.js +41 -0
- package/dist/resources/extensions/gsd/milestone-validation-gates.js +11 -12
- package/dist/resources/extensions/gsd/notification-overlay.js +26 -12
- package/dist/resources/extensions/gsd/notification-store.js +5 -4
- package/dist/resources/extensions/gsd/prompt-validation.js +126 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +3 -1
- package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
- package/dist/resources/extensions/gsd/shortcut-defs.js +7 -1
- package/dist/resources/extensions/gsd/state.js +9 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +52 -1
- package/dist/resources/extensions/gsd/tools/complete-task.js +51 -1
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +4 -1
- package/dist/resources/extensions/ollama/index.js +13 -5
- package/dist/resources/extensions/shared/gsd-phase-state.js +35 -0
- package/dist/resources/extensions/subagent/agents.js +8 -0
- package/dist/resources/extensions/subagent/index.js +17 -0
- package/dist/startup-model-validation.d.ts +0 -1
- package/dist/startup-model-validation.js +6 -2
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +1 -1
- package/packages/mcp-server/dist/server.d.ts +12 -1
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +90 -42
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +1 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/server.ts +110 -38
- package/packages/mcp-server/src/workflow-tools.ts +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts +8 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.test.js +75 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +55 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +57 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +9 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js +6 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/model-resolver.test.ts +85 -0
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +83 -0
- package/packages/pi-coding-agent/src/core/retry-handler.ts +60 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +15 -6
- package/packages/pi-coding-agent/src/modes/interactive/controllers/model-controller.ts +6 -1
- package/pkg/package.json +1 -1
- package/src/resources/agents/debugger.md +58 -0
- package/src/resources/agents/doc-writer.md +43 -0
- package/src/resources/agents/git-ops.md +56 -0
- package/src/resources/agents/javascript-pro.md +46 -271
- package/src/resources/agents/planner.md +55 -0
- package/src/resources/agents/refactorer.md +47 -0
- package/src/resources/agents/reviewer.md +48 -0
- package/src/resources/agents/security.md +59 -0
- package/src/resources/agents/tester.md +50 -0
- package/src/resources/agents/typescript-pro.md +41 -235
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +109 -3
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +133 -2
- package/src/resources/extensions/gsd/auto/phases.ts +4 -0
- package/src/resources/extensions/gsd/auto-prompts.ts +111 -33
- package/src/resources/extensions/gsd/auto-start.ts +31 -4
- package/src/resources/extensions/gsd/auto.ts +4 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +2 -5
- package/src/resources/extensions/gsd/doctor-providers.ts +24 -0
- package/src/resources/extensions/gsd/error-classifier.ts +4 -1
- package/src/resources/extensions/gsd/gate-registry.ts +251 -0
- package/src/resources/extensions/gsd/gsd-db.ts +51 -0
- package/src/resources/extensions/gsd/milestone-validation-gates.ts +11 -13
- package/src/resources/extensions/gsd/notification-overlay.ts +27 -11
- package/src/resources/extensions/gsd/notification-store.ts +5 -4
- package/src/resources/extensions/gsd/prompt-validation.ts +157 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -1
- package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
- package/src/resources/extensions/gsd/shortcut-defs.ts +8 -1
- package/src/resources/extensions/gsd/state.ts +13 -2
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/complete-slice-gate-closure.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/gate-registry.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/prompt-system-gate-coverage.test.ts +208 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/register-shortcuts.test.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +63 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +63 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +4 -1
- package/src/resources/extensions/gsd/types.ts +26 -0
- package/src/resources/extensions/ollama/index.ts +13 -3
- package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +28 -0
- package/src/resources/extensions/shared/gsd-phase-state.ts +42 -0
- package/src/resources/extensions/shared/tests/gsd-phase-state.test.ts +48 -0
- package/src/resources/extensions/subagent/agents.ts +10 -0
- package/src/resources/extensions/subagent/index.ts +18 -0
- package/src/resources/extensions/subagent/tests/agents-conflicts.test.ts +33 -0
- /package/dist/web/standalone/.next/static/{cYPZv_bAhZk2ms-Pz6vsY → f-Gremw0nLxxFUySaHRPw}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{cYPZv_bAhZk2ms-Pz6vsY → f-Gremw0nLxxFUySaHRPw}/_ssgManifest.js +0 -0
|
@@ -119,6 +119,19 @@ describe("RetryHandler — long-context entitlement 429 (#2803)", () => {
|
|
|
119
119
|
const retryStart = emittedEvents.find((e) => e.type === "auto_retry_start");
|
|
120
120
|
assert.ok(retryStart, "Regular 429 should enter backoff retry");
|
|
121
121
|
});
|
|
122
|
+
it("classifies OpenRouter credit affordability errors as quota_exhausted", async () => {
|
|
123
|
+
const { deps, emittedEvents } = createMockDeps({
|
|
124
|
+
model: createMockModel("openrouter", "openai/gpt-5-pro"),
|
|
125
|
+
markUsageLimitReachedResult: false,
|
|
126
|
+
fallbackResult: null,
|
|
127
|
+
});
|
|
128
|
+
const handler = new RetryHandler(deps);
|
|
129
|
+
const msg = errorMessage("402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.");
|
|
130
|
+
const result = await handler.handleRetryableError(msg);
|
|
131
|
+
assert.equal(result, true, "affordability error should trigger credit-aware retry");
|
|
132
|
+
const retryStart = emittedEvents.find((e) => e.type === "auto_retry_start");
|
|
133
|
+
assert.ok(retryStart, "Expected immediate retry after reducing max tokens");
|
|
134
|
+
});
|
|
122
135
|
});
|
|
123
136
|
describe("long-context model downgrade", () => {
|
|
124
137
|
it("downgrades from [1m] to base model when entitlement error and no fallback", async () => {
|
|
@@ -198,6 +211,44 @@ describe("RetryHandler — long-context entitlement 429 (#2803)", () => {
|
|
|
198
211
|
assert.equal(endEvents[0]?.finalError, "Retry cancelled");
|
|
199
212
|
});
|
|
200
213
|
});
|
|
214
|
+
describe("credit-aware maxTokens retry", () => {
|
|
215
|
+
it("reduces maxTokens on same model when provider reports affordable cap", async () => {
|
|
216
|
+
const expensiveModel = createMockModel("openrouter", "openai/gpt-5-pro");
|
|
217
|
+
expensiveModel.maxTokens = 128000;
|
|
218
|
+
const { deps, emittedEvents, onModelChangeFn } = createMockDeps({
|
|
219
|
+
model: expensiveModel,
|
|
220
|
+
markUsageLimitReachedResult: false,
|
|
221
|
+
fallbackResult: null,
|
|
222
|
+
});
|
|
223
|
+
const handler = new RetryHandler(deps);
|
|
224
|
+
const msg = errorMessage("402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.");
|
|
225
|
+
const result = await handler.handleRetryableError(msg);
|
|
226
|
+
assert.equal(result, true, "should retry after reducing maxTokens");
|
|
227
|
+
const setModelCalls = deps.agent.setModel.mock.calls;
|
|
228
|
+
assert.equal(setModelCalls.length, 1, "should apply one model downgrade");
|
|
229
|
+
const downgraded = setModelCalls[0].arguments[0];
|
|
230
|
+
assert.equal(downgraded.provider, "openrouter");
|
|
231
|
+
assert.equal(downgraded.id, "openai/gpt-5-pro");
|
|
232
|
+
assert.equal(downgraded.maxTokens, 297, "expected affordability cap with safety buffer");
|
|
233
|
+
assert.equal(onModelChangeFn.mock.calls.length, 1, "should notify about model update");
|
|
234
|
+
const switchEvent = emittedEvents.find((e) => e.type === "fallback_provider_switch");
|
|
235
|
+
assert.ok(switchEvent, "should emit model-adjustment event");
|
|
236
|
+
assert.ok(String(switchEvent?.reason || "").includes("credit-aware retry"), "switch reason should mention credit-aware retry");
|
|
237
|
+
});
|
|
238
|
+
it("does not mark credentials in cooldown for affordability quota errors", async () => {
|
|
239
|
+
const expensiveModel = createMockModel("openrouter", "openai/gpt-5-pro");
|
|
240
|
+
expensiveModel.maxTokens = 128000;
|
|
241
|
+
const { deps, markUsageLimitReached } = createMockDeps({
|
|
242
|
+
model: expensiveModel,
|
|
243
|
+
markUsageLimitReachedResult: false,
|
|
244
|
+
fallbackResult: null,
|
|
245
|
+
});
|
|
246
|
+
const handler = new RetryHandler(deps);
|
|
247
|
+
const msg = errorMessage("402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.");
|
|
248
|
+
await handler.handleRetryableError(msg);
|
|
249
|
+
assert.equal(markUsageLimitReached.mock.calls.length, 0, "quota error should skip credential cooldown");
|
|
250
|
+
});
|
|
251
|
+
});
|
|
201
252
|
describe("isRetryableError", () => {
|
|
202
253
|
it("considers long-context entitlement error as retryable", () => {
|
|
203
254
|
const { deps } = createMockDeps();
|
|
@@ -215,6 +266,12 @@ describe("RetryHandler — long-context entitlement 429 (#2803)", () => {
|
|
|
215
266
|
'Please wait a moment and try again, or switch to a different provider.');
|
|
216
267
|
assert.equal(handler.isRetryableError(msg), false);
|
|
217
268
|
});
|
|
269
|
+
it("considers OpenRouter affordability credit errors as retryable", () => {
|
|
270
|
+
const { deps } = createMockDeps();
|
|
271
|
+
const handler = new RetryHandler(deps);
|
|
272
|
+
const msg = errorMessage("402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.");
|
|
273
|
+
assert.equal(handler.isRetryableError(msg), true);
|
|
274
|
+
});
|
|
218
275
|
});
|
|
219
276
|
describe("third-party block claude-code fallback (#3772)", () => {
|
|
220
277
|
it("switches to claude-code provider when current provider is anthropic", async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry-handler.test.js","sourceRoot":"","sources":["../../src/core/retry-handler.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * RetryHandler tests — long-context entitlement 429 error handling (#2803)\n *\n * Verifies that \"Extra usage is required for long context requests\" errors\n * are classified as quota_exhausted (not rate_limit) and trigger a model\n * downgrade from [1m] to base when no cross-provider fallback exists.\n */\n\nimport { describe, it, beforeEach, mock, type Mock } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { RetryHandler, type RetryHandlerDeps } from \"./retry-handler.js\";\nimport type { Api, AssistantMessage, Model } from \"@gsd/pi-ai\";\nimport type { FallbackResolver } from \"./fallback-resolver.js\";\nimport type { ModelRegistry } from \"./model-registry.js\";\nimport type { SettingsManager } from \"./settings-manager.js\";\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\nfunction createMockModel(provider: string, id: string): Model<Api> {\n\treturn {\n\t\tid,\n\t\tname: id,\n\t\tapi: \"anthropic\" as Api,\n\t\tprovider,\n\t\tbaseUrl: \"https://api.anthropic.com\",\n\t\treasoning: false,\n\t\tinput: [\"text\"],\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: 1_000_000,\n\t\tmaxTokens: 16384,\n\t} as Model<Api>;\n}\n\nfunction errorMessage(msg: string): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: \"anthropic-messages\",\n\t\tprovider: \"anthropic\",\n\t\tmodel: \"claude-opus-4-6[1m]\",\n\t\tusage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },\n\t\tstopReason: \"error\",\n\t\terrorMessage: msg,\n\t\ttimestamp: Date.now(),\n\t} as AssistantMessage;\n}\n\ninterface MockDeps {\n\tdeps: RetryHandlerDeps;\n\temittedEvents: Array<Record<string, any>>;\n\tcontinueFn: Mock<() => Promise<void>>;\n\tonModelChangeFn: Mock<(model: Model<any>) => void>;\n\tmarkUsageLimitReached: Mock<(...args: any[]) => boolean>;\n\tfindFallback: Mock<(...args: any[]) => Promise<any>>;\n\tfindModel: Mock<(provider: string, modelId: string) => Model<Api> | undefined>;\n}\n\nfunction createMockDeps(overrides?: {\n\tmodel?: Model<Api>;\n\tretryEnabled?: boolean;\n\tmarkUsageLimitReachedResult?: boolean;\n\tfallbackResult?: any;\n\tfindModelResult?: (provider: string, modelId: string) => Model<Api> | undefined;\n\tretrySettings?: {\n\t\tmaxRetries?: number;\n\t\tbaseDelayMs?: number;\n\t\tmaxDelayMs?: number;\n\t};\n}): MockDeps {\n\tconst model = overrides?.model ?? createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\");\n\tconst emittedEvents: Array<Record<string, any>> = [];\n\tconst continueFn = mock.fn(async () => {});\n\tconst onModelChangeFn = mock.fn((_model: Model<any>) => {});\n\tconst markUsageLimitReached = mock.fn(\n\t\t() => overrides?.markUsageLimitReachedResult ?? false,\n\t);\n\tconst findFallback = mock.fn(async () => overrides?.fallbackResult ?? null);\n\tconst findModel = mock.fn(\n\t\toverrides?.findModelResult ?? ((_provider: string, _modelId: string) => undefined),\n\t);\n\n\tconst messages: Array<{ role: string } & Record<string, any>> = [];\n\n\tconst deps: RetryHandlerDeps = {\n\t\tagent: {\n\t\t\tcontinue: continueFn,\n\t\t\tstate: { messages },\n\t\t\tsetModel: mock.fn(),\n\t\t\treplaceMessages: mock.fn((newMessages: any[]) => {\n\t\t\t\tmessages.length = 0;\n\t\t\t\tmessages.push(...newMessages);\n\t\t\t}),\n\t\t} as any,\n\t\tsettingsManager: {\n\t\t\tgetRetryEnabled: () => overrides?.retryEnabled ?? true,\n\t\t\tgetRetrySettings: () => ({\n\t\t\t\tenabled: overrides?.retryEnabled ?? true,\n\t\t\t\tmaxRetries: overrides?.retrySettings?.maxRetries ?? 5,\n\t\t\t\tbaseDelayMs: overrides?.retrySettings?.baseDelayMs ?? 1000,\n\t\t\t\tmaxDelayMs: overrides?.retrySettings?.maxDelayMs ?? 30000,\n\t\t\t}),\n\t\t} as unknown as SettingsManager,\n\t\tmodelRegistry: {\n\t\t\tauthStorage: {\n\t\t\t\tmarkUsageLimitReached,\n\t\t\t},\n\t\t\tfind: findModel,\n\t\t} as unknown as ModelRegistry,\n\t\tfallbackResolver: {\n\t\t\tfindFallback,\n\t\t} as unknown as FallbackResolver,\n\t\tgetModel: () => model,\n\t\tgetSessionId: () => \"test-session\",\n\t\temit: (event: any) => emittedEvents.push(event),\n\t\tonModelChange: onModelChangeFn,\n\t};\n\n\treturn { deps, emittedEvents, continueFn, onModelChangeFn, markUsageLimitReached, findFallback, findModel };\n}\n\n// ─── _classifyErrorType (tested via handleRetryableError behavior) ──────────\n\ndescribe(\"RetryHandler — long-context entitlement 429 (#2803)\", () => {\n\n\tdescribe(\"error classification\", () => {\n\t\tit(\"classifies 'Extra usage is required for long context requests' as quota_exhausted, not rate_limit\", async () => {\n\t\t\t// When the error is classified as quota_exhausted AND no alternate credentials\n\t\t\t// AND no fallback, the handler should emit fallback_chain_exhausted and stop.\n\t\t\t// If misclassified as rate_limit, it would enter the backoff loop instead.\n\t\t\tconst { deps, emittedEvents, findModel } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false, // no alternate credentials\n\t\t\t\tfallbackResult: null, // no cross-provider fallback\n\t\t\t\tfindModelResult: () => undefined, // no base model either\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t'429 {\"type\":\"error\",\"error\":{\"type\":\"rate_limit_error\",\"message\":\"Extra usage is required for long context requests.\"}}'\n\t\t\t);\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\t// Should NOT retry (would be true if misclassified as rate_limit entering backoff)\n\t\t\tassert.equal(result, false);\n\n\t\t\t// Should emit fallback_chain_exhausted (quota_exhausted path), NOT auto_retry_start (backoff path)\n\t\t\tconst chainExhausted = emittedEvents.find((e) => e.type === \"fallback_chain_exhausted\");\n\t\t\tassert.ok(chainExhausted, \"Expected fallback_chain_exhausted event for entitlement error\");\n\n\t\t\tconst retryStart = emittedEvents.find((e) => e.type === \"auto_retry_start\");\n\t\t\tassert.equal(retryStart, undefined, \"Should NOT emit auto_retry_start for entitlement error\");\n\t\t});\n\n\t\tit(\"still classifies regular 429 rate limits as rate_limit\", async () => {\n\t\t\t// A normal \"rate limit\" 429 should still be classified as rate_limit\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"429 Too Many Requests\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\t// Should enter the backoff loop (rate_limit path, not quota_exhausted)\n\t\t\tassert.equal(result, true);\n\n\t\t\tconst retryStart = emittedEvents.find((e) => e.type === \"auto_retry_start\");\n\t\t\tassert.ok(retryStart, \"Regular 429 should enter backoff retry\");\n\t\t});\n\t});\n\n\tdescribe(\"long-context model downgrade\", () => {\n\t\tit(\"downgrades from [1m] to base model when entitlement error and no fallback\", async () => {\n\t\t\tconst baseModel = createMockModel(\"anthropic\", \"claude-opus-4-6\");\n\t\t\tconst { deps, emittedEvents, onModelChangeFn, continueFn } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"anthropic\" && modelId === \"claude-opus-4-6\") return baseModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"Should retry after downgrade\");\n\n\t\t\t// Should have called setModel with the base model\n\t\t\tconst setModelCalls = (deps.agent.setModel as any).mock.calls;\n\t\t\tassert.equal(setModelCalls.length, 1);\n\t\t\tassert.equal(setModelCalls[0].arguments[0].id, \"claude-opus-4-6\");\n\n\t\t\t// Should have notified about model change\n\t\t\tassert.equal(onModelChangeFn.mock.calls.length, 1);\n\n\t\t\t// Should emit a fallback_provider_switch event indicating downgrade\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"Expected fallback_provider_switch event for downgrade\");\n\t\t\tassert.ok(switchEvent!.reason.includes(\"long context downgrade\"), `reason should mention downgrade: ${switchEvent!.reason}`);\n\t\t});\n\n\t\tit(\"emits fallback_chain_exhausted when base model is also unavailable\", async () => {\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t\tfindModelResult: () => undefined, // base model not found\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, false);\n\t\t\tconst chainExhausted = emittedEvents.find((e) => e.type === \"fallback_chain_exhausted\");\n\t\t\tassert.ok(chainExhausted, \"Expected fallback_chain_exhausted when base model unavailable\");\n\t\t});\n\n\t\tit(\"does not attempt downgrade for non-[1m] models\", async () => {\n\t\t\t// When a regular model (no [1m] suffix) gets a quota_exhausted error\n\t\t\t// with no fallback, it should just stop — no downgrade attempt.\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, false);\n\t\t\tconst chainExhausted = emittedEvents.find((e) => e.type === \"fallback_chain_exhausted\");\n\t\t\tassert.ok(chainExhausted);\n\n\t\t\t// No downgrade switch should occur\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.equal(switchEvent, undefined, \"Should not switch for non-[1m] models\");\n\t\t});\n\t});\n\n\tdescribe(\"retry cancellation\", () => {\n\t\tit(\"cancels queued immediate continue callbacks when retry is aborted\", async () => {\n\t\t\tconst { deps, emittedEvents, continueFn } = createMockDeps({\n\t\t\t\tmarkUsageLimitReachedResult: true,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"429 Too Many Requests\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\t\t\tassert.equal(result, true, \"retry should be initiated\");\n\n\t\t\thandler.abortRetry();\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 10));\n\n\t\t\tassert.equal(continueFn.mock.calls.length, 0, \"cancelled retry must not continue after explicit abort\");\n\t\t\tconst endEvents = emittedEvents.filter((e) => e.type === \"auto_retry_end\");\n\t\t\tassert.equal(endEvents.length, 1, \"retry cancellation should emit a single auto_retry_end event\");\n\t\t\tassert.equal(endEvents[0]?.finalError, \"Retry cancelled\");\n\t\t});\n\t});\n\n\tdescribe(\"isRetryableError\", () => {\n\t\tit(\"considers long-context entitlement error as retryable\", () => {\n\t\t\tconst { deps } = createMockDeps();\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\t\t\tassert.equal(handler.isRetryableError(msg), true);\n\t\t});\n\n\t\tit(\"does NOT consider credential cooldown error as retryable (#3429)\", () => {\n\t\t\t// The credential cooldown message from getApiKey() must not re-enter\n\t\t\t// the retry handler. Re-entry creates cascading empty error entries\n\t\t\t// in the session file that break resume.\n\t\t\tconst { deps } = createMockDeps();\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t'All credentials for \"anthropic\" are in a cooldown window. ' +\n\t\t\t\t'Please wait a moment and try again, or switch to a different provider.',\n\t\t\t);\n\t\t\tassert.equal(handler.isRetryableError(msg), false);\n\t\t});\n\t});\n\n\tdescribe(\"third-party block claude-code fallback (#3772)\", () => {\n\t\tit(\"switches to claude-code provider when current provider is anthropic\", async () => {\n\t\t\tconst ccModel = createMockModel(\"claude-code\", \"claude-opus-4-6\");\n\t\t\tconst { deps, emittedEvents, onModelChangeFn } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"claude-code\" && modelId === \"claude-opus-4-6\") return ccModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t\tdeps.isClaudeCodeReady = () => true;\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"third-party apps cannot draw from extra usage\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"should retry via claude-code fallback\");\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"Expected fallback_provider_switch event\");\n\t\t\tassert.ok(switchEvent!.to.startsWith(\"claude-code/\"), \"Should switch to claude-code provider\");\n\t\t});\n\n\t\tit(\"switches to claude-code on 'out of extra usage' error (#3772)\", async () => {\n\t\t\tconst ccModel = createMockModel(\"claude-code\", \"claude-opus-4-6\");\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"claude-code\" && modelId === \"claude-opus-4-6\") return ccModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t\tdeps.isClaudeCodeReady = () => true;\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"You're out of extra usage. Add more at claude.ai/settings/usage and keep going.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"should retry via claude-code fallback\");\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"Expected fallback_provider_switch event\");\n\t\t\tassert.ok(switchEvent!.to.startsWith(\"claude-code/\"), \"Should switch to claude-code provider\");\n\t\t});\n\n\t\tit(\"does NOT switch to claude-code when current provider is not anthropic\", async () => {\n\t\t\tconst ccModel = createMockModel(\"claude-code\", \"gpt-4o\");\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"openai\", \"gpt-4o\"),\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"claude-code\" && modelId === \"gpt-4o\") return ccModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t\tdeps.isClaudeCodeReady = () => true;\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"third-party apps are not supported for this plan\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\t// Should NOT have triggered the claude-code fallback\n\t\t\tconst switchEvent = emittedEvents.find(\n\t\t\t\t(e) => e.type === \"fallback_provider_switch\" && e.to?.startsWith(\"claude-code/\"),\n\t\t\t);\n\t\t\tassert.equal(switchEvent, undefined, \"Should NOT switch non-anthropic provider to claude-code\");\n\t\t});\n\t});\n\n\tdescribe(\"quota_exhausted credential backoff (#3430)\", () => {\n\t\tit(\"does NOT call markUsageLimitReached for quota_exhausted errors\", async () => {\n\t\t\t// \"Extra usage is required\" is an account-level billing gate.\n\t\t\t// Backing off the credential for 30 minutes blocks all provider\n\t\t\t// requests and has no effect on the billing condition.\n\t\t\tconst { deps, markUsageLimitReached } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t\tfindModelResult: () => undefined,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t'429 {\"type\":\"error\",\"error\":{\"type\":\"rate_limit_error\",\"message\":\"Extra usage is required for long context requests.\"}}',\n\t\t\t);\n\n\t\t\tawait handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(\n\t\t\t\tmarkUsageLimitReached.mock.calls.length,\n\t\t\t\t0,\n\t\t\t\t\"markUsageLimitReached must NOT be called for quota_exhausted errors\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"still calls markUsageLimitReached for regular rate_limit errors\", async () => {\n\t\t\tconst { deps, markUsageLimitReached } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"429 Too Many Requests\");\n\n\t\t\tawait handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(\n\t\t\t\tmarkUsageLimitReached.mock.calls.length,\n\t\t\t\t1,\n\t\t\t\t\"markUsageLimitReached should be called for rate_limit errors\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"still tries cross-provider fallback for quota_exhausted without credential backoff\", async () => {\n\t\t\tconst fallbackModel = createMockModel(\"openai\", \"gpt-4o\");\n\t\t\tconst { deps, markUsageLimitReached, continueFn } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: { model: fallbackModel, reason: \"cross-provider fallback\" },\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"should retry with fallback provider\");\n\t\t\tassert.equal(\n\t\t\t\tmarkUsageLimitReached.mock.calls.length,\n\t\t\t\t0,\n\t\t\t\t\"should NOT back off credentials before trying fallback\",\n\t\t\t);\n\t\t});\n\t});\n});\n"]}
|
|
1
|
+
{"version":3,"file":"retry-handler.test.js","sourceRoot":"","sources":["../../src/core/retry-handler.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAc,IAAI,EAAa,MAAM,WAAW,CAAC;AACtE,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAyB,MAAM,oBAAoB,CAAC;AAMzE,+EAA+E;AAE/E,SAAS,eAAe,CAAC,QAAgB,EAAE,EAAU;IACpD,OAAO;QACN,EAAE;QACF,IAAI,EAAE,EAAE;QACR,GAAG,EAAE,WAAkB;QACvB,QAAQ;QACR,OAAO,EAAE,2BAA2B;QACpC,SAAS,EAAE,KAAK;QAChB,KAAK,EAAE,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;QAC1D,aAAa,EAAE,SAAS;QACxB,SAAS,EAAE,KAAK;KACF,CAAC;AACjB,CAAC;AAED,SAAS,YAAY,CAAC,GAAW;IAChC,OAAO;QACN,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,EAAE;QACX,GAAG,EAAE,oBAAoB;QACzB,QAAQ,EAAE,WAAW;QACrB,KAAK,EAAE,qBAAqB;QAC5B,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACjJ,UAAU,EAAE,OAAO;QACnB,YAAY,EAAE,GAAG;QACjB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACD,CAAC;AACvB,CAAC;AAYD,SAAS,cAAc,CAAC,SAWvB;IACA,MAAM,KAAK,GAAG,SAAS,EAAE,KAAK,IAAI,eAAe,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAC;IACtF,MAAM,aAAa,GAA+B,EAAE,CAAC;IACrD,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC,CAAC;IAC3C,MAAM,eAAe,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,MAAkB,EAAE,EAAE,GAAE,CAAC,CAAC,CAAC;IAC5D,MAAM,qBAAqB,GAAG,IAAI,CAAC,EAAE,CACpC,GAAG,EAAE,CAAC,SAAS,EAAE,2BAA2B,IAAI,KAAK,CACrD,CAAC;IACF,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,SAAS,EAAE,cAAc,IAAI,IAAI,CAAC,CAAC;IAC5E,MAAM,SAAS,GAAG,IAAI,CAAC,EAAE,CACxB,SAAS,EAAE,eAAe,IAAI,CAAC,CAAC,SAAiB,EAAE,QAAgB,EAAE,EAAE,CAAC,SAAS,CAAC,CAClF,CAAC;IAEF,MAAM,QAAQ,GAAkD,EAAE,CAAC;IAEnE,MAAM,IAAI,GAAqB;QAC9B,KAAK,EAAE;YACN,QAAQ,EAAE,UAAU;YACpB,KAAK,EAAE,EAAE,QAAQ,EAAE;YACnB,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE;YACnB,eAAe,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,WAAkB,EAAE,EAAE;gBAC/C,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;gBACpB,QAAQ,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;YAC/B,CAAC,CAAC;SACK;QACR,eAAe,EAAE;YAChB,eAAe,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,YAAY,IAAI,IAAI;YACtD,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC;gBACxB,OAAO,EAAE,SAAS,EAAE,YAAY,IAAI,IAAI;gBACxC,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC;gBACrD,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,IAAI,IAAI;gBAC1D,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,IAAI,KAAK;aACzD,CAAC;SAC4B;QAC/B,aAAa,EAAE;YACd,WAAW,EAAE;gBACZ,qBAAqB;aACrB;YACD,IAAI,EAAE,SAAS;SACa;QAC7B,gBAAgB,EAAE;YACjB,YAAY;SACmB;QAChC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK;QACrB,YAAY,EAAE,GAAG,EAAE,CAAC,cAAc;QAClC,IAAI,EAAE,CAAC,KAAU,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;QAC/C,aAAa,EAAE,eAAe;KAC9B,CAAC;IAEF,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,qBAAqB,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;AAC7G,CAAC;AAED,+EAA+E;AAE/E,QAAQ,CAAC,qDAAqD,EAAE,GAAG,EAAE;IAEpE,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACrC,EAAE,CAAC,mGAAmG,EAAE,KAAK,IAAI,EAAE;YAClH,+EAA+E;YAC/E,8EAA8E;YAC9E,2EAA2E;YAC3E,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,cAAc,CAAC;gBACzD,KAAK,EAAE,eAAe,CAAC,WAAW,EAAE,qBAAqB,CAAC;gBAC1D,2BAA2B,EAAE,KAAK,EAAE,2BAA2B;gBAC/D,cAAc,EAAE,IAAI,EAAE,6BAA6B;gBACnD,eAAe,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,uBAAuB;aACzD,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CACvB,yHAAyH,CACzH,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAEvD,mFAAmF;YACnF,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAE5B,mGAAmG;YACnG,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,0BAA0B,CAAC,CAAC;YACxF,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,+DAA+D,CAAC,CAAC;YAE3F,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC;YAC5E,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,SAAS,EAAE,wDAAwD,CAAC,CAAC;QAC/F,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;YACvE,qEAAqE;YACrE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,cAAc,CAAC;gBAC9C,KAAK,EAAE,eAAe,CAAC,WAAW,EAAE,iBAAiB,CAAC;gBACtD,2BAA2B,EAAE,KAAK;gBAClC,cAAc,EAAE,IAAI;aACpB,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CAAC,uBAAuB,CAAC,CAAC;YAElD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAEvD,uEAAuE;YACvE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAE3B,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC;YAC5E,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,wCAAwC,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;YACrF,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,cAAc,CAAC;gBAC9C,KAAK,EAAE,eAAe,CAAC,YAAY,EAAE,kBAAkB,CAAC;gBACxD,2BAA2B,EAAE,KAAK;gBAClC,cAAc,EAAE,IAAI;aACpB,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CACvB,yHAAyH,CACzH,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAEvD,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,uDAAuD,CAAC,CAAC;YACpF,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC;YAC5E,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,oDAAoD,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC7C,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;YAC1F,MAAM,SAAS,GAAG,eAAe,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;YAClE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,eAAe,EAAE,UAAU,EAAE,GAAG,cAAc,CAAC;gBAC3E,KAAK,EAAE,eAAe,CAAC,WAAW,EAAE,qBAAqB,CAAC;gBAC1D,2BAA2B,EAAE,KAAK;gBAClC,cAAc,EAAE,IAAI;gBACpB,eAAe,EAAE,CAAC,QAAgB,EAAE,OAAe,EAAE,EAAE;oBACtD,IAAI,QAAQ,KAAK,WAAW,IAAI,OAAO,KAAK,iBAAiB;wBAAE,OAAO,SAAS,CAAC;oBAChF,OAAO,SAAS,CAAC;gBAClB,CAAC;aACD,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CAAC,oDAAoD,CAAC,CAAC;YAE/E,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAEvD,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,8BAA8B,CAAC,CAAC;YAE3D,kDAAkD;YAClD,MAAM,aAAa,GAAI,IAAI,CAAC,KAAK,CAAC,QAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;YAC9D,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACtC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,iBAAiB,CAAC,CAAC;YAElE,0CAA0C;YAC1C,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAEnD,oEAAoE;YACpE,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,0BAA0B,CAAC,CAAC;YACrF,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,uDAAuD,CAAC,CAAC;YAChF,MAAM,CAAC,EAAE,CAAC,WAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,oCAAoC,WAAY,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9H,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;YACnF,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,cAAc,CAAC;gBAC9C,KAAK,EAAE,eAAe,CAAC,WAAW,EAAE,qBAAqB,CAAC;gBAC1D,2BAA2B,EAAE,KAAK;gBAClC,cAAc,EAAE,IAAI;gBACpB,eAAe,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,uBAAuB;aACzD,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CAAC,oDAAoD,CAAC,CAAC;YAE/E,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAEvD,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC5B,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,0BAA0B,CAAC,CAAC;YACxF,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,+DAA+D,CAAC,CAAC;QAC5F,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC/D,qEAAqE;YACrE,gEAAgE;YAChE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,cAAc,CAAC;gBAC9C,KAAK,EAAE,eAAe,CAAC,WAAW,EAAE,iBAAiB,CAAC;gBACtD,2BAA2B,EAAE,KAAK;gBAClC,cAAc,EAAE,IAAI;aACpB,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CAAC,oDAAoD,CAAC,CAAC;YAE/E,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAEvD,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC5B,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,0BAA0B,CAAC,CAAC;YACxF,MAAM,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC;YAE1B,mCAAmC;YACnC,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,0BAA0B,CAAC,CAAC;YACrF,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,SAAS,EAAE,uCAAuC,CAAC,CAAC;QAC/E,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QACnC,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;YAClF,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,GAAG,cAAc,CAAC;gBAC1D,2BAA2B,EAAE,IAAI;aACjC,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CAAC,uBAAuB,CAAC,CAAC;YAElD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YACvD,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,2BAA2B,CAAC,CAAC;YAExD,OAAO,CAAC,UAAU,EAAE,CAAC;YACrB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;YAExD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,wDAAwD,CAAC,CAAC;YACxG,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;YAC3E,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,8DAA8D,CAAC,CAAC;YAClG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC7C,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;YACrF,MAAM,cAAc,GAAG,eAAe,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;YACzE,cAAc,CAAC,SAAS,GAAG,MAAM,CAAC;YAElC,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,cAAc,CAAC;gBAC/D,KAAK,EAAE,cAAc;gBACrB,2BAA2B,EAAE,KAAK;gBAClC,cAAc,EAAE,IAAI;aACpB,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CACvB,yHAAyH,CACzH,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YACvD,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,uCAAuC,CAAC,CAAC;YAEpE,MAAM,aAAa,GAAI,IAAI,CAAC,KAAK,CAAC,QAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;YAC9D,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,kCAAkC,CAAC,CAAC;YAC1E,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAe,CAAC;YAC/D,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YAChD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,EAAE,kBAAkB,CAAC,CAAC;YAChD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,EAAE,GAAG,EAAE,+CAA+C,CAAC,CAAC;YAEzF,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,kCAAkC,CAAC,CAAC;YACvF,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,0BAA0B,CAAC,CAAC;YACrF,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,oCAAoC,CAAC,CAAC;YAC7D,MAAM,CAAC,EAAE,CACR,MAAM,CAAC,WAAW,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAChE,iDAAiD,CACjD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;YACrF,MAAM,cAAc,GAAG,eAAe,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;YACzE,cAAc,CAAC,SAAS,GAAG,MAAM,CAAC;YAElC,MAAM,EAAE,IAAI,EAAE,qBAAqB,EAAE,GAAG,cAAc,CAAC;gBACtD,KAAK,EAAE,cAAc;gBACrB,2BAA2B,EAAE,KAAK;gBAClC,cAAc,EAAE,IAAI;aACpB,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CACvB,yHAAyH,CACzH,CAAC;YAEF,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,6CAA6C,CAAC,CAAC;QACzG,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;YAChE,MAAM,EAAE,IAAI,EAAE,GAAG,cAAc,EAAE,CAAC;YAClC,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CAAC,oDAAoD,CAAC,CAAC;YAC/E,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;YAC3E,qEAAqE;YACrE,oEAAoE;YACpE,yCAAyC;YACzC,MAAM,EAAE,IAAI,EAAE,GAAG,cAAc,EAAE,CAAC;YAClC,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CACvB,4DAA4D;gBAC5D,wEAAwE,CACxE,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;YACxE,MAAM,EAAE,IAAI,EAAE,GAAG,cAAc,EAAE,CAAC;YAClC,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CACvB,yHAAyH,CACzH,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gDAAgD,EAAE,GAAG,EAAE;QAC/D,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;YACpF,MAAM,OAAO,GAAG,eAAe,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;YAClE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,cAAc,CAAC;gBAC/D,KAAK,EAAE,eAAe,CAAC,WAAW,EAAE,iBAAiB,CAAC;gBACtD,eAAe,EAAE,CAAC,QAAgB,EAAE,OAAe,EAAE,EAAE;oBACtD,IAAI,QAAQ,KAAK,aAAa,IAAI,OAAO,KAAK,iBAAiB;wBAAE,OAAO,OAAO,CAAC;oBAChF,OAAO,SAAS,CAAC;gBAClB,CAAC;aACD,CAAC,CAAC;YACH,IAAI,CAAC,iBAAiB,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;YAEpC,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CAAC,+CAA+C,CAAC,CAAC;YAE1E,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAEvD,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,uCAAuC,CAAC,CAAC;YACpE,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,0BAA0B,CAAC,CAAC;YACrF,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,yCAAyC,CAAC,CAAC;YAClE,MAAM,CAAC,EAAE,CAAC,WAAY,CAAC,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,uCAAuC,CAAC,CAAC;QAChG,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;YAC9E,MAAM,OAAO,GAAG,eAAe,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;YAClE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,cAAc,CAAC;gBAC9C,KAAK,EAAE,eAAe,CAAC,WAAW,EAAE,iBAAiB,CAAC;gBACtD,eAAe,EAAE,CAAC,QAAgB,EAAE,OAAe,EAAE,EAAE;oBACtD,IAAI,QAAQ,KAAK,aAAa,IAAI,OAAO,KAAK,iBAAiB;wBAAE,OAAO,OAAO,CAAC;oBAChF,OAAO,SAAS,CAAC;gBAClB,CAAC;aACD,CAAC,CAAC;YACH,IAAI,CAAC,iBAAiB,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;YAEpC,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CAAC,iFAAiF,CAAC,CAAC;YAE5G,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAEvD,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,uCAAuC,CAAC,CAAC;YACpE,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,0BAA0B,CAAC,CAAC;YACrF,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,yCAAyC,CAAC,CAAC;YAClE,MAAM,CAAC,EAAE,CAAC,WAAY,CAAC,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,uCAAuC,CAAC,CAAC;QAChG,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;YACtF,MAAM,OAAO,GAAG,eAAe,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;YACzD,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,cAAc,CAAC;gBAC9C,KAAK,EAAE,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC;gBAC1C,eAAe,EAAE,CAAC,QAAgB,EAAE,OAAe,EAAE,EAAE;oBACtD,IAAI,QAAQ,KAAK,aAAa,IAAI,OAAO,KAAK,QAAQ;wBAAE,OAAO,OAAO,CAAC;oBACvE,OAAO,SAAS,CAAC;gBAClB,CAAC;aACD,CAAC,CAAC;YACH,IAAI,CAAC,iBAAiB,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;YAEpC,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CAAC,kDAAkD,CAAC,CAAC;YAE7E,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAEvD,qDAAqD;YACrD,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CACrC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,0BAA0B,IAAI,CAAC,CAAC,EAAE,EAAE,UAAU,CAAC,cAAc,CAAC,CAChF,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,SAAS,EAAE,yDAAyD,CAAC,CAAC;QACjG,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,4CAA4C,EAAE,GAAG,EAAE;QAC3D,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;YAC/E,8DAA8D;YAC9D,gEAAgE;YAChE,uDAAuD;YACvD,MAAM,EAAE,IAAI,EAAE,qBAAqB,EAAE,GAAG,cAAc,CAAC;gBACtD,KAAK,EAAE,eAAe,CAAC,WAAW,EAAE,qBAAqB,CAAC;gBAC1D,2BAA2B,EAAE,KAAK;gBAClC,cAAc,EAAE,IAAI;gBACpB,eAAe,EAAE,GAAG,EAAE,CAAC,SAAS;aAChC,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CACvB,yHAAyH,CACzH,CAAC;YAEF,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAExC,MAAM,CAAC,KAAK,CACX,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EACvC,CAAC,EACD,qEAAqE,CACrE,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;YAChF,MAAM,EAAE,IAAI,EAAE,qBAAqB,EAAE,GAAG,cAAc,CAAC;gBACtD,KAAK,EAAE,eAAe,CAAC,WAAW,EAAE,iBAAiB,CAAC;gBACtD,2BAA2B,EAAE,KAAK;gBAClC,cAAc,EAAE,IAAI;aACpB,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CAAC,uBAAuB,CAAC,CAAC;YAElD,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAExC,MAAM,CAAC,KAAK,CACX,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EACvC,CAAC,EACD,8DAA8D,CAC9D,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;YACnG,MAAM,aAAa,GAAG,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC1D,MAAM,EAAE,IAAI,EAAE,qBAAqB,EAAE,UAAU,EAAE,GAAG,cAAc,CAAC;gBAClE,KAAK,EAAE,eAAe,CAAC,WAAW,EAAE,qBAAqB,CAAC;gBAC1D,2BAA2B,EAAE,KAAK;gBAClC,cAAc,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,yBAAyB,EAAE;aAC3E,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,YAAY,CAAC,oDAAoD,CAAC,CAAC;YAE/E,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAEvD,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,qCAAqC,CAAC,CAAC;YAClE,MAAM,CAAC,KAAK,CACX,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EACvC,CAAC,EACD,wDAAwD,CACxD,CAAC;QACH,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["/**\n * RetryHandler tests — long-context entitlement 429 error handling (#2803)\n *\n * Verifies that \"Extra usage is required for long context requests\" errors\n * are classified as quota_exhausted (not rate_limit) and trigger a model\n * downgrade from [1m] to base when no cross-provider fallback exists.\n */\n\nimport { describe, it, beforeEach, mock, type Mock } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { RetryHandler, type RetryHandlerDeps } from \"./retry-handler.js\";\nimport type { Api, AssistantMessage, Model } from \"@gsd/pi-ai\";\nimport type { FallbackResolver } from \"./fallback-resolver.js\";\nimport type { ModelRegistry } from \"./model-registry.js\";\nimport type { SettingsManager } from \"./settings-manager.js\";\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\nfunction createMockModel(provider: string, id: string): Model<Api> {\n\treturn {\n\t\tid,\n\t\tname: id,\n\t\tapi: \"anthropic\" as Api,\n\t\tprovider,\n\t\tbaseUrl: \"https://api.anthropic.com\",\n\t\treasoning: false,\n\t\tinput: [\"text\"],\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: 1_000_000,\n\t\tmaxTokens: 16384,\n\t} as Model<Api>;\n}\n\nfunction errorMessage(msg: string): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: \"anthropic-messages\",\n\t\tprovider: \"anthropic\",\n\t\tmodel: \"claude-opus-4-6[1m]\",\n\t\tusage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },\n\t\tstopReason: \"error\",\n\t\terrorMessage: msg,\n\t\ttimestamp: Date.now(),\n\t} as AssistantMessage;\n}\n\ninterface MockDeps {\n\tdeps: RetryHandlerDeps;\n\temittedEvents: Array<Record<string, any>>;\n\tcontinueFn: Mock<() => Promise<void>>;\n\tonModelChangeFn: Mock<(model: Model<any>) => void>;\n\tmarkUsageLimitReached: Mock<(...args: any[]) => boolean>;\n\tfindFallback: Mock<(...args: any[]) => Promise<any>>;\n\tfindModel: Mock<(provider: string, modelId: string) => Model<Api> | undefined>;\n}\n\nfunction createMockDeps(overrides?: {\n\tmodel?: Model<Api>;\n\tretryEnabled?: boolean;\n\tmarkUsageLimitReachedResult?: boolean;\n\tfallbackResult?: any;\n\tfindModelResult?: (provider: string, modelId: string) => Model<Api> | undefined;\n\tretrySettings?: {\n\t\tmaxRetries?: number;\n\t\tbaseDelayMs?: number;\n\t\tmaxDelayMs?: number;\n\t};\n}): MockDeps {\n\tconst model = overrides?.model ?? createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\");\n\tconst emittedEvents: Array<Record<string, any>> = [];\n\tconst continueFn = mock.fn(async () => {});\n\tconst onModelChangeFn = mock.fn((_model: Model<any>) => {});\n\tconst markUsageLimitReached = mock.fn(\n\t\t() => overrides?.markUsageLimitReachedResult ?? false,\n\t);\n\tconst findFallback = mock.fn(async () => overrides?.fallbackResult ?? null);\n\tconst findModel = mock.fn(\n\t\toverrides?.findModelResult ?? ((_provider: string, _modelId: string) => undefined),\n\t);\n\n\tconst messages: Array<{ role: string } & Record<string, any>> = [];\n\n\tconst deps: RetryHandlerDeps = {\n\t\tagent: {\n\t\t\tcontinue: continueFn,\n\t\t\tstate: { messages },\n\t\t\tsetModel: mock.fn(),\n\t\t\treplaceMessages: mock.fn((newMessages: any[]) => {\n\t\t\t\tmessages.length = 0;\n\t\t\t\tmessages.push(...newMessages);\n\t\t\t}),\n\t\t} as any,\n\t\tsettingsManager: {\n\t\t\tgetRetryEnabled: () => overrides?.retryEnabled ?? true,\n\t\t\tgetRetrySettings: () => ({\n\t\t\t\tenabled: overrides?.retryEnabled ?? true,\n\t\t\t\tmaxRetries: overrides?.retrySettings?.maxRetries ?? 5,\n\t\t\t\tbaseDelayMs: overrides?.retrySettings?.baseDelayMs ?? 1000,\n\t\t\t\tmaxDelayMs: overrides?.retrySettings?.maxDelayMs ?? 30000,\n\t\t\t}),\n\t\t} as unknown as SettingsManager,\n\t\tmodelRegistry: {\n\t\t\tauthStorage: {\n\t\t\t\tmarkUsageLimitReached,\n\t\t\t},\n\t\t\tfind: findModel,\n\t\t} as unknown as ModelRegistry,\n\t\tfallbackResolver: {\n\t\t\tfindFallback,\n\t\t} as unknown as FallbackResolver,\n\t\tgetModel: () => model,\n\t\tgetSessionId: () => \"test-session\",\n\t\temit: (event: any) => emittedEvents.push(event),\n\t\tonModelChange: onModelChangeFn,\n\t};\n\n\treturn { deps, emittedEvents, continueFn, onModelChangeFn, markUsageLimitReached, findFallback, findModel };\n}\n\n// ─── _classifyErrorType (tested via handleRetryableError behavior) ──────────\n\ndescribe(\"RetryHandler — long-context entitlement 429 (#2803)\", () => {\n\n\tdescribe(\"error classification\", () => {\n\t\tit(\"classifies 'Extra usage is required for long context requests' as quota_exhausted, not rate_limit\", async () => {\n\t\t\t// When the error is classified as quota_exhausted AND no alternate credentials\n\t\t\t// AND no fallback, the handler should emit fallback_chain_exhausted and stop.\n\t\t\t// If misclassified as rate_limit, it would enter the backoff loop instead.\n\t\t\tconst { deps, emittedEvents, findModel } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false, // no alternate credentials\n\t\t\t\tfallbackResult: null, // no cross-provider fallback\n\t\t\t\tfindModelResult: () => undefined, // no base model either\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t'429 {\"type\":\"error\",\"error\":{\"type\":\"rate_limit_error\",\"message\":\"Extra usage is required for long context requests.\"}}'\n\t\t\t);\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\t// Should NOT retry (would be true if misclassified as rate_limit entering backoff)\n\t\t\tassert.equal(result, false);\n\n\t\t\t// Should emit fallback_chain_exhausted (quota_exhausted path), NOT auto_retry_start (backoff path)\n\t\t\tconst chainExhausted = emittedEvents.find((e) => e.type === \"fallback_chain_exhausted\");\n\t\t\tassert.ok(chainExhausted, \"Expected fallback_chain_exhausted event for entitlement error\");\n\n\t\t\tconst retryStart = emittedEvents.find((e) => e.type === \"auto_retry_start\");\n\t\t\tassert.equal(retryStart, undefined, \"Should NOT emit auto_retry_start for entitlement error\");\n\t\t});\n\n\t\tit(\"still classifies regular 429 rate limits as rate_limit\", async () => {\n\t\t\t// A normal \"rate limit\" 429 should still be classified as rate_limit\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"429 Too Many Requests\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\t// Should enter the backoff loop (rate_limit path, not quota_exhausted)\n\t\t\tassert.equal(result, true);\n\n\t\t\tconst retryStart = emittedEvents.find((e) => e.type === \"auto_retry_start\");\n\t\t\tassert.ok(retryStart, \"Regular 429 should enter backoff retry\");\n\t\t});\n\n\t\tit(\"classifies OpenRouter credit affordability errors as quota_exhausted\", async () => {\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"openrouter\", \"openai/gpt-5-pro\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t\"402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.\",\n\t\t\t);\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"affordability error should trigger credit-aware retry\");\n\t\t\tconst retryStart = emittedEvents.find((e) => e.type === \"auto_retry_start\");\n\t\t\tassert.ok(retryStart, \"Expected immediate retry after reducing max tokens\");\n\t\t});\n\t});\n\n\tdescribe(\"long-context model downgrade\", () => {\n\t\tit(\"downgrades from [1m] to base model when entitlement error and no fallback\", async () => {\n\t\t\tconst baseModel = createMockModel(\"anthropic\", \"claude-opus-4-6\");\n\t\t\tconst { deps, emittedEvents, onModelChangeFn, continueFn } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"anthropic\" && modelId === \"claude-opus-4-6\") return baseModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"Should retry after downgrade\");\n\n\t\t\t// Should have called setModel with the base model\n\t\t\tconst setModelCalls = (deps.agent.setModel as any).mock.calls;\n\t\t\tassert.equal(setModelCalls.length, 1);\n\t\t\tassert.equal(setModelCalls[0].arguments[0].id, \"claude-opus-4-6\");\n\n\t\t\t// Should have notified about model change\n\t\t\tassert.equal(onModelChangeFn.mock.calls.length, 1);\n\n\t\t\t// Should emit a fallback_provider_switch event indicating downgrade\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"Expected fallback_provider_switch event for downgrade\");\n\t\t\tassert.ok(switchEvent!.reason.includes(\"long context downgrade\"), `reason should mention downgrade: ${switchEvent!.reason}`);\n\t\t});\n\n\t\tit(\"emits fallback_chain_exhausted when base model is also unavailable\", async () => {\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t\tfindModelResult: () => undefined, // base model not found\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, false);\n\t\t\tconst chainExhausted = emittedEvents.find((e) => e.type === \"fallback_chain_exhausted\");\n\t\t\tassert.ok(chainExhausted, \"Expected fallback_chain_exhausted when base model unavailable\");\n\t\t});\n\n\t\tit(\"does not attempt downgrade for non-[1m] models\", async () => {\n\t\t\t// When a regular model (no [1m] suffix) gets a quota_exhausted error\n\t\t\t// with no fallback, it should just stop — no downgrade attempt.\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, false);\n\t\t\tconst chainExhausted = emittedEvents.find((e) => e.type === \"fallback_chain_exhausted\");\n\t\t\tassert.ok(chainExhausted);\n\n\t\t\t// No downgrade switch should occur\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.equal(switchEvent, undefined, \"Should not switch for non-[1m] models\");\n\t\t});\n\t});\n\n\tdescribe(\"retry cancellation\", () => {\n\t\tit(\"cancels queued immediate continue callbacks when retry is aborted\", async () => {\n\t\t\tconst { deps, emittedEvents, continueFn } = createMockDeps({\n\t\t\t\tmarkUsageLimitReachedResult: true,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"429 Too Many Requests\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\t\t\tassert.equal(result, true, \"retry should be initiated\");\n\n\t\t\thandler.abortRetry();\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 10));\n\n\t\t\tassert.equal(continueFn.mock.calls.length, 0, \"cancelled retry must not continue after explicit abort\");\n\t\t\tconst endEvents = emittedEvents.filter((e) => e.type === \"auto_retry_end\");\n\t\t\tassert.equal(endEvents.length, 1, \"retry cancellation should emit a single auto_retry_end event\");\n\t\t\tassert.equal(endEvents[0]?.finalError, \"Retry cancelled\");\n\t\t});\n\t});\n\n\tdescribe(\"credit-aware maxTokens retry\", () => {\n\t\tit(\"reduces maxTokens on same model when provider reports affordable cap\", async () => {\n\t\t\tconst expensiveModel = createMockModel(\"openrouter\", \"openai/gpt-5-pro\");\n\t\t\texpensiveModel.maxTokens = 128000;\n\n\t\t\tconst { deps, emittedEvents, onModelChangeFn } = createMockDeps({\n\t\t\t\tmodel: expensiveModel,\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t\"402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.\",\n\t\t\t);\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\t\t\tassert.equal(result, true, \"should retry after reducing maxTokens\");\n\n\t\t\tconst setModelCalls = (deps.agent.setModel as any).mock.calls;\n\t\t\tassert.equal(setModelCalls.length, 1, \"should apply one model downgrade\");\n\t\t\tconst downgraded = setModelCalls[0].arguments[0] as Model<Api>;\n\t\t\tassert.equal(downgraded.provider, \"openrouter\");\n\t\t\tassert.equal(downgraded.id, \"openai/gpt-5-pro\");\n\t\t\tassert.equal(downgraded.maxTokens, 297, \"expected affordability cap with safety buffer\");\n\n\t\t\tassert.equal(onModelChangeFn.mock.calls.length, 1, \"should notify about model update\");\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"should emit model-adjustment event\");\n\t\t\tassert.ok(\n\t\t\t\tString(switchEvent?.reason || \"\").includes(\"credit-aware retry\"),\n\t\t\t\t\"switch reason should mention credit-aware retry\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"does not mark credentials in cooldown for affordability quota errors\", async () => {\n\t\t\tconst expensiveModel = createMockModel(\"openrouter\", \"openai/gpt-5-pro\");\n\t\t\texpensiveModel.maxTokens = 128000;\n\n\t\t\tconst { deps, markUsageLimitReached } = createMockDeps({\n\t\t\t\tmodel: expensiveModel,\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t\"402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.\",\n\t\t\t);\n\n\t\t\tawait handler.handleRetryableError(msg);\n\t\t\tassert.equal(markUsageLimitReached.mock.calls.length, 0, \"quota error should skip credential cooldown\");\n\t\t});\n\t});\n\n\tdescribe(\"isRetryableError\", () => {\n\t\tit(\"considers long-context entitlement error as retryable\", () => {\n\t\t\tconst { deps } = createMockDeps();\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\t\t\tassert.equal(handler.isRetryableError(msg), true);\n\t\t});\n\n\t\tit(\"does NOT consider credential cooldown error as retryable (#3429)\", () => {\n\t\t\t// The credential cooldown message from getApiKey() must not re-enter\n\t\t\t// the retry handler. Re-entry creates cascading empty error entries\n\t\t\t// in the session file that break resume.\n\t\t\tconst { deps } = createMockDeps();\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t'All credentials for \"anthropic\" are in a cooldown window. ' +\n\t\t\t\t'Please wait a moment and try again, or switch to a different provider.',\n\t\t\t);\n\t\t\tassert.equal(handler.isRetryableError(msg), false);\n\t\t});\n\n\t\tit(\"considers OpenRouter affordability credit errors as retryable\", () => {\n\t\t\tconst { deps } = createMockDeps();\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t\"402 This request requires more credits, or fewer max_tokens. You requested up to 32000 tokens, but can only afford 329.\",\n\t\t\t);\n\t\t\tassert.equal(handler.isRetryableError(msg), true);\n\t\t});\n\t});\n\n\tdescribe(\"third-party block claude-code fallback (#3772)\", () => {\n\t\tit(\"switches to claude-code provider when current provider is anthropic\", async () => {\n\t\t\tconst ccModel = createMockModel(\"claude-code\", \"claude-opus-4-6\");\n\t\t\tconst { deps, emittedEvents, onModelChangeFn } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"claude-code\" && modelId === \"claude-opus-4-6\") return ccModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t\tdeps.isClaudeCodeReady = () => true;\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"third-party apps cannot draw from extra usage\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"should retry via claude-code fallback\");\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"Expected fallback_provider_switch event\");\n\t\t\tassert.ok(switchEvent!.to.startsWith(\"claude-code/\"), \"Should switch to claude-code provider\");\n\t\t});\n\n\t\tit(\"switches to claude-code on 'out of extra usage' error (#3772)\", async () => {\n\t\t\tconst ccModel = createMockModel(\"claude-code\", \"claude-opus-4-6\");\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"claude-code\" && modelId === \"claude-opus-4-6\") return ccModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t\tdeps.isClaudeCodeReady = () => true;\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"You're out of extra usage. Add more at claude.ai/settings/usage and keep going.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"should retry via claude-code fallback\");\n\t\t\tconst switchEvent = emittedEvents.find((e) => e.type === \"fallback_provider_switch\");\n\t\t\tassert.ok(switchEvent, \"Expected fallback_provider_switch event\");\n\t\t\tassert.ok(switchEvent!.to.startsWith(\"claude-code/\"), \"Should switch to claude-code provider\");\n\t\t});\n\n\t\tit(\"does NOT switch to claude-code when current provider is not anthropic\", async () => {\n\t\t\tconst ccModel = createMockModel(\"claude-code\", \"gpt-4o\");\n\t\t\tconst { deps, emittedEvents } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"openai\", \"gpt-4o\"),\n\t\t\t\tfindModelResult: (provider: string, modelId: string) => {\n\t\t\t\t\tif (provider === \"claude-code\" && modelId === \"gpt-4o\") return ccModel;\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t\tdeps.isClaudeCodeReady = () => true;\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"third-party apps are not supported for this plan\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\t// Should NOT have triggered the claude-code fallback\n\t\t\tconst switchEvent = emittedEvents.find(\n\t\t\t\t(e) => e.type === \"fallback_provider_switch\" && e.to?.startsWith(\"claude-code/\"),\n\t\t\t);\n\t\t\tassert.equal(switchEvent, undefined, \"Should NOT switch non-anthropic provider to claude-code\");\n\t\t});\n\t});\n\n\tdescribe(\"quota_exhausted credential backoff (#3430)\", () => {\n\t\tit(\"does NOT call markUsageLimitReached for quota_exhausted errors\", async () => {\n\t\t\t// \"Extra usage is required\" is an account-level billing gate.\n\t\t\t// Backing off the credential for 30 minutes blocks all provider\n\t\t\t// requests and has no effect on the billing condition.\n\t\t\tconst { deps, markUsageLimitReached } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t\tfindModelResult: () => undefined,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\n\t\t\t\t'429 {\"type\":\"error\",\"error\":{\"type\":\"rate_limit_error\",\"message\":\"Extra usage is required for long context requests.\"}}',\n\t\t\t);\n\n\t\t\tawait handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(\n\t\t\t\tmarkUsageLimitReached.mock.calls.length,\n\t\t\t\t0,\n\t\t\t\t\"markUsageLimitReached must NOT be called for quota_exhausted errors\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"still calls markUsageLimitReached for regular rate_limit errors\", async () => {\n\t\t\tconst { deps, markUsageLimitReached } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: null,\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"429 Too Many Requests\");\n\n\t\t\tawait handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(\n\t\t\t\tmarkUsageLimitReached.mock.calls.length,\n\t\t\t\t1,\n\t\t\t\t\"markUsageLimitReached should be called for rate_limit errors\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"still tries cross-provider fallback for quota_exhausted without credential backoff\", async () => {\n\t\t\tconst fallbackModel = createMockModel(\"openai\", \"gpt-4o\");\n\t\t\tconst { deps, markUsageLimitReached, continueFn } = createMockDeps({\n\t\t\t\tmodel: createMockModel(\"anthropic\", \"claude-opus-4-6[1m]\"),\n\t\t\t\tmarkUsageLimitReachedResult: false,\n\t\t\t\tfallbackResult: { model: fallbackModel, reason: \"cross-provider fallback\" },\n\t\t\t});\n\n\t\t\tconst handler = new RetryHandler(deps);\n\t\t\tconst msg = errorMessage(\"Extra usage is required for long context requests.\");\n\n\t\t\tconst result = await handler.handleRetryableError(msg);\n\n\t\t\tassert.equal(result, true, \"should retry with fallback provider\");\n\t\t\tassert.equal(\n\t\t\t\tmarkUsageLimitReached.mock.calls.length,\n\t\t\t\t0,\n\t\t\t\t\"should NOT back off credentials before trying fallback\",\n\t\t\t);\n\t\t});\n\t});\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/model-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAkB,MAAM,YAAY,CAAC;AACxD,OAAO,EACN,SAAS,EACT,KAAK,SAAS,EAGd,KAAK,EAGL,KAAK,GAAG,EACR,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAUzE,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D;AAoBD,UAAU,eAAe;IACxB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAWD;;;;;;;GAOG;AACH,qBAAa,sBAAuB,SAAQ,SAAU,YAAW,SAAS;IACzE,OAAO,CAAC,WAAW,CAAQ;IAG3B,OAAO,CAAC,QAAQ,CAAS;IACzB,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IACD,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,YAAY,CAAmB;IAGvC,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,kBAAkB,CAAa;IAGvC,OAAO,CAAC,cAAc,CAAmB;IACzC,OAAO,CAAC,iBAAiB,CAAa;IAEtC,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,YAAY,CAAC,CAAa;IAClC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,SAAS,CAAC,CAAO;IACzB,OAAO,CAAC,aAAa,CAAC,CAAO;gBAG5B,GAAG,EAAE,GAAG,EACR,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,EACpC,eAAe,EAAE,eAAe,EAChC,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,aAAa,CAAC,eAAe,CAAC,EAC5C,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,EACrC,QAAQ,EAAE,MAAM,IAAI,EACpB,kBAAkB,CAAC,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"model-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/model-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAkB,MAAM,YAAY,CAAC;AACxD,OAAO,EACN,SAAS,EACT,KAAK,SAAS,EAGd,KAAK,EAGL,KAAK,GAAG,EACR,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAUzE,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D;AAoBD,UAAU,eAAe;IACxB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAWD;;;;;;;GAOG;AACH,qBAAa,sBAAuB,SAAQ,SAAU,YAAW,SAAS;IACzE,OAAO,CAAC,WAAW,CAAQ;IAG3B,OAAO,CAAC,QAAQ,CAAS;IACzB,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IACD,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,YAAY,CAAmB;IAGvC,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,kBAAkB,CAAa;IAGvC,OAAO,CAAC,cAAc,CAAmB;IACzC,OAAO,CAAC,iBAAiB,CAAa;IAEtC,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,YAAY,CAAC,CAAa;IAClC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,SAAS,CAAC,CAAO;IACzB,OAAO,CAAC,aAAa,CAAC,CAAO;gBAG5B,GAAG,EAAE,GAAG,EACR,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,EACpC,eAAe,EAAE,eAAe,EAChC,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,aAAa,CAAC,eAAe,CAAC,EAC5C,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,EACrC,QAAQ,EAAE,MAAM,IAAI,EACpB,kBAAkB,CAAC,EAAE,MAAM;YA6Ed,UAAU;IA+CxB;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAehC;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAoCxB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAmB1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,QAAQ;IAmBhB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,UAAU;IAkBlB,4DAA4D;IAC5D,OAAO,CAAC,cAAc;IAsDtB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAsEzB,OAAO,CAAC,eAAe;IAYvB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAiElC,0DAA0D;IAC1D,OAAO,CAAC,MAAM;IA2Bd,4DAA4D;IAC5D,OAAO,CAAC,QAAQ;IA2BhB,OAAO,CAAC,YAAY;IAMpB,cAAc,IAAI,KAAK;CAGvB"}
|
|
@@ -58,7 +58,10 @@ export class ModelSelectorComponent extends Container {
|
|
|
58
58
|
this.settingsManager = settingsManager;
|
|
59
59
|
this.modelRegistry = modelRegistry;
|
|
60
60
|
this.scopedModels = scopedModels;
|
|
61
|
-
|
|
61
|
+
// Only land in "scoped" view when at least one scoped model has working
|
|
62
|
+
// auth — otherwise the user would see an empty picker (#unconfigured-models).
|
|
63
|
+
const hasReadyScopedModel = scopedModels.some((scoped) => modelRegistry.isProviderRequestReady(scoped.model.provider));
|
|
64
|
+
this.scope = hasReadyScopedModel ? "scoped" : "all";
|
|
62
65
|
this.onSelectCallback = onSelect;
|
|
63
66
|
this.onCancelCallback = onCancel;
|
|
64
67
|
// Add top border
|
|
@@ -145,7 +148,11 @@ export class ModelSelectorComponent extends Container {
|
|
|
145
148
|
return;
|
|
146
149
|
}
|
|
147
150
|
this.allModels = this.sortModelsWithinProvider(models);
|
|
148
|
-
|
|
151
|
+
// Scoped models must also be filtered by provider readiness so users
|
|
152
|
+
// can't pick a scoped model whose provider has no API key / OAuth.
|
|
153
|
+
this.scopedModelItems = this.sortModelsWithinProvider(this.scopedModels
|
|
154
|
+
.filter((scoped) => this.modelRegistry.isProviderRequestReady(scoped.model.provider))
|
|
155
|
+
.map((scoped) => ({
|
|
149
156
|
provider: scoped.model.provider,
|
|
150
157
|
id: scoped.model.id,
|
|
151
158
|
model: scoped.model,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-selector.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/model-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Model, modelsAreEqual } from \"@gsd/pi-ai\";\nimport {\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tgetEditorKeybindings,\n\tInput,\n\tSpacer,\n\tText,\n\ttype TUI,\n} from \"@gsd/pi-tui\";\nimport type { ModelRegistry } from \"../../../core/model-registry.js\";\nimport type { SettingsManager } from \"../../../core/settings-manager.js\";\nimport { theme } from \"../theme/theme.js\";\nimport { DynamicBorder } from \"./dynamic-border.js\";\nimport { keyHint } from \"./keybinding-hints.js\";\n\n/** Display names for providers in the model selector UI. */\nconst PROVIDER_DISPLAY_NAMES: Record<string, string> = {\n\tanthropic: \"anthropic-api\",\n};\n\nexport function providerDisplayName(provider: string): string {\n\treturn PROVIDER_DISPLAY_NAMES[provider] ?? provider;\n}\n\nfunction formatTokenCount(count: number): string {\n\tif (count >= 1_000_000) {\n\t\tconst millions = count / 1_000_000;\n\t\treturn millions % 1 === 0 ? `${millions}M` : `${millions.toFixed(1)}M`;\n\t}\n\tif (count >= 1_000) {\n\t\tconst thousands = count / 1_000;\n\t\treturn thousands % 1 === 0 ? `${thousands}K` : `${thousands.toFixed(1)}K`;\n\t}\n\treturn count.toString();\n}\n\ninterface ModelItem {\n\tprovider: string;\n\tid: string;\n\tmodel: Model<any>;\n}\n\ninterface ScopedModelItem {\n\tmodel: Model<any>;\n\tthinkingLevel?: string;\n}\n\n/**\n * A navigable row — either a provider group header or a selectable model entry.\n */\ntype ListRow =\n\t| { kind: \"header\"; provider: string; count: number }\n\t| { kind: \"model\"; item: ModelItem };\n\ntype ModelScope = \"all\" | \"scoped\";\n\n/**\n * Component that renders a grouped model selector with search.\n *\n * Browsing (no search): models are grouped under provider headers.\n * - Current model's provider is shown first; remaining providers sorted alphabetically.\n * - Arrow keys navigate all rows; headers are skipped during selection.\n * Searching: reverts to a flat fuzzy-filtered list (same as before), with [provider] badges.\n */\nexport class ModelSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: Input;\n\n\t// Focusable implementation - propagate to searchInput for IME cursor positioning\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\tprivate listContainer: Container;\n\tprivate allModels: ModelItem[] = [];\n\tprivate scopedModelItems: ModelItem[] = [];\n\tprivate activeModels: ModelItem[] = [];\n\n\t// Grouped (browse) state\n\tprivate groupedRows: ListRow[] = [];\n\tprivate modelRowIndices: number[] = []; // indices into groupedRows that are \"model\" kind\n\tprivate selectedGroupIndex: number = 0; // index into groupedRows (can be model or header)\n\n\t// Search (flat) state\n\tprivate filteredModels: ModelItem[] = [];\n\tprivate selectedFlatIndex: number = 0;\n\n\tprivate isSearching: boolean = false;\n\tprivate currentModel?: Model<any>;\n\tprivate settingsManager: SettingsManager;\n\tprivate modelRegistry: ModelRegistry;\n\tprivate onSelectCallback: (model: Model<any>) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate errorMessage?: string;\n\tprivate tui: TUI;\n\tprivate scopedModels: ReadonlyArray<ScopedModelItem>;\n\tprivate scope: ModelScope = \"all\";\n\tprivate scopeText?: Text;\n\tprivate scopeHintText?: Text;\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tcurrentModel: Model<any> | undefined,\n\t\tsettingsManager: SettingsManager,\n\t\tmodelRegistry: ModelRegistry,\n\t\tscopedModels: ReadonlyArray<ScopedModelItem>,\n\t\tonSelect: (model: Model<any>) => void,\n\t\tonCancel: () => void,\n\t\tinitialSearchInput?: string,\n\t) {\n\t\tsuper();\n\n\t\tthis.tui = tui;\n\t\tthis.currentModel = currentModel;\n\t\tthis.settingsManager = settingsManager;\n\t\tthis.modelRegistry = modelRegistry;\n\t\tthis.scopedModels = scopedModels;\n\t\tthis.scope = scopedModels.length > 0 ? \"scoped\" : \"all\";\n\t\tthis.onSelectCallback = onSelect;\n\t\tthis.onCancelCallback = onCancel;\n\n\t\t// Add top border\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add hint about model filtering\n\t\tif (scopedModels.length > 0) {\n\t\t\tthis.scopeText = new Text(this.getScopeText(), 0, 0);\n\t\t\tthis.addChild(this.scopeText);\n\t\t\tthis.scopeHintText = new Text(this.getScopeHintText(), 0, 0);\n\t\t\tthis.addChild(this.scopeHintText);\n\t\t} else {\n\t\t\tconst hintText = \"Only showing models with configured API keys (see README for details)\";\n\t\t\tthis.addChild(new Text(theme.fg(\"warning\", hintText), 0, 0));\n\t\t}\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create search input\n\t\tthis.searchInput = new Input();\n\t\tif (initialSearchInput) {\n\t\t\tthis.searchInput.setValue(initialSearchInput);\n\t\t}\n\t\tthis.searchInput.onSubmit = () => {\n\t\t\tif (this.isSearching) {\n\t\t\t\tif (this.filteredModels[this.selectedFlatIndex]) {\n\t\t\t\t\tthis.handleSelect(this.filteredModels[this.selectedFlatIndex].model);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst model = this.getSelectedModel();\n\t\t\t\tif (model) this.handleSelect(model);\n\t\t\t}\n\t\t};\n\t\tthis.addChild(this.searchInput);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create list container\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add bottom border\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Load models and do initial render\n\t\tthis.loadModels().then(() => {\n\t\t\tif (initialSearchInput) {\n\t\t\t\tthis.isSearching = true;\n\t\t\t\tthis.filterModels(initialSearchInput);\n\t\t\t} else {\n\t\t\t\tthis.buildGroupedRows();\n\t\t\t\tthis.jumpToCurrentModel();\n\t\t\t\tthis.updateList();\n\t\t\t}\n\t\t\t// Request re-render after models are loaded\n\t\t\tthis.tui.requestRender();\n\t\t});\n\t}\n\n\tprivate async loadModels(): Promise<void> {\n\t\tlet models: ModelItem[];\n\n\t\t// Refresh to pick up any changes to models.json\n\t\tthis.modelRegistry.refresh();\n\n\t\t// Check for models.json errors\n\t\tconst loadError = this.modelRegistry.getError();\n\t\tif (loadError) {\n\t\t\tthis.errorMessage = loadError;\n\t\t}\n\n\t\t// Load available models (built-in models still work even if models.json failed)\n\t\ttry {\n\t\t\tconst availableModels = this.modelRegistry.getAvailable();\n\t\t\tmodels = availableModels.map((model: Model<any>) => ({\n\t\t\t\tprovider: model.provider,\n\t\t\t\tid: model.id,\n\t\t\t\tmodel,\n\t\t\t}));\n\t\t} catch (error) {\n\t\t\tthis.allModels = [];\n\t\t\tthis.scopedModelItems = [];\n\t\t\tthis.activeModels = [];\n\t\t\tthis.filteredModels = [];\n\t\t\tthis.groupedRows = [];\n\t\t\tthis.modelRowIndices = [];\n\t\t\tthis.errorMessage = error instanceof Error ? error.message : String(error);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.allModels = this.sortModelsWithinProvider(models);\n\t\tthis.scopedModelItems = this.sortModelsWithinProvider(\n\t\t\tthis.scopedModels.map((scoped) => ({\n\t\t\t\tprovider: scoped.model.provider,\n\t\t\t\tid: scoped.model.id,\n\t\t\t\tmodel: scoped.model,\n\t\t\t})),\n\t\t);\n\t\tthis.activeModels = this.scope === \"scoped\" ? this.scopedModelItems : this.allModels;\n\t\tthis.filteredModels = this.activeModels;\n\t}\n\n\t/**\n\t * Sort models within each provider: current model first, then by name desc.\n\t * Provider ordering is handled separately in buildGroupedRows().\n\t */\n\tprivate sortModelsWithinProvider(models: ModelItem[]): ModelItem[] {\n\t\tconst sorted = [...models];\n\t\tsorted.sort((a, b) => {\n\t\t\tconst aIsCurrent = modelsAreEqual(this.currentModel, a.model);\n\t\t\tconst bIsCurrent = modelsAreEqual(this.currentModel, b.model);\n\t\t\tif (aIsCurrent && !bIsCurrent) return -1;\n\t\t\tif (!aIsCurrent && bIsCurrent) return 1;\n\t\t\t// Within provider: newest/largest model name first\n\t\t\tconst nameCmp = b.model.name.localeCompare(a.model.name);\n\t\t\tif (nameCmp !== 0) return nameCmp;\n\t\t\treturn a.provider.localeCompare(b.provider);\n\t\t});\n\t\treturn sorted;\n\t}\n\n\t/**\n\t * Build the grouped rows array for browse mode.\n\t * Current model's provider comes first; remaining providers sorted alphabetically.\n\t */\n\tprivate buildGroupedRows(): void {\n\t\t// Group models by provider\n\t\tconst byProvider = new Map<string, ModelItem[]>();\n\t\tfor (const item of this.activeModels) {\n\t\t\tlet group = byProvider.get(item.provider);\n\t\t\tif (!group) {\n\t\t\t\tgroup = [];\n\t\t\t\tbyProvider.set(item.provider, group);\n\t\t\t}\n\t\t\tgroup.push(item);\n\t\t}\n\n\t\t// Determine provider order: current model's provider first, rest alphabetically\n\t\tconst currentProvider = this.currentModel?.provider;\n\t\tconst providers = Array.from(byProvider.keys()).sort((a, b) => {\n\t\t\tif (a === currentProvider) return -1;\n\t\t\tif (b === currentProvider) return 1;\n\t\t\treturn a.localeCompare(b);\n\t\t});\n\n\t\tconst rows: ListRow[] = [];\n\t\tconst modelIndices: number[] = [];\n\n\t\tfor (const provider of providers) {\n\t\t\tconst items = byProvider.get(provider)!;\n\t\t\trows.push({ kind: \"header\", provider, count: items.length });\n\t\t\tfor (const item of items) {\n\t\t\t\tmodelIndices.push(rows.length);\n\t\t\t\trows.push({ kind: \"model\", item });\n\t\t\t}\n\t\t}\n\n\t\tthis.groupedRows = rows;\n\t\tthis.modelRowIndices = modelIndices;\n\t}\n\n\t/**\n\t * Move selectedGroupIndex to point at the current model (or first model).\n\t */\n\tprivate jumpToCurrentModel(): void {\n\t\tif (this.groupedRows.length === 0) {\n\t\t\tthis.selectedGroupIndex = 0;\n\t\t\treturn;\n\t\t}\n\t\t// Find the current model in grouped rows\n\t\tfor (let i = 0; i < this.groupedRows.length; i++) {\n\t\t\tconst row = this.groupedRows[i];\n\t\t\tif (row.kind === \"model\" && modelsAreEqual(this.currentModel, row.item.model)) {\n\t\t\t\tthis.selectedGroupIndex = i;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t// Fall back to first model row\n\t\tif (this.modelRowIndices.length > 0) {\n\t\t\tthis.selectedGroupIndex = this.modelRowIndices[0];\n\t\t}\n\t}\n\n\t/**\n\t * Get the currently selected model from grouped or flat state.\n\t */\n\tprivate getSelectedModel(): Model<any> | undefined {\n\t\tif (this.isSearching) {\n\t\t\treturn this.filteredModels[this.selectedFlatIndex]?.model;\n\t\t}\n\t\tconst row = this.groupedRows[this.selectedGroupIndex];\n\t\treturn row?.kind === \"model\" ? row.item.model : undefined;\n\t}\n\n\tprivate getScopeText(): string {\n\t\tconst allText = this.scope === \"all\" ? theme.fg(\"accent\", \"all\") : theme.fg(\"muted\", \"all\");\n\t\tconst scopedText = this.scope === \"scoped\" ? theme.fg(\"accent\", \"scoped\") : theme.fg(\"muted\", \"scoped\");\n\t\treturn `${theme.fg(\"muted\", \"Scope: \")}${allText}${theme.fg(\"muted\", \" | \")}${scopedText}`;\n\t}\n\n\tprivate getScopeHintText(): string {\n\t\treturn keyHint(\"tab\", \"scope\") + theme.fg(\"muted\", \" (all/scoped)\");\n\t}\n\n\tprivate setScope(scope: ModelScope): void {\n\t\tif (this.scope === scope) return;\n\t\tthis.scope = scope;\n\t\tthis.activeModels = this.scope === \"scoped\" ? this.scopedModelItems : this.allModels;\n\n\t\tif (this.isSearching) {\n\t\t\tthis.selectedFlatIndex = 0;\n\t\t\tthis.filterModels(this.searchInput.getValue());\n\t\t} else {\n\t\t\tthis.buildGroupedRows();\n\t\t\tthis.jumpToCurrentModel();\n\t\t\tthis.updateList();\n\t\t}\n\n\t\tif (this.scopeText) {\n\t\t\tthis.scopeText.setText(this.getScopeText());\n\t\t}\n\t}\n\n\tprivate filterModels(query: string): void {\n\t\tthis.filteredModels = query\n\t\t\t? fuzzyFilter(this.activeModels, query, ({ id, provider }) => `${id} ${provider}`)\n\t\t\t: this.activeModels;\n\t\tthis.selectedFlatIndex = Math.min(this.selectedFlatIndex, Math.max(0, this.filteredModels.length - 1));\n\t\tthis.updateList();\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\n\t\tif (this.errorMessage) {\n\t\t\tconst errorLines = this.errorMessage.split(\"\\n\");\n\t\t\tfor (const line of errorLines) {\n\t\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"error\", line), 0, 0));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.isSearching) {\n\t\t\tthis.renderFlatList();\n\t\t} else {\n\t\t\tthis.renderGroupedList();\n\t\t}\n\t}\n\n\t/** Flat fuzzy-search results, same as original behaviour */\n\tprivate renderFlatList(): void {\n\t\tconst maxVisible = 10;\n\n\t\tif (this.filteredModels.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No matching models\"), 0, 0));\n\t\t\treturn;\n\t\t}\n\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(\n\t\t\t\tthis.selectedFlatIndex - Math.floor(maxVisible / 2),\n\t\t\t\tthis.filteredModels.length - maxVisible,\n\t\t\t),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.filteredModels.length);\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst item = this.filteredModels[i];\n\t\t\tif (!item) continue;\n\n\t\t\tconst isSelected = i === this.selectedFlatIndex;\n\t\t\tconst isCurrent = modelsAreEqual(this.currentModel, item.model);\n\n\t\t\tconst ctx = formatTokenCount(item.model.contextWindow);\n\t\t\tconst ctxBadge = theme.fg(\"muted\", `${ctx}`);\n\t\t\tconst providerBadge = theme.fg(\"muted\", `[${providerDisplayName(item.provider)}]`);\n\t\t\tconst checkmark = isCurrent ? theme.fg(\"success\", \" ✓\") : \"\";\n\n\t\t\tlet line: string;\n\t\t\tif (isSelected) {\n\t\t\t\tconst prefix = theme.fg(\"accent\", \"→ \");\n\t\t\t\tline = `${prefix}${theme.fg(\"accent\", item.id)} ${ctxBadge} ${providerBadge}${checkmark}`;\n\t\t\t} else {\n\t\t\t\tline = ` ${item.id} ${ctxBadge} ${providerBadge}${checkmark}`;\n\t\t\t}\n\n\t\t\tthis.listContainer.addChild(new Text(line, 0, 0));\n\t\t}\n\n\t\tif (startIndex > 0 || endIndex < this.filteredModels.length) {\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew Text(theme.fg(\"muted\", ` (${this.selectedFlatIndex + 1}/${this.filteredModels.length})`), 0, 0),\n\t\t\t);\n\t\t}\n\n\t\t// Detail line for selected model\n\t\tconst selected = this.filteredModels[this.selectedFlatIndex];\n\t\tif (selected) {\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", ` ${this.modelDetailLine(selected.model)}`), 0, 0));\n\t\t}\n\t}\n\n\t/**\n\t * Grouped browse view: provider headers + model rows, windowed around selection.\n\t * Shows enough rows to fill ~10 visible lines; headers count as one line each.\n\t */\n\tprivate renderGroupedList(): void {\n\t\tconst maxVisible = 12;\n\n\t\tif (this.groupedRows.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No models available\"), 0, 0));\n\t\t\treturn;\n\t\t}\n\n\t\t// Window around selectedGroupIndex\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(\n\t\t\t\tthis.selectedGroupIndex - Math.floor(maxVisible / 2),\n\t\t\t\tthis.groupedRows.length - maxVisible,\n\t\t\t),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.groupedRows.length);\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst row = this.groupedRows[i];\n\t\t\tif (!row) continue;\n\n\t\t\tif (row.kind === \"header\") {\n\t\t\t\t// Provider group header — always unselectable\n\t\t\t\tconst providerLabel = theme.fg(\"borderAccent\", providerDisplayName(row.provider));\n\t\t\t\tconst count = theme.fg(\"muted\", ` (${row.count})`);\n\t\t\t\t// Add blank line before header if not the very first visible row\n\t\t\t\tif (i > startIndex) {\n\t\t\t\t\tthis.listContainer.addChild(new Text(\"\", 0, 0));\n\t\t\t\t}\n\t\t\t\tthis.listContainer.addChild(new Text(` ${providerLabel}${count}`, 0, 0));\n\t\t\t} else {\n\t\t\t\t// Model row\n\t\t\t\tconst isSelected = i === this.selectedGroupIndex;\n\t\t\t\tconst isCurrent = modelsAreEqual(this.currentModel, row.item.model);\n\n\t\t\t\tconst ctx = formatTokenCount(row.item.model.contextWindow);\n\t\t\t\tconst ctxBadge = theme.fg(\"muted\", ` ${ctx}`);\n\t\t\t\tconst checkmark = isCurrent ? theme.fg(\"success\", \" ✓\") : \"\";\n\n\t\t\t\tlet line: string;\n\t\t\t\tif (isSelected) {\n\t\t\t\t\tline = ` ${theme.fg(\"accent\", \"→\")} ${theme.fg(\"accent\", row.item.id)}${ctxBadge}${checkmark}`;\n\t\t\t\t} else {\n\t\t\t\t\tline = ` ${row.item.id}${ctxBadge}${checkmark}`;\n\t\t\t\t}\n\n\t\t\t\tthis.listContainer.addChild(new Text(line, 0, 0));\n\t\t\t}\n\t\t}\n\n\t\t// Scroll indicator\n\t\tif (startIndex > 0 || endIndex < this.groupedRows.length) {\n\t\t\tconst modelPos = this.modelRowIndices.indexOf(this.selectedGroupIndex) + 1;\n\t\t\tconst totalModels = this.modelRowIndices.length;\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew Text(theme.fg(\"muted\", ` (${modelPos}/${totalModels})`), 0, 0),\n\t\t\t);\n\t\t}\n\n\t\t// Detail line for selected model\n\t\tconst selectedModel = this.getSelectedModel();\n\t\tif (selectedModel) {\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew Text(theme.fg(\"muted\", ` ${this.modelDetailLine(selectedModel)}`), 0, 0),\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate modelDetailLine(m: Model<any>): string {\n\t\treturn [\n\t\t\tm.name,\n\t\t\t`ctx: ${formatTokenCount(m.contextWindow)}`,\n\t\t\t`out: ${formatTokenCount(m.maxTokens)}`,\n\t\t\tm.reasoning ? \"thinking\" : \"\",\n\t\t\tm.input.includes(\"image\") ? \"vision\" : \"\",\n\t\t]\n\t\t\t.filter(Boolean)\n\t\t\t.join(\" · \");\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getEditorKeybindings();\n\n\t\t// Tab: scope toggle\n\t\tif (kb.matches(keyData, \"tab\")) {\n\t\t\tif (this.scopedModelItems.length > 0) {\n\t\t\t\tconst nextScope: ModelScope = this.scope === \"all\" ? \"scoped\" : \"all\";\n\t\t\t\tthis.setScope(nextScope);\n\t\t\t\tif (this.scopeHintText) {\n\t\t\t\t\tthis.scopeHintText.setText(this.getScopeHintText());\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Navigation keys\n\t\tif (kb.matches(keyData, \"selectUp\")) {\n\t\t\tthis.moveUp();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(keyData, \"selectDown\")) {\n\t\t\tthis.moveDown();\n\t\t\treturn;\n\t\t}\n\n\t\t// Confirm\n\t\tif (kb.matches(keyData, \"selectConfirm\")) {\n\t\t\tconst model = this.getSelectedModel();\n\t\t\tif (model) this.handleSelect(model);\n\t\t\treturn;\n\t\t}\n\n\t\t// Cancel\n\t\tif (kb.matches(keyData, \"selectCancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t\treturn;\n\t\t}\n\n\t\t// Everything else: feed to search input\n\t\tconst prevQuery = this.searchInput.getValue();\n\t\tthis.searchInput.handleInput(keyData);\n\t\tconst newQuery = this.searchInput.getValue();\n\n\t\tif (newQuery !== prevQuery) {\n\t\t\tconst entering = !prevQuery && !!newQuery;\n\t\t\tconst leaving = !!prevQuery && !newQuery;\n\n\t\t\tif (entering) {\n\t\t\t\t// Entering search mode: remember current model position\n\t\t\t\tthis.isSearching = true;\n\t\t\t\tthis.selectedFlatIndex = 0;\n\t\t\t} else if (leaving) {\n\t\t\t\t// Leaving search mode: return to grouped view, restore position\n\t\t\t\tthis.isSearching = false;\n\t\t\t\tthis.buildGroupedRows();\n\t\t\t\tthis.jumpToCurrentModel();\n\t\t\t}\n\t\t\tif (this.isSearching) {\n\t\t\t\tthis.filterModels(newQuery);\n\t\t\t} else {\n\t\t\t\tthis.updateList();\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Move selection up, skipping headers in grouped mode */\n\tprivate moveUp(): void {\n\t\tif (this.isSearching) {\n\t\t\tif (this.filteredModels.length === 0) return;\n\t\t\tthis.selectedFlatIndex =\n\t\t\t\tthis.selectedFlatIndex === 0\n\t\t\t\t\t? this.filteredModels.length - 1\n\t\t\t\t\t: this.selectedFlatIndex - 1;\n\t\t\tthis.updateList();\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.groupedRows.length === 0) return;\n\t\tlet next = this.selectedGroupIndex - 1;\n\t\t// Wrap\n\t\tif (next < 0) next = this.groupedRows.length - 1;\n\t\t// Skip headers\n\t\twhile (next > 0 && this.groupedRows[next]?.kind === \"header\") {\n\t\t\tnext--;\n\t\t}\n\t\t// If landed on header at 0, wrap to bottom\n\t\tif (this.groupedRows[next]?.kind === \"header\") {\n\t\t\tnext = this.groupedRows.length - 1;\n\t\t}\n\t\tthis.selectedGroupIndex = next;\n\t\tthis.updateList();\n\t}\n\n\t/** Move selection down, skipping headers in grouped mode */\n\tprivate moveDown(): void {\n\t\tif (this.isSearching) {\n\t\t\tif (this.filteredModels.length === 0) return;\n\t\t\tthis.selectedFlatIndex =\n\t\t\t\tthis.selectedFlatIndex === this.filteredModels.length - 1\n\t\t\t\t\t? 0\n\t\t\t\t\t: this.selectedFlatIndex + 1;\n\t\t\tthis.updateList();\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.groupedRows.length === 0) return;\n\t\tlet next = this.selectedGroupIndex + 1;\n\t\t// Wrap\n\t\tif (next >= this.groupedRows.length) next = 0;\n\t\t// Skip headers\n\t\twhile (next < this.groupedRows.length - 1 && this.groupedRows[next]?.kind === \"header\") {\n\t\t\tnext++;\n\t\t}\n\t\t// If landed on header at end, wrap to first model\n\t\tif (this.groupedRows[next]?.kind === \"header\") {\n\t\t\tnext = this.modelRowIndices[0] ?? 0;\n\t\t}\n\t\tthis.selectedGroupIndex = next;\n\t\tthis.updateList();\n\t}\n\n\tprivate handleSelect(model: Model<any>): void {\n\t\t// Save as new default\n\t\tthis.settingsManager.setDefaultModelAndProvider(model.provider, model.id);\n\t\tthis.onSelectCallback(model);\n\t}\n\n\tgetSearchInput(): Input {\n\t\treturn this.searchInput;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"model-selector.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/model-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,cAAc,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EACN,SAAS,EAET,WAAW,EACX,oBAAoB,EACpB,KAAK,EACL,MAAM,EACN,IAAI,GAEJ,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,4DAA4D;AAC5D,MAAM,sBAAsB,GAA2B;IACtD,SAAS,EAAE,eAAe;CAC1B,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IACnD,OAAO,sBAAsB,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC;AACrD,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAa;IACtC,IAAI,KAAK,IAAI,SAAS,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;QACnC,OAAO,QAAQ,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACxE,CAAC;IACD,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;QACpB,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK,CAAC;QAChC,OAAO,SAAS,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAC3E,CAAC;IACD,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;AACzB,CAAC;AAsBD;;;;;;;GAOG;AACH,MAAM,OAAO,sBAAuB,SAAQ,SAAS;IAKpD,IAAI,OAAO;QACV,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IACD,IAAI,OAAO,CAAC,KAAc;QACzB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,WAAW,CAAC,OAAO,GAAG,KAAK,CAAC;IAClC,CAAC;IA4BD,YACC,GAAQ,EACR,YAAoC,EACpC,eAAgC,EAChC,aAA4B,EAC5B,YAA4C,EAC5C,QAAqC,EACrC,QAAoB,EACpB,kBAA2B;QAE3B,KAAK,EAAE,CAAC;QA9CT,iFAAiF;QACzE,aAAQ,GAAG,KAAK,CAAC;QASjB,cAAS,GAAgB,EAAE,CAAC;QAC5B,qBAAgB,GAAgB,EAAE,CAAC;QACnC,iBAAY,GAAgB,EAAE,CAAC;QAEvC,yBAAyB;QACjB,gBAAW,GAAc,EAAE,CAAC;QAC5B,oBAAe,GAAa,EAAE,CAAC,CAAC,iDAAiD;QACjF,uBAAkB,GAAW,CAAC,CAAC,CAAC,kDAAkD;QAE1F,sBAAsB;QACd,mBAAc,GAAgB,EAAE,CAAC;QACjC,sBAAiB,GAAW,CAAC,CAAC;QAE9B,gBAAW,GAAY,KAAK,CAAC;QAS7B,UAAK,GAAe,KAAK,CAAC;QAgBjC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QACvC,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,wEAAwE;QACxE,8EAA8E;QAC9E,MAAM,mBAAmB,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CACxD,aAAa,CAAC,sBAAsB,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAC3D,CAAC;QACF,IAAI,CAAC,KAAK,GAAG,mBAAmB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;QACpD,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC;QACjC,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC;QAEjC,iBAAiB;QACjB,IAAI,CAAC,QAAQ,CAAC,IAAI,aAAa,EAAE,CAAC,CAAC;QACnC,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7B,iCAAiC;QACjC,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACrD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC9B,IAAI,CAAC,aAAa,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC7D,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACP,MAAM,QAAQ,GAAG,uEAAuE,CAAC;YACzF,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7B,sBAAsB;QACtB,IAAI,CAAC,WAAW,GAAG,IAAI,KAAK,EAAE,CAAC;QAC/B,IAAI,kBAAkB,EAAE,CAAC;YACxB,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG,GAAG,EAAE;YAChC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACtB,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC;oBACjD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,KAAK,CAAC,CAAC;gBACtE,CAAC;YACF,CAAC;iBAAM,CAAC;gBACP,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtC,IAAI,KAAK;oBAAE,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YACrC,CAAC;QACF,CAAC,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAEhC,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7B,wBAAwB;QACxB,IAAI,CAAC,aAAa,GAAG,IAAI,SAAS,EAAE,CAAC;QACrC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAElC,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7B,oBAAoB;QACpB,IAAI,CAAC,QAAQ,CAAC,IAAI,aAAa,EAAE,CAAC,CAAC;QAEnC,oCAAoC;QACpC,IAAI,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;YAC3B,IAAI,kBAAkB,EAAE,CAAC;gBACxB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;gBACxB,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC;YACvC,CAAC;iBAAM,CAAC;gBACP,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACxB,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBAC1B,IAAI,CAAC,UAAU,EAAE,CAAC;YACnB,CAAC;YACD,4CAA4C;YAC5C,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC1B,CAAC,CAAC,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,UAAU;QACvB,IAAI,MAAmB,CAAC;QAExB,gDAAgD;QAChD,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;QAE7B,+BAA+B;QAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;QAChD,IAAI,SAAS,EAAE,CAAC;YACf,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;QAC/B,CAAC;QAED,gFAAgF;QAChF,IAAI,CAAC;YACJ,MAAM,eAAe,GAAG,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;YAC1D,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,KAAiB,EAAE,EAAE,CAAC,CAAC;gBACpD,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,KAAK;aACL,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;YACpB,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;YAC3B,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;YACvB,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;YACzB,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;YAC1B,IAAI,CAAC,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3E,OAAO;QACR,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAC;QACvD,qEAAqE;QACrE,mEAAmE;QACnE,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,wBAAwB,CACpD,IAAI,CAAC,YAAY;aACf,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,sBAAsB,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;aACpF,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YACjB,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ;YAC/B,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE;YACnB,KAAK,EAAE,MAAM,CAAC,KAAK;SACnB,CAAC,CAAC,CACJ,CAAC;QACF,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;QACrF,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,YAAY,CAAC;IACzC,CAAC;IAED;;;OAGG;IACK,wBAAwB,CAAC,MAAmB;QACnD,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACpB,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YAC9D,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YAC9D,IAAI,UAAU,IAAI,CAAC,UAAU;gBAAE,OAAO,CAAC,CAAC,CAAC;YACzC,IAAI,CAAC,UAAU,IAAI,UAAU;gBAAE,OAAO,CAAC,CAAC;YACxC,mDAAmD;YACnD,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACzD,IAAI,OAAO,KAAK,CAAC;gBAAE,OAAO,OAAO,CAAC;YAClC,OAAO,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;;OAGG;IACK,gBAAgB;QACvB,2BAA2B;QAC3B,MAAM,UAAU,GAAG,IAAI,GAAG,EAAuB,CAAC;QAClD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtC,IAAI,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;gBACZ,KAAK,GAAG,EAAE,CAAC;gBACX,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACtC,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;QAED,gFAAgF;QAChF,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC;QACpD,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC7D,IAAI,CAAC,KAAK,eAAe;gBAAE,OAAO,CAAC,CAAC,CAAC;YACrC,IAAI,CAAC,KAAK,eAAe;gBAAE,OAAO,CAAC,CAAC;YACpC,OAAO,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,GAAc,EAAE,CAAC;QAC3B,MAAM,YAAY,GAAa,EAAE,CAAC;QAElC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;YAC7D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBAC1B,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC/B,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACpC,CAAC;QACF,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,eAAe,GAAG,YAAY,CAAC;IACrC,CAAC;IAED;;OAEG;IACK,kBAAkB;QACzB,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAC;YAC5B,OAAO;QACR,CAAC;QACD,yCAAyC;QACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAClD,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YAChC,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/E,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAC;gBAC5B,OAAO;YACR,CAAC;QACF,CAAC;QACD,+BAA+B;QAC/B,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACnD,CAAC;IACF,CAAC;IAED;;OAEG;IACK,gBAAgB;QACvB,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC;QAC3D,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACtD,OAAO,GAAG,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3D,CAAC;IAEO,YAAY;QACnB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC5F,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACxG,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,GAAG,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,UAAU,EAAE,CAAC;IAC5F,CAAC;IAEO,gBAAgB;QACvB,OAAO,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACrE,CAAC;IAEO,QAAQ,CAAC,KAAiB;QACjC,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK;YAAE,OAAO;QACjC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;QAErF,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;YAC3B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1B,IAAI,CAAC,UAAU,EAAE,CAAC;QACnB,CAAC;QAED,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QAC7C,CAAC;IACF,CAAC;IAEO,YAAY,CAAC,KAAa;QACjC,IAAI,CAAC,cAAc,GAAG,KAAK;YAC1B,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;YAClF,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC;QACrB,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACvG,IAAI,CAAC,UAAU,EAAE,CAAC;IACnB,CAAC;IAEO,UAAU;QACjB,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAE3B,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjD,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;gBAC/B,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACtE,CAAC;YACD,OAAO;QACR,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,CAAC,cAAc,EAAE,CAAC;QACvB,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC1B,CAAC;IACF,CAAC;IAED,4DAA4D;IACpD,cAAc;QACrB,MAAM,UAAU,GAAG,EAAE,CAAC;QAEtB,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,sBAAsB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACvF,OAAO;QACR,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAC1B,CAAC,EACD,IAAI,CAAC,GAAG,CACP,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,EACnD,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,UAAU,CACvC,CACD,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,UAAU,EAAE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAE/E,KAAK,IAAI,CAAC,GAAG,UAAU,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;YACpC,IAAI,CAAC,IAAI;gBAAE,SAAS;YAEpB,MAAM,UAAU,GAAG,CAAC,KAAK,IAAI,CAAC,iBAAiB,CAAC;YAChD,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YAEhE,MAAM,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YACvD,MAAM,QAAQ,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;YAC7C,MAAM,aAAa,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YACnF,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAE7D,IAAI,IAAY,CAAC;YACjB,IAAI,UAAU,EAAE,CAAC;gBAChB,MAAM,MAAM,GAAG,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBACxC,IAAI,GAAG,GAAG,MAAM,GAAG,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,QAAQ,IAAI,aAAa,GAAG,SAAS,EAAE,CAAC;YAC3F,CAAC;iBAAM,CAAC;gBACP,IAAI,GAAG,KAAK,IAAI,CAAC,EAAE,IAAI,QAAQ,IAAI,aAAa,GAAG,SAAS,EAAE,CAAC;YAChE,CAAC;YAED,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACnD,CAAC;QAED,IAAI,UAAU,GAAG,CAAC,IAAI,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC;YAC7D,IAAI,CAAC,aAAa,CAAC,QAAQ,CAC1B,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,iBAAiB,GAAG,CAAC,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CACpG,CAAC;QACH,CAAC;QAED,iCAAiC;QACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC7D,IAAI,QAAQ,EAAE,CAAC;YACd,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3C,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7G,CAAC;IACF,CAAC;IAED;;;OAGG;IACK,iBAAiB;QACxB,MAAM,UAAU,GAAG,EAAE,CAAC;QAEtB,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACxF,OAAO;QACR,CAAC;QAED,mCAAmC;QACnC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAC1B,CAAC,EACD,IAAI,CAAC,GAAG,CACP,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,EACpD,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,UAAU,CACpC,CACD,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAE5E,KAAK,IAAI,CAAC,GAAG,UAAU,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YAChC,IAAI,CAAC,GAAG;gBAAE,SAAS;YAEnB,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC3B,8CAA8C;gBAC9C,MAAM,aAAa,GAAG,KAAK,CAAC,EAAE,CAAC,cAAc,EAAE,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAClF,MAAM,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;gBACnD,iEAAiE;gBACjE,IAAI,CAAC,GAAG,UAAU,EAAE,CAAC;oBACpB,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACjD,CAAC;gBACD,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,aAAa,GAAG,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC3E,CAAC;iBAAM,CAAC;gBACP,YAAY;gBACZ,MAAM,UAAU,GAAG,CAAC,KAAK,IAAI,CAAC,kBAAkB,CAAC;gBACjD,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAEpE,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;gBAC3D,MAAM,QAAQ,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;gBAC9C,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAE7D,IAAI,IAAY,CAAC;gBACjB,IAAI,UAAU,EAAE,CAAC;oBAChB,IAAI,GAAG,KAAK,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,QAAQ,GAAG,SAAS,EAAE,CAAC;gBACjG,CAAC;qBAAM,CAAC;oBACP,IAAI,GAAG,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,QAAQ,GAAG,SAAS,EAAE,CAAC;gBACpD,CAAC;gBAED,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACnD,CAAC;QACF,CAAC;QAED,mBAAmB;QACnB,IAAI,UAAU,GAAG,CAAC,IAAI,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;YAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC;YAC3E,MAAM,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC;YAChD,IAAI,CAAC,aAAa,CAAC,QAAQ,CAC1B,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,QAAQ,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CACnE,CAAC;QACH,CAAC;QAED,iCAAiC;QACjC,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC9C,IAAI,aAAa,EAAE,CAAC;YACnB,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3C,IAAI,CAAC,aAAa,CAAC,QAAQ,CAC1B,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAC7E,CAAC;QACH,CAAC;IACF,CAAC;IAEO,eAAe,CAAC,CAAa;QACpC,OAAO;YACN,CAAC,CAAC,IAAI;YACN,QAAQ,gBAAgB,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE;YAC3C,QAAQ,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE;YACvC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;YAC7B,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;SACzC;aACC,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,KAAK,CAAC,CAAC;IACf,CAAC;IAED,WAAW,CAAC,OAAe;QAC1B,MAAM,EAAE,GAAG,oBAAoB,EAAE,CAAC;QAElC,oBAAoB;QACpB,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC;YAChC,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtC,MAAM,SAAS,GAAe,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;gBACtE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;gBACzB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;oBACxB,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;gBACrD,CAAC;YACF,CAAC;YACD,OAAO;QACR,CAAC;QAED,kBAAkB;QAClB,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC;YACrC,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,OAAO;QACR,CAAC;QACD,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,OAAO;QACR,CAAC;QAED,UAAU;QACV,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,EAAE,CAAC;YAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtC,IAAI,KAAK;gBAAE,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YACpC,OAAO;QACR,CAAC;QAED,SAAS;QACT,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,OAAO;QACR,CAAC;QAED,wCAAwC;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;QAC9C,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;QAE7C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,CAAC,SAAS,IAAI,CAAC,CAAC,QAAQ,CAAC;YAC1C,MAAM,OAAO,GAAG,CAAC,CAAC,SAAS,IAAI,CAAC,QAAQ,CAAC;YAEzC,IAAI,QAAQ,EAAE,CAAC;gBACd,wDAAwD;gBACxD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;gBACxB,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;YAC5B,CAAC;iBAAM,IAAI,OAAO,EAAE,CAAC;gBACpB,gEAAgE;gBAChE,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;gBACzB,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACxB,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC3B,CAAC;YACD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACtB,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACP,IAAI,CAAC,UAAU,EAAE,CAAC;YACnB,CAAC;QACF,CAAC;IACF,CAAC;IAED,0DAA0D;IAClD,MAAM;QACb,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YAC7C,IAAI,CAAC,iBAAiB;gBACrB,IAAI,CAAC,iBAAiB,KAAK,CAAC;oBAC3B,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC;oBAChC,CAAC,CAAC,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC,UAAU,EAAE,CAAC;YAClB,OAAO;QACR,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC1C,IAAI,IAAI,GAAG,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAC;QACvC,OAAO;QACP,IAAI,IAAI,GAAG,CAAC;YAAE,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;QACjD,eAAe;QACf,OAAO,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC9D,IAAI,EAAE,CAAC;QACR,CAAC;QACD,2CAA2C;QAC3C,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC/C,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,UAAU,EAAE,CAAC;IACnB,CAAC;IAED,4DAA4D;IACpD,QAAQ;QACf,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YAC7C,IAAI,CAAC,iBAAiB;gBACrB,IAAI,CAAC,iBAAiB,KAAK,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC;oBACxD,CAAC,CAAC,CAAC;oBACH,CAAC,CAAC,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC,UAAU,EAAE,CAAC;YAClB,OAAO;QACR,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC1C,IAAI,IAAI,GAAG,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAC;QACvC,OAAO;QACP,IAAI,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM;YAAE,IAAI,GAAG,CAAC,CAAC;QAC9C,eAAe;QACf,OAAO,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;YACxF,IAAI,EAAE,CAAC;QACR,CAAC;QACD,kDAAkD;QAClD,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC/C,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;QACD,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,UAAU,EAAE,CAAC;IACnB,CAAC;IAEO,YAAY,CAAC,KAAiB;QACrC,sBAAsB;QACtB,IAAI,CAAC,eAAe,CAAC,0BAA0B,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1E,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,cAAc;QACb,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC;CACD","sourcesContent":["import { type Model, modelsAreEqual } from \"@gsd/pi-ai\";\nimport {\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tgetEditorKeybindings,\n\tInput,\n\tSpacer,\n\tText,\n\ttype TUI,\n} from \"@gsd/pi-tui\";\nimport type { ModelRegistry } from \"../../../core/model-registry.js\";\nimport type { SettingsManager } from \"../../../core/settings-manager.js\";\nimport { theme } from \"../theme/theme.js\";\nimport { DynamicBorder } from \"./dynamic-border.js\";\nimport { keyHint } from \"./keybinding-hints.js\";\n\n/** Display names for providers in the model selector UI. */\nconst PROVIDER_DISPLAY_NAMES: Record<string, string> = {\n\tanthropic: \"anthropic-api\",\n};\n\nexport function providerDisplayName(provider: string): string {\n\treturn PROVIDER_DISPLAY_NAMES[provider] ?? provider;\n}\n\nfunction formatTokenCount(count: number): string {\n\tif (count >= 1_000_000) {\n\t\tconst millions = count / 1_000_000;\n\t\treturn millions % 1 === 0 ? `${millions}M` : `${millions.toFixed(1)}M`;\n\t}\n\tif (count >= 1_000) {\n\t\tconst thousands = count / 1_000;\n\t\treturn thousands % 1 === 0 ? `${thousands}K` : `${thousands.toFixed(1)}K`;\n\t}\n\treturn count.toString();\n}\n\ninterface ModelItem {\n\tprovider: string;\n\tid: string;\n\tmodel: Model<any>;\n}\n\ninterface ScopedModelItem {\n\tmodel: Model<any>;\n\tthinkingLevel?: string;\n}\n\n/**\n * A navigable row — either a provider group header or a selectable model entry.\n */\ntype ListRow =\n\t| { kind: \"header\"; provider: string; count: number }\n\t| { kind: \"model\"; item: ModelItem };\n\ntype ModelScope = \"all\" | \"scoped\";\n\n/**\n * Component that renders a grouped model selector with search.\n *\n * Browsing (no search): models are grouped under provider headers.\n * - Current model's provider is shown first; remaining providers sorted alphabetically.\n * - Arrow keys navigate all rows; headers are skipped during selection.\n * Searching: reverts to a flat fuzzy-filtered list (same as before), with [provider] badges.\n */\nexport class ModelSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: Input;\n\n\t// Focusable implementation - propagate to searchInput for IME cursor positioning\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\tprivate listContainer: Container;\n\tprivate allModels: ModelItem[] = [];\n\tprivate scopedModelItems: ModelItem[] = [];\n\tprivate activeModels: ModelItem[] = [];\n\n\t// Grouped (browse) state\n\tprivate groupedRows: ListRow[] = [];\n\tprivate modelRowIndices: number[] = []; // indices into groupedRows that are \"model\" kind\n\tprivate selectedGroupIndex: number = 0; // index into groupedRows (can be model or header)\n\n\t// Search (flat) state\n\tprivate filteredModels: ModelItem[] = [];\n\tprivate selectedFlatIndex: number = 0;\n\n\tprivate isSearching: boolean = false;\n\tprivate currentModel?: Model<any>;\n\tprivate settingsManager: SettingsManager;\n\tprivate modelRegistry: ModelRegistry;\n\tprivate onSelectCallback: (model: Model<any>) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate errorMessage?: string;\n\tprivate tui: TUI;\n\tprivate scopedModels: ReadonlyArray<ScopedModelItem>;\n\tprivate scope: ModelScope = \"all\";\n\tprivate scopeText?: Text;\n\tprivate scopeHintText?: Text;\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tcurrentModel: Model<any> | undefined,\n\t\tsettingsManager: SettingsManager,\n\t\tmodelRegistry: ModelRegistry,\n\t\tscopedModels: ReadonlyArray<ScopedModelItem>,\n\t\tonSelect: (model: Model<any>) => void,\n\t\tonCancel: () => void,\n\t\tinitialSearchInput?: string,\n\t) {\n\t\tsuper();\n\n\t\tthis.tui = tui;\n\t\tthis.currentModel = currentModel;\n\t\tthis.settingsManager = settingsManager;\n\t\tthis.modelRegistry = modelRegistry;\n\t\tthis.scopedModels = scopedModels;\n\t\t// Only land in \"scoped\" view when at least one scoped model has working\n\t\t// auth — otherwise the user would see an empty picker (#unconfigured-models).\n\t\tconst hasReadyScopedModel = scopedModels.some((scoped) =>\n\t\t\tmodelRegistry.isProviderRequestReady(scoped.model.provider),\n\t\t);\n\t\tthis.scope = hasReadyScopedModel ? \"scoped\" : \"all\";\n\t\tthis.onSelectCallback = onSelect;\n\t\tthis.onCancelCallback = onCancel;\n\n\t\t// Add top border\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add hint about model filtering\n\t\tif (scopedModels.length > 0) {\n\t\t\tthis.scopeText = new Text(this.getScopeText(), 0, 0);\n\t\t\tthis.addChild(this.scopeText);\n\t\t\tthis.scopeHintText = new Text(this.getScopeHintText(), 0, 0);\n\t\t\tthis.addChild(this.scopeHintText);\n\t\t} else {\n\t\t\tconst hintText = \"Only showing models with configured API keys (see README for details)\";\n\t\t\tthis.addChild(new Text(theme.fg(\"warning\", hintText), 0, 0));\n\t\t}\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create search input\n\t\tthis.searchInput = new Input();\n\t\tif (initialSearchInput) {\n\t\t\tthis.searchInput.setValue(initialSearchInput);\n\t\t}\n\t\tthis.searchInput.onSubmit = () => {\n\t\t\tif (this.isSearching) {\n\t\t\t\tif (this.filteredModels[this.selectedFlatIndex]) {\n\t\t\t\t\tthis.handleSelect(this.filteredModels[this.selectedFlatIndex].model);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst model = this.getSelectedModel();\n\t\t\t\tif (model) this.handleSelect(model);\n\t\t\t}\n\t\t};\n\t\tthis.addChild(this.searchInput);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create list container\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add bottom border\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Load models and do initial render\n\t\tthis.loadModels().then(() => {\n\t\t\tif (initialSearchInput) {\n\t\t\t\tthis.isSearching = true;\n\t\t\t\tthis.filterModels(initialSearchInput);\n\t\t\t} else {\n\t\t\t\tthis.buildGroupedRows();\n\t\t\t\tthis.jumpToCurrentModel();\n\t\t\t\tthis.updateList();\n\t\t\t}\n\t\t\t// Request re-render after models are loaded\n\t\t\tthis.tui.requestRender();\n\t\t});\n\t}\n\n\tprivate async loadModels(): Promise<void> {\n\t\tlet models: ModelItem[];\n\n\t\t// Refresh to pick up any changes to models.json\n\t\tthis.modelRegistry.refresh();\n\n\t\t// Check for models.json errors\n\t\tconst loadError = this.modelRegistry.getError();\n\t\tif (loadError) {\n\t\t\tthis.errorMessage = loadError;\n\t\t}\n\n\t\t// Load available models (built-in models still work even if models.json failed)\n\t\ttry {\n\t\t\tconst availableModels = this.modelRegistry.getAvailable();\n\t\t\tmodels = availableModels.map((model: Model<any>) => ({\n\t\t\t\tprovider: model.provider,\n\t\t\t\tid: model.id,\n\t\t\t\tmodel,\n\t\t\t}));\n\t\t} catch (error) {\n\t\t\tthis.allModels = [];\n\t\t\tthis.scopedModelItems = [];\n\t\t\tthis.activeModels = [];\n\t\t\tthis.filteredModels = [];\n\t\t\tthis.groupedRows = [];\n\t\t\tthis.modelRowIndices = [];\n\t\t\tthis.errorMessage = error instanceof Error ? error.message : String(error);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.allModels = this.sortModelsWithinProvider(models);\n\t\t// Scoped models must also be filtered by provider readiness so users\n\t\t// can't pick a scoped model whose provider has no API key / OAuth.\n\t\tthis.scopedModelItems = this.sortModelsWithinProvider(\n\t\t\tthis.scopedModels\n\t\t\t\t.filter((scoped) => this.modelRegistry.isProviderRequestReady(scoped.model.provider))\n\t\t\t\t.map((scoped) => ({\n\t\t\t\t\tprovider: scoped.model.provider,\n\t\t\t\t\tid: scoped.model.id,\n\t\t\t\t\tmodel: scoped.model,\n\t\t\t\t})),\n\t\t);\n\t\tthis.activeModels = this.scope === \"scoped\" ? this.scopedModelItems : this.allModels;\n\t\tthis.filteredModels = this.activeModels;\n\t}\n\n\t/**\n\t * Sort models within each provider: current model first, then by name desc.\n\t * Provider ordering is handled separately in buildGroupedRows().\n\t */\n\tprivate sortModelsWithinProvider(models: ModelItem[]): ModelItem[] {\n\t\tconst sorted = [...models];\n\t\tsorted.sort((a, b) => {\n\t\t\tconst aIsCurrent = modelsAreEqual(this.currentModel, a.model);\n\t\t\tconst bIsCurrent = modelsAreEqual(this.currentModel, b.model);\n\t\t\tif (aIsCurrent && !bIsCurrent) return -1;\n\t\t\tif (!aIsCurrent && bIsCurrent) return 1;\n\t\t\t// Within provider: newest/largest model name first\n\t\t\tconst nameCmp = b.model.name.localeCompare(a.model.name);\n\t\t\tif (nameCmp !== 0) return nameCmp;\n\t\t\treturn a.provider.localeCompare(b.provider);\n\t\t});\n\t\treturn sorted;\n\t}\n\n\t/**\n\t * Build the grouped rows array for browse mode.\n\t * Current model's provider comes first; remaining providers sorted alphabetically.\n\t */\n\tprivate buildGroupedRows(): void {\n\t\t// Group models by provider\n\t\tconst byProvider = new Map<string, ModelItem[]>();\n\t\tfor (const item of this.activeModels) {\n\t\t\tlet group = byProvider.get(item.provider);\n\t\t\tif (!group) {\n\t\t\t\tgroup = [];\n\t\t\t\tbyProvider.set(item.provider, group);\n\t\t\t}\n\t\t\tgroup.push(item);\n\t\t}\n\n\t\t// Determine provider order: current model's provider first, rest alphabetically\n\t\tconst currentProvider = this.currentModel?.provider;\n\t\tconst providers = Array.from(byProvider.keys()).sort((a, b) => {\n\t\t\tif (a === currentProvider) return -1;\n\t\t\tif (b === currentProvider) return 1;\n\t\t\treturn a.localeCompare(b);\n\t\t});\n\n\t\tconst rows: ListRow[] = [];\n\t\tconst modelIndices: number[] = [];\n\n\t\tfor (const provider of providers) {\n\t\t\tconst items = byProvider.get(provider)!;\n\t\t\trows.push({ kind: \"header\", provider, count: items.length });\n\t\t\tfor (const item of items) {\n\t\t\t\tmodelIndices.push(rows.length);\n\t\t\t\trows.push({ kind: \"model\", item });\n\t\t\t}\n\t\t}\n\n\t\tthis.groupedRows = rows;\n\t\tthis.modelRowIndices = modelIndices;\n\t}\n\n\t/**\n\t * Move selectedGroupIndex to point at the current model (or first model).\n\t */\n\tprivate jumpToCurrentModel(): void {\n\t\tif (this.groupedRows.length === 0) {\n\t\t\tthis.selectedGroupIndex = 0;\n\t\t\treturn;\n\t\t}\n\t\t// Find the current model in grouped rows\n\t\tfor (let i = 0; i < this.groupedRows.length; i++) {\n\t\t\tconst row = this.groupedRows[i];\n\t\t\tif (row.kind === \"model\" && modelsAreEqual(this.currentModel, row.item.model)) {\n\t\t\t\tthis.selectedGroupIndex = i;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t// Fall back to first model row\n\t\tif (this.modelRowIndices.length > 0) {\n\t\t\tthis.selectedGroupIndex = this.modelRowIndices[0];\n\t\t}\n\t}\n\n\t/**\n\t * Get the currently selected model from grouped or flat state.\n\t */\n\tprivate getSelectedModel(): Model<any> | undefined {\n\t\tif (this.isSearching) {\n\t\t\treturn this.filteredModels[this.selectedFlatIndex]?.model;\n\t\t}\n\t\tconst row = this.groupedRows[this.selectedGroupIndex];\n\t\treturn row?.kind === \"model\" ? row.item.model : undefined;\n\t}\n\n\tprivate getScopeText(): string {\n\t\tconst allText = this.scope === \"all\" ? theme.fg(\"accent\", \"all\") : theme.fg(\"muted\", \"all\");\n\t\tconst scopedText = this.scope === \"scoped\" ? theme.fg(\"accent\", \"scoped\") : theme.fg(\"muted\", \"scoped\");\n\t\treturn `${theme.fg(\"muted\", \"Scope: \")}${allText}${theme.fg(\"muted\", \" | \")}${scopedText}`;\n\t}\n\n\tprivate getScopeHintText(): string {\n\t\treturn keyHint(\"tab\", \"scope\") + theme.fg(\"muted\", \" (all/scoped)\");\n\t}\n\n\tprivate setScope(scope: ModelScope): void {\n\t\tif (this.scope === scope) return;\n\t\tthis.scope = scope;\n\t\tthis.activeModels = this.scope === \"scoped\" ? this.scopedModelItems : this.allModels;\n\n\t\tif (this.isSearching) {\n\t\t\tthis.selectedFlatIndex = 0;\n\t\t\tthis.filterModels(this.searchInput.getValue());\n\t\t} else {\n\t\t\tthis.buildGroupedRows();\n\t\t\tthis.jumpToCurrentModel();\n\t\t\tthis.updateList();\n\t\t}\n\n\t\tif (this.scopeText) {\n\t\t\tthis.scopeText.setText(this.getScopeText());\n\t\t}\n\t}\n\n\tprivate filterModels(query: string): void {\n\t\tthis.filteredModels = query\n\t\t\t? fuzzyFilter(this.activeModels, query, ({ id, provider }) => `${id} ${provider}`)\n\t\t\t: this.activeModels;\n\t\tthis.selectedFlatIndex = Math.min(this.selectedFlatIndex, Math.max(0, this.filteredModels.length - 1));\n\t\tthis.updateList();\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\n\t\tif (this.errorMessage) {\n\t\t\tconst errorLines = this.errorMessage.split(\"\\n\");\n\t\t\tfor (const line of errorLines) {\n\t\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"error\", line), 0, 0));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.isSearching) {\n\t\t\tthis.renderFlatList();\n\t\t} else {\n\t\t\tthis.renderGroupedList();\n\t\t}\n\t}\n\n\t/** Flat fuzzy-search results, same as original behaviour */\n\tprivate renderFlatList(): void {\n\t\tconst maxVisible = 10;\n\n\t\tif (this.filteredModels.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No matching models\"), 0, 0));\n\t\t\treturn;\n\t\t}\n\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(\n\t\t\t\tthis.selectedFlatIndex - Math.floor(maxVisible / 2),\n\t\t\t\tthis.filteredModels.length - maxVisible,\n\t\t\t),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.filteredModels.length);\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst item = this.filteredModels[i];\n\t\t\tif (!item) continue;\n\n\t\t\tconst isSelected = i === this.selectedFlatIndex;\n\t\t\tconst isCurrent = modelsAreEqual(this.currentModel, item.model);\n\n\t\t\tconst ctx = formatTokenCount(item.model.contextWindow);\n\t\t\tconst ctxBadge = theme.fg(\"muted\", `${ctx}`);\n\t\t\tconst providerBadge = theme.fg(\"muted\", `[${providerDisplayName(item.provider)}]`);\n\t\t\tconst checkmark = isCurrent ? theme.fg(\"success\", \" ✓\") : \"\";\n\n\t\t\tlet line: string;\n\t\t\tif (isSelected) {\n\t\t\t\tconst prefix = theme.fg(\"accent\", \"→ \");\n\t\t\t\tline = `${prefix}${theme.fg(\"accent\", item.id)} ${ctxBadge} ${providerBadge}${checkmark}`;\n\t\t\t} else {\n\t\t\t\tline = ` ${item.id} ${ctxBadge} ${providerBadge}${checkmark}`;\n\t\t\t}\n\n\t\t\tthis.listContainer.addChild(new Text(line, 0, 0));\n\t\t}\n\n\t\tif (startIndex > 0 || endIndex < this.filteredModels.length) {\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew Text(theme.fg(\"muted\", ` (${this.selectedFlatIndex + 1}/${this.filteredModels.length})`), 0, 0),\n\t\t\t);\n\t\t}\n\n\t\t// Detail line for selected model\n\t\tconst selected = this.filteredModels[this.selectedFlatIndex];\n\t\tif (selected) {\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", ` ${this.modelDetailLine(selected.model)}`), 0, 0));\n\t\t}\n\t}\n\n\t/**\n\t * Grouped browse view: provider headers + model rows, windowed around selection.\n\t * Shows enough rows to fill ~10 visible lines; headers count as one line each.\n\t */\n\tprivate renderGroupedList(): void {\n\t\tconst maxVisible = 12;\n\n\t\tif (this.groupedRows.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No models available\"), 0, 0));\n\t\t\treturn;\n\t\t}\n\n\t\t// Window around selectedGroupIndex\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(\n\t\t\t\tthis.selectedGroupIndex - Math.floor(maxVisible / 2),\n\t\t\t\tthis.groupedRows.length - maxVisible,\n\t\t\t),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.groupedRows.length);\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst row = this.groupedRows[i];\n\t\t\tif (!row) continue;\n\n\t\t\tif (row.kind === \"header\") {\n\t\t\t\t// Provider group header — always unselectable\n\t\t\t\tconst providerLabel = theme.fg(\"borderAccent\", providerDisplayName(row.provider));\n\t\t\t\tconst count = theme.fg(\"muted\", ` (${row.count})`);\n\t\t\t\t// Add blank line before header if not the very first visible row\n\t\t\t\tif (i > startIndex) {\n\t\t\t\t\tthis.listContainer.addChild(new Text(\"\", 0, 0));\n\t\t\t\t}\n\t\t\t\tthis.listContainer.addChild(new Text(` ${providerLabel}${count}`, 0, 0));\n\t\t\t} else {\n\t\t\t\t// Model row\n\t\t\t\tconst isSelected = i === this.selectedGroupIndex;\n\t\t\t\tconst isCurrent = modelsAreEqual(this.currentModel, row.item.model);\n\n\t\t\t\tconst ctx = formatTokenCount(row.item.model.contextWindow);\n\t\t\t\tconst ctxBadge = theme.fg(\"muted\", ` ${ctx}`);\n\t\t\t\tconst checkmark = isCurrent ? theme.fg(\"success\", \" ✓\") : \"\";\n\n\t\t\t\tlet line: string;\n\t\t\t\tif (isSelected) {\n\t\t\t\t\tline = ` ${theme.fg(\"accent\", \"→\")} ${theme.fg(\"accent\", row.item.id)}${ctxBadge}${checkmark}`;\n\t\t\t\t} else {\n\t\t\t\t\tline = ` ${row.item.id}${ctxBadge}${checkmark}`;\n\t\t\t\t}\n\n\t\t\t\tthis.listContainer.addChild(new Text(line, 0, 0));\n\t\t\t}\n\t\t}\n\n\t\t// Scroll indicator\n\t\tif (startIndex > 0 || endIndex < this.groupedRows.length) {\n\t\t\tconst modelPos = this.modelRowIndices.indexOf(this.selectedGroupIndex) + 1;\n\t\t\tconst totalModels = this.modelRowIndices.length;\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew Text(theme.fg(\"muted\", ` (${modelPos}/${totalModels})`), 0, 0),\n\t\t\t);\n\t\t}\n\n\t\t// Detail line for selected model\n\t\tconst selectedModel = this.getSelectedModel();\n\t\tif (selectedModel) {\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew Text(theme.fg(\"muted\", ` ${this.modelDetailLine(selectedModel)}`), 0, 0),\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate modelDetailLine(m: Model<any>): string {\n\t\treturn [\n\t\t\tm.name,\n\t\t\t`ctx: ${formatTokenCount(m.contextWindow)}`,\n\t\t\t`out: ${formatTokenCount(m.maxTokens)}`,\n\t\t\tm.reasoning ? \"thinking\" : \"\",\n\t\t\tm.input.includes(\"image\") ? \"vision\" : \"\",\n\t\t]\n\t\t\t.filter(Boolean)\n\t\t\t.join(\" · \");\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getEditorKeybindings();\n\n\t\t// Tab: scope toggle\n\t\tif (kb.matches(keyData, \"tab\")) {\n\t\t\tif (this.scopedModelItems.length > 0) {\n\t\t\t\tconst nextScope: ModelScope = this.scope === \"all\" ? \"scoped\" : \"all\";\n\t\t\t\tthis.setScope(nextScope);\n\t\t\t\tif (this.scopeHintText) {\n\t\t\t\t\tthis.scopeHintText.setText(this.getScopeHintText());\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Navigation keys\n\t\tif (kb.matches(keyData, \"selectUp\")) {\n\t\t\tthis.moveUp();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(keyData, \"selectDown\")) {\n\t\t\tthis.moveDown();\n\t\t\treturn;\n\t\t}\n\n\t\t// Confirm\n\t\tif (kb.matches(keyData, \"selectConfirm\")) {\n\t\t\tconst model = this.getSelectedModel();\n\t\t\tif (model) this.handleSelect(model);\n\t\t\treturn;\n\t\t}\n\n\t\t// Cancel\n\t\tif (kb.matches(keyData, \"selectCancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t\treturn;\n\t\t}\n\n\t\t// Everything else: feed to search input\n\t\tconst prevQuery = this.searchInput.getValue();\n\t\tthis.searchInput.handleInput(keyData);\n\t\tconst newQuery = this.searchInput.getValue();\n\n\t\tif (newQuery !== prevQuery) {\n\t\t\tconst entering = !prevQuery && !!newQuery;\n\t\t\tconst leaving = !!prevQuery && !newQuery;\n\n\t\t\tif (entering) {\n\t\t\t\t// Entering search mode: remember current model position\n\t\t\t\tthis.isSearching = true;\n\t\t\t\tthis.selectedFlatIndex = 0;\n\t\t\t} else if (leaving) {\n\t\t\t\t// Leaving search mode: return to grouped view, restore position\n\t\t\t\tthis.isSearching = false;\n\t\t\t\tthis.buildGroupedRows();\n\t\t\t\tthis.jumpToCurrentModel();\n\t\t\t}\n\t\t\tif (this.isSearching) {\n\t\t\t\tthis.filterModels(newQuery);\n\t\t\t} else {\n\t\t\t\tthis.updateList();\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Move selection up, skipping headers in grouped mode */\n\tprivate moveUp(): void {\n\t\tif (this.isSearching) {\n\t\t\tif (this.filteredModels.length === 0) return;\n\t\t\tthis.selectedFlatIndex =\n\t\t\t\tthis.selectedFlatIndex === 0\n\t\t\t\t\t? this.filteredModels.length - 1\n\t\t\t\t\t: this.selectedFlatIndex - 1;\n\t\t\tthis.updateList();\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.groupedRows.length === 0) return;\n\t\tlet next = this.selectedGroupIndex - 1;\n\t\t// Wrap\n\t\tif (next < 0) next = this.groupedRows.length - 1;\n\t\t// Skip headers\n\t\twhile (next > 0 && this.groupedRows[next]?.kind === \"header\") {\n\t\t\tnext--;\n\t\t}\n\t\t// If landed on header at 0, wrap to bottom\n\t\tif (this.groupedRows[next]?.kind === \"header\") {\n\t\t\tnext = this.groupedRows.length - 1;\n\t\t}\n\t\tthis.selectedGroupIndex = next;\n\t\tthis.updateList();\n\t}\n\n\t/** Move selection down, skipping headers in grouped mode */\n\tprivate moveDown(): void {\n\t\tif (this.isSearching) {\n\t\t\tif (this.filteredModels.length === 0) return;\n\t\t\tthis.selectedFlatIndex =\n\t\t\t\tthis.selectedFlatIndex === this.filteredModels.length - 1\n\t\t\t\t\t? 0\n\t\t\t\t\t: this.selectedFlatIndex + 1;\n\t\t\tthis.updateList();\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.groupedRows.length === 0) return;\n\t\tlet next = this.selectedGroupIndex + 1;\n\t\t// Wrap\n\t\tif (next >= this.groupedRows.length) next = 0;\n\t\t// Skip headers\n\t\twhile (next < this.groupedRows.length - 1 && this.groupedRows[next]?.kind === \"header\") {\n\t\t\tnext++;\n\t\t}\n\t\t// If landed on header at end, wrap to first model\n\t\tif (this.groupedRows[next]?.kind === \"header\") {\n\t\t\tnext = this.modelRowIndices[0] ?? 0;\n\t\t}\n\t\tthis.selectedGroupIndex = next;\n\t\tthis.updateList();\n\t}\n\n\tprivate handleSelect(model: Model<any>): void {\n\t\t// Save as new default\n\t\tthis.settingsManager.setDefaultModelAndProvider(model.provider, model.id);\n\t\tthis.onSelectCallback(model);\n\t}\n\n\tgetSearchInput(): Input {\n\t\treturn this.searchInput;\n\t}\n}\n"]}
|
package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-controller.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/controllers/model-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBtF;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAyBxG;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"model-controller.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/controllers/model-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBtF;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAyBxG;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAgBzE;AAED,wBAAsB,4BAA4B,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAI3E"}
|
|
@@ -45,7 +45,12 @@ export async function findExactModelMatch(host, searchTerm) {
|
|
|
45
45
|
}
|
|
46
46
|
export async function getModelCandidates(host) {
|
|
47
47
|
if (host.session.scopedModels.length > 0) {
|
|
48
|
-
|
|
48
|
+
// Filter scoped models by provider auth readiness so callers like
|
|
49
|
+
// findExactModelMatch can't resolve a scoped-but-unconfigured model.
|
|
50
|
+
const registry = host.session.modelRegistry;
|
|
51
|
+
return host.session.scopedModels
|
|
52
|
+
.filter((scoped) => registry.isProviderRequestReady(scoped.model.provider))
|
|
53
|
+
.map((scoped) => scoped.model);
|
|
49
54
|
}
|
|
50
55
|
host.session.modelRegistry.refresh();
|
|
51
56
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-controller.js","sourceRoot":"","sources":["../../../../src/modes/interactive/controllers/model-controller.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAS,EAAE,UAAmB;IACtE,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,OAAO;IACR,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC1D,IAAI,KAAK,EAAE,CAAC;QACX,IAAI,CAAC;YACJ,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YACnC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YACzB,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAC/B,IAAI,CAAC,UAAU,CAAC,UAAU,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;YACtC,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,SAAS,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACxE,CAAC;QACD,OAAO;IACR,CAAC;IAED,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAS,EAAE,UAAkB;IACtE,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;IAC/B,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAE5B,IAAI,cAAkC,CAAC;IACvC,IAAI,aAAa,GAAG,EAAE,CAAC;IAEvB,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACjC,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAChD,aAAa,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;IACtD,CAAC;SAAM,CAAC;QACP,aAAa,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACpC,CAAC;IAED,IAAI,CAAC,aAAa;QAAE,OAAO,SAAS,CAAC;IAErC,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,aAAa,CAAC;QACxD,MAAM,aAAa,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,cAAc,CAAC;QACxF,OAAO,OAAO,IAAI,aAAa,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,OAAO,YAAY,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAChE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAS;IACjD,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,MAAW,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"model-controller.js","sourceRoot":"","sources":["../../../../src/modes/interactive/controllers/model-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Model } from \"@gsd/pi-ai\";\n\nexport async function handleModelCommand(host: any, searchTerm?: string): Promise<void> {\n\tif (!searchTerm) {\n\t\thost.showModelSelector();\n\t\treturn;\n\t}\n\n\tconst model = await findExactModelMatch(host, searchTerm);\n\tif (model) {\n\t\ttry {\n\t\t\tawait host.session.setModel(model);\n\t\t\thost.footer.invalidate();\n\t\t\thost.updateEditorBorderColor();\n\t\t\thost.showStatus(`Model: ${model.id}`);\n\t\t\thost.checkDaxnutsEasterEgg(model);\n\t\t} catch (error) {\n\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t}\n\t\treturn;\n\t}\n\n\thost.showModelSelector(searchTerm);\n}\n\nexport async function findExactModelMatch(host: any, searchTerm: string): Promise<Model<any> | undefined> {\n\tconst term = searchTerm.trim();\n\tif (!term) return undefined;\n\n\tlet targetProvider: string | undefined;\n\tlet targetModelId = \"\";\n\n\tif (term.includes(\"/\")) {\n\t\tconst parts = term.split(\"/\", 2);\n\t\ttargetProvider = parts[0]?.trim().toLowerCase();\n\t\ttargetModelId = parts[1]?.trim().toLowerCase() ?? \"\";\n\t} else {\n\t\ttargetModelId = term.toLowerCase();\n\t}\n\n\tif (!targetModelId) return undefined;\n\n\tconst models = await getModelCandidates(host);\n\tconst exactMatches = models.filter((item) => {\n\t\tconst idMatch = item.id.toLowerCase() === targetModelId;\n\t\tconst providerMatch = !targetProvider || item.provider.toLowerCase() === targetProvider;\n\t\treturn idMatch && providerMatch;\n\t});\n\n\treturn exactMatches.length === 1 ? exactMatches[0] : undefined;\n}\n\nexport async function getModelCandidates(host: any): Promise<Model<any>[]> {\n\tif (host.session.scopedModels.length > 0) {\n\t\t// Filter scoped models by provider auth readiness so callers like\n\t\t// findExactModelMatch can't resolve a scoped-but-unconfigured model.\n\t\tconst registry = host.session.modelRegistry;\n\t\treturn host.session.scopedModels\n\t\t\t.filter((scoped: any) => registry.isProviderRequestReady(scoped.model.provider))\n\t\t\t.map((scoped: any) => scoped.model);\n\t}\n\n\thost.session.modelRegistry.refresh();\n\ttry {\n\t\treturn await host.session.modelRegistry.getAvailable();\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nexport async function updateAvailableProviderCount(host: any): Promise<void> {\n\tconst models = await getModelCandidates(host);\n\tconst uniqueProviders = new Set(models.map((m) => m.provider));\n\thost.footerDataProvider.setAvailableProviderCount(uniqueProviders.size);\n}\n\n"]}
|