@ponythewhite/base-context 1.0.0 → 1.0.1
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/CHANGELOG.md +33 -0
- package/NOTICE +0 -5
- package/README.md +44 -27
- package/dist/NOTICE +0 -5
- package/dist/base-context-runtime/pyproject.toml +1 -1
- package/dist/base-context-runtime/src/rlm/__init__.py +7 -5
- package/dist/base-context-runtime/test/test_subagent_registry.py +28 -1
- package/dist/base-context-runtime/uv.lock +1 -1
- package/dist/build-info.json +1 -1
- package/dist/bundle/amazon-bedrock.js +21 -0
- package/dist/bundle/{anthropic-YY4S534V.js → anthropic-UV5GZDGU.js} +5 -5
- package/dist/bundle/{azure-openai-responses-JRP6MIM3.js → azure-openai-responses-WSNPXLYC.js} +6 -6
- package/dist/bundle/{bundled-modules-P5HARVZA.js → bundled-modules-TXUMJ2XQ.js} +71 -16
- package/dist/bundle/chunk-27QCJ2AZ.js +2578 -0
- package/dist/bundle/{chunk-MZHTNNVA.js → chunk-4GXPNXOJ.js} +8 -0
- package/dist/bundle/{chunk-SC5KG5R4.js → chunk-DGNX7HQ3.js} +1 -7
- package/dist/bundle/{chunk-A53O363M.js → chunk-GRJFXLBM.js} +0 -1
- package/dist/bundle/chunk-HKINIBP4.js +29 -0
- package/dist/bundle/{chunk-UDSW6FNG.js → chunk-KTNETTHI.js} +1 -1
- package/dist/bundle/{chunk-BYVP7LWV.js → chunk-S3INFPZZ.js} +1861 -4662
- package/dist/bundle/{chunk-73DCPU3D.js → chunk-V3L54UD6.js} +1019 -3427
- package/dist/bundle/{chunk-U7AUVG3B.js → chunk-VSIYFWYI.js} +24 -6
- package/dist/bundle/{chunk-IW77OXFS.js → chunk-W46VZFI6.js} +0 -2099
- package/dist/bundle/{cli-main-O4X7GFGY.js → cli-main-BYMSRPH6.js} +8 -6
- package/dist/bundle/cli.js +2 -2
- package/dist/bundle/{google-AUTVGDGZ.js → google-T32FMD4G.js} +6 -6
- package/dist/bundle/{google-vertex-Q75D7RKS.js → google-vertex-56KP6I3B.js} +3 -3
- package/dist/bundle/{main-XKOW2BV6.js → main-ODOYCEQC.js} +7 -5
- package/dist/bundle/{mistral-7ESB7QUD.js → mistral-WGBMYIVU.js} +5 -5
- package/dist/bundle/{openai-codex-responses-LV3QRPN4.js → openai-codex-responses-PIV2RQ3G.js} +6 -6
- package/dist/bundle/{openai-completions-OJECLPXJ.js → openai-completions-64C3JPR4.js} +11 -22
- package/dist/bundle/{openai-responses-FN6HZMBC.js → openai-responses-UI7RSTDV.js} +6 -6
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +108 -59
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/daemon-ps.d.ts +4 -3
- package/dist/cli/daemon-ps.d.ts.map +1 -1
- package/dist/cli/daemon-ps.js +6 -1
- package/dist/cli/daemon-ps.js.map +1 -1
- package/dist/cli/product-doctor.d.ts +0 -1
- package/dist/cli/product-doctor.d.ts.map +1 -1
- package/dist/cli/product-doctor.js +6 -3
- package/dist/cli/product-doctor.js.map +1 -1
- package/dist/config.d.ts +0 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -8
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-config.d.ts +1 -2
- package/dist/core/agent-session-config.d.ts.map +1 -1
- package/dist/core/agent-session-config.js +0 -3
- package/dist/core/agent-session-config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +5 -4
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +5 -3
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +2 -27
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +10 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +107 -107
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +8 -35
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +33 -243
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/cron-jobs.d.ts.map +1 -1
- package/dist/core/cron-jobs.js +7 -1
- package/dist/core/cron-jobs.js.map +1 -1
- package/dist/core/inference-coordinator.d.ts +6 -1
- package/dist/core/inference-coordinator.d.ts.map +1 -1
- package/dist/core/inference-coordinator.js +18 -2
- package/dist/core/inference-coordinator.js.map +1 -1
- package/dist/core/kernel/bootstrap.d.ts.map +1 -1
- package/dist/core/kernel/bootstrap.js +2 -2
- package/dist/core/kernel/bootstrap.js.map +1 -1
- package/dist/core/kernel/repl-manager.d.ts +2 -0
- package/dist/core/kernel/repl-manager.d.ts.map +1 -1
- package/dist/core/kernel/repl-manager.js +44 -1
- package/dist/core/kernel/repl-manager.js.map +1 -1
- package/dist/core/logging.d.ts +4 -3
- package/dist/core/logging.d.ts.map +1 -1
- package/dist/core/logging.js +6 -6
- package/dist/core/logging.js.map +1 -1
- package/dist/core/mcp/mcp-manager.d.ts.map +1 -1
- package/dist/core/mcp/mcp-manager.js +3 -3
- package/dist/core/mcp/mcp-manager.js.map +1 -1
- package/dist/core/model-registry.d.ts +1 -16
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +88 -196
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +2 -19
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +36 -266
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/provider-contracts.d.ts +5 -6
- package/dist/core/provider-contracts.d.ts.map +1 -1
- package/dist/core/provider-contracts.js +25 -36
- package/dist/core/provider-contracts.js.map +1 -1
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +0 -2
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/rlm-max-subagents.d.ts +32 -0
- package/dist/core/rlm-max-subagents.d.ts.map +1 -0
- package/dist/core/rlm-max-subagents.js +50 -0
- package/dist/core/rlm-max-subagents.js.map +1 -0
- package/dist/core/rlm-runtime.d.ts +3 -3
- package/dist/core/rlm-runtime.d.ts.map +1 -1
- package/dist/core/rlm-runtime.js.map +1 -1
- package/dist/core/sdk.d.ts +4 -3
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +27 -14
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -16
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +12 -44
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +6 -6
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/installer.mjs +2 -3
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +39 -34
- package/dist/main.js.map +1 -1
- package/dist/modes/acp/acp-mode.d.ts.map +1 -1
- package/dist/modes/acp/acp-mode.js +1 -1
- package/dist/modes/acp/acp-mode.js.map +1 -1
- package/dist/modes/agent-connection/daemon-agent-connection.d.ts +6 -2
- package/dist/modes/agent-connection/daemon-agent-connection.d.ts.map +1 -1
- package/dist/modes/agent-connection/daemon-agent-connection.js +13 -2
- package/dist/modes/agent-connection/daemon-agent-connection.js.map +1 -1
- package/dist/modes/agent-connection/in-process-agent-connection.d.ts +2 -0
- package/dist/modes/agent-connection/in-process-agent-connection.d.ts.map +1 -1
- package/dist/modes/agent-connection/in-process-agent-connection.js +6 -0
- package/dist/modes/agent-connection/in-process-agent-connection.js.map +1 -1
- package/dist/modes/agent-connection/types.d.ts +3 -0
- package/dist/modes/agent-connection/types.d.ts.map +1 -1
- package/dist/modes/agent-connection/types.js.map +1 -1
- package/dist/modes/agents-view/agents-view-mode.d.ts.map +1 -1
- package/dist/modes/agents-view/agents-view-mode.js +2 -19
- package/dist/modes/agents-view/agents-view-mode.js.map +1 -1
- package/dist/modes/daemon/daemon-mode.d.ts +5 -0
- package/dist/modes/daemon/daemon-mode.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-mode.js +107 -12
- package/dist/modes/daemon/daemon-mode.js.map +1 -1
- package/dist/modes/daemon/daemon-protocol.d.ts +194 -165
- package/dist/modes/daemon/daemon-protocol.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-protocol.js +16 -11
- package/dist/modes/daemon/daemon-protocol.js.map +1 -1
- package/dist/modes/daemon/daemon-rlm-capacity-coordinator.d.ts +19 -0
- package/dist/modes/daemon/daemon-rlm-capacity-coordinator.d.ts.map +1 -0
- package/dist/modes/daemon/daemon-rlm-capacity-coordinator.js +74 -0
- package/dist/modes/daemon/daemon-rlm-capacity-coordinator.js.map +1 -0
- package/dist/modes/daemon/daemon-rlm-capacity.d.ts +19 -0
- package/dist/modes/daemon/daemon-rlm-capacity.d.ts.map +1 -0
- package/dist/modes/daemon/daemon-rlm-capacity.js +85 -0
- package/dist/modes/daemon/daemon-rlm-capacity.js.map +1 -0
- package/dist/modes/daemon/daemon-session-summarizer.d.ts +2 -3
- package/dist/modes/daemon/daemon-session-summarizer.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-session-summarizer.js +32 -23
- package/dist/modes/daemon/daemon-session-summarizer.js.map +1 -1
- package/dist/modes/daemon/daemon-state-root.d.ts +15 -0
- package/dist/modes/daemon/daemon-state-root.d.ts.map +1 -0
- package/dist/modes/daemon/daemon-state-root.js +40 -0
- package/dist/modes/daemon/daemon-state-root.js.map +1 -0
- package/dist/modes/daemon/daemon-supervisor-ownership.d.ts +2 -0
- package/dist/modes/daemon/daemon-supervisor-ownership.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-supervisor-ownership.js +27 -0
- package/dist/modes/daemon/daemon-supervisor-ownership.js.map +1 -1
- package/dist/modes/daemon/daemon-supervisor.d.ts +10 -1
- package/dist/modes/daemon/daemon-supervisor.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-supervisor.js +213 -20
- package/dist/modes/daemon/daemon-supervisor.js.map +1 -1
- package/dist/modes/daemon/daemon-worker-protocol.d.ts +28 -1
- package/dist/modes/daemon/daemon-worker-protocol.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-worker-protocol.js +16 -2
- package/dist/modes/daemon/daemon-worker-protocol.js.map +1 -1
- package/dist/modes/daemon/saved-session-catalog.d.ts.map +1 -1
- package/dist/modes/daemon/saved-session-catalog.js +2 -0
- package/dist/modes/daemon/saved-session-catalog.js.map +1 -1
- package/dist/modes/interactive/auth-flows.d.ts +0 -6
- package/dist/modes/interactive/auth-flows.d.ts.map +1 -1
- package/dist/modes/interactive/auth-flows.js +6 -126
- package/dist/modes/interactive/auth-flows.js.map +1 -1
- package/dist/modes/interactive/components/configuration-menu.d.ts +3 -0
- package/dist/modes/interactive/components/configuration-menu.d.ts.map +1 -1
- package/dist/modes/interactive/components/configuration-menu.js +13 -2
- package/dist/modes/interactive/components/configuration-menu.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +2 -2
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +0 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +0 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +0 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +3 -40
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +2 -0
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +13 -2
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +2 -11
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/feature-hints.d.ts.map +1 -1
- package/dist/modes/interactive/feature-hints.js +0 -4
- package/dist/modes/interactive/feature-hints.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +3 -12
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +81 -507
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/onboarding.d.ts +0 -3
- package/dist/modes/interactive/onboarding.d.ts.map +1 -1
- package/dist/modes/interactive/onboarding.js +0 -17
- package/dist/modes/interactive/onboarding.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +2 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +24 -11
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/node/amazon-bedrock.d.ts +2 -0
- package/dist/node/amazon-bedrock.d.ts.map +1 -0
- package/dist/node/amazon-bedrock.js +6 -0
- package/dist/node/amazon-bedrock.js.map +1 -0
- package/dist/product-identity.d.ts +0 -1
- package/dist/product-identity.d.ts.map +1 -1
- package/dist/product-identity.js +0 -1
- package/dist/product-identity.js.map +1 -1
- package/docs/development.md +1 -1
- package/docs/fork-philosophy.md +4 -8
- package/docs/installation.md +83 -62
- package/docs/providers.md +23 -25
- package/docs/quickstart.md +19 -10
- package/docs/rlm-runtime.md +13 -5
- package/docs/rpc.md +4 -4
- package/docs/sdk.md +20 -11
- package/docs/sessions.md +0 -1
- package/docs/settings.md +9 -42
- package/docs/skills.md +0 -1
- package/docs/upstream-0.9.5.md +171 -0
- package/docs/usage.md +14 -10
- package/package.json +4 -4
- package/dist/core/agent-traces.d.ts +0 -149
- package/dist/core/agent-traces.d.ts.map +0 -1
- package/dist/core/agent-traces.js +0 -904
- package/dist/core/agent-traces.js.map +0 -1
- package/dist/core/prime-inference-auth.d.ts +0 -70
- package/dist/core/prime-inference-auth.d.ts.map +0 -1
- package/dist/core/prime-inference-auth.js +0 -352
- package/dist/core/prime-inference-auth.js.map +0 -1
- package/dist/core/prime-inference-model-selection.d.ts +0 -16
- package/dist/core/prime-inference-model-selection.d.ts.map +0 -1
- package/dist/core/prime-inference-model-selection.js +0 -16
- package/dist/core/prime-inference-model-selection.js.map +0 -1
- package/dist/core/prime-inference-models.d.ts +0 -6
- package/dist/core/prime-inference-models.d.ts.map +0 -1
- package/dist/core/prime-inference-models.js +0 -62
- package/dist/core/prime-inference-models.js.map +0 -1
- package/dist/core/telemetry.d.ts +0 -95
- package/dist/core/telemetry.d.ts.map +0 -1
- package/dist/core/telemetry.js +0 -637
- package/dist/core/telemetry.js.map +0 -1
- package/dist/modes/interactive/components/prime-onboarding-splash.d.ts +0 -39
- package/dist/modes/interactive/components/prime-onboarding-splash.d.ts.map +0 -1
- package/dist/modes/interactive/components/prime-onboarding-splash.js +0 -286
- package/dist/modes/interactive/components/prime-onboarding-splash.js.map +0 -1
- package/dist/modes/interactive/components/prime-team-selector.d.ts +0 -30
- package/dist/modes/interactive/components/prime-team-selector.d.ts.map +0 -1
- package/dist/modes/interactive/components/prime-team-selector.js +0 -166
- package/dist/modes/interactive/components/prime-team-selector.js.map +0 -1
- package/dist/skills/prime-intellect/SKILL.md +0 -87
- package/dist/skills/prime-intellect/references/compute.md +0 -45
- package/dist/skills/prime-intellect/references/environments.md +0 -73
- package/dist/skills/prime-intellect/references/inference.md +0 -47
- package/dist/skills/prime-intellect/references/sandboxes.md +0 -75
- package/skills/prime-intellect/SKILL.md +0 -87
- package/skills/prime-intellect/references/compute.md +0 -45
- package/skills/prime-intellect/references/environments.md +0 -73
- package/skills/prime-intellect/references/inference.md +0 -47
- package/skills/prime-intellect/references/sandboxes.md +0 -75
|
@@ -99,6 +99,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
99
99
|
onCancelCallback;
|
|
100
100
|
availableModels;
|
|
101
101
|
configuredProviders;
|
|
102
|
+
providerFilter;
|
|
102
103
|
recentRank;
|
|
103
104
|
errorMessage;
|
|
104
105
|
tui;
|
|
@@ -175,6 +176,14 @@ export class ModelSelectorComponent extends Container {
|
|
|
175
176
|
}
|
|
176
177
|
this.tui.requestRender();
|
|
177
178
|
}
|
|
179
|
+
setProviderFilter(provider) {
|
|
180
|
+
this.providerFilter = provider;
|
|
181
|
+
this.scope = "all";
|
|
182
|
+
this.panel.setTitle(`Models: ${provider}`);
|
|
183
|
+
if (this.scopeText)
|
|
184
|
+
this.scopeText.setText(this.getScopeText());
|
|
185
|
+
this.updateState(this.currentModel);
|
|
186
|
+
}
|
|
178
187
|
updateAvailableModels(availableModels) {
|
|
179
188
|
this.updateState(this.currentModel, availableModels);
|
|
180
189
|
}
|
|
@@ -224,7 +233,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
224
233
|
this.errorMessage = error instanceof Error ? error.message : String(error);
|
|
225
234
|
return;
|
|
226
235
|
}
|
|
227
|
-
this.allModels = this.sortModels(models);
|
|
236
|
+
this.allModels = this.sortModels(models.filter((model) => this.providerFilter === undefined || model.provider === this.providerFilter));
|
|
228
237
|
const availableModelsById = new Map(availableModels.map((model) => [`${model.provider}/${model.id}`, model]));
|
|
229
238
|
this.scopedModels = this.scopedModels.map((scoped) => {
|
|
230
239
|
const scopedModelId = `${scoped.model.provider}/${scoped.model.id}`;
|
|
@@ -234,7 +243,9 @@ export class ModelSelectorComponent extends Container {
|
|
|
234
243
|
: this.modelRegistry.find(scoped.model.provider, scoped.model.id));
|
|
235
244
|
return refreshed ? { ...scoped, model: refreshed } : scoped;
|
|
236
245
|
});
|
|
237
|
-
this.scopedModelItems = this.scopedModels
|
|
246
|
+
this.scopedModelItems = this.scopedModels
|
|
247
|
+
.filter((scoped) => this.providerFilter === undefined || scoped.model.provider === this.providerFilter)
|
|
248
|
+
.map((scoped) => ({
|
|
238
249
|
provider: scoped.model.provider,
|
|
239
250
|
id: scoped.model.id,
|
|
240
251
|
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 \"@ponythewhite/base-context-ai\";\nimport {\n\ttype Component,\n\tContainer,\n\ttype Focusable,\n\tfuzzyMatch,\n\tgetKeybindings,\n\tSpacer,\n\tText,\n\ttype TUI,\n} from \"@ponythewhite/base-context-tui\";\nimport type { ModelRegistry } from \"../../../core/model-registry.js\";\nimport { theme } from \"../theme/theme.js\";\nimport { keyHint } from \"./keybinding-hints.js\";\nimport {\n\tgetMenuListLayout,\n\tMenuList,\n\tMenuPanel,\n\tMenuRow,\n\tMenuSearchInput,\n\ttype MenuViewportProvider,\n} from \"./menu-panel.js\";\nimport { shouldTreatAsBack } from \"./modal-back.js\";\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\nenum ModelSearchMatchQuality {\n\tExactShortId,\n\tExactFullId,\n\tPrefixOrToken,\n\tFuzzy,\n}\n\ninterface ModelSearchMatch {\n\tquality: ModelSearchMatchQuality;\n\tscore: number;\n}\n\nfunction normalizeModelSearchText(value: string): string {\n\treturn value.toLowerCase().replace(/[\\s\\-_.:/]+/g, \"\");\n}\n\nfunction getModelSearchFields(item: ModelItem): { shortId: string; fullIds: string[]; all: string[] } {\n\tconst shortId = item.id.slice(item.id.lastIndexOf(\"/\") + 1);\n\tconst fullIds = [item.id, `${item.provider}/${item.id}`];\n\treturn {\n\t\tshortId,\n\t\tfullIds,\n\t\tall: [shortId, ...fullIds, item.model.name, item.provider],\n\t};\n}\n\nfunction getBestFuzzyScore(queryTokens: string[], fields: string[]): number | null {\n\tlet total = 0;\n\tfor (const token of queryTokens) {\n\t\tlet best = Number.POSITIVE_INFINITY;\n\t\tfor (const field of fields) {\n\t\t\tconst match = fuzzyMatch(token, field);\n\t\t\tif (match.matches) best = Math.min(best, match.score);\n\t\t}\n\t\tif (!Number.isFinite(best)) return null;\n\t\ttotal += best;\n\t}\n\treturn total;\n}\n\nfunction scoreModelSearch(item: ModelItem, query: string): ModelSearchMatch | null {\n\tconst queryTokens = query.trim().split(/\\s+/);\n\tconst normalizedQuery = normalizeModelSearchText(query);\n\tconst normalizedTokens = queryTokens.map(normalizeModelSearchText).filter(Boolean);\n\tif (!normalizedQuery || normalizedTokens.length === 0) return null;\n\n\tconst fields = getModelSearchFields(item);\n\tif (normalizeModelSearchText(fields.shortId) === normalizedQuery) {\n\t\treturn { quality: ModelSearchMatchQuality.ExactShortId, score: 0 };\n\t}\n\tif (fields.fullIds.some((field) => normalizeModelSearchText(field) === normalizedQuery)) {\n\t\treturn { quality: ModelSearchMatchQuality.ExactFullId, score: 0 };\n\t}\n\n\tconst normalizedFields = fields.all.map(normalizeModelSearchText);\n\tconst fieldTokens = fields.all\n\t\t.flatMap((field) => field.split(/[\\s/_-]+/))\n\t\t.map(normalizeModelSearchText)\n\t\t.filter(Boolean);\n\tconst fuzzyScore = getBestFuzzyScore(normalizedTokens, normalizedFields);\n\tconst isPrefixOrToken = normalizedTokens.every(\n\t\t(token) =>\n\t\t\tnormalizedFields.some((field) => field.startsWith(token)) ||\n\t\t\tfieldTokens.some((field) => field.startsWith(token)),\n\t);\n\tif (isPrefixOrToken && fuzzyScore !== null) {\n\t\treturn { quality: ModelSearchMatchQuality.PrefixOrToken, score: fuzzyScore };\n\t}\n\treturn fuzzyScore === null ? null : { quality: ModelSearchMatchQuality.Fuzzy, score: fuzzyScore };\n}\n\nexport interface ModelSelectorOptions {\n\tavailableModels?: ReadonlyArray<Model<any>>;\n\tconfiguredProviders?: ReadonlySet<string>;\n\theader?: Component;\n\tgetHeaderRows?: () => number;\n\tsubtitle?: string;\n\tgetRows?: () => number;\n\trecentModels?: ReadonlyArray<string>;\n}\n\ntype ModelScope = \"all\" | \"scoped\";\n\nconst PREFERRED_VISIBLE_MODELS = 10;\nconst MODEL_LIST_RESERVED_ROWS = {\n\tbase: 7,\n\tdetail: 2,\n};\nconst MODEL_SCROLL_INDICATOR_ROWS = 1;\nconst MODEL_HELP_MIN_ROWS = 12;\nconst MODEL_DETAIL_MIN_ROWS = 14;\n\n/**\n * Component that renders a model selector with search\n */\nexport class ModelSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: MenuSearchInput;\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\tprivate filteredModels: ModelItem[] = [];\n\tprivate selectedIndex: number = 0;\n\tprivate searchQuery = \"\";\n\tprivate currentModel?: Model<any>;\n\tprivate modelRegistry: ModelRegistry;\n\tprivate onSelectCallback: (model: Model<any>) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate availableModels?: ReadonlyArray<Model<any>>;\n\tprivate configuredProviders?: ReadonlySet<string>;\n\tprivate recentRank: Map<string, number>;\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\tprivate panel: MenuPanel;\n\tprivate headerHelpContainer: Container;\n\tprivate warningText?: Text;\n\tprivate listLayout = getMenuListLayout({\n\t\tpreferredVisibleItems: PREFERRED_VISIBLE_MODELS,\n\t\treservedRows: MODEL_LIST_RESERVED_ROWS.base,\n\t\tcomfortableItemRows: 3,\n\t\tcompactItemRows: 2,\n\t});\n\tprivate responsiveLayoutKey = \"\";\n\tprivate readonly viewport: MenuViewportProvider;\n\tprivate readonly getHeaderRows: () => number;\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tcurrentModel: Model<any> | undefined,\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\toptions: ModelSelectorOptions = {},\n\t) {\n\t\tsuper();\n\n\t\tthis.tui = tui;\n\t\tthis.currentModel = currentModel;\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\t\tthis.availableModels = options.availableModels;\n\t\tthis.configuredProviders = options.configuredProviders;\n\t\tthis.recentRank = new Map((options.recentModels ?? []).map((key, i) => [key, i]));\n\t\tthis.viewport = { getRows: options.getRows };\n\t\tthis.getHeaderRows = options.header ? (options.getHeaderRows ?? (() => 2)) : () => 0;\n\n\t\tthis.panel = new MenuPanel({\n\t\t\ttitle: \"Models\",\n\t\t\tsubtitle: options.subtitle ?? \"All models across supported providers.\",\n\t\t});\n\t\tthis.addChild(this.panel);\n\t\tif (options.header) {\n\t\t\tthis.panel.addChild(options.header);\n\t\t\tthis.panel.addChild(new Spacer(1));\n\t\t}\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.scopeHintText = new Text(this.getScopeHintText(), 0, 0);\n\t\t} else {\n\t\t\tconst hintText = \"Signed-in providers first. Other models prompt sign-in.\";\n\t\t\tthis.warningText = new Text(theme.fg(\"muted\", hintText), 0, 0);\n\t\t}\n\t\tthis.headerHelpContainer = new Container();\n\t\tthis.panel.addChild(this.headerHelpContainer);\n\n\t\t// Create search input\n\t\tthis.searchInput = new MenuSearchInput(\"Search models\");\n\t\tif (initialSearchInput) {\n\t\t\tthis.searchInput.setValue(initialSearchInput);\n\t\t}\n\t\tthis.searchInput.onSubmit = () => {\n\t\t\tthis.handleConfirm();\n\t\t};\n\t\tthis.panel.addChild(this.searchInput);\n\n\t\tthis.panel.addChild(new Spacer(1));\n\n\t\t// Create list container\n\t\tthis.listContainer = new MenuList({ compact: () => this.listLayout.compact });\n\t\tthis.panel.addChild(this.listContainer);\n\t\tthis.updateResponsiveLayout();\n\n\t\tthis.loadModels();\n\t\tif (initialSearchInput) {\n\t\t\tthis.filterModels(initialSearchInput);\n\t\t} else {\n\t\t\tthis.updateList();\n\t\t}\n\t\tthis.tui.requestRender();\n\t}\n\n\tupdateAvailableModels(availableModels: ReadonlyArray<Model<any>>): void {\n\t\tthis.updateState(this.currentModel, availableModels);\n\t}\n\n\tupdateState(\n\t\tcurrentModel: Model<any> | undefined,\n\t\tavailableModels = this.availableModels,\n\t\tconfiguredProviders = this.configuredProviders,\n\t): void {\n\t\tthis.currentModel = currentModel;\n\t\tthis.availableModels = availableModels;\n\t\tthis.configuredProviders = configuredProviders;\n\t\tconst query = this.searchInput.getValue();\n\t\tconst selectedKey = this.getSelectedModelKey();\n\n\t\tthis.loadModels();\n\t\tthis.filterModels(query);\n\n\t\tif (selectedKey) {\n\t\t\tconst selectedIndex = this.filteredModels.findIndex((item) => this.getModelKey(item) === selectedKey);\n\t\t\tif (selectedIndex >= 0) {\n\t\t\t\tthis.selectedIndex = selectedIndex;\n\t\t\t\tthis.updateList();\n\t\t\t}\n\t\t}\n\n\t\tthis.tui.requestRender();\n\t}\n\n\tprivate loadModels(): void {\n\t\tlet models: ModelItem[];\n\t\tthis.errorMessage = undefined;\n\n\t\tif (this.availableModels === undefined) {\n\t\t\tthis.modelRegistry.refresh();\n\t\t\tconst loadError = this.modelRegistry.getError();\n\t\t\tif (loadError) {\n\t\t\t\tthis.errorMessage = loadError;\n\t\t\t}\n\t\t}\n\n\t\t// Load available models (built-in models still work even if models.json failed)\n\t\tlet availableModels: ReadonlyArray<Model<any>>;\n\t\ttry {\n\t\t\tavailableModels =\n\t\t\t\tthis.availableModels !== undefined ? this.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.errorMessage = error instanceof Error ? error.message : String(error);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.allModels = this.sortModels(models);\n\t\tconst availableModelsById = new Map(availableModels.map((model) => [`${model.provider}/${model.id}`, model]));\n\t\tthis.scopedModels = this.scopedModels.map((scoped) => {\n\t\t\tconst scopedModelId = `${scoped.model.provider}/${scoped.model.id}`;\n\t\t\tconst refreshed =\n\t\t\t\tavailableModelsById.get(scopedModelId) ??\n\t\t\t\t(this.availableModels !== undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: this.modelRegistry.find(scoped.model.provider, scoped.model.id));\n\t\t\treturn refreshed ? { ...scoped, model: refreshed } : scoped;\n\t\t});\n\t\tthis.scopedModelItems = this.scopedModels.map((scoped) => ({\n\t\t\tprovider: scoped.model.provider,\n\t\t\tid: scoped.model.id,\n\t\t\tmodel: scoped.model,\n\t\t}));\n\t\tthis.activeModels = this.scope === \"scoped\" ? this.scopedModelItems : this.allModels;\n\t\tthis.filteredModels = this.activeModels;\n\t\tconst currentIndex = this.filteredModels.findIndex((item) => modelsAreEqual(this.currentModel, item.model));\n\t\tthis.selectedIndex =\n\t\t\tcurrentIndex >= 0 ? currentIndex : Math.min(this.selectedIndex, Math.max(0, this.getSelectableCount() - 1));\n\t}\n\n\tprivate getModelKey(item: ModelItem): string {\n\t\treturn `${item.provider}/${item.id}`;\n\t}\n\n\tprivate getSelectedModelKey(): string | undefined {\n\t\tconst selected = this.filteredModels[this.selectedIndex];\n\t\treturn selected ? this.getModelKey(selected) : undefined;\n\t}\n\n\tprivate recentRankOf(item: ModelItem): number {\n\t\t// Finite sentinel so subtracting two non-recent ranks yields 0, not NaN.\n\t\treturn this.recentRank.get(`${item.provider}/${item.id}`) ?? Number.MAX_SAFE_INTEGER;\n\t}\n\n\tprivate isProviderConfigured(item: ModelItem): boolean {\n\t\treturn this.configuredProviders?.has(item.provider) || this.modelRegistry.hasConfiguredAuth(item.model);\n\t}\n\n\tprivate sortModels(models: ModelItem[]): ModelItem[] {\n\t\tconst sorted = [...models];\n\t\tsorted.sort((a, b) => {\n\t\t\tconst configuredDiff = Number(this.isProviderConfigured(b)) - Number(this.isProviderConfigured(a));\n\t\t\tif (configuredDiff !== 0) return configuredDiff;\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 aIsCurrent ? -1 : 1;\n\t\t\tconst rankDiff = this.recentRankOf(a) - this.recentRankOf(b);\n\t\t\tif (rankDiff !== 0) return rankDiff;\n\t\t\tconst providerDiff = a.provider.localeCompare(b.provider);\n\t\t\tif (providerDiff !== 0) return providerDiff;\n\t\t\tconst aFeatured = a.model.featured === true;\n\t\t\tconst bFeatured = b.model.featured === true;\n\t\t\tif (aFeatured !== bFeatured) return aFeatured ? -1 : 1;\n\t\t\treturn a.id.localeCompare(b.id, undefined, { numeric: true });\n\t\t});\n\t\treturn sorted;\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(\"app.model.toggleScope\", \"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\t\tconst currentIndex = this.activeModels.findIndex((item) => modelsAreEqual(this.currentModel, item.model));\n\t\tthis.selectedIndex = currentIndex >= 0 ? currentIndex : 0;\n\t\tthis.filterModels(this.searchInput.getValue());\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\tconst queryChanged = query !== this.searchQuery;\n\t\tthis.searchQuery = query;\n\t\tif (query.trim()) {\n\t\t\tconst matches = this.activeModels.flatMap((item) => {\n\t\t\t\tconst match = scoreModelSearch(item, query);\n\t\t\t\treturn match ? [{ item, ...match }] : [];\n\t\t\t});\n\t\t\tmatches.sort(\n\t\t\t\t(a, b) =>\n\t\t\t\t\ta.quality - b.quality ||\n\t\t\t\t\ta.score - b.score ||\n\t\t\t\t\tNumber(this.isProviderConfigured(b.item)) - Number(this.isProviderConfigured(a.item)) ||\n\t\t\t\t\tNumber(modelsAreEqual(this.currentModel, b.item.model)) -\n\t\t\t\t\t\tNumber(modelsAreEqual(this.currentModel, a.item.model)) ||\n\t\t\t\t\tthis.recentRankOf(a.item) - this.recentRankOf(b.item) ||\n\t\t\t\t\tthis.getModelKey(a.item).localeCompare(this.getModelKey(b.item), undefined, { numeric: true }),\n\t\t\t);\n\t\t\tthis.filteredModels = matches.map(({ item }) => item);\n\t\t} else {\n\t\t\tthis.filteredModels = this.activeModels;\n\t\t}\n\t\tthis.selectedIndex = queryChanged ? 0 : Math.min(this.selectedIndex, Math.max(0, this.getSelectableCount() - 1));\n\t\tthis.updateList();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst previousLayoutKey = this.responsiveLayoutKey;\n\t\tthis.updateResponsiveLayout();\n\t\tif (this.responsiveLayoutKey !== previousLayoutKey) {\n\t\t\tthis.updateList();\n\t\t}\n\t\treturn super.render(width);\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.updateResponsiveLayout();\n\t\tthis.listContainer.clear();\n\n\t\tconst maxVisible = this.listLayout.visibleItems;\n\t\tconst selectedModelIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(selectedModelIndex - Math.floor(maxVisible / 2), this.filteredModels.length - maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.filteredModels.length);\n\n\t\t// Show visible slice of filtered models\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.selectedIndex;\n\t\t\tconst isCurrent = modelsAreEqual(this.currentModel, item.model);\n\t\t\tconst isConfigured = this.isProviderConfigured(item);\n\t\t\tconst meta = isConfigured\n\t\t\t\t? isCurrent\n\t\t\t\t\t? theme.fg(\"success\", \"current\")\n\t\t\t\t\t: undefined\n\t\t\t\t: theme.fg(\"warning\", isCurrent ? \"current · sign in\" : \"sign in\");\n\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew MenuRow({\n\t\t\t\t\tprimary: item.id,\n\t\t\t\t\tsecondary: item.provider,\n\t\t\t\t\tmeta,\n\t\t\t\t\tselected: isSelected,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\t// Add scroll indicator if needed\n\t\tif (startIndex > 0 || endIndex < this.filteredModels.length) {\n\t\t\tconst scrollInfo = theme.fg(\"muted\", ` (${selectedModelIndex + 1}/${this.filteredModels.length})`);\n\t\t\tthis.listContainer.addChild(new Text(scrollInfo, 0, 0));\n\t\t}\n\n\t\t// Show error message or \"no results\" if empty\n\t\tif (this.errorMessage) {\n\t\t\t// Show error in red\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} else if (this.filteredModels.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \"No matching models\"), 0, 0));\n\t\t} else {\n\t\t\tconst selected = this.filteredModels[this.selectedIndex];\n\t\t\tif (selected && this.shouldShowSelectedDetails()) {\n\t\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", selected.model.name), 0, 0));\n\t\t\t}\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (kb.matches(keyData, \"app.model.toggleScope\")) {\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\t\t// Up arrow - wrap to bottom when at top\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tconst selectableCount = this.getSelectableCount();\n\t\t\tif (selectableCount === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? selectableCount - 1 : this.selectedIndex - 1;\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Down arrow - wrap to top when at bottom\n\t\telse if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tconst selectableCount = this.getSelectableCount();\n\t\t\tif (selectableCount === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === selectableCount - 1 ? 0 : this.selectedIndex + 1;\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Enter\n\t\telse if (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tthis.handleConfirm();\n\t\t}\n\t\t// Escape / Ctrl+C, or left arrow when the search field is at its start\n\t\telse if (kb.matches(keyData, \"tui.select.cancel\") || shouldTreatAsBack(keyData, this.searchInput)) {\n\t\t\tthis.onCancelCallback();\n\t\t}\n\t\t// Pass everything else to search input\n\t\telse {\n\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\tthis.filterModels(this.searchInput.getValue());\n\t\t}\n\t}\n\n\tprivate handleSelect(model: Model<any>): void {\n\t\tthis.onSelectCallback(model);\n\t}\n\n\tprivate handleConfirm(): void {\n\t\tconst selectedModel = this.filteredModels[this.selectedIndex];\n\t\tif (selectedModel) {\n\t\t\tthis.handleSelect(selectedModel.model);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tprivate getSelectableCount(): number {\n\t\treturn this.filteredModels.length;\n\t}\n\n\tgetSearchInput(): MenuSearchInput {\n\t\treturn this.searchInput;\n\t}\n\n\tprivate updateResponsiveLayout(): void {\n\t\tconst showHeaderHelp = this.shouldShowHeaderHelp();\n\t\tlet headerHelpRows = 0;\n\t\tthis.headerHelpContainer.clear();\n\t\tif (showHeaderHelp) {\n\t\t\tif (this.scopeText && this.scopeHintText) {\n\t\t\t\tthis.headerHelpContainer.addChild(this.scopeText);\n\t\t\t\tthis.headerHelpContainer.addChild(this.scopeHintText);\n\t\t\t\theaderHelpRows += 2;\n\t\t\t} else if (this.warningText) {\n\t\t\t\tthis.headerHelpContainer.addChild(this.warningText);\n\t\t\t\theaderHelpRows += 1;\n\t\t\t}\n\t\t\tthis.headerHelpContainer.addChild(new Spacer(1));\n\t\t\theaderHelpRows += 1;\n\t\t}\n\n\t\tconst headerRows = this.getHeaderRows();\n\t\tconst reservedRows =\n\t\t\tMODEL_LIST_RESERVED_ROWS.base +\n\t\t\theaderRows +\n\t\t\theaderHelpRows +\n\t\t\t(this.shouldShowSelectedDetails() ? MODEL_LIST_RESERVED_ROWS.detail : 0);\n\t\tthis.listLayout = getMenuListLayout({\n\t\t\tgetRows: this.viewport.getRows,\n\t\t\tpreferredVisibleItems: PREFERRED_VISIBLE_MODELS,\n\t\t\ttotalItems: this.filteredModels.length,\n\t\t\treservedRows,\n\t\t\tcomfortableItemRows: 3,\n\t\t\tcompactItemRows: 2,\n\t\t\tscrollIndicatorRows: MODEL_SCROLL_INDICATOR_ROWS,\n\t\t});\n\t\tthis.responsiveLayoutKey = [\n\t\t\theaderRows,\n\t\t\tshowHeaderHelp ? \"help\" : \"no-help\",\n\t\t\theaderHelpRows,\n\t\t\tthis.shouldShowSelectedDetails() ? \"detail\" : \"no-detail\",\n\t\t\tthis.listLayout.compact ? \"compact\" : \"comfortable\",\n\t\t\tthis.listLayout.visibleItems,\n\t\t].join(\":\");\n\t}\n\n\tprivate shouldShowHeaderHelp(): boolean {\n\t\treturn this.hasRows(MODEL_HELP_MIN_ROWS);\n\t}\n\n\tprivate shouldShowSelectedDetails(): boolean {\n\t\treturn this.hasRows(MODEL_DETAIL_MIN_ROWS);\n\t}\n\n\tprivate hasRows(minRows: number): boolean {\n\t\tconst rows = this.viewport.getRows?.();\n\t\treturn rows === undefined || !Number.isFinite(rows) || rows >= minRows;\n\t}\n}\n"]}
|
|
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 \"@ponythewhite/base-context-ai\";\nimport {\n\ttype Component,\n\tContainer,\n\ttype Focusable,\n\tfuzzyMatch,\n\tgetKeybindings,\n\tSpacer,\n\tText,\n\ttype TUI,\n} from \"@ponythewhite/base-context-tui\";\nimport type { ModelRegistry } from \"../../../core/model-registry.js\";\nimport { theme } from \"../theme/theme.js\";\nimport { keyHint } from \"./keybinding-hints.js\";\nimport {\n\tgetMenuListLayout,\n\tMenuList,\n\tMenuPanel,\n\tMenuRow,\n\tMenuSearchInput,\n\ttype MenuViewportProvider,\n} from \"./menu-panel.js\";\nimport { shouldTreatAsBack } from \"./modal-back.js\";\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\nenum ModelSearchMatchQuality {\n\tExactShortId,\n\tExactFullId,\n\tPrefixOrToken,\n\tFuzzy,\n}\n\ninterface ModelSearchMatch {\n\tquality: ModelSearchMatchQuality;\n\tscore: number;\n}\n\nfunction normalizeModelSearchText(value: string): string {\n\treturn value.toLowerCase().replace(/[\\s\\-_.:/]+/g, \"\");\n}\n\nfunction getModelSearchFields(item: ModelItem): { shortId: string; fullIds: string[]; all: string[] } {\n\tconst shortId = item.id.slice(item.id.lastIndexOf(\"/\") + 1);\n\tconst fullIds = [item.id, `${item.provider}/${item.id}`];\n\treturn {\n\t\tshortId,\n\t\tfullIds,\n\t\tall: [shortId, ...fullIds, item.model.name, item.provider],\n\t};\n}\n\nfunction getBestFuzzyScore(queryTokens: string[], fields: string[]): number | null {\n\tlet total = 0;\n\tfor (const token of queryTokens) {\n\t\tlet best = Number.POSITIVE_INFINITY;\n\t\tfor (const field of fields) {\n\t\t\tconst match = fuzzyMatch(token, field);\n\t\t\tif (match.matches) best = Math.min(best, match.score);\n\t\t}\n\t\tif (!Number.isFinite(best)) return null;\n\t\ttotal += best;\n\t}\n\treturn total;\n}\n\nfunction scoreModelSearch(item: ModelItem, query: string): ModelSearchMatch | null {\n\tconst queryTokens = query.trim().split(/\\s+/);\n\tconst normalizedQuery = normalizeModelSearchText(query);\n\tconst normalizedTokens = queryTokens.map(normalizeModelSearchText).filter(Boolean);\n\tif (!normalizedQuery || normalizedTokens.length === 0) return null;\n\n\tconst fields = getModelSearchFields(item);\n\tif (normalizeModelSearchText(fields.shortId) === normalizedQuery) {\n\t\treturn { quality: ModelSearchMatchQuality.ExactShortId, score: 0 };\n\t}\n\tif (fields.fullIds.some((field) => normalizeModelSearchText(field) === normalizedQuery)) {\n\t\treturn { quality: ModelSearchMatchQuality.ExactFullId, score: 0 };\n\t}\n\n\tconst normalizedFields = fields.all.map(normalizeModelSearchText);\n\tconst fieldTokens = fields.all\n\t\t.flatMap((field) => field.split(/[\\s/_-]+/))\n\t\t.map(normalizeModelSearchText)\n\t\t.filter(Boolean);\n\tconst fuzzyScore = getBestFuzzyScore(normalizedTokens, normalizedFields);\n\tconst isPrefixOrToken = normalizedTokens.every(\n\t\t(token) =>\n\t\t\tnormalizedFields.some((field) => field.startsWith(token)) ||\n\t\t\tfieldTokens.some((field) => field.startsWith(token)),\n\t);\n\tif (isPrefixOrToken && fuzzyScore !== null) {\n\t\treturn { quality: ModelSearchMatchQuality.PrefixOrToken, score: fuzzyScore };\n\t}\n\treturn fuzzyScore === null ? null : { quality: ModelSearchMatchQuality.Fuzzy, score: fuzzyScore };\n}\n\nexport interface ModelSelectorOptions {\n\tavailableModels?: ReadonlyArray<Model<any>>;\n\tconfiguredProviders?: ReadonlySet<string>;\n\theader?: Component;\n\tgetHeaderRows?: () => number;\n\tsubtitle?: string;\n\tgetRows?: () => number;\n\trecentModels?: ReadonlyArray<string>;\n}\n\ntype ModelScope = \"all\" | \"scoped\";\n\nconst PREFERRED_VISIBLE_MODELS = 10;\nconst MODEL_LIST_RESERVED_ROWS = {\n\tbase: 7,\n\tdetail: 2,\n};\nconst MODEL_SCROLL_INDICATOR_ROWS = 1;\nconst MODEL_HELP_MIN_ROWS = 12;\nconst MODEL_DETAIL_MIN_ROWS = 14;\n\n/**\n * Component that renders a model selector with search\n */\nexport class ModelSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: MenuSearchInput;\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\tprivate filteredModels: ModelItem[] = [];\n\tprivate selectedIndex: number = 0;\n\tprivate searchQuery = \"\";\n\tprivate currentModel?: Model<any>;\n\tprivate modelRegistry: ModelRegistry;\n\tprivate onSelectCallback: (model: Model<any>) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate availableModels?: ReadonlyArray<Model<any>>;\n\tprivate configuredProviders?: ReadonlySet<string>;\n\tprivate providerFilter?: string;\n\tprivate recentRank: Map<string, number>;\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\tprivate panel: MenuPanel;\n\tprivate headerHelpContainer: Container;\n\tprivate warningText?: Text;\n\tprivate listLayout = getMenuListLayout({\n\t\tpreferredVisibleItems: PREFERRED_VISIBLE_MODELS,\n\t\treservedRows: MODEL_LIST_RESERVED_ROWS.base,\n\t\tcomfortableItemRows: 3,\n\t\tcompactItemRows: 2,\n\t});\n\tprivate responsiveLayoutKey = \"\";\n\tprivate readonly viewport: MenuViewportProvider;\n\tprivate readonly getHeaderRows: () => number;\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tcurrentModel: Model<any> | undefined,\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\toptions: ModelSelectorOptions = {},\n\t) {\n\t\tsuper();\n\n\t\tthis.tui = tui;\n\t\tthis.currentModel = currentModel;\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\t\tthis.availableModels = options.availableModels;\n\t\tthis.configuredProviders = options.configuredProviders;\n\t\tthis.recentRank = new Map((options.recentModels ?? []).map((key, i) => [key, i]));\n\t\tthis.viewport = { getRows: options.getRows };\n\t\tthis.getHeaderRows = options.header ? (options.getHeaderRows ?? (() => 2)) : () => 0;\n\n\t\tthis.panel = new MenuPanel({\n\t\t\ttitle: \"Models\",\n\t\t\tsubtitle: options.subtitle ?? \"All models across supported providers.\",\n\t\t});\n\t\tthis.addChild(this.panel);\n\t\tif (options.header) {\n\t\t\tthis.panel.addChild(options.header);\n\t\t\tthis.panel.addChild(new Spacer(1));\n\t\t}\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.scopeHintText = new Text(this.getScopeHintText(), 0, 0);\n\t\t} else {\n\t\t\tconst hintText = \"Signed-in providers first. Other models prompt sign-in.\";\n\t\t\tthis.warningText = new Text(theme.fg(\"muted\", hintText), 0, 0);\n\t\t}\n\t\tthis.headerHelpContainer = new Container();\n\t\tthis.panel.addChild(this.headerHelpContainer);\n\n\t\t// Create search input\n\t\tthis.searchInput = new MenuSearchInput(\"Search models\");\n\t\tif (initialSearchInput) {\n\t\t\tthis.searchInput.setValue(initialSearchInput);\n\t\t}\n\t\tthis.searchInput.onSubmit = () => {\n\t\t\tthis.handleConfirm();\n\t\t};\n\t\tthis.panel.addChild(this.searchInput);\n\n\t\tthis.panel.addChild(new Spacer(1));\n\n\t\t// Create list container\n\t\tthis.listContainer = new MenuList({ compact: () => this.listLayout.compact });\n\t\tthis.panel.addChild(this.listContainer);\n\t\tthis.updateResponsiveLayout();\n\n\t\tthis.loadModels();\n\t\tif (initialSearchInput) {\n\t\t\tthis.filterModels(initialSearchInput);\n\t\t} else {\n\t\t\tthis.updateList();\n\t\t}\n\t\tthis.tui.requestRender();\n\t}\n\n\tsetProviderFilter(provider: string): void {\n\t\tthis.providerFilter = provider;\n\t\tthis.scope = \"all\";\n\t\tthis.panel.setTitle(`Models: ${provider}`);\n\t\tif (this.scopeText) this.scopeText.setText(this.getScopeText());\n\t\tthis.updateState(this.currentModel);\n\t}\n\n\tupdateAvailableModels(availableModels: ReadonlyArray<Model<any>>): void {\n\t\tthis.updateState(this.currentModel, availableModels);\n\t}\n\n\tupdateState(\n\t\tcurrentModel: Model<any> | undefined,\n\t\tavailableModels = this.availableModels,\n\t\tconfiguredProviders = this.configuredProviders,\n\t): void {\n\t\tthis.currentModel = currentModel;\n\t\tthis.availableModels = availableModels;\n\t\tthis.configuredProviders = configuredProviders;\n\t\tconst query = this.searchInput.getValue();\n\t\tconst selectedKey = this.getSelectedModelKey();\n\n\t\tthis.loadModels();\n\t\tthis.filterModels(query);\n\n\t\tif (selectedKey) {\n\t\t\tconst selectedIndex = this.filteredModels.findIndex((item) => this.getModelKey(item) === selectedKey);\n\t\t\tif (selectedIndex >= 0) {\n\t\t\t\tthis.selectedIndex = selectedIndex;\n\t\t\t\tthis.updateList();\n\t\t\t}\n\t\t}\n\n\t\tthis.tui.requestRender();\n\t}\n\n\tprivate loadModels(): void {\n\t\tlet models: ModelItem[];\n\t\tthis.errorMessage = undefined;\n\n\t\tif (this.availableModels === undefined) {\n\t\t\tthis.modelRegistry.refresh();\n\t\t\tconst loadError = this.modelRegistry.getError();\n\t\t\tif (loadError) {\n\t\t\t\tthis.errorMessage = loadError;\n\t\t\t}\n\t\t}\n\n\t\t// Load available models (built-in models still work even if models.json failed)\n\t\tlet availableModels: ReadonlyArray<Model<any>>;\n\t\ttry {\n\t\t\tavailableModels =\n\t\t\t\tthis.availableModels !== undefined ? this.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.errorMessage = error instanceof Error ? error.message : String(error);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.allModels = this.sortModels(\n\t\t\tmodels.filter((model) => this.providerFilter === undefined || model.provider === this.providerFilter),\n\t\t);\n\t\tconst availableModelsById = new Map(availableModels.map((model) => [`${model.provider}/${model.id}`, model]));\n\t\tthis.scopedModels = this.scopedModels.map((scoped) => {\n\t\t\tconst scopedModelId = `${scoped.model.provider}/${scoped.model.id}`;\n\t\t\tconst refreshed =\n\t\t\t\tavailableModelsById.get(scopedModelId) ??\n\t\t\t\t(this.availableModels !== undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: this.modelRegistry.find(scoped.model.provider, scoped.model.id));\n\t\t\treturn refreshed ? { ...scoped, model: refreshed } : scoped;\n\t\t});\n\t\tthis.scopedModelItems = this.scopedModels\n\t\t\t.filter((scoped) => this.providerFilter === undefined || scoped.model.provider === this.providerFilter)\n\t\t\t.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\tthis.activeModels = this.scope === \"scoped\" ? this.scopedModelItems : this.allModels;\n\t\tthis.filteredModels = this.activeModels;\n\t\tconst currentIndex = this.filteredModels.findIndex((item) => modelsAreEqual(this.currentModel, item.model));\n\t\tthis.selectedIndex =\n\t\t\tcurrentIndex >= 0 ? currentIndex : Math.min(this.selectedIndex, Math.max(0, this.getSelectableCount() - 1));\n\t}\n\n\tprivate getModelKey(item: ModelItem): string {\n\t\treturn `${item.provider}/${item.id}`;\n\t}\n\n\tprivate getSelectedModelKey(): string | undefined {\n\t\tconst selected = this.filteredModels[this.selectedIndex];\n\t\treturn selected ? this.getModelKey(selected) : undefined;\n\t}\n\n\tprivate recentRankOf(item: ModelItem): number {\n\t\t// Finite sentinel so subtracting two non-recent ranks yields 0, not NaN.\n\t\treturn this.recentRank.get(`${item.provider}/${item.id}`) ?? Number.MAX_SAFE_INTEGER;\n\t}\n\n\tprivate isProviderConfigured(item: ModelItem): boolean {\n\t\treturn this.configuredProviders?.has(item.provider) || this.modelRegistry.hasConfiguredAuth(item.model);\n\t}\n\n\tprivate sortModels(models: ModelItem[]): ModelItem[] {\n\t\tconst sorted = [...models];\n\t\tsorted.sort((a, b) => {\n\t\t\tconst configuredDiff = Number(this.isProviderConfigured(b)) - Number(this.isProviderConfigured(a));\n\t\t\tif (configuredDiff !== 0) return configuredDiff;\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 aIsCurrent ? -1 : 1;\n\t\t\tconst rankDiff = this.recentRankOf(a) - this.recentRankOf(b);\n\t\t\tif (rankDiff !== 0) return rankDiff;\n\t\t\tconst providerDiff = a.provider.localeCompare(b.provider);\n\t\t\tif (providerDiff !== 0) return providerDiff;\n\t\t\tconst aFeatured = a.model.featured === true;\n\t\t\tconst bFeatured = b.model.featured === true;\n\t\t\tif (aFeatured !== bFeatured) return aFeatured ? -1 : 1;\n\t\t\treturn a.id.localeCompare(b.id, undefined, { numeric: true });\n\t\t});\n\t\treturn sorted;\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(\"app.model.toggleScope\", \"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\t\tconst currentIndex = this.activeModels.findIndex((item) => modelsAreEqual(this.currentModel, item.model));\n\t\tthis.selectedIndex = currentIndex >= 0 ? currentIndex : 0;\n\t\tthis.filterModels(this.searchInput.getValue());\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\tconst queryChanged = query !== this.searchQuery;\n\t\tthis.searchQuery = query;\n\t\tif (query.trim()) {\n\t\t\tconst matches = this.activeModels.flatMap((item) => {\n\t\t\t\tconst match = scoreModelSearch(item, query);\n\t\t\t\treturn match ? [{ item, ...match }] : [];\n\t\t\t});\n\t\t\tmatches.sort(\n\t\t\t\t(a, b) =>\n\t\t\t\t\ta.quality - b.quality ||\n\t\t\t\t\ta.score - b.score ||\n\t\t\t\t\tNumber(this.isProviderConfigured(b.item)) - Number(this.isProviderConfigured(a.item)) ||\n\t\t\t\t\tNumber(modelsAreEqual(this.currentModel, b.item.model)) -\n\t\t\t\t\t\tNumber(modelsAreEqual(this.currentModel, a.item.model)) ||\n\t\t\t\t\tthis.recentRankOf(a.item) - this.recentRankOf(b.item) ||\n\t\t\t\t\tthis.getModelKey(a.item).localeCompare(this.getModelKey(b.item), undefined, { numeric: true }),\n\t\t\t);\n\t\t\tthis.filteredModels = matches.map(({ item }) => item);\n\t\t} else {\n\t\t\tthis.filteredModels = this.activeModels;\n\t\t}\n\t\tthis.selectedIndex = queryChanged ? 0 : Math.min(this.selectedIndex, Math.max(0, this.getSelectableCount() - 1));\n\t\tthis.updateList();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst previousLayoutKey = this.responsiveLayoutKey;\n\t\tthis.updateResponsiveLayout();\n\t\tif (this.responsiveLayoutKey !== previousLayoutKey) {\n\t\t\tthis.updateList();\n\t\t}\n\t\treturn super.render(width);\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.updateResponsiveLayout();\n\t\tthis.listContainer.clear();\n\n\t\tconst maxVisible = this.listLayout.visibleItems;\n\t\tconst selectedModelIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(selectedModelIndex - Math.floor(maxVisible / 2), this.filteredModels.length - maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.filteredModels.length);\n\n\t\t// Show visible slice of filtered models\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.selectedIndex;\n\t\t\tconst isCurrent = modelsAreEqual(this.currentModel, item.model);\n\t\t\tconst isConfigured = this.isProviderConfigured(item);\n\t\t\tconst meta = isConfigured\n\t\t\t\t? isCurrent\n\t\t\t\t\t? theme.fg(\"success\", \"current\")\n\t\t\t\t\t: undefined\n\t\t\t\t: theme.fg(\"warning\", isCurrent ? \"current · sign in\" : \"sign in\");\n\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew MenuRow({\n\t\t\t\t\tprimary: item.id,\n\t\t\t\t\tsecondary: item.provider,\n\t\t\t\t\tmeta,\n\t\t\t\t\tselected: isSelected,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\t// Add scroll indicator if needed\n\t\tif (startIndex > 0 || endIndex < this.filteredModels.length) {\n\t\t\tconst scrollInfo = theme.fg(\"muted\", ` (${selectedModelIndex + 1}/${this.filteredModels.length})`);\n\t\t\tthis.listContainer.addChild(new Text(scrollInfo, 0, 0));\n\t\t}\n\n\t\t// Show error message or \"no results\" if empty\n\t\tif (this.errorMessage) {\n\t\t\t// Show error in red\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} else if (this.filteredModels.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \"No matching models\"), 0, 0));\n\t\t} else {\n\t\t\tconst selected = this.filteredModels[this.selectedIndex];\n\t\t\tif (selected && this.shouldShowSelectedDetails()) {\n\t\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", selected.model.name), 0, 0));\n\t\t\t}\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (kb.matches(keyData, \"app.model.toggleScope\")) {\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\t\t// Up arrow - wrap to bottom when at top\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tconst selectableCount = this.getSelectableCount();\n\t\t\tif (selectableCount === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? selectableCount - 1 : this.selectedIndex - 1;\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Down arrow - wrap to top when at bottom\n\t\telse if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tconst selectableCount = this.getSelectableCount();\n\t\t\tif (selectableCount === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === selectableCount - 1 ? 0 : this.selectedIndex + 1;\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Enter\n\t\telse if (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tthis.handleConfirm();\n\t\t}\n\t\t// Escape / Ctrl+C, or left arrow when the search field is at its start\n\t\telse if (kb.matches(keyData, \"tui.select.cancel\") || shouldTreatAsBack(keyData, this.searchInput)) {\n\t\t\tthis.onCancelCallback();\n\t\t}\n\t\t// Pass everything else to search input\n\t\telse {\n\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\tthis.filterModels(this.searchInput.getValue());\n\t\t}\n\t}\n\n\tprivate handleSelect(model: Model<any>): void {\n\t\tthis.onSelectCallback(model);\n\t}\n\n\tprivate handleConfirm(): void {\n\t\tconst selectedModel = this.filteredModels[this.selectedIndex];\n\t\tif (selectedModel) {\n\t\t\tthis.handleSelect(selectedModel.model);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tprivate getSelectableCount(): number {\n\t\treturn this.filteredModels.length;\n\t}\n\n\tgetSearchInput(): MenuSearchInput {\n\t\treturn this.searchInput;\n\t}\n\n\tprivate updateResponsiveLayout(): void {\n\t\tconst showHeaderHelp = this.shouldShowHeaderHelp();\n\t\tlet headerHelpRows = 0;\n\t\tthis.headerHelpContainer.clear();\n\t\tif (showHeaderHelp) {\n\t\t\tif (this.scopeText && this.scopeHintText) {\n\t\t\t\tthis.headerHelpContainer.addChild(this.scopeText);\n\t\t\t\tthis.headerHelpContainer.addChild(this.scopeHintText);\n\t\t\t\theaderHelpRows += 2;\n\t\t\t} else if (this.warningText) {\n\t\t\t\tthis.headerHelpContainer.addChild(this.warningText);\n\t\t\t\theaderHelpRows += 1;\n\t\t\t}\n\t\t\tthis.headerHelpContainer.addChild(new Spacer(1));\n\t\t\theaderHelpRows += 1;\n\t\t}\n\n\t\tconst headerRows = this.getHeaderRows();\n\t\tconst reservedRows =\n\t\t\tMODEL_LIST_RESERVED_ROWS.base +\n\t\t\theaderRows +\n\t\t\theaderHelpRows +\n\t\t\t(this.shouldShowSelectedDetails() ? MODEL_LIST_RESERVED_ROWS.detail : 0);\n\t\tthis.listLayout = getMenuListLayout({\n\t\t\tgetRows: this.viewport.getRows,\n\t\t\tpreferredVisibleItems: PREFERRED_VISIBLE_MODELS,\n\t\t\ttotalItems: this.filteredModels.length,\n\t\t\treservedRows,\n\t\t\tcomfortableItemRows: 3,\n\t\t\tcompactItemRows: 2,\n\t\t\tscrollIndicatorRows: MODEL_SCROLL_INDICATOR_ROWS,\n\t\t});\n\t\tthis.responsiveLayoutKey = [\n\t\t\theaderRows,\n\t\t\tshowHeaderHelp ? \"help\" : \"no-help\",\n\t\t\theaderHelpRows,\n\t\t\tthis.shouldShowSelectedDetails() ? \"detail\" : \"no-detail\",\n\t\t\tthis.listLayout.compact ? \"compact\" : \"comfortable\",\n\t\t\tthis.listLayout.visibleItems,\n\t\t].join(\":\");\n\t}\n\n\tprivate shouldShowHeaderHelp(): boolean {\n\t\treturn this.hasRows(MODEL_HELP_MIN_ROWS);\n\t}\n\n\tprivate shouldShowSelectedDetails(): boolean {\n\t\treturn this.hasRows(MODEL_DETAIL_MIN_ROWS);\n\t}\n\n\tprivate hasRows(minRows: number): boolean {\n\t\tconst rows = this.viewport.getRows?.();\n\t\treturn rows === undefined || !Number.isFinite(rows) || rows >= minRows;\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/oauth-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Component,\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tgetKeybindings,\n\tSpacer,\n\tTruncatedText,\n} from \"@ponythewhite/base-context-tui\";\nimport type { AuthStatus, AuthStorage } from \"../../../core/auth-storage.js\";\nimport { PRIME_INFERENCE_PROVIDER_ID } from \"../../../core/prime-inference-auth.js\";\nimport { getProviderAuthContract } from \"../../../core/provider-contracts.js\";\nimport { theme } from \"../theme/theme.js\";\nimport {\n\tgetMenuListLayout,\n\tMenuList,\n\tMenuPanel,\n\tMenuRow,\n\tMenuSearchInput,\n\ttype MenuViewportProvider,\n} from \"./menu-panel.js\";\n\nexport type AuthSelectorCategory = \"provider\" | \"service\";\n\nexport type AuthSelectorProvider = {\n\tid: string;\n\tname: string;\n\tauthType: \"oauth\" | \"api_key\";\n\t/** Which tab the entry belongs to. Defaults to \"provider\" when omitted. */\n\tcategory?: AuthSelectorCategory;\n};\n\nexport interface OAuthSelectorOptions extends MenuViewportProvider {\n\tinitialCategory?: AuthSelectorCategory;\n\theader?: Component;\n\tgetHeaderRows?: () => number;\n\ttitle?: string;\n\tsubtitle?: string;\n\tsearchPlaceholder?: string;\n}\n\nexport function compareAuthSelectorProviders(a: AuthSelectorProvider, b: AuthSelectorProvider): number {\n\tif (a.authType !== b.authType) {\n\t\treturn a.authType === \"oauth\" ? -1 : 1;\n\t}\n\treturn a.name.localeCompare(b.name);\n}\n\nconst PREFERRED_VISIBLE_PROVIDERS = 8;\nconst PROVIDER_LIST_RESERVED_ROWS = 7;\n/** Extra fixed rows the Providers/MCP Connections tab bar (text + spacer) consumes. */\nconst TAB_BAR_RESERVED_ROWS = 2;\nconst PROVIDER_SCROLL_INDICATOR_ROWS = 1;\n\nexport class OAuthSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: MenuSearchInput;\n\n\t// Delegate focus to the search input so its IME cursor remains positioned correctly.\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\n\tprivate listContainer: Container;\n\tprivate tabBar?: TruncatedText;\n\tprivate allProviders: AuthSelectorProvider[];\n\tprivate filteredProviders: AuthSelectorProvider[];\n\tprivate selectedIndex: number = 0;\n\tprivate searchQuery = \"\";\n\tprivate mode: \"login\" | \"logout\";\n\t/** Tabs present in the data, in display order. Empty/single → no tab bar. */\n\tprivate categories: AuthSelectorCategory[] = [];\n\tprivate activeCategory: AuthSelectorCategory = \"provider\";\n\tprivate authStorage: AuthStorage;\n\tprivate getAuthStatus: (providerId: string) => AuthStatus;\n\tprivate onSelectCallback: (provider: AuthSelectorProvider) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate listLayout = getMenuListLayout({\n\t\tpreferredVisibleItems: PREFERRED_VISIBLE_PROVIDERS,\n\t\treservedRows: PROVIDER_LIST_RESERVED_ROWS,\n\t\tcomfortableItemRows: 3,\n\t\tcompactItemRows: 2,\n\t});\n\tprivate readonly viewport: MenuViewportProvider;\n\tprivate readonly getHeaderRows: () => number;\n\n\tconstructor(\n\t\tmode: \"login\" | \"logout\",\n\t\tauthStorage: AuthStorage,\n\t\tproviders: AuthSelectorProvider[],\n\t\tonSelect: (provider: AuthSelectorProvider) => void,\n\t\tonCancel: () => void,\n\t\tgetAuthStatus?: (providerId: string) => AuthStatus,\n\t\toptions: OAuthSelectorOptions = {},\n\t) {\n\t\tsuper();\n\n\t\tthis.mode = mode;\n\t\tthis.authStorage = authStorage;\n\t\tthis.getAuthStatus = getAuthStatus ?? ((providerId) => this.authStorage.getAuthStatus(providerId));\n\t\tthis.viewport = options;\n\t\tthis.getHeaderRows = options.header ? (options.getHeaderRows ?? (() => TAB_BAR_RESERVED_ROWS)) : () => 0;\n\t\tthis.allProviders = this.sortProviders(providers);\n\t\tthis.filteredProviders = this.allProviders;\n\t\tthis.onSelectCallback = onSelect;\n\t\tthis.onCancelCallback = onCancel;\n\n\t\tconst present = new Set(providers.map((p) => p.category ?? \"provider\"));\n\t\tthis.categories = ([\"provider\", \"service\"] as const).filter((c) => present.has(c));\n\t\tthis.activeCategory =\n\t\t\toptions.initialCategory && this.categories.includes(options.initialCategory)\n\t\t\t\t? options.initialCategory\n\t\t\t\t: (this.categories[0] ?? \"provider\");\n\n\t\tconst panel = new MenuPanel({\n\t\t\ttitle: options.title ?? (mode === \"login\" ? \"Providers\" : \"Saved Credentials\"),\n\t\t\tsubtitle:\n\t\t\t\toptions.subtitle ??\n\t\t\t\t(mode === \"login\" ? \"API keys; unvalidated OAuth unavailable.\" : \"Choose a credential to remove.\"),\n\t\t});\n\t\tthis.addChild(panel);\n\t\tif (options.header) {\n\t\t\tpanel.addChild(options.header);\n\t\t\tpanel.addChild(new Spacer(1));\n\t\t}\n\n\t\tif (this.categories.length > 1) {\n\t\t\tthis.tabBar = new TruncatedText(\"\");\n\t\t\tpanel.addChild(this.tabBar);\n\t\t\tpanel.addChild(new Spacer(1));\n\t\t}\n\n\t\tthis.searchInput = new MenuSearchInput(options.searchPlaceholder ?? \"Search providers\");\n\t\tthis.searchInput.onSubmit = () => {\n\t\t\tconst selectedProvider = this.filteredProviders[this.selectedIndex];\n\t\t\tif (selectedProvider) {\n\t\t\t\tthis.onSelectCallback(selectedProvider);\n\t\t\t}\n\t\t};\n\t\tpanel.addChild(this.searchInput);\n\t\tpanel.addChild(new Spacer(1));\n\n\t\tthis.listContainer = new MenuList({ compact: () => this.listLayout.compact });\n\t\tpanel.addChild(this.listContainer);\n\n\t\tthis.filterProviders(\"\");\n\t}\n\n\tprivate inActiveCategory(provider: AuthSelectorProvider): boolean {\n\t\treturn (provider.category ?? \"provider\") === this.activeCategory;\n\t}\n\n\tprivate switchCategory(direction: 1 | -1): void {\n\t\tif (this.categories.length < 2) return;\n\t\tconst current = this.categories.indexOf(this.activeCategory);\n\t\tconst next = (current + direction + this.categories.length) % this.categories.length;\n\t\tthis.activeCategory = this.categories[next];\n\t\tthis.selectedIndex = 0;\n\t\tthis.searchInput.setValue(\"\");\n\t\tthis.filterProviders(\"\");\n\t}\n\n\tprivate updateTabBar(): void {\n\t\tif (!this.tabBar) return;\n\t\tconst labels: Record<AuthSelectorCategory, string> = {\n\t\t\tprovider: \"Providers\",\n\t\t\tservice: \"MCP Connections\",\n\t\t};\n\t\tconst rendered = this.categories\n\t\t\t.map((category) =>\n\t\t\t\tcategory === this.activeCategory\n\t\t\t\t\t? theme.bold(theme.fg(\"accent\", labels[category]))\n\t\t\t\t\t: theme.fg(\"muted\", labels[category]),\n\t\t\t)\n\t\t\t.join(theme.fg(\"muted\", \" · \"));\n\t\tthis.tabBar.setText(`${rendered} ${theme.fg(\"muted\", \"←/→ switch\")}`);\n\t}\n\n\tprivate filterProviders(query: string): void {\n\t\tconst queryChanged = query !== this.searchQuery;\n\t\tthis.searchQuery = query;\n\t\tconst inCategory = this.allProviders.filter((p) => this.inActiveCategory(p));\n\t\tthis.filteredProviders = query\n\t\t\t? fuzzyFilter(inCategory, query, (provider) => `${provider.name} ${provider.id} ${provider.authType}`)\n\t\t\t: inCategory;\n\t\tthis.selectedIndex = queryChanged\n\t\t\t? 0\n\t\t\t: Math.max(0, Math.min(this.selectedIndex, Math.max(0, this.filteredProviders.length - 1)));\n\t\tthis.updateTabBar();\n\t\tthis.updateList();\n\t}\n\n\tprivate sortProviders(providers: AuthSelectorProvider[]): AuthSelectorProvider[] {\n\t\treturn [...providers].sort((a, b) => {\n\t\t\tconst rankDelta = this.getProviderSortRank(a) - this.getProviderSortRank(b);\n\t\t\tif (rankDelta !== 0) {\n\t\t\t\treturn rankDelta;\n\t\t\t}\n\t\t\tif (this.mode === \"login\" && a.id !== b.id) {\n\t\t\t\tif (a.id === PRIME_INFERENCE_PROVIDER_ID) return -1;\n\t\t\t\tif (b.id === PRIME_INFERENCE_PROVIDER_ID) return 1;\n\t\t\t}\n\t\t\treturn compareAuthSelectorProviders(a, b);\n\t\t});\n\t}\n\n\trefresh(): void {\n\t\tconst selected = this.filteredProviders[this.selectedIndex];\n\t\tthis.allProviders = this.sortProviders(this.allProviders);\n\t\tthis.filterProviders(this.searchInput.getValue());\n\t\tif (selected) {\n\t\t\tconst selectedIndex = this.filteredProviders.findIndex(\n\t\t\t\t(provider) => provider.id === selected.id && provider.authType === selected.authType,\n\t\t\t);\n\t\t\tif (selectedIndex >= 0) {\n\t\t\t\tthis.selectedIndex = selectedIndex;\n\t\t\t\tthis.updateList();\n\t\t\t}\n\t\t}\n\t}\n\n\tgetSearchInput(): MenuSearchInput {\n\t\treturn this.searchInput;\n\t}\n\n\tprivate getProviderSortRank(provider: AuthSelectorProvider): number {\n\t\tif (this.isProviderConfigured(provider)) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (this.isProviderStale(provider)) {\n\t\t\treturn 1;\n\t\t}\n\t\treturn 2;\n\t}\n\n\tprivate isProviderStale(provider: AuthSelectorProvider): boolean {\n\t\tconst status = this.getAuthStatus(provider.id);\n\t\tconst credential = this.authStorage.get(provider.id);\n\t\tconst storageStatus = this.authStorage.getAuthStatus(provider.id);\n\t\treturn status.source === \"stale\" || (storageStatus.source === \"stale\" && credential?.type === provider.authType);\n\t}\n\n\tprivate isProviderConfigured(provider: AuthSelectorProvider): boolean {\n\t\tconst status = this.getAuthStatus(provider.id);\n\t\tconst credential = this.authStorage.get(provider.id);\n\t\tif (this.isProviderStale(provider)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (status.source && status.source !== \"stored\") {\n\t\t\treturn provider.authType === \"api_key\";\n\t\t}\n\n\t\tif (credential) {\n\t\t\treturn status.configured;\n\t\t}\n\t\tif (provider.authType !== \"api_key\") {\n\t\t\treturn false;\n\t\t}\n\t\treturn status.source !== undefined;\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst previousLayout = this.listLayout;\n\t\tthis.updateLayout();\n\t\tif (\n\t\t\tthis.listLayout.compact !== previousLayout.compact ||\n\t\t\tthis.listLayout.visibleItems !== previousLayout.visibleItems\n\t\t) {\n\t\t\tthis.updateList();\n\t\t}\n\t\treturn super.render(width);\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.updateLayout();\n\t\tthis.listContainer.clear();\n\n\t\tconst maxVisible = this.listLayout.visibleItems;\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(maxVisible / 2), this.filteredProviders.length - maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.filteredProviders.length);\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst provider = this.filteredProviders[i];\n\t\t\tif (!provider) continue;\n\n\t\t\tconst isSelected = i === this.selectedIndex;\n\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew MenuRow({\n\t\t\t\t\tprimary: provider.name,\n\t\t\t\t\tsecondary: provider.authType === \"oauth\" ? \"subscription\" : \"api key\",\n\t\t\t\t\tmeta: this.formatStatusIndicator(provider),\n\t\t\t\t\tselected: isSelected,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\tif (startIndex > 0 || endIndex < this.filteredProviders.length) {\n\t\t\tconst scrollInfo = theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filteredProviders.length})`);\n\t\t\tthis.listContainer.addChild(new TruncatedText(scrollInfo, 1, 0));\n\t\t}\n\n\t\tif (this.filteredProviders.length === 0) {\n\t\t\tconst message =\n\t\t\t\tthis.allProviders.length === 0\n\t\t\t\t\t? this.mode === \"login\"\n\t\t\t\t\t\t? \"No providers available\"\n\t\t\t\t\t\t: \"No providers logged in. Use /login first.\"\n\t\t\t\t\t: \"No matching providers\";\n\t\t\tthis.listContainer.addChild(new TruncatedText(theme.fg(\"muted\", message), 1, 0));\n\t\t}\n\t}\n\n\tprivate formatStatusIndicator(provider: AuthSelectorProvider): string {\n\t\tconst status = this.getAuthStatus(provider.id);\n\t\tconst credential = this.authStorage.get(provider.id);\n\t\tif (this.isProviderStale(provider)) {\n\t\t\treturn theme.fg(\"warning\", status.label ?? \"expired\");\n\t\t}\n\t\tif (\n\t\t\tcredential?.type === \"oauth\" &&\n\t\t\tgetProviderAuthContract(provider.id).oauth !== \"validated\" &&\n\t\t\t(provider.authType === \"oauth\" || (!status.configured && !status.source))\n\t\t) {\n\t\t\treturn theme.fg(\"warning\", \"saved OAuth unavailable\");\n\t\t}\n\t\tif (!status.configured && !status.source) return theme.fg(\"muted\", \"unconfigured\");\n\n\t\tif (status.source && status.source !== \"stored\") {\n\t\t\treturn provider.authType === \"api_key\"\n\t\t\t\t? this.formatApiKeyStatusIndicator(status)\n\t\t\t\t: theme.fg(\"muted\", \"unconfigured\");\n\t\t}\n\n\t\tif (credential?.type === provider.authType) return theme.fg(\"success\", \"configured\");\n\t\tif (credential) {\n\t\t\tconst label = credential.type === \"oauth\" ? \"subscription configured\" : \"API key configured\";\n\t\t\treturn theme.fg(\"warning\", label);\n\t\t}\n\t\tif (provider.authType !== \"api_key\") return theme.fg(\"muted\", \"unconfigured\");\n\n\t\treturn this.formatApiKeyStatusIndicator(status);\n\t}\n\n\tprivate formatApiKeyStatusIndicator(status: AuthStatus): string {\n\t\tswitch (status.source) {\n\t\t\tcase \"environment\":\n\t\t\t\treturn theme.fg(\"success\", `env: ${status.label ?? \"API key\"}`);\n\t\t\tcase \"prime_cli\":\n\t\t\t\treturn theme.fg(\"success\", status.label ?? \"Prime CLI\");\n\t\t\tcase \"runtime\":\n\t\t\t\treturn theme.fg(\"success\", \"runtime API key\");\n\t\t\tcase \"fallback\":\n\t\t\t\treturn theme.fg(\"success\", \"custom API key\");\n\t\t\tcase \"models_json_key\":\n\t\t\t\treturn theme.fg(\"success\", \"key in models.json\");\n\t\t\tcase \"models_json_command\":\n\t\t\t\treturn theme.fg(\"success\", \"command in models.json\");\n\t\t\tdefault:\n\t\t\t\treturn theme.fg(\"muted\", \"unconfigured\");\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.filteredProviders.length === 0) return;\n\t\t\tthis.selectedIndex = Math.max(0, this.selectedIndex - 1);\n\t\t\tthis.updateList();\n\t\t} else if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.filteredProviders.length === 0) return;\n\t\t\tthis.selectedIndex = Math.min(this.filteredProviders.length - 1, this.selectedIndex + 1);\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Only steal left/right for tabs when the search field is empty, so cursor\n\t\t// editing still works while filtering.\n\t\telse if (\n\t\t\tthis.categories.length > 1 &&\n\t\t\tthis.searchInput.getValue() === \"\" &&\n\t\t\tkb.matches(keyData, \"tui.editor.cursorLeft\")\n\t\t) {\n\t\t\tthis.switchCategory(-1);\n\t\t} else if (\n\t\t\tthis.categories.length > 1 &&\n\t\t\tthis.searchInput.getValue() === \"\" &&\n\t\t\tkb.matches(keyData, \"tui.editor.cursorRight\")\n\t\t) {\n\t\t\tthis.switchCategory(1);\n\t\t} else if (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tconst selectedProvider = this.filteredProviders[this.selectedIndex];\n\t\t\tif (selectedProvider) {\n\t\t\t\tthis.onSelectCallback(selectedProvider);\n\t\t\t}\n\t\t} else if (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t} else {\n\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\tthis.filterProviders(this.searchInput.getValue());\n\t\t}\n\t}\n\n\tprivate get reservedRows(): number {\n\t\treturn PROVIDER_LIST_RESERVED_ROWS + this.getHeaderRows() + (this.tabBar ? TAB_BAR_RESERVED_ROWS : 0);\n\t}\n\n\tprivate updateLayout(): void {\n\t\tthis.listLayout = getMenuListLayout({\n\t\t\tgetRows: this.viewport.getRows,\n\t\t\tpreferredVisibleItems: PREFERRED_VISIBLE_PROVIDERS,\n\t\t\ttotalItems: this.filteredProviders.length,\n\t\t\treservedRows: this.reservedRows,\n\t\t\tcomfortableItemRows: 3,\n\t\t\tcompactItemRows: 2,\n\t\t\tscrollIndicatorRows: PROVIDER_SCROLL_INDICATOR_ROWS,\n\t\t});\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"oauth-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/oauth-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,SAAS,EACd,SAAS,EACT,KAAK,SAAS,EAKd,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAG7E,OAAO,EAKN,eAAe,EACf,KAAK,oBAAoB,EACzB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,SAAS,CAAC;AAE1D,MAAM,MAAM,oBAAoB,GAAG;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CAChC,CAAC;AAEF,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IACjE,eAAe,CAAC,EAAE,oBAAoB,CAAC;IACvC,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,MAAM,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,4BAA4B,CAAC,CAAC,EAAE,oBAAoB,EAAE,CAAC,EAAE,oBAAoB,GAAG,MAAM,CAKrG;AAQD,qBAAa,sBAAuB,SAAQ,SAAU,YAAW,SAAS;IACzE,OAAO,CAAC,WAAW,CAAkB;IAGrC,OAAO,CAAC,QAAQ,CAAS;IACzB,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IAED,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,MAAM,CAAC,CAAgB;IAC/B,OAAO,CAAC,YAAY,CAAyB;IAC7C,OAAO,CAAC,iBAAiB,CAAyB;IAClD,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,IAAI,CAAqB;IACjC,+EAA6E;IAC7E,OAAO,CAAC,UAAU,CAA8B;IAChD,OAAO,CAAC,cAAc,CAAoC;IAC1D,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,aAAa,CAAqC;IAC1D,OAAO,CAAC,gBAAgB,CAA2C;IACnE,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,UAAU,CAKf;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuB;IAChD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAE7C,YACC,IAAI,EAAE,OAAO,GAAG,QAAQ,EACxB,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,oBAAoB,EAAE,EACjC,QAAQ,EAAE,CAAC,QAAQ,EAAE,oBAAoB,KAAK,IAAI,EAClD,QAAQ,EAAE,MAAM,IAAI,EACpB,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,UAAU,EAClD,OAAO,GAAE,oBAAyB,EAqDlC;IAED,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,aAAa;IAUrB,OAAO,IAAI,IAAI,CAad;IAED,cAAc,IAAI,eAAe,CAEhC;IAED,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,oBAAoB;IAoBnB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAUvC;IAED,OAAO,CAAC,UAAU;IA2ClB,OAAO,CAAC,qBAAqB;IA+B7B,OAAO,CAAC,2BAA2B;IAiBnC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAoCjC;IAED,OAAO,KAAK,YAAY,GAEvB;IAED,OAAO,CAAC,YAAY;CAWpB","sourcesContent":["import {\n\ttype Component,\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tgetKeybindings,\n\tSpacer,\n\tTruncatedText,\n} from \"@ponythewhite/base-context-tui\";\nimport type { AuthStatus, AuthStorage } from \"../../../core/auth-storage.js\";\nimport { getProviderAuthContract } from \"../../../core/provider-contracts.js\";\nimport { theme } from \"../theme/theme.js\";\nimport {\n\tgetMenuListLayout,\n\tMenuList,\n\tMenuPanel,\n\tMenuRow,\n\tMenuSearchInput,\n\ttype MenuViewportProvider,\n} from \"./menu-panel.js\";\n\nexport type AuthSelectorCategory = \"provider\" | \"service\";\n\nexport type AuthSelectorProvider = {\n\tid: string;\n\tname: string;\n\tauthType: \"oauth\" | \"api_key\";\n\t/** Which tab the entry belongs to. Defaults to \"provider\" when omitted. */\n\tcategory?: AuthSelectorCategory;\n};\n\nexport interface OAuthSelectorOptions extends MenuViewportProvider {\n\tinitialCategory?: AuthSelectorCategory;\n\theader?: Component;\n\tgetHeaderRows?: () => number;\n\ttitle?: string;\n\tsubtitle?: string;\n\tsearchPlaceholder?: string;\n}\n\nexport function compareAuthSelectorProviders(a: AuthSelectorProvider, b: AuthSelectorProvider): number {\n\tif (a.authType !== b.authType) {\n\t\treturn a.authType === \"oauth\" ? -1 : 1;\n\t}\n\treturn a.name.localeCompare(b.name);\n}\n\nconst PREFERRED_VISIBLE_PROVIDERS = 8;\nconst PROVIDER_LIST_RESERVED_ROWS = 7;\n/** Extra fixed rows the Providers/MCP Connections tab bar (text + spacer) consumes. */\nconst TAB_BAR_RESERVED_ROWS = 2;\nconst PROVIDER_SCROLL_INDICATOR_ROWS = 1;\n\nexport class OAuthSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: MenuSearchInput;\n\n\t// Delegate focus to the search input so its IME cursor remains positioned correctly.\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\n\tprivate listContainer: Container;\n\tprivate tabBar?: TruncatedText;\n\tprivate allProviders: AuthSelectorProvider[];\n\tprivate filteredProviders: AuthSelectorProvider[];\n\tprivate selectedIndex: number = 0;\n\tprivate searchQuery = \"\";\n\tprivate mode: \"login\" | \"logout\";\n\t/** Tabs present in the data, in display order. Empty/single → no tab bar. */\n\tprivate categories: AuthSelectorCategory[] = [];\n\tprivate activeCategory: AuthSelectorCategory = \"provider\";\n\tprivate authStorage: AuthStorage;\n\tprivate getAuthStatus: (providerId: string) => AuthStatus;\n\tprivate onSelectCallback: (provider: AuthSelectorProvider) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate listLayout = getMenuListLayout({\n\t\tpreferredVisibleItems: PREFERRED_VISIBLE_PROVIDERS,\n\t\treservedRows: PROVIDER_LIST_RESERVED_ROWS,\n\t\tcomfortableItemRows: 3,\n\t\tcompactItemRows: 2,\n\t});\n\tprivate readonly viewport: MenuViewportProvider;\n\tprivate readonly getHeaderRows: () => number;\n\n\tconstructor(\n\t\tmode: \"login\" | \"logout\",\n\t\tauthStorage: AuthStorage,\n\t\tproviders: AuthSelectorProvider[],\n\t\tonSelect: (provider: AuthSelectorProvider) => void,\n\t\tonCancel: () => void,\n\t\tgetAuthStatus?: (providerId: string) => AuthStatus,\n\t\toptions: OAuthSelectorOptions = {},\n\t) {\n\t\tsuper();\n\n\t\tthis.mode = mode;\n\t\tthis.authStorage = authStorage;\n\t\tthis.getAuthStatus = getAuthStatus ?? ((providerId) => this.authStorage.getAuthStatus(providerId));\n\t\tthis.viewport = options;\n\t\tthis.getHeaderRows = options.header ? (options.getHeaderRows ?? (() => TAB_BAR_RESERVED_ROWS)) : () => 0;\n\t\tthis.allProviders = this.sortProviders(providers);\n\t\tthis.filteredProviders = this.allProviders;\n\t\tthis.onSelectCallback = onSelect;\n\t\tthis.onCancelCallback = onCancel;\n\n\t\tconst present = new Set(providers.map((p) => p.category ?? \"provider\"));\n\t\tthis.categories = ([\"provider\", \"service\"] as const).filter((c) => present.has(c));\n\t\tthis.activeCategory =\n\t\t\toptions.initialCategory && this.categories.includes(options.initialCategory)\n\t\t\t\t? options.initialCategory\n\t\t\t\t: (this.categories[0] ?? \"provider\");\n\n\t\tconst panel = new MenuPanel({\n\t\t\ttitle: options.title ?? (mode === \"login\" ? \"Providers\" : \"Saved Credentials\"),\n\t\t\tsubtitle:\n\t\t\t\toptions.subtitle ??\n\t\t\t\t(mode === \"login\" ? \"Subscription login or API keys.\" : \"Choose a credential to remove.\"),\n\t\t});\n\t\tthis.addChild(panel);\n\t\tif (options.header) {\n\t\t\tpanel.addChild(options.header);\n\t\t\tpanel.addChild(new Spacer(1));\n\t\t}\n\n\t\tif (this.categories.length > 1) {\n\t\t\tthis.tabBar = new TruncatedText(\"\");\n\t\t\tpanel.addChild(this.tabBar);\n\t\t\tpanel.addChild(new Spacer(1));\n\t\t}\n\n\t\tthis.searchInput = new MenuSearchInput(options.searchPlaceholder ?? \"Search providers\");\n\t\tthis.searchInput.onSubmit = () => {\n\t\t\tconst selectedProvider = this.filteredProviders[this.selectedIndex];\n\t\t\tif (selectedProvider) {\n\t\t\t\tthis.onSelectCallback(selectedProvider);\n\t\t\t}\n\t\t};\n\t\tpanel.addChild(this.searchInput);\n\t\tpanel.addChild(new Spacer(1));\n\n\t\tthis.listContainer = new MenuList({ compact: () => this.listLayout.compact });\n\t\tpanel.addChild(this.listContainer);\n\n\t\tthis.filterProviders(\"\");\n\t}\n\n\tprivate inActiveCategory(provider: AuthSelectorProvider): boolean {\n\t\treturn (provider.category ?? \"provider\") === this.activeCategory;\n\t}\n\n\tprivate switchCategory(direction: 1 | -1): void {\n\t\tif (this.categories.length < 2) return;\n\t\tconst current = this.categories.indexOf(this.activeCategory);\n\t\tconst next = (current + direction + this.categories.length) % this.categories.length;\n\t\tthis.activeCategory = this.categories[next];\n\t\tthis.selectedIndex = 0;\n\t\tthis.searchInput.setValue(\"\");\n\t\tthis.filterProviders(\"\");\n\t}\n\n\tprivate updateTabBar(): void {\n\t\tif (!this.tabBar) return;\n\t\tconst labels: Record<AuthSelectorCategory, string> = {\n\t\t\tprovider: \"Providers\",\n\t\t\tservice: \"MCP Connections\",\n\t\t};\n\t\tconst rendered = this.categories\n\t\t\t.map((category) =>\n\t\t\t\tcategory === this.activeCategory\n\t\t\t\t\t? theme.bold(theme.fg(\"accent\", labels[category]))\n\t\t\t\t\t: theme.fg(\"muted\", labels[category]),\n\t\t\t)\n\t\t\t.join(theme.fg(\"muted\", \" · \"));\n\t\tthis.tabBar.setText(`${rendered} ${theme.fg(\"muted\", \"←/→ switch\")}`);\n\t}\n\n\tprivate filterProviders(query: string): void {\n\t\tconst queryChanged = query !== this.searchQuery;\n\t\tthis.searchQuery = query;\n\t\tconst inCategory = this.allProviders.filter((p) => this.inActiveCategory(p));\n\t\tthis.filteredProviders = query\n\t\t\t? fuzzyFilter(inCategory, query, (provider) => `${provider.name} ${provider.id} ${provider.authType}`)\n\t\t\t: inCategory;\n\t\tthis.selectedIndex = queryChanged\n\t\t\t? 0\n\t\t\t: Math.max(0, Math.min(this.selectedIndex, Math.max(0, this.filteredProviders.length - 1)));\n\t\tthis.updateTabBar();\n\t\tthis.updateList();\n\t}\n\n\tprivate sortProviders(providers: AuthSelectorProvider[]): AuthSelectorProvider[] {\n\t\treturn [...providers].sort((a, b) => {\n\t\t\tconst rankDelta = this.getProviderSortRank(a) - this.getProviderSortRank(b);\n\t\t\tif (rankDelta !== 0) {\n\t\t\t\treturn rankDelta;\n\t\t\t}\n\t\t\treturn compareAuthSelectorProviders(a, b);\n\t\t});\n\t}\n\n\trefresh(): void {\n\t\tconst selected = this.filteredProviders[this.selectedIndex];\n\t\tthis.allProviders = this.sortProviders(this.allProviders);\n\t\tthis.filterProviders(this.searchInput.getValue());\n\t\tif (selected) {\n\t\t\tconst selectedIndex = this.filteredProviders.findIndex(\n\t\t\t\t(provider) => provider.id === selected.id && provider.authType === selected.authType,\n\t\t\t);\n\t\t\tif (selectedIndex >= 0) {\n\t\t\t\tthis.selectedIndex = selectedIndex;\n\t\t\t\tthis.updateList();\n\t\t\t}\n\t\t}\n\t}\n\n\tgetSearchInput(): MenuSearchInput {\n\t\treturn this.searchInput;\n\t}\n\n\tprivate getProviderSortRank(provider: AuthSelectorProvider): number {\n\t\tif (this.isProviderConfigured(provider)) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (this.isProviderStale(provider)) {\n\t\t\treturn 1;\n\t\t}\n\t\treturn 2;\n\t}\n\n\tprivate isProviderStale(provider: AuthSelectorProvider): boolean {\n\t\tconst status = this.getAuthStatus(provider.id);\n\t\tconst credential = this.authStorage.get(provider.id);\n\t\tconst storageStatus = this.authStorage.getAuthStatus(provider.id);\n\t\treturn status.source === \"stale\" || (storageStatus.source === \"stale\" && credential?.type === provider.authType);\n\t}\n\n\tprivate isProviderConfigured(provider: AuthSelectorProvider): boolean {\n\t\tconst status = this.getAuthStatus(provider.id);\n\t\tconst credential = this.authStorage.get(provider.id);\n\t\tif (this.isProviderStale(provider)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (status.source && status.source !== \"stored\") {\n\t\t\treturn provider.authType === \"api_key\";\n\t\t}\n\n\t\tif (credential) {\n\t\t\treturn status.configured;\n\t\t}\n\t\tif (provider.authType !== \"api_key\") {\n\t\t\treturn false;\n\t\t}\n\t\treturn status.source !== undefined;\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst previousLayout = this.listLayout;\n\t\tthis.updateLayout();\n\t\tif (\n\t\t\tthis.listLayout.compact !== previousLayout.compact ||\n\t\t\tthis.listLayout.visibleItems !== previousLayout.visibleItems\n\t\t) {\n\t\t\tthis.updateList();\n\t\t}\n\t\treturn super.render(width);\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.updateLayout();\n\t\tthis.listContainer.clear();\n\n\t\tconst maxVisible = this.listLayout.visibleItems;\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(maxVisible / 2), this.filteredProviders.length - maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.filteredProviders.length);\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst provider = this.filteredProviders[i];\n\t\t\tif (!provider) continue;\n\n\t\t\tconst isSelected = i === this.selectedIndex;\n\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew MenuRow({\n\t\t\t\t\tprimary: provider.name,\n\t\t\t\t\tsecondary: provider.authType === \"oauth\" ? \"subscription\" : \"api key\",\n\t\t\t\t\tmeta: this.formatStatusIndicator(provider),\n\t\t\t\t\tselected: isSelected,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\tif (startIndex > 0 || endIndex < this.filteredProviders.length) {\n\t\t\tconst scrollInfo = theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filteredProviders.length})`);\n\t\t\tthis.listContainer.addChild(new TruncatedText(scrollInfo, 1, 0));\n\t\t}\n\n\t\tif (this.filteredProviders.length === 0) {\n\t\t\tconst message =\n\t\t\t\tthis.allProviders.length === 0\n\t\t\t\t\t? this.mode === \"login\"\n\t\t\t\t\t\t? \"No providers available\"\n\t\t\t\t\t\t: \"No providers logged in. Use /login first.\"\n\t\t\t\t\t: \"No matching providers\";\n\t\t\tthis.listContainer.addChild(new TruncatedText(theme.fg(\"muted\", message), 1, 0));\n\t\t}\n\t}\n\n\tprivate formatStatusIndicator(provider: AuthSelectorProvider): string {\n\t\tconst status = this.getAuthStatus(provider.id);\n\t\tconst credential = this.authStorage.get(provider.id);\n\t\tif (this.isProviderStale(provider)) {\n\t\t\treturn theme.fg(\"warning\", status.label ?? \"expired\");\n\t\t}\n\t\tif (\n\t\t\tcredential?.type === \"oauth\" &&\n\t\t\tgetProviderAuthContract(provider.id).oauth !== \"supported\" &&\n\t\t\t(provider.authType === \"oauth\" || (!status.configured && !status.source))\n\t\t) {\n\t\t\treturn theme.fg(\"warning\", \"saved OAuth unavailable\");\n\t\t}\n\t\tif (!status.configured && !status.source) return theme.fg(\"muted\", \"unconfigured\");\n\n\t\tif (status.source && status.source !== \"stored\") {\n\t\t\treturn provider.authType === \"api_key\"\n\t\t\t\t? this.formatApiKeyStatusIndicator(status)\n\t\t\t\t: theme.fg(\"muted\", \"unconfigured\");\n\t\t}\n\n\t\tif (credential?.type === provider.authType) return theme.fg(\"success\", \"configured\");\n\t\tif (credential) {\n\t\t\tconst label = credential.type === \"oauth\" ? \"subscription configured\" : \"API key configured\";\n\t\t\treturn theme.fg(\"warning\", label);\n\t\t}\n\t\tif (provider.authType !== \"api_key\") return theme.fg(\"muted\", \"unconfigured\");\n\n\t\treturn this.formatApiKeyStatusIndicator(status);\n\t}\n\n\tprivate formatApiKeyStatusIndicator(status: AuthStatus): string {\n\t\tswitch (status.source) {\n\t\t\tcase \"environment\":\n\t\t\t\treturn theme.fg(\"success\", `env: ${status.label ?? \"API key\"}`);\n\t\t\tcase \"runtime\":\n\t\t\t\treturn theme.fg(\"success\", \"runtime API key\");\n\t\t\tcase \"fallback\":\n\t\t\t\treturn theme.fg(\"success\", \"custom API key\");\n\t\t\tcase \"models_json_key\":\n\t\t\t\treturn theme.fg(\"success\", \"key in models.json\");\n\t\t\tcase \"models_json_command\":\n\t\t\t\treturn theme.fg(\"success\", \"command in models.json\");\n\t\t\tdefault:\n\t\t\t\treturn theme.fg(\"muted\", \"unconfigured\");\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.filteredProviders.length === 0) return;\n\t\t\tthis.selectedIndex = Math.max(0, this.selectedIndex - 1);\n\t\t\tthis.updateList();\n\t\t} else if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.filteredProviders.length === 0) return;\n\t\t\tthis.selectedIndex = Math.min(this.filteredProviders.length - 1, this.selectedIndex + 1);\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Only steal left/right for tabs when the search field is empty, so cursor\n\t\t// editing still works while filtering.\n\t\telse if (\n\t\t\tthis.categories.length > 1 &&\n\t\t\tthis.searchInput.getValue() === \"\" &&\n\t\t\tkb.matches(keyData, \"tui.editor.cursorLeft\")\n\t\t) {\n\t\t\tthis.switchCategory(-1);\n\t\t} else if (\n\t\t\tthis.categories.length > 1 &&\n\t\t\tthis.searchInput.getValue() === \"\" &&\n\t\t\tkb.matches(keyData, \"tui.editor.cursorRight\")\n\t\t) {\n\t\t\tthis.switchCategory(1);\n\t\t} else if (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tconst selectedProvider = this.filteredProviders[this.selectedIndex];\n\t\t\tif (selectedProvider) {\n\t\t\t\tthis.onSelectCallback(selectedProvider);\n\t\t\t}\n\t\t} else if (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t} else {\n\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\tthis.filterProviders(this.searchInput.getValue());\n\t\t}\n\t}\n\n\tprivate get reservedRows(): number {\n\t\treturn PROVIDER_LIST_RESERVED_ROWS + this.getHeaderRows() + (this.tabBar ? TAB_BAR_RESERVED_ROWS : 0);\n\t}\n\n\tprivate updateLayout(): void {\n\t\tthis.listLayout = getMenuListLayout({\n\t\t\tgetRows: this.viewport.getRows,\n\t\t\tpreferredVisibleItems: PREFERRED_VISIBLE_PROVIDERS,\n\t\t\ttotalItems: this.filteredProviders.length,\n\t\t\treservedRows: this.reservedRows,\n\t\t\tcomfortableItemRows: 3,\n\t\t\tcompactItemRows: 2,\n\t\t\tscrollIndicatorRows: PROVIDER_SCROLL_INDICATOR_ROWS,\n\t\t});\n\t}\n}\n"]}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Container, fuzzyFilter, getKeybindings, Spacer, TruncatedText, } from "@ponythewhite/base-context-tui";
|
|
2
|
-
import { PRIME_INFERENCE_PROVIDER_ID } from "../../../core/prime-inference-auth.js";
|
|
3
2
|
import { getProviderAuthContract } from "../../../core/provider-contracts.js";
|
|
4
3
|
import { theme } from "../theme/theme.js";
|
|
5
4
|
import { getMenuListLayout, MenuList, MenuPanel, MenuRow, MenuSearchInput, } from "./menu-panel.js";
|
|
@@ -67,7 +66,7 @@ export class OAuthSelectorComponent extends Container {
|
|
|
67
66
|
const panel = new MenuPanel({
|
|
68
67
|
title: options.title ?? (mode === "login" ? "Providers" : "Saved Credentials"),
|
|
69
68
|
subtitle: options.subtitle ??
|
|
70
|
-
(mode === "login" ? "
|
|
69
|
+
(mode === "login" ? "Subscription login or API keys." : "Choose a credential to remove."),
|
|
71
70
|
});
|
|
72
71
|
this.addChild(panel);
|
|
73
72
|
if (options.header) {
|
|
@@ -138,12 +137,6 @@ export class OAuthSelectorComponent extends Container {
|
|
|
138
137
|
if (rankDelta !== 0) {
|
|
139
138
|
return rankDelta;
|
|
140
139
|
}
|
|
141
|
-
if (this.mode === "login" && a.id !== b.id) {
|
|
142
|
-
if (a.id === PRIME_INFERENCE_PROVIDER_ID)
|
|
143
|
-
return -1;
|
|
144
|
-
if (b.id === PRIME_INFERENCE_PROVIDER_ID)
|
|
145
|
-
return 1;
|
|
146
|
-
}
|
|
147
140
|
return compareAuthSelectorProviders(a, b);
|
|
148
141
|
});
|
|
149
142
|
}
|
|
@@ -241,7 +234,7 @@ export class OAuthSelectorComponent extends Container {
|
|
|
241
234
|
return theme.fg("warning", status.label ?? "expired");
|
|
242
235
|
}
|
|
243
236
|
if (credential?.type === "oauth" &&
|
|
244
|
-
getProviderAuthContract(provider.id).oauth !== "
|
|
237
|
+
getProviderAuthContract(provider.id).oauth !== "supported" &&
|
|
245
238
|
(provider.authType === "oauth" || (!status.configured && !status.source))) {
|
|
246
239
|
return theme.fg("warning", "saved OAuth unavailable");
|
|
247
240
|
}
|
|
@@ -266,8 +259,6 @@ export class OAuthSelectorComponent extends Container {
|
|
|
266
259
|
switch (status.source) {
|
|
267
260
|
case "environment":
|
|
268
261
|
return theme.fg("success", `env: ${status.label ?? "API key"}`);
|
|
269
|
-
case "prime_cli":
|
|
270
|
-
return theme.fg("success", status.label ?? "Prime CLI");
|
|
271
262
|
case "runtime":
|
|
272
263
|
return theme.fg("success", "runtime API key");
|
|
273
264
|
case "fallback":
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-selector.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/oauth-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Component,\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tgetKeybindings,\n\tSpacer,\n\tTruncatedText,\n} from \"@ponythewhite/base-context-tui\";\nimport type { AuthStatus, AuthStorage } from \"../../../core/auth-storage.js\";\nimport { PRIME_INFERENCE_PROVIDER_ID } from \"../../../core/prime-inference-auth.js\";\nimport { getProviderAuthContract } from \"../../../core/provider-contracts.js\";\nimport { theme } from \"../theme/theme.js\";\nimport {\n\tgetMenuListLayout,\n\tMenuList,\n\tMenuPanel,\n\tMenuRow,\n\tMenuSearchInput,\n\ttype MenuViewportProvider,\n} from \"./menu-panel.js\";\n\nexport type AuthSelectorCategory = \"provider\" | \"service\";\n\nexport type AuthSelectorProvider = {\n\tid: string;\n\tname: string;\n\tauthType: \"oauth\" | \"api_key\";\n\t/** Which tab the entry belongs to. Defaults to \"provider\" when omitted. */\n\tcategory?: AuthSelectorCategory;\n};\n\nexport interface OAuthSelectorOptions extends MenuViewportProvider {\n\tinitialCategory?: AuthSelectorCategory;\n\theader?: Component;\n\tgetHeaderRows?: () => number;\n\ttitle?: string;\n\tsubtitle?: string;\n\tsearchPlaceholder?: string;\n}\n\nexport function compareAuthSelectorProviders(a: AuthSelectorProvider, b: AuthSelectorProvider): number {\n\tif (a.authType !== b.authType) {\n\t\treturn a.authType === \"oauth\" ? -1 : 1;\n\t}\n\treturn a.name.localeCompare(b.name);\n}\n\nconst PREFERRED_VISIBLE_PROVIDERS = 8;\nconst PROVIDER_LIST_RESERVED_ROWS = 7;\n/** Extra fixed rows the Providers/MCP Connections tab bar (text + spacer) consumes. */\nconst TAB_BAR_RESERVED_ROWS = 2;\nconst PROVIDER_SCROLL_INDICATOR_ROWS = 1;\n\nexport class OAuthSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: MenuSearchInput;\n\n\t// Delegate focus to the search input so its IME cursor remains positioned correctly.\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\n\tprivate listContainer: Container;\n\tprivate tabBar?: TruncatedText;\n\tprivate allProviders: AuthSelectorProvider[];\n\tprivate filteredProviders: AuthSelectorProvider[];\n\tprivate selectedIndex: number = 0;\n\tprivate searchQuery = \"\";\n\tprivate mode: \"login\" | \"logout\";\n\t/** Tabs present in the data, in display order. Empty/single → no tab bar. */\n\tprivate categories: AuthSelectorCategory[] = [];\n\tprivate activeCategory: AuthSelectorCategory = \"provider\";\n\tprivate authStorage: AuthStorage;\n\tprivate getAuthStatus: (providerId: string) => AuthStatus;\n\tprivate onSelectCallback: (provider: AuthSelectorProvider) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate listLayout = getMenuListLayout({\n\t\tpreferredVisibleItems: PREFERRED_VISIBLE_PROVIDERS,\n\t\treservedRows: PROVIDER_LIST_RESERVED_ROWS,\n\t\tcomfortableItemRows: 3,\n\t\tcompactItemRows: 2,\n\t});\n\tprivate readonly viewport: MenuViewportProvider;\n\tprivate readonly getHeaderRows: () => number;\n\n\tconstructor(\n\t\tmode: \"login\" | \"logout\",\n\t\tauthStorage: AuthStorage,\n\t\tproviders: AuthSelectorProvider[],\n\t\tonSelect: (provider: AuthSelectorProvider) => void,\n\t\tonCancel: () => void,\n\t\tgetAuthStatus?: (providerId: string) => AuthStatus,\n\t\toptions: OAuthSelectorOptions = {},\n\t) {\n\t\tsuper();\n\n\t\tthis.mode = mode;\n\t\tthis.authStorage = authStorage;\n\t\tthis.getAuthStatus = getAuthStatus ?? ((providerId) => this.authStorage.getAuthStatus(providerId));\n\t\tthis.viewport = options;\n\t\tthis.getHeaderRows = options.header ? (options.getHeaderRows ?? (() => TAB_BAR_RESERVED_ROWS)) : () => 0;\n\t\tthis.allProviders = this.sortProviders(providers);\n\t\tthis.filteredProviders = this.allProviders;\n\t\tthis.onSelectCallback = onSelect;\n\t\tthis.onCancelCallback = onCancel;\n\n\t\tconst present = new Set(providers.map((p) => p.category ?? \"provider\"));\n\t\tthis.categories = ([\"provider\", \"service\"] as const).filter((c) => present.has(c));\n\t\tthis.activeCategory =\n\t\t\toptions.initialCategory && this.categories.includes(options.initialCategory)\n\t\t\t\t? options.initialCategory\n\t\t\t\t: (this.categories[0] ?? \"provider\");\n\n\t\tconst panel = new MenuPanel({\n\t\t\ttitle: options.title ?? (mode === \"login\" ? \"Providers\" : \"Saved Credentials\"),\n\t\t\tsubtitle:\n\t\t\t\toptions.subtitle ??\n\t\t\t\t(mode === \"login\" ? \"API keys; unvalidated OAuth unavailable.\" : \"Choose a credential to remove.\"),\n\t\t});\n\t\tthis.addChild(panel);\n\t\tif (options.header) {\n\t\t\tpanel.addChild(options.header);\n\t\t\tpanel.addChild(new Spacer(1));\n\t\t}\n\n\t\tif (this.categories.length > 1) {\n\t\t\tthis.tabBar = new TruncatedText(\"\");\n\t\t\tpanel.addChild(this.tabBar);\n\t\t\tpanel.addChild(new Spacer(1));\n\t\t}\n\n\t\tthis.searchInput = new MenuSearchInput(options.searchPlaceholder ?? \"Search providers\");\n\t\tthis.searchInput.onSubmit = () => {\n\t\t\tconst selectedProvider = this.filteredProviders[this.selectedIndex];\n\t\t\tif (selectedProvider) {\n\t\t\t\tthis.onSelectCallback(selectedProvider);\n\t\t\t}\n\t\t};\n\t\tpanel.addChild(this.searchInput);\n\t\tpanel.addChild(new Spacer(1));\n\n\t\tthis.listContainer = new MenuList({ compact: () => this.listLayout.compact });\n\t\tpanel.addChild(this.listContainer);\n\n\t\tthis.filterProviders(\"\");\n\t}\n\n\tprivate inActiveCategory(provider: AuthSelectorProvider): boolean {\n\t\treturn (provider.category ?? \"provider\") === this.activeCategory;\n\t}\n\n\tprivate switchCategory(direction: 1 | -1): void {\n\t\tif (this.categories.length < 2) return;\n\t\tconst current = this.categories.indexOf(this.activeCategory);\n\t\tconst next = (current + direction + this.categories.length) % this.categories.length;\n\t\tthis.activeCategory = this.categories[next];\n\t\tthis.selectedIndex = 0;\n\t\tthis.searchInput.setValue(\"\");\n\t\tthis.filterProviders(\"\");\n\t}\n\n\tprivate updateTabBar(): void {\n\t\tif (!this.tabBar) return;\n\t\tconst labels: Record<AuthSelectorCategory, string> = {\n\t\t\tprovider: \"Providers\",\n\t\t\tservice: \"MCP Connections\",\n\t\t};\n\t\tconst rendered = this.categories\n\t\t\t.map((category) =>\n\t\t\t\tcategory === this.activeCategory\n\t\t\t\t\t? theme.bold(theme.fg(\"accent\", labels[category]))\n\t\t\t\t\t: theme.fg(\"muted\", labels[category]),\n\t\t\t)\n\t\t\t.join(theme.fg(\"muted\", \" · \"));\n\t\tthis.tabBar.setText(`${rendered} ${theme.fg(\"muted\", \"←/→ switch\")}`);\n\t}\n\n\tprivate filterProviders(query: string): void {\n\t\tconst queryChanged = query !== this.searchQuery;\n\t\tthis.searchQuery = query;\n\t\tconst inCategory = this.allProviders.filter((p) => this.inActiveCategory(p));\n\t\tthis.filteredProviders = query\n\t\t\t? fuzzyFilter(inCategory, query, (provider) => `${provider.name} ${provider.id} ${provider.authType}`)\n\t\t\t: inCategory;\n\t\tthis.selectedIndex = queryChanged\n\t\t\t? 0\n\t\t\t: Math.max(0, Math.min(this.selectedIndex, Math.max(0, this.filteredProviders.length - 1)));\n\t\tthis.updateTabBar();\n\t\tthis.updateList();\n\t}\n\n\tprivate sortProviders(providers: AuthSelectorProvider[]): AuthSelectorProvider[] {\n\t\treturn [...providers].sort((a, b) => {\n\t\t\tconst rankDelta = this.getProviderSortRank(a) - this.getProviderSortRank(b);\n\t\t\tif (rankDelta !== 0) {\n\t\t\t\treturn rankDelta;\n\t\t\t}\n\t\t\tif (this.mode === \"login\" && a.id !== b.id) {\n\t\t\t\tif (a.id === PRIME_INFERENCE_PROVIDER_ID) return -1;\n\t\t\t\tif (b.id === PRIME_INFERENCE_PROVIDER_ID) return 1;\n\t\t\t}\n\t\t\treturn compareAuthSelectorProviders(a, b);\n\t\t});\n\t}\n\n\trefresh(): void {\n\t\tconst selected = this.filteredProviders[this.selectedIndex];\n\t\tthis.allProviders = this.sortProviders(this.allProviders);\n\t\tthis.filterProviders(this.searchInput.getValue());\n\t\tif (selected) {\n\t\t\tconst selectedIndex = this.filteredProviders.findIndex(\n\t\t\t\t(provider) => provider.id === selected.id && provider.authType === selected.authType,\n\t\t\t);\n\t\t\tif (selectedIndex >= 0) {\n\t\t\t\tthis.selectedIndex = selectedIndex;\n\t\t\t\tthis.updateList();\n\t\t\t}\n\t\t}\n\t}\n\n\tgetSearchInput(): MenuSearchInput {\n\t\treturn this.searchInput;\n\t}\n\n\tprivate getProviderSortRank(provider: AuthSelectorProvider): number {\n\t\tif (this.isProviderConfigured(provider)) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (this.isProviderStale(provider)) {\n\t\t\treturn 1;\n\t\t}\n\t\treturn 2;\n\t}\n\n\tprivate isProviderStale(provider: AuthSelectorProvider): boolean {\n\t\tconst status = this.getAuthStatus(provider.id);\n\t\tconst credential = this.authStorage.get(provider.id);\n\t\tconst storageStatus = this.authStorage.getAuthStatus(provider.id);\n\t\treturn status.source === \"stale\" || (storageStatus.source === \"stale\" && credential?.type === provider.authType);\n\t}\n\n\tprivate isProviderConfigured(provider: AuthSelectorProvider): boolean {\n\t\tconst status = this.getAuthStatus(provider.id);\n\t\tconst credential = this.authStorage.get(provider.id);\n\t\tif (this.isProviderStale(provider)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (status.source && status.source !== \"stored\") {\n\t\t\treturn provider.authType === \"api_key\";\n\t\t}\n\n\t\tif (credential) {\n\t\t\treturn status.configured;\n\t\t}\n\t\tif (provider.authType !== \"api_key\") {\n\t\t\treturn false;\n\t\t}\n\t\treturn status.source !== undefined;\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst previousLayout = this.listLayout;\n\t\tthis.updateLayout();\n\t\tif (\n\t\t\tthis.listLayout.compact !== previousLayout.compact ||\n\t\t\tthis.listLayout.visibleItems !== previousLayout.visibleItems\n\t\t) {\n\t\t\tthis.updateList();\n\t\t}\n\t\treturn super.render(width);\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.updateLayout();\n\t\tthis.listContainer.clear();\n\n\t\tconst maxVisible = this.listLayout.visibleItems;\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(maxVisible / 2), this.filteredProviders.length - maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.filteredProviders.length);\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst provider = this.filteredProviders[i];\n\t\t\tif (!provider) continue;\n\n\t\t\tconst isSelected = i === this.selectedIndex;\n\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew MenuRow({\n\t\t\t\t\tprimary: provider.name,\n\t\t\t\t\tsecondary: provider.authType === \"oauth\" ? \"subscription\" : \"api key\",\n\t\t\t\t\tmeta: this.formatStatusIndicator(provider),\n\t\t\t\t\tselected: isSelected,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\tif (startIndex > 0 || endIndex < this.filteredProviders.length) {\n\t\t\tconst scrollInfo = theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filteredProviders.length})`);\n\t\t\tthis.listContainer.addChild(new TruncatedText(scrollInfo, 1, 0));\n\t\t}\n\n\t\tif (this.filteredProviders.length === 0) {\n\t\t\tconst message =\n\t\t\t\tthis.allProviders.length === 0\n\t\t\t\t\t? this.mode === \"login\"\n\t\t\t\t\t\t? \"No providers available\"\n\t\t\t\t\t\t: \"No providers logged in. Use /login first.\"\n\t\t\t\t\t: \"No matching providers\";\n\t\t\tthis.listContainer.addChild(new TruncatedText(theme.fg(\"muted\", message), 1, 0));\n\t\t}\n\t}\n\n\tprivate formatStatusIndicator(provider: AuthSelectorProvider): string {\n\t\tconst status = this.getAuthStatus(provider.id);\n\t\tconst credential = this.authStorage.get(provider.id);\n\t\tif (this.isProviderStale(provider)) {\n\t\t\treturn theme.fg(\"warning\", status.label ?? \"expired\");\n\t\t}\n\t\tif (\n\t\t\tcredential?.type === \"oauth\" &&\n\t\t\tgetProviderAuthContract(provider.id).oauth !== \"validated\" &&\n\t\t\t(provider.authType === \"oauth\" || (!status.configured && !status.source))\n\t\t) {\n\t\t\treturn theme.fg(\"warning\", \"saved OAuth unavailable\");\n\t\t}\n\t\tif (!status.configured && !status.source) return theme.fg(\"muted\", \"unconfigured\");\n\n\t\tif (status.source && status.source !== \"stored\") {\n\t\t\treturn provider.authType === \"api_key\"\n\t\t\t\t? this.formatApiKeyStatusIndicator(status)\n\t\t\t\t: theme.fg(\"muted\", \"unconfigured\");\n\t\t}\n\n\t\tif (credential?.type === provider.authType) return theme.fg(\"success\", \"configured\");\n\t\tif (credential) {\n\t\t\tconst label = credential.type === \"oauth\" ? \"subscription configured\" : \"API key configured\";\n\t\t\treturn theme.fg(\"warning\", label);\n\t\t}\n\t\tif (provider.authType !== \"api_key\") return theme.fg(\"muted\", \"unconfigured\");\n\n\t\treturn this.formatApiKeyStatusIndicator(status);\n\t}\n\n\tprivate formatApiKeyStatusIndicator(status: AuthStatus): string {\n\t\tswitch (status.source) {\n\t\t\tcase \"environment\":\n\t\t\t\treturn theme.fg(\"success\", `env: ${status.label ?? \"API key\"}`);\n\t\t\tcase \"prime_cli\":\n\t\t\t\treturn theme.fg(\"success\", status.label ?? \"Prime CLI\");\n\t\t\tcase \"runtime\":\n\t\t\t\treturn theme.fg(\"success\", \"runtime API key\");\n\t\t\tcase \"fallback\":\n\t\t\t\treturn theme.fg(\"success\", \"custom API key\");\n\t\t\tcase \"models_json_key\":\n\t\t\t\treturn theme.fg(\"success\", \"key in models.json\");\n\t\t\tcase \"models_json_command\":\n\t\t\t\treturn theme.fg(\"success\", \"command in models.json\");\n\t\t\tdefault:\n\t\t\t\treturn theme.fg(\"muted\", \"unconfigured\");\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.filteredProviders.length === 0) return;\n\t\t\tthis.selectedIndex = Math.max(0, this.selectedIndex - 1);\n\t\t\tthis.updateList();\n\t\t} else if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.filteredProviders.length === 0) return;\n\t\t\tthis.selectedIndex = Math.min(this.filteredProviders.length - 1, this.selectedIndex + 1);\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Only steal left/right for tabs when the search field is empty, so cursor\n\t\t// editing still works while filtering.\n\t\telse if (\n\t\t\tthis.categories.length > 1 &&\n\t\t\tthis.searchInput.getValue() === \"\" &&\n\t\t\tkb.matches(keyData, \"tui.editor.cursorLeft\")\n\t\t) {\n\t\t\tthis.switchCategory(-1);\n\t\t} else if (\n\t\t\tthis.categories.length > 1 &&\n\t\t\tthis.searchInput.getValue() === \"\" &&\n\t\t\tkb.matches(keyData, \"tui.editor.cursorRight\")\n\t\t) {\n\t\t\tthis.switchCategory(1);\n\t\t} else if (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tconst selectedProvider = this.filteredProviders[this.selectedIndex];\n\t\t\tif (selectedProvider) {\n\t\t\t\tthis.onSelectCallback(selectedProvider);\n\t\t\t}\n\t\t} else if (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t} else {\n\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\tthis.filterProviders(this.searchInput.getValue());\n\t\t}\n\t}\n\n\tprivate get reservedRows(): number {\n\t\treturn PROVIDER_LIST_RESERVED_ROWS + this.getHeaderRows() + (this.tabBar ? TAB_BAR_RESERVED_ROWS : 0);\n\t}\n\n\tprivate updateLayout(): void {\n\t\tthis.listLayout = getMenuListLayout({\n\t\t\tgetRows: this.viewport.getRows,\n\t\t\tpreferredVisibleItems: PREFERRED_VISIBLE_PROVIDERS,\n\t\t\ttotalItems: this.filteredProviders.length,\n\t\t\treservedRows: this.reservedRows,\n\t\t\tcomfortableItemRows: 3,\n\t\t\tcompactItemRows: 2,\n\t\t\tscrollIndicatorRows: PROVIDER_SCROLL_INDICATOR_ROWS,\n\t\t});\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"oauth-selector.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/oauth-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Component,\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tgetKeybindings,\n\tSpacer,\n\tTruncatedText,\n} from \"@ponythewhite/base-context-tui\";\nimport type { AuthStatus, AuthStorage } from \"../../../core/auth-storage.js\";\nimport { getProviderAuthContract } from \"../../../core/provider-contracts.js\";\nimport { theme } from \"../theme/theme.js\";\nimport {\n\tgetMenuListLayout,\n\tMenuList,\n\tMenuPanel,\n\tMenuRow,\n\tMenuSearchInput,\n\ttype MenuViewportProvider,\n} from \"./menu-panel.js\";\n\nexport type AuthSelectorCategory = \"provider\" | \"service\";\n\nexport type AuthSelectorProvider = {\n\tid: string;\n\tname: string;\n\tauthType: \"oauth\" | \"api_key\";\n\t/** Which tab the entry belongs to. Defaults to \"provider\" when omitted. */\n\tcategory?: AuthSelectorCategory;\n};\n\nexport interface OAuthSelectorOptions extends MenuViewportProvider {\n\tinitialCategory?: AuthSelectorCategory;\n\theader?: Component;\n\tgetHeaderRows?: () => number;\n\ttitle?: string;\n\tsubtitle?: string;\n\tsearchPlaceholder?: string;\n}\n\nexport function compareAuthSelectorProviders(a: AuthSelectorProvider, b: AuthSelectorProvider): number {\n\tif (a.authType !== b.authType) {\n\t\treturn a.authType === \"oauth\" ? -1 : 1;\n\t}\n\treturn a.name.localeCompare(b.name);\n}\n\nconst PREFERRED_VISIBLE_PROVIDERS = 8;\nconst PROVIDER_LIST_RESERVED_ROWS = 7;\n/** Extra fixed rows the Providers/MCP Connections tab bar (text + spacer) consumes. */\nconst TAB_BAR_RESERVED_ROWS = 2;\nconst PROVIDER_SCROLL_INDICATOR_ROWS = 1;\n\nexport class OAuthSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: MenuSearchInput;\n\n\t// Delegate focus to the search input so its IME cursor remains positioned correctly.\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\n\tprivate listContainer: Container;\n\tprivate tabBar?: TruncatedText;\n\tprivate allProviders: AuthSelectorProvider[];\n\tprivate filteredProviders: AuthSelectorProvider[];\n\tprivate selectedIndex: number = 0;\n\tprivate searchQuery = \"\";\n\tprivate mode: \"login\" | \"logout\";\n\t/** Tabs present in the data, in display order. Empty/single → no tab bar. */\n\tprivate categories: AuthSelectorCategory[] = [];\n\tprivate activeCategory: AuthSelectorCategory = \"provider\";\n\tprivate authStorage: AuthStorage;\n\tprivate getAuthStatus: (providerId: string) => AuthStatus;\n\tprivate onSelectCallback: (provider: AuthSelectorProvider) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate listLayout = getMenuListLayout({\n\t\tpreferredVisibleItems: PREFERRED_VISIBLE_PROVIDERS,\n\t\treservedRows: PROVIDER_LIST_RESERVED_ROWS,\n\t\tcomfortableItemRows: 3,\n\t\tcompactItemRows: 2,\n\t});\n\tprivate readonly viewport: MenuViewportProvider;\n\tprivate readonly getHeaderRows: () => number;\n\n\tconstructor(\n\t\tmode: \"login\" | \"logout\",\n\t\tauthStorage: AuthStorage,\n\t\tproviders: AuthSelectorProvider[],\n\t\tonSelect: (provider: AuthSelectorProvider) => void,\n\t\tonCancel: () => void,\n\t\tgetAuthStatus?: (providerId: string) => AuthStatus,\n\t\toptions: OAuthSelectorOptions = {},\n\t) {\n\t\tsuper();\n\n\t\tthis.mode = mode;\n\t\tthis.authStorage = authStorage;\n\t\tthis.getAuthStatus = getAuthStatus ?? ((providerId) => this.authStorage.getAuthStatus(providerId));\n\t\tthis.viewport = options;\n\t\tthis.getHeaderRows = options.header ? (options.getHeaderRows ?? (() => TAB_BAR_RESERVED_ROWS)) : () => 0;\n\t\tthis.allProviders = this.sortProviders(providers);\n\t\tthis.filteredProviders = this.allProviders;\n\t\tthis.onSelectCallback = onSelect;\n\t\tthis.onCancelCallback = onCancel;\n\n\t\tconst present = new Set(providers.map((p) => p.category ?? \"provider\"));\n\t\tthis.categories = ([\"provider\", \"service\"] as const).filter((c) => present.has(c));\n\t\tthis.activeCategory =\n\t\t\toptions.initialCategory && this.categories.includes(options.initialCategory)\n\t\t\t\t? options.initialCategory\n\t\t\t\t: (this.categories[0] ?? \"provider\");\n\n\t\tconst panel = new MenuPanel({\n\t\t\ttitle: options.title ?? (mode === \"login\" ? \"Providers\" : \"Saved Credentials\"),\n\t\t\tsubtitle:\n\t\t\t\toptions.subtitle ??\n\t\t\t\t(mode === \"login\" ? \"Subscription login or API keys.\" : \"Choose a credential to remove.\"),\n\t\t});\n\t\tthis.addChild(panel);\n\t\tif (options.header) {\n\t\t\tpanel.addChild(options.header);\n\t\t\tpanel.addChild(new Spacer(1));\n\t\t}\n\n\t\tif (this.categories.length > 1) {\n\t\t\tthis.tabBar = new TruncatedText(\"\");\n\t\t\tpanel.addChild(this.tabBar);\n\t\t\tpanel.addChild(new Spacer(1));\n\t\t}\n\n\t\tthis.searchInput = new MenuSearchInput(options.searchPlaceholder ?? \"Search providers\");\n\t\tthis.searchInput.onSubmit = () => {\n\t\t\tconst selectedProvider = this.filteredProviders[this.selectedIndex];\n\t\t\tif (selectedProvider) {\n\t\t\t\tthis.onSelectCallback(selectedProvider);\n\t\t\t}\n\t\t};\n\t\tpanel.addChild(this.searchInput);\n\t\tpanel.addChild(new Spacer(1));\n\n\t\tthis.listContainer = new MenuList({ compact: () => this.listLayout.compact });\n\t\tpanel.addChild(this.listContainer);\n\n\t\tthis.filterProviders(\"\");\n\t}\n\n\tprivate inActiveCategory(provider: AuthSelectorProvider): boolean {\n\t\treturn (provider.category ?? \"provider\") === this.activeCategory;\n\t}\n\n\tprivate switchCategory(direction: 1 | -1): void {\n\t\tif (this.categories.length < 2) return;\n\t\tconst current = this.categories.indexOf(this.activeCategory);\n\t\tconst next = (current + direction + this.categories.length) % this.categories.length;\n\t\tthis.activeCategory = this.categories[next];\n\t\tthis.selectedIndex = 0;\n\t\tthis.searchInput.setValue(\"\");\n\t\tthis.filterProviders(\"\");\n\t}\n\n\tprivate updateTabBar(): void {\n\t\tif (!this.tabBar) return;\n\t\tconst labels: Record<AuthSelectorCategory, string> = {\n\t\t\tprovider: \"Providers\",\n\t\t\tservice: \"MCP Connections\",\n\t\t};\n\t\tconst rendered = this.categories\n\t\t\t.map((category) =>\n\t\t\t\tcategory === this.activeCategory\n\t\t\t\t\t? theme.bold(theme.fg(\"accent\", labels[category]))\n\t\t\t\t\t: theme.fg(\"muted\", labels[category]),\n\t\t\t)\n\t\t\t.join(theme.fg(\"muted\", \" · \"));\n\t\tthis.tabBar.setText(`${rendered} ${theme.fg(\"muted\", \"←/→ switch\")}`);\n\t}\n\n\tprivate filterProviders(query: string): void {\n\t\tconst queryChanged = query !== this.searchQuery;\n\t\tthis.searchQuery = query;\n\t\tconst inCategory = this.allProviders.filter((p) => this.inActiveCategory(p));\n\t\tthis.filteredProviders = query\n\t\t\t? fuzzyFilter(inCategory, query, (provider) => `${provider.name} ${provider.id} ${provider.authType}`)\n\t\t\t: inCategory;\n\t\tthis.selectedIndex = queryChanged\n\t\t\t? 0\n\t\t\t: Math.max(0, Math.min(this.selectedIndex, Math.max(0, this.filteredProviders.length - 1)));\n\t\tthis.updateTabBar();\n\t\tthis.updateList();\n\t}\n\n\tprivate sortProviders(providers: AuthSelectorProvider[]): AuthSelectorProvider[] {\n\t\treturn [...providers].sort((a, b) => {\n\t\t\tconst rankDelta = this.getProviderSortRank(a) - this.getProviderSortRank(b);\n\t\t\tif (rankDelta !== 0) {\n\t\t\t\treturn rankDelta;\n\t\t\t}\n\t\t\treturn compareAuthSelectorProviders(a, b);\n\t\t});\n\t}\n\n\trefresh(): void {\n\t\tconst selected = this.filteredProviders[this.selectedIndex];\n\t\tthis.allProviders = this.sortProviders(this.allProviders);\n\t\tthis.filterProviders(this.searchInput.getValue());\n\t\tif (selected) {\n\t\t\tconst selectedIndex = this.filteredProviders.findIndex(\n\t\t\t\t(provider) => provider.id === selected.id && provider.authType === selected.authType,\n\t\t\t);\n\t\t\tif (selectedIndex >= 0) {\n\t\t\t\tthis.selectedIndex = selectedIndex;\n\t\t\t\tthis.updateList();\n\t\t\t}\n\t\t}\n\t}\n\n\tgetSearchInput(): MenuSearchInput {\n\t\treturn this.searchInput;\n\t}\n\n\tprivate getProviderSortRank(provider: AuthSelectorProvider): number {\n\t\tif (this.isProviderConfigured(provider)) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (this.isProviderStale(provider)) {\n\t\t\treturn 1;\n\t\t}\n\t\treturn 2;\n\t}\n\n\tprivate isProviderStale(provider: AuthSelectorProvider): boolean {\n\t\tconst status = this.getAuthStatus(provider.id);\n\t\tconst credential = this.authStorage.get(provider.id);\n\t\tconst storageStatus = this.authStorage.getAuthStatus(provider.id);\n\t\treturn status.source === \"stale\" || (storageStatus.source === \"stale\" && credential?.type === provider.authType);\n\t}\n\n\tprivate isProviderConfigured(provider: AuthSelectorProvider): boolean {\n\t\tconst status = this.getAuthStatus(provider.id);\n\t\tconst credential = this.authStorage.get(provider.id);\n\t\tif (this.isProviderStale(provider)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (status.source && status.source !== \"stored\") {\n\t\t\treturn provider.authType === \"api_key\";\n\t\t}\n\n\t\tif (credential) {\n\t\t\treturn status.configured;\n\t\t}\n\t\tif (provider.authType !== \"api_key\") {\n\t\t\treturn false;\n\t\t}\n\t\treturn status.source !== undefined;\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst previousLayout = this.listLayout;\n\t\tthis.updateLayout();\n\t\tif (\n\t\t\tthis.listLayout.compact !== previousLayout.compact ||\n\t\t\tthis.listLayout.visibleItems !== previousLayout.visibleItems\n\t\t) {\n\t\t\tthis.updateList();\n\t\t}\n\t\treturn super.render(width);\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.updateLayout();\n\t\tthis.listContainer.clear();\n\n\t\tconst maxVisible = this.listLayout.visibleItems;\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(maxVisible / 2), this.filteredProviders.length - maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.filteredProviders.length);\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst provider = this.filteredProviders[i];\n\t\t\tif (!provider) continue;\n\n\t\t\tconst isSelected = i === this.selectedIndex;\n\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew MenuRow({\n\t\t\t\t\tprimary: provider.name,\n\t\t\t\t\tsecondary: provider.authType === \"oauth\" ? \"subscription\" : \"api key\",\n\t\t\t\t\tmeta: this.formatStatusIndicator(provider),\n\t\t\t\t\tselected: isSelected,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\tif (startIndex > 0 || endIndex < this.filteredProviders.length) {\n\t\t\tconst scrollInfo = theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filteredProviders.length})`);\n\t\t\tthis.listContainer.addChild(new TruncatedText(scrollInfo, 1, 0));\n\t\t}\n\n\t\tif (this.filteredProviders.length === 0) {\n\t\t\tconst message =\n\t\t\t\tthis.allProviders.length === 0\n\t\t\t\t\t? this.mode === \"login\"\n\t\t\t\t\t\t? \"No providers available\"\n\t\t\t\t\t\t: \"No providers logged in. Use /login first.\"\n\t\t\t\t\t: \"No matching providers\";\n\t\t\tthis.listContainer.addChild(new TruncatedText(theme.fg(\"muted\", message), 1, 0));\n\t\t}\n\t}\n\n\tprivate formatStatusIndicator(provider: AuthSelectorProvider): string {\n\t\tconst status = this.getAuthStatus(provider.id);\n\t\tconst credential = this.authStorage.get(provider.id);\n\t\tif (this.isProviderStale(provider)) {\n\t\t\treturn theme.fg(\"warning\", status.label ?? \"expired\");\n\t\t}\n\t\tif (\n\t\t\tcredential?.type === \"oauth\" &&\n\t\t\tgetProviderAuthContract(provider.id).oauth !== \"supported\" &&\n\t\t\t(provider.authType === \"oauth\" || (!status.configured && !status.source))\n\t\t) {\n\t\t\treturn theme.fg(\"warning\", \"saved OAuth unavailable\");\n\t\t}\n\t\tif (!status.configured && !status.source) return theme.fg(\"muted\", \"unconfigured\");\n\n\t\tif (status.source && status.source !== \"stored\") {\n\t\t\treturn provider.authType === \"api_key\"\n\t\t\t\t? this.formatApiKeyStatusIndicator(status)\n\t\t\t\t: theme.fg(\"muted\", \"unconfigured\");\n\t\t}\n\n\t\tif (credential?.type === provider.authType) return theme.fg(\"success\", \"configured\");\n\t\tif (credential) {\n\t\t\tconst label = credential.type === \"oauth\" ? \"subscription configured\" : \"API key configured\";\n\t\t\treturn theme.fg(\"warning\", label);\n\t\t}\n\t\tif (provider.authType !== \"api_key\") return theme.fg(\"muted\", \"unconfigured\");\n\n\t\treturn this.formatApiKeyStatusIndicator(status);\n\t}\n\n\tprivate formatApiKeyStatusIndicator(status: AuthStatus): string {\n\t\tswitch (status.source) {\n\t\t\tcase \"environment\":\n\t\t\t\treturn theme.fg(\"success\", `env: ${status.label ?? \"API key\"}`);\n\t\t\tcase \"runtime\":\n\t\t\t\treturn theme.fg(\"success\", \"runtime API key\");\n\t\t\tcase \"fallback\":\n\t\t\t\treturn theme.fg(\"success\", \"custom API key\");\n\t\t\tcase \"models_json_key\":\n\t\t\t\treturn theme.fg(\"success\", \"key in models.json\");\n\t\t\tcase \"models_json_command\":\n\t\t\t\treturn theme.fg(\"success\", \"command in models.json\");\n\t\t\tdefault:\n\t\t\t\treturn theme.fg(\"muted\", \"unconfigured\");\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.filteredProviders.length === 0) return;\n\t\t\tthis.selectedIndex = Math.max(0, this.selectedIndex - 1);\n\t\t\tthis.updateList();\n\t\t} else if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.filteredProviders.length === 0) return;\n\t\t\tthis.selectedIndex = Math.min(this.filteredProviders.length - 1, this.selectedIndex + 1);\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Only steal left/right for tabs when the search field is empty, so cursor\n\t\t// editing still works while filtering.\n\t\telse if (\n\t\t\tthis.categories.length > 1 &&\n\t\t\tthis.searchInput.getValue() === \"\" &&\n\t\t\tkb.matches(keyData, \"tui.editor.cursorLeft\")\n\t\t) {\n\t\t\tthis.switchCategory(-1);\n\t\t} else if (\n\t\t\tthis.categories.length > 1 &&\n\t\t\tthis.searchInput.getValue() === \"\" &&\n\t\t\tkb.matches(keyData, \"tui.editor.cursorRight\")\n\t\t) {\n\t\t\tthis.switchCategory(1);\n\t\t} else if (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tconst selectedProvider = this.filteredProviders[this.selectedIndex];\n\t\t\tif (selectedProvider) {\n\t\t\t\tthis.onSelectCallback(selectedProvider);\n\t\t\t}\n\t\t} else if (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t} else {\n\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\tthis.filterProviders(this.searchInput.getValue());\n\t\t}\n\t}\n\n\tprivate get reservedRows(): number {\n\t\treturn PROVIDER_LIST_RESERVED_ROWS + this.getHeaderRows() + (this.tabBar ? TAB_BAR_RESERVED_ROWS : 0);\n\t}\n\n\tprivate updateLayout(): void {\n\t\tthis.listLayout = getMenuListLayout({\n\t\t\tgetRows: this.viewport.getRows,\n\t\t\tpreferredVisibleItems: PREFERRED_VISIBLE_PROVIDERS,\n\t\t\ttotalItems: this.filteredProviders.length,\n\t\t\treservedRows: this.reservedRows,\n\t\t\tcomfortableItemRows: 3,\n\t\t\tcompactItemRows: 2,\n\t\t\tscrollIndicatorRows: PROVIDER_SCROLL_INDICATOR_ROWS,\n\t\t});\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-hints.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/feature-hints.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,WAAW,kBAAkB;IAClC,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;IACzD,iBAAiB,EAAE,OAAO,CAAC;CAC3B;AAED,UAAU,qBAAqB;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAAC;CACzD;AAED,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,aAAa,EAAE,SAAS,qBAAqB,
|
|
1
|
+
{"version":3,"file":"feature-hints.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/feature-hints.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,WAAW,kBAAkB;IAClC,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;IACzD,iBAAiB,EAAE,OAAO,CAAC;CAC3B;AAED,UAAU,qBAAqB;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAAC;CACzD;AAED,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,aAAa,EAAE,SAAS,qBAAqB,EAoFhD,CAAC;AAEX,qBAAa,eAAe;IAC3B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,UAAU,CAAqB;IAEvC,IAAI,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,GAAG,SAAS,CASzD;IAED,OAAO,CAAC,MAAM;CAcd","sourcesContent":["import type { AppKeybinding } from \"../../core/keybindings.js\";\n\nexport interface FeatureHintContext {\n\tgetKeybinding(action: AppKeybinding): string | undefined;\n\tisResidentSession: boolean;\n}\n\ninterface FeatureHintDefinition {\n\tid: string;\n\tgetText(context: FeatureHintContext): string | undefined;\n}\n\nexport interface FeatureHint {\n\tid: string;\n\ttext: string;\n}\n\nexport const FEATURE_HINTS: readonly FeatureHintDefinition[] = [\n\t{\n\t\tid: \"side-question\",\n\t\tgetText: () => \"Use /btw <question> to ask questions without interrupting your agent.\",\n\t},\n\t{\n\t\tid: \"prompt-stash\",\n\t\tgetText: ({ getKeybinding }) => {\n\t\t\tconst key = getKeybinding(\"app.prompt.stash\");\n\t\t\treturn key ? `Press ${key} to stash your prompt and restore it later.` : undefined;\n\t\t},\n\t},\n\t{\n\t\tid: \"follow-up\",\n\t\tgetText: ({ getKeybinding }) => {\n\t\t\tconst key = getKeybinding(\"app.message.followUp\");\n\t\t\treturn key ? `Press ${key} to send a message after your agent finishes.` : undefined;\n\t\t},\n\t},\n\t{\n\t\tid: \"heartbeat\",\n\t\tgetText: () => \"Use /heartbeat every 10m <instruction> to repeat a task on a schedule.\",\n\t},\n\t{\n\t\tid: \"subagents\",\n\t\tgetText: () => \"Base Context can delegate tasks to subagents and run them in parallel.\",\n\t},\n\t{\n\t\tid: \"agents-view\",\n\t\tgetText: ({ getKeybinding, isResidentSession }) => {\n\t\t\tif (!isResidentSession) return undefined;\n\t\t\tconst key = getKeybinding(\"app.agents.back\");\n\t\t\treturn key ? `Hit ${key} for Session View: search running, idle, and inactive sessions.` : undefined;\n\t\t},\n\t},\n\t{\n\t\tid: \"session-rewind\",\n\t\tgetText: () => \"Run /tree to open the session tree and return to a previous message.\",\n\t},\n\t{\n\t\tid: \"steering\",\n\t\tgetText: () => \"Send a message while your agent works to steer its current task.\",\n\t},\n\t{\n\t\tid: \"agent-messaging\",\n\t\tgetText: () => \"Agents can message each other to share context and coordinate their work.\",\n\t},\n\t{\n\t\tid: \"goal\",\n\t\tgetText: () => \"Use /goal <objective> to keep your agent working until the goal is complete.\",\n\t},\n\t{\n\t\tid: \"refine\",\n\t\tgetText: () => \"Use /refine to turn useful lessons into reusable skills, memory, and prompts.\",\n\t},\n\t{\n\t\tid: \"persistent-ipython\",\n\t\tgetText: () => \"Compaction removes kernel variables over 16 MiB; smaller state persists.\",\n\t},\n\t{\n\t\tid: \"context-usage\",\n\t\tgetText: () => \"Use /context to check token usage, cost, and remaining context.\",\n\t},\n\t{\n\t\tid: \"session-fork\",\n\t\tgetText: () => \"Use /fork to start a new session from an earlier prompt.\",\n\t},\n\t{\n\t\tid: \"compaction\",\n\t\tgetText: () => \"Use /compact <instructions> to summarize old messages and free up context.\",\n\t},\n\t{\n\t\tid: \"auto-compaction\",\n\t\tgetText: () => \"Base Context automatically compacts long sessions before context fills up.\",\n\t},\n\t{\n\t\tid: \"auto-refine\",\n\t\tgetText: () => \"Base Context self-improves by refining skills, memories, prompts, and subagents.\",\n\t},\n\t{\n\t\tid: \"background-running\",\n\t\tgetText: ({ isResidentSession }) =>\n\t\t\tisResidentSession ? \"You can close the terminal while your agent keeps running in the background.\" : undefined,\n\t},\n] as const;\n\nexport class FeatureHintDeck {\n\tprivate remaining: FeatureHint[] = [];\n\tprivate previousId: string | undefined;\n\n\tnext(context: FeatureHintContext): FeatureHint | undefined {\n\t\tif (this.remaining.length === 0) {\n\t\t\tthis.refill(context);\n\t\t}\n\t\tconst hint = this.remaining.pop();\n\t\tif (hint) {\n\t\t\tthis.previousId = hint.id;\n\t\t}\n\t\treturn hint;\n\t}\n\n\tprivate refill(context: FeatureHintContext): void {\n\t\tconst hints = FEATURE_HINTS.flatMap((hint) => {\n\t\t\tconst text = hint.getText(context);\n\t\t\treturn text ? [{ id: hint.id, text }] : [];\n\t\t});\n\t\tfor (let index = hints.length - 1; index > 0; index--) {\n\t\t\tconst target = Math.floor(Math.random() * (index + 1));\n\t\t\t[hints[index], hints[target]] = [hints[target]!, hints[index]!];\n\t\t}\n\t\tif (hints.length > 1 && hints[hints.length - 1]?.id === this.previousId) {\n\t\t\t[hints[0], hints[hints.length - 1]] = [hints[hints.length - 1]!, hints[0]!];\n\t\t}\n\t\tthis.remaining = hints;\n\t}\n}\n"]}
|
|
@@ -54,10 +54,6 @@ export const FEATURE_HINTS = [
|
|
|
54
54
|
id: "refine",
|
|
55
55
|
getText: () => "Use /refine to turn useful lessons into reusable skills, memory, and prompts.",
|
|
56
56
|
},
|
|
57
|
-
{
|
|
58
|
-
id: "trace-sharing",
|
|
59
|
-
getText: () => "Share traces with Prime Intellect using /traces on to train open-source LLMs.",
|
|
60
|
-
},
|
|
61
57
|
{
|
|
62
58
|
id: "persistent-ipython",
|
|
63
59
|
getText: () => "Compaction removes kernel variables over 16 MiB; smaller state persists.",
|