gsd-pi 2.77.0 → 2.78.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 +18 -36
- package/dist/claude-cli-check.js +5 -1
- package/dist/cli-web-branch.d.ts +1 -0
- package/dist/cli-web-branch.js +3 -0
- package/dist/cli.js +38 -2
- package/dist/extension-discovery.d.ts +6 -0
- package/dist/extension-discovery.js +37 -0
- package/dist/extension-registry.d.ts +3 -0
- package/dist/extension-sort.d.ts +18 -0
- package/dist/extension-sort.js +114 -0
- package/dist/extension-validator.d.ts +47 -0
- package/dist/extension-validator.js +127 -0
- package/dist/headless.js +49 -4
- package/dist/loader.js +35 -7
- package/dist/provider-migrations.d.ts +18 -0
- package/dist/provider-migrations.js +14 -0
- package/dist/resource-loader.d.ts +40 -0
- package/dist/resource-loader.js +32 -13
- package/dist/resources/extensions/browser-tools/capture.js +9 -0
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
- package/dist/resources/extensions/browser-tools/tools/forms.js +5 -1
- package/dist/resources/extensions/browser-tools/tools/intent.js +5 -1
- package/dist/resources/extensions/claude-code-cli/readiness.js +5 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +552 -67
- package/dist/resources/extensions/cmux/index.js +20 -0
- package/dist/resources/extensions/github-sync/templates.js +103 -0
- package/dist/resources/extensions/google-search/extension-manifest.json +5 -4
- package/dist/resources/extensions/google-search/index.js +3 -375
- package/dist/resources/extensions/gsd/abandon-detect.js +44 -0
- package/dist/resources/extensions/gsd/auto/loop.js +124 -2
- package/dist/resources/extensions/gsd/auto/phases.js +57 -39
- package/dist/resources/extensions/gsd/auto/resolve.js +24 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +10 -2
- package/dist/resources/extensions/gsd/auto/session.js +6 -2
- package/dist/resources/extensions/gsd/auto/turn-epoch.js +95 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +201 -38
- package/dist/resources/extensions/gsd/auto-loop.js +1 -1
- package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
- package/dist/resources/extensions/gsd/auto-post-unit.js +215 -64
- package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
- package/dist/resources/extensions/gsd/auto-recovery.js +210 -24
- package/dist/resources/extensions/gsd/auto-start.js +122 -30
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +11 -5
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +47 -7
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +11 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +180 -34
- package/dist/resources/extensions/gsd/auto.js +107 -35
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +19 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +209 -0
- package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +5 -6
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +11 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -3
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +11 -6
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +127 -9
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +31 -4
- package/dist/resources/extensions/gsd/commands-cmux.js +9 -6
- package/dist/resources/extensions/gsd/commands-extensions.js +634 -43
- package/dist/resources/extensions/gsd/component-loader.js +447 -0
- package/dist/resources/extensions/gsd/component-types.js +69 -0
- package/dist/resources/extensions/gsd/context-store.js +23 -7
- package/dist/resources/extensions/gsd/detection.js +49 -1
- package/dist/resources/extensions/gsd/dispatch-guard.js +29 -3
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/file-lock.js +49 -9
- package/dist/resources/extensions/gsd/forensics.js +106 -0
- package/dist/resources/extensions/gsd/gate-registry.js +2 -2
- package/dist/resources/extensions/gsd/git-constants.js +28 -1
- package/dist/resources/extensions/gsd/git-self-heal.js +27 -0
- package/dist/resources/extensions/gsd/git-service.js +127 -2
- package/dist/resources/extensions/gsd/gitignore.js +1 -0
- package/dist/resources/extensions/gsd/gsd-db.js +6 -3
- package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -1
- package/dist/resources/extensions/gsd/guided-flow.js +39 -13
- package/dist/resources/extensions/gsd/journal.js +17 -2
- package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
- package/dist/resources/extensions/gsd/milestone-actions.js +15 -0
- package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
- package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
- package/dist/resources/extensions/gsd/model-router.js +6 -0
- package/dist/resources/extensions/gsd/native-git-bridge.js +34 -4
- package/dist/resources/extensions/gsd/notifications.js +30 -16
- package/dist/resources/extensions/gsd/preferences-validation.js +23 -0
- package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
- package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
- package/dist/resources/extensions/gsd/prompts/system.md +1 -0
- package/dist/resources/extensions/gsd/reports.js +5 -4
- package/dist/resources/extensions/gsd/safety/git-checkpoint.js +11 -0
- package/dist/resources/extensions/gsd/service-tier.js +5 -2
- package/dist/resources/extensions/gsd/session-lock.js +19 -10
- package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
- package/dist/resources/extensions/gsd/slice-cadence.js +238 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
- package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
- package/dist/resources/extensions/gsd/state.js +69 -58
- package/dist/resources/extensions/gsd/sync-lock.js +98 -42
- package/dist/resources/extensions/gsd/tools/complete-slice.js +21 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +31 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
- package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +370 -0
- package/dist/resources/extensions/gsd/uok/audit.js +18 -2
- package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
- package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
- package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
- package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
- package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
- package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +10 -4
- package/dist/resources/extensions/gsd/uok/writer.js +82 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +10 -2
- package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +86 -8
- package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
- package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
- package/dist/resources/extensions/mcp-client/auth.js +10 -1
- package/dist/resources/extensions/mcp-client/index.js +121 -10
- package/dist/resources/extensions/ollama/index.js +5 -1
- package/dist/resources/extensions/remote-questions/manager.js +11 -5
- package/dist/resources/extensions/shared/cmux-events.js +12 -0
- package/dist/resources/extensions/shared/rtk-session-stats.js +1 -2
- package/dist/resources/skills/create-skill/SKILL.md +2 -2
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
- package/dist/resources/skills/create-skill/workflows/audit-skill.md +4 -4
- package/dist/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
- 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/react-loadable-manifest.json +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.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/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- 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-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/chunks/1926.js +1 -0
- package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +1 -1
- 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/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-5fc74f13a25fa1bb.js → webpack-2e68521d7c82f7c2.js} +1 -1
- package/package.json +17 -16
- package/packages/daemon/package.json +2 -2
- package/packages/daemon/src/logger.ts +4 -3
- package/packages/mcp-server/README.md +3 -3
- package/packages/mcp-server/dist/env-writer.d.ts +1 -0
- package/packages/mcp-server/dist/env-writer.d.ts.map +1 -1
- package/packages/mcp-server/dist/env-writer.js +74 -6
- package/packages/mcp-server/dist/env-writer.js.map +1 -1
- package/packages/mcp-server/dist/server.d.ts +24 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +111 -87
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +15 -6
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +7 -2
- package/packages/mcp-server/src/env-writer.test.ts +79 -1
- package/packages/mcp-server/src/env-writer.ts +76 -6
- package/packages/mcp-server/src/mcp-server.test.ts +25 -3
- package/packages/mcp-server/src/readers/graph.test.ts +87 -15
- package/packages/mcp-server/src/readers/readers.test.ts +5 -1
- package/packages/mcp-server/src/secure-env-collect.test.ts +232 -237
- package/packages/mcp-server/src/server.ts +158 -105
- package/packages/mcp-server/src/workflow-tools.test.ts +85 -0
- package/packages/mcp-server/src/workflow-tools.ts +19 -6
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +7 -2
- package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
- package/packages/native/src/__tests__/clipboard.test.mjs +69 -23
- package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
- package/packages/native/src/__tests__/ps.test.mjs +14 -8
- package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
- package/packages/native/src/__tests__/truncate.test.mjs +17 -2
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/package.json +6 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +226 -31
- package/packages/pi-agent-core/src/agent.test.ts +96 -102
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/capability-patches.js +9 -2
- package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
- package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
- package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
- package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai.js +17 -0
- package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.test.js +43 -70
- package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
- package/packages/pi-ai/dist/models.test.js +36 -11
- package/packages/pi-ai/dist/models.test.js.map +1 -1
- package/packages/pi-ai/package.json +6 -1
- package/packages/pi-ai/scripts/generate-models.ts +44 -0
- package/packages/pi-ai/src/models/capability-patches.ts +10 -2
- package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
- package/packages/pi-ai/src/models/generated/openai.ts +17 -0
- package/packages/pi-ai/src/models.generated.test.ts +46 -73
- package/packages/pi-ai/src/models.test.ts +48 -11
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js +75 -12
- package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +25 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +105 -6
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +230 -28
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts +30 -2
- package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/utils.js +113 -12
- package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +29 -18
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js +130 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.js +56 -1
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/discovery-cache.test.js +8 -15
- package/packages/pi-coding-agent/dist/core/discovery-cache.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.d.ts +25 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.js +109 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-registry.d.ts +67 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-registry.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-registry.js +167 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-registry.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +8 -2
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +85 -8
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +7 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +41 -4
- package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.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/resource-loader-cache-reset.test.js +76 -18
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +4 -1
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.test.js +19 -1
- package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -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 +19 -5
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js +2 -1
- package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -0
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js +15 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +20 -13
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts +7 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +31 -9
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +30 -12
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +18 -3
- 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 +139 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +105 -13
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +6 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
- package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
- package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
- package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +368 -28
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +122 -6
- package/packages/pi-coding-agent/src/core/compaction/utils.ts +111 -13
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.test.ts +154 -0
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +32 -18
- package/packages/pi-coding-agent/src/core/compaction-utils.test.ts +68 -1
- package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +9 -18
- package/packages/pi-coding-agent/src/core/extensions/extension-discovery.ts +119 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-registry.ts +222 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +82 -11
- package/packages/pi-coding-agent/src/core/extensions/types.ts +8 -0
- package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +48 -4
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +22 -2
- package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
- package/packages/pi-coding-agent/src/core/resource-loader.ts +1 -1
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
- package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
- package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
- package/packages/pi-coding-agent/src/core/sdk.test.ts +25 -1
- package/packages/pi-coding-agent/src/core/sdk.ts +10 -3
- package/packages/pi-coding-agent/src/core/system-prompt.ts +38 -4
- package/packages/pi-coding-agent/src/core/tools/path-utils.test.ts +2 -1
- package/packages/pi-coding-agent/src/index.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/provider-display-name.test.ts +17 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +49 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +14 -5
- package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +45 -11
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +160 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +20 -3
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +2 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +119 -13
- package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +31 -14
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +51 -6
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
- package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
- package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
- package/packages/pi-tui/dist/components/editor.d.ts +14 -0
- package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/editor.js +19 -0
- package/packages/pi-tui/dist/components/editor.js.map +1 -1
- package/packages/pi-tui/dist/components/image.test.js +6 -5
- package/packages/pi-tui/dist/components/image.test.js.map +1 -1
- package/packages/pi-tui/dist/editor-component.d.ts +2 -0
- package/packages/pi-tui/dist/editor-component.d.ts.map +1 -1
- package/packages/pi-tui/dist/editor-component.js.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.d.ts +7 -0
- package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.js +20 -0
- package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
- package/packages/pi-tui/package.json +6 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +46 -15
- package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
- package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +62 -6
- package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
- package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
- package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
- package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
- package/packages/pi-tui/src/components/editor.ts +22 -0
- package/packages/pi-tui/src/components/image.test.ts +10 -5
- package/packages/pi-tui/src/editor-component.ts +3 -0
- package/packages/pi-tui/src/stdin-buffer.ts +26 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/dist/rpc-client.test.js +101 -51
- package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
- package/packages/rpc-client/package.json +6 -1
- package/packages/rpc-client/src/rpc-client.test.ts +109 -52
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/pkg/package.json +1 -1
- package/scripts/install.js +526 -0
- package/scripts/lib/workspace-manifest.cjs +86 -0
- package/scripts/link-workspace-packages.cjs +5 -17
- package/scripts/postinstall.js +9 -178
- package/src/resources/extensions/browser-tools/capture.ts +12 -0
- package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
- package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
- package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
- package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
- package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +5 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +602 -73
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +1028 -91
- package/src/resources/extensions/cmux/index.ts +35 -10
- package/src/resources/extensions/github-sync/templates.ts +151 -0
- package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
- package/src/resources/extensions/github-sync/tests/templates.test.ts +92 -1
- package/src/resources/extensions/google-search/extension-manifest.json +5 -4
- package/src/resources/extensions/google-search/index.ts +9 -470
- package/src/resources/extensions/gsd/abandon-detect.ts +62 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -1
- package/src/resources/extensions/gsd/auto/loop.ts +142 -2
- package/src/resources/extensions/gsd/auto/phases.ts +62 -38
- package/src/resources/extensions/gsd/auto/resolve.ts +29 -0
- package/src/resources/extensions/gsd/auto/run-unit.ts +16 -2
- package/src/resources/extensions/gsd/auto/session.ts +7 -2
- package/src/resources/extensions/gsd/auto/turn-epoch.ts +108 -0
- package/src/resources/extensions/gsd/auto/types.ts +1 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +214 -37
- package/src/resources/extensions/gsd/auto-loop.ts +1 -1
- package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
- package/src/resources/extensions/gsd/auto-post-unit.ts +226 -73
- package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
- package/src/resources/extensions/gsd/auto-recovery.ts +240 -25
- package/src/resources/extensions/gsd/auto-start.ts +146 -14
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -5
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +51 -7
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +14 -3
- package/src/resources/extensions/gsd/auto-worktree.ts +190 -31
- package/src/resources/extensions/gsd/auto.ts +127 -41
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +20 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +221 -0
- package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +6 -6
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +11 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -3
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +13 -9
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +158 -9
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +27 -8
- package/src/resources/extensions/gsd/commands-cmux.ts +10 -6
- package/src/resources/extensions/gsd/commands-extensions.ts +747 -41
- package/src/resources/extensions/gsd/component-loader.ts +598 -0
- package/src/resources/extensions/gsd/component-types.ts +362 -0
- package/src/resources/extensions/gsd/context-store.ts +25 -8
- package/src/resources/extensions/gsd/detection.ts +58 -1
- package/src/resources/extensions/gsd/dispatch-guard.ts +26 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/file-lock.ts +84 -11
- package/src/resources/extensions/gsd/forensics.ts +118 -1
- package/src/resources/extensions/gsd/gate-registry.ts +2 -2
- package/src/resources/extensions/gsd/git-constants.ts +30 -1
- package/src/resources/extensions/gsd/git-self-heal.ts +31 -0
- package/src/resources/extensions/gsd/git-service.ts +150 -2
- package/src/resources/extensions/gsd/gitignore.ts +1 -0
- package/src/resources/extensions/gsd/gsd-db.ts +6 -3
- package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -1
- package/src/resources/extensions/gsd/guided-flow.ts +57 -14
- package/src/resources/extensions/gsd/journal.ts +38 -3
- package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
- package/src/resources/extensions/gsd/milestone-actions.ts +18 -0
- package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
- package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
- package/src/resources/extensions/gsd/model-router.ts +6 -0
- package/src/resources/extensions/gsd/native-git-bridge.ts +34 -4
- package/src/resources/extensions/gsd/notifications.ts +27 -15
- package/src/resources/extensions/gsd/preferences-validation.ts +21 -0
- package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
- package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
- package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
- package/src/resources/extensions/gsd/prompts/system.md +1 -0
- package/src/resources/extensions/gsd/reports.ts +5 -4
- package/src/resources/extensions/gsd/safety/git-checkpoint.ts +15 -0
- package/src/resources/extensions/gsd/service-tier.ts +5 -2
- package/src/resources/extensions/gsd/session-lock.ts +20 -10
- package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
- package/src/resources/extensions/gsd/slice-cadence.ts +299 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
- package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
- package/src/resources/extensions/gsd/state.ts +76 -66
- package/src/resources/extensions/gsd/sync-lock.ts +97 -39
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +270 -0
- package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +341 -0
- package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +264 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +135 -285
- package/src/resources/extensions/gsd/tests/auto-mode-guards.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +61 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +166 -0
- package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
- package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/cmux.test.ts +5 -9
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +16 -8
- package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
- package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/context-store.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +91 -3
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +14 -9
- package/src/resources/extensions/gsd/tests/dispatch-guard-summary-db-mismatch.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
- package/src/resources/extensions/gsd/tests/file-lock.test.ts +86 -12
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
- package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/gate-storage.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +131 -0
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
- package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -56
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +144 -7
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -16
- package/src/resources/extensions/gsd/tests/integration/worktree-e2e.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
- package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -55
- package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
- package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
- package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -48
- package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
- package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
- package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +54 -41
- package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +213 -0
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +13 -7
- package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +75 -2
- package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
- package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
- package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +170 -0
- package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/rewrite-docs-abandon-detect.test.ts +195 -0
- package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
- package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
- package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
- package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
- package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
- package/src/resources/extensions/gsd/tests/sync-lock.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +61 -1
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +50 -2
- package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +162 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +258 -0
- package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
- package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +19 -2
- package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/validate-extension-package.test.ts +168 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +139 -5
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
- package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +25 -2
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
- package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
- package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +210 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +262 -0
- package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +7 -5
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
- package/src/resources/extensions/gsd/tools/complete-slice.ts +38 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +49 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +8 -2
- package/src/resources/extensions/gsd/types.ts +3 -3
- package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +574 -0
- package/src/resources/extensions/gsd/uok/audit.ts +20 -2
- package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
- package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
- package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
- package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
- package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
- package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
- package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +13 -5
- package/src/resources/extensions/gsd/uok/writer.ts +113 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +22 -3
- package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +109 -7
- package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
- package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
- package/src/resources/extensions/mcp-client/auth.ts +12 -1
- package/src/resources/extensions/mcp-client/index.ts +132 -11
- package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
- package/src/resources/extensions/ollama/index.ts +5 -1
- package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
- package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
- package/src/resources/extensions/remote-questions/manager.ts +36 -4
- package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
- package/src/resources/extensions/shared/cmux-events.ts +59 -0
- package/src/resources/extensions/shared/rtk-session-stats.ts +1 -2
- package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
- package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
- package/src/resources/skills/create-skill/SKILL.md +2 -2
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
- package/src/resources/skills/create-skill/workflows/audit-skill.md +4 -4
- package/src/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
- package/dist/web/standalone/.next/server/chunks/7461.js +0 -1
- package/dist/web/standalone/.next/static/chunks/2826.e59e8578e2e28639.js +0 -9
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
- package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -143
- package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -142
- package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
- package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
- package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
- package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
- package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -74
- package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
- package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
- package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -125
- package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
- /package/dist/web/standalone/.next/static/{pV-mPo7rYGb5JBC09C8GG → C1zT2kEfoLhDdbWPWKrXd}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{pV-mPo7rYGb5JBC09C8GG → C1zT2kEfoLhDdbWPWKrXd}/_ssgManifest.js +0 -0
|
@@ -8,6 +8,12 @@ import { ModelDiscoveryCache } from "./discovery-cache.js";
|
|
|
8
8
|
let testDir: string;
|
|
9
9
|
let cachePath: string;
|
|
10
10
|
|
|
11
|
+
function markEntryStale(cache: ModelDiscoveryCache, provider: string): void {
|
|
12
|
+
const entry = cache.get(provider);
|
|
13
|
+
assert.ok(entry, `expected cache entry for ${provider}`);
|
|
14
|
+
entry.fetchedAt = Date.now() - entry.ttlMs - 1;
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
beforeEach(() => {
|
|
12
18
|
testDir = join(tmpdir(), `discovery-cache-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
13
19
|
mkdirSync(testDir, { recursive: true });
|
|
@@ -92,12 +98,7 @@ describe("ModelDiscoveryCache — staleness", () => {
|
|
|
92
98
|
it("entries with expired TTL are stale", () => {
|
|
93
99
|
const cache = new ModelDiscoveryCache(cachePath);
|
|
94
100
|
cache.set("openai", [{ id: "gpt-4o" }], 1); // 1ms TTL
|
|
95
|
-
|
|
96
|
-
// Wait for TTL to expire
|
|
97
|
-
const start = Date.now();
|
|
98
|
-
while (Date.now() - start < 5) {
|
|
99
|
-
// busy wait
|
|
100
|
-
}
|
|
101
|
+
markEntryStale(cache, "openai");
|
|
101
102
|
|
|
102
103
|
assert.equal(cache.isStale("openai"), true);
|
|
103
104
|
});
|
|
@@ -110,12 +111,7 @@ describe("ModelDiscoveryCache — getAll", () => {
|
|
|
110
111
|
const cache = new ModelDiscoveryCache(cachePath);
|
|
111
112
|
cache.set("openai", [{ id: "gpt-4o" }]);
|
|
112
113
|
cache.set("stale", [{ id: "old" }], 1);
|
|
113
|
-
|
|
114
|
-
// Wait for stale TTL
|
|
115
|
-
const start = Date.now();
|
|
116
|
-
while (Date.now() - start < 5) {
|
|
117
|
-
// busy wait
|
|
118
|
-
}
|
|
114
|
+
markEntryStale(cache, "stale");
|
|
119
115
|
|
|
120
116
|
const all = cache.getAll();
|
|
121
117
|
assert.ok(all.has("openai"));
|
|
@@ -126,12 +122,7 @@ describe("ModelDiscoveryCache — getAll", () => {
|
|
|
126
122
|
const cache = new ModelDiscoveryCache(cachePath);
|
|
127
123
|
cache.set("openai", [{ id: "gpt-4o" }]);
|
|
128
124
|
cache.set("stale", [{ id: "old" }], 1);
|
|
129
|
-
|
|
130
|
-
// Wait for stale TTL
|
|
131
|
-
const start = Date.now();
|
|
132
|
-
while (Date.now() - start < 5) {
|
|
133
|
-
// busy wait
|
|
134
|
-
}
|
|
125
|
+
markEntryStale(cache, "stale");
|
|
135
126
|
|
|
136
127
|
const all = cache.getAll(true);
|
|
137
128
|
assert.ok(all.has("openai"));
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs'
|
|
2
|
+
import { join, resolve } from 'node:path'
|
|
3
|
+
import { readManifest, readManifestFromEntryPath } from './extension-registry.js'
|
|
4
|
+
|
|
5
|
+
function isExtensionFile(name: string): boolean {
|
|
6
|
+
return name.endsWith('.ts') || name.endsWith('.js')
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Resolves the entry-point file(s) for a single extension directory.
|
|
11
|
+
*
|
|
12
|
+
* 1. If the directory contains a package.json with a `pi` manifest object,
|
|
13
|
+
* the manifest is authoritative:
|
|
14
|
+
* - `pi.extensions` array → resolve each entry relative to the directory.
|
|
15
|
+
* - `pi: {}` (no extensions) → return empty (library opt-out, e.g. cmux).
|
|
16
|
+
* 2. Only when no `pi` manifest exists does it fall back to `index.ts` → `index.js`.
|
|
17
|
+
*/
|
|
18
|
+
export function resolveExtensionEntries(dir: string): string[] {
|
|
19
|
+
const packageJsonPath = join(dir, 'package.json')
|
|
20
|
+
if (existsSync(packageJsonPath)) {
|
|
21
|
+
try {
|
|
22
|
+
const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8'))
|
|
23
|
+
if (pkg?.pi && typeof pkg.pi === 'object') {
|
|
24
|
+
// When a pi manifest exists, it is authoritative — don't fall through
|
|
25
|
+
// to index.ts/index.js auto-detection. This allows library directories
|
|
26
|
+
// (like cmux) to opt out by declaring "pi": {} with no extensions.
|
|
27
|
+
const declared = pkg.pi.extensions
|
|
28
|
+
if (!Array.isArray(declared) || declared.length === 0) {
|
|
29
|
+
return []
|
|
30
|
+
}
|
|
31
|
+
return declared
|
|
32
|
+
.filter((entry: unknown): entry is string => typeof entry === 'string')
|
|
33
|
+
.map((entry: string) => resolve(dir, entry))
|
|
34
|
+
.filter((entry: string) => existsSync(entry))
|
|
35
|
+
}
|
|
36
|
+
} catch {
|
|
37
|
+
// Ignore malformed manifests and fall back to index.ts/index.js discovery.
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const indexTs = join(dir, 'index.ts')
|
|
42
|
+
if (existsSync(indexTs)) {
|
|
43
|
+
return [indexTs]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const indexJs = join(dir, 'index.js')
|
|
47
|
+
if (existsSync(indexJs)) {
|
|
48
|
+
return [indexJs]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return []
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Discovers all extension entry-point paths under an extensions directory.
|
|
56
|
+
*
|
|
57
|
+
* - Top-level .ts/.js files are treated as standalone extension entry points.
|
|
58
|
+
* - Subdirectories are resolved via `resolveExtensionEntries()` (package.json →
|
|
59
|
+
* pi.extensions, then index.ts/index.js fallback).
|
|
60
|
+
*/
|
|
61
|
+
export function discoverExtensionEntryPaths(extensionsDir: string): string[] {
|
|
62
|
+
if (!existsSync(extensionsDir)) {
|
|
63
|
+
return []
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const discovered: string[] = []
|
|
67
|
+
for (const entry of readdirSync(extensionsDir, { withFileTypes: true })) {
|
|
68
|
+
const entryPath = join(extensionsDir, entry.name)
|
|
69
|
+
|
|
70
|
+
if ((entry.isFile() || entry.isSymbolicLink()) && isExtensionFile(entry.name)) {
|
|
71
|
+
discovered.push(entryPath)
|
|
72
|
+
continue
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
76
|
+
discovered.push(...resolveExtensionEntries(entryPath))
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return discovered
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Merge bundled and installed extension entry paths.
|
|
85
|
+
* Installed extensions with the same manifest ID as a bundled extension take precedence (D-14).
|
|
86
|
+
* Loader stays dumb — receives a pre-merged path list (D-15).
|
|
87
|
+
*/
|
|
88
|
+
export function mergeExtensionEntryPaths(bundledPaths: string[], installedExtDir: string): string[] {
|
|
89
|
+
if (!existsSync(installedExtDir)) return bundledPaths
|
|
90
|
+
|
|
91
|
+
// Build map: manifest ID → entry paths for installed extensions
|
|
92
|
+
const installedById = new Map<string, string[]>()
|
|
93
|
+
for (const entry of readdirSync(installedExtDir, { withFileTypes: true })) {
|
|
94
|
+
if (!entry.isDirectory()) continue
|
|
95
|
+
const dir = join(installedExtDir, entry.name)
|
|
96
|
+
const manifest = readManifest(dir)
|
|
97
|
+
const entries = resolveExtensionEntries(dir)
|
|
98
|
+
if (manifest && entries.length > 0) {
|
|
99
|
+
installedById.set(manifest.id, entries)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (installedById.size === 0) return bundledPaths
|
|
104
|
+
|
|
105
|
+
// Filter bundled paths: skip any whose manifest id is shadowed by installed
|
|
106
|
+
const merged: string[] = []
|
|
107
|
+
for (const entryPath of bundledPaths) {
|
|
108
|
+
const manifest = readManifestFromEntryPath(entryPath)
|
|
109
|
+
if (manifest && installedById.has(manifest.id)) continue // shadowed by installed
|
|
110
|
+
merged.push(entryPath)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Append all installed entries
|
|
114
|
+
for (const entries of installedById.values()) {
|
|
115
|
+
merged.push(...entries)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return merged
|
|
119
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extension Registry — manages manifest reading, registry persistence, and enable/disable state.
|
|
3
|
+
*
|
|
4
|
+
* Extensions without manifests always load (backwards compatible).
|
|
5
|
+
* A fresh install has an empty registry — all extensions enabled by default.
|
|
6
|
+
* The only way an extension stops loading is an explicit `gsd extensions disable <id>`.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { getAgentDir } from "../../config.js";
|
|
11
|
+
import { dirname, join } from "node:path";
|
|
12
|
+
|
|
13
|
+
// ─── Types ──────────────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
export interface ExtensionManifest {
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
version: string;
|
|
19
|
+
description: string;
|
|
20
|
+
tier: "core" | "bundled" | "community";
|
|
21
|
+
requires: { platform: string };
|
|
22
|
+
provides?: {
|
|
23
|
+
tools?: string[];
|
|
24
|
+
commands?: string[];
|
|
25
|
+
hooks?: string[];
|
|
26
|
+
shortcuts?: string[];
|
|
27
|
+
};
|
|
28
|
+
dependencies?: {
|
|
29
|
+
extensions?: string[];
|
|
30
|
+
runtime?: string[];
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ExtensionRegistryEntry {
|
|
35
|
+
id: string;
|
|
36
|
+
enabled: boolean;
|
|
37
|
+
source: "bundled" | "user" | "project";
|
|
38
|
+
disabledAt?: string;
|
|
39
|
+
disabledReason?: string;
|
|
40
|
+
version?: string; // From manifest, used for semver comparison
|
|
41
|
+
installedFrom?: string; // Original specifier: npm package name, git URL, or local path
|
|
42
|
+
installType?: "npm" | "git" | "local"; // Explicit source type
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface ExtensionRegistry {
|
|
46
|
+
version: 1;
|
|
47
|
+
entries: Record<string, ExtensionRegistryEntry>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ─── Validation ─────────────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
function isRegistry(data: unknown): data is ExtensionRegistry {
|
|
53
|
+
if (typeof data !== "object" || data === null) return false;
|
|
54
|
+
const obj = data as Record<string, unknown>;
|
|
55
|
+
return obj.version === 1 && typeof obj.entries === "object" && obj.entries !== null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function isManifest(data: unknown): data is ExtensionManifest {
|
|
59
|
+
if (typeof data !== "object" || data === null) return false;
|
|
60
|
+
const obj = data as Record<string, unknown>;
|
|
61
|
+
return (
|
|
62
|
+
typeof obj.id === "string" &&
|
|
63
|
+
typeof obj.name === "string" &&
|
|
64
|
+
typeof obj.version === "string" &&
|
|
65
|
+
typeof obj.tier === "string"
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ─── Registry Path ──────────────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
export function getRegistryPath(): string {
|
|
72
|
+
return join(dirname(getAgentDir()), "extensions", "registry.json");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ─── Registry I/O ───────────────────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
function defaultRegistry(): ExtensionRegistry {
|
|
78
|
+
return { version: 1, entries: {} };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function loadRegistry(): ExtensionRegistry {
|
|
82
|
+
const filePath = getRegistryPath();
|
|
83
|
+
try {
|
|
84
|
+
if (!existsSync(filePath)) return defaultRegistry();
|
|
85
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
86
|
+
const parsed = JSON.parse(raw);
|
|
87
|
+
return isRegistry(parsed) ? parsed : defaultRegistry();
|
|
88
|
+
} catch {
|
|
89
|
+
return defaultRegistry();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function saveRegistry(registry: ExtensionRegistry): void {
|
|
94
|
+
const filePath = getRegistryPath();
|
|
95
|
+
try {
|
|
96
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
97
|
+
const tmp = filePath + ".tmp";
|
|
98
|
+
writeFileSync(tmp, JSON.stringify(registry, null, 2), "utf-8");
|
|
99
|
+
renameSync(tmp, filePath);
|
|
100
|
+
} catch {
|
|
101
|
+
// Non-fatal — don't let persistence failures break operation
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ─── Query ──────────────────────────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
/** Returns true if the extension is enabled (missing entries default to enabled). */
|
|
108
|
+
export function isExtensionEnabled(registry: ExtensionRegistry, id: string): boolean {
|
|
109
|
+
const entry = registry.entries[id];
|
|
110
|
+
if (!entry) return true;
|
|
111
|
+
return entry.enabled;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ─── Mutations ──────────────────────────────────────────────────────────────
|
|
115
|
+
|
|
116
|
+
export function enableExtension(registry: ExtensionRegistry, id: string): void {
|
|
117
|
+
const entry = registry.entries[id];
|
|
118
|
+
if (entry) {
|
|
119
|
+
entry.enabled = true;
|
|
120
|
+
delete entry.disabledAt;
|
|
121
|
+
delete entry.disabledReason;
|
|
122
|
+
} else {
|
|
123
|
+
registry.entries[id] = { id, enabled: true, source: "bundled" };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Disable an extension. Returns an error string if the extension is core (cannot disable),
|
|
129
|
+
* or null on success.
|
|
130
|
+
*/
|
|
131
|
+
export function disableExtension(
|
|
132
|
+
registry: ExtensionRegistry,
|
|
133
|
+
id: string,
|
|
134
|
+
manifest: ExtensionManifest | null,
|
|
135
|
+
reason?: string,
|
|
136
|
+
): string | null {
|
|
137
|
+
if (manifest?.tier === "core") {
|
|
138
|
+
return `Cannot disable "${id}" — it is a core extension.`;
|
|
139
|
+
}
|
|
140
|
+
const entry = registry.entries[id];
|
|
141
|
+
if (entry) {
|
|
142
|
+
entry.enabled = false;
|
|
143
|
+
entry.disabledAt = new Date().toISOString();
|
|
144
|
+
entry.disabledReason = reason;
|
|
145
|
+
} else {
|
|
146
|
+
registry.entries[id] = {
|
|
147
|
+
id,
|
|
148
|
+
enabled: false,
|
|
149
|
+
source: "bundled",
|
|
150
|
+
disabledAt: new Date().toISOString(),
|
|
151
|
+
disabledReason: reason,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ─── Manifest Reading ───────────────────────────────────────────────────────
|
|
158
|
+
|
|
159
|
+
/** Read extension-manifest.json from a directory. Returns null if missing or invalid. */
|
|
160
|
+
export function readManifest(extensionDir: string): ExtensionManifest | null {
|
|
161
|
+
const manifestPath = join(extensionDir, "extension-manifest.json");
|
|
162
|
+
if (!existsSync(manifestPath)) return null;
|
|
163
|
+
try {
|
|
164
|
+
const raw = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
165
|
+
return isManifest(raw) ? raw : null;
|
|
166
|
+
} catch {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Given an entry path (e.g. `.../extensions/browser-tools/index.ts`),
|
|
173
|
+
* resolve the parent directory and read its manifest.
|
|
174
|
+
*/
|
|
175
|
+
export function readManifestFromEntryPath(entryPath: string): ExtensionManifest | null {
|
|
176
|
+
const dir = dirname(entryPath);
|
|
177
|
+
return readManifest(dir);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// ─── Discovery ──────────────────────────────────────────────────────────────
|
|
181
|
+
|
|
182
|
+
/** Scan all subdirectories of extensionsDir for manifests. Returns a Map<id, manifest>. */
|
|
183
|
+
export function discoverAllManifests(extensionsDir: string): Map<string, ExtensionManifest> {
|
|
184
|
+
const manifests = new Map<string, ExtensionManifest>();
|
|
185
|
+
if (!existsSync(extensionsDir)) return manifests;
|
|
186
|
+
|
|
187
|
+
for (const entry of readdirSync(extensionsDir, { withFileTypes: true })) {
|
|
188
|
+
if (!entry.isDirectory()) continue;
|
|
189
|
+
const manifest = readManifest(join(extensionsDir, entry.name));
|
|
190
|
+
if (manifest) {
|
|
191
|
+
manifests.set(manifest.id, manifest);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return manifests;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Auto-populate registry entries for newly discovered extensions.
|
|
199
|
+
* Extensions already in the registry are left untouched.
|
|
200
|
+
*/
|
|
201
|
+
export function ensureRegistryEntries(extensionsDir: string): void {
|
|
202
|
+
const manifests = discoverAllManifests(extensionsDir);
|
|
203
|
+
if (manifests.size === 0) return;
|
|
204
|
+
|
|
205
|
+
const registry = loadRegistry();
|
|
206
|
+
let changed = false;
|
|
207
|
+
|
|
208
|
+
for (const [id, manifest] of manifests) {
|
|
209
|
+
if (!registry.entries[id]) {
|
|
210
|
+
registry.entries[id] = {
|
|
211
|
+
id,
|
|
212
|
+
enabled: true,
|
|
213
|
+
source: "bundled",
|
|
214
|
+
};
|
|
215
|
+
changed = true;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (changed) {
|
|
220
|
+
saveRegistry(registry);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
@@ -39,6 +39,8 @@ import { execCommand } from "../exec.js";
|
|
|
39
39
|
import { getUntrustedExtensionPaths } from "./project-trust.js";
|
|
40
40
|
export { isProjectTrusted, trustProject, getUntrustedExtensionPaths } from "./project-trust.js";
|
|
41
41
|
import { registerToolCompatibility } from "../tools/tool-compatibility-registry.js";
|
|
42
|
+
import { mergeExtensionEntryPaths } from "./extension-discovery.js";
|
|
43
|
+
import { sortExtensionPaths } from "./extension-sort.js";
|
|
42
44
|
import type {
|
|
43
45
|
Extension,
|
|
44
46
|
ExtensionAPI,
|
|
@@ -651,15 +653,72 @@ export function containsTypeScriptSyntax(source: string): boolean {
|
|
|
651
653
|
* are compiled once and reused across all extensions.
|
|
652
654
|
*/
|
|
653
655
|
let _extensionLoaderJiti: ReturnType<typeof createJiti> | null = null;
|
|
656
|
+
// Tracks every extension-module path that jiti has compiled through the shared
|
|
657
|
+
// singleton so resetExtensionLoaderCache() can also evict Node's global
|
|
658
|
+
// require.cache entries for those modules. jiti stores compiled modules under
|
|
659
|
+
// `nativeRequire.cache[filename]` when `moduleCache: true`, so a new singleton
|
|
660
|
+
// still returns the stale cached module on re-import without this eviction.
|
|
661
|
+
const _loadedExtensionPaths = new Set<string>();
|
|
662
|
+
const _extensionRequire = createRequire(import.meta.url);
|
|
654
663
|
|
|
655
664
|
/**
|
|
656
665
|
* Reset the shared jiti singleton so the next call to getExtensionLoaderJiti()
|
|
657
666
|
* creates a fresh instance. This prevents memory leaks in long-running daemon
|
|
658
667
|
* processes (every loaded module stays cached forever) and ensures stale modules
|
|
659
668
|
* are not returned when extension source changes on disk.
|
|
669
|
+
*
|
|
670
|
+
* #3616: resetting the singleton alone is insufficient — jiti stores compiled
|
|
671
|
+
* modules in Node's global require.cache when `moduleCache: true`, which is
|
|
672
|
+
* shared across singletons. We also evict cached entries for every extension
|
|
673
|
+
* path we've previously loaded so the next import recompiles from disk.
|
|
660
674
|
*/
|
|
661
675
|
export function resetExtensionLoaderCache(): void {
|
|
662
676
|
_extensionLoaderJiti = null;
|
|
677
|
+
// Build a set of exact cache keys we expect (raw path, resolved path,
|
|
678
|
+
// realpath) AND a set of (basename, containing-directory) pairs so we
|
|
679
|
+
// can also catch entries that jiti/Node wrote under a canonicalized
|
|
680
|
+
// form (Windows drive-letter case, separator swap, UNC prefix, symlink
|
|
681
|
+
// resolution). require.cache is shared across all createRequire
|
|
682
|
+
// instances for CJS, so iterating any instance's cache covers jiti's
|
|
683
|
+
// internal `nativeRequire.cache` writes.
|
|
684
|
+
const exact = new Set<string>();
|
|
685
|
+
const signatures = new Set<string>();
|
|
686
|
+
const makeSignature = (p: string): string => {
|
|
687
|
+
const normalized = p.replace(/\\/g, "/").toLowerCase();
|
|
688
|
+
const slash = normalized.lastIndexOf("/");
|
|
689
|
+
const base = slash >= 0 ? normalized.slice(slash + 1) : normalized;
|
|
690
|
+
// Use the trailing two path segments as the signature — unique
|
|
691
|
+
// enough to avoid collisions in typical filesystems while tolerating
|
|
692
|
+
// drive-letter / separator variations that differ in the prefix.
|
|
693
|
+
const parent = slash >= 0 ? normalized.slice(0, slash) : "";
|
|
694
|
+
const parentSlash = parent.lastIndexOf("/");
|
|
695
|
+
const parentSeg = parentSlash >= 0 ? parent.slice(parentSlash + 1) : parent;
|
|
696
|
+
return `${parentSeg}/${base}`;
|
|
697
|
+
};
|
|
698
|
+
for (const raw of _loadedExtensionPaths) {
|
|
699
|
+
exact.add(raw);
|
|
700
|
+
try {
|
|
701
|
+
exact.add(_extensionRequire.resolve(raw));
|
|
702
|
+
} catch {
|
|
703
|
+
// unresolvable — fall through; signature scan may still hit it
|
|
704
|
+
}
|
|
705
|
+
try {
|
|
706
|
+
exact.add(fs.realpathSync(raw));
|
|
707
|
+
} catch {
|
|
708
|
+
// file may have been deleted already; ignore
|
|
709
|
+
}
|
|
710
|
+
signatures.add(makeSignature(raw));
|
|
711
|
+
}
|
|
712
|
+
for (const key of Object.keys(_extensionRequire.cache)) {
|
|
713
|
+
if (exact.has(key) || signatures.has(makeSignature(key))) {
|
|
714
|
+
try {
|
|
715
|
+
delete _extensionRequire.cache[key];
|
|
716
|
+
} catch {
|
|
717
|
+
// require.cache is best-effort; ignore failures (e.g. frozen cache).
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
_loadedExtensionPaths.clear();
|
|
663
722
|
}
|
|
664
723
|
|
|
665
724
|
function getExtensionLoaderJiti() {
|
|
@@ -694,6 +753,7 @@ async function loadExtensionModule(extensionPath: string) {
|
|
|
694
753
|
const jiti = getExtensionLoaderJiti();
|
|
695
754
|
|
|
696
755
|
const module = await jiti.import(extensionPath, { default: true });
|
|
756
|
+
_loadedExtensionPaths.add(extensionPath);
|
|
697
757
|
const factory = module as ExtensionFactory;
|
|
698
758
|
return typeof factory !== "function" ? undefined : factory;
|
|
699
759
|
}
|
|
@@ -847,24 +907,21 @@ export async function loadExtensionFromFactory(
|
|
|
847
907
|
/**
|
|
848
908
|
* Load extensions from paths.
|
|
849
909
|
*
|
|
850
|
-
*
|
|
851
|
-
*
|
|
910
|
+
* Paths are expected to be topologically sorted by caller (see sortExtensionPaths).
|
|
911
|
+
* Factories are awaited sequentially so a dependency's factory fully initializes
|
|
912
|
+
* (registers tools, commands, hooks on `pi`) before any dependent's factory runs.
|
|
852
913
|
*/
|
|
853
914
|
export async function loadExtensions(paths: string[], cwd: string, eventBus?: EventBus): Promise<LoadExtensionsResult> {
|
|
854
915
|
const resolvedEventBus = eventBus ?? createEventBus();
|
|
855
916
|
const runtime = createExtensionRuntime();
|
|
856
917
|
|
|
857
|
-
const results = await Promise.all(
|
|
858
|
-
paths.map((extPath) => loadExtension(extPath, cwd, resolvedEventBus, runtime)),
|
|
859
|
-
);
|
|
860
|
-
|
|
861
918
|
const extensions: Extension[] = [];
|
|
862
919
|
const errors: Array<{ path: string; error: string }> = [];
|
|
863
920
|
|
|
864
|
-
for (
|
|
865
|
-
const { extension, error } =
|
|
921
|
+
for (const extPath of paths) {
|
|
922
|
+
const { extension, error } = await loadExtension(extPath, cwd, resolvedEventBus, runtime);
|
|
866
923
|
if (error) {
|
|
867
|
-
errors.push({ path:
|
|
924
|
+
errors.push({ path: extPath, error });
|
|
868
925
|
} else if (extension) {
|
|
869
926
|
extensions.push(extension);
|
|
870
927
|
}
|
|
@@ -873,6 +930,7 @@ export async function loadExtensions(paths: string[], cwd: string, eventBus?: Ev
|
|
|
873
930
|
return {
|
|
874
931
|
extensions,
|
|
875
932
|
errors,
|
|
933
|
+
warnings: [],
|
|
876
934
|
runtime,
|
|
877
935
|
};
|
|
878
936
|
}
|
|
@@ -1034,7 +1092,12 @@ export async function discoverAndLoadExtensions(
|
|
|
1034
1092
|
|
|
1035
1093
|
// 2. Global extensions: agentDir/extensions/
|
|
1036
1094
|
const globalExtDir = path.join(agentDir, "extensions");
|
|
1037
|
-
|
|
1095
|
+
// 2b. Installed extensions: ~/.gsd/extensions/ merged with bundled (D-14, D-15)
|
|
1096
|
+
// Discovery handles ID-based merge — loader stays dumb.
|
|
1097
|
+
const installedExtDir = path.join(path.dirname(agentDir), "extensions");
|
|
1098
|
+
const globalPaths = discoverExtensionsInDir(globalExtDir);
|
|
1099
|
+
const mergedPaths = mergeExtensionEntryPaths(globalPaths, installedExtDir);
|
|
1100
|
+
addPaths(mergedPaths);
|
|
1038
1101
|
|
|
1039
1102
|
// 3. Explicitly configured paths
|
|
1040
1103
|
for (const p of configuredPaths) {
|
|
@@ -1054,5 +1117,13 @@ export async function discoverAndLoadExtensions(
|
|
|
1054
1117
|
addPaths([resolved]);
|
|
1055
1118
|
}
|
|
1056
1119
|
|
|
1057
|
-
|
|
1120
|
+
// Topological sort: ensure declared dependencies load first (D-06, D-07)
|
|
1121
|
+
const { sortedPaths, warnings: sortWarnings } = sortExtensionPaths(allPaths)
|
|
1122
|
+
// Emit warnings to stderr immediately — loader runs before ctx.ui is ready (D-08)
|
|
1123
|
+
for (const w of sortWarnings) {
|
|
1124
|
+
process.stderr.write(`[gsd] ${w.message}\n`)
|
|
1125
|
+
}
|
|
1126
|
+
const result = await loadExtensions(sortedPaths, cwd, eventBus)
|
|
1127
|
+
result.warnings.push(...sortWarnings)
|
|
1128
|
+
return result
|
|
1058
1129
|
}
|
|
@@ -1783,10 +1783,18 @@ export interface Extension {
|
|
|
1783
1783
|
lifecycleHooks: LifecycleHookMap;
|
|
1784
1784
|
}
|
|
1785
1785
|
|
|
1786
|
+
/** Warning from extension dependency sort (missing deps, cycles). */
|
|
1787
|
+
export interface ExtensionLoadWarning {
|
|
1788
|
+
declaringId: string;
|
|
1789
|
+
missingId: string;
|
|
1790
|
+
message: string;
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1786
1793
|
/** Result of loading extensions. */
|
|
1787
1794
|
export interface LoadExtensionsResult {
|
|
1788
1795
|
extensions: Extension[];
|
|
1789
1796
|
errors: Array<{ path: string; error: string }>;
|
|
1797
|
+
warnings: ExtensionLoadWarning[];
|
|
1790
1798
|
/** Shared runtime - actions are throwing stubs until runner.initialize() */
|
|
1791
1799
|
runtime: ExtensionRuntime;
|
|
1792
1800
|
}
|
|
@@ -14,6 +14,7 @@ import { spawn } from "node:child_process";
|
|
|
14
14
|
import * as fs from "node:fs";
|
|
15
15
|
import * as path from "node:path";
|
|
16
16
|
import * as os from "node:os";
|
|
17
|
+
import { spawnSync } from "node:child_process";
|
|
17
18
|
|
|
18
19
|
// ---------------------------------------------------------------------------
|
|
19
20
|
// Helpers — lightweight JSON-RPC over stdio (no dependency on our LSP code)
|
|
@@ -251,11 +252,23 @@ function fileToUri(filePath: string): string {
|
|
|
251
252
|
return `file://${path.resolve(filePath)}`;
|
|
252
253
|
}
|
|
253
254
|
|
|
255
|
+
function hasTypescriptLanguageServer(): boolean {
|
|
256
|
+
const probe = spawnSync("typescript-language-server", ["--help"], {
|
|
257
|
+
stdio: "ignore",
|
|
258
|
+
});
|
|
259
|
+
return probe.status === 0 || probe.status === 1;
|
|
260
|
+
}
|
|
261
|
+
|
|
254
262
|
// ---------------------------------------------------------------------------
|
|
255
263
|
// Tests
|
|
256
264
|
// ---------------------------------------------------------------------------
|
|
257
265
|
|
|
258
266
|
test("LSP integration: typescript-language-server", async (t) => {
|
|
267
|
+
if (!hasTypescriptLanguageServer()) {
|
|
268
|
+
t.skip("typescript-language-server not installed in this environment");
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
|
|
259
272
|
const { dir, cleanup } = createTempProject();
|
|
260
273
|
const mainPath = path.join(dir, "src", "main.ts");
|
|
261
274
|
const mathPath = path.join(dir, "src", "math.ts");
|
|
@@ -302,8 +315,19 @@ test("LSP integration: typescript-language-server", async (t) => {
|
|
|
302
315
|
textDocument: { uri: mathUri, languageId: "typescript", version: 1, text: mathContent },
|
|
303
316
|
});
|
|
304
317
|
|
|
305
|
-
//
|
|
306
|
-
|
|
318
|
+
// Poll for a published diagnostics notification on main.ts, which
|
|
319
|
+
// is the observable signal that TypeScript has finished indexing
|
|
320
|
+
// the opened file. Previous magic-sleep (3000ms) was too short on
|
|
321
|
+
// slow CI machines and wasteful on fast ones (#4798).
|
|
322
|
+
const INDEX_DEADLINE_MS = 15_000;
|
|
323
|
+
const indexDeadline = Date.now() + INDEX_DEADLINE_MS;
|
|
324
|
+
while (Date.now() < indexDeadline) {
|
|
325
|
+
const diags = lsp
|
|
326
|
+
.getNotifications("textDocument/publishDiagnostics")
|
|
327
|
+
.filter((n) => (n.params as { uri: string }).uri === mainUri);
|
|
328
|
+
if (diags.length > 0) break;
|
|
329
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
330
|
+
}
|
|
307
331
|
|
|
308
332
|
// ---- Hover ----
|
|
309
333
|
await t.test("hover on 'add' call", async () => {
|
|
@@ -368,8 +392,28 @@ test("LSP integration: typescript-language-server", async (t) => {
|
|
|
368
392
|
|
|
369
393
|
// ---- Diagnostics (published via notification) ----
|
|
370
394
|
await t.test("diagnostics for type error", async () => {
|
|
371
|
-
//
|
|
372
|
-
|
|
395
|
+
// Poll for the specific type-error diagnostic on main.ts
|
|
396
|
+
// instead of sleeping a fixed 2s. tsserver pushes diagnostics
|
|
397
|
+
// incrementally — we need to wait until at least one diag
|
|
398
|
+
// contains a type-error signal, not just any diag.
|
|
399
|
+
const DIAG_DEADLINE_MS = 10_000;
|
|
400
|
+
const diagDeadline = Date.now() + DIAG_DEADLINE_MS;
|
|
401
|
+
while (Date.now() < diagDeadline) {
|
|
402
|
+
const candidates = lsp
|
|
403
|
+
.getNotifications("textDocument/publishDiagnostics")
|
|
404
|
+
.filter((n) => (n.params as { uri: string }).uri === mainUri)
|
|
405
|
+
.flatMap(
|
|
406
|
+
(n) => (n.params as { diagnostics: Array<{ message: string }> }).diagnostics,
|
|
407
|
+
);
|
|
408
|
+
if (
|
|
409
|
+
candidates.some(
|
|
410
|
+
(d) => d.message.includes("not assignable") || d.message.includes("Type"),
|
|
411
|
+
)
|
|
412
|
+
) {
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
415
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
416
|
+
}
|
|
373
417
|
|
|
374
418
|
const diagNotifications = lsp.getNotifications("textDocument/publishDiagnostics");
|
|
375
419
|
const mainDiags = diagNotifications.filter(
|