gsd-pi 2.63.0 → 2.64.0-dev.05b8a94
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 +46 -134
- package/dist/cli.js +48 -6
- package/dist/headless-query.js +11 -1
- package/dist/headless.js +3 -1
- package/dist/help-text.js +4 -1
- package/dist/onboarding.js +15 -8
- package/dist/resource-loader.js +18 -3
- package/dist/resources/extensions/bg-shell/bg-shell-lifecycle.js +22 -7
- package/dist/resources/extensions/bg-shell/process-manager.js +6 -1
- package/dist/resources/extensions/cmux/index.js +21 -12
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +27 -0
- package/dist/resources/extensions/gsd/auto/finalize-timeout.js +40 -0
- package/dist/resources/extensions/gsd/auto/loop.js +4 -0
- package/dist/resources/extensions/gsd/auto/phases.js +157 -22
- package/dist/resources/extensions/gsd/auto/session.js +12 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +14 -8
- package/dist/resources/extensions/gsd/auto-model-selection.js +32 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +222 -11
- package/dist/resources/extensions/gsd/auto-prompts.js +25 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +15 -7
- package/dist/resources/extensions/gsd/auto-start.js +10 -21
- package/dist/resources/extensions/gsd/auto-timers.js +2 -1
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +17 -0
- package/dist/resources/extensions/gsd/auto-verification.js +138 -1
- package/dist/resources/extensions/gsd/auto-worktree.js +13 -7
- package/dist/resources/extensions/gsd/auto.js +24 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +158 -75
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +13 -0
- package/dist/resources/extensions/gsd/bootstrap/notify-interceptor.js +28 -0
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +85 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +3 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +40 -1
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +15 -0
- package/dist/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.js +54 -0
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +50 -2
- package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -0
- package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +103 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +9 -4
- package/dist/resources/extensions/gsd/constants.js +42 -0
- package/dist/resources/extensions/gsd/db-writer.js +72 -4
- package/dist/resources/extensions/gsd/forensics.js +20 -4
- package/dist/resources/extensions/gsd/gsd-db.js +64 -17
- package/dist/resources/extensions/gsd/guided-flow.js +19 -0
- package/dist/resources/extensions/gsd/metrics.js +27 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +5 -3
- package/dist/resources/extensions/gsd/notification-overlay.js +224 -0
- package/dist/resources/extensions/gsd/notification-store.js +268 -0
- package/dist/resources/extensions/gsd/notification-widget.js +56 -0
- package/dist/resources/extensions/gsd/post-execution-checks.js +407 -0
- package/dist/resources/extensions/gsd/pre-execution-checks.js +464 -0
- package/dist/resources/extensions/gsd/preferences-types.js +6 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +33 -0
- package/dist/resources/extensions/gsd/preferences.js +11 -2
- package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -0
- package/dist/resources/extensions/gsd/prompts/doctor-heal.md +1 -0
- package/dist/resources/extensions/gsd/prompts/forensics.md +2 -0
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +2 -0
- package/dist/resources/extensions/gsd/prompts/system.md +4 -7
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
- package/dist/resources/extensions/gsd/roadmap-mutations.js +1 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +9 -5
- package/dist/resources/extensions/gsd/safety/content-validator.js +73 -0
- package/dist/resources/extensions/gsd/safety/destructive-guard.js +34 -0
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +109 -0
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +83 -0
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +71 -0
- package/dist/resources/extensions/gsd/safety/git-checkpoint.js +91 -0
- package/dist/resources/extensions/gsd/safety/safety-harness.js +64 -0
- package/dist/resources/extensions/gsd/slice-parallel-conflict.js +67 -0
- package/dist/resources/extensions/gsd/slice-parallel-eligibility.js +51 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +378 -0
- package/dist/resources/extensions/gsd/state.js +74 -14
- package/dist/resources/extensions/gsd/status-guards.js +11 -0
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +17 -12
- package/dist/resources/extensions/gsd/tools/complete-slice.js +40 -26
- package/dist/resources/extensions/gsd/tools/complete-task.js +12 -12
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +33 -25
- package/dist/resources/extensions/gsd/tools/plan-slice.js +5 -8
- package/dist/resources/extensions/gsd/verification-evidence.js +18 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +8 -0
- package/dist/resources/extensions/gsd/workflow-projections.js +21 -5
- package/dist/resources/extensions/gsd/worktree-manager.js +82 -29
- package/dist/resources/extensions/gsd/worktree-resolver.js +4 -3
- package/dist/resources/extensions/mcp-client/auth.js +101 -0
- package/dist/resources/extensions/mcp-client/index.js +10 -1
- package/dist/resources/extensions/ollama/index.js +28 -22
- package/dist/resources/extensions/ollama/model-capabilities.js +37 -34
- package/dist/resources/extensions/ollama/ndjson-stream.js +54 -0
- package/dist/resources/extensions/ollama/ollama-chat-provider.js +380 -0
- package/dist/resources/extensions/ollama/ollama-client.js +23 -32
- package/dist/resources/extensions/ollama/ollama-discovery.js +2 -7
- package/dist/resources/extensions/ollama/ollama-tool.js +62 -0
- package/dist/resources/extensions/ollama/thinking-parser.js +104 -0
- package/dist/update-cmd.js +4 -2
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +20 -19
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +4 -4
- package/dist/web/standalone/.next/routes-manifest.json +6 -0
- 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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +1 -1
- 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.js.nft.json +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.js.nft.json +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.js.nft.json +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/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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/notifications/route.js +3 -0
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -0
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -0
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +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.js.nft.json +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.js.nft.json +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 +2 -2
- 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.js.nft.json +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.js.nft.json +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.js.nft.json +1 -1
- 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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
- 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.js.nft.json +1 -1
- 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.js.nft.json +1 -1
- 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.js.nft.json +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.js.nft.json +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 +20 -19
- package/dist/web/standalone/.next/server/chunks/6897.js +12 -0
- package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
- package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
- package/dist/web/standalone/.next/server/middleware-build-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/Vbx2-SrSBOgta6576xj9m/_buildManifest.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/_global-error/page-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/api/boot/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/captures/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/files/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/git/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/history/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/notifications/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/projects/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/steer/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/undo/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/update/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-0c485498795110d6.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-8805a20e15762c3c.js +1 -0
- 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/next/dist/client/components/builtin/not-found-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-8805a20e15762c3c.js +1 -0
- 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/welcome-screen.js +1 -1
- package/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.d.ts +8 -0
- package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +70 -3
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +317 -5
- package/packages/pi-agent-core/src/agent-loop.ts +90 -6
- package/packages/pi-ai/dist/types.d.ts +16 -1
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/src/types.ts +18 -1
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +38 -0
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +11 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +9 -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 +50 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +41 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +7 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +31 -4
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.js +28 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.js +46 -0
- package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +1 -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 +12 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +3 -3
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +24 -0
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +23 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +84 -57
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +9 -0
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +8 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +6 -0
- 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 +36 -0
- 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-tool-refresh.test.ts +64 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +10 -0
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +53 -0
- package/packages/pi-coding-agent/src/core/auth-storage.ts +66 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.test.ts +39 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +34 -4
- package/packages/pi-coding-agent/src/core/extensions/provider-registration.test.ts +81 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +14 -0
- package/packages/pi-coding-agent/src/core/model-resolver.ts +3 -3
- package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +42 -0
- package/packages/pi-coding-agent/src/core/resource-loader.ts +94 -57
- package/packages/pi-coding-agent/src/core/sdk.ts +10 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +9 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +33 -0
- package/packages/pi-tui/dist/components/loader.d.ts +4 -2
- package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/loader.js +27 -9
- package/packages/pi-tui/dist/components/loader.js.map +1 -1
- package/packages/pi-tui/dist/components/text.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/text.js +2 -0
- package/packages/pi-tui/dist/components/text.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts +2 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +35 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/components/loader.ts +27 -10
- package/packages/pi-tui/src/components/text.ts +1 -0
- package/packages/pi-tui/src/tui.ts +32 -0
- package/pkg/package.json +1 -1
- package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +19 -7
- package/src/resources/extensions/bg-shell/process-manager.ts +8 -2
- package/src/resources/extensions/cmux/index.ts +18 -12
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +27 -0
- package/src/resources/extensions/gsd/auto/finalize-timeout.ts +46 -0
- package/src/resources/extensions/gsd/auto/loop.ts +5 -0
- package/src/resources/extensions/gsd/auto/phases.ts +194 -33
- package/src/resources/extensions/gsd/auto/session.ts +14 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +16 -7
- package/src/resources/extensions/gsd/auto-model-selection.ts +36 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +263 -12
- package/src/resources/extensions/gsd/auto-prompts.ts +21 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +9 -8
- package/src/resources/extensions/gsd/auto-start.ts +11 -20
- package/src/resources/extensions/gsd/auto-timers.ts +2 -1
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
- package/src/resources/extensions/gsd/auto-verification.ts +190 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +14 -6
- package/src/resources/extensions/gsd/auto.ts +26 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +172 -88
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +15 -0
- package/src/resources/extensions/gsd/bootstrap/notify-interceptor.ts +34 -0
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +98 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +4 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +44 -1
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +19 -0
- package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +57 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +59 -2
- package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -0
- package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +139 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +10 -4
- package/src/resources/extensions/gsd/constants.ts +44 -0
- package/src/resources/extensions/gsd/db-writer.ts +78 -4
- package/src/resources/extensions/gsd/forensics.ts +21 -5
- package/src/resources/extensions/gsd/gsd-db.ts +64 -17
- package/src/resources/extensions/gsd/guided-flow.ts +22 -0
- package/src/resources/extensions/gsd/metrics.ts +28 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +5 -3
- package/src/resources/extensions/gsd/notification-overlay.ts +267 -0
- package/src/resources/extensions/gsd/notification-store.ts +288 -0
- package/src/resources/extensions/gsd/notification-widget.ts +68 -0
- package/src/resources/extensions/gsd/post-execution-checks.ts +539 -0
- package/src/resources/extensions/gsd/pre-execution-checks.ts +573 -0
- package/src/resources/extensions/gsd/preferences-types.ts +44 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +33 -0
- package/src/resources/extensions/gsd/preferences.ts +13 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -0
- package/src/resources/extensions/gsd/prompts/doctor-heal.md +1 -0
- package/src/resources/extensions/gsd/prompts/forensics.md +2 -0
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +2 -0
- package/src/resources/extensions/gsd/prompts/system.md +4 -7
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
- package/src/resources/extensions/gsd/roadmap-mutations.ts +1 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +10 -5
- package/src/resources/extensions/gsd/safety/content-validator.ts +98 -0
- package/src/resources/extensions/gsd/safety/destructive-guard.ts +49 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +151 -0
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +120 -0
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +108 -0
- package/src/resources/extensions/gsd/safety/git-checkpoint.ts +106 -0
- package/src/resources/extensions/gsd/safety/safety-harness.ts +105 -0
- package/src/resources/extensions/gsd/slice-parallel-conflict.ts +86 -0
- package/src/resources/extensions/gsd/slice-parallel-eligibility.ts +73 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +477 -0
- package/src/resources/extensions/gsd/state.ts +67 -12
- package/src/resources/extensions/gsd/status-guards.ts +13 -0
- package/src/resources/extensions/gsd/tests/artifact-corruption-2630.test.ts +288 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +34 -13
- package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/cmux.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/complete-slice-string-coercion.test.ts +247 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +109 -0
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +13 -9
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/deferred-slice-dispatch.test.ts +203 -0
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +130 -0
- package/src/resources/extensions/gsd/tests/doctor-fix-flag.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/enhanced-verification-integration.test.ts +526 -0
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/git-checkpoint.test.ts +94 -0
- package/src/resources/extensions/gsd/tests/insert-slice-no-wipe.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +27 -7
- package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/metrics.test.ts +116 -1
- package/src/resources/extensions/gsd/tests/milestone-status-tool.test.ts +201 -0
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +249 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +82 -18
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +312 -0
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +813 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +999 -0
- package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +266 -0
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +457 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/shared-wal.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/slice-parallel-conflict.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/slice-parallel-eligibility.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +83 -0
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +349 -0
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +163 -0
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +35 -2
- package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +148 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +34 -20
- package/src/resources/extensions/gsd/tools/complete-slice.ts +41 -26
- package/src/resources/extensions/gsd/tools/complete-task.ts +12 -12
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +55 -30
- package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -8
- package/src/resources/extensions/gsd/types.ts +44 -22
- package/src/resources/extensions/gsd/verification-evidence.ts +68 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +15 -1
- package/src/resources/extensions/gsd/workflow-projections.ts +23 -5
- package/src/resources/extensions/gsd/worktree-manager.ts +76 -28
- package/src/resources/extensions/gsd/worktree-resolver.ts +4 -3
- package/src/resources/extensions/mcp-client/auth.ts +149 -0
- package/src/resources/extensions/mcp-client/index.ts +16 -1
- package/src/resources/extensions/ollama/index.ts +26 -25
- package/src/resources/extensions/ollama/model-capabilities.ts +41 -34
- package/src/resources/extensions/ollama/ndjson-stream.ts +63 -0
- package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +20 -0
- package/src/resources/extensions/ollama/ollama-chat-provider.ts +459 -0
- package/src/resources/extensions/ollama/ollama-client.ts +30 -30
- package/src/resources/extensions/ollama/ollama-discovery.ts +5 -8
- package/src/resources/extensions/ollama/ollama-tool.ts +69 -0
- package/src/resources/extensions/ollama/tests/ollama-chat-provider-stream.test.ts +82 -0
- package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +0 -27
- package/src/resources/extensions/ollama/thinking-parser.ts +116 -0
- package/src/resources/extensions/ollama/types.ts +23 -0
- package/dist/web/standalone/.next/server/chunks/2229.js +0 -12
- package/dist/web/standalone/.next/static/5FLUBNdqolRyyehCyChPd/_buildManifest.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/_global-error/page-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/boot/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/captures/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/files/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/git/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/history/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/projects/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/steer/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/undo/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/update/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-62be3b5fa91e4c8f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-c4cc189e7b117ea2.js +0 -1
- /package/dist/web/standalone/.next/static/{5FLUBNdqolRyyehCyChPd → Vbx2-SrSBOgta6576xj9m}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// GSD-2 — Regression tests for #3616: tool list persistence across newSession() calls
|
|
2
|
+
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
3
|
+
|
|
4
|
+
import test, { describe } from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
import { readFileSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
|
|
9
|
+
const source = readFileSync(
|
|
10
|
+
join(process.cwd(), "packages/pi-coding-agent/src/core/agent-session.ts"),
|
|
11
|
+
"utf-8",
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
describe("#3616 — newSession() must restore full tool set", () => {
|
|
15
|
+
test("newSession() calls _refreshToolRegistry with includeAllExtensionTools when cwd is unchanged", () => {
|
|
16
|
+
// Find the newSession method
|
|
17
|
+
const newSessionStart = source.indexOf("async newSession(options?:");
|
|
18
|
+
assert.ok(newSessionStart >= 0, "should find newSession method");
|
|
19
|
+
|
|
20
|
+
// Get the method body (up to the next top-level method)
|
|
21
|
+
const methodBody = source.slice(newSessionStart, newSessionStart + 3000);
|
|
22
|
+
|
|
23
|
+
// Verify the cwd-changed branch rebuilds tools
|
|
24
|
+
assert.ok(
|
|
25
|
+
methodBody.includes("if (this._cwd !== previousCwd)"),
|
|
26
|
+
"should have cwd-change guard",
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
// Verify the else branch exists and refreshes tools with includeAllExtensionTools
|
|
30
|
+
const elseIdx = methodBody.indexOf("} else {");
|
|
31
|
+
assert.ok(elseIdx >= 0, "should have else branch for cwd-unchanged case");
|
|
32
|
+
|
|
33
|
+
const elseBranch = methodBody.slice(elseIdx, elseIdx + 800);
|
|
34
|
+
assert.ok(
|
|
35
|
+
elseBranch.includes("_refreshToolRegistry"),
|
|
36
|
+
"else branch should call _refreshToolRegistry",
|
|
37
|
+
);
|
|
38
|
+
assert.ok(
|
|
39
|
+
elseBranch.includes("includeAllExtensionTools: true"),
|
|
40
|
+
"else branch should pass includeAllExtensionTools: true to restore narrowed tools",
|
|
41
|
+
);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test("newSession() references #3616 in the else-branch comment", () => {
|
|
45
|
+
const idx = source.indexOf("#3616");
|
|
46
|
+
assert.ok(idx >= 0, "source should reference issue #3616 for the tool restore fix");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("agent.reset() does not clear _state.tools (tools persist across reset)", () => {
|
|
50
|
+
// This is a structural invariant — if reset() starts clearing tools,
|
|
51
|
+
// the newSession() refresh becomes the only defense against tool loss.
|
|
52
|
+
const agentSource = readFileSync(
|
|
53
|
+
join(process.cwd(), "packages/pi-agent-core/src/agent.ts"),
|
|
54
|
+
"utf-8",
|
|
55
|
+
);
|
|
56
|
+
const resetStart = agentSource.indexOf("reset()");
|
|
57
|
+
assert.ok(resetStart >= 0, "should find reset() method");
|
|
58
|
+
const resetBody = agentSource.slice(resetStart, resetStart + 400);
|
|
59
|
+
assert.ok(
|
|
60
|
+
!resetBody.includes("tools"),
|
|
61
|
+
"reset() should NOT touch _state.tools — tools are managed by agent-session",
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -1577,6 +1577,16 @@ export class AgentSession {
|
|
|
1577
1577
|
activeToolNames: this.getActiveToolNames(),
|
|
1578
1578
|
includeAllExtensionTools: true,
|
|
1579
1579
|
});
|
|
1580
|
+
} else {
|
|
1581
|
+
// Even when cwd hasn't changed, restore the full tool set (#3616).
|
|
1582
|
+
// Extensions (e.g., discuss flows) may narrow the active tool list
|
|
1583
|
+
// via setActiveTools() during a session. Without this refresh, the
|
|
1584
|
+
// narrowed set persists into the next session — causing tools like
|
|
1585
|
+
// gsd_plan_slice to be missing from auto-mode subagent sessions.
|
|
1586
|
+
this._refreshToolRegistry({
|
|
1587
|
+
activeToolNames: this.getActiveToolNames(),
|
|
1588
|
+
includeAllExtensionTools: true,
|
|
1589
|
+
});
|
|
1580
1590
|
}
|
|
1581
1591
|
|
|
1582
1592
|
// Run setup callback if provided (e.g., to append initial messages)
|
|
@@ -356,6 +356,59 @@ describe("AuthStorage — oauth credential for non-OAuth provider (#2083)", () =
|
|
|
356
356
|
});
|
|
357
357
|
});
|
|
358
358
|
|
|
359
|
+
// ─── Gemini CLI OAuth token detection ─────────────────────────────────────────
|
|
360
|
+
|
|
361
|
+
describe("AuthStorage — Gemini CLI OAuth token detection", () => {
|
|
362
|
+
it("rejects Google OAuth access token (ya29. prefix) stored as api_key for google provider", () => {
|
|
363
|
+
const storage = inMemory({});
|
|
364
|
+
assert.throws(
|
|
365
|
+
() => storage.set("google", makeKey("ya29.a0ARrdaM_fake_oauth_token_from_gemini_cli")),
|
|
366
|
+
(err: Error) => {
|
|
367
|
+
assert.ok(err.message.includes("OAuth access token"), `Expected message about OAuth token, got: ${err.message}`);
|
|
368
|
+
assert.ok(
|
|
369
|
+
err.message.includes("GEMINI_API_KEY") || err.message.includes("google-gemini-cli"),
|
|
370
|
+
`Expected guidance about GEMINI_API_KEY or google-gemini-cli, got: ${err.message}`,
|
|
371
|
+
);
|
|
372
|
+
return true;
|
|
373
|
+
},
|
|
374
|
+
);
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it("rejects Google OAuth access token for google provider via getApiKey when set as env var", async () => {
|
|
378
|
+
const storage = inMemory({});
|
|
379
|
+
// Simulate runtime override with OAuth token
|
|
380
|
+
storage.setRuntimeApiKey("google", "ya29.c.b0AXv0zTPQ_fake_oauth_token");
|
|
381
|
+
const key = await storage.getApiKey("google");
|
|
382
|
+
// Should return undefined (blocked) or throw
|
|
383
|
+
assert.equal(key, undefined, "OAuth token should be blocked for google provider");
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
it("allows legitimate Google API keys (AIza prefix) for google provider", () => {
|
|
387
|
+
const storage = inMemory({});
|
|
388
|
+
storage.set("google", makeKey("AIzaSyD_fake_legitimate_api_key_here"));
|
|
389
|
+
const creds = storage.getCredentialsForProvider("google");
|
|
390
|
+
assert.equal(creds.length, 1);
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
it("allows ya29 tokens for google-gemini-cli provider (OAuth is expected there)", () => {
|
|
394
|
+
// google-gemini-cli stores OAuth credentials with type: "oauth", not "api_key"
|
|
395
|
+
// But if someone somehow stored an api_key, it shouldn't be blocked for OAuth providers
|
|
396
|
+
const storage = inMemory({});
|
|
397
|
+
storage.set("google-gemini-cli", makeKey("ya29.a0ARrdaM_token_for_gemini_cli"));
|
|
398
|
+
const creds = storage.getCredentialsForProvider("google-gemini-cli");
|
|
399
|
+
assert.equal(creds.length, 1);
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
it("rejects Google OAuth token (ya29. prefix) for openai provider that uses GEMINI_API_KEY indirectly", () => {
|
|
403
|
+
// Only google provider should be blocked, not others
|
|
404
|
+
const storage = inMemory({});
|
|
405
|
+
// This should NOT throw - other providers can have whatever keys they want
|
|
406
|
+
storage.set("openai", makeKey("ya29.some_value"));
|
|
407
|
+
const creds = storage.getCredentialsForProvider("openai");
|
|
408
|
+
assert.equal(creds.length, 1);
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
|
|
359
412
|
// ─── getAll truncation ────────────────────────────────────────────────────────
|
|
360
413
|
|
|
361
414
|
describe("AuthStorage — getAll()", () => {
|
|
@@ -34,6 +34,46 @@ export type OAuthCredential = {
|
|
|
34
34
|
|
|
35
35
|
export type AuthCredential = ApiKeyCredential | OAuthCredential;
|
|
36
36
|
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// Google OAuth token detection
|
|
39
|
+
// ============================================================================
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Providers that use Google AI Studio API keys (not OAuth tokens).
|
|
43
|
+
* OAuth access tokens (ya29.*) are not valid API keys for these providers.
|
|
44
|
+
*/
|
|
45
|
+
const GOOGLE_API_KEY_PROVIDERS = new Set(["google"]);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Detect if a string is a Google OAuth access token rather than an API key.
|
|
49
|
+
* Google OAuth access tokens start with "ya29." — these are issued by
|
|
50
|
+
* Google's OAuth2 token endpoint and are not valid as AI Studio API keys.
|
|
51
|
+
*
|
|
52
|
+
* Users who installed Google's Gemini CLI may have these tokens and
|
|
53
|
+
* mistakenly set them as GEMINI_API_KEY.
|
|
54
|
+
*/
|
|
55
|
+
export function isGoogleOAuthToken(key: string): boolean {
|
|
56
|
+
return key.startsWith("ya29.");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Validate that an API key is not a Google OAuth token being used for
|
|
61
|
+
* a provider that requires actual API keys (e.g., Google AI Studio).
|
|
62
|
+
* Throws a descriptive error if the key appears to be an OAuth token.
|
|
63
|
+
*/
|
|
64
|
+
function validateNotGoogleOAuthToken(provider: string, key: string): void {
|
|
65
|
+
if (GOOGLE_API_KEY_PROVIDERS.has(provider) && isGoogleOAuthToken(key)) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`The provided key for "${provider}" appears to be a Google OAuth access token (ya29.*), ` +
|
|
68
|
+
`not a valid API key. Google AI Studio requires an API key starting with "AIza...". ` +
|
|
69
|
+
`\n\nIf you're using Google's Gemini CLI, its OAuth tokens are not compatible. ` +
|
|
70
|
+
`Either:\n` +
|
|
71
|
+
` 1. Get an API key from https://aistudio.google.com/apikey and set GEMINI_API_KEY\n` +
|
|
72
|
+
` 2. Use '/login google-gemini-cli' to authenticate via Cloud Code Assist`,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
37
77
|
/**
|
|
38
78
|
* On-disk format: each provider maps to a single credential or an array of credentials.
|
|
39
79
|
* Single credentials are normalized to arrays at load time for internal use.
|
|
@@ -360,6 +400,9 @@ export class AuthStorage {
|
|
|
360
400
|
*/
|
|
361
401
|
set(provider: string, credential: AuthCredential): void {
|
|
362
402
|
if (credential.type === "api_key") {
|
|
403
|
+
// Block Google OAuth tokens being stored as API keys for AI Studio providers
|
|
404
|
+
validateNotGoogleOAuthToken(provider, credential.key);
|
|
405
|
+
|
|
363
406
|
const existing = this.getCredentialsForProvider(provider);
|
|
364
407
|
// Deduplicate: don't add if same key already exists
|
|
365
408
|
const isDuplicate = existing.some(
|
|
@@ -762,6 +805,16 @@ export class AuthStorage {
|
|
|
762
805
|
// Runtime override takes highest priority
|
|
763
806
|
const runtimeKey = this.runtimeOverrides.get(providerId);
|
|
764
807
|
if (runtimeKey) {
|
|
808
|
+
// Block Google OAuth tokens used as runtime API key overrides
|
|
809
|
+
if (GOOGLE_API_KEY_PROVIDERS.has(providerId) && isGoogleOAuthToken(runtimeKey)) {
|
|
810
|
+
this.recordError(
|
|
811
|
+
new Error(
|
|
812
|
+
`Blocked Google OAuth access token (ya29.*) for provider "${providerId}". ` +
|
|
813
|
+
`Use an API key from https://aistudio.google.com/apikey or '/login google-gemini-cli'.`,
|
|
814
|
+
),
|
|
815
|
+
);
|
|
816
|
+
return undefined;
|
|
817
|
+
}
|
|
765
818
|
return runtimeKey;
|
|
766
819
|
}
|
|
767
820
|
|
|
@@ -780,7 +833,19 @@ export class AuthStorage {
|
|
|
780
833
|
|
|
781
834
|
// Fall back to environment variable
|
|
782
835
|
const envKey = getEnvApiKey(providerId);
|
|
783
|
-
if (envKey)
|
|
836
|
+
if (envKey) {
|
|
837
|
+
// Block Google OAuth tokens from environment variables (e.g., GEMINI_API_KEY=ya29.*)
|
|
838
|
+
if (GOOGLE_API_KEY_PROVIDERS.has(providerId) && isGoogleOAuthToken(envKey)) {
|
|
839
|
+
this.recordError(
|
|
840
|
+
new Error(
|
|
841
|
+
`GEMINI_API_KEY contains a Google OAuth access token (ya29.*), not an API key. ` +
|
|
842
|
+
`Get an API key from https://aistudio.google.com/apikey or use '/login google-gemini-cli'.`,
|
|
843
|
+
),
|
|
844
|
+
);
|
|
845
|
+
return undefined;
|
|
846
|
+
}
|
|
847
|
+
return envKey;
|
|
848
|
+
}
|
|
784
849
|
|
|
785
850
|
// Fall back to custom resolver (e.g., models.json custom providers)
|
|
786
851
|
return this.fallbackResolver?.(providerId) ?? undefined;
|
|
@@ -4,7 +4,7 @@ import * as fs from "node:fs";
|
|
|
4
4
|
import * as os from "node:os";
|
|
5
5
|
import * as path from "node:path";
|
|
6
6
|
import { isProjectTrusted, trustProject, getUntrustedExtensionPaths } from "./project-trust.js";
|
|
7
|
-
import { containsTypeScriptSyntax, loadExtensions } from "./loader.js";
|
|
7
|
+
import { containsTypeScriptSyntax, loadExtensions, resetExtensionLoaderCache } from "./loader.js";
|
|
8
8
|
|
|
9
9
|
// ─── helpers ──────────────────────────────────────────────────────────────────
|
|
10
10
|
|
|
@@ -235,3 +235,41 @@ describe("loadExtensions", () => {
|
|
|
235
235
|
);
|
|
236
236
|
});
|
|
237
237
|
});
|
|
238
|
+
|
|
239
|
+
// ─── resetExtensionLoaderCache ───────────────────────────────────────────────
|
|
240
|
+
|
|
241
|
+
describe("resetExtensionLoaderCache", () => {
|
|
242
|
+
let tmpDir: string;
|
|
243
|
+
|
|
244
|
+
beforeEach(() => {
|
|
245
|
+
tmpDir = makeTempDir();
|
|
246
|
+
// Always start with a clean cache so tests are independent
|
|
247
|
+
resetExtensionLoaderCache();
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
afterEach(() => {
|
|
251
|
+
resetExtensionLoaderCache();
|
|
252
|
+
cleanDir(tmpDir);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it("clears the jiti singleton so a fresh instance is created on next load", async () => {
|
|
256
|
+
// Write a minimal valid extension that returns a name
|
|
257
|
+
const extPath = path.join(tmpDir, "cache-ext.ts");
|
|
258
|
+
fs.writeFileSync(
|
|
259
|
+
extPath,
|
|
260
|
+
`export default function activate(api: any) { return { name: "cache-ext" }; }\n`,
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
// First load — creates the jiti singleton and caches the module
|
|
264
|
+
const result1 = await loadExtensions([extPath], tmpDir);
|
|
265
|
+
assert.equal(result1.extensions.length, 1, "first load should succeed");
|
|
266
|
+
|
|
267
|
+
// Reset the cache — nulls the singleton
|
|
268
|
+
resetExtensionLoaderCache();
|
|
269
|
+
|
|
270
|
+
// Second load — should create a new jiti instance (not reuse the old one)
|
|
271
|
+
// and still successfully load the extension
|
|
272
|
+
const result2 = await loadExtensions([extPath], tmpDir);
|
|
273
|
+
assert.equal(result2.extensions.length, 1, "load after reset should succeed with fresh jiti");
|
|
274
|
+
});
|
|
275
|
+
});
|
|
@@ -624,6 +624,39 @@ export function containsTypeScriptSyntax(source: string): boolean {
|
|
|
624
624
|
return TS_SYNTAX_PATTERNS.some((pattern) => pattern.test(source));
|
|
625
625
|
}
|
|
626
626
|
|
|
627
|
+
/**
|
|
628
|
+
* Shared jiti instance for loading extension modules.
|
|
629
|
+
*
|
|
630
|
+
* Before this fix (#2108), each extension created a NEW jiti instance with
|
|
631
|
+
* `moduleCache: false`, causing shared dependencies (e.g. @gsd/pi-agent-core)
|
|
632
|
+
* to be recompiled for every extension — turning a ~3s parallel load into a
|
|
633
|
+
* ~15-30s serial compilation bottleneck.
|
|
634
|
+
*
|
|
635
|
+
* Using a single shared instance with `moduleCache: true` means shared modules
|
|
636
|
+
* are compiled once and reused across all extensions.
|
|
637
|
+
*/
|
|
638
|
+
let _extensionLoaderJiti: ReturnType<typeof createJiti> | null = null;
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* Reset the shared jiti singleton so the next call to getExtensionLoaderJiti()
|
|
642
|
+
* creates a fresh instance. This prevents memory leaks in long-running daemon
|
|
643
|
+
* processes (every loaded module stays cached forever) and ensures stale modules
|
|
644
|
+
* are not returned when extension source changes on disk.
|
|
645
|
+
*/
|
|
646
|
+
export function resetExtensionLoaderCache(): void {
|
|
647
|
+
_extensionLoaderJiti = null;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
function getExtensionLoaderJiti() {
|
|
651
|
+
if (!_extensionLoaderJiti) {
|
|
652
|
+
_extensionLoaderJiti = createJiti(import.meta.url, {
|
|
653
|
+
moduleCache: true,
|
|
654
|
+
...getJitiOptions(),
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
return _extensionLoaderJiti;
|
|
658
|
+
}
|
|
659
|
+
|
|
627
660
|
async function loadExtensionModule(extensionPath: string) {
|
|
628
661
|
// Pre-compiled extension loading: if the source is .ts and a sibling .js
|
|
629
662
|
// file exists with matching or newer mtime, use native import() to skip
|
|
@@ -643,10 +676,7 @@ async function loadExtensionModule(extensionPath: string) {
|
|
|
643
676
|
}
|
|
644
677
|
}
|
|
645
678
|
|
|
646
|
-
const jiti =
|
|
647
|
-
moduleCache: false,
|
|
648
|
-
...getJitiOptions(),
|
|
649
|
-
});
|
|
679
|
+
const jiti = getExtensionLoaderJiti();
|
|
650
680
|
|
|
651
681
|
const module = await jiti.import(extensionPath, { default: true });
|
|
652
682
|
const factory = module as ExtensionFactory;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// GSD2 — Regression test: pendingProviderRegistrations must be flushed exactly once (#3576)
|
|
2
|
+
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
3
|
+
|
|
4
|
+
import { describe, it } from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* This test validates that the provider preflush pattern in sdk.ts clears
|
|
9
|
+
* pendingProviderRegistrations after iterating, so bindCore() doesn't
|
|
10
|
+
* re-register the same providers.
|
|
11
|
+
*
|
|
12
|
+
* The bug: createAgentSession() iterated pendingProviderRegistrations but
|
|
13
|
+
* did not clear the array. Later, bindCore() replayed and registered the
|
|
14
|
+
* same providers again, stacking wrappers.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
interface ProviderEntry {
|
|
18
|
+
name: string;
|
|
19
|
+
config: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface MockRuntime {
|
|
23
|
+
pendingProviderRegistrations: ProviderEntry[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe("provider registration preflush", () => {
|
|
27
|
+
it("clears pending registrations after preflush so bindCore does not replay", () => {
|
|
28
|
+
const registered: string[] = [];
|
|
29
|
+
const runtime: MockRuntime = {
|
|
30
|
+
pendingProviderRegistrations: [
|
|
31
|
+
{ name: "ollama", config: { type: "ollama" } },
|
|
32
|
+
{ name: "custom-provider", config: { type: "custom" } },
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Simulate sdk.ts preflush (lines 220-223)
|
|
37
|
+
for (const { name } of runtime.pendingProviderRegistrations) {
|
|
38
|
+
registered.push(name);
|
|
39
|
+
}
|
|
40
|
+
// The fix: clear after preflush
|
|
41
|
+
runtime.pendingProviderRegistrations = [];
|
|
42
|
+
|
|
43
|
+
// Simulate bindCore() flush (runner.ts lines 268-271)
|
|
44
|
+
for (const { name } of runtime.pendingProviderRegistrations) {
|
|
45
|
+
registered.push(name);
|
|
46
|
+
}
|
|
47
|
+
runtime.pendingProviderRegistrations = [];
|
|
48
|
+
|
|
49
|
+
assert.deepEqual(
|
|
50
|
+
registered,
|
|
51
|
+
["ollama", "custom-provider"],
|
|
52
|
+
"each provider should be registered exactly once",
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("without the fix, providers are registered twice", () => {
|
|
57
|
+
const registered: string[] = [];
|
|
58
|
+
const runtime: MockRuntime = {
|
|
59
|
+
pendingProviderRegistrations: [
|
|
60
|
+
{ name: "ollama", config: { type: "ollama" } },
|
|
61
|
+
],
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Old behavior: preflush without clearing
|
|
65
|
+
for (const { name } of runtime.pendingProviderRegistrations) {
|
|
66
|
+
registered.push(name);
|
|
67
|
+
}
|
|
68
|
+
// NOT clearing — simulating the old bug
|
|
69
|
+
|
|
70
|
+
// bindCore() replays the same queue
|
|
71
|
+
for (const { name } of runtime.pendingProviderRegistrations) {
|
|
72
|
+
registered.push(name);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
assert.deepEqual(
|
|
76
|
+
registered,
|
|
77
|
+
["ollama", "ollama"],
|
|
78
|
+
"without clearing, providers are registered twice (demonstrating the bug)",
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -1341,6 +1341,8 @@ export interface ProviderModelConfig {
|
|
|
1341
1341
|
headers?: Record<string, string>;
|
|
1342
1342
|
/** OpenAI compatibility settings. */
|
|
1343
1343
|
compat?: Model<Api>["compat"];
|
|
1344
|
+
/** Opaque provider-specific options (e.g. Ollama keep_alive, num_gpu). */
|
|
1345
|
+
providerOptions?: Record<string, unknown>;
|
|
1344
1346
|
}
|
|
1345
1347
|
|
|
1346
1348
|
/** Extension factory function type. Supports both sync and async initialization. */
|
|
@@ -467,6 +467,18 @@ export class ModelRegistry {
|
|
|
467
467
|
this.customProviderApiKeys.set(providerName, providerConfig.apiKey);
|
|
468
468
|
}
|
|
469
469
|
|
|
470
|
+
// Register custom providers so isProviderRequestReady() can find
|
|
471
|
+
// them (#3531). Without this, models.json providers with apiKey
|
|
472
|
+
// fail the auth check and are invisible to the fallback resolver.
|
|
473
|
+
if (!this.registeredProviders.has(providerName)) {
|
|
474
|
+
this.registeredProviders.set(providerName, {
|
|
475
|
+
authMode: providerConfig.apiKey ? "apiKey" : "none",
|
|
476
|
+
apiKey: providerConfig.apiKey,
|
|
477
|
+
baseUrl: providerConfig.baseUrl,
|
|
478
|
+
isReady: providerConfig.apiKey ? () => true : undefined,
|
|
479
|
+
} as any);
|
|
480
|
+
}
|
|
481
|
+
|
|
470
482
|
for (const modelDef of modelDefs) {
|
|
471
483
|
const api = modelDef.api || providerConfig.api;
|
|
472
484
|
if (!api) continue;
|
|
@@ -742,6 +754,7 @@ export class ModelRegistry {
|
|
|
742
754
|
maxTokens: modelDef.maxTokens,
|
|
743
755
|
headers,
|
|
744
756
|
compat: modelDef.compat,
|
|
757
|
+
providerOptions: modelDef.providerOptions,
|
|
745
758
|
} as Model<Api>);
|
|
746
759
|
}
|
|
747
760
|
|
|
@@ -917,5 +930,6 @@ export interface ProviderConfigInput {
|
|
|
917
930
|
maxTokens: number;
|
|
918
931
|
headers?: Record<string, string>;
|
|
919
932
|
compat?: Model<Api>["compat"];
|
|
933
|
+
providerOptions?: Record<string, unknown>;
|
|
920
934
|
}>;
|
|
921
935
|
}
|
|
@@ -13,7 +13,7 @@ import type { ModelRegistry } from "./model-registry.js";
|
|
|
13
13
|
/** Default model IDs for each known provider */
|
|
14
14
|
const defaultModelPerProvider: Record<KnownProvider, string> = {
|
|
15
15
|
"amazon-bedrock": "us.anthropic.claude-opus-4-6-v1",
|
|
16
|
-
anthropic: "claude-opus-4-6
|
|
16
|
+
anthropic: "claude-opus-4-6",
|
|
17
17
|
"anthropic-vertex": "claude-sonnet-4-6",
|
|
18
18
|
openai: "gpt-5.4",
|
|
19
19
|
"azure-openai-responses": "gpt-5.2",
|
|
@@ -24,7 +24,7 @@ const defaultModelPerProvider: Record<KnownProvider, string> = {
|
|
|
24
24
|
"google-vertex": "gemini-3-pro-preview",
|
|
25
25
|
"github-copilot": "gpt-4o",
|
|
26
26
|
openrouter: "openai/gpt-5.1-codex",
|
|
27
|
-
"vercel-ai-gateway": "anthropic/claude-opus-4-6
|
|
27
|
+
"vercel-ai-gateway": "anthropic/claude-opus-4-6",
|
|
28
28
|
xai: "grok-4-fast-non-reasoning",
|
|
29
29
|
groq: "openai/gpt-oss-120b",
|
|
30
30
|
cerebras: "zai-glm-4.6",
|
|
@@ -507,7 +507,7 @@ export async function findInitialModel(options: {
|
|
|
507
507
|
const found = modelRegistry.find(defaultProvider, defaultModelId);
|
|
508
508
|
if (found) {
|
|
509
509
|
// Check if the provider's recommended default is a higher-capability variant
|
|
510
|
-
// of the saved model (e.g. saved "claude-opus-4-6" vs recommended "claude-opus-4-6
|
|
510
|
+
// of the saved model (e.g. saved "claude-opus-4-6" vs recommended "claude-opus-4-6-extended").
|
|
511
511
|
// If so, prefer the recommended variant to avoid using a smaller context window (#1125).
|
|
512
512
|
const recommendedId = defaultModelPerProvider[defaultProvider as KnownProvider];
|
|
513
513
|
if (recommendedId && recommendedId !== defaultModelId && recommendedId.startsWith(defaultModelId)) {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// GSD-2 — Regression test for #3616: reload() must reset jiti extension loader cache
|
|
2
|
+
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
3
|
+
|
|
4
|
+
import test, { describe } from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
import { readFileSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
|
|
9
|
+
const source = readFileSync(
|
|
10
|
+
join(process.cwd(), "packages/pi-coding-agent/src/core/resource-loader.ts"),
|
|
11
|
+
"utf-8",
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
describe("#3616 — reload() must invalidate jiti module cache", () => {
|
|
15
|
+
test("resource-loader imports resetExtensionLoaderCache from loader.js", () => {
|
|
16
|
+
assert.ok(
|
|
17
|
+
source.includes("resetExtensionLoaderCache"),
|
|
18
|
+
"resource-loader.ts should import resetExtensionLoaderCache",
|
|
19
|
+
);
|
|
20
|
+
assert.ok(
|
|
21
|
+
source.includes('from "./extensions/loader.js"'),
|
|
22
|
+
"resetExtensionLoaderCache should be imported from extensions/loader.js",
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test("reload() calls resetExtensionLoaderCache before loadExtensions", () => {
|
|
27
|
+
const reloadStart = source.indexOf("async reload(): Promise<void>");
|
|
28
|
+
assert.ok(reloadStart >= 0, "should find reload() method");
|
|
29
|
+
const reloadBody = source.slice(reloadStart, reloadStart + 4000);
|
|
30
|
+
|
|
31
|
+
const resetIdx = reloadBody.indexOf("resetExtensionLoaderCache()");
|
|
32
|
+
assert.ok(resetIdx >= 0, "reload() should call resetExtensionLoaderCache()");
|
|
33
|
+
|
|
34
|
+
const loadIdx = reloadBody.indexOf("loadExtensions(");
|
|
35
|
+
assert.ok(loadIdx >= 0, "reload() should call loadExtensions");
|
|
36
|
+
|
|
37
|
+
assert.ok(
|
|
38
|
+
resetIdx < loadIdx,
|
|
39
|
+
"resetExtensionLoaderCache() must be called BEFORE loadExtensions to ensure fresh modules",
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
});
|