gsd-pi 2.57.0-dev.f22a903 → 2.58.0-dev.778d6ac
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 +1 -1
- package/dist/cli.js +49 -35
- package/dist/headless-ui.d.ts +17 -0
- package/dist/headless-ui.js +97 -3
- package/dist/headless.js +67 -6
- package/dist/help-text.js +1 -0
- package/dist/onboarding.js +44 -0
- package/dist/resource-loader.js +16 -1
- package/dist/resources/agents/researcher.md +1 -1
- package/dist/resources/extensions/ask-user-questions.js +16 -3
- package/dist/resources/extensions/async-jobs/extension-manifest.json +1 -1
- package/dist/resources/extensions/bg-shell/extension-manifest.json +1 -1
- package/dist/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +14 -6
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +59 -36
- package/dist/resources/extensions/context7/extension-manifest.json +1 -1
- package/dist/resources/extensions/get-secrets-from-user.js +8 -5
- package/dist/resources/extensions/google-search/extension-manifest.json +1 -1
- package/dist/resources/extensions/google-search/index.js +2 -1
- package/dist/resources/extensions/gsd/auto/phases.js +25 -21
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +2 -2
- package/dist/resources/extensions/gsd/auto-dashboard.js +37 -20
- package/dist/resources/extensions/gsd/auto-dispatch.js +17 -2
- package/dist/resources/extensions/gsd/auto-model-selection.js +26 -3
- package/dist/resources/extensions/gsd/auto-post-unit.js +16 -4
- package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
- package/dist/resources/extensions/gsd/auto-recovery.js +13 -5
- package/dist/resources/extensions/gsd/auto-start.js +35 -22
- package/dist/resources/extensions/gsd/auto-worktree.js +196 -12
- package/dist/resources/extensions/gsd/auto.js +4 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +32 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -8
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -18
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +44 -11
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +67 -0
- package/dist/resources/extensions/gsd/captures.js +56 -4
- package/dist/resources/extensions/gsd/db-writer.js +116 -8
- package/dist/resources/extensions/gsd/doctor-git-checks.js +28 -0
- package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +5 -4
- package/dist/resources/extensions/gsd/doctor.js +3 -1
- package/dist/resources/extensions/gsd/error-classifier.js +13 -10
- package/dist/resources/extensions/gsd/extension-manifest.json +16 -1
- package/dist/resources/extensions/gsd/forensics.js +123 -20
- package/dist/resources/extensions/gsd/git-service.js +23 -1
- package/dist/resources/extensions/gsd/gitignore.js +33 -0
- package/dist/resources/extensions/gsd/gsd-db.js +36 -9
- package/dist/resources/extensions/gsd/guided-flow.js +106 -44
- package/dist/resources/extensions/gsd/health-widget-core.js +31 -0
- package/dist/resources/extensions/gsd/health-widget.js +17 -0
- package/dist/resources/extensions/gsd/index.js +1 -1
- package/dist/resources/extensions/gsd/memory-extractor.js +7 -0
- package/dist/resources/extensions/gsd/migrate-external.js +8 -1
- package/dist/resources/extensions/gsd/milestone-validation-gates.js +45 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +18 -0
- package/dist/resources/extensions/gsd/model-router.js +35 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +17 -0
- package/dist/resources/extensions/gsd/notifications.js +16 -1
- package/dist/resources/extensions/gsd/parallel-eligibility.js +13 -2
- package/dist/resources/extensions/gsd/parallel-merge.js +78 -5
- package/dist/resources/extensions/gsd/parsers-legacy.js +20 -3
- package/dist/resources/extensions/gsd/paths.js +43 -0
- package/dist/resources/extensions/gsd/preferences-models.js +14 -1
- package/dist/resources/extensions/gsd/preferences-types.js +2 -1
- package/dist/resources/extensions/gsd/preferences.js +13 -16
- package/dist/resources/extensions/gsd/prompt-loader.js +4 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -2
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -1
- package/dist/resources/extensions/gsd/prompts/forensics.md +2 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -0
- package/dist/resources/extensions/gsd/prompts/rethink.md +1 -1
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -0
- package/dist/resources/extensions/gsd/repo-identity.js +205 -11
- package/dist/resources/extensions/gsd/rethink.js +5 -0
- package/dist/resources/extensions/gsd/roadmap-slices.js +5 -4
- package/dist/resources/extensions/gsd/state.js +85 -27
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
- package/dist/resources/extensions/gsd/tools/complete-task.js +34 -71
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +12 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +29 -1
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +14 -3
- package/dist/resources/extensions/gsd/triage-resolution.js +22 -7
- package/dist/resources/extensions/gsd/undo.js +2 -2
- package/dist/resources/extensions/gsd/unit-ownership.js +164 -33
- package/dist/resources/extensions/gsd/verdict-parser.js +20 -8
- package/dist/resources/extensions/gsd/workflow-manifest.js +24 -5
- package/dist/resources/extensions/gsd/workflow-projections.js +95 -63
- package/dist/resources/extensions/gsd/workflow-reconcile.js +35 -5
- package/dist/resources/extensions/gsd/workspace-index.js +24 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +105 -1
- package/dist/resources/extensions/gsd/worktree-resolver.js +20 -3
- package/dist/resources/extensions/mcp-client/index.js +11 -7
- package/dist/resources/extensions/ollama/index.js +112 -0
- package/dist/resources/extensions/ollama/model-capabilities.js +115 -0
- package/dist/resources/extensions/ollama/ollama-client.js +168 -0
- package/dist/resources/extensions/ollama/ollama-commands.js +194 -0
- package/dist/resources/extensions/ollama/ollama-discovery.js +69 -0
- package/dist/resources/extensions/ollama/ollama-tool.js +184 -0
- package/dist/resources/extensions/ollama/types.js +2 -0
- package/dist/resources/extensions/search-the-web/extension-manifest.json +1 -1
- package/dist/resources/extensions/shared/interview-ui.js +11 -1
- package/dist/resources/skills/create-gsd-extension/SKILL.md +5 -3
- package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
- package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
- package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
- package/dist/startup-model-validation.d.ts +39 -0
- package/dist/startup-model-validation.js +50 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +16 -16
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_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 +2 -2
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- 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 +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 +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +16 -16
- package/dist/web/standalone/.next/server/chunks/2229.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +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 +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +9 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-61d3afac6d0f0ce7.js → webpack-a1c1e452c6b32d04.js} +1 -1
- package/dist/web/standalone/.next/static/css/f6e8833d46e738d8.css +1 -0
- package/dist/web-mode.js +2 -1
- package/package.json +2 -2
- package/packages/daemon/src/cli.ts +49 -0
- package/packages/daemon/src/daemon.test.ts +104 -1
- package/packages/daemon/src/daemon.ts +24 -1
- package/packages/daemon/src/discord-bot.ts +73 -3
- package/packages/daemon/src/event-bridge.ts +15 -9
- package/packages/daemon/src/event-formatter.ts +30 -2
- package/packages/daemon/src/index.ts +9 -0
- package/packages/daemon/src/launchd.test.ts +356 -0
- package/packages/daemon/src/launchd.ts +242 -0
- package/packages/daemon/src/message-batcher.test.ts +2 -2
- package/packages/daemon/src/message-batcher.ts +9 -3
- package/packages/daemon/src/orchestrator.test.ts +1 -0
- package/packages/daemon/src/orchestrator.ts +106 -2
- package/packages/native/dist/ast/index.js +9 -5
- package/packages/native/dist/ast/types.js +2 -1
- package/packages/native/dist/clipboard/index.js +12 -7
- package/packages/native/dist/clipboard/types.js +2 -1
- package/packages/native/dist/diff/index.js +12 -7
- package/packages/native/dist/diff/types.js +2 -1
- package/packages/native/dist/fd/index.js +6 -3
- package/packages/native/dist/fd/types.js +2 -1
- package/packages/native/dist/glob/index.js +9 -5
- package/packages/native/dist/glob/types.js +2 -1
- package/packages/native/dist/grep/index.js +9 -5
- package/packages/native/dist/grep/types.js +2 -1
- package/packages/native/dist/gsd-parser/index.js +18 -11
- package/packages/native/dist/gsd-parser/types.js +2 -1
- package/packages/native/dist/highlight/index.js +12 -7
- package/packages/native/dist/highlight/types.js +2 -1
- package/packages/native/dist/html/index.js +6 -3
- package/packages/native/dist/html/types.js +2 -1
- package/packages/native/dist/image/index.js +10 -5
- package/packages/native/dist/image/types.js +7 -4
- package/packages/native/dist/index.js +70 -17
- package/packages/native/dist/json-parse/index.js +13 -8
- package/packages/native/dist/native.js +47 -10
- package/packages/native/dist/ps/index.js +15 -9
- package/packages/native/dist/ps/types.js +2 -1
- package/packages/native/dist/stream-process/index.js +12 -7
- package/packages/native/dist/text/index.js +24 -14
- package/packages/native/dist/text/types.js +5 -2
- package/packages/native/dist/truncate/index.js +12 -7
- package/packages/native/dist/ttsr/index.js +12 -7
- package/packages/native/dist/ttsr/types.js +2 -1
- package/packages/native/dist/xxhash/index.js +9 -5
- package/packages/native/package.json +19 -19
- package/packages/native/src/__tests__/module-compat.test.mjs +91 -0
- package/packages/native/src/native.ts +9 -8
- package/packages/pi-agent-core/dist/agent-loop.js +3 -2
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/proxy.d.ts +1 -1
- package/packages/pi-agent-core/dist/proxy.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/proxy.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +45 -0
- package/packages/pi-agent-core/src/agent-loop.ts +3 -2
- package/packages/pi-agent-core/src/proxy.ts +1 -1
- package/packages/pi-ai/dist/env-api-keys.js +1 -0
- package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
- package/packages/pi-ai/dist/index.d.ts +1 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +19 -2
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js +25 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -0
- package/packages/pi-ai/dist/types.d.ts +3 -3
- 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/json-parse.d.ts +3 -0
- package/packages/pi-ai/dist/utils/json-parse.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/json-parse.js +24 -1
- package/packages/pi-ai/dist/utils/json-parse.js.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.d.ts +37 -0
- package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/repair-tool-json.js +75 -0
- package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +73 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -0
- package/packages/pi-ai/src/env-api-keys.ts +1 -0
- package/packages/pi-ai/src/index.ts +1 -0
- package/packages/pi-ai/src/providers/anthropic-shared.test.ts +29 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +17 -2
- package/packages/pi-ai/src/types.ts +3 -2
- package/packages/pi-ai/src/utils/json-parse.ts +28 -1
- package/packages/pi-ai/src/utils/repair-tool-json.ts +88 -0
- package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +102 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +31 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +17 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +62 -2
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +176 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/exec.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/exec.js +3 -1
- package/packages/pi-coding-agent/dist/core/exec.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts +28 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js +37 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js +63 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts +19 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js +115 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js +109 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts +44 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js +97 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js +181 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/index.js +1 -1
- package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.js +3 -0
- package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +3 -0
- package/packages/pi-coding-agent/dist/core/lsp/lspmux.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 +31 -2
- package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.test.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/messages.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/messages.test.js +86 -0
- package/packages/pi-coding-agent/dist/core/messages.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +10 -0
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +12 -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 +6 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +48 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +193 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +10 -3
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js +13 -4
- package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts +16 -0
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +80 -0
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts +2 -2
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js +5 -0
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +38 -1
- package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +236 -0
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +94 -1
- package/packages/pi-coding-agent/src/core/exec.ts +3 -1
- package/packages/pi-coding-agent/src/core/extensions/extension-manifest.test.ts +77 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-manifest.ts +62 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-sort.test.ts +134 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-sort.ts +137 -0
- package/packages/pi-coding-agent/src/core/extensions/index.ts +4 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +5 -0
- package/packages/pi-coding-agent/src/core/image-overflow-recovery.test.ts +228 -0
- package/packages/pi-coding-agent/src/core/image-overflow-recovery.ts +118 -0
- package/packages/pi-coding-agent/src/core/index.ts +6 -0
- package/packages/pi-coding-agent/src/core/lsp/index.ts +3 -0
- package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +3 -0
- package/packages/pi-coding-agent/src/core/messages.test.ts +114 -0
- package/packages/pi-coding-agent/src/core/messages.ts +29 -2
- package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
- package/packages/pi-coding-agent/src/core/resource-loader.ts +20 -1
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +255 -0
- package/packages/pi-coding-agent/src/core/retry-handler.ts +52 -1
- package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +11 -3
- package/packages/pi-coding-agent/src/core/tools/read.ts +14 -4
- package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +92 -0
- package/packages/pi-coding-agent/src/index.ts +6 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -0
- package/packages/pi-coding-agent/src/modes/rpc/remote-terminal.ts +6 -0
- package/packages/pi-tui/dist/terminal.d.ts +2 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +9 -0
- package/packages/pi-tui/dist/terminal.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +9 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/terminal.ts +14 -0
- package/packages/pi-tui/src/tui.ts +8 -0
- package/pkg/package.json +1 -1
- package/scripts/ensure-workspace-builds.cjs +45 -14
- package/src/resources/agents/researcher.md +1 -1
- package/src/resources/extensions/ask-user-questions.ts +21 -3
- package/src/resources/extensions/async-jobs/extension-manifest.json +1 -1
- package/src/resources/extensions/bg-shell/extension-manifest.json +1 -1
- package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +13 -6
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +63 -35
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +28 -0
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -1
- package/src/resources/extensions/context7/extension-manifest.json +1 -1
- package/src/resources/extensions/get-secrets-from-user.ts +8 -5
- package/src/resources/extensions/google-search/extension-manifest.json +1 -1
- package/src/resources/extensions/google-search/index.ts +2 -1
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/phases.ts +43 -34
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +2 -2
- package/src/resources/extensions/gsd/auto-dashboard.ts +37 -19
- package/src/resources/extensions/gsd/auto-dispatch.ts +18 -2
- package/src/resources/extensions/gsd/auto-model-selection.ts +26 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +18 -4
- package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +12 -5
- package/src/resources/extensions/gsd/auto-start.ts +35 -26
- package/src/resources/extensions/gsd/auto-worktree.ts +190 -9
- package/src/resources/extensions/gsd/auto.ts +5 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +31 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +85 -8
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +38 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +31 -19
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +50 -11
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +75 -0
- package/src/resources/extensions/gsd/captures.ts +63 -3
- package/src/resources/extensions/gsd/db-writer.ts +140 -7
- package/src/resources/extensions/gsd/doctor-git-checks.ts +26 -0
- package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +5 -4
- package/src/resources/extensions/gsd/doctor.ts +3 -1
- package/src/resources/extensions/gsd/error-classifier.ts +14 -11
- package/src/resources/extensions/gsd/extension-manifest.json +16 -1
- package/src/resources/extensions/gsd/forensics.ts +144 -20
- package/src/resources/extensions/gsd/git-service.ts +26 -3
- package/src/resources/extensions/gsd/gitignore.ts +33 -0
- package/src/resources/extensions/gsd/gsd-db.ts +43 -7
- package/src/resources/extensions/gsd/guided-flow.ts +114 -45
- package/src/resources/extensions/gsd/health-widget-core.ts +34 -0
- package/src/resources/extensions/gsd/health-widget.ts +17 -0
- package/src/resources/extensions/gsd/index.ts +1 -0
- package/src/resources/extensions/gsd/memory-extractor.ts +8 -0
- package/src/resources/extensions/gsd/migrate-external.ts +9 -1
- package/src/resources/extensions/gsd/milestone-validation-gates.ts +56 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +19 -0
- package/src/resources/extensions/gsd/model-router.ts +35 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +17 -0
- package/src/resources/extensions/gsd/notifications.ts +16 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +15 -2
- package/src/resources/extensions/gsd/parallel-merge.ts +87 -4
- package/src/resources/extensions/gsd/parsers-legacy.ts +22 -3
- package/src/resources/extensions/gsd/paths.ts +42 -0
- package/src/resources/extensions/gsd/preferences-models.ts +14 -1
- package/src/resources/extensions/gsd/preferences-types.ts +2 -1
- package/src/resources/extensions/gsd/preferences.ts +13 -15
- package/src/resources/extensions/gsd/prompt-loader.ts +4 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -2
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -1
- package/src/resources/extensions/gsd/prompts/forensics.md +2 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -0
- package/src/resources/extensions/gsd/prompts/rethink.md +1 -1
- package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -0
- package/src/resources/extensions/gsd/repo-identity.ts +186 -11
- package/src/resources/extensions/gsd/rethink.ts +6 -0
- package/src/resources/extensions/gsd/roadmap-slices.ts +5 -4
- package/src/resources/extensions/gsd/state.ts +84 -32
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/auto-mode-interactive-guard.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +71 -1
- package/src/resources/extensions/gsd/tests/captures.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/cli-provider-rate-limit.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/completion-hierarchy-guards.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +131 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +7 -12
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +78 -5
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/dynamic-routing-default.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/event-replay-idempotency.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +129 -0
- package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +125 -12
- package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +164 -0
- package/src/resources/extensions/gsd/tests/guided-flow-dynamic-routing.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +111 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-false-positives.test.ts +243 -0
- package/src/resources/extensions/gsd/tests/integration/gitignore-staging-2570.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +959 -0
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +85 -2
- package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/model-router.test.ts +68 -3
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/notifications.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/parallel-eligibility-ghost.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +297 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/prompt-loader-replacement.test.ts +178 -0
- package/src/resources/extensions/gsd/tests/prompt-tool-names.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/queue-execution-guard.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/reconciliation-edge-cases.test.ts +162 -0
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +233 -0
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +305 -0
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +405 -0
- package/src/resources/extensions/gsd/tests/state-derivation-parity.test.ts +257 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +1628 -0
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +174 -0
- package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +221 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +289 -0
- package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +100 -17
- package/src/resources/extensions/gsd/tests/vacuum-recovery.test.ts +154 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/verdict-parser.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +95 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +36 -74
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +13 -1
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +36 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +20 -2
- package/src/resources/extensions/gsd/triage-resolution.ts +23 -6
- package/src/resources/extensions/gsd/types.ts +4 -2
- package/src/resources/extensions/gsd/undo.ts +2 -2
- package/src/resources/extensions/gsd/unit-ownership.ts +206 -35
- package/src/resources/extensions/gsd/verdict-parser.ts +21 -6
- package/src/resources/extensions/gsd/workflow-logger.ts +3 -1
- package/src/resources/extensions/gsd/workflow-manifest.ts +22 -5
- package/src/resources/extensions/gsd/workflow-projections.ts +97 -64
- package/src/resources/extensions/gsd/workflow-reconcile.ts +39 -10
- package/src/resources/extensions/gsd/workspace-index.ts +30 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +120 -1
- package/src/resources/extensions/gsd/worktree-resolver.ts +22 -3
- package/src/resources/extensions/mcp-client/index.ts +13 -7
- package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +55 -0
- package/src/resources/extensions/ollama/index.ts +130 -0
- package/src/resources/extensions/ollama/model-capabilities.ts +145 -0
- package/src/resources/extensions/ollama/ollama-client.ts +196 -0
- package/src/resources/extensions/ollama/ollama-commands.ts +248 -0
- package/src/resources/extensions/ollama/ollama-discovery.ts +106 -0
- package/src/resources/extensions/ollama/ollama-tool.ts +218 -0
- package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +162 -0
- package/src/resources/extensions/ollama/tests/ollama-client.test.ts +38 -0
- package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +28 -0
- package/src/resources/extensions/ollama/types.ts +130 -0
- package/src/resources/extensions/search-the-web/extension-manifest.json +1 -1
- package/src/resources/extensions/shared/interview-ui.ts +12 -1
- package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +156 -0
- package/src/resources/skills/create-gsd-extension/SKILL.md +5 -3
- package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
- package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
- package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
- package/dist/web/standalone/.next/static/chunks/6502.8b732f67a11b11b4.js +0 -9
- package/dist/web/standalone/.next/static/css/a58ef8a151aa0493.css +0 -1
- package/src/resources/extensions/gsd/tests/empty-db-reconciliation.test.ts +0 -79
- /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { describe, it } from "node:test";
|
|
3
|
+
import {
|
|
4
|
+
isImageDimensionError,
|
|
5
|
+
MANY_IMAGE_MAX_DIMENSION,
|
|
6
|
+
downsizeConversationImages,
|
|
7
|
+
} from "./image-overflow-recovery.js";
|
|
8
|
+
import type { Message } from "@gsd/pi-ai";
|
|
9
|
+
|
|
10
|
+
// ─── isImageDimensionError ────────────────────────────────────────────────────
|
|
11
|
+
|
|
12
|
+
describe("isImageDimensionError", () => {
|
|
13
|
+
it("returns true for Anthropic many-image dimension error", () => {
|
|
14
|
+
const errorMessage =
|
|
15
|
+
'Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"messages.125.content.38.image.source.base64.data: At least one of the image dimensions exceed max allowed size for many-image requests: 2000 pixels"}}';
|
|
16
|
+
assert.equal(isImageDimensionError(errorMessage), true);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("returns true for bare dimension exceed message", () => {
|
|
20
|
+
const errorMessage =
|
|
21
|
+
"image dimensions exceed max allowed size for many-image requests: 2000 pixels";
|
|
22
|
+
assert.equal(isImageDimensionError(errorMessage), true);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("returns false for unrelated 400 error", () => {
|
|
26
|
+
const errorMessage =
|
|
27
|
+
'Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"max_tokens: 4096 > 2048"}}';
|
|
28
|
+
assert.equal(isImageDimensionError(errorMessage), false);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("returns false for rate limit error", () => {
|
|
32
|
+
assert.equal(isImageDimensionError("429 rate limit exceeded"), false);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("returns false for empty string", () => {
|
|
36
|
+
assert.equal(isImageDimensionError(""), false);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("returns false for undefined", () => {
|
|
40
|
+
assert.equal(isImageDimensionError(undefined), false);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// ─── MANY_IMAGE_MAX_DIMENSION ─────────────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
describe("MANY_IMAGE_MAX_DIMENSION", () => {
|
|
47
|
+
it("is less than 2000 (the API-enforced limit)", () => {
|
|
48
|
+
assert.ok(MANY_IMAGE_MAX_DIMENSION < 2000);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("is a positive integer", () => {
|
|
52
|
+
assert.ok(MANY_IMAGE_MAX_DIMENSION > 0);
|
|
53
|
+
assert.equal(MANY_IMAGE_MAX_DIMENSION, Math.floor(MANY_IMAGE_MAX_DIMENSION));
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// ─── helpers ──────────────────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
function makeUserMsg(content: Message["content"] & any): Message {
|
|
60
|
+
return { role: "user", content, timestamp: Date.now() } as Message;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function makeAssistantMsg(text: string): Message {
|
|
64
|
+
return {
|
|
65
|
+
role: "assistant",
|
|
66
|
+
content: [{ type: "text", text }],
|
|
67
|
+
api: "anthropic-messages",
|
|
68
|
+
provider: "anthropic",
|
|
69
|
+
model: "claude-opus-4-6",
|
|
70
|
+
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
|
|
71
|
+
stopReason: "stop",
|
|
72
|
+
timestamp: Date.now(),
|
|
73
|
+
} as Message;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function makeToolResultMsg(images: number): Message {
|
|
77
|
+
const content: any[] = [];
|
|
78
|
+
for (let i = 0; i < images; i++) {
|
|
79
|
+
content.push({ type: "image", data: `img${i}`, mimeType: "image/png" });
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
role: "toolResult",
|
|
83
|
+
toolCallId: `tc${Math.random()}`,
|
|
84
|
+
toolName: "screenshot",
|
|
85
|
+
content,
|
|
86
|
+
isError: false,
|
|
87
|
+
timestamp: Date.now(),
|
|
88
|
+
} as Message;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ─── downsizeConversationImages ───────────────────────────────────────────────
|
|
92
|
+
|
|
93
|
+
describe("downsizeConversationImages", () => {
|
|
94
|
+
it("counts images in user and toolResult messages", () => {
|
|
95
|
+
const messages: Message[] = [
|
|
96
|
+
makeUserMsg([
|
|
97
|
+
{ type: "image", data: "img1", mimeType: "image/png" },
|
|
98
|
+
{ type: "image", data: "img2", mimeType: "image/png" },
|
|
99
|
+
]),
|
|
100
|
+
makeAssistantMsg("I see them"),
|
|
101
|
+
makeToolResultMsg(1),
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
const result = downsizeConversationImages(messages);
|
|
105
|
+
assert.equal(result.imageCount, 3);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("returns processed=false when no images present", () => {
|
|
109
|
+
const messages: Message[] = [
|
|
110
|
+
makeUserMsg("just text"),
|
|
111
|
+
makeAssistantMsg("reply"),
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
const result = downsizeConversationImages(messages);
|
|
115
|
+
assert.equal(result.imageCount, 0);
|
|
116
|
+
assert.equal(result.processed, false);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("returns processed=false when image count <= RECENT_IMAGES_TO_KEEP", () => {
|
|
120
|
+
const messages: Message[] = [
|
|
121
|
+
makeUserMsg([
|
|
122
|
+
{ type: "image", data: "img1", mimeType: "image/png" },
|
|
123
|
+
]),
|
|
124
|
+
makeAssistantMsg("got it"),
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
const result = downsizeConversationImages(messages);
|
|
128
|
+
assert.equal(result.imageCount, 1);
|
|
129
|
+
assert.equal(result.processed, false);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("strips older images when many images present, preserves recent ones", () => {
|
|
133
|
+
const messages: Message[] = [];
|
|
134
|
+
for (let i = 0; i < 25; i++) {
|
|
135
|
+
messages.push(
|
|
136
|
+
makeUserMsg([
|
|
137
|
+
{ type: "text", text: `message ${i}` },
|
|
138
|
+
{ type: "image", data: `img${i}`, mimeType: "image/png" },
|
|
139
|
+
]),
|
|
140
|
+
);
|
|
141
|
+
messages.push(makeAssistantMsg(`reply ${i}`));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const result = downsizeConversationImages(messages);
|
|
145
|
+
assert.ok(result.processed);
|
|
146
|
+
assert.equal(result.imageCount, 25);
|
|
147
|
+
assert.equal(result.strippedCount, 20); // 25 - 5 recent
|
|
148
|
+
|
|
149
|
+
// Count remaining images
|
|
150
|
+
let remainingImages = 0;
|
|
151
|
+
for (const msg of messages) {
|
|
152
|
+
if (msg.role === "assistant") continue;
|
|
153
|
+
if (typeof msg.content === "string") continue;
|
|
154
|
+
const arr = msg.content as any[];
|
|
155
|
+
for (const block of arr) {
|
|
156
|
+
if (block.type === "image") remainingImages++;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
assert.equal(remainingImages, 5, "Should keep exactly 5 most recent images");
|
|
160
|
+
|
|
161
|
+
// The 5 most recent user messages (indices 40,42,44,46,48) should have images
|
|
162
|
+
for (let i = 20; i < 25; i++) {
|
|
163
|
+
const userMsg = messages[i * 2]; // user messages at even indices
|
|
164
|
+
const arr = userMsg.content as any[];
|
|
165
|
+
const hasImage = arr.some((c: any) => c.type === "image");
|
|
166
|
+
assert.ok(hasImage, `Recent message ${i} should retain its image`);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("adds text placeholder when stripping an image", () => {
|
|
171
|
+
const messages: Message[] = [];
|
|
172
|
+
for (let i = 0; i < 10; i++) {
|
|
173
|
+
messages.push(
|
|
174
|
+
makeUserMsg([
|
|
175
|
+
{ type: "image", data: `img${i}`, mimeType: "image/jpeg" },
|
|
176
|
+
]),
|
|
177
|
+
);
|
|
178
|
+
messages.push(makeAssistantMsg(`reply ${i}`));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
downsizeConversationImages(messages);
|
|
182
|
+
|
|
183
|
+
// First message's image should have been replaced with text
|
|
184
|
+
const firstMsg = messages[0];
|
|
185
|
+
const arr = firstMsg.content as any[];
|
|
186
|
+
const placeholder = arr.find(
|
|
187
|
+
(c: any) => c.type === "text" && c.text.includes("[image removed"),
|
|
188
|
+
);
|
|
189
|
+
assert.ok(placeholder, "Stripped image should be replaced with text placeholder");
|
|
190
|
+
assert.ok(
|
|
191
|
+
placeholder.text.includes("image/jpeg"),
|
|
192
|
+
"Placeholder should mention original mime type",
|
|
193
|
+
);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it("handles toolResult messages with images", () => {
|
|
197
|
+
const messages: Message[] = [];
|
|
198
|
+
for (let i = 0; i < 10; i++) {
|
|
199
|
+
messages.push(makeToolResultMsg(1));
|
|
200
|
+
messages.push(makeAssistantMsg(`reply ${i}`));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const result = downsizeConversationImages(messages);
|
|
204
|
+
assert.equal(result.imageCount, 10);
|
|
205
|
+
assert.equal(result.strippedCount, 5);
|
|
206
|
+
assert.ok(result.processed);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it("handles mixed user and toolResult images", () => {
|
|
210
|
+
const messages: Message[] = [];
|
|
211
|
+
for (let i = 0; i < 8; i++) {
|
|
212
|
+
messages.push(
|
|
213
|
+
makeUserMsg([
|
|
214
|
+
{ type: "text", text: `check ${i}` },
|
|
215
|
+
{ type: "image", data: `uimg${i}`, mimeType: "image/png" },
|
|
216
|
+
]),
|
|
217
|
+
);
|
|
218
|
+
messages.push(makeAssistantMsg(`processing ${i}`));
|
|
219
|
+
messages.push(makeToolResultMsg(1));
|
|
220
|
+
messages.push(makeAssistantMsg(`done ${i}`));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const result = downsizeConversationImages(messages);
|
|
224
|
+
// 8 user images + 8 tool result images = 16 total
|
|
225
|
+
assert.equal(result.imageCount, 16);
|
|
226
|
+
assert.equal(result.strippedCount, 11); // 16 - 5 recent
|
|
227
|
+
});
|
|
228
|
+
});
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image overflow recovery for many-image sessions.
|
|
3
|
+
*
|
|
4
|
+
* When a conversation accumulates many images (screenshots, file reads, etc.),
|
|
5
|
+
* the Anthropic API enforces a stricter per-image dimension limit (2000px) for
|
|
6
|
+
* "many-image requests." This module detects the resulting 400 error and
|
|
7
|
+
* recovers by stripping older images from the conversation history, preserving
|
|
8
|
+
* the most recent ones to maintain session continuity.
|
|
9
|
+
*
|
|
10
|
+
* @see https://github.com/gsd-build/gsd-2/issues/2874
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { Message, ImageContent, TextContent } from "@gsd/pi-ai";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Maximum image dimension (px) that the Anthropic API allows in many-image
|
|
17
|
+
* requests. Images at or above this size in a large conversation will be
|
|
18
|
+
* rejected with a 400 error. We use 1568 as the safe ceiling (Anthropic's
|
|
19
|
+
* recommended max for multi-image requests).
|
|
20
|
+
*/
|
|
21
|
+
export const MANY_IMAGE_MAX_DIMENSION = 1568;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Number of recent images to preserve when stripping old images.
|
|
25
|
+
* Keeps the most recent screenshots/images so the model retains visual context
|
|
26
|
+
* for the current task.
|
|
27
|
+
*/
|
|
28
|
+
const RECENT_IMAGES_TO_KEEP = 5;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Regex matching the Anthropic API error for oversized images in many-image requests.
|
|
32
|
+
*/
|
|
33
|
+
const IMAGE_DIMENSION_ERROR_RE =
|
|
34
|
+
/image.dimensions?.exceed.*max.*allowed.*size.*many.image/i;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Detect whether an error message is the Anthropic "image dimensions exceed max
|
|
38
|
+
* allowed size for many-image requests" 400 error.
|
|
39
|
+
*/
|
|
40
|
+
export function isImageDimensionError(errorMessage: string | undefined | null): boolean {
|
|
41
|
+
if (!errorMessage) return false;
|
|
42
|
+
return IMAGE_DIMENSION_ERROR_RE.test(errorMessage);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface DownsizeResult {
|
|
46
|
+
/** Total number of images found in the conversation */
|
|
47
|
+
imageCount: number;
|
|
48
|
+
/** Whether any images were stripped */
|
|
49
|
+
processed: boolean;
|
|
50
|
+
/** Number of images that were stripped */
|
|
51
|
+
strippedCount: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Strip older images from conversation messages to recover from many-image
|
|
56
|
+
* dimension errors. Preserves the N most recent images and replaces older ones
|
|
57
|
+
* with a text placeholder.
|
|
58
|
+
*
|
|
59
|
+
* Mutates messages in place (same pattern as replaceMessages/compaction).
|
|
60
|
+
*
|
|
61
|
+
* Accepts Message[] (the LLM message union) so it works with both
|
|
62
|
+
* agent.state.messages and session entries.
|
|
63
|
+
*/
|
|
64
|
+
export function downsizeConversationImages(messages: Message[]): DownsizeResult {
|
|
65
|
+
// First pass: collect all image locations (message index + content index)
|
|
66
|
+
const imageLocations: Array<{ msgIdx: number; contentIdx: number }> = [];
|
|
67
|
+
|
|
68
|
+
for (let msgIdx = 0; msgIdx < messages.length; msgIdx++) {
|
|
69
|
+
const msg = messages[msgIdx];
|
|
70
|
+
if (msg.role === "assistant") continue;
|
|
71
|
+
|
|
72
|
+
// UserMessage can have string content; ToolResultMessage always has array
|
|
73
|
+
if (msg.role === "user" && typeof msg.content === "string") continue;
|
|
74
|
+
|
|
75
|
+
const contentArr = msg.content as (TextContent | ImageContent)[];
|
|
76
|
+
if (!Array.isArray(contentArr)) continue;
|
|
77
|
+
|
|
78
|
+
for (let contentIdx = 0; contentIdx < contentArr.length; contentIdx++) {
|
|
79
|
+
if (contentArr[contentIdx].type === "image") {
|
|
80
|
+
imageLocations.push({ msgIdx, contentIdx });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const imageCount = imageLocations.length;
|
|
86
|
+
if (imageCount === 0) {
|
|
87
|
+
return { imageCount: 0, processed: false, strippedCount: 0 };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Determine which images to strip (all except the N most recent)
|
|
91
|
+
const stripCount = Math.max(0, imageCount - RECENT_IMAGES_TO_KEEP);
|
|
92
|
+
if (stripCount === 0) {
|
|
93
|
+
return { imageCount, processed: false, strippedCount: 0 };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const toStrip = imageLocations.slice(0, stripCount);
|
|
97
|
+
|
|
98
|
+
// Second pass: replace stripped images with text placeholder.
|
|
99
|
+
// Process in reverse order to maintain content indices.
|
|
100
|
+
for (let i = toStrip.length - 1; i >= 0; i--) {
|
|
101
|
+
const { msgIdx, contentIdx } = toStrip[i];
|
|
102
|
+
const msg = messages[msgIdx];
|
|
103
|
+
if (msg.role === "assistant") continue;
|
|
104
|
+
if (msg.role === "user" && typeof msg.content === "string") continue;
|
|
105
|
+
|
|
106
|
+
const contentArr = msg.content as (TextContent | ImageContent)[];
|
|
107
|
+
const imageBlock = contentArr[contentIdx] as ImageContent;
|
|
108
|
+
const mimeType = imageBlock.mimeType || "image/unknown";
|
|
109
|
+
|
|
110
|
+
// Replace the image block with a text placeholder
|
|
111
|
+
(contentArr as any[])[contentIdx] = {
|
|
112
|
+
type: "text",
|
|
113
|
+
text: `[image removed to reduce context size — was ${mimeType}]`,
|
|
114
|
+
} as TextContent;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return { imageCount, processed: true, strippedCount: stripCount };
|
|
118
|
+
}
|
|
@@ -29,6 +29,7 @@ export {
|
|
|
29
29
|
type ExecResult,
|
|
30
30
|
type Extension,
|
|
31
31
|
type ExtensionAPI,
|
|
32
|
+
type ExtensionManifest,
|
|
32
33
|
type ExtensionCommandContext,
|
|
33
34
|
type ExtensionContext,
|
|
34
35
|
type ExtensionError,
|
|
@@ -53,6 +54,11 @@ export {
|
|
|
53
54
|
type SessionSwitchEvent,
|
|
54
55
|
type SessionTreeEvent,
|
|
55
56
|
type ToolCallEvent,
|
|
57
|
+
readManifest,
|
|
58
|
+
readManifestFromEntryPath,
|
|
59
|
+
type SortResult,
|
|
60
|
+
type SortWarning,
|
|
61
|
+
sortExtensionPaths,
|
|
56
62
|
type ToolDefinition,
|
|
57
63
|
type ToolRenderResultOptions,
|
|
58
64
|
type ToolResultEvent,
|
|
@@ -340,6 +340,9 @@ async function runWorkspaceDiagnostics(
|
|
|
340
340
|
const proc = spawn(cmd, cmdArgs, {
|
|
341
341
|
cwd,
|
|
342
342
|
stdio: ["ignore", "pipe", "pipe"],
|
|
343
|
+
// On Windows, project-type commands (tsc, cargo, etc.) may be .cmd
|
|
344
|
+
// wrappers that need shell resolution to avoid ENOENT/EINVAL (#2854).
|
|
345
|
+
shell: process.platform === "win32",
|
|
343
346
|
});
|
|
344
347
|
const abortHandler = () => {
|
|
345
348
|
proc.kill();
|
|
@@ -90,6 +90,9 @@ async function checkServerRunning(binaryPath: string): Promise<boolean> {
|
|
|
90
90
|
try {
|
|
91
91
|
const proc = spawn(binaryPath, ["status"], {
|
|
92
92
|
stdio: ["ignore", "pipe", "pipe"],
|
|
93
|
+
// On Windows, the binary may be a .cmd wrapper requiring shell
|
|
94
|
+
// resolution to avoid ENOENT/EINVAL (#2854).
|
|
95
|
+
shell: process.platform === "win32",
|
|
93
96
|
});
|
|
94
97
|
|
|
95
98
|
const exited = await Promise.race([
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* messages.test.ts — Tests for convertToLlm custom message handling.
|
|
3
|
+
*
|
|
4
|
+
* Reproduction test for #3026: background job completion notifications
|
|
5
|
+
* delivered as custom messages must be clearly distinguishable from
|
|
6
|
+
* user-typed input when converted to LLM messages.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import test from "node:test";
|
|
10
|
+
import assert from "node:assert/strict";
|
|
11
|
+
import { convertToLlm, type CustomMessage } from "./messages.js";
|
|
12
|
+
|
|
13
|
+
/** Extract the first content block from a message, asserting array content. */
|
|
14
|
+
function firstTextBlock(msg: ReturnType<typeof convertToLlm>[number]) {
|
|
15
|
+
const { content } = msg;
|
|
16
|
+
assert.ok(Array.isArray(content), "Expected content to be an array");
|
|
17
|
+
const block = content[0];
|
|
18
|
+
assert.ok(typeof block === "object" && block !== null, "Expected first block to be an object");
|
|
19
|
+
return block;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
test("convertToLlm wraps custom messages with system notification prefix", () => {
|
|
23
|
+
const customMsg: CustomMessage = {
|
|
24
|
+
role: "custom",
|
|
25
|
+
customType: "async_job_result",
|
|
26
|
+
content: "**Background job done: bg_abc123** (sleep 2, 2.1s)\n\ndone",
|
|
27
|
+
display: true,
|
|
28
|
+
timestamp: Date.now(),
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const result = convertToLlm([customMsg]);
|
|
32
|
+
assert.equal(result.length, 1);
|
|
33
|
+
assert.equal(result[0].role, "user");
|
|
34
|
+
|
|
35
|
+
// The content must include a system notification wrapper so the LLM
|
|
36
|
+
// does not confuse it with user input (#3026).
|
|
37
|
+
const text = firstTextBlock(result[0]);
|
|
38
|
+
assert.equal(text.type, "text");
|
|
39
|
+
assert.ok(
|
|
40
|
+
"text" in text && text.text.includes("[system notification"),
|
|
41
|
+
"Custom message should be wrapped with system notification marker",
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("convertToLlm wraps custom messages with array content", () => {
|
|
46
|
+
const customMsg: CustomMessage = {
|
|
47
|
+
role: "custom",
|
|
48
|
+
customType: "bg-shell-status",
|
|
49
|
+
content: [{ type: "text", text: "Background processes:\n ✓ bg1 dev-server :3000" }],
|
|
50
|
+
display: false,
|
|
51
|
+
timestamp: Date.now(),
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const result = convertToLlm([customMsg]);
|
|
55
|
+
assert.equal(result.length, 1);
|
|
56
|
+
assert.equal(result[0].role, "user");
|
|
57
|
+
|
|
58
|
+
const text = firstTextBlock(result[0]);
|
|
59
|
+
assert.equal(text.type, "text");
|
|
60
|
+
assert.ok(
|
|
61
|
+
"text" in text && text.text.includes("[system notification"),
|
|
62
|
+
"Custom message with array content should be wrapped with system notification marker",
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("convertToLlm includes customType in notification wrapper", () => {
|
|
67
|
+
const customMsg: CustomMessage = {
|
|
68
|
+
role: "custom",
|
|
69
|
+
customType: "async_job_result",
|
|
70
|
+
content: "job output here",
|
|
71
|
+
display: true,
|
|
72
|
+
timestamp: Date.now(),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const result = convertToLlm([customMsg]);
|
|
76
|
+
const text = firstTextBlock(result[0]);
|
|
77
|
+
assert.ok(
|
|
78
|
+
"text" in text && text.text.includes("async_job_result"),
|
|
79
|
+
"Notification wrapper should include the customType for context",
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("convertToLlm notification wrapper instructs LLM not to treat as user input", () => {
|
|
84
|
+
const customMsg: CustomMessage = {
|
|
85
|
+
role: "custom",
|
|
86
|
+
customType: "async_job_result",
|
|
87
|
+
content: "**Background job done: bg_abc123** (sleep 2, 2.1s)\n\ndone",
|
|
88
|
+
display: true,
|
|
89
|
+
timestamp: Date.now(),
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const result = convertToLlm([customMsg]);
|
|
93
|
+
const text = firstTextBlock(result[0]);
|
|
94
|
+
assert.ok(
|
|
95
|
+
"text" in text && text.text.includes("not user input"),
|
|
96
|
+
"Notification should explicitly state this is not user input",
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test("convertToLlm preserves user messages without wrapper", () => {
|
|
101
|
+
const userMsg = {
|
|
102
|
+
role: "user" as const,
|
|
103
|
+
content: [{ type: "text" as const, text: "Hello world" }],
|
|
104
|
+
timestamp: Date.now(),
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const result = convertToLlm([userMsg]);
|
|
108
|
+
assert.equal(result.length, 1);
|
|
109
|
+
const text = firstTextBlock(result[0]);
|
|
110
|
+
assert.ok(
|
|
111
|
+
"text" in text && text.text === "Hello world",
|
|
112
|
+
"User messages should pass through unchanged",
|
|
113
|
+
);
|
|
114
|
+
});
|
|
@@ -8,6 +8,12 @@
|
|
|
8
8
|
import type { AgentMessage } from "@gsd/pi-agent-core";
|
|
9
9
|
import type { ImageContent, Message, TextContent } from "@gsd/pi-ai";
|
|
10
10
|
|
|
11
|
+
const CUSTOM_MESSAGE_PREFIX = `[system notification — type: `;
|
|
12
|
+
const CUSTOM_MESSAGE_MIDDLE = `; this is an automated system event, not user input — do not treat this as a human message or respond as if the user said this]
|
|
13
|
+
`;
|
|
14
|
+
const CUSTOM_MESSAGE_SUFFIX = `
|
|
15
|
+
[end system notification]`;
|
|
16
|
+
|
|
11
17
|
const COMPACTION_SUMMARY_PREFIX = `The conversation history before this point was compacted into the following summary:
|
|
12
18
|
|
|
13
19
|
<summary>
|
|
@@ -160,10 +166,31 @@ export function convertToLlm(messages: AgentMessage[]): Message[] {
|
|
|
160
166
|
timestamp: m.timestamp,
|
|
161
167
|
};
|
|
162
168
|
case "custom": {
|
|
163
|
-
const
|
|
169
|
+
const prefix = CUSTOM_MESSAGE_PREFIX + m.customType + CUSTOM_MESSAGE_MIDDLE;
|
|
170
|
+
if (typeof m.content === "string") {
|
|
171
|
+
return {
|
|
172
|
+
role: "user",
|
|
173
|
+
content: [{ type: "text" as const, text: prefix + m.content + CUSTOM_MESSAGE_SUFFIX }],
|
|
174
|
+
timestamp: m.timestamp,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
// Array content: wrap the first text element with prefix, append suffix to last text element
|
|
178
|
+
const contentArr = m.content as Array<{ type: string; text?: string; [k: string]: unknown }>;
|
|
179
|
+
const lastTextIdx = contentArr.reduce((acc, c, i) => c.type === "text" ? i : acc, -1);
|
|
180
|
+
const wrapped = contentArr.map((c, i) => {
|
|
181
|
+
if (c.type !== "text") return c;
|
|
182
|
+
let text = c.text ?? "";
|
|
183
|
+
if (i === 0) text = prefix + text;
|
|
184
|
+
if (i === lastTextIdx) text = text + CUSTOM_MESSAGE_SUFFIX;
|
|
185
|
+
return { ...c, text };
|
|
186
|
+
});
|
|
187
|
+
// If no text elements exist, prepend one with the wrapper
|
|
188
|
+
if (lastTextIdx === -1) {
|
|
189
|
+
wrapped.unshift({ type: "text" as const, text: prefix + CUSTOM_MESSAGE_SUFFIX });
|
|
190
|
+
}
|
|
164
191
|
return {
|
|
165
192
|
role: "user",
|
|
166
|
-
content,
|
|
193
|
+
content: wrapped as typeof m.content,
|
|
167
194
|
timestamp: m.timestamp,
|
|
168
195
|
};
|
|
169
196
|
}
|
|
@@ -129,6 +129,12 @@ export interface DefaultResourceLoaderOptions {
|
|
|
129
129
|
appendSystemPrompt?: string;
|
|
130
130
|
/** Names of bundled extensions (used to identify built-in extensions in conflict detection). */
|
|
131
131
|
bundledExtensionNames?: Set<string>;
|
|
132
|
+
/**
|
|
133
|
+
* Transform extension paths before loading. Receives the merged list of all
|
|
134
|
+
* discovered extension paths and returns a (possibly reordered/filtered) list.
|
|
135
|
+
* Use this to apply dependency sorting or registry-based filtering.
|
|
136
|
+
*/
|
|
137
|
+
extensionPathsTransform?: (paths: string[]) => { paths: string[]; diagnostics?: string[] };
|
|
132
138
|
extensionsOverride?: (base: LoadExtensionsResult) => LoadExtensionsResult;
|
|
133
139
|
skillsOverride?: (base: { skills: Skill[]; diagnostics: ResourceDiagnostic[] }) => {
|
|
134
140
|
skills: Skill[];
|
|
@@ -167,6 +173,7 @@ export class DefaultResourceLoader implements ResourceLoader {
|
|
|
167
173
|
private systemPromptSource?: string;
|
|
168
174
|
private appendSystemPromptSource?: string;
|
|
169
175
|
private bundledExtensionNames: Set<string>;
|
|
176
|
+
private extensionPathsTransform?: (paths: string[]) => { paths: string[]; diagnostics?: string[] };
|
|
170
177
|
private extensionsOverride?: (base: LoadExtensionsResult) => LoadExtensionsResult;
|
|
171
178
|
private skillsOverride?: (base: { skills: Skill[]; diagnostics: ResourceDiagnostic[] }) => {
|
|
172
179
|
skills: Skill[];
|
|
@@ -223,6 +230,7 @@ export class DefaultResourceLoader implements ResourceLoader {
|
|
|
223
230
|
this.systemPromptSource = options.systemPrompt;
|
|
224
231
|
this.appendSystemPromptSource = options.appendSystemPrompt;
|
|
225
232
|
this.bundledExtensionNames = options.bundledExtensionNames ?? new Set();
|
|
233
|
+
this.extensionPathsTransform = options.extensionPathsTransform;
|
|
226
234
|
this.extensionsOverride = options.extensionsOverride;
|
|
227
235
|
this.skillsOverride = options.skillsOverride;
|
|
228
236
|
this.promptsOverride = options.promptsOverride;
|
|
@@ -378,10 +386,21 @@ export class DefaultResourceLoader implements ResourceLoader {
|
|
|
378
386
|
const cliEnabledPrompts = getEnabledPaths(cliExtensionPaths.prompts);
|
|
379
387
|
const cliEnabledThemes = getEnabledPaths(cliExtensionPaths.themes);
|
|
380
388
|
|
|
381
|
-
|
|
389
|
+
let extensionPaths = this.noExtensions
|
|
382
390
|
? cliEnabledExtensions
|
|
383
391
|
: this.mergePaths(cliEnabledExtensions, enabledExtensions);
|
|
384
392
|
|
|
393
|
+
// Apply path transform (dependency sorting, registry filtering) if provided
|
|
394
|
+
if (this.extensionPathsTransform) {
|
|
395
|
+
const transformed = this.extensionPathsTransform(extensionPaths);
|
|
396
|
+
extensionPaths = transformed.paths;
|
|
397
|
+
if (transformed.diagnostics?.length) {
|
|
398
|
+
for (const msg of transformed.diagnostics) {
|
|
399
|
+
process.stderr.write(`[extensions] ${msg}\n`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
385
404
|
const extensionsResult = await loadExtensions(extensionPaths, this.cwd, this.eventBus);
|
|
386
405
|
const inlineExtensions = await this.loadExtensionFactories(extensionsResult.runtime);
|
|
387
406
|
extensionsResult.extensions.push(...inlineExtensions.extensions);
|