gsd-pi 2.76.0-dev.4100bd590 → 2.76.0-dev.76f9a2dc5
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/dist/resource-loader.d.ts +1 -1
- package/dist/resource-loader.js +2 -8
- package/dist/resources/extensions/gsd/auto/phases.js +4 -1
- package/dist/resources/extensions/gsd/auto/session.js +4 -0
- package/dist/resources/extensions/gsd/auto-model-selection.js +13 -2
- package/dist/resources/extensions/gsd/auto-start.js +12 -7
- package/dist/resources/extensions/gsd/auto.js +4 -1
- package/dist/resources/extensions/gsd/complexity-classifier.js +5 -3
- package/dist/resources/extensions/gsd/init-wizard.js +15 -1
- package/dist/resources/extensions/gsd/prompt-loader.js +22 -7
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +1 -1
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +20 -20
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +20 -20
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +60 -15
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/providers/think-tag-parser.d.ts +17 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.js +75 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.js.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.js +41 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.js.map +1 -0
- package/packages/pi-ai/src/providers/openai-completions.ts +57 -16
- package/packages/pi-ai/src/providers/think-tag-parser.test.ts +44 -0
- package/packages/pi-ai/src/providers/think-tag-parser.ts +94 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.js +92 -12
- package/packages/pi-coding-agent/dist/core/model-discovery.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.test.js +16 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js +61 -1
- package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +76 -10
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +5 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +13 -7
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts +7 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js +29 -21
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/packages/pi-coding-agent/src/core/model-discovery.test.ts +19 -0
- package/packages/pi-coding-agent/src/core/model-discovery.ts +99 -12
- package/packages/pi-coding-agent/src/core/model-registry-discovery.test.ts +75 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +86 -10
- package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +6 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +16 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts +36 -22
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/scripts/link-workspace-packages.cjs +1 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/phases.ts +4 -0
- package/src/resources/extensions/gsd/auto/session.ts +7 -1
- package/src/resources/extensions/gsd/auto-model-selection.ts +16 -1
- package/src/resources/extensions/gsd/auto-start.ts +12 -7
- package/src/resources/extensions/gsd/auto.ts +4 -1
- package/src/resources/extensions/gsd/complexity-classifier.ts +5 -3
- package/src/resources/extensions/gsd/init-wizard.ts +15 -1
- package/src/resources/extensions/gsd/prompt-loader.ts +30 -7
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +33 -3
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +49 -0
- /package/dist/web/standalone/.next/static/{YnUwu2WWaT0_hyTLUF4nq → UMCfv_sVnLXawpUAjvArc}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{YnUwu2WWaT0_hyTLUF4nq → UMCfv_sVnLXawpUAjvArc}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-manager.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/provider-manager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * TUI component for managing provider configurations.\n * Shows providers with auth status, discovery support, and model counts.\n */\n\nimport {\n\tContainer,\n\ttype Focusable,\n\tgetEditorKeybindings,\n\tSpacer,\n\tText,\n\ttype TUI,\n} from \"@gsd/pi-tui\";\nimport type { AuthStorage } from \"../../../core/auth-storage.js\";\nimport { getDiscoverableProviders } from \"../../../core/model-discovery.js\";\nimport { providerDisplayName } from \"./model-selector.js\";\nimport type { ModelRegistry } from \"../../../core/model-registry.js\";\nimport { ModelsJsonWriter } from \"../../../core/models-json-writer.js\";\nimport { theme } from \"../theme/theme.js\";\nimport { rawKeyHint } from \"./keybinding-hints.js\";\n\ninterface ProviderInfo {\n\tname: string;\n\thasAuth: boolean;\n\tsupportsDiscovery: boolean;\n\tmodelCount: number;\n}\n\nexport class ProviderManagerComponent extends Container implements Focusable {\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}\n\n\tprivate providers: ProviderInfo[] = [];\n\tprivate selectedIndex = 0;\n\tprivate listContainer: Container;\n\tprivate tui: TUI;\n\tprivate authStorage: AuthStorage;\n\tprivate modelRegistry: ModelRegistry;\n\tprivate modelsJsonWriter: ModelsJsonWriter;\n\tprivate onDone: () => void;\n\tprivate onDiscover: (provider: string) => void;\n\tprivate onSetupAuth: (provider: string) => void;\n\tprivate confirmingRemove = false;\n\tprivate hintsContainer: Container;\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tauthStorage: AuthStorage,\n\t\tmodelRegistry: ModelRegistry,\n\t\tonDone: () => void,\n\t\tonDiscover: (provider: string) => void,\n\t\tonSetupAuth?: (provider: string) => void,\n\t) {\n\t\tsuper();\n\n\t\tthis.tui = tui;\n\t\tthis.authStorage = authStorage;\n\t\tthis.modelRegistry = modelRegistry;\n\t\tthis.modelsJsonWriter = new ModelsJsonWriter(this.modelRegistry.modelsJsonPath);\n\t\tthis.onDone = onDone;\n\t\tthis.onDiscover = onDiscover;\n\t\tthis.onSetupAuth = onSetupAuth ?? (() => {});\n\n\t\t// Header\n\t\tthis.addChild(new Text(theme.fg(\"accent\", \"Provider Manager\"), 0, 0));\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Hints\n\t\tthis.hintsContainer = new Container();\n\t\tthis.addChild(this.hintsContainer);\n\t\tthis.updateHints();\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// List\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\tthis.loadProviders();\n\t\tthis.updateList();\n\t}\n\n\tprivate loadProviders(): void {\n\t\tconst discoverableSet = new Set(getDiscoverableProviders());\n\t\tconst allModels = this.modelRegistry.getAll();\n\n\t\t// Group models by provider\n\t\tconst providerModelCounts = new Map<string, number>();\n\t\tfor (const model of allModels) {\n\t\t\tproviderModelCounts.set(model.provider, (providerModelCounts.get(model.provider) ?? 0) + 1);\n\t\t}\n\n\t\t// Build provider list from all known providers\n\t\tconst providerNames = new Set([\n\t\t\t...providerModelCounts.keys(),\n\t\t\t...discoverableSet,\n\t\t]);\n\n\t\tthis.providers = Array.from(providerNames)\n\t\t\t.sort()\n\t\t\t.map((name) => ({\n\t\t\t\tname,\n\t\t\t\thasAuth: this.authStorage.hasAuth(name),\n\t\t\t\tsupportsDiscovery: discoverableSet.has(name),\n\t\t\t\tmodelCount: providerModelCounts.get(name) ?? 0,\n\t\t\t}));\n\t\tthis.clampSelectedIndex();\n\t}\n\n\tprivate clampSelectedIndex(): void {\n\t\tif (this.providers.length === 0) {\n\t\t\tthis.selectedIndex = 0;\n\t\t\treturn;\n\t\t}\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.providers.length - 1);\n\t}\n\n\tprivate updateHints(): void {\n\t\tthis.hintsContainer.clear();\n\t\tif (this.confirmingRemove) {\n\t\t\tconst hints = [\n\t\t\t\trawKeyHint(\"r\", \"confirm removal\"),\n\t\t\t\trawKeyHint(\"esc\", \"cancel\"),\n\t\t\t].join(\" \");\n\t\t\tthis.hintsContainer.addChild(new Text(hints, 0, 0));\n\t\t} else {\n\t\t\tconst hints = [\n\t\t\t\trawKeyHint(\"enter\", \"setup auth\"),\n\t\t\t\trawKeyHint(\"d\", \"discover\"),\n\t\t\t\trawKeyHint(\"r\", \"remove auth\"),\n\t\t\t\trawKeyHint(\"esc\", \"close\"),\n\t\t\t].join(\" \");\n\t\t\tthis.hintsContainer.addChild(new Text(hints, 0, 0));\n\t\t}\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\n\t\tfor (let i = 0; i < this.providers.length; i++) {\n\t\t\tconst p = this.providers[i];\n\t\t\tconst isSelected = i === this.selectedIndex;\n\n\t\t\tconst authBadge = p.hasAuth ? theme.fg(\"success\", \"[auth]\") : theme.fg(\"muted\", \"[no auth]\");\n\t\t\tconst discoveryBadge = p.supportsDiscovery ? theme.fg(\"accent\", \"[discovery]\") : \"\";\n\t\t\tconst countBadge = theme.fg(\"muted\", `(${p.modelCount} models)`);\n\n\t\t\tconst prefix = isSelected ? theme.fg(\"accent\", \"> \") : \" \";\n\t\t\tconst nameText = isSelected ? theme.fg(\"accent\", providerDisplayName(p.name)) : providerDisplayName(p.name);\n\n\t\t\tconst parts = [prefix, nameText, \" \", authBadge];\n\t\t\tif (discoveryBadge) parts.push(\" \", discoveryBadge);\n\t\t\tparts.push(\" \", countBadge);\n\n\t\t\tthis.listContainer.addChild(new Text(parts.join(\"\"), 0, 0));\n\t\t}\n\n\t\tif (this.providers.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No providers configured\"), 0, 0));\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getEditorKeybindings();\n\n\t\tif (kb.matches(keyData, \"selectUp\")) {\n\t\t\tif (this.providers.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.providers.length - 1 : this.selectedIndex - 1;\n\t\t\tthis.updateList();\n\t\t\tthis.tui.requestRender();\n\t\t} else if (kb.matches(keyData, \"selectDown\")) {\n\t\t\tif (this.providers.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.providers.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\tthis.updateList();\n\t\t\tthis.tui.requestRender();\n\t\t} else if (kb.matches(keyData, \"selectCancel\")) {\n\t\t\tif (this.confirmingRemove) {\n\t\t\t\tthis.confirmingRemove = false;\n\t\t\t\tthis.updateHints();\n\t\t\t\tthis.tui.requestRender();\n\t\t\t} else {\n\t\t\t\tthis.onDone();\n\t\t\t}\n\t\t} else if (keyData === \"d\" || keyData === \"D\") {\n\t\t\tconst provider = this.providers[this.selectedIndex];\n\t\t\tif (provider?.supportsDiscovery) {\n\t\t\t\tthis.onDiscover(provider.name);\n\t\t\t}\n\t\t} else if (keyData === \"r\" || keyData === \"R\") {\n\t\t\tconst provider = this.providers[this.selectedIndex];\n\t\t\tif (provider?.hasAuth) {\n\t\t\t\tif (this.confirmingRemove) {\n\t\t\t\t\tthis.confirmingRemove = false;\n\t\t\t\t\tthis.authStorage.remove(provider.name);\n\t\t\t\t\tthis.modelsJsonWriter.removeProvider(provider.name);\n\t\t\t\t\tthis.modelRegistry.refresh();\n\t\t\t\t\tthis.loadProviders();\n\t\t\t\t\tthis.updateHints();\n\t\t\t\t\tthis.updateList();\n\t\t\t\t\tthis.tui.requestRender();\n\t\t\t\t} else {\n\t\t\t\t\tthis.confirmingRemove = true;\n\t\t\t\t\tthis.updateHints();\n\t\t\t\t\tthis.tui.requestRender();\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (kb.matches(keyData, \"selectConfirm\")) {\n\t\t\t// Enter key → initiate auth setup for the selected provider (#3579)\n\t\t\tconst provider = this.providers[this.selectedIndex];\n\t\t\tif (provider) {\n\t\t\t\tthis.onSetupAuth(provider.name);\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"provider-manager.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/provider-manager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * TUI component for managing provider configurations.\n * Shows providers with auth status, discovery support, and model counts.\n */\n\nimport {\n\tContainer,\n\ttype Focusable,\n\tgetEditorKeybindings,\n\tSpacer,\n\tText,\n\ttype TUI,\n} from \"@gsd/pi-tui\";\nimport type { AuthStorage } from \"../../../core/auth-storage.js\";\nimport { getDiscoverableProviders, getDiscoveryAdapter } from \"../../../core/model-discovery.js\";\nimport { providerDisplayName } from \"./model-selector.js\";\nimport type { ModelRegistry } from \"../../../core/model-registry.js\";\nimport { ModelsJsonWriter } from \"../../../core/models-json-writer.js\";\nimport { theme } from \"../theme/theme.js\";\nimport { rawKeyHint } from \"./keybinding-hints.js\";\n\ninterface ProviderInfo {\n\tname: string;\n\thasAuth: boolean;\n\tsupportsDiscovery: boolean;\n\tmodelCount: number;\n}\n\nexport class ProviderManagerComponent extends Container implements Focusable {\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}\n\n\tprivate providers: ProviderInfo[] = [];\n\tprivate selectedIndex = 0;\n\tprivate listContainer: Container;\n\tprivate tui: TUI;\n\tprivate authStorage: AuthStorage;\n\tprivate modelRegistry: ModelRegistry;\n\tprivate modelsJsonWriter: ModelsJsonWriter;\n\tprivate onDone: () => void;\n\tprivate onDiscover: (provider: string) => void;\n\tprivate onSetupAuth: (provider: string) => void;\n\tprivate confirmingRemove = false;\n\tprivate hintsContainer: Container;\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tauthStorage: AuthStorage,\n\t\tmodelRegistry: ModelRegistry,\n\t\tonDone: () => void,\n\t\tonDiscover: (provider: string) => void,\n\t\tonSetupAuth?: (provider: string) => void,\n\t) {\n\t\tsuper();\n\n\t\tthis.tui = tui;\n\t\tthis.authStorage = authStorage;\n\t\tthis.modelRegistry = modelRegistry;\n\t\tthis.modelsJsonWriter = new ModelsJsonWriter(this.modelRegistry.modelsJsonPath);\n\t\tthis.onDone = onDone;\n\t\tthis.onDiscover = onDiscover;\n\t\tthis.onSetupAuth = onSetupAuth ?? (() => {});\n\n\t\t// Header\n\t\tthis.addChild(new Text(theme.fg(\"accent\", \"Provider Manager\"), 0, 0));\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Hints\n\t\tthis.hintsContainer = new Container();\n\t\tthis.addChild(this.hintsContainer);\n\t\tthis.updateHints();\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// List\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\tthis.loadProviders();\n\t\tthis.updateList();\n\t}\n\n\tprivate loadProviders(): void {\n\t\tconst discoverableSet = new Set(getDiscoverableProviders());\n\t\tconst allModels = this.modelRegistry.getAll();\n\n\t\t// Group models by provider\n\t\tconst providerModelCounts = new Map<string, number>();\n\t\tfor (const model of allModels) {\n\t\t\tproviderModelCounts.set(model.provider, (providerModelCounts.get(model.provider) ?? 0) + 1);\n\t\t}\n\n\t\t// Build provider list from all known providers\n\t\tconst providerNames = new Set([\n\t\t\t...providerModelCounts.keys(),\n\t\t\t...discoverableSet,\n\t\t]);\n\n\t\tthis.providers = Array.from(providerNames)\n\t\t\t.sort()\n\t\t\t.map((name) => {\n\t\t\t\tconst providerApis = new Set(\n\t\t\t\t\tallModels\n\t\t\t\t\t\t.filter((m) => m.provider === name)\n\t\t\t\t\t\t.map((m) => m.api)\n\t\t\t\t\t\t.filter((api): api is string => typeof api === \"string\" && api.length > 0),\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tname,\n\t\t\t\t\thasAuth: this.authStorage.hasAuth(name),\n\t\t\t\t\tsupportsDiscovery:\n\t\t\t\t\t\tdiscoverableSet.has(name) || getDiscoveryAdapter(name, providerApis).supportsDiscovery,\n\t\t\t\t\tmodelCount: providerModelCounts.get(name) ?? 0,\n\t\t\t\t};\n\t\t\t});\n\t\tthis.clampSelectedIndex();\n\t}\n\n\tprivate clampSelectedIndex(): void {\n\t\tif (this.providers.length === 0) {\n\t\t\tthis.selectedIndex = 0;\n\t\t\treturn;\n\t\t}\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.providers.length - 1);\n\t}\n\n\tprivate updateHints(): void {\n\t\tthis.hintsContainer.clear();\n\t\tif (this.confirmingRemove) {\n\t\t\tconst hints = [\n\t\t\t\trawKeyHint(\"r\", \"confirm removal\"),\n\t\t\t\trawKeyHint(\"esc\", \"cancel\"),\n\t\t\t].join(\" \");\n\t\t\tthis.hintsContainer.addChild(new Text(hints, 0, 0));\n\t\t} else {\n\t\t\tconst hints = [\n\t\t\t\trawKeyHint(\"enter\", \"setup auth\"),\n\t\t\t\trawKeyHint(\"d\", \"discover\"),\n\t\t\t\trawKeyHint(\"r\", \"remove auth\"),\n\t\t\t\trawKeyHint(\"esc\", \"close\"),\n\t\t\t].join(\" \");\n\t\t\tthis.hintsContainer.addChild(new Text(hints, 0, 0));\n\t\t}\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\n\t\tfor (let i = 0; i < this.providers.length; i++) {\n\t\t\tconst p = this.providers[i];\n\t\t\tconst isSelected = i === this.selectedIndex;\n\n\t\t\tconst authBadge = p.hasAuth ? theme.fg(\"success\", \"[auth]\") : theme.fg(\"muted\", \"[no auth]\");\n\t\t\tconst discoveryBadge = p.supportsDiscovery ? theme.fg(\"accent\", \"[discovery]\") : \"\";\n\t\t\tconst countBadge = theme.fg(\"muted\", `(${p.modelCount} models)`);\n\n\t\t\tconst prefix = isSelected ? theme.fg(\"accent\", \"> \") : \" \";\n\t\t\tconst nameText = isSelected ? theme.fg(\"accent\", providerDisplayName(p.name)) : providerDisplayName(p.name);\n\n\t\t\tconst parts = [prefix, nameText, \" \", authBadge];\n\t\t\tif (discoveryBadge) parts.push(\" \", discoveryBadge);\n\t\t\tparts.push(\" \", countBadge);\n\n\t\t\tthis.listContainer.addChild(new Text(parts.join(\"\"), 0, 0));\n\t\t}\n\n\t\tif (this.providers.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No providers configured\"), 0, 0));\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getEditorKeybindings();\n\n\t\tif (kb.matches(keyData, \"selectUp\")) {\n\t\t\tif (this.providers.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.providers.length - 1 : this.selectedIndex - 1;\n\t\t\tthis.updateList();\n\t\t\tthis.tui.requestRender();\n\t\t} else if (kb.matches(keyData, \"selectDown\")) {\n\t\t\tif (this.providers.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.providers.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\tthis.updateList();\n\t\t\tthis.tui.requestRender();\n\t\t} else if (kb.matches(keyData, \"selectCancel\")) {\n\t\t\tif (this.confirmingRemove) {\n\t\t\t\tthis.confirmingRemove = false;\n\t\t\t\tthis.updateHints();\n\t\t\t\tthis.tui.requestRender();\n\t\t\t} else {\n\t\t\t\tthis.onDone();\n\t\t\t}\n\t\t} else if (keyData === \"d\" || keyData === \"D\") {\n\t\t\tconst provider = this.providers[this.selectedIndex];\n\t\t\tif (provider?.supportsDiscovery) {\n\t\t\t\tthis.onDiscover(provider.name);\n\t\t\t}\n\t\t} else if (keyData === \"r\" || keyData === \"R\") {\n\t\t\tconst provider = this.providers[this.selectedIndex];\n\t\t\tif (provider?.hasAuth) {\n\t\t\t\tif (this.confirmingRemove) {\n\t\t\t\t\tthis.confirmingRemove = false;\n\t\t\t\t\tthis.authStorage.remove(provider.name);\n\t\t\t\t\tthis.modelsJsonWriter.removeProvider(provider.name);\n\t\t\t\t\tthis.modelRegistry.refresh();\n\t\t\t\t\tthis.loadProviders();\n\t\t\t\t\tthis.updateHints();\n\t\t\t\t\tthis.updateList();\n\t\t\t\t\tthis.tui.requestRender();\n\t\t\t\t} else {\n\t\t\t\t\tthis.confirmingRemove = true;\n\t\t\t\t\tthis.updateHints();\n\t\t\t\t\tthis.tui.requestRender();\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (kb.matches(keyData, \"selectConfirm\")) {\n\t\t\t// Enter key → initiate auth setup for the selected provider (#3579)\n\t\t\tconst provider = this.providers[this.selectedIndex];\n\t\t\tif (provider) {\n\t\t\t\tthis.onSetupAuth(provider.name);\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Container, type MarkdownTheme } from "@gsd/pi-tui";
|
|
2
2
|
import type { ParsedSkillBlock } from "../../../core/agent-session.js";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Renders a skill invocation in the shared chat-frame style (top rule,
|
|
5
|
+
* `• skill - <name>` header, `│ ` body margin) with purple border/label
|
|
6
|
+
* matching compaction so it visually aligns with user/assistant messages.
|
|
7
7
|
*/
|
|
8
|
-
export declare class SkillInvocationMessageComponent extends
|
|
8
|
+
export declare class SkillInvocationMessageComponent extends Container {
|
|
9
9
|
private expanded;
|
|
10
10
|
private skillBlock;
|
|
11
11
|
private markdownTheme;
|
|
12
12
|
constructor(skillBlock: ParsedSkillBlock, markdownTheme?: MarkdownTheme);
|
|
13
13
|
setExpanded(expanded: boolean): void;
|
|
14
14
|
invalidate(): void;
|
|
15
|
-
private
|
|
15
|
+
private rebuild;
|
|
16
|
+
render(width: number): string[];
|
|
16
17
|
}
|
|
17
18
|
//# sourceMappingURL=skill-invocation-message.d.ts.map
|
package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-invocation-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/skill-invocation-message.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"skill-invocation-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/skill-invocation-message.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAY,KAAK,aAAa,EAAQ,MAAM,aAAa,CAAC;AAC5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAKvE;;;;GAIG;AACH,qBAAa,+BAAgC,SAAQ,SAAS;IAC7D,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,aAAa,CAAgB;gBAEzB,UAAU,EAAE,gBAAgB,EAAE,aAAa,GAAE,aAAkC;IAO3F,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAO3B,UAAU,IAAI,IAAI;IAK3B,OAAO,CAAC,OAAO;IAoBN,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAYxC"}
|
package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js
CHANGED
|
@@ -1,45 +1,53 @@
|
|
|
1
|
-
|
|
1
|
+
// GSD / pi-coding-agent — Skill invocation message component
|
|
2
|
+
import { Container, Markdown, Text } from "@gsd/pi-tui";
|
|
2
3
|
import { getMarkdownTheme, theme } from "../theme/theme.js";
|
|
4
|
+
import { renderChatFrame } from "./chat-frame.js";
|
|
3
5
|
import { editorKey } from "./keybinding-hints.js";
|
|
4
6
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* Renders a skill invocation in the shared chat-frame style (top rule,
|
|
8
|
+
* `• skill - <name>` header, `│ ` body margin) with purple border/label
|
|
9
|
+
* matching compaction so it visually aligns with user/assistant messages.
|
|
8
10
|
*/
|
|
9
|
-
export class SkillInvocationMessageComponent extends
|
|
11
|
+
export class SkillInvocationMessageComponent extends Container {
|
|
10
12
|
constructor(skillBlock, markdownTheme = getMarkdownTheme()) {
|
|
11
|
-
super(
|
|
13
|
+
super();
|
|
12
14
|
this.expanded = false;
|
|
13
15
|
this.skillBlock = skillBlock;
|
|
14
16
|
this.markdownTheme = markdownTheme;
|
|
15
|
-
this.
|
|
17
|
+
this.rebuild();
|
|
16
18
|
}
|
|
17
19
|
setExpanded(expanded) {
|
|
18
|
-
this.expanded
|
|
19
|
-
|
|
20
|
+
if (this.expanded !== expanded) {
|
|
21
|
+
this.expanded = expanded;
|
|
22
|
+
this.rebuild();
|
|
23
|
+
}
|
|
20
24
|
}
|
|
21
25
|
invalidate() {
|
|
22
26
|
super.invalidate();
|
|
23
|
-
this.
|
|
27
|
+
this.rebuild();
|
|
24
28
|
}
|
|
25
|
-
|
|
29
|
+
rebuild() {
|
|
26
30
|
this.clear();
|
|
27
31
|
if (this.expanded) {
|
|
28
|
-
|
|
29
|
-
const label = theme.fg("customMessageLabel", theme.bold("[skill]"));
|
|
30
|
-
this.addChild(new Text(label, 0, 0));
|
|
31
|
-
const header = `**${this.skillBlock.name}**\n\n`;
|
|
32
|
-
this.addChild(new Markdown(header + this.skillBlock.content, 0, 0, this.markdownTheme, {
|
|
32
|
+
this.addChild(new Markdown(this.skillBlock.content, 0, 0, this.markdownTheme, {
|
|
33
33
|
color: (text) => theme.fg("customMessageText", text),
|
|
34
34
|
}));
|
|
35
35
|
}
|
|
36
36
|
else {
|
|
37
|
-
|
|
38
|
-
const line = theme.fg("customMessageLabel", theme.bold("[skill]") + " ") +
|
|
39
|
-
theme.fg("customMessageText", this.skillBlock.name) +
|
|
40
|
-
theme.fg("dim", ` (${editorKey("expandTools")} to expand)`);
|
|
41
|
-
this.addChild(new Text(line, 0, 0));
|
|
37
|
+
this.addChild(new Text(theme.fg("dim", `(${editorKey("expandTools")} to expand)`), 0, 0));
|
|
42
38
|
}
|
|
43
39
|
}
|
|
40
|
+
render(width) {
|
|
41
|
+
const frameWidth = Math.max(20, width);
|
|
42
|
+
const contentWidth = Math.max(1, frameWidth - 4);
|
|
43
|
+
const lines = super.render(contentWidth);
|
|
44
|
+
const framed = renderChatFrame(lines, frameWidth, {
|
|
45
|
+
label: `skill - ${this.skillBlock.name}`,
|
|
46
|
+
tone: "skill",
|
|
47
|
+
timestampFormat: "date-time-iso",
|
|
48
|
+
showTimestamp: false,
|
|
49
|
+
});
|
|
50
|
+
return framed.length > 0 ? ["", ...framed] : framed;
|
|
51
|
+
}
|
|
44
52
|
}
|
|
45
53
|
//# sourceMappingURL=skill-invocation-message.js.map
|
package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-invocation-message.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/skill-invocation-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"skill-invocation-message.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/skill-invocation-message.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAsB,IAAI,EAAE,MAAM,aAAa,CAAC;AAE5E,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;GAIG;AACH,MAAM,OAAO,+BAAgC,SAAQ,SAAS;IAK7D,YAAY,UAA4B,EAAE,gBAA+B,gBAAgB,EAAE;QAC1F,KAAK,EAAE,CAAC;QALD,aAAQ,GAAG,KAAK,CAAC;QAMxB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,OAAO,EAAE,CAAC;IAChB,CAAC;IAED,WAAW,CAAC,QAAiB;QAC5B,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAChC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;YACzB,IAAI,CAAC,OAAO,EAAE,CAAC;QAChB,CAAC;IACF,CAAC;IAEQ,UAAU;QAClB,KAAK,CAAC,UAAU,EAAE,CAAC;QACnB,IAAI,CAAC,OAAO,EAAE,CAAC;IAChB,CAAC;IAEO,OAAO;QACd,IAAI,CAAC,KAAK,EAAE,CAAC;QAEb,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,CACZ,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE;gBAC/D,KAAK,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,mBAAmB,EAAE,IAAI,CAAC;aAC5D,CAAC,CACF,CAAC;QACH,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,QAAQ,CACZ,IAAI,IAAI,CACP,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,SAAS,CAAC,aAAa,CAAC,aAAa,CAAC,EAC1D,CAAC,EACD,CAAC,CACD,CACD,CAAC;QACH,CAAC;IACF,CAAC;IAEQ,MAAM,CAAC,KAAa;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QACvC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE;YACjD,KAAK,EAAE,WAAW,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;YACxC,IAAI,EAAE,OAAO;YACb,eAAe,EAAE,eAAe;YAChC,aAAa,EAAE,KAAK;SACpB,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACrD,CAAC;CACD","sourcesContent":["// GSD / pi-coding-agent — Skill invocation message component\nimport { Container, Markdown, type MarkdownTheme, Text } from \"@gsd/pi-tui\";\nimport type { ParsedSkillBlock } from \"../../../core/agent-session.js\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.js\";\nimport { renderChatFrame } from \"./chat-frame.js\";\nimport { editorKey } from \"./keybinding-hints.js\";\n\n/**\n * Renders a skill invocation in the shared chat-frame style (top rule,\n * `• skill - <name>` header, `│ ` body margin) with purple border/label\n * matching compaction so it visually aligns with user/assistant messages.\n */\nexport class SkillInvocationMessageComponent extends Container {\n\tprivate expanded = false;\n\tprivate skillBlock: ParsedSkillBlock;\n\tprivate markdownTheme: MarkdownTheme;\n\n\tconstructor(skillBlock: ParsedSkillBlock, markdownTheme: MarkdownTheme = getMarkdownTheme()) {\n\t\tsuper();\n\t\tthis.skillBlock = skillBlock;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.rebuild();\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tif (this.expanded !== expanded) {\n\t\t\tthis.expanded = expanded;\n\t\t\tthis.rebuild();\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.rebuild();\n\t}\n\n\tprivate rebuild(): void {\n\t\tthis.clear();\n\n\t\tif (this.expanded) {\n\t\t\tthis.addChild(\n\t\t\t\tnew Markdown(this.skillBlock.content, 0, 0, this.markdownTheme, {\n\t\t\t\t\tcolor: (text: string) => theme.fg(\"customMessageText\", text),\n\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\tthis.addChild(\n\t\t\t\tnew Text(\n\t\t\t\t\ttheme.fg(\"dim\", `(${editorKey(\"expandTools\")} to expand)`),\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst frameWidth = Math.max(20, width);\n\t\tconst contentWidth = Math.max(1, frameWidth - 4);\n\t\tconst lines = super.render(contentWidth);\n\t\tconst framed = renderChatFrame(lines, frameWidth, {\n\t\t\tlabel: `skill - ${this.skillBlock.name}`,\n\t\t\ttone: \"skill\",\n\t\t\ttimestampFormat: \"date-time-iso\",\n\t\t\tshowTimestamp: false,\n\t\t});\n\t\treturn framed.length > 0 ? [\"\", ...framed] : framed;\n\t}\n}\n"]}
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
getDefaultTTL,
|
|
6
6
|
getDiscoverableProviders,
|
|
7
7
|
getDiscoveryAdapter,
|
|
8
|
+
supportsDiscoveryForApi,
|
|
8
9
|
} from "./model-discovery.js";
|
|
9
10
|
|
|
10
11
|
// ─── getDiscoveryAdapter ─────────────────────────────────────────────────────
|
|
@@ -52,6 +53,12 @@ describe("getDiscoveryAdapter", () => {
|
|
|
52
53
|
assert.equal(adapter.supportsDiscovery, false);
|
|
53
54
|
});
|
|
54
55
|
|
|
56
|
+
it("returns OpenAI-style adapter for unknown provider with OpenAI-compatible API", () => {
|
|
57
|
+
const adapter = getDiscoveryAdapter("my-proxy", ["openai-completions"]);
|
|
58
|
+
assert.equal(adapter.provider, "my-proxy");
|
|
59
|
+
assert.equal(adapter.supportsDiscovery, true);
|
|
60
|
+
});
|
|
61
|
+
|
|
55
62
|
it("static adapter fetchModels returns empty array", async () => {
|
|
56
63
|
const adapter = getDiscoveryAdapter("anthropic");
|
|
57
64
|
const models = await adapter.fetchModels("key");
|
|
@@ -123,3 +130,15 @@ describe("DISCOVERY_TTLS", () => {
|
|
|
123
130
|
}
|
|
124
131
|
});
|
|
125
132
|
});
|
|
133
|
+
|
|
134
|
+
describe("supportsDiscoveryForApi", () => {
|
|
135
|
+
it("returns true for OpenAI-compatible APIs", () => {
|
|
136
|
+
assert.equal(supportsDiscoveryForApi("openai-completions"), true);
|
|
137
|
+
assert.equal(supportsDiscoveryForApi("openai-responses"), true);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("returns false for non-discoverable APIs", () => {
|
|
141
|
+
assert.equal(supportsDiscoveryForApi("anthropic-messages"), false);
|
|
142
|
+
assert.equal(supportsDiscoveryForApi(undefined), false);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
@@ -26,6 +26,14 @@ export interface ProviderDiscoveryAdapter {
|
|
|
26
26
|
fetchModels(apiKey: string, baseUrl?: string): Promise<DiscoveredModel[]>;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
export const OPENAI_COMPAT_DISCOVERY_APIS = new Set([
|
|
30
|
+
"openai",
|
|
31
|
+
"openai-completions",
|
|
32
|
+
"openai-responses",
|
|
33
|
+
"openai-codex-responses",
|
|
34
|
+
"azure-openai-responses",
|
|
35
|
+
]);
|
|
36
|
+
|
|
29
37
|
/** Per-provider TTLs in milliseconds */
|
|
30
38
|
export const DISCOVERY_TTLS: Record<string, number> = {
|
|
31
39
|
ollama: 5 * 60 * 1000, // 5 minutes (local, models change often)
|
|
@@ -53,10 +61,77 @@ async function fetchWithTimeout(url: string, options: RequestInit = {}, timeoutM
|
|
|
53
61
|
|
|
54
62
|
const OPENAI_EXCLUDED_PREFIXES = ["embedding", "tts", "dall-e", "whisper", "text-embedding", "davinci", "babbage"];
|
|
55
63
|
|
|
64
|
+
function asPositiveNumber(value: unknown): number | undefined {
|
|
65
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) return value;
|
|
66
|
+
if (typeof value === "string") {
|
|
67
|
+
const n = Number.parseFloat(value);
|
|
68
|
+
if (Number.isFinite(n) && n > 0) return n;
|
|
69
|
+
}
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function pickFirstPositiveNumber(record: Record<string, unknown>, keys: string[]): number | undefined {
|
|
74
|
+
for (const key of keys) {
|
|
75
|
+
const value = asPositiveNumber(record[key]);
|
|
76
|
+
if (value !== undefined) return value;
|
|
77
|
+
}
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function discoverInputModalities(rawModel: Record<string, unknown>, id: string): Array<"text" | "image"> {
|
|
82
|
+
const directModalities = rawModel.input_modalities;
|
|
83
|
+
const capabilitiesModalities = (rawModel.capabilities as Record<string, unknown> | undefined)?.input_modalities;
|
|
84
|
+
const source = Array.isArray(directModalities)
|
|
85
|
+
? directModalities
|
|
86
|
+
: Array.isArray(capabilitiesModalities)
|
|
87
|
+
? capabilitiesModalities
|
|
88
|
+
: [];
|
|
89
|
+
const supportsImage = source.some((m) => typeof m === "string" && /image|vision/i.test(m))
|
|
90
|
+
|| /vision|image|omni|multimodal/i.test(id);
|
|
91
|
+
return supportsImage ? ["text", "image"] : ["text"];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function parseOpenAICompatibleModel(rawModel: Record<string, unknown>): DiscoveredModel | undefined {
|
|
95
|
+
const id = typeof rawModel.id === "string" ? rawModel.id : "";
|
|
96
|
+
if (!id) return undefined;
|
|
97
|
+
if (OPENAI_EXCLUDED_PREFIXES.some((prefix) => id.startsWith(prefix))) return undefined;
|
|
98
|
+
|
|
99
|
+
const contextWindow = pickFirstPositiveNumber(rawModel, [
|
|
100
|
+
"context_window",
|
|
101
|
+
"context_length",
|
|
102
|
+
"max_context_length",
|
|
103
|
+
"max_input_tokens",
|
|
104
|
+
"input_token_limit",
|
|
105
|
+
"max_model_len",
|
|
106
|
+
]);
|
|
107
|
+
const maxTokens = pickFirstPositiveNumber(rawModel, [
|
|
108
|
+
"max_output_tokens",
|
|
109
|
+
"output_token_limit",
|
|
110
|
+
"max_completion_tokens",
|
|
111
|
+
"max_tokens",
|
|
112
|
+
]);
|
|
113
|
+
const reasoning = rawModel.reasoning === true
|
|
114
|
+
|| rawModel.supports_reasoning === true
|
|
115
|
+
|| ((rawModel.capabilities as Record<string, unknown> | undefined)?.reasoning === true);
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
id,
|
|
119
|
+
name: typeof rawModel.name === "string" && rawModel.name.length > 0 ? rawModel.name : id,
|
|
120
|
+
contextWindow,
|
|
121
|
+
maxTokens,
|
|
122
|
+
reasoning,
|
|
123
|
+
input: discoverInputModalities(rawModel, id),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
56
127
|
class OpenAIDiscoveryAdapter implements ProviderDiscoveryAdapter {
|
|
57
|
-
provider
|
|
128
|
+
provider: string;
|
|
58
129
|
supportsDiscovery = true;
|
|
59
130
|
|
|
131
|
+
constructor(provider: string) {
|
|
132
|
+
this.provider = provider;
|
|
133
|
+
}
|
|
134
|
+
|
|
60
135
|
async fetchModels(apiKey: string, baseUrl?: string): Promise<DiscoveredModel[]> {
|
|
61
136
|
const url = `${baseUrl ?? "https://api.openai.com"}/v1/models`;
|
|
62
137
|
const response = await fetchWithTimeout(url, {
|
|
@@ -67,14 +142,10 @@ class OpenAIDiscoveryAdapter implements ProviderDiscoveryAdapter {
|
|
|
67
142
|
throw new Error(`OpenAI models API returned ${response.status}: ${response.statusText}`);
|
|
68
143
|
}
|
|
69
144
|
|
|
70
|
-
const data = (await response.json()) as { data
|
|
71
|
-
return data.data
|
|
72
|
-
.
|
|
73
|
-
.
|
|
74
|
-
id: m.id,
|
|
75
|
-
name: m.id,
|
|
76
|
-
input: ["text" as const, "image" as const],
|
|
77
|
-
}));
|
|
145
|
+
const data = (await response.json()) as { data?: Array<Record<string, unknown>> };
|
|
146
|
+
return (data.data ?? [])
|
|
147
|
+
.map((m) => parseOpenAICompatibleModel(m))
|
|
148
|
+
.filter((m): m is DiscoveredModel => !!m);
|
|
78
149
|
}
|
|
79
150
|
}
|
|
80
151
|
|
|
@@ -207,7 +278,7 @@ class StaticDiscoveryAdapter implements ProviderDiscoveryAdapter {
|
|
|
207
278
|
// ─── Registry ────────────────────────────────────────────────────────────────
|
|
208
279
|
|
|
209
280
|
const adapters: Record<string, ProviderDiscoveryAdapter> = {
|
|
210
|
-
openai: new OpenAIDiscoveryAdapter(),
|
|
281
|
+
openai: new OpenAIDiscoveryAdapter("openai"),
|
|
211
282
|
ollama: new OllamaDiscoveryAdapter(),
|
|
212
283
|
openrouter: new OpenRouterDiscoveryAdapter(),
|
|
213
284
|
google: new GoogleDiscoveryAdapter(),
|
|
@@ -220,8 +291,24 @@ const adapters: Record<string, ProviderDiscoveryAdapter> = {
|
|
|
220
291
|
mistral: new StaticDiscoveryAdapter("mistral"),
|
|
221
292
|
};
|
|
222
293
|
|
|
223
|
-
export function
|
|
224
|
-
|
|
294
|
+
export function supportsDiscoveryForApi(api: string | undefined): boolean {
|
|
295
|
+
if (!api) return false;
|
|
296
|
+
return OPENAI_COMPAT_DISCOVERY_APIS.has(api);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export function getDiscoveryAdapter(provider: string, providerApis?: Iterable<string>): ProviderDiscoveryAdapter {
|
|
300
|
+
const known = adapters[provider];
|
|
301
|
+
if (known) return known;
|
|
302
|
+
|
|
303
|
+
if (providerApis) {
|
|
304
|
+
for (const api of providerApis) {
|
|
305
|
+
if (supportsDiscoveryForApi(api)) {
|
|
306
|
+
return new OpenAIDiscoveryAdapter(provider);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return new StaticDiscoveryAdapter(provider);
|
|
225
312
|
}
|
|
226
313
|
|
|
227
314
|
export function getDiscoverableProviders(): string[] {
|
|
@@ -6,6 +6,7 @@ import { afterEach, beforeEach, describe, it } from "node:test";
|
|
|
6
6
|
import { AuthStorage } from "./auth-storage.js";
|
|
7
7
|
import { ModelDiscoveryCache } from "./discovery-cache.js";
|
|
8
8
|
import { getDefaultTTL, getDiscoverableProviders, getDiscoveryAdapter } from "./model-discovery.js";
|
|
9
|
+
import { ModelRegistry } from "./model-registry.js";
|
|
9
10
|
|
|
10
11
|
let testDir: string;
|
|
11
12
|
|
|
@@ -133,3 +134,77 @@ describe("Discovery TTL configuration", () => {
|
|
|
133
134
|
assert.equal(customTTL, defaultTTL);
|
|
134
135
|
});
|
|
135
136
|
});
|
|
137
|
+
|
|
138
|
+
describe("ModelRegistry discovery — OpenAI-compatible custom providers", () => {
|
|
139
|
+
it("discovers custom OpenAI-compatible providers and maps capability metadata", async () => {
|
|
140
|
+
const providerName = `minimax-openai-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
141
|
+
const modelsPath = join(testDir, "models.json");
|
|
142
|
+
writeFileSync(
|
|
143
|
+
modelsPath,
|
|
144
|
+
JSON.stringify(
|
|
145
|
+
{
|
|
146
|
+
providers: {
|
|
147
|
+
[providerName]: {
|
|
148
|
+
baseUrl: "https://api.minimax.example",
|
|
149
|
+
apiKey: "minimax-test-key",
|
|
150
|
+
api: "openai-completions",
|
|
151
|
+
models: [{ id: "bootstrap-model" }],
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
null,
|
|
156
|
+
2,
|
|
157
|
+
),
|
|
158
|
+
"utf-8",
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
const prevFetch = globalThis.fetch;
|
|
162
|
+
let requestedUrl = "";
|
|
163
|
+
globalThis.fetch = (async (input: string | URL | Request) => {
|
|
164
|
+
requestedUrl = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
165
|
+
return new Response(
|
|
166
|
+
JSON.stringify({
|
|
167
|
+
data: [
|
|
168
|
+
{
|
|
169
|
+
id: "MiniMax-M2.7-highspeed",
|
|
170
|
+
name: "MiniMax M2.7 Highspeed",
|
|
171
|
+
context_window: 165000,
|
|
172
|
+
max_output_tokens: 32768,
|
|
173
|
+
supports_reasoning: true,
|
|
174
|
+
input_modalities: ["text", "image"],
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
}),
|
|
178
|
+
{
|
|
179
|
+
status: 200,
|
|
180
|
+
headers: { "content-type": "application/json" },
|
|
181
|
+
},
|
|
182
|
+
);
|
|
183
|
+
}) as typeof globalThis.fetch;
|
|
184
|
+
|
|
185
|
+
try {
|
|
186
|
+
const registry = new ModelRegistry(AuthStorage.inMemory({}), modelsPath);
|
|
187
|
+
// Guard against global cache leakage from prior test runs.
|
|
188
|
+
registry.getDiscoveryCache().clear(providerName);
|
|
189
|
+
const results = await registry.discoverModels([providerName]);
|
|
190
|
+
|
|
191
|
+
const discovery = results.find((r) => r.provider === providerName);
|
|
192
|
+
assert.ok(discovery, "discovery result should include custom provider");
|
|
193
|
+
assert.equal(discovery?.error, undefined, "custom provider discovery should succeed");
|
|
194
|
+
assert.equal(requestedUrl, "https://api.minimax.example/v1/models");
|
|
195
|
+
|
|
196
|
+
const discovered = registry
|
|
197
|
+
.getAllWithDiscovered()
|
|
198
|
+
.find((m) => m.provider === providerName && m.id === "MiniMax-M2.7-highspeed");
|
|
199
|
+
assert.ok(discovered, "discovered model should be merged into model list");
|
|
200
|
+
assert.equal(discovered?.api, "openai-completions");
|
|
201
|
+
assert.equal(discovered?.baseUrl, "https://api.minimax.example");
|
|
202
|
+
assert.equal(discovered?.contextWindow, 165000);
|
|
203
|
+
assert.equal(discovered?.maxTokens, 32768);
|
|
204
|
+
assert.equal(discovered?.reasoning, true);
|
|
205
|
+
assert.deepEqual(discovered?.input, ["text", "image"]);
|
|
206
|
+
} finally {
|
|
207
|
+
globalThis.fetch = prevFetch;
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
});
|
|
@@ -29,7 +29,7 @@ import { getAgentDir } from "../config.js";
|
|
|
29
29
|
import type { AuthStorage } from "./auth-storage.js";
|
|
30
30
|
import { ModelDiscoveryCache } from "./discovery-cache.js";
|
|
31
31
|
import type { DiscoveredModel, DiscoveryResult } from "./model-discovery.js";
|
|
32
|
-
import { getDefaultTTL, getDiscoverableProviders, getDiscoveryAdapter } from "./model-discovery.js";
|
|
32
|
+
import { getDefaultTTL, getDiscoverableProviders, getDiscoveryAdapter, supportsDiscoveryForApi } from "./model-discovery.js";
|
|
33
33
|
import { clearConfigValueCache, resolveConfigValue, resolveHeaders } from "./resolve-config-value.js";
|
|
34
34
|
import { isLocalModel } from "./local-model-check.js";
|
|
35
35
|
|
|
@@ -788,11 +788,12 @@ export class ModelRegistry {
|
|
|
788
788
|
* Results are cached and merged into the registry (never overrides existing models).
|
|
789
789
|
*/
|
|
790
790
|
async discoverModels(providers?: string[]): Promise<DiscoveryResult[]> {
|
|
791
|
-
const targetProviders = providers ??
|
|
791
|
+
const targetProviders = providers ?? this.getAutoDiscoverableProviders();
|
|
792
792
|
const results: DiscoveryResult[] = [];
|
|
793
793
|
|
|
794
794
|
for (const providerName of targetProviders) {
|
|
795
|
-
const
|
|
795
|
+
const providerApis = this.getProviderApis(providerName);
|
|
796
|
+
const adapter = getDiscoveryAdapter(providerName, providerApis);
|
|
796
797
|
if (!adapter.supportsDiscovery) continue;
|
|
797
798
|
|
|
798
799
|
// Skip if cache is still fresh
|
|
@@ -812,8 +813,10 @@ export class ModelRegistry {
|
|
|
812
813
|
const apiKey = await this.authStorage.getApiKey(providerName);
|
|
813
814
|
if (!apiKey && !this.isProviderRequestReady(providerName)) continue;
|
|
814
815
|
|
|
815
|
-
const
|
|
816
|
-
|
|
816
|
+
const baseUrl = this.getProviderBaseUrl(providerName);
|
|
817
|
+
const models = await adapter.fetchModels(apiKey ?? "", baseUrl);
|
|
818
|
+
const ttlMs = this.getDiscoveryTtl(providerName, providerApis);
|
|
819
|
+
this.discoveryCache.set(providerName, models, ttlMs);
|
|
817
820
|
results.push({
|
|
818
821
|
provider: providerName,
|
|
819
822
|
models,
|
|
@@ -865,24 +868,97 @@ export class ModelRegistry {
|
|
|
865
868
|
const converted: Model<Api>[] = [];
|
|
866
869
|
for (const result of results) {
|
|
867
870
|
if (result.error) continue;
|
|
871
|
+
const providerDefaults = this.getDiscoveryProviderDefaults(result.provider);
|
|
868
872
|
for (const dm of result.models) {
|
|
869
873
|
converted.push({
|
|
870
874
|
id: dm.id,
|
|
871
875
|
name: dm.name ?? dm.id,
|
|
872
|
-
api:
|
|
876
|
+
api: providerDefaults.api,
|
|
873
877
|
provider: result.provider,
|
|
874
|
-
baseUrl:
|
|
878
|
+
baseUrl: providerDefaults.baseUrl,
|
|
875
879
|
reasoning: dm.reasoning ?? false,
|
|
876
|
-
input: dm.input ??
|
|
880
|
+
input: dm.input ?? providerDefaults.input,
|
|
877
881
|
cost: dm.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
878
|
-
contextWindow: dm.contextWindow ??
|
|
879
|
-
maxTokens: dm.maxTokens ??
|
|
882
|
+
contextWindow: dm.contextWindow ?? providerDefaults.contextWindow,
|
|
883
|
+
maxTokens: dm.maxTokens ?? providerDefaults.maxTokens,
|
|
880
884
|
} as Model<Api>);
|
|
881
885
|
}
|
|
882
886
|
}
|
|
883
887
|
return converted;
|
|
884
888
|
}
|
|
885
889
|
|
|
890
|
+
private getProviderApis(provider: string): Set<string> {
|
|
891
|
+
const apis = new Set<string>();
|
|
892
|
+
for (const model of this.models) {
|
|
893
|
+
if (model.provider === provider && typeof model.api === "string" && model.api.length > 0) {
|
|
894
|
+
apis.add(model.api);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
const providerConfig = this.registeredProviders.get(provider);
|
|
899
|
+
if (providerConfig?.api) apis.add(providerConfig.api);
|
|
900
|
+
for (const modelDef of providerConfig?.models ?? []) {
|
|
901
|
+
if (modelDef.api) apis.add(modelDef.api);
|
|
902
|
+
}
|
|
903
|
+
return apis;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
private getAutoDiscoverableProviders(): string[] {
|
|
907
|
+
const discoverable = new Set<string>(getDiscoverableProviders());
|
|
908
|
+
for (const provider of new Set(this.models.map((m) => m.provider))) {
|
|
909
|
+
const apis = this.getProviderApis(provider);
|
|
910
|
+
for (const api of apis) {
|
|
911
|
+
if (supportsDiscoveryForApi(api)) {
|
|
912
|
+
discoverable.add(provider);
|
|
913
|
+
break;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
return [...discoverable];
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
private getProviderBaseUrl(provider: string): string | undefined {
|
|
921
|
+
const fromModels = this.models.find((m) => m.provider === provider && typeof m.baseUrl === "string" && m.baseUrl.length > 0);
|
|
922
|
+
if (fromModels?.baseUrl) return fromModels.baseUrl;
|
|
923
|
+
return this.registeredProviders.get(provider)?.baseUrl;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
private getDiscoveryProviderDefaults(provider: string): {
|
|
927
|
+
api: Api;
|
|
928
|
+
baseUrl: string;
|
|
929
|
+
input: ("text" | "image")[];
|
|
930
|
+
contextWindow: number;
|
|
931
|
+
maxTokens: number;
|
|
932
|
+
} {
|
|
933
|
+
const first = this.models.find((m) => m.provider === provider);
|
|
934
|
+
if (first) {
|
|
935
|
+
return {
|
|
936
|
+
api: first.api,
|
|
937
|
+
baseUrl: first.baseUrl,
|
|
938
|
+
input: first.input,
|
|
939
|
+
contextWindow: first.contextWindow,
|
|
940
|
+
maxTokens: first.maxTokens,
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
return {
|
|
945
|
+
api: "openai-completions",
|
|
946
|
+
baseUrl: this.registeredProviders.get(provider)?.baseUrl ?? "",
|
|
947
|
+
input: ["text"],
|
|
948
|
+
contextWindow: 128000,
|
|
949
|
+
maxTokens: 16384,
|
|
950
|
+
};
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
private getDiscoveryTtl(provider: string, providerApis: Set<string>): number {
|
|
954
|
+
for (const api of providerApis) {
|
|
955
|
+
if (supportsDiscoveryForApi(api)) {
|
|
956
|
+
return getDefaultTTL("openai");
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
return getDefaultTTL(provider);
|
|
960
|
+
}
|
|
961
|
+
|
|
886
962
|
/**
|
|
887
963
|
* Check if a model's baseUrl points to a local endpoint.
|
|
888
964
|
* Delegates to standalone isLocalModel() function.
|