gsd-pi 2.18.0 → 2.20.0
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 +5 -1
- package/dist/cli.js +3 -3
- package/dist/onboarding.d.ts +3 -1
- package/dist/onboarding.js +77 -3
- package/dist/remote-questions-config.d.ts +1 -1
- package/dist/resources/extensions/google-search/index.ts +164 -47
- package/dist/resources/extensions/gsd/auto-dashboard.ts +14 -2
- package/dist/resources/extensions/gsd/auto-prompts.ts +148 -39
- package/dist/resources/extensions/gsd/auto-worktree.ts +93 -9
- package/dist/resources/extensions/gsd/auto.ts +690 -39
- package/dist/resources/extensions/gsd/captures.ts +384 -0
- package/dist/resources/extensions/gsd/commands.ts +654 -36
- package/dist/resources/extensions/gsd/complexity-classifier.ts +322 -0
- package/dist/resources/extensions/gsd/context-budget.ts +243 -0
- package/dist/resources/extensions/gsd/context-store.ts +195 -0
- package/dist/resources/extensions/gsd/dashboard-overlay.ts +51 -3
- package/dist/resources/extensions/gsd/db-writer.ts +341 -0
- package/dist/resources/extensions/gsd/debug-logger.ts +178 -0
- package/dist/resources/extensions/gsd/dispatch-guard.ts +0 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +54 -0
- package/dist/resources/extensions/gsd/doctor-proactive.ts +286 -0
- package/dist/resources/extensions/gsd/doctor.ts +283 -2
- package/dist/resources/extensions/gsd/export.ts +81 -2
- package/dist/resources/extensions/gsd/files.ts +39 -9
- package/dist/resources/extensions/gsd/git-service.ts +6 -0
- package/dist/resources/extensions/gsd/gsd-db.ts +752 -0
- package/dist/resources/extensions/gsd/guided-flow.ts +26 -1
- package/dist/resources/extensions/gsd/history.ts +0 -1
- package/dist/resources/extensions/gsd/index.ts +277 -1
- package/dist/resources/extensions/gsd/md-importer.ts +526 -0
- package/dist/resources/extensions/gsd/metrics.ts +84 -0
- package/dist/resources/extensions/gsd/model-cost-table.ts +65 -0
- package/dist/resources/extensions/gsd/model-router.ts +256 -0
- package/dist/resources/extensions/gsd/notifications.ts +0 -1
- package/dist/resources/extensions/gsd/post-unit-hooks.ts +72 -2
- package/dist/resources/extensions/gsd/preferences.ts +198 -150
- package/dist/resources/extensions/gsd/prompt-loader.ts +45 -9
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -5
- package/dist/resources/extensions/gsd/prompts/heal-skill.md +45 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +5 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +48 -0
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -0
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +8 -0
- package/dist/resources/extensions/gsd/prompts/system.md +2 -1
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +62 -0
- package/dist/resources/extensions/gsd/quick.ts +156 -0
- package/dist/resources/extensions/gsd/skill-discovery.ts +5 -3
- package/dist/resources/extensions/gsd/skill-health.ts +417 -0
- package/dist/resources/extensions/gsd/skill-telemetry.ts +127 -0
- package/dist/resources/extensions/gsd/state.ts +30 -0
- package/dist/resources/extensions/gsd/templates/preferences.md +1 -0
- package/dist/resources/extensions/gsd/tests/captures.test.ts +438 -0
- package/dist/resources/extensions/gsd/tests/complexity-classifier.test.ts +181 -0
- package/dist/resources/extensions/gsd/tests/context-budget.test.ts +283 -0
- package/dist/resources/extensions/gsd/tests/context-compression.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/context-store.test.ts +462 -0
- package/dist/resources/extensions/gsd/tests/continue-here.test.ts +204 -0
- package/dist/resources/extensions/gsd/tests/dashboard-budget.test.ts +346 -0
- package/dist/resources/extensions/gsd/tests/db-writer.test.ts +602 -0
- package/dist/resources/extensions/gsd/tests/debug-logger.test.ts +185 -0
- package/dist/resources/extensions/gsd/tests/derive-state-db.test.ts +406 -0
- package/dist/resources/extensions/gsd/tests/dispatch-guard.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +22 -0
- package/dist/resources/extensions/gsd/tests/doctor-proactive.test.ts +244 -0
- package/dist/resources/extensions/gsd/tests/doctor-runtime.test.ts +303 -0
- package/dist/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +434 -0
- package/dist/resources/extensions/gsd/tests/gsd-db.test.ts +353 -0
- package/dist/resources/extensions/gsd/tests/gsd-inspect.test.ts +125 -0
- package/dist/resources/extensions/gsd/tests/gsd-tools.test.ts +326 -0
- package/dist/resources/extensions/gsd/tests/integration-edge.test.ts +228 -0
- package/dist/resources/extensions/gsd/tests/integration-lifecycle.test.ts +277 -0
- package/dist/resources/extensions/gsd/tests/md-importer.test.ts +411 -0
- package/dist/resources/extensions/gsd/tests/metrics.test.ts +197 -0
- package/dist/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +144 -0
- package/dist/resources/extensions/gsd/tests/model-cost-table.test.ts +69 -0
- package/dist/resources/extensions/gsd/tests/model-isolation.test.ts +99 -0
- package/dist/resources/extensions/gsd/tests/model-router.test.ts +167 -0
- package/dist/resources/extensions/gsd/tests/parsers.test.ts +40 -0
- package/dist/resources/extensions/gsd/tests/post-unit-hooks.test.ts +41 -1
- package/dist/resources/extensions/gsd/tests/preferences-git.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/preferences-hooks.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/preferences-mode.test.ts +110 -0
- package/dist/resources/extensions/gsd/tests/preferences-models.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +464 -0
- package/dist/resources/extensions/gsd/tests/prompt-db.test.ts +385 -0
- package/dist/resources/extensions/gsd/tests/remote-questions.test.ts +488 -1
- package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +17 -29
- package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +2 -8
- package/dist/resources/extensions/gsd/tests/routing-history.test.ts +215 -62
- package/dist/resources/extensions/gsd/tests/skill-lifecycle.test.ts +126 -0
- package/dist/resources/extensions/gsd/tests/stop-auto-remote.test.ts +31 -8
- package/dist/resources/extensions/gsd/tests/token-savings.test.ts +366 -0
- package/dist/resources/extensions/gsd/tests/triage-dispatch.test.ts +224 -0
- package/dist/resources/extensions/gsd/tests/triage-resolution.test.ts +215 -0
- package/dist/resources/extensions/gsd/tests/unit-runtime.test.ts +25 -1
- package/dist/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +145 -0
- package/dist/resources/extensions/gsd/tests/visualizer-data.test.ts +290 -0
- package/dist/resources/extensions/gsd/tests/visualizer-overlay.test.ts +120 -0
- package/dist/resources/extensions/gsd/tests/visualizer-views.test.ts +478 -0
- package/dist/resources/extensions/gsd/tests/worktree-db-integration.test.ts +205 -0
- package/dist/resources/extensions/gsd/tests/worktree-db.test.ts +442 -0
- package/dist/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +165 -0
- package/dist/resources/extensions/gsd/triage-resolution.ts +200 -0
- package/dist/resources/extensions/gsd/triage-ui.ts +175 -0
- package/dist/resources/extensions/gsd/types.ts +29 -0
- package/dist/resources/extensions/gsd/undo.ts +0 -1
- package/dist/resources/extensions/gsd/unit-runtime.ts +5 -1
- package/dist/resources/extensions/gsd/visualizer-data.ts +505 -0
- package/dist/resources/extensions/gsd/visualizer-overlay.ts +337 -0
- package/dist/resources/extensions/gsd/visualizer-views.ts +755 -0
- package/dist/resources/extensions/gsd/worktree-command.ts +18 -0
- package/dist/resources/extensions/gsd/worktree-manager.ts +11 -4
- package/dist/resources/extensions/remote-questions/config.ts +4 -2
- package/dist/resources/extensions/remote-questions/discord-adapter.ts +35 -4
- package/dist/resources/extensions/remote-questions/format.ts +166 -14
- package/dist/resources/extensions/remote-questions/manager.ts +14 -4
- package/dist/resources/extensions/remote-questions/remote-command.ts +100 -4
- package/dist/resources/extensions/remote-questions/slack-adapter.ts +58 -2
- package/dist/resources/extensions/remote-questions/telegram-adapter.ts +161 -0
- package/dist/resources/extensions/remote-questions/types.ts +2 -1
- package/dist/resources/extensions/ttsr/ttsr-manager.ts +26 -0
- package/dist/resources/extensions/voice/index.ts +4 -3
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +12 -1
- package/packages/pi-coding-agent/dist/core/agent-session.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 +5 -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 +6 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js +25 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.js +106 -3
- package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lsp.md +6 -0
- package/packages/pi-coding-agent/dist/core/lsp/types.d.ts +35 -0
- package/packages/pi-coding-agent/dist/core/lsp/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/types.js +6 -0
- package/packages/pi-coding-agent/dist/core/lsp/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/utils.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/lsp/utils.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/utils.js +45 -0
- package/packages/pi-coding-agent/dist/core/lsp/utils.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +43 -11
- package/packages/pi-coding-agent/dist/core/settings-manager.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 +7 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +5 -0
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +5 -0
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +13 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +6 -0
- package/packages/pi-coding-agent/src/core/lsp/client.ts +26 -0
- package/packages/pi-coding-agent/src/core/lsp/index.ts +157 -2
- package/packages/pi-coding-agent/src/core/lsp/lsp.md +6 -0
- package/packages/pi-coding-agent/src/core/lsp/types.ts +53 -0
- package/packages/pi-coding-agent/src/core/lsp/utils.ts +56 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +41 -11
- package/packages/pi-coding-agent/src/core/system-prompt.ts +7 -1
- package/packages/pi-coding-agent/src/core/tools/edit.ts +3 -0
- package/packages/pi-coding-agent/src/core/tools/write.ts +3 -0
- package/src/resources/extensions/google-search/index.ts +164 -47
- package/src/resources/extensions/gsd/auto-dashboard.ts +14 -2
- package/src/resources/extensions/gsd/auto-prompts.ts +148 -39
- package/src/resources/extensions/gsd/auto-worktree.ts +93 -9
- package/src/resources/extensions/gsd/auto.ts +690 -39
- package/src/resources/extensions/gsd/captures.ts +384 -0
- package/src/resources/extensions/gsd/commands.ts +654 -36
- package/src/resources/extensions/gsd/complexity-classifier.ts +322 -0
- package/src/resources/extensions/gsd/context-budget.ts +243 -0
- package/src/resources/extensions/gsd/context-store.ts +195 -0
- package/src/resources/extensions/gsd/dashboard-overlay.ts +51 -3
- package/src/resources/extensions/gsd/db-writer.ts +341 -0
- package/src/resources/extensions/gsd/debug-logger.ts +178 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +0 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +54 -0
- package/src/resources/extensions/gsd/doctor-proactive.ts +286 -0
- package/src/resources/extensions/gsd/doctor.ts +283 -2
- package/src/resources/extensions/gsd/export.ts +81 -2
- package/src/resources/extensions/gsd/files.ts +39 -9
- package/src/resources/extensions/gsd/git-service.ts +6 -0
- package/src/resources/extensions/gsd/gsd-db.ts +752 -0
- package/src/resources/extensions/gsd/guided-flow.ts +26 -1
- package/src/resources/extensions/gsd/history.ts +0 -1
- package/src/resources/extensions/gsd/index.ts +277 -1
- package/src/resources/extensions/gsd/md-importer.ts +526 -0
- package/src/resources/extensions/gsd/metrics.ts +84 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +65 -0
- package/src/resources/extensions/gsd/model-router.ts +256 -0
- package/src/resources/extensions/gsd/notifications.ts +0 -1
- package/src/resources/extensions/gsd/post-unit-hooks.ts +72 -2
- package/src/resources/extensions/gsd/preferences.ts +198 -150
- package/src/resources/extensions/gsd/prompt-loader.ts +45 -9
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -5
- package/src/resources/extensions/gsd/prompts/heal-skill.md +45 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +5 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +48 -0
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -0
- package/src/resources/extensions/gsd/prompts/replan-slice.md +8 -0
- package/src/resources/extensions/gsd/prompts/system.md +2 -1
- package/src/resources/extensions/gsd/prompts/triage-captures.md +62 -0
- package/src/resources/extensions/gsd/quick.ts +156 -0
- package/src/resources/extensions/gsd/skill-discovery.ts +5 -3
- package/src/resources/extensions/gsd/skill-health.ts +417 -0
- package/src/resources/extensions/gsd/skill-telemetry.ts +127 -0
- package/src/resources/extensions/gsd/state.ts +30 -0
- package/src/resources/extensions/gsd/templates/preferences.md +1 -0
- package/src/resources/extensions/gsd/tests/captures.test.ts +438 -0
- package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +181 -0
- package/src/resources/extensions/gsd/tests/context-budget.test.ts +283 -0
- package/src/resources/extensions/gsd/tests/context-compression.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/context-store.test.ts +462 -0
- package/src/resources/extensions/gsd/tests/continue-here.test.ts +204 -0
- package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +346 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +602 -0
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +185 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +406 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +22 -0
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +244 -0
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +434 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +353 -0
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +326 -0
- package/src/resources/extensions/gsd/tests/integration-edge.test.ts +228 -0
- package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +277 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +411 -0
- package/src/resources/extensions/gsd/tests/metrics.test.ts +197 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/model-isolation.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/model-router.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/parsers.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +41 -1
- package/src/resources/extensions/gsd/tests/preferences-git.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/preferences-hooks.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/preferences-mode.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/preferences-models.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +464 -0
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +385 -0
- package/src/resources/extensions/gsd/tests/remote-questions.test.ts +488 -1
- package/src/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +17 -29
- package/src/resources/extensions/gsd/tests/resolve-ts.mjs +2 -8
- package/src/resources/extensions/gsd/tests/routing-history.test.ts +215 -62
- package/src/resources/extensions/gsd/tests/skill-lifecycle.test.ts +126 -0
- package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +31 -8
- package/src/resources/extensions/gsd/tests/token-savings.test.ts +366 -0
- package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +224 -0
- package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +215 -0
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +25 -1
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +290 -0
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +478 -0
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +442 -0
- package/src/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +165 -0
- package/src/resources/extensions/gsd/triage-resolution.ts +200 -0
- package/src/resources/extensions/gsd/triage-ui.ts +175 -0
- package/src/resources/extensions/gsd/types.ts +29 -0
- package/src/resources/extensions/gsd/undo.ts +0 -1
- package/src/resources/extensions/gsd/unit-runtime.ts +5 -1
- package/src/resources/extensions/gsd/visualizer-data.ts +505 -0
- package/src/resources/extensions/gsd/visualizer-overlay.ts +337 -0
- package/src/resources/extensions/gsd/visualizer-views.ts +755 -0
- package/src/resources/extensions/gsd/worktree-command.ts +18 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +11 -4
- package/src/resources/extensions/remote-questions/config.ts +4 -2
- package/src/resources/extensions/remote-questions/discord-adapter.ts +35 -4
- package/src/resources/extensions/remote-questions/format.ts +166 -14
- package/src/resources/extensions/remote-questions/manager.ts +14 -4
- package/src/resources/extensions/remote-questions/remote-command.ts +100 -4
- package/src/resources/extensions/remote-questions/slack-adapter.ts +58 -2
- package/src/resources/extensions/remote-questions/telegram-adapter.ts +161 -0
- package/src/resources/extensions/remote-questions/types.ts +2 -1
- package/src/resources/extensions/ttsr/ttsr-manager.ts +26 -0
- package/src/resources/extensions/voice/index.ts +4 -3
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
[](https://www.npmjs.com/package/gsd-pi)
|
|
8
8
|
[](https://www.npmjs.com/package/gsd-pi)
|
|
9
9
|
[](https://github.com/gsd-build/GSD-2)
|
|
10
|
+
[](https://discord.gg/gsd)
|
|
10
11
|
[](LICENSE)
|
|
11
12
|
|
|
12
13
|
The original GSD went viral as a prompt framework for Claude Code. It worked, but it was fighting the tool — injecting prompts through slash commands, hoping the LLM would follow instructions, with no actual control over context windows, sessions, or execution.
|
|
@@ -231,6 +232,7 @@ On first run, GSD launches a branded setup wizard that walks you through LLM pro
|
|
|
231
232
|
| `/gsd` | Step mode — executes one unit at a time, pauses between each |
|
|
232
233
|
| `/gsd next` | Explicit step mode (same as bare `/gsd`) |
|
|
233
234
|
| `/gsd auto` | Autonomous mode — researches, plans, executes, commits, repeats |
|
|
235
|
+
| `/gsd quick` | Execute a quick task with GSD guarantees, skip planning overhead |
|
|
234
236
|
| `/gsd stop` | Stop auto mode gracefully |
|
|
235
237
|
| `/gsd steer` | Hard-steer plan documents during execution |
|
|
236
238
|
| `/gsd discuss` | Discuss architecture and decisions (works alongside auto mode) |
|
|
@@ -238,7 +240,9 @@ On first run, GSD launches a branded setup wizard that walks you through LLM pro
|
|
|
238
240
|
| `/gsd queue` | Queue future milestones (safe during auto mode) |
|
|
239
241
|
| `/gsd prefs` | Model selection, timeouts, budget ceiling |
|
|
240
242
|
| `/gsd migrate` | Migrate a v1 `.planning` directory to `.gsd` format |
|
|
241
|
-
| `/gsd
|
|
243
|
+
| `/gsd help` | Categorized command reference for all GSD subcommands |
|
|
244
|
+
| `/gsd mode` | Switch workflow mode (solo/team) with coordinated defaults |
|
|
245
|
+
| `/gsd doctor` | Runtime health checks with auto-fix for common issues |
|
|
242
246
|
| `/worktree` (`/wt`) | Git worktree lifecycle — create, switch, merge, remove |
|
|
243
247
|
| `/voice` | Toggle real-time speech-to-text (macOS, Linux) |
|
|
244
248
|
| `/exit` | Graceful shutdown — saves session state before exiting |
|
package/dist/cli.js
CHANGED
|
@@ -105,8 +105,10 @@ ensureManagedTools(join(agentDir, 'bin'));
|
|
|
105
105
|
const authStorage = AuthStorage.create(authFilePath);
|
|
106
106
|
loadStoredEnvKeys(authStorage);
|
|
107
107
|
migratePiCredentials(authStorage);
|
|
108
|
+
const modelRegistry = new ModelRegistry(authStorage);
|
|
109
|
+
const settingsManager = SettingsManager.create(agentDir);
|
|
108
110
|
// Run onboarding wizard on first launch (no LLM provider configured)
|
|
109
|
-
if (!isPrintMode && shouldRunOnboarding(authStorage)) {
|
|
111
|
+
if (!isPrintMode && shouldRunOnboarding(authStorage, settingsManager.getDefaultProvider())) {
|
|
110
112
|
await runOnboarding(authStorage);
|
|
111
113
|
// Clean up stdin state left by @clack/prompts.
|
|
112
114
|
// readline.emitKeypressEvents() adds a permanent data listener and
|
|
@@ -126,8 +128,6 @@ if (!isPrintMode) {
|
|
|
126
128
|
if (!isPrintMode && process.stdout.columns && process.stdout.columns < 40) {
|
|
127
129
|
process.stderr.write(chalk.yellow(`[gsd] Terminal width is ${process.stdout.columns} columns (minimum recommended: 40). Output may be unreadable.\n`));
|
|
128
130
|
}
|
|
129
|
-
const modelRegistry = new ModelRegistry(authStorage);
|
|
130
|
-
const settingsManager = SettingsManager.create(agentDir);
|
|
131
131
|
// --list-models: print available models and exit (no TTY needed)
|
|
132
132
|
if (cliFlags.listModels !== undefined) {
|
|
133
133
|
const models = modelRegistry.getAvailable();
|
package/dist/onboarding.d.ts
CHANGED
|
@@ -19,9 +19,11 @@ import type { AuthStorage } from '@gsd/pi-coding-agent';
|
|
|
19
19
|
*
|
|
20
20
|
* Returns false (skip wizard) when:
|
|
21
21
|
* - Any LLM provider is already available via auth.json, env vars, runtime overrides, or fallback auth
|
|
22
|
+
* - A default provider is already configured in settings (covers extension-based providers
|
|
23
|
+
* that may not require credentials in auth.json)
|
|
22
24
|
* - Not a TTY (piped input, subagent, CI)
|
|
23
25
|
*/
|
|
24
|
-
export declare function shouldRunOnboarding(authStorage: AuthStorage): boolean;
|
|
26
|
+
export declare function shouldRunOnboarding(authStorage: AuthStorage, settingsDefaultProvider?: string): boolean;
|
|
25
27
|
/**
|
|
26
28
|
* Run the unified onboarding wizard.
|
|
27
29
|
*
|
package/dist/onboarding.js
CHANGED
|
@@ -113,11 +113,15 @@ function isCancelError(p, err) {
|
|
|
113
113
|
*
|
|
114
114
|
* Returns false (skip wizard) when:
|
|
115
115
|
* - Any LLM provider is already available via auth.json, env vars, runtime overrides, or fallback auth
|
|
116
|
+
* - A default provider is already configured in settings (covers extension-based providers
|
|
117
|
+
* that may not require credentials in auth.json)
|
|
116
118
|
* - Not a TTY (piped input, subagent, CI)
|
|
117
119
|
*/
|
|
118
|
-
export function shouldRunOnboarding(authStorage) {
|
|
120
|
+
export function shouldRunOnboarding(authStorage, settingsDefaultProvider) {
|
|
119
121
|
if (!process.stdin.isTTY)
|
|
120
122
|
return false;
|
|
123
|
+
if (settingsDefaultProvider)
|
|
124
|
+
return false;
|
|
121
125
|
// Check if any LLM provider has credentials
|
|
122
126
|
const hasLlmAuth = LLM_PROVIDER_IDS.some(id => authStorage.hasAuth(id));
|
|
123
127
|
return !hasLlmAuth;
|
|
@@ -564,12 +568,13 @@ async function runRemoteQuestionsStep(p, pc, authStorage) {
|
|
|
564
568
|
// Check existing config
|
|
565
569
|
const hasDiscord = authStorage.has('discord_bot') && !!authStorage.get('discord_bot')?.key;
|
|
566
570
|
const hasSlack = authStorage.has('slack_bot') && !!authStorage.get('slack_bot')?.key;
|
|
567
|
-
const
|
|
571
|
+
const hasTelegram = authStorage.has('telegram_bot') && !!authStorage.get('telegram_bot')?.key;
|
|
572
|
+
const existingChannel = hasDiscord ? 'Discord' : hasSlack ? 'Slack' : hasTelegram ? 'Telegram' : null;
|
|
568
573
|
const options = [];
|
|
569
574
|
if (existingChannel) {
|
|
570
575
|
options.push({ value: 'keep', label: `Keep current (${existingChannel})`, hint: 'already configured' });
|
|
571
576
|
}
|
|
572
|
-
options.push({ value: 'discord', label: 'Discord', hint: 'receive questions in a Discord channel' }, { value: 'slack', label: 'Slack', hint: 'receive questions in a Slack channel' }, { value: 'skip', label: 'Skip for now', hint: 'use /gsd remote inside GSD later' });
|
|
577
|
+
options.push({ value: 'discord', label: 'Discord', hint: 'receive questions in a Discord channel' }, { value: 'slack', label: 'Slack', hint: 'receive questions in a Slack channel' }, { value: 'telegram', label: 'Telegram', hint: 'receive questions via Telegram bot' }, { value: 'skip', label: 'Skip for now', hint: 'use /gsd remote inside GSD later' });
|
|
573
578
|
const choice = await p.select({
|
|
574
579
|
message: 'Set up remote questions? (get notified when GSD needs input)',
|
|
575
580
|
options,
|
|
@@ -638,6 +643,74 @@ async function runRemoteQuestionsStep(p, pc, authStorage) {
|
|
|
638
643
|
p.log.success(`Slack channel: ${pc.green(channelId.trim())}`);
|
|
639
644
|
return 'Slack';
|
|
640
645
|
}
|
|
646
|
+
if (choice === 'telegram') {
|
|
647
|
+
const token = await p.password({
|
|
648
|
+
message: 'Paste your Telegram bot token (from @BotFather):',
|
|
649
|
+
mask: '●',
|
|
650
|
+
});
|
|
651
|
+
if (p.isCancel(token) || !token?.trim())
|
|
652
|
+
return null;
|
|
653
|
+
const trimmed = token.trim();
|
|
654
|
+
if (!/^\d+:[A-Za-z0-9_-]+$/.test(trimmed)) {
|
|
655
|
+
p.log.warn('Invalid token format — Telegram bot tokens look like 123456789:ABCdefGHI...');
|
|
656
|
+
return null;
|
|
657
|
+
}
|
|
658
|
+
// Validate
|
|
659
|
+
const s = p.spinner();
|
|
660
|
+
s.start('Validating Telegram bot token...');
|
|
661
|
+
try {
|
|
662
|
+
const res = await fetch(`https://api.telegram.org/bot${trimmed}/getMe`, {
|
|
663
|
+
signal: AbortSignal.timeout(15_000),
|
|
664
|
+
});
|
|
665
|
+
const data = await res.json();
|
|
666
|
+
if (!data?.ok || !data?.result?.id) {
|
|
667
|
+
s.stop('Telegram token validation failed');
|
|
668
|
+
return null;
|
|
669
|
+
}
|
|
670
|
+
s.stop(`Telegram bot: ${pc.green(data.result.first_name ?? data.result.username ?? 'bot')}`);
|
|
671
|
+
}
|
|
672
|
+
catch {
|
|
673
|
+
s.stop('Could not reach Telegram API');
|
|
674
|
+
return null;
|
|
675
|
+
}
|
|
676
|
+
authStorage.set('telegram_bot', { type: 'api_key', key: trimmed });
|
|
677
|
+
process.env.TELEGRAM_BOT_TOKEN = trimmed;
|
|
678
|
+
const chatId = await p.text({
|
|
679
|
+
message: 'Paste the Telegram chat ID (e.g. -1001234567890):',
|
|
680
|
+
validate: (val) => {
|
|
681
|
+
if (!val || !/^-?\d{5,20}$/.test(val.trim()))
|
|
682
|
+
return 'Expected a numeric chat ID (can be negative for groups)';
|
|
683
|
+
},
|
|
684
|
+
});
|
|
685
|
+
if (p.isCancel(chatId) || !chatId)
|
|
686
|
+
return null;
|
|
687
|
+
const trimmedChatId = chatId.trim();
|
|
688
|
+
// Test send
|
|
689
|
+
const ts = p.spinner();
|
|
690
|
+
ts.start('Testing message delivery...');
|
|
691
|
+
try {
|
|
692
|
+
const res = await fetch(`https://api.telegram.org/bot${trimmed}/sendMessage`, {
|
|
693
|
+
method: 'POST',
|
|
694
|
+
headers: { 'Content-Type': 'application/json' },
|
|
695
|
+
body: JSON.stringify({ chat_id: trimmedChatId, text: 'GSD remote questions connected.' }),
|
|
696
|
+
signal: AbortSignal.timeout(15_000),
|
|
697
|
+
});
|
|
698
|
+
const data = await res.json();
|
|
699
|
+
if (!data?.ok) {
|
|
700
|
+
ts.stop(`Could not send to chat: ${data?.description ?? 'unknown error'}`);
|
|
701
|
+
return null;
|
|
702
|
+
}
|
|
703
|
+
ts.stop('Test message sent');
|
|
704
|
+
}
|
|
705
|
+
catch {
|
|
706
|
+
ts.stop('Could not reach Telegram API');
|
|
707
|
+
return null;
|
|
708
|
+
}
|
|
709
|
+
const { saveRemoteQuestionsConfig } = await import('./remote-questions-config.js');
|
|
710
|
+
saveRemoteQuestionsConfig('telegram', trimmedChatId);
|
|
711
|
+
p.log.success(`Telegram chat: ${pc.green(trimmedChatId)}`);
|
|
712
|
+
return 'Telegram';
|
|
713
|
+
}
|
|
641
714
|
return null;
|
|
642
715
|
}
|
|
643
716
|
async function runDiscordChannelStep(p, pc, token) {
|
|
@@ -756,6 +829,7 @@ export function loadStoredEnvKeys(authStorage) {
|
|
|
756
829
|
['jina', 'JINA_API_KEY'],
|
|
757
830
|
['slack_bot', 'SLACK_BOT_TOKEN'],
|
|
758
831
|
['discord_bot', 'DISCORD_BOT_TOKEN'],
|
|
832
|
+
['telegram_bot', 'TELEGRAM_BOT_TOKEN'],
|
|
759
833
|
['groq', 'GROQ_API_KEY'],
|
|
760
834
|
['ollama-cloud', 'OLLAMA_API_KEY'],
|
|
761
835
|
['custom-openai', 'CUSTOM_OPENAI_API_KEY'],
|
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
* but onboarding.ts is compiled by tsc — dynamic imports from compiled
|
|
8
8
|
* JS to uncompiled .ts fail at runtime (#592).
|
|
9
9
|
*/
|
|
10
|
-
export declare function saveRemoteQuestionsConfig(channel: "slack" | "discord", channelId: string): void;
|
|
10
|
+
export declare function saveRemoteQuestionsConfig(channel: "slack" | "discord" | "telegram", channelId: string): void;
|
|
@@ -68,6 +68,101 @@ async function getClient(): Promise<GoogleGenAIClient> {
|
|
|
68
68
|
return client;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Perform a search using OAuth credentials via the Cloud Code Assist API.
|
|
73
|
+
* This is used as a fallback when GEMINI_API_KEY is not set.
|
|
74
|
+
*/
|
|
75
|
+
async function searchWithOAuth(
|
|
76
|
+
query: string,
|
|
77
|
+
accessToken: string,
|
|
78
|
+
projectId: string,
|
|
79
|
+
signal?: AbortSignal,
|
|
80
|
+
): Promise<SearchResult> {
|
|
81
|
+
const model = process.env.GEMINI_SEARCH_MODEL || "gemini-2.5-flash";
|
|
82
|
+
const url = `https://cloudcode-pa.googleapis.com/v1internal:streamGenerateContent`;
|
|
83
|
+
|
|
84
|
+
const GEMINI_CLI_HEADERS = {
|
|
85
|
+
ideType: "IDE_UNSPECIFIED",
|
|
86
|
+
platform: "PLATFORM_UNSPECIFIED",
|
|
87
|
+
pluginType: "GEMINI",
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const executeFetch = async (retries = 3): Promise<Response> => {
|
|
91
|
+
const response = await fetch(url, {
|
|
92
|
+
method: "POST",
|
|
93
|
+
headers: {
|
|
94
|
+
Authorization: `Bearer ${accessToken}`,
|
|
95
|
+
"Content-Type": "application/json",
|
|
96
|
+
"User-Agent": "google-cloud-sdk vscode_cloudshelleditor/0.1",
|
|
97
|
+
"X-Goog-Api-Client": "gl-node/22.17.0",
|
|
98
|
+
"Client-Metadata": JSON.stringify(GEMINI_CLI_HEADERS),
|
|
99
|
+
},
|
|
100
|
+
body: JSON.stringify({
|
|
101
|
+
project: projectId,
|
|
102
|
+
model,
|
|
103
|
+
request: {
|
|
104
|
+
contents: [{ parts: [{ text: query }] }],
|
|
105
|
+
tools: [{ googleSearch: {} }],
|
|
106
|
+
},
|
|
107
|
+
}),
|
|
108
|
+
signal,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
if (!response.ok && retries > 0 && (response.status === 429 || response.status >= 500)) {
|
|
112
|
+
await new Promise((resolve) => setTimeout(resolve, 1000 * (4 - retries)));
|
|
113
|
+
return executeFetch(retries - 1);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return response;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const response = await executeFetch();
|
|
120
|
+
|
|
121
|
+
if (!response.ok) {
|
|
122
|
+
const errorText = await response.text();
|
|
123
|
+
throw new Error(`Cloud Code Assist API error (${response.status}): ${errorText}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Note: streamGenerateContent returns SSE; for now, we consume all chunks.
|
|
127
|
+
// For simplicity and to match the previous structure, we'll read to end.
|
|
128
|
+
const text = await response.text();
|
|
129
|
+
const jsonLines = text.split("\n")
|
|
130
|
+
.filter(l => l.startsWith("data:"))
|
|
131
|
+
.map(l => l.slice(5).trim())
|
|
132
|
+
.filter(l => l.length > 0);
|
|
133
|
+
|
|
134
|
+
let data;
|
|
135
|
+
if (jsonLines.length > 0) {
|
|
136
|
+
// Aggregate chunks if needed, but for now we take the last chunk or assume it's one
|
|
137
|
+
data = JSON.parse(jsonLines[jsonLines.length - 1]);
|
|
138
|
+
} else {
|
|
139
|
+
data = JSON.parse(text);
|
|
140
|
+
} const candidate = data.response?.candidates?.[0];
|
|
141
|
+
const answer = candidate?.content?.parts?.find((p: any) => p.text)?.text ?? "";
|
|
142
|
+
const grounding = candidate?.groundingMetadata;
|
|
143
|
+
|
|
144
|
+
const sources: SearchSource[] = [];
|
|
145
|
+
const seenTitles = new Set<string>();
|
|
146
|
+
if (grounding?.groundingChunks) {
|
|
147
|
+
for (const chunk of grounding.groundingChunks) {
|
|
148
|
+
if (chunk.web) {
|
|
149
|
+
const title = chunk.web.title ?? "Untitled";
|
|
150
|
+
if (seenTitles.has(title)) continue;
|
|
151
|
+
seenTitles.add(title);
|
|
152
|
+
const domain = chunk.web.domain ?? title;
|
|
153
|
+
sources.push({
|
|
154
|
+
title,
|
|
155
|
+
uri: chunk.web.uri ?? "",
|
|
156
|
+
domain,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const searchQueries = grounding?.webSearchQueries ?? [];
|
|
163
|
+
return { answer, sources, searchQueries, cached: false };
|
|
164
|
+
}
|
|
165
|
+
|
|
71
166
|
// ── In-session cache ─────────────────────────────────────────────────────────
|
|
72
167
|
|
|
73
168
|
const resultCache = new Map<string, SearchResult>();
|
|
@@ -87,7 +182,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
87
182
|
"Returns an AI-synthesized answer grounded in Google Search results, plus source URLs. " +
|
|
88
183
|
"Use this when you need current information from the web: recent events, documentation, " +
|
|
89
184
|
"product details, technical references, news, etc. " +
|
|
90
|
-
"Requires GEMINI_API_KEY. Alternative to Brave-based search tools
|
|
185
|
+
"Requires GEMINI_API_KEY or Google login. Alternative to Brave-based search tools.",
|
|
91
186
|
promptSnippet: "Search the web via Google Search to get current information with sources",
|
|
92
187
|
promptGuidelines: [
|
|
93
188
|
"Use google_search when you need up-to-date web information that isn't in your training data.",
|
|
@@ -109,17 +204,33 @@ export default function (pi: ExtensionAPI) {
|
|
|
109
204
|
),
|
|
110
205
|
}),
|
|
111
206
|
|
|
112
|
-
async execute(_toolCallId, params, signal, _onUpdate,
|
|
207
|
+
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
113
208
|
const startTime = Date.now();
|
|
114
209
|
const maxSources = Math.min(Math.max(params.maxSources ?? 5, 1), 10);
|
|
115
210
|
|
|
116
|
-
// Check for
|
|
211
|
+
// Check for credentials
|
|
212
|
+
let oauthToken: string | undefined;
|
|
213
|
+
let projectId: string | undefined;
|
|
214
|
+
|
|
117
215
|
if (!process.env.GEMINI_API_KEY) {
|
|
216
|
+
const oauthRaw = await ctx.modelRegistry.getApiKeyForProvider("google-gemini-cli");
|
|
217
|
+
if (oauthRaw) {
|
|
218
|
+
try {
|
|
219
|
+
const parsed = JSON.parse(oauthRaw);
|
|
220
|
+
oauthToken = parsed.token;
|
|
221
|
+
projectId = parsed.projectId;
|
|
222
|
+
} catch {
|
|
223
|
+
// Fall through to error
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (!process.env.GEMINI_API_KEY && (!oauthToken || !projectId)) {
|
|
118
229
|
return {
|
|
119
230
|
content: [
|
|
120
231
|
{
|
|
121
232
|
type: "text",
|
|
122
|
-
text: "Error:
|
|
233
|
+
text: "Error: No authentication found for Google Search. Please set GEMINI_API_KEY or log in via Google.\n\nExample: export GEMINI_API_KEY=your_key or use /login google",
|
|
123
234
|
},
|
|
124
235
|
],
|
|
125
236
|
isError: true,
|
|
@@ -128,7 +239,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
128
239
|
sourceCount: 0,
|
|
129
240
|
cached: false,
|
|
130
241
|
durationMs: Date.now() - startTime,
|
|
131
|
-
error: "auth_error:
|
|
242
|
+
error: "auth_error: No credentials set",
|
|
132
243
|
} as SearchDetails,
|
|
133
244
|
};
|
|
134
245
|
}
|
|
@@ -152,49 +263,52 @@ export default function (pi: ExtensionAPI) {
|
|
|
152
263
|
// Call Gemini with Google Search grounding
|
|
153
264
|
let result: SearchResult;
|
|
154
265
|
try {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
266
|
+
if (process.env.GEMINI_API_KEY) {
|
|
267
|
+
const ai = await getClient();
|
|
268
|
+
const response = await ai.models.generateContent({
|
|
269
|
+
model: process.env.GEMINI_SEARCH_MODEL || "gemini-2.5-flash",
|
|
270
|
+
contents: params.query,
|
|
271
|
+
config: {
|
|
272
|
+
tools: [{ googleSearch: {} }],
|
|
273
|
+
abortSignal: signal,
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// Extract answer text
|
|
278
|
+
const answer = response.text ?? "";
|
|
279
|
+
|
|
280
|
+
// Extract grounding metadata
|
|
281
|
+
const candidate = response.candidates?.[0];
|
|
282
|
+
const grounding = candidate?.groundingMetadata;
|
|
283
|
+
|
|
284
|
+
// Parse sources from grounding chunks
|
|
285
|
+
const sources: SearchSource[] = [];
|
|
286
|
+
const seenTitles = new Set<string>();
|
|
287
|
+
if (grounding?.groundingChunks) {
|
|
288
|
+
for (const chunk of grounding.groundingChunks) {
|
|
289
|
+
if (chunk.web) {
|
|
290
|
+
const title = chunk.web.title ?? "Untitled";
|
|
291
|
+
// Dedupe by title since URIs are redirect URLs that differ per call
|
|
292
|
+
if (seenTitles.has(title)) continue;
|
|
293
|
+
seenTitles.add(title);
|
|
294
|
+
// domain field is not available via Gemini API, use title as fallback
|
|
295
|
+
// (title is typically the domain name, e.g. "wikipedia.org")
|
|
296
|
+
const domain = chunk.web.domain ?? title;
|
|
297
|
+
sources.push({
|
|
298
|
+
title,
|
|
299
|
+
uri: chunk.web.uri ?? "",
|
|
300
|
+
domain,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
190
303
|
}
|
|
191
304
|
}
|
|
192
|
-
}
|
|
193
305
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
306
|
+
// Extract search queries Gemini actually performed
|
|
307
|
+
const searchQueries = grounding?.webSearchQueries ?? [];
|
|
308
|
+
result = { answer, sources, searchQueries, cached: false };
|
|
309
|
+
} else {
|
|
310
|
+
result = await searchWithOAuth(params.query, oauthToken!, projectId!, signal);
|
|
311
|
+
}
|
|
198
312
|
} catch (err: unknown) {
|
|
199
313
|
const msg = err instanceof Error ? err.message : String(err);
|
|
200
314
|
|
|
@@ -287,9 +401,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
287
401
|
// ── Startup notification ─────────────────────────────────────────────────
|
|
288
402
|
|
|
289
403
|
pi.on("session_start", async (_event, ctx) => {
|
|
290
|
-
if (
|
|
404
|
+
if (process.env.GEMINI_API_KEY) return;
|
|
405
|
+
|
|
406
|
+
const hasOAuth = await ctx.modelRegistry.authStorage.hasAuth("google-gemini-cli");
|
|
407
|
+
if (!hasOAuth) {
|
|
291
408
|
ctx.ui.notify(
|
|
292
|
-
"Google Search: No
|
|
409
|
+
"Google Search: No authentication set. Log in via Google or set GEMINI_API_KEY to use google_search.",
|
|
293
410
|
"warning",
|
|
294
411
|
);
|
|
295
412
|
}
|
|
@@ -10,7 +10,7 @@ import type { ExtensionContext, ExtensionCommandContext } from "@gsd/pi-coding-a
|
|
|
10
10
|
import type { GSDState } from "./types.js";
|
|
11
11
|
import { getCurrentBranch } from "./worktree.js";
|
|
12
12
|
import { getActiveHook } from "./post-unit-hooks.js";
|
|
13
|
-
import { getLedger, getProjectTotals, formatCost, formatTokenCount } from "./metrics.js";
|
|
13
|
+
import { getLedger, getProjectTotals, formatCost, formatTokenCount, formatTierSavings } from "./metrics.js";
|
|
14
14
|
import {
|
|
15
15
|
resolveMilestoneFile,
|
|
16
16
|
resolveSliceFile,
|
|
@@ -39,6 +39,8 @@ export interface AutoDashboardData {
|
|
|
39
39
|
projectedRemainingCost?: number;
|
|
40
40
|
/** Whether token profile has been auto-downgraded due to budget prediction */
|
|
41
41
|
profileDowngraded?: boolean;
|
|
42
|
+
/** Number of pending captures awaiting triage (0 if none or file missing) */
|
|
43
|
+
pendingCaptureCount: number;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
// ─── Unit Description Helpers ─────────────────────────────────────────────────
|
|
@@ -239,6 +241,7 @@ export function updateProgressWidget(
|
|
|
239
241
|
unitId: string,
|
|
240
242
|
state: GSDState,
|
|
241
243
|
accessors: WidgetStateAccessors,
|
|
244
|
+
tierBadge?: string,
|
|
242
245
|
): void {
|
|
243
246
|
if (!ctx.hasUI) return;
|
|
244
247
|
|
|
@@ -319,7 +322,8 @@ export function updateProgressWidget(
|
|
|
319
322
|
|
|
320
323
|
const target = task ? `${task.id}: ${task.title}` : unitId;
|
|
321
324
|
const actionLeft = `${pad}${theme.fg("accent", "▸")} ${theme.fg("accent", verb)} ${theme.fg("text", target)}`;
|
|
322
|
-
const
|
|
325
|
+
const tierTag = tierBadge ? theme.fg("dim", `[${tierBadge}] `) : "";
|
|
326
|
+
const phaseBadge = `${tierTag}${theme.fg("dim", phaseLabel)}`;
|
|
323
327
|
lines.push(rightAlign(actionLeft, phaseBadge, width));
|
|
324
328
|
lines.push("");
|
|
325
329
|
|
|
@@ -414,6 +418,14 @@ export function updateProgressWidget(
|
|
|
414
418
|
? `${modelPhase}${theme.fg("dim", modelDisplay)}`
|
|
415
419
|
: "";
|
|
416
420
|
lines.push(rightAlign(`${pad}${sLeft}`, sRight, width));
|
|
421
|
+
|
|
422
|
+
// Dynamic routing savings summary
|
|
423
|
+
if (mLedger && mLedger.units.some(u => u.tier)) {
|
|
424
|
+
const savings = formatTierSavings(mLedger.units);
|
|
425
|
+
if (savings) {
|
|
426
|
+
lines.push(truncateToWidth(theme.fg("dim", `${pad}${savings}`), width));
|
|
427
|
+
}
|
|
428
|
+
}
|
|
417
429
|
}
|
|
418
430
|
|
|
419
431
|
const hintParts: string[] = [];
|