gsd-pi 2.78.0-dev.aeeb2ca00 → 2.78.1-dev.84a383f51
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 +7 -7
- package/dist/claude-cli-check.js +64 -37
- package/dist/cli-policy.d.ts +13 -0
- package/dist/cli-policy.js +17 -0
- package/dist/cli.js +95 -55
- package/dist/headless-query.d.ts +22 -0
- package/dist/headless-query.js +24 -4
- package/dist/headless.d.ts +10 -0
- package/dist/headless.js +16 -1
- package/dist/loader.js +7 -10
- package/dist/onboarding.d.ts +10 -0
- package/dist/onboarding.js +2 -2
- package/dist/provider-migrations.d.ts +2 -2
- package/dist/provider-migrations.js +5 -2
- package/dist/resource-loader.d.ts +5 -2
- package/dist/resource-loader.js +28 -5
- package/dist/resources/.managed-resources-content-hash +1 -0
- package/dist/resources/extensions/claude-code-cli/readiness.js +77 -45
- package/dist/resources/extensions/gsd/auto/loop.js +23 -0
- package/dist/resources/extensions/gsd/auto/phases.js +2 -2
- package/dist/resources/extensions/gsd/auto/run-unit.js +3 -1
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +43 -4
- package/dist/resources/extensions/gsd/auto-runtime-state.js +31 -0
- package/dist/resources/extensions/gsd/auto-start.js +1 -1
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +30 -0
- package/dist/resources/extensions/gsd/auto.js +14 -5
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +14 -2
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -5
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -4
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +94 -31
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +11 -6
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +34 -8
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +38 -2
- package/dist/resources/extensions/gsd/commands/catalog.js +69 -5
- package/dist/resources/extensions/gsd/commands/handlers/core.js +22 -1
- package/dist/resources/extensions/gsd/commands-mcp-status.js +3 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -1
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +4 -0
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +39 -1
- package/dist/resources/extensions/gsd/error-classifier.js +1 -1
- package/dist/resources/extensions/gsd/forensics.js +2 -2
- package/dist/resources/extensions/gsd/git-service.js +12 -5
- package/dist/resources/extensions/gsd/gsd-db.js +11 -2
- package/dist/resources/extensions/gsd/guided-flow.js +23 -23
- package/dist/resources/extensions/gsd/memory-store.js +66 -31
- package/dist/resources/extensions/gsd/milestone-id-reservation.js +36 -0
- package/dist/resources/extensions/gsd/model-router.js +114 -9
- package/dist/resources/extensions/gsd/native-git-bridge.js +7 -1
- package/dist/resources/extensions/gsd/preferences-models.js +91 -15
- package/dist/resources/extensions/gsd/preferences-types.js +2 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +32 -0
- package/dist/resources/extensions/gsd/preferences.js +5 -3
- package/dist/resources/extensions/gsd/prompt-loader.js +23 -12
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +9 -3
- package/dist/resources/extensions/gsd/state.js +42 -0
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/dist/resources/extensions/gsd/tools/memory-tools.js +18 -1
- package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
- package/dist/resources/extensions/gsd/watch/header-renderer.js +3 -1
- package/dist/resources/extensions/gsd/worktree-command.js +26 -46
- package/dist/resources/extensions/gsd/worktree-session-state.js +33 -0
- package/dist/resources/extensions/mcp-client/index.js +6 -3
- package/dist/resources/extensions/slash-commands/create-extension.js +36 -22
- package/dist/resources/skills/create-gsd-extension/SKILL.md +9 -5
- package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
- package/dist/rtk-shared.d.ts +3 -0
- package/dist/rtk-shared.js +17 -0
- package/dist/rtk.d.ts +2 -5
- package/dist/rtk.js +3 -20
- package/dist/runtime-checks.d.ts +27 -0
- package/dist/runtime-checks.js +38 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
- 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/react-loadable-manifest.json +44 -4
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/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 +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +4 -2
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
- package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +1 -0
- package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +1 -0
- package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +1 -0
- package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +1 -0
- package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +1 -0
- package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +1 -0
- package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +10 -0
- package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +2 -0
- package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +20 -0
- package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-5b113fd32bc2a1c3.js → page-9bf2e0c50fb2ca05.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +1 -0
- package/dist/web/standalone/package.json +2 -1
- package/dist/worktree-status-banner.d.ts +1 -0
- package/dist/worktree-status-banner.js +132 -0
- package/package.json +1 -1
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/dist/alias-telemetry.d.ts +8 -0
- package/packages/mcp-server/dist/alias-telemetry.d.ts.map +1 -0
- package/packages/mcp-server/dist/alias-telemetry.js +30 -0
- package/packages/mcp-server/dist/alias-telemetry.js.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +74 -46
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/alias-telemetry.test.ts +78 -0
- package/packages/mcp-server/src/alias-telemetry.ts +30 -0
- package/packages/mcp-server/src/workflow-tools.test.ts +26 -0
- package/packages/mcp-server/src/workflow-tools.ts +93 -58
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +231 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +48 -19
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +13 -0
- 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/dist/utils/repair-tool-json.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.js +24 -3
- package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +26 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +289 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +52 -20
- package/packages/pi-ai/src/types.ts +13 -0
- package/packages/pi-ai/src/utils/repair-tool-json.ts +24 -3
- package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +32 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +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 +6 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.js +4 -0
- package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +19 -2
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +10 -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 +18 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +13 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +20 -16
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +37 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.js +49 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +133 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +78 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +181 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +7 -0
- package/packages/pi-coding-agent/src/core/messages.ts +4 -0
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +32 -2
- package/packages/pi-coding-agent/src/core/model-registry.ts +21 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +33 -15
- package/packages/pi-coding-agent/src/core/token-telemetry.ts +77 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +212 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +17 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
- package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +102 -0
- package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +200 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +17 -3
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +161 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +1 -0
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -3
- package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +219 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +78 -46
- package/src/resources/extensions/gsd/auto/loop.ts +24 -2
- package/src/resources/extensions/gsd/auto/phases.ts +3 -3
- package/src/resources/extensions/gsd/auto/run-unit.ts +3 -1
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto/types.ts +1 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +46 -8
- package/src/resources/extensions/gsd/auto-runtime-state.ts +51 -0
- package/src/resources/extensions/gsd/auto-start.ts +1 -1
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +2 -4
- package/src/resources/extensions/gsd/auto-worktree.ts +38 -0
- package/src/resources/extensions/gsd/auto.ts +14 -4
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +15 -13
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +8 -7
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +10 -9
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +102 -31
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +12 -6
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +39 -8
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +39 -11
- package/src/resources/extensions/gsd/commands/catalog.ts +75 -5
- package/src/resources/extensions/gsd/commands/handlers/core.ts +22 -1
- package/src/resources/extensions/gsd/commands-mcp-status.ts +3 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -1
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +4 -0
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +39 -1
- package/src/resources/extensions/gsd/doctor-types.ts +3 -1
- package/src/resources/extensions/gsd/error-classifier.ts +1 -1
- package/src/resources/extensions/gsd/forensics.ts +2 -2
- package/src/resources/extensions/gsd/git-service.ts +13 -5
- package/src/resources/extensions/gsd/gsd-db.ts +12 -2
- package/src/resources/extensions/gsd/guided-flow.ts +25 -25
- package/src/resources/extensions/gsd/memory-store.ts +81 -28
- package/src/resources/extensions/gsd/milestone-id-reservation.ts +47 -0
- package/src/resources/extensions/gsd/model-router.ts +172 -9
- package/src/resources/extensions/gsd/native-git-bridge.ts +7 -1
- package/src/resources/extensions/gsd/preferences-models.ts +101 -15
- package/src/resources/extensions/gsd/preferences-types.ts +6 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +35 -0
- package/src/resources/extensions/gsd/preferences.ts +16 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +26 -12
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +9 -3
- package/src/resources/extensions/gsd/state.ts +42 -0
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +178 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +9 -5
- package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +21 -4
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +138 -211
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +142 -59
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +7 -4
- package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +89 -32
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +41 -23
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +3 -43
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +22 -87
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +7 -118
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +18 -60
- package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +14 -76
- package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +22 -83
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +1 -63
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +81 -0
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +22 -12
- package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +0 -23
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +128 -0
- package/src/resources/extensions/gsd/tests/memory-tools.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +124 -0
- package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +152 -0
- package/src/resources/extensions/gsd/tests/model-router.test.ts +169 -8
- package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +32 -43
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +4 -10
- package/src/resources/extensions/gsd/tests/preferences.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +168 -19
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +23 -1
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +51 -4
- package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +7 -16
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +15 -1
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -0
- package/src/resources/extensions/gsd/tools/memory-tools.ts +17 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +8 -8
- package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
- package/src/resources/extensions/gsd/watch/header-renderer.ts +3 -1
- package/src/resources/extensions/gsd/workflow-logger.ts +1 -0
- package/src/resources/extensions/gsd/worktree-command.ts +31 -44
- package/src/resources/extensions/gsd/worktree-session-state.ts +35 -0
- package/src/resources/extensions/mcp-client/index.ts +6 -3
- package/src/resources/extensions/mcp-client/tests/global-config.test.ts +91 -0
- package/src/resources/extensions/slash-commands/create-extension.ts +38 -24
- package/src/resources/skills/create-gsd-extension/SKILL.md +9 -5
- package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
- package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
- package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +58 -0
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +0 -601
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +0 -651
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +0 -91
- package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +0 -53
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +0 -112
- package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +0 -23
- package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +0 -5
- package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
- package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +0 -608
- package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +0 -11
- package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +0 -20
- package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +0 -1
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +0 -22
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +0 -47
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +0 -75
- /package/dist/web/standalone/.next/static/{cAJH99yNS1UPbeSEiNRrV → UF5VF4F1tB0miEtJS7LyX}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{cAJH99yNS1UPbeSEiNRrV → UF5VF4F1tB0miEtJS7LyX}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #4757 — readConfigs() must also read the global
|
|
3
|
+
* ~/.gsd/mcp.json (resolved as $GSD_HOME/mcp.json when GSD_HOME is set).
|
|
4
|
+
*
|
|
5
|
+
* Behaviour test against the exported getServerConfig — no source grep.
|
|
6
|
+
* The fixture is anchored via $GSD_HOME so the test never touches the
|
|
7
|
+
* developer's real ~/.gsd directory.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import test, { before, after } from "node:test";
|
|
11
|
+
import assert from "node:assert/strict";
|
|
12
|
+
import { writeFileSync, mkdtempSync, realpathSync, rmSync } from "node:fs";
|
|
13
|
+
import { tmpdir } from "node:os";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
|
|
16
|
+
import { getServerConfig } from "../index.js";
|
|
17
|
+
|
|
18
|
+
let cwdDir: string;
|
|
19
|
+
let gsdHomeDir: string;
|
|
20
|
+
let originalCwd: string;
|
|
21
|
+
let originalGsdHome: string | undefined;
|
|
22
|
+
|
|
23
|
+
before(() => {
|
|
24
|
+
originalCwd = process.cwd();
|
|
25
|
+
originalGsdHome = process.env.GSD_HOME;
|
|
26
|
+
|
|
27
|
+
// realpathSync resolves any symlink in tmpdir() — on macOS /var → /private/var
|
|
28
|
+
// so process.cwd() after chdir matches what mkdtempSync returned.
|
|
29
|
+
cwdDir = realpathSync(mkdtempSync(join(tmpdir(), "mcp-cwd-")));
|
|
30
|
+
gsdHomeDir = realpathSync(mkdtempSync(join(tmpdir(), "mcp-gsdhome-")));
|
|
31
|
+
|
|
32
|
+
// Project-local fixture (also defines `shared-server` for the precedence test)
|
|
33
|
+
writeFileSync(
|
|
34
|
+
join(cwdDir, ".mcp.json"),
|
|
35
|
+
JSON.stringify({
|
|
36
|
+
mcpServers: {
|
|
37
|
+
"project-server": { command: "echo", args: ["proj"] },
|
|
38
|
+
"shared-server": { command: "echo", args: ["from-project"] },
|
|
39
|
+
},
|
|
40
|
+
}),
|
|
41
|
+
"utf-8",
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
// Global fixture rooted at $GSD_HOME (also defines `shared-server` to test
|
|
45
|
+
// that project-local takes precedence on name collision)
|
|
46
|
+
writeFileSync(
|
|
47
|
+
join(gsdHomeDir, "mcp.json"),
|
|
48
|
+
JSON.stringify({
|
|
49
|
+
mcpServers: {
|
|
50
|
+
"global-server": { command: "echo", args: ["glob"] },
|
|
51
|
+
"shared-server": { command: "echo", args: ["from-global"] },
|
|
52
|
+
},
|
|
53
|
+
}),
|
|
54
|
+
"utf-8",
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
process.chdir(cwdDir);
|
|
58
|
+
process.env.GSD_HOME = gsdHomeDir;
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
after(() => {
|
|
62
|
+
process.chdir(originalCwd);
|
|
63
|
+
if (originalGsdHome === undefined) delete process.env.GSD_HOME;
|
|
64
|
+
else process.env.GSD_HOME = originalGsdHome;
|
|
65
|
+
try { rmSync(cwdDir, { recursive: true, force: true }); } catch { /* best-effort */ }
|
|
66
|
+
try { rmSync(gsdHomeDir, { recursive: true, force: true }); } catch { /* best-effort */ }
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("#4757: getServerConfig resolves servers declared in $GSD_HOME/mcp.json", () => {
|
|
70
|
+
const cfg = getServerConfig("global-server");
|
|
71
|
+
assert.ok(cfg, "server defined in $GSD_HOME/mcp.json must resolve");
|
|
72
|
+
assert.equal(cfg?.name, "global-server");
|
|
73
|
+
assert.equal(cfg?.sourcePath, join(gsdHomeDir, "mcp.json"));
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("#4757: project-local servers still resolve when global config exists", () => {
|
|
77
|
+
const cfg = getServerConfig("project-server");
|
|
78
|
+
assert.ok(cfg, "project-local server must continue to resolve");
|
|
79
|
+
assert.equal(cfg?.sourcePath, join(cwdDir, ".mcp.json"));
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("#4757: project-local config wins on server-name collision", () => {
|
|
83
|
+
const cfg = getServerConfig("shared-server");
|
|
84
|
+
assert.ok(cfg, "shared server must resolve");
|
|
85
|
+
assert.equal(
|
|
86
|
+
cfg?.sourcePath,
|
|
87
|
+
join(cwdDir, ".mcp.json"),
|
|
88
|
+
"project-local config must take precedence over $GSD_HOME on name collision",
|
|
89
|
+
);
|
|
90
|
+
assert.deepEqual(cfg?.args, ["from-project"]);
|
|
91
|
+
});
|
|
@@ -221,41 +221,38 @@ function sendPrompt(description: string, result: RoundResult, pi: ExtensionAPI):
|
|
|
221
221
|
: "";
|
|
222
222
|
|
|
223
223
|
const docHints: string[] = [
|
|
224
|
-
"-
|
|
225
|
-
"-
|
|
226
|
-
"-
|
|
227
|
-
"-
|
|
228
|
-
"- `~/.gsd/agent/docs/extending-pi/22-key-rules-gotchas.md` — must-read rules before shipping",
|
|
224
|
+
"- `docs/extension-sdk/README.md` — overview, quick start, directory layout",
|
|
225
|
+
"- `docs/extension-sdk/api-reference.md` — ExtensionAPI and ExtensionContext surfaces",
|
|
226
|
+
"- `docs/extension-sdk/building-extensions.md` — tools, commands, events, UI, state",
|
|
227
|
+
"- `docs/extension-sdk/rules.md` — non-negotiable rules and gotchas",
|
|
229
228
|
];
|
|
230
229
|
|
|
231
230
|
if (uiSelected.includes("custom component")) {
|
|
232
|
-
docHints.push("-
|
|
233
|
-
docHints.push("-
|
|
234
|
-
docHints.push("-
|
|
235
|
-
docHints.push("-
|
|
236
|
-
docHints.push("-
|
|
237
|
-
docHints.push("- `~/.gsd/agent/docs/pi-ui-tui/19-building-a-complete-component-step-by-step.md` — step-by-step guide");
|
|
238
|
-
docHints.push("- `~/.gsd/agent/docs/pi-ui-tui/21-common-mistakes-and-how-to-avoid-them.md` — pitfalls");
|
|
231
|
+
docHints.push("- `docs/extension-sdk/building-extensions.md#custom-components` — ctx.ui.custom() API");
|
|
232
|
+
docHints.push("- `docs/dev/pi-ui-tui/06-ctx-ui-custom-full-custom-components.md` — step-by-step component guide");
|
|
233
|
+
docHints.push("- `docs/dev/pi-ui-tui/07-built-in-components-the-building-blocks.md` — Text, Box, SelectList");
|
|
234
|
+
docHints.push("- `docs/dev/pi-ui-tui/09-keyboard-input-how-to-handle-keys.md` — Key, matchesKey");
|
|
235
|
+
docHints.push("- `docs/dev/pi-ui-tui/10-line-width-the-cardinal-rule.md` — truncation, width rules");
|
|
239
236
|
} else if (uiSelected.includes("Dialogs")) {
|
|
240
|
-
docHints.push("-
|
|
237
|
+
docHints.push("- `docs/extension-sdk/building-extensions.md#built-in-dialogs` — select, confirm, input");
|
|
241
238
|
} else if (uiSelected.includes("Status")) {
|
|
242
|
-
docHints.push("-
|
|
239
|
+
docHints.push("- `docs/extension-sdk/building-extensions.md#persistent-ui-elements` — status, widgets");
|
|
243
240
|
}
|
|
244
241
|
|
|
245
242
|
if (uiSelected.includes("tool") || result.answers["purpose"]) {
|
|
246
|
-
docHints.push("-
|
|
243
|
+
docHints.push("- `docs/dev/extending-pi/14-custom-rendering-controlling-what-the-user-sees.md` — renderCall / renderResult");
|
|
247
244
|
}
|
|
248
245
|
|
|
249
246
|
if (eventsSelected && !eventsSelected.includes("standalone")) {
|
|
250
|
-
docHints.push("-
|
|
247
|
+
docHints.push("- `docs/dev/extending-pi/07-events-the-nervous-system.md` — all events reference");
|
|
251
248
|
}
|
|
252
249
|
|
|
253
250
|
if (eventsSelected.includes("context / prompt")) {
|
|
254
|
-
docHints.push("-
|
|
251
|
+
docHints.push("- `docs/dev/extending-pi/15-system-prompt-modification.md` — system prompt hooks");
|
|
255
252
|
}
|
|
256
253
|
|
|
257
254
|
if (persistenceSelected.includes("session")) {
|
|
258
|
-
docHints.push("-
|
|
255
|
+
docHints.push("- `docs/extension-sdk/building-extensions.md#state-management` — state reconstruction, appendEntry");
|
|
259
256
|
}
|
|
260
257
|
|
|
261
258
|
const prompt = `Create a new pi extension based on this description:
|
|
@@ -270,13 +267,30 @@ ${docHints.join("\n")}
|
|
|
270
267
|
|
|
271
268
|
## Output
|
|
272
269
|
|
|
273
|
-
Write the complete implementation as a
|
|
274
|
-
|
|
275
|
-
\`~/.gsd/agent/extensions/<kebab-case-name
|
|
276
|
-
|
|
277
|
-
|
|
270
|
+
Write the complete implementation as a directory-based extension:
|
|
271
|
+
|
|
272
|
+
\`~/.gsd/agent/extensions/<kebab-case-name>/index.ts\`
|
|
273
|
+
\`~/.gsd/agent/extensions/<kebab-case-name>/extension-manifest.json\`
|
|
274
|
+
|
|
275
|
+
The manifest must follow this format:
|
|
276
|
+
\`\`\`json
|
|
277
|
+
{
|
|
278
|
+
"id": "<kebab-case-name>",
|
|
279
|
+
"name": "<Human Name>",
|
|
280
|
+
"version": "1.0.0",
|
|
281
|
+
"description": "<one-line description>",
|
|
282
|
+
"tier": "community",
|
|
283
|
+
"requires": { "platform": ">=2.29.0" },
|
|
284
|
+
"provides": {
|
|
285
|
+
"tools": ["<tool_names_registered>"],
|
|
286
|
+
"commands": ["<command_names_registered>"],
|
|
287
|
+
"hooks": ["<event_names_subscribed>"],
|
|
288
|
+
"shortcuts": ["<shortcut_keys_registered>"]
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
\`\`\`
|
|
278
292
|
|
|
279
|
-
|
|
293
|
+
Only include non-empty arrays in \`provides\`. See \`docs/extension-sdk/manifest-spec.md\` for the full spec.
|
|
280
294
|
|
|
281
295
|
## Rules you must follow exactly
|
|
282
296
|
|
|
@@ -19,8 +19,8 @@ Note: `~/.gsd/agent/extensions/` is reserved for bundled extensions synced from
|
|
|
19
19
|
3. **Commands** — Give users slash commands (`pi.registerCommand()`). Users type `/mycommand`.
|
|
20
20
|
|
|
21
21
|
**Non-negotiable rules:**
|
|
22
|
-
- Use `StringEnum` from `@
|
|
23
|
-
- Truncate tool output to 50KB / 2000 lines max (use `truncateHead`/`truncateTail` from `@
|
|
22
|
+
- Use `StringEnum` from `@gsd/pi-ai` for string enum params (NOT `Type.Union`/`Type.Literal` — breaks Google's API)
|
|
23
|
+
- Truncate tool output to 50KB / 2000 lines max (use `truncateHead`/`truncateTail` from `@gsd/pi-coding-agent`)
|
|
24
24
|
- Store stateful tool state in `details` for branching support
|
|
25
25
|
- Check `signal?.aborted` in long-running tool executions
|
|
26
26
|
- Use `pi.exec()` not `child_process` for shell commands
|
|
@@ -34,10 +34,10 @@ Note: `~/.gsd/agent/extensions/` is reserved for bundled extensions synced from
|
|
|
34
34
|
|
|
35
35
|
| Package | Purpose |
|
|
36
36
|
|---------|---------|
|
|
37
|
-
| `@
|
|
37
|
+
| `@gsd/pi-coding-agent` | `ExtensionAPI`, `ExtensionContext`, `Theme`, event types, tool utilities, `DynamicBorder`, `BorderedLoader`, `CustomEditor`, `highlightCode` |
|
|
38
38
|
| `@sinclair/typebox` | `Type.Object`, `Type.String`, `Type.Number`, `Type.Optional`, `Type.Boolean`, `Type.Array` |
|
|
39
|
-
| `@
|
|
40
|
-
| `@
|
|
39
|
+
| `@gsd/pi-ai` | `StringEnum` (required for string enums), `Type` re-export |
|
|
40
|
+
| `@gsd/pi-tui` | `Text`, `Box`, `Container`, `Spacer`, `Markdown`, `SelectList`, `Input`, `matchesKey`, `Key`, `truncateToWidth`, `visibleWidth` |
|
|
41
41
|
| Node.js built-ins | `node:fs`, `node:path`, `node:child_process`, etc. |
|
|
42
42
|
|
|
43
43
|
</essential_principles>
|
|
@@ -65,6 +65,9 @@ All domain knowledge in `references/`:
|
|
|
65
65
|
**Capabilities:** custom-tools.md, custom-commands.md, custom-ui.md, custom-rendering.md
|
|
66
66
|
**Patterns:** state-management.md, system-prompt-modification.md, compaction-session-control.md
|
|
67
67
|
**Infrastructure:** model-provider-management.md, remote-execution-overrides.md, packaging-distribution.md, mode-behavior.md
|
|
68
|
+
**Spec:** `docs/extension-sdk/manifest-spec.md` — manifest format, tiers, validation
|
|
69
|
+
**Testing:** `docs/extension-sdk/testing.md` — mock patterns, test conventions
|
|
70
|
+
**SDK:** `docs/extension-sdk/` — the authoritative GSD-2 extension guide
|
|
68
71
|
**Gotchas:** key-rules-gotchas.md
|
|
69
72
|
</reference_index>
|
|
70
73
|
|
|
@@ -78,6 +81,7 @@ All domain knowledge in `references/`:
|
|
|
78
81
|
|
|
79
82
|
<success_criteria>
|
|
80
83
|
Extension is complete when:
|
|
84
|
+
- `extension-manifest.json` exists with accurate `provides` listing all registered tools/commands/hooks/shortcuts
|
|
81
85
|
- TypeScript compiles without errors (jiti handles this at runtime)
|
|
82
86
|
- Extension loads on GSD startup or `/reload` without errors
|
|
83
87
|
- Tools appear in the LLM's system prompt and are callable
|
|
@@ -19,7 +19,7 @@ pi.registerCommand("deploy", {
|
|
|
19
19
|
Add tab-completion for command arguments:
|
|
20
20
|
|
|
21
21
|
```typescript
|
|
22
|
-
import type { AutocompleteItem } from "@
|
|
22
|
+
import type { AutocompleteItem } from "@gsd/pi-tui";
|
|
23
23
|
|
|
24
24
|
pi.registerCommand("deploy", {
|
|
25
25
|
description: "Deploy to an environment",
|
|
@@ -6,8 +6,8 @@ Custom rendering for tools and messages — control how they appear in the TUI.
|
|
|
6
6
|
Tools can provide `renderCall` (how the call looks) and `renderResult` (how the result looks):
|
|
7
7
|
|
|
8
8
|
```typescript
|
|
9
|
-
import { Text } from "@
|
|
10
|
-
import { keyHint } from "@
|
|
9
|
+
import { Text } from "@gsd/pi-tui";
|
|
10
|
+
import { keyHint } from "@gsd/pi-coding-agent";
|
|
11
11
|
|
|
12
12
|
pi.registerTool({
|
|
13
13
|
name: "my_tool",
|
|
@@ -54,7 +54,7 @@ If you omit `renderCall`/`renderResult`, the built-in renderer is used. Useful f
|
|
|
54
54
|
Key hint helpers for showing keybinding info in render output:
|
|
55
55
|
|
|
56
56
|
```typescript
|
|
57
|
-
import { keyHint, appKeyHint, editorKey, rawKeyHint } from "@
|
|
57
|
+
import { keyHint, appKeyHint, editorKey, rawKeyHint } from "@gsd/pi-coding-agent";
|
|
58
58
|
|
|
59
59
|
// Editor action hint (respects user keybinding config)
|
|
60
60
|
keyHint("expandTools", "to expand") // e.g., "Ctrl+O to expand"
|
|
@@ -69,7 +69,7 @@ rawKeyHint("Ctrl+O", "to expand")
|
|
|
69
69
|
Register a renderer for custom message types:
|
|
70
70
|
|
|
71
71
|
```typescript
|
|
72
|
-
import { Text } from "@
|
|
72
|
+
import { Text } from "@gsd/pi-tui";
|
|
73
73
|
|
|
74
74
|
pi.registerMessageRenderer("my-extension", (message, options, theme) => {
|
|
75
75
|
const { expanded } = options;
|
|
@@ -92,7 +92,7 @@ pi.sendMessage({
|
|
|
92
92
|
|
|
93
93
|
<syntax_highlighting>
|
|
94
94
|
```typescript
|
|
95
|
-
import { highlightCode, getLanguageFromPath } from "@
|
|
95
|
+
import { highlightCode, getLanguageFromPath } from "@gsd/pi-coding-agent";
|
|
96
96
|
|
|
97
97
|
const lang = getLanguageFromPath("/path/to/file.rs"); // "rust"
|
|
98
98
|
const highlighted = highlightCode(code, lang, theme);
|
|
@@ -5,7 +5,7 @@ Complete custom tools reference — registration, parameters, execution, output
|
|
|
5
5
|
<registration>
|
|
6
6
|
```typescript
|
|
7
7
|
import { Type } from "@sinclair/typebox";
|
|
8
|
-
import { StringEnum } from "@
|
|
8
|
+
import { StringEnum } from "@gsd/pi-ai";
|
|
9
9
|
|
|
10
10
|
pi.registerTool({
|
|
11
11
|
name: "my_tool", // Unique identifier (snake_case)
|
|
@@ -60,7 +60,7 @@ pi.registerTool({
|
|
|
60
60
|
**⚠️ MUST use `StringEnum` for string enum parameters:**
|
|
61
61
|
|
|
62
62
|
```typescript
|
|
63
|
-
import { StringEnum } from "@
|
|
63
|
+
import { StringEnum } from "@gsd/pi-ai";
|
|
64
64
|
|
|
65
65
|
// ✅ Correct — works with all providers including Google
|
|
66
66
|
action: StringEnum(["list", "add", "remove"] as const)
|
|
@@ -77,7 +77,7 @@ Tools MUST truncate output to avoid context overflow. Built-in limit: 50KB / 200
|
|
|
77
77
|
import {
|
|
78
78
|
truncateHead, truncateTail, formatSize,
|
|
79
79
|
DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES,
|
|
80
|
-
} from "@
|
|
80
|
+
} from "@gsd/pi-coding-agent";
|
|
81
81
|
|
|
82
82
|
async execute(toolCallId, params, signal, onUpdate, ctx) {
|
|
83
83
|
const output = await runCommand();
|
|
@@ -129,7 +129,7 @@ Use `pi.setActiveTools(names)` to enable/disable tools at runtime.
|
|
|
129
129
|
Register a tool with the same name as a built-in (`read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`) to override it. **Must match exact result shape including `details` type.**
|
|
130
130
|
|
|
131
131
|
```typescript
|
|
132
|
-
import { createReadTool } from "@
|
|
132
|
+
import { createReadTool } from "@gsd/pi-coding-agent";
|
|
133
133
|
|
|
134
134
|
pi.registerTool({
|
|
135
135
|
name: "read",
|
|
@@ -277,7 +277,7 @@ bottom-left bottom-center bottom-right
|
|
|
277
277
|
Replace the main input editor permanently:
|
|
278
278
|
|
|
279
279
|
```typescript
|
|
280
|
-
import { CustomEditor } from "@
|
|
280
|
+
import { CustomEditor } from "@gsd/pi-coding-agent";
|
|
281
281
|
|
|
282
282
|
class VimEditor extends CustomEditor {
|
|
283
283
|
private mode: "normal" | "insert" = "insert";
|
|
@@ -307,7 +307,7 @@ ctx.ui.setEditorComponent(undefined); // Restore default
|
|
|
307
307
|
</custom_editor>
|
|
308
308
|
|
|
309
309
|
<built_in_components>
|
|
310
|
-
**From `@
|
|
310
|
+
**From `@gsd/pi-tui`:**
|
|
311
311
|
|
|
312
312
|
| Component | Constructor | Purpose |
|
|
313
313
|
|-----------|-------------|---------|
|
|
@@ -352,7 +352,7 @@ const settings = new SettingsList(items, 15, getSettingsListTheme(),
|
|
|
352
352
|
);
|
|
353
353
|
```
|
|
354
354
|
|
|
355
|
-
**From `@
|
|
355
|
+
**From `@gsd/pi-coding-agent`:**
|
|
356
356
|
|
|
357
357
|
| Component | Constructor | Purpose |
|
|
358
358
|
|-----------|-------------|---------|
|
|
@@ -363,7 +363,7 @@ const settings = new SettingsList(items, 15, getSettingsListTheme(),
|
|
|
363
363
|
|
|
364
364
|
<keyboard_input>
|
|
365
365
|
```typescript
|
|
366
|
-
import { matchesKey, Key } from "@
|
|
366
|
+
import { matchesKey, Key } from "@gsd/pi-tui";
|
|
367
367
|
|
|
368
368
|
handleInput(data: string) {
|
|
369
369
|
// Basic keys
|
|
@@ -403,7 +403,7 @@ handleInput(data: string) {
|
|
|
403
403
|
**Cardinal rule: each line from render() must not exceed `width` visible characters.**
|
|
404
404
|
|
|
405
405
|
```typescript
|
|
406
|
-
import { visibleWidth, truncateToWidth, wrapTextWithAnsi } from "@
|
|
406
|
+
import { visibleWidth, truncateToWidth, wrapTextWithAnsi } from "@gsd/pi-tui";
|
|
407
407
|
|
|
408
408
|
visibleWidth("\x1b[32mHello\x1b[0m"); // Returns 5 (ignores ANSI codes)
|
|
409
409
|
truncateToWidth("Very long text here", 10); // "Very lo..."
|
|
@@ -470,7 +470,7 @@ Always use theme from callback params, never import directly.
|
|
|
470
470
|
|
|
471
471
|
**Syntax highlighting:**
|
|
472
472
|
```typescript
|
|
473
|
-
import { highlightCode, getLanguageFromPath } from "@
|
|
473
|
+
import { highlightCode, getLanguageFromPath } from "@gsd/pi-coding-agent";
|
|
474
474
|
const lang = getLanguageFromPath("/file.rs"); // "rust"
|
|
475
475
|
const highlighted = highlightCode(code, lang, theme);
|
|
476
476
|
```
|
|
@@ -47,7 +47,7 @@ pi.on("before_agent_start", async (event, ctx) => {
|
|
|
47
47
|
|
|
48
48
|
**tool_call** — Fired before tool executes. Can block.
|
|
49
49
|
```typescript
|
|
50
|
-
import { isToolCallEventType } from "@
|
|
50
|
+
import { isToolCallEventType } from "@gsd/pi-coding-agent";
|
|
51
51
|
|
|
52
52
|
pi.on("tool_call", async (event, ctx) => {
|
|
53
53
|
if (isToolCallEventType("bash", event)) {
|
|
@@ -61,7 +61,7 @@ pi.on("tool_call", async (event, ctx) => {
|
|
|
61
61
|
|
|
62
62
|
**tool_result** — Fired after tool executes. Can modify result. Handlers chain like middleware.
|
|
63
63
|
```typescript
|
|
64
|
-
import { isToolResultEventType } from "@
|
|
64
|
+
import { isToolResultEventType } from "@gsd/pi-coding-agent";
|
|
65
65
|
|
|
66
66
|
pi.on("tool_result", async (event, ctx) => {
|
|
67
67
|
if (isToolResultEventType("bash", event)) {
|
|
@@ -105,7 +105,7 @@ pi.on("model_select", async (event, ctx) => {
|
|
|
105
105
|
Built-in type guards for tool events:
|
|
106
106
|
|
|
107
107
|
```typescript
|
|
108
|
-
import { isToolCallEventType, isToolResultEventType } from "@
|
|
108
|
+
import { isToolCallEventType, isToolResultEventType } from "@gsd/pi-coding-agent";
|
|
109
109
|
|
|
110
110
|
// Tool calls — narrows event.input type
|
|
111
111
|
if (isToolCallEventType("bash", event)) { /* event.input: { command, timeout? } */ }
|
|
@@ -39,7 +39,7 @@ If no `pi` manifest exists, auto-discovers:
|
|
|
39
39
|
</convention_directories>
|
|
40
40
|
|
|
41
41
|
<dependencies>
|
|
42
|
-
- List `@
|
|
42
|
+
- List `@gsd/pi-ai`, `@gsd/pi-coding-agent`, `@gsd/pi-tui`, `@sinclair/typebox` in `peerDependencies` with `"*"` — they're bundled by the runtime.
|
|
43
43
|
- Other npm deps go in `dependencies`. The runtime runs `npm install` on package installation.
|
|
44
44
|
</dependencies>
|
|
45
45
|
|
|
@@ -6,7 +6,7 @@ Remote execution via pluggable operations, spawnHook for bash, and tool override
|
|
|
6
6
|
Built-in tools support pluggable operations for SSH, containers, etc.:
|
|
7
7
|
|
|
8
8
|
```typescript
|
|
9
|
-
import { createReadTool, createBashTool, createWriteTool } from "@
|
|
9
|
+
import { createReadTool, createBashTool, createWriteTool } from "@gsd/pi-coding-agent";
|
|
10
10
|
|
|
11
11
|
// Create tool with custom remote operations
|
|
12
12
|
const remoteBash = createBashTool(cwd, {
|
|
@@ -37,7 +37,7 @@ const bashTool = createBashTool(cwd, {
|
|
|
37
37
|
Full SSH pattern with flag-based switching:
|
|
38
38
|
|
|
39
39
|
```typescript
|
|
40
|
-
import { createBashTool, type ExtensionAPI } from "@
|
|
40
|
+
import { createBashTool, type ExtensionAPI } from "@gsd/pi-coding-agent";
|
|
41
41
|
|
|
42
42
|
export default function (pi: ExtensionAPI) {
|
|
43
43
|
pi.registerFlag("ssh", { description: "SSH target", type: "string" });
|
|
@@ -65,7 +65,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
65
65
|
Override built-in tools for logging/access control — omit renderCall/renderResult to keep built-in rendering:
|
|
66
66
|
|
|
67
67
|
```typescript
|
|
68
|
-
import { createReadTool } from "@
|
|
68
|
+
import { createReadTool } from "@gsd/pi-coding-agent";
|
|
69
69
|
import { Type } from "@sinclair/typebox";
|
|
70
70
|
|
|
71
71
|
pi.registerTool({
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* {{CAPABILITIES_LIST}}
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { ExtensionAPI } from "@
|
|
8
|
+
import type { ExtensionAPI } from "@gsd/pi-coding-agent";
|
|
9
9
|
import { Type } from "@sinclair/typebox";
|
|
10
|
-
import { StringEnum } from "@
|
|
10
|
+
import { StringEnum } from "@gsd/pi-ai";
|
|
11
11
|
|
|
12
12
|
export default function (pi: ExtensionAPI) {
|
|
13
13
|
// === Events ===
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* State is stored in tool result details for proper branching support.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { ExtensionAPI, ExtensionContext } from "@
|
|
7
|
+
import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
|
|
8
8
|
import { Type } from "@sinclair/typebox";
|
|
9
|
-
import { StringEnum } from "@
|
|
10
|
-
import { Text, truncateToWidth, matchesKey, Key } from "@
|
|
9
|
+
import { StringEnum } from "@gsd/pi-ai";
|
|
10
|
+
import { Text, truncateToWidth, matchesKey, Key } from "@gsd/pi-tui";
|
|
11
11
|
|
|
12
12
|
interface {{ItemType}} {
|
|
13
13
|
id: number;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// GSD-2 — Extension template import path validation
|
|
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
|
+
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
7
|
+
import { join, dirname, relative } from "node:path";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
|
|
10
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const skillRoot = join(__dirname, "..");
|
|
12
|
+
|
|
13
|
+
function walk(dir: string): string[] {
|
|
14
|
+
const out: string[] = [];
|
|
15
|
+
for (const entry of readdirSync(dir)) {
|
|
16
|
+
const full = join(dir, entry);
|
|
17
|
+
if (statSync(full).isDirectory()) {
|
|
18
|
+
out.push(...walk(full));
|
|
19
|
+
} else {
|
|
20
|
+
out.push(full);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe("extension templates use @gsd/* imports", () => {
|
|
27
|
+
const templates = ["extension-skeleton.ts", "stateful-tool-skeleton.ts"];
|
|
28
|
+
|
|
29
|
+
for (const template of templates) {
|
|
30
|
+
it(`${template} uses @gsd/pi-coding-agent (not @mariozechner)`, () => {
|
|
31
|
+
const content = readFileSync(join(__dirname, template), "utf-8");
|
|
32
|
+
assert.ok(content.includes("@gsd/pi-coding-agent"), `Expected @gsd/pi-coding-agent import in ${template}`);
|
|
33
|
+
assert.ok(!content.includes("@mariozechner/"), `Found stale @mariozechner/ import in ${template}`);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
it("extension-skeleton.ts uses @gsd/pi-ai for StringEnum", () => {
|
|
38
|
+
const content = readFileSync(join(__dirname, "extension-skeleton.ts"), "utf-8");
|
|
39
|
+
assert.ok(content.includes("@gsd/pi-ai"), "Expected @gsd/pi-ai import");
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("stateful-tool-skeleton.ts uses @gsd/pi-tui", () => {
|
|
43
|
+
const content = readFileSync(join(__dirname, "stateful-tool-skeleton.ts"), "utf-8");
|
|
44
|
+
assert.ok(content.includes("@gsd/pi-tui"), "Expected @gsd/pi-tui import");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("no @mariozechner/ references anywhere in create-gsd-extension/", () => {
|
|
48
|
+
const offenders: string[] = [];
|
|
49
|
+
for (const file of walk(skillRoot)) {
|
|
50
|
+
if (file.endsWith("templates.test.ts")) continue;
|
|
51
|
+
const content = readFileSync(file, "utf-8");
|
|
52
|
+
if (content.includes("@mariozechner/")) {
|
|
53
|
+
offenders.push(relative(skillRoot, file));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
assert.deepEqual(offenders, [], `Stale @mariozechner/ references found in: ${offenders.join(", ")}`);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -34,22 +34,19 @@ Identify what the extension needs from the user's description:
|
|
|
34
34
|
|
|
35
35
|
## Step 3: Choose Extension Structure
|
|
36
36
|
|
|
37
|
-
**
|
|
38
|
-
```
|
|
39
|
-
~/.pi/agent/extensions/my-extension.ts
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
**Directory with index.ts** — for multi-file extensions:
|
|
37
|
+
**Directory with index.ts** — the standard pattern for all extensions:
|
|
43
38
|
```
|
|
44
39
|
~/.pi/agent/extensions/my-extension/
|
|
45
|
-
├──
|
|
46
|
-
├──
|
|
47
|
-
|
|
40
|
+
├── extension-manifest.json # Required — declares capabilities
|
|
41
|
+
├── index.ts # Entry point (must export default function)
|
|
42
|
+
├── tools.ts # Optional — tool implementations
|
|
43
|
+
└── utils.ts # Optional — shared utilities
|
|
48
44
|
```
|
|
49
45
|
|
|
50
46
|
**Package with dependencies** — when npm packages are needed:
|
|
51
47
|
```
|
|
52
48
|
~/.pi/agent/extensions/my-extension/
|
|
49
|
+
├── extension-manifest.json
|
|
53
50
|
├── package.json
|
|
54
51
|
├── src/index.ts
|
|
55
52
|
└── node_modules/
|
|
@@ -64,12 +61,34 @@ For packages, `package.json` needs:
|
|
|
64
61
|
}
|
|
65
62
|
```
|
|
66
63
|
|
|
64
|
+
## Step 3b: Create the Extension Manifest
|
|
65
|
+
|
|
66
|
+
Every extension must include an `extension-manifest.json`:
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"id": "my-extension",
|
|
71
|
+
"name": "My Extension",
|
|
72
|
+
"version": "1.0.0",
|
|
73
|
+
"description": "What this extension does in one line",
|
|
74
|
+
"tier": "community",
|
|
75
|
+
"requires": { "platform": ">=2.29.0" },
|
|
76
|
+
"provides": {
|
|
77
|
+
"tools": ["my_tool"],
|
|
78
|
+
"commands": ["mycommand"],
|
|
79
|
+
"hooks": ["session_start"]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Only include non-empty arrays in `provides`. See `docs/extension-sdk/manifest-spec.md` for the full spec.
|
|
85
|
+
|
|
67
86
|
## Step 4: Write the Extension
|
|
68
87
|
|
|
69
88
|
Start with the skeleton:
|
|
70
89
|
|
|
71
90
|
```typescript
|
|
72
|
-
import type { ExtensionAPI } from "@
|
|
91
|
+
import type { ExtensionAPI } from "@gsd/pi-coding-agent";
|
|
73
92
|
|
|
74
93
|
export default function (pi: ExtensionAPI) {
|
|
75
94
|
// Register events, tools, commands here
|
|
@@ -81,7 +100,7 @@ Then add capabilities based on Step 2. Reference the appropriate reference files
|
|
|
81
100
|
**Tool registration pattern:**
|
|
82
101
|
```typescript
|
|
83
102
|
import { Type } from "@sinclair/typebox";
|
|
84
|
-
import { StringEnum } from "@
|
|
103
|
+
import { StringEnum } from "@gsd/pi-ai";
|
|
85
104
|
|
|
86
105
|
pi.registerTool({
|
|
87
106
|
name: "my_tool",
|
|
@@ -144,7 +163,8 @@ Fix issues, add features, refine. Use `/reload` for hot-reload during developmen
|
|
|
144
163
|
|
|
145
164
|
<success_criteria>
|
|
146
165
|
Extension creation is complete when:
|
|
147
|
-
- [ ] Extension
|
|
166
|
+
- [ ] Extension directory created with index.ts and extension-manifest.json
|
|
167
|
+
- [ ] Manifest `provides` accurately lists all registered tools, commands, hooks, shortcuts
|
|
148
168
|
- [ ] All imports resolve (TypeBox, pi-ai, pi-coding-agent, pi-tui as needed)
|
|
149
169
|
- [ ] Tools use `StringEnum` for string enums (not `Type.Union`/`Type.Literal`)
|
|
150
170
|
- [ ] Tool output is truncated if variable-length
|