gsd-pi 2.41.0 → 2.42.0-dev.eedc83f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -29
- package/dist/cli-web-branch.d.ts +6 -0
- package/dist/cli-web-branch.js +17 -0
- package/dist/cli.js +15 -1
- package/dist/onboarding.js +2 -1
- package/dist/resource-loader.js +39 -6
- package/dist/resources/extensions/async-jobs/async-bash-tool.js +52 -4
- package/dist/resources/extensions/gsd/auto/loop.js +89 -1
- package/dist/resources/extensions/gsd/auto/phases.js +28 -10
- package/dist/resources/extensions/gsd/auto/session.js +6 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +8 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +19 -2
- package/dist/resources/extensions/gsd/auto-post-unit.js +7 -0
- package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
- package/dist/resources/extensions/gsd/auto-recovery.js +12 -4
- package/dist/resources/extensions/gsd/auto-start.js +8 -3
- package/dist/resources/extensions/gsd/auto-worktree.js +147 -13
- package/dist/resources/extensions/gsd/auto.js +64 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +199 -164
- package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +62 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +25 -3
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +7 -2
- package/dist/resources/extensions/gsd/commands/catalog.js +40 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +146 -0
- package/dist/resources/extensions/gsd/context-injector.js +74 -0
- package/dist/resources/extensions/gsd/context-store.js +4 -3
- package/dist/resources/extensions/gsd/custom-execution-policy.js +47 -0
- package/dist/resources/extensions/gsd/custom-verification.js +145 -0
- package/dist/resources/extensions/gsd/custom-workflow-engine.js +164 -0
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -0
- package/dist/resources/extensions/gsd/db-writer.js +5 -2
- package/dist/resources/extensions/gsd/definition-loader.js +352 -0
- package/dist/resources/extensions/gsd/detection.js +20 -1
- package/dist/resources/extensions/gsd/dev-execution-policy.js +24 -0
- package/dist/resources/extensions/gsd/dev-workflow-engine.js +82 -0
- package/dist/resources/extensions/gsd/doctor-checks.js +31 -1
- package/dist/resources/extensions/gsd/doctor-providers.js +10 -0
- package/dist/resources/extensions/gsd/doctor.js +11 -1
- package/dist/resources/extensions/gsd/engine-resolver.js +40 -0
- package/dist/resources/extensions/gsd/engine-types.js +8 -0
- package/dist/resources/extensions/gsd/execution-policy.js +8 -0
- package/dist/resources/extensions/gsd/exit-command.js +12 -2
- package/dist/resources/extensions/gsd/export.js +9 -13
- package/dist/resources/extensions/gsd/extension-manifest.json +2 -2
- package/dist/resources/extensions/gsd/files.js +28 -11
- package/dist/resources/extensions/gsd/forensics.js +94 -3
- package/dist/resources/extensions/gsd/git-constants.js +1 -0
- package/dist/resources/extensions/gsd/git-service.js +73 -3
- package/dist/resources/extensions/gsd/graph.js +225 -0
- package/dist/resources/extensions/gsd/gsd-db.js +25 -8
- package/dist/resources/extensions/gsd/guided-flow-queue.js +1 -1
- package/dist/resources/extensions/gsd/guided-flow.js +7 -3
- package/dist/resources/extensions/gsd/journal.js +85 -0
- package/dist/resources/extensions/gsd/md-importer.js +5 -0
- package/dist/resources/extensions/gsd/milestone-ids.js +1 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +3 -2
- package/dist/resources/extensions/gsd/post-unit-hooks.js +24 -412
- package/dist/resources/extensions/gsd/preferences-types.js +2 -0
- package/dist/resources/extensions/gsd/preferences.js +60 -8
- package/dist/resources/extensions/gsd/prompt-loader.js +34 -4
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +11 -10
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
- package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/dist/resources/extensions/gsd/prompts/forensics.md +12 -5
- package/dist/resources/extensions/gsd/prompts/queue.md +1 -1
- package/dist/resources/extensions/gsd/repo-identity.js +92 -7
- package/dist/resources/extensions/gsd/rule-registry.js +489 -0
- package/dist/resources/extensions/gsd/rule-types.js +6 -0
- package/dist/resources/extensions/gsd/run-manager.js +134 -0
- package/dist/resources/extensions/gsd/service-tier.js +147 -0
- package/dist/resources/extensions/gsd/session-lock.js +2 -2
- package/dist/resources/extensions/gsd/structured-data-formatter.js +2 -1
- package/dist/resources/extensions/gsd/templates/decisions.md +2 -2
- package/dist/resources/extensions/gsd/workflow-engine.js +7 -0
- package/dist/resources/extensions/gsd/workflow-templates.js +13 -1
- package/dist/resources/extensions/gsd/worktree-manager.js +20 -6
- package/dist/resources/extensions/gsd/worktree-resolver.js +21 -4
- package/dist/resources/extensions/mcp-client/index.js +2 -1
- package/dist/resources/extensions/search-the-web/tool-search.js +3 -3
- package/dist/resources/extensions/subagent/index.js +7 -3
- package/dist/resources/extensions/voice/index.js +4 -4
- package/dist/resources/skills/create-workflow/SKILL.md +103 -0
- package/dist/resources/skills/create-workflow/references/feature-patterns.md +128 -0
- package/dist/resources/skills/create-workflow/references/verification-policies.md +76 -0
- package/dist/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
- package/dist/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
- package/dist/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
- package/dist/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
- package/dist/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
- package/dist/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
- package/dist/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
- package/dist/web/standalone/.next/build-manifest.json +4 -4
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- 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/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +3 -3
- 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/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
- package/dist/web/standalone/.next/server/chunks/229.js +3 -3
- package/dist/web/standalone/.next/server/chunks/471.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/4024.c195dc1fdd2adbea.js +9 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-9afaaebf6042a1d7.js → webpack-fa307370fcf9fb2c.js} +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/dist/web-mode.d.ts +4 -0
- package/dist/web-mode.js +69 -11
- package/package.json +1 -1
- package/packages/native/src/__tests__/text.test.mjs +33 -0
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/dist/types.d.ts +6 -0
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/src/agent.test.ts +53 -0
- package/packages/pi-agent-core/src/agent.ts +3 -0
- package/packages/pi-agent-core/src/types.ts +6 -0
- package/packages/pi-agent-core/tsconfig.json +1 -1
- package/packages/pi-ai/dist/models.d.ts +5 -3
- package/packages/pi-ai/dist/models.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +801 -1468
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +1135 -1588
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +60 -2
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/packages/pi-ai/scripts/generate-models.ts +1543 -0
- package/packages/pi-ai/src/models.generated.ts +1140 -1593
- package/packages/pi-ai/src/models.ts +7 -4
- package/packages/pi-ai/src/utils/oauth/github-copilot.ts +74 -2
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +8 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +7 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +29 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +60 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/discovery-cache.test.js +3 -1
- package/packages/pi-coding-agent/dist/core/discovery-cache.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +18 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js +23 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-manager.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-manager.js +63 -11
- package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +20 -6
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +6 -5
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.js +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +9 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +10 -7
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +34 -10
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +7 -1
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +68 -0
- package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -2
- package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +4 -2
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +18 -0
- package/packages/pi-coding-agent/src/core/lsp/client.ts +29 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +3 -0
- package/packages/pi-coding-agent/src/core/package-manager.ts +99 -58
- package/packages/pi-coding-agent/src/core/resource-loader.ts +24 -6
- package/packages/pi-coding-agent/src/core/system-prompt.ts +6 -5
- package/packages/pi-coding-agent/src/modes/interactive/components/extension-editor.ts +3 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +10 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +11 -7
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +36 -11
- package/pkg/package.json +1 -1
- package/src/resources/extensions/async-jobs/async-bash-timeout.test.ts +122 -0
- package/src/resources/extensions/async-jobs/async-bash-tool.ts +40 -4
- package/src/resources/extensions/gsd/auto/loop-deps.ts +5 -1
- package/src/resources/extensions/gsd/auto/loop.ts +101 -1
- package/src/resources/extensions/gsd/auto/phases.ts +30 -10
- package/src/resources/extensions/gsd/auto/session.ts +6 -0
- package/src/resources/extensions/gsd/auto/types.ts +4 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +9 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +25 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +8 -0
- package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +12 -4
- package/src/resources/extensions/gsd/auto-start.ts +8 -3
- package/src/resources/extensions/gsd/auto-worktree.ts +162 -18
- package/src/resources/extensions/gsd/auto.ts +71 -2
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +209 -162
- package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +62 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +25 -4
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +9 -2
- package/src/resources/extensions/gsd/commands/catalog.ts +40 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +164 -0
- package/src/resources/extensions/gsd/context-injector.ts +100 -0
- package/src/resources/extensions/gsd/context-store.ts +4 -3
- package/src/resources/extensions/gsd/custom-execution-policy.ts +73 -0
- package/src/resources/extensions/gsd/custom-verification.ts +180 -0
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +216 -0
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -0
- package/src/resources/extensions/gsd/db-writer.ts +6 -2
- package/src/resources/extensions/gsd/definition-loader.ts +462 -0
- package/src/resources/extensions/gsd/detection.ts +20 -1
- package/src/resources/extensions/gsd/dev-execution-policy.ts +51 -0
- package/src/resources/extensions/gsd/dev-workflow-engine.ts +110 -0
- package/src/resources/extensions/gsd/doctor-checks.ts +32 -1
- package/src/resources/extensions/gsd/doctor-providers.ts +13 -0
- package/src/resources/extensions/gsd/doctor-types.ts +1 -0
- package/src/resources/extensions/gsd/doctor.ts +12 -1
- package/src/resources/extensions/gsd/engine-resolver.ts +57 -0
- package/src/resources/extensions/gsd/engine-types.ts +71 -0
- package/src/resources/extensions/gsd/execution-policy.ts +43 -0
- package/src/resources/extensions/gsd/exit-command.ts +14 -2
- package/src/resources/extensions/gsd/export.ts +8 -15
- package/src/resources/extensions/gsd/extension-manifest.json +2 -2
- package/src/resources/extensions/gsd/files.ts +29 -12
- package/src/resources/extensions/gsd/forensics.ts +101 -3
- package/src/resources/extensions/gsd/git-constants.ts +1 -0
- package/src/resources/extensions/gsd/git-service.ts +76 -6
- package/src/resources/extensions/gsd/graph.ts +312 -0
- package/src/resources/extensions/gsd/gsd-db.ts +37 -8
- package/src/resources/extensions/gsd/guided-flow-queue.ts +1 -1
- package/src/resources/extensions/gsd/guided-flow.ts +7 -3
- package/src/resources/extensions/gsd/journal.ts +134 -0
- package/src/resources/extensions/gsd/md-importer.ts +6 -0
- package/src/resources/extensions/gsd/milestone-ids.ts +1 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +3 -2
- package/src/resources/extensions/gsd/post-unit-hooks.ts +24 -462
- package/src/resources/extensions/gsd/preferences-types.ts +6 -0
- package/src/resources/extensions/gsd/preferences.ts +63 -6
- package/src/resources/extensions/gsd/prompt-loader.ts +35 -4
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +11 -10
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
- package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/src/resources/extensions/gsd/prompts/forensics.md +12 -5
- package/src/resources/extensions/gsd/prompts/queue.md +1 -1
- package/src/resources/extensions/gsd/repo-identity.ts +95 -7
- package/src/resources/extensions/gsd/rule-registry.ts +599 -0
- package/src/resources/extensions/gsd/rule-types.ts +68 -0
- package/src/resources/extensions/gsd/run-manager.ts +180 -0
- package/src/resources/extensions/gsd/service-tier.ts +184 -0
- package/src/resources/extensions/gsd/session-lock.ts +2 -2
- package/src/resources/extensions/gsd/structured-data-formatter.ts +3 -1
- package/src/resources/extensions/gsd/templates/decisions.md +2 -2
- package/src/resources/extensions/gsd/tests/activity-log.test.ts +31 -69
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +103 -120
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +202 -0
- package/src/resources/extensions/gsd/tests/bundled-workflow-defs.test.ts +180 -0
- package/src/resources/extensions/gsd/tests/captures.test.ts +12 -1
- package/src/resources/extensions/gsd/tests/commands-workflow-custom.test.ts +283 -0
- package/src/resources/extensions/gsd/tests/context-injector.test.ts +313 -0
- package/src/resources/extensions/gsd/tests/context-store.test.ts +10 -5
- package/src/resources/extensions/gsd/tests/continue-here.test.ts +20 -20
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +540 -0
- package/src/resources/extensions/gsd/tests/custom-verification.test.ts +382 -0
- package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +339 -0
- package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/definition-loader.test.ts +778 -0
- package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +318 -0
- package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +15 -10
- package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +5 -4
- package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/doctor-task-done-missing-summary-slice-loop.test.ts +174 -0
- package/src/resources/extensions/gsd/tests/e2e-workflow-pipeline-integration.test.ts +476 -0
- package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +271 -0
- package/src/resources/extensions/gsd/tests/exit-command.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/git-locale.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/git-service.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +599 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +7 -7
- package/src/resources/extensions/gsd/tests/iterate-engine-integration.test.ts +429 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +513 -0
- package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +147 -0
- package/src/resources/extensions/gsd/tests/journal.test.ts +341 -0
- package/src/resources/extensions/gsd/tests/manifest-status.test.ts +73 -82
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +31 -1
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/milestone-id-reservation.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/parsers.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +47 -25
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +61 -1
- package/src/resources/extensions/gsd/tests/routing-history.test.ts +11 -22
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +413 -0
- package/src/resources/extensions/gsd/tests/run-manager.test.ts +229 -0
- package/src/resources/extensions/gsd/tests/service-tier.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/skill-lifecycle.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +151 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +156 -263
- package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +203 -106
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -3
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +74 -0
- package/src/resources/extensions/gsd/types.ts +3 -0
- package/src/resources/extensions/gsd/workflow-engine.ts +38 -0
- package/src/resources/extensions/gsd/workflow-templates.ts +12 -1
- package/src/resources/extensions/gsd/worktree-manager.ts +21 -6
- package/src/resources/extensions/gsd/worktree-resolver.ts +32 -11
- package/src/resources/extensions/mcp-client/index.ts +5 -1
- package/src/resources/extensions/search-the-web/tool-search.ts +3 -3
- package/src/resources/extensions/subagent/index.ts +7 -3
- package/src/resources/extensions/voice/index.ts +4 -4
- package/src/resources/skills/create-workflow/SKILL.md +103 -0
- package/src/resources/skills/create-workflow/references/feature-patterns.md +128 -0
- package/src/resources/skills/create-workflow/references/verification-policies.md +76 -0
- package/src/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
- package/src/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
- package/src/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
- package/src/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
- package/src/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
- package/src/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
- package/src/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
- package/dist/web/standalone/.next/static/chunks/4024.279c423e4661ece1.js +0 -9
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
- /package/dist/web/standalone/.next/static/{Ute3pMouVczQyT15qrBBO → JUBX5FUR73jiViQU5a-Cx}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Ute3pMouVczQyT15qrBBO → JUBX5FUR73jiViQU5a-Cx}/_ssgManifest.js +0 -0
|
@@ -687,6 +687,8 @@ export class AgentSession {
|
|
|
687
687
|
* Call this when completely done with the session.
|
|
688
688
|
*/
|
|
689
689
|
dispose(): void {
|
|
690
|
+
this._extensionErrorUnsubscriber?.();
|
|
691
|
+
this._extensionErrorUnsubscriber = undefined;
|
|
690
692
|
this._disconnectFromAgent();
|
|
691
693
|
this._eventListeners = [];
|
|
692
694
|
}
|
|
@@ -1928,7 +1930,11 @@ export class AgentSession {
|
|
|
1928
1930
|
runner.setUIContext(this._extensionUIContext);
|
|
1929
1931
|
runner.bindCommandContext(this._extensionCommandContextActions);
|
|
1930
1932
|
|
|
1931
|
-
|
|
1933
|
+
try {
|
|
1934
|
+
this._extensionErrorUnsubscriber?.();
|
|
1935
|
+
} catch {
|
|
1936
|
+
// Ignore errors from previous unsubscriber
|
|
1937
|
+
}
|
|
1932
1938
|
this._extensionErrorUnsubscriber = this._extensionErrorListener
|
|
1933
1939
|
? runner.onError(this._extensionErrorListener)
|
|
1934
1940
|
: undefined;
|
|
@@ -263,6 +263,74 @@ describe("AuthStorage — areAllCredentialsBackedOff", () => {
|
|
|
263
263
|
});
|
|
264
264
|
});
|
|
265
265
|
|
|
266
|
+
// ─── mismatched oauth credential for non-OAuth provider (#2083) ───────────────
|
|
267
|
+
|
|
268
|
+
describe("AuthStorage — oauth credential for non-OAuth provider (#2083)", () => {
|
|
269
|
+
it("returns undefined when openrouter has type:oauth (no registered OAuth provider)", async () => {
|
|
270
|
+
// Simulates the bug: OpenRouter credential stored as type:"oauth"
|
|
271
|
+
// but OpenRouter is not a registered OAuth provider.
|
|
272
|
+
const storage = inMemory({
|
|
273
|
+
openrouter: {
|
|
274
|
+
type: "oauth",
|
|
275
|
+
access_token: "sk-or-v1-fake",
|
|
276
|
+
refresh_token: "rt-fake",
|
|
277
|
+
expires: Date.now() + 3_600_000,
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// Before the fix, getApiKey returns undefined because
|
|
282
|
+
// resolveCredentialApiKey calls getOAuthProvider("openrouter") → null → undefined.
|
|
283
|
+
// The key in the oauth credential is never extracted.
|
|
284
|
+
const key = await storage.getApiKey("openrouter");
|
|
285
|
+
// After the fix, the oauth credential with an unrecognised provider
|
|
286
|
+
// should be skipped, and getApiKey should fall through to env / fallback.
|
|
287
|
+
assert.equal(key, undefined);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("falls through to env var when openrouter has type:oauth credential", async () => {
|
|
291
|
+
const storage = inMemory({
|
|
292
|
+
openrouter: {
|
|
293
|
+
type: "oauth",
|
|
294
|
+
access_token: "sk-or-v1-fake",
|
|
295
|
+
refresh_token: "rt-fake",
|
|
296
|
+
expires: Date.now() + 3_600_000,
|
|
297
|
+
},
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// Simulate OPENROUTER_API_KEY being set via env
|
|
301
|
+
const origEnv = process.env.OPENROUTER_API_KEY;
|
|
302
|
+
try {
|
|
303
|
+
process.env.OPENROUTER_API_KEY = "sk-or-v1-env-key";
|
|
304
|
+
const key = await storage.getApiKey("openrouter");
|
|
305
|
+
assert.equal(key, "sk-or-v1-env-key");
|
|
306
|
+
} finally {
|
|
307
|
+
if (origEnv === undefined) {
|
|
308
|
+
delete process.env.OPENROUTER_API_KEY;
|
|
309
|
+
} else {
|
|
310
|
+
process.env.OPENROUTER_API_KEY = origEnv;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it("falls through to fallback resolver when openrouter has type:oauth credential", async () => {
|
|
316
|
+
const storage = inMemory({
|
|
317
|
+
openrouter: {
|
|
318
|
+
type: "oauth",
|
|
319
|
+
access_token: "sk-or-v1-fake",
|
|
320
|
+
refresh_token: "rt-fake",
|
|
321
|
+
expires: Date.now() + 3_600_000,
|
|
322
|
+
},
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
storage.setFallbackResolver((provider) =>
|
|
326
|
+
provider === "openrouter" ? "sk-or-v1-fallback" : undefined,
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
const key = await storage.getApiKey("openrouter");
|
|
330
|
+
assert.equal(key, "sk-or-v1-fallback");
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
|
|
266
334
|
// ─── getAll truncation ────────────────────────────────────────────────────────
|
|
267
335
|
|
|
268
336
|
describe("AuthStorage — getAll()", () => {
|
|
@@ -202,6 +202,7 @@ export class AuthStorage {
|
|
|
202
202
|
private fallbackResolver?: (provider: string) => string | undefined;
|
|
203
203
|
private loadError: Error | null = null;
|
|
204
204
|
private errors: Error[] = [];
|
|
205
|
+
private credentialChangeListeners: Set<() => void> = new Set();
|
|
205
206
|
|
|
206
207
|
/**
|
|
207
208
|
* Round-robin index per provider. Incremented on each call to getApiKey
|
|
@@ -263,6 +264,25 @@ export class AuthStorage {
|
|
|
263
264
|
this.fallbackResolver = resolver;
|
|
264
265
|
}
|
|
265
266
|
|
|
267
|
+
/**
|
|
268
|
+
* Register a callback to be notified when credentials change (e.g., after OAuth token refresh).
|
|
269
|
+
* Returns a function to unregister the listener.
|
|
270
|
+
*/
|
|
271
|
+
onCredentialChange(listener: () => void): () => void {
|
|
272
|
+
this.credentialChangeListeners.add(listener);
|
|
273
|
+
return () => this.credentialChangeListeners.delete(listener);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
private notifyCredentialChange(): void {
|
|
277
|
+
for (const listener of this.credentialChangeListeners) {
|
|
278
|
+
try {
|
|
279
|
+
listener();
|
|
280
|
+
} catch {
|
|
281
|
+
// Don't let listener errors break the refresh flow
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
266
286
|
private recordError(error: unknown): void {
|
|
267
287
|
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
268
288
|
this.errors.push(normalizedError);
|
|
@@ -667,6 +687,11 @@ export class AuthStorage {
|
|
|
667
687
|
return { result: refreshed, next: JSON.stringify(merged, null, 2) };
|
|
668
688
|
});
|
|
669
689
|
|
|
690
|
+
// Notify listeners after credential change (e.g., model registry refresh)
|
|
691
|
+
if (result) {
|
|
692
|
+
queueMicrotask(() => this.notifyCredentialChange());
|
|
693
|
+
}
|
|
694
|
+
|
|
670
695
|
return result;
|
|
671
696
|
}
|
|
672
697
|
|
|
@@ -731,9 +756,12 @@ export class AuthStorage {
|
|
|
731
756
|
if (credentials.length > 0) {
|
|
732
757
|
const index = this.selectCredentialIndex(providerId, credentials, sessionId);
|
|
733
758
|
if (index >= 0) {
|
|
734
|
-
|
|
759
|
+
const resolved = await this.resolveCredentialApiKey(providerId, credentials[index]);
|
|
760
|
+
if (resolved) return resolved;
|
|
761
|
+
// Credential unresolvable (e.g. type:"oauth" for a non-OAuth provider) —
|
|
762
|
+
// fall through to env / fallback instead of returning undefined (#2083)
|
|
735
763
|
}
|
|
736
|
-
// All credentials backed off - fall through to env/fallback
|
|
764
|
+
// All credentials backed off or unresolvable - fall through to env/fallback
|
|
737
765
|
}
|
|
738
766
|
|
|
739
767
|
// Fall back to environment variable
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
|
-
import {
|
|
2
|
+
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { afterEach, beforeEach, describe, it } from "node:test";
|
|
@@ -59,7 +59,9 @@ describe("ModelDiscoveryCache — basic operations", () => {
|
|
|
59
59
|
|
|
60
60
|
cache.clear("openai");
|
|
61
61
|
assert.equal(cache.get("openai"), undefined);
|
|
62
|
-
|
|
62
|
+
const googleEntry = cache.get("google");
|
|
63
|
+
assert.ok(googleEntry);
|
|
64
|
+
assert.equal(googleEntry.models[0].id, "gemini-pro");
|
|
63
65
|
});
|
|
64
66
|
|
|
65
67
|
it("clear without provider removes all entries", () => {
|
|
@@ -569,6 +569,24 @@ function createExtensionAPI(
|
|
|
569
569
|
}
|
|
570
570
|
|
|
571
571
|
async function loadExtensionModule(extensionPath: string) {
|
|
572
|
+
// Pre-compiled extension loading: if the source is .ts and a sibling .js
|
|
573
|
+
// file exists with matching or newer mtime, use native import() to skip
|
|
574
|
+
// jiti JIT compilation entirely. This is the biggest startup win for
|
|
575
|
+
// bundled extensions that have already been built.
|
|
576
|
+
if (extensionPath.endsWith(".ts")) {
|
|
577
|
+
const jsPath = extensionPath.replace(/\.ts$/, ".js");
|
|
578
|
+
try {
|
|
579
|
+
const [tsStat, jsStat] = [fs.statSync(extensionPath), fs.statSync(jsPath)];
|
|
580
|
+
if (jsStat.mtimeMs >= tsStat.mtimeMs) {
|
|
581
|
+
const module = await import(jsPath);
|
|
582
|
+
const factory = (module.default ?? module) as ExtensionFactory;
|
|
583
|
+
return typeof factory !== "function" ? undefined : factory;
|
|
584
|
+
}
|
|
585
|
+
} catch {
|
|
586
|
+
// .js file doesn't exist or stat failed — fall through to jiti
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
572
590
|
const jiti = createJiti(import.meta.url, {
|
|
573
591
|
moduleCache: false,
|
|
574
592
|
...getJitiOptions(),
|
|
@@ -29,6 +29,9 @@ let idleTimeoutMs: number | null = null;
|
|
|
29
29
|
let idleCheckInterval: ReturnType<typeof setInterval> | null = null;
|
|
30
30
|
const IDLE_CHECK_INTERVAL_MS = 60 * 1000;
|
|
31
31
|
|
|
32
|
+
/** Maximum allowed size for the message buffer (10 MB). */
|
|
33
|
+
const MAX_MESSAGE_BUFFER_SIZE = 10 * 1024 * 1024;
|
|
34
|
+
|
|
32
35
|
/**
|
|
33
36
|
* Configure the idle timeout for LSP clients.
|
|
34
37
|
*/
|
|
@@ -52,6 +55,10 @@ function startIdleChecker(): void {
|
|
|
52
55
|
shutdownClient(key);
|
|
53
56
|
}
|
|
54
57
|
}
|
|
58
|
+
// Stop the checker if there are no more clients to monitor
|
|
59
|
+
if (clients.size === 0) {
|
|
60
|
+
stopIdleChecker();
|
|
61
|
+
}
|
|
55
62
|
}, IDLE_CHECK_INTERVAL_MS);
|
|
56
63
|
}
|
|
57
64
|
|
|
@@ -252,6 +259,17 @@ async function startMessageReader(client: LspClient): Promise<void> {
|
|
|
252
259
|
return new Promise<void>((resolve) => {
|
|
253
260
|
stdout.on("data", async (chunk: Buffer) => {
|
|
254
261
|
const currentBuffer: Buffer = Buffer.concat([client.messageBuffer, chunk]);
|
|
262
|
+
|
|
263
|
+
if (currentBuffer.length > MAX_MESSAGE_BUFFER_SIZE) {
|
|
264
|
+
if (process.env.DEBUG) {
|
|
265
|
+
console.error(
|
|
266
|
+
`[lsp] Message buffer exceeded ${MAX_MESSAGE_BUFFER_SIZE} bytes (${currentBuffer.length}), discarding`,
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
client.messageBuffer = Buffer.alloc(0);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
255
273
|
client.messageBuffer = currentBuffer;
|
|
256
274
|
|
|
257
275
|
let workingBuffer = currentBuffer;
|
|
@@ -708,6 +726,14 @@ function shutdownClient(key: string): void {
|
|
|
708
726
|
client.proc.kill();
|
|
709
727
|
}
|
|
710
728
|
clients.delete(key);
|
|
729
|
+
clientLocks.delete(key);
|
|
730
|
+
|
|
731
|
+
// Clean up any file operation locks associated with this client
|
|
732
|
+
for (const lockKey of Array.from(fileOperationLocks.keys())) {
|
|
733
|
+
if (lockKey.startsWith(`${key}:`)) {
|
|
734
|
+
fileOperationLocks.delete(lockKey);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
711
737
|
}
|
|
712
738
|
|
|
713
739
|
// =============================================================================
|
|
@@ -822,6 +848,9 @@ async function sendNotification(client: LspClient, method: string, params: unkno
|
|
|
822
848
|
function shutdownAll(): void {
|
|
823
849
|
const clientsToShutdown = Array.from(clients.values());
|
|
824
850
|
clients.clear();
|
|
851
|
+
clientLocks.clear();
|
|
852
|
+
fileOperationLocks.clear();
|
|
853
|
+
stopIdleChecker();
|
|
825
854
|
|
|
826
855
|
const err = new Error("LSP client shutdown");
|
|
827
856
|
for (const client of clientsToShutdown) {
|
|
@@ -243,6 +243,9 @@ export class ModelRegistry {
|
|
|
243
243
|
return undefined;
|
|
244
244
|
});
|
|
245
245
|
|
|
246
|
+
// Refresh models when credentials change (e.g., OAuth token refresh with new model limits)
|
|
247
|
+
this.authStorage.onCredentialChange(() => this.refresh());
|
|
248
|
+
|
|
246
249
|
// Load models
|
|
247
250
|
this.loadModels();
|
|
248
251
|
}
|
|
@@ -1562,6 +1562,26 @@ export class DefaultPackageManager implements PackageManager {
|
|
|
1562
1562
|
}
|
|
1563
1563
|
}
|
|
1564
1564
|
|
|
1565
|
+
/**
|
|
1566
|
+
* Batch-discover which resource subdirectories exist under a parent dir.
|
|
1567
|
+
* A single readdirSync replaces 4 separate existsSync probes, reducing
|
|
1568
|
+
* syscalls during startup.
|
|
1569
|
+
*/
|
|
1570
|
+
private discoverResourceSubdirs(baseDir: string): Set<string> {
|
|
1571
|
+
try {
|
|
1572
|
+
const entries = readdirSync(baseDir, { withFileTypes: true });
|
|
1573
|
+
const names = new Set<string>();
|
|
1574
|
+
for (const e of entries) {
|
|
1575
|
+
if (e.isDirectory() || e.isSymbolicLink()) {
|
|
1576
|
+
names.add(e.name);
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
return names;
|
|
1580
|
+
} catch {
|
|
1581
|
+
return new Set();
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1565
1585
|
private addAutoDiscoveredResources(
|
|
1566
1586
|
accumulator: ResourceAccumulator,
|
|
1567
1587
|
globalSettings: ReturnType<SettingsManager["getGlobalSettings"]>,
|
|
@@ -1595,6 +1615,11 @@ export class DefaultPackageManager implements PackageManager {
|
|
|
1595
1615
|
themes: (projectSettings.themes ?? []) as string[],
|
|
1596
1616
|
};
|
|
1597
1617
|
|
|
1618
|
+
// Batch directory discovery: one readdir of each parent replaces up to
|
|
1619
|
+
// 4 separate existsSync calls per base directory, cutting syscalls.
|
|
1620
|
+
const projectSubdirs = this.discoverResourceSubdirs(projectBaseDir);
|
|
1621
|
+
const userSubdirs = this.discoverResourceSubdirs(globalBaseDir);
|
|
1622
|
+
|
|
1598
1623
|
const userDirs = {
|
|
1599
1624
|
extensions: join(globalBaseDir, "extensions"),
|
|
1600
1625
|
skills: join(globalBaseDir, "skills"),
|
|
@@ -1626,66 +1651,82 @@ export class DefaultPackageManager implements PackageManager {
|
|
|
1626
1651
|
}
|
|
1627
1652
|
};
|
|
1628
1653
|
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1654
|
+
// Project resources — skip collect calls when the parent readdir shows
|
|
1655
|
+
// the subdirectory doesn't exist (avoids redundant existsSync + readdirSync).
|
|
1656
|
+
if (projectSubdirs.has("extensions")) {
|
|
1657
|
+
addResources(
|
|
1658
|
+
"extensions",
|
|
1659
|
+
collectAutoExtensionEntries(projectDirs.extensions),
|
|
1660
|
+
projectMetadata,
|
|
1661
|
+
projectOverrides.extensions,
|
|
1662
|
+
projectBaseDir,
|
|
1663
|
+
);
|
|
1664
|
+
}
|
|
1665
|
+
{
|
|
1666
|
+
const skillEntries = [
|
|
1667
|
+
...(projectSubdirs.has("skills") ? collectAutoSkillEntries(projectDirs.skills) : []),
|
|
1640
1668
|
...projectAgentsSkillDirs.flatMap((dir) => collectAutoSkillEntries(dir)),
|
|
1641
|
-
]
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1669
|
+
];
|
|
1670
|
+
if (skillEntries.length > 0) {
|
|
1671
|
+
addResources("skills", skillEntries, projectMetadata, projectOverrides.skills, projectBaseDir);
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
if (projectSubdirs.has("prompts")) {
|
|
1675
|
+
addResources(
|
|
1676
|
+
"prompts",
|
|
1677
|
+
collectAutoPromptEntries(projectDirs.prompts),
|
|
1678
|
+
projectMetadata,
|
|
1679
|
+
projectOverrides.prompts,
|
|
1680
|
+
projectBaseDir,
|
|
1681
|
+
);
|
|
1682
|
+
}
|
|
1683
|
+
if (projectSubdirs.has("themes")) {
|
|
1684
|
+
addResources(
|
|
1685
|
+
"themes",
|
|
1686
|
+
collectAutoThemeEntries(projectDirs.themes),
|
|
1687
|
+
projectMetadata,
|
|
1688
|
+
projectOverrides.themes,
|
|
1689
|
+
projectBaseDir,
|
|
1690
|
+
);
|
|
1691
|
+
}
|
|
1660
1692
|
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1693
|
+
// User (global) resources
|
|
1694
|
+
if (userSubdirs.has("extensions")) {
|
|
1695
|
+
addResources(
|
|
1696
|
+
"extensions",
|
|
1697
|
+
collectAutoExtensionEntries(userDirs.extensions),
|
|
1698
|
+
userMetadata,
|
|
1699
|
+
userOverrides.extensions,
|
|
1700
|
+
globalBaseDir,
|
|
1701
|
+
);
|
|
1702
|
+
}
|
|
1703
|
+
{
|
|
1704
|
+
const skillEntries = [
|
|
1705
|
+
...(userSubdirs.has("skills") ? collectAutoSkillEntries(userDirs.skills) : []),
|
|
1706
|
+
...collectAutoSkillEntries(userAgentsSkillsDir),
|
|
1707
|
+
];
|
|
1708
|
+
if (skillEntries.length > 0) {
|
|
1709
|
+
addResources("skills", skillEntries, userMetadata, userOverrides.skills, globalBaseDir);
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
if (userSubdirs.has("prompts")) {
|
|
1713
|
+
addResources(
|
|
1714
|
+
"prompts",
|
|
1715
|
+
collectAutoPromptEntries(userDirs.prompts),
|
|
1716
|
+
userMetadata,
|
|
1717
|
+
userOverrides.prompts,
|
|
1718
|
+
globalBaseDir,
|
|
1719
|
+
);
|
|
1720
|
+
}
|
|
1721
|
+
if (userSubdirs.has("themes")) {
|
|
1722
|
+
addResources(
|
|
1723
|
+
"themes",
|
|
1724
|
+
collectAutoThemeEntries(userDirs.themes),
|
|
1725
|
+
userMetadata,
|
|
1726
|
+
userOverrides.themes,
|
|
1727
|
+
globalBaseDir,
|
|
1728
|
+
);
|
|
1729
|
+
}
|
|
1689
1730
|
}
|
|
1690
1731
|
|
|
1691
1732
|
private collectFilesFromPaths(paths: string[], resourceType: ResourceType): string[] {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
|
-
import { join, resolve, sep } from "node:path";
|
|
3
|
+
import { basename, dirname, join, resolve, sep } from "node:path";
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import { CONFIG_DIR_NAME, getAgentDir } from "../config.js";
|
|
6
6
|
import { loadThemeFromPath, type Theme } from "../modes/interactive/theme/theme.js";
|
|
@@ -127,6 +127,8 @@ export interface DefaultResourceLoaderOptions {
|
|
|
127
127
|
noThemes?: boolean;
|
|
128
128
|
systemPrompt?: string;
|
|
129
129
|
appendSystemPrompt?: string;
|
|
130
|
+
/** Names of bundled extensions (used to identify built-in extensions in conflict detection). */
|
|
131
|
+
bundledExtensionNames?: Set<string>;
|
|
130
132
|
extensionsOverride?: (base: LoadExtensionsResult) => LoadExtensionsResult;
|
|
131
133
|
skillsOverride?: (base: { skills: Skill[]; diagnostics: ResourceDiagnostic[] }) => {
|
|
132
134
|
skills: Skill[];
|
|
@@ -164,6 +166,7 @@ export class DefaultResourceLoader implements ResourceLoader {
|
|
|
164
166
|
private noThemes: boolean;
|
|
165
167
|
private systemPromptSource?: string;
|
|
166
168
|
private appendSystemPromptSource?: string;
|
|
169
|
+
private bundledExtensionNames: Set<string>;
|
|
167
170
|
private extensionsOverride?: (base: LoadExtensionsResult) => LoadExtensionsResult;
|
|
168
171
|
private skillsOverride?: (base: { skills: Skill[]; diagnostics: ResourceDiagnostic[] }) => {
|
|
169
172
|
skills: Skill[];
|
|
@@ -219,6 +222,7 @@ export class DefaultResourceLoader implements ResourceLoader {
|
|
|
219
222
|
this.noThemes = options.noThemes ?? false;
|
|
220
223
|
this.systemPromptSource = options.systemPrompt;
|
|
221
224
|
this.appendSystemPromptSource = options.appendSystemPrompt;
|
|
225
|
+
this.bundledExtensionNames = options.bundledExtensionNames ?? new Set();
|
|
222
226
|
this.extensionsOverride = options.extensionsOverride;
|
|
223
227
|
this.skillsOverride = options.skillsOverride;
|
|
224
228
|
this.promptsOverride = options.promptsOverride;
|
|
@@ -790,6 +794,19 @@ export class DefaultResourceLoader implements ResourceLoader {
|
|
|
790
794
|
return target.startsWith(prefix);
|
|
791
795
|
}
|
|
792
796
|
|
|
797
|
+
/**
|
|
798
|
+
* Extract the extension name from its path.
|
|
799
|
+
* For root-level files: basename without extension (e.g. "search-the-web.ts" → "search-the-web")
|
|
800
|
+
* For subdirectory extensions: the directory name (e.g. "/path/to/gsd/index.ts" → "gsd")
|
|
801
|
+
*/
|
|
802
|
+
private getExtensionNameFromPath(extPath: string): string {
|
|
803
|
+
const base = basename(extPath);
|
|
804
|
+
if (base === "index.js" || base === "index.ts") {
|
|
805
|
+
return basename(dirname(extPath));
|
|
806
|
+
}
|
|
807
|
+
return base.replace(/\.(?:ts|js)$/, "");
|
|
808
|
+
}
|
|
809
|
+
|
|
793
810
|
private detectExtensionConflicts(extensions: Extension[]): Array<{ path: string; message: string }> {
|
|
794
811
|
const conflicts: Array<{ path: string; message: string }> = [];
|
|
795
812
|
|
|
@@ -803,9 +820,10 @@ export class DefaultResourceLoader implements ResourceLoader {
|
|
|
803
820
|
for (const toolName of ext.tools.keys()) {
|
|
804
821
|
const existingOwner = toolOwners.get(toolName);
|
|
805
822
|
if (existingOwner && existingOwner !== ext.path) {
|
|
806
|
-
// Determine if the existing owner is a
|
|
807
|
-
|
|
808
|
-
|
|
823
|
+
// Determine if the existing owner is a bundled extension by checking
|
|
824
|
+
// its name against the canonical bundled extensions list
|
|
825
|
+
const ownerName = this.getExtensionNameFromPath(existingOwner);
|
|
826
|
+
const isBuiltIn = this.bundledExtensionNames.has(ownerName);
|
|
809
827
|
const hint = isBuiltIn
|
|
810
828
|
? ` (built-in tool supersedes — consider removing ${ext.path})`
|
|
811
829
|
: "";
|
|
@@ -822,8 +840,8 @@ export class DefaultResourceLoader implements ResourceLoader {
|
|
|
822
840
|
for (const commandName of ext.commands.keys()) {
|
|
823
841
|
const existingOwner = commandOwners.get(commandName);
|
|
824
842
|
if (existingOwner && existingOwner !== ext.path) {
|
|
825
|
-
const
|
|
826
|
-
|
|
843
|
+
const ownerName = this.getExtensionNameFromPath(existingOwner);
|
|
844
|
+
const isBuiltIn = this.bundledExtensionNames.has(ownerName);
|
|
827
845
|
const hint = isBuiltIn
|
|
828
846
|
? ` (built-in command supersedes — consider removing ${ext.path})`
|
|
829
847
|
: "";
|
|
@@ -84,9 +84,9 @@ export function buildSystemPrompt(options: BuildSystemPromptOptions = {}): strin
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
// Append skills section (
|
|
88
|
-
const
|
|
89
|
-
if (
|
|
87
|
+
// Append skills section (if read or Skill tool is available)
|
|
88
|
+
const customPromptHasSkillAccess = !selectedTools || selectedTools.includes("read") || selectedTools.includes("Skill");
|
|
89
|
+
if (customPromptHasSkillAccess && skills.length > 0) {
|
|
90
90
|
prompt += formatSkillsForPrompt(skills);
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -232,8 +232,9 @@ Pi documentation (read only when the user asks about pi itself, its SDK, extensi
|
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
// Append skills section (
|
|
236
|
-
|
|
235
|
+
// Append skills section (if read or Skill tool is available)
|
|
236
|
+
const hasSkill = tools.includes("Skill");
|
|
237
|
+
if ((hasRead || hasSkill) && skills.length > 0) {
|
|
237
238
|
prompt += formatSkillsForPrompt(skills);
|
|
238
239
|
}
|
|
239
240
|
|
|
@@ -113,6 +113,9 @@ export class ExtensionEditorComponent extends Container implements Focusable {
|
|
|
113
113
|
private openExternalEditor(): void {
|
|
114
114
|
const editorCmd = process.env.VISUAL || process.env.EDITOR;
|
|
115
115
|
if (!editorCmd) {
|
|
116
|
+
// No editor configured — nothing to do.
|
|
117
|
+
// The main interactive-mode handler shows a warning with an iTerm2 hint;
|
|
118
|
+
// this component is a secondary editor so we silently bail.
|
|
116
119
|
return;
|
|
117
120
|
}
|
|
118
121
|
|
|
@@ -68,10 +68,14 @@ export class FooterComponent implements Component {
|
|
|
68
68
|
const totalCacheWrite = usageTotals.cacheWrite;
|
|
69
69
|
const totalCost = usageTotals.cost;
|
|
70
70
|
|
|
71
|
+
// Use activeInferenceModel during streaming to show the model actually
|
|
72
|
+
// being used, not the configured model which may have been switched mid-turn.
|
|
73
|
+
const displayModel = state.activeInferenceModel ?? state.model;
|
|
74
|
+
|
|
71
75
|
// Calculate context usage from session (handles compaction correctly).
|
|
72
76
|
// After compaction, tokens are unknown until the next LLM response.
|
|
73
77
|
const contextUsage = this.session.getContextUsage();
|
|
74
|
-
const contextWindow = contextUsage?.contextWindow ??
|
|
78
|
+
const contextWindow = contextUsage?.contextWindow ?? displayModel?.contextWindow ?? 0;
|
|
75
79
|
const contextPercentValue = contextUsage?.percent ?? 0;
|
|
76
80
|
const contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : "?";
|
|
77
81
|
|
|
@@ -102,7 +106,7 @@ export class FooterComponent implements Component {
|
|
|
102
106
|
if (totalCacheWrite) statsParts.push(`W${formatTokens(totalCacheWrite)}`);
|
|
103
107
|
|
|
104
108
|
// Show cost with "(sub)" indicator if using OAuth subscription
|
|
105
|
-
const usingSubscription =
|
|
109
|
+
const usingSubscription = displayModel ? this.session.modelRegistry.isUsingOAuth(displayModel) : false;
|
|
106
110
|
if (totalCost || usingSubscription) {
|
|
107
111
|
const costStr = `$${totalCost.toFixed(3)}${usingSubscription ? " (sub)" : ""}`;
|
|
108
112
|
statsParts.push(costStr);
|
|
@@ -127,7 +131,7 @@ export class FooterComponent implements Component {
|
|
|
127
131
|
let statsLeft = statsParts.join(" ");
|
|
128
132
|
|
|
129
133
|
// Add model name on the right side, plus thinking level if model supports it
|
|
130
|
-
const modelName =
|
|
134
|
+
const modelName = displayModel?.id || "no-model";
|
|
131
135
|
|
|
132
136
|
let statsLeftWidth = visibleWidth(statsLeft);
|
|
133
137
|
|
|
@@ -142,7 +146,7 @@ export class FooterComponent implements Component {
|
|
|
142
146
|
|
|
143
147
|
// Add thinking level indicator if model supports reasoning
|
|
144
148
|
let rightSideWithoutProvider = modelName;
|
|
145
|
-
if (
|
|
149
|
+
if (displayModel?.reasoning) {
|
|
146
150
|
const thinkingLevel = state.thinkingLevel || "off";
|
|
147
151
|
rightSideWithoutProvider =
|
|
148
152
|
thinkingLevel === "off" ? `${modelName} • thinking off` : `${modelName} • ${thinkingLevel}`;
|
|
@@ -150,8 +154,8 @@ export class FooterComponent implements Component {
|
|
|
150
154
|
|
|
151
155
|
// Prepend the provider in parentheses if there are multiple providers and there's enough room
|
|
152
156
|
let rightSide = rightSideWithoutProvider;
|
|
153
|
-
if (this.footerData.getAvailableProviderCount() > 1 &&
|
|
154
|
-
rightSide = `(${
|
|
157
|
+
if (this.footerData.getAvailableProviderCount() > 1 && displayModel) {
|
|
158
|
+
rightSide = `(${displayModel.provider}) ${rightSideWithoutProvider}`;
|
|
155
159
|
if (statsLeftWidth + minPadding + visibleWidth(rightSide) > width) {
|
|
156
160
|
// Too wide, fall back
|
|
157
161
|
rightSide = rightSideWithoutProvider;
|