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
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// GSD Extension — Model Cost Table
|
|
2
|
+
// Static cost reference for known models, used by the dynamic router
|
|
3
|
+
// for cross-provider cost comparison.
|
|
4
|
+
//
|
|
5
|
+
// Costs are approximate per-1K-token rates in USD (input tokens).
|
|
6
|
+
// Updated with GSD releases. Users can override via preferences.
|
|
7
|
+
|
|
8
|
+
export interface ModelCostEntry {
|
|
9
|
+
/** Model ID (bare, without provider prefix) */
|
|
10
|
+
id: string;
|
|
11
|
+
/** Approximate cost per 1K input tokens in USD */
|
|
12
|
+
inputPer1k: number;
|
|
13
|
+
/** Approximate cost per 1K output tokens in USD */
|
|
14
|
+
outputPer1k: number;
|
|
15
|
+
/** Last updated date */
|
|
16
|
+
updatedAt: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Bundled cost table for known models.
|
|
21
|
+
* Updated periodically with GSD releases.
|
|
22
|
+
*/
|
|
23
|
+
export const BUNDLED_COST_TABLE: ModelCostEntry[] = [
|
|
24
|
+
// Anthropic
|
|
25
|
+
{ id: "claude-opus-4-6", inputPer1k: 0.015, outputPer1k: 0.075, updatedAt: "2025-03-15" },
|
|
26
|
+
{ id: "claude-sonnet-4-6", inputPer1k: 0.003, outputPer1k: 0.015, updatedAt: "2025-03-15" },
|
|
27
|
+
{ id: "claude-haiku-4-5", inputPer1k: 0.0008, outputPer1k: 0.004, updatedAt: "2025-03-15" },
|
|
28
|
+
{ id: "claude-sonnet-4-5-20250514", inputPer1k: 0.003, outputPer1k: 0.015, updatedAt: "2025-03-15" },
|
|
29
|
+
{ id: "claude-3-5-sonnet-latest", inputPer1k: 0.003, outputPer1k: 0.015, updatedAt: "2025-03-15" },
|
|
30
|
+
{ id: "claude-3-5-haiku-latest", inputPer1k: 0.0008, outputPer1k: 0.004, updatedAt: "2025-03-15" },
|
|
31
|
+
{ id: "claude-3-opus-latest", inputPer1k: 0.015, outputPer1k: 0.075, updatedAt: "2025-03-15" },
|
|
32
|
+
|
|
33
|
+
// OpenAI
|
|
34
|
+
{ id: "gpt-4o", inputPer1k: 0.0025, outputPer1k: 0.01, updatedAt: "2025-03-15" },
|
|
35
|
+
{ id: "gpt-4o-mini", inputPer1k: 0.00015, outputPer1k: 0.0006, updatedAt: "2025-03-15" },
|
|
36
|
+
{ id: "o1", inputPer1k: 0.015, outputPer1k: 0.06, updatedAt: "2025-03-15" },
|
|
37
|
+
{ id: "o3", inputPer1k: 0.015, outputPer1k: 0.06, updatedAt: "2025-03-15" },
|
|
38
|
+
{ id: "gpt-4-turbo", inputPer1k: 0.01, outputPer1k: 0.03, updatedAt: "2025-03-15" },
|
|
39
|
+
|
|
40
|
+
// Google
|
|
41
|
+
{ id: "gemini-2.0-flash", inputPer1k: 0.0001, outputPer1k: 0.0004, updatedAt: "2025-03-15" },
|
|
42
|
+
{ id: "gemini-flash-2.0", inputPer1k: 0.0001, outputPer1k: 0.0004, updatedAt: "2025-03-15" },
|
|
43
|
+
{ id: "gemini-2.5-pro", inputPer1k: 0.00125, outputPer1k: 0.005, updatedAt: "2025-03-15" },
|
|
44
|
+
|
|
45
|
+
// DeepSeek
|
|
46
|
+
{ id: "deepseek-chat", inputPer1k: 0.00014, outputPer1k: 0.00028, updatedAt: "2025-03-15" },
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Lookup cost for a model ID. Returns undefined if not found.
|
|
51
|
+
*/
|
|
52
|
+
export function lookupModelCost(modelId: string): ModelCostEntry | undefined {
|
|
53
|
+
const bareId = modelId.includes("/") ? modelId.split("/").pop()! : modelId;
|
|
54
|
+
return BUNDLED_COST_TABLE.find(e => e.id === bareId)
|
|
55
|
+
?? BUNDLED_COST_TABLE.find(e => bareId.includes(e.id) || e.id.includes(bareId));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Compare two models by input cost. Returns negative if a is cheaper.
|
|
60
|
+
*/
|
|
61
|
+
export function compareModelCost(modelIdA: string, modelIdB: string): number {
|
|
62
|
+
const costA = lookupModelCost(modelIdA)?.inputPer1k ?? 999;
|
|
63
|
+
const costB = lookupModelCost(modelIdB)?.inputPer1k ?? 999;
|
|
64
|
+
return costA - costB;
|
|
65
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
// GSD Extension — Dynamic Model Router
|
|
2
|
+
// Maps complexity tiers to models, enforcing downgrade-only semantics.
|
|
3
|
+
// The user's configured model is always the ceiling.
|
|
4
|
+
|
|
5
|
+
import type { ComplexityTier, ClassificationResult } from "./complexity-classifier.js";
|
|
6
|
+
import { tierOrdinal } from "./complexity-classifier.js";
|
|
7
|
+
import type { ResolvedModelConfig } from "./preferences.js";
|
|
8
|
+
|
|
9
|
+
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
10
|
+
|
|
11
|
+
export interface DynamicRoutingConfig {
|
|
12
|
+
enabled?: boolean;
|
|
13
|
+
tier_models?: {
|
|
14
|
+
light?: string;
|
|
15
|
+
standard?: string;
|
|
16
|
+
heavy?: string;
|
|
17
|
+
};
|
|
18
|
+
escalate_on_failure?: boolean; // default: true
|
|
19
|
+
budget_pressure?: boolean; // default: true
|
|
20
|
+
cross_provider?: boolean; // default: true
|
|
21
|
+
hooks?: boolean; // default: true
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface RoutingDecision {
|
|
25
|
+
/** The model ID to use (may be downgraded from configured) */
|
|
26
|
+
modelId: string;
|
|
27
|
+
/** Fallback chain: [selected_model, ...configured_fallbacks, configured_primary] */
|
|
28
|
+
fallbacks: string[];
|
|
29
|
+
/** The complexity tier that drove this decision */
|
|
30
|
+
tier: ComplexityTier;
|
|
31
|
+
/** True if the model was downgraded from the configured primary */
|
|
32
|
+
wasDowngraded: boolean;
|
|
33
|
+
/** Human-readable reason for this decision */
|
|
34
|
+
reason: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ─── Known Model Tiers ───────────────────────────────────────────────────────
|
|
38
|
+
// Maps known model IDs to their capability tier. Used when tier_models is not
|
|
39
|
+
// explicitly configured to pick the best available model for each tier.
|
|
40
|
+
|
|
41
|
+
const MODEL_CAPABILITY_TIER: Record<string, ComplexityTier> = {
|
|
42
|
+
// Light-tier models (cheapest)
|
|
43
|
+
"claude-haiku-4-5": "light",
|
|
44
|
+
"claude-3-5-haiku-latest": "light",
|
|
45
|
+
"claude-3-haiku-20240307": "light",
|
|
46
|
+
"gpt-4o-mini": "light",
|
|
47
|
+
"gemini-2.0-flash": "light",
|
|
48
|
+
"gemini-flash-2.0": "light",
|
|
49
|
+
|
|
50
|
+
// Standard-tier models
|
|
51
|
+
"claude-sonnet-4-6": "standard",
|
|
52
|
+
"claude-sonnet-4-5-20250514": "standard",
|
|
53
|
+
"claude-3-5-sonnet-latest": "standard",
|
|
54
|
+
"gpt-4o": "standard",
|
|
55
|
+
"gemini-2.5-pro": "standard",
|
|
56
|
+
"deepseek-chat": "standard",
|
|
57
|
+
|
|
58
|
+
// Heavy-tier models (most capable)
|
|
59
|
+
"claude-opus-4-6": "heavy",
|
|
60
|
+
"claude-3-opus-latest": "heavy",
|
|
61
|
+
"gpt-4-turbo": "heavy",
|
|
62
|
+
"o1": "heavy",
|
|
63
|
+
"o3": "heavy",
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// ─── Cost Table (per 1K input tokens, approximate USD) ───────────────────────
|
|
67
|
+
// Used for cross-provider cost comparison when multiple providers offer
|
|
68
|
+
// the same capability tier.
|
|
69
|
+
|
|
70
|
+
const MODEL_COST_PER_1K_INPUT: Record<string, number> = {
|
|
71
|
+
"claude-haiku-4-5": 0.0008,
|
|
72
|
+
"claude-3-5-haiku-latest": 0.0008,
|
|
73
|
+
"claude-sonnet-4-6": 0.003,
|
|
74
|
+
"claude-sonnet-4-5-20250514": 0.003,
|
|
75
|
+
"claude-opus-4-6": 0.015,
|
|
76
|
+
"gpt-4o-mini": 0.00015,
|
|
77
|
+
"gpt-4o": 0.0025,
|
|
78
|
+
"gemini-2.0-flash": 0.0001,
|
|
79
|
+
"gemini-2.5-pro": 0.00125,
|
|
80
|
+
"deepseek-chat": 0.00014,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// ─── Public API ──────────────────────────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Resolve the model to use for a given complexity tier.
|
|
87
|
+
*
|
|
88
|
+
* Downgrade-only: the returned model is always equal to or cheaper than
|
|
89
|
+
* the user's configured primary model. Never upgrades beyond configuration.
|
|
90
|
+
*
|
|
91
|
+
* @param classification The complexity classification result
|
|
92
|
+
* @param phaseConfig The user's configured model for this phase (ceiling)
|
|
93
|
+
* @param routingConfig Dynamic routing configuration
|
|
94
|
+
* @param availableModelIds List of available model IDs (from registry)
|
|
95
|
+
*/
|
|
96
|
+
export function resolveModelForComplexity(
|
|
97
|
+
classification: ClassificationResult,
|
|
98
|
+
phaseConfig: ResolvedModelConfig | undefined,
|
|
99
|
+
routingConfig: DynamicRoutingConfig,
|
|
100
|
+
availableModelIds: string[],
|
|
101
|
+
): RoutingDecision {
|
|
102
|
+
// If no phase config or routing disabled, pass through
|
|
103
|
+
if (!phaseConfig || !routingConfig.enabled) {
|
|
104
|
+
return {
|
|
105
|
+
modelId: phaseConfig?.primary ?? "",
|
|
106
|
+
fallbacks: phaseConfig?.fallbacks ?? [],
|
|
107
|
+
tier: classification.tier,
|
|
108
|
+
wasDowngraded: false,
|
|
109
|
+
reason: "dynamic routing disabled or no phase config",
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const configuredPrimary = phaseConfig.primary;
|
|
114
|
+
const configuredTier = getModelTier(configuredPrimary);
|
|
115
|
+
const requestedTier = classification.tier;
|
|
116
|
+
|
|
117
|
+
// Downgrade-only: if requested tier >= configured tier, no change
|
|
118
|
+
if (tierOrdinal(requestedTier) >= tierOrdinal(configuredTier)) {
|
|
119
|
+
return {
|
|
120
|
+
modelId: configuredPrimary,
|
|
121
|
+
fallbacks: phaseConfig.fallbacks,
|
|
122
|
+
tier: requestedTier,
|
|
123
|
+
wasDowngraded: false,
|
|
124
|
+
reason: `tier ${requestedTier} >= configured ${configuredTier}`,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Find the best model for the requested tier
|
|
129
|
+
const targetModelId = findModelForTier(
|
|
130
|
+
requestedTier,
|
|
131
|
+
routingConfig,
|
|
132
|
+
availableModelIds,
|
|
133
|
+
routingConfig.cross_provider !== false,
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
if (!targetModelId) {
|
|
137
|
+
// No suitable model found — use configured primary
|
|
138
|
+
return {
|
|
139
|
+
modelId: configuredPrimary,
|
|
140
|
+
fallbacks: phaseConfig.fallbacks,
|
|
141
|
+
tier: requestedTier,
|
|
142
|
+
wasDowngraded: false,
|
|
143
|
+
reason: `no ${requestedTier}-tier model available`,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Build fallback chain: [downgraded_model, ...configured_fallbacks, configured_primary]
|
|
148
|
+
const fallbacks = [
|
|
149
|
+
...phaseConfig.fallbacks.filter(f => f !== targetModelId),
|
|
150
|
+
configuredPrimary,
|
|
151
|
+
].filter(f => f !== targetModelId);
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
modelId: targetModelId,
|
|
155
|
+
fallbacks,
|
|
156
|
+
tier: requestedTier,
|
|
157
|
+
wasDowngraded: true,
|
|
158
|
+
reason: classification.reason,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Escalate to the next tier after a failure.
|
|
164
|
+
* Returns the new tier, or null if already at heavy (max).
|
|
165
|
+
*/
|
|
166
|
+
export function escalateTier(currentTier: ComplexityTier): ComplexityTier | null {
|
|
167
|
+
switch (currentTier) {
|
|
168
|
+
case "light": return "standard";
|
|
169
|
+
case "standard": return "heavy";
|
|
170
|
+
case "heavy": return null;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Get the default routing config (all features enabled).
|
|
176
|
+
*/
|
|
177
|
+
export function defaultRoutingConfig(): DynamicRoutingConfig {
|
|
178
|
+
return {
|
|
179
|
+
enabled: false,
|
|
180
|
+
escalate_on_failure: true,
|
|
181
|
+
budget_pressure: true,
|
|
182
|
+
cross_provider: true,
|
|
183
|
+
hooks: true,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// ─── Internal ────────────────────────────────────────────────────────────────
|
|
188
|
+
|
|
189
|
+
function getModelTier(modelId: string): ComplexityTier {
|
|
190
|
+
// Strip provider prefix if present
|
|
191
|
+
const bareId = modelId.includes("/") ? modelId.split("/").pop()! : modelId;
|
|
192
|
+
|
|
193
|
+
// Check exact match first
|
|
194
|
+
if (MODEL_CAPABILITY_TIER[bareId]) return MODEL_CAPABILITY_TIER[bareId];
|
|
195
|
+
|
|
196
|
+
// Check if any known model ID is a prefix/suffix match
|
|
197
|
+
for (const [knownId, tier] of Object.entries(MODEL_CAPABILITY_TIER)) {
|
|
198
|
+
if (bareId.includes(knownId) || knownId.includes(bareId)) return tier;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Unknown models are assumed heavy (safest assumption)
|
|
202
|
+
return "heavy";
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function findModelForTier(
|
|
206
|
+
tier: ComplexityTier,
|
|
207
|
+
config: DynamicRoutingConfig,
|
|
208
|
+
availableModelIds: string[],
|
|
209
|
+
crossProvider: boolean,
|
|
210
|
+
): string | null {
|
|
211
|
+
// 1. Check explicit tier_models config
|
|
212
|
+
const explicitModel = config.tier_models?.[tier];
|
|
213
|
+
if (explicitModel && availableModelIds.includes(explicitModel)) {
|
|
214
|
+
return explicitModel;
|
|
215
|
+
}
|
|
216
|
+
// Also check with provider prefix stripped
|
|
217
|
+
if (explicitModel) {
|
|
218
|
+
const match = availableModelIds.find(id => {
|
|
219
|
+
const bareAvail = id.includes("/") ? id.split("/").pop()! : id;
|
|
220
|
+
const bareExplicit = explicitModel.includes("/") ? explicitModel.split("/").pop()! : explicitModel;
|
|
221
|
+
return bareAvail === bareExplicit;
|
|
222
|
+
});
|
|
223
|
+
if (match) return match;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// 2. Auto-detect: find the cheapest available model in the requested tier
|
|
227
|
+
const candidates = availableModelIds
|
|
228
|
+
.filter(id => {
|
|
229
|
+
const modelTier = getModelTier(id);
|
|
230
|
+
return modelTier === tier;
|
|
231
|
+
})
|
|
232
|
+
.sort((a, b) => {
|
|
233
|
+
if (!crossProvider) return 0;
|
|
234
|
+
const costA = getModelCost(a);
|
|
235
|
+
const costB = getModelCost(b);
|
|
236
|
+
return costA - costB;
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
return candidates[0] ?? null;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function getModelCost(modelId: string): number {
|
|
243
|
+
const bareId = modelId.includes("/") ? modelId.split("/").pop()! : modelId;
|
|
244
|
+
|
|
245
|
+
if (MODEL_COST_PER_1K_INPUT[bareId] !== undefined) {
|
|
246
|
+
return MODEL_COST_PER_1K_INPUT[bareId];
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Check partial matches
|
|
250
|
+
for (const [knownId, cost] of Object.entries(MODEL_COST_PER_1K_INPUT)) {
|
|
251
|
+
if (bareId.includes(knownId) || knownId.includes(bareId)) return cost;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Unknown cost — assume expensive to avoid routing to unknown cheap models
|
|
255
|
+
return 999;
|
|
256
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// GSD Extension — Desktop Notification Helper
|
|
2
2
|
// Cross-platform desktop notifications for auto-mode events.
|
|
3
|
-
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
4
3
|
|
|
5
4
|
import { execFileSync } from "node:child_process";
|
|
6
5
|
import type { NotificationPreferences } from "./types.js";
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// GSD Extension — Hook Engine (Post-Unit, Pre-Dispatch, State Persistence)
|
|
2
2
|
// Manages hook queue, cycle tracking, artifact verification, pre-dispatch
|
|
3
3
|
// interception, and durable hook state for user-configured extensibility.
|
|
4
|
-
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
5
4
|
|
|
6
5
|
import type {
|
|
7
6
|
PostUnitHookConfig,
|
|
@@ -60,7 +59,8 @@ export function checkPostUnitHooks(
|
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
// Don't trigger hooks for other hook units (prevent hook-on-hook chains)
|
|
63
|
-
|
|
62
|
+
// Don't trigger hooks for triage units (prevent hook-on-triage chains)
|
|
63
|
+
if (completedUnitType.startsWith("hook/") || completedUnitType === "triage-captures") return null;
|
|
64
64
|
|
|
65
65
|
// Check if any hooks are configured for this unit type
|
|
66
66
|
const hooks = resolvePostUnitHooks().filter(h =>
|
|
@@ -411,6 +411,76 @@ export function getHookStatus(): HookStatusEntry[] {
|
|
|
411
411
|
return entries;
|
|
412
412
|
}
|
|
413
413
|
|
|
414
|
+
/**
|
|
415
|
+
* Manually trigger a specific hook for a unit.
|
|
416
|
+
* This bypasses the normal flow and forces the hook to run even if its artifact exists.
|
|
417
|
+
*
|
|
418
|
+
* @param hookName - The name of the hook to trigger (e.g., "code-review")
|
|
419
|
+
* @param unitType - The type of unit that triggered the hook (e.g., "execute-task")
|
|
420
|
+
* @param unitId - The unit ID (e.g., "M001/S01/T01")
|
|
421
|
+
* @param basePath - The project base path
|
|
422
|
+
* @returns The hook dispatch result or null if hook not found
|
|
423
|
+
*/
|
|
424
|
+
export function triggerHookManually(
|
|
425
|
+
hookName: string,
|
|
426
|
+
unitType: string,
|
|
427
|
+
unitId: string,
|
|
428
|
+
basePath: string,
|
|
429
|
+
): HookDispatchResult | null {
|
|
430
|
+
// Find the hook configuration
|
|
431
|
+
const hook = resolvePostUnitHooks().find(h => h.name === hookName);
|
|
432
|
+
if (!hook) {
|
|
433
|
+
console.error(`[triggerHookManually] Hook "${hookName}" not found in post_unit_hooks`);
|
|
434
|
+
return null;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (!hook.prompt || typeof hook.prompt !== 'string' || hook.prompt.trim().length === 0) {
|
|
438
|
+
console.error(`[triggerHookManually] Hook "${hookName}" has empty prompt`);
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// Reset any active hook state to allow manual triggering
|
|
443
|
+
activeHook = {
|
|
444
|
+
hookName: hook.name,
|
|
445
|
+
triggerUnitType: unitType,
|
|
446
|
+
triggerUnitId: unitId,
|
|
447
|
+
cycle: 1,
|
|
448
|
+
pendingRetry: false,
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
// Build the hook queue with just this hook
|
|
452
|
+
hookQueue = [{
|
|
453
|
+
config: hook,
|
|
454
|
+
triggerUnitType: unitType,
|
|
455
|
+
triggerUnitId: unitId,
|
|
456
|
+
}];
|
|
457
|
+
|
|
458
|
+
// Set the cycle count for this specific hook+trigger
|
|
459
|
+
const cycleKey = `${hook.name}/${unitType}/${unitId}`;
|
|
460
|
+
const currentCycle = (cycleCounts.get(cycleKey) ?? 0) + 1;
|
|
461
|
+
cycleCounts.set(cycleKey, currentCycle);
|
|
462
|
+
|
|
463
|
+
// Update active hook with the cycle count
|
|
464
|
+
activeHook.cycle = currentCycle;
|
|
465
|
+
|
|
466
|
+
// Build the prompt with variable substitution
|
|
467
|
+
const [mid, sid, tid] = unitId.split("/");
|
|
468
|
+
const prompt = hook.prompt
|
|
469
|
+
.replace(/\{milestoneId\}/g, mid ?? "")
|
|
470
|
+
.replace(/\{sliceId\}/g, sid ?? "")
|
|
471
|
+
.replace(/\{taskId\}/g, tid ?? "");
|
|
472
|
+
|
|
473
|
+
console.log(`[triggerHookManually] Built prompt for ${hookName}, length: ${prompt.length}`);
|
|
474
|
+
|
|
475
|
+
return {
|
|
476
|
+
hookName: hook.name,
|
|
477
|
+
prompt,
|
|
478
|
+
model: hook.model,
|
|
479
|
+
unitType: `hook/${hook.name}`,
|
|
480
|
+
unitId,
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
|
|
414
484
|
/**
|
|
415
485
|
* Format hook status for terminal display.
|
|
416
486
|
*/
|