gsd-pi 2.80.0-dev.c5f2443b3 → 2.80.0-dev.f55d16d13
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/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +2 -2
- package/dist/resources/extensions/github-sync/templates.js +39 -8
- package/dist/resources/extensions/gsd/auto/loop.js +16 -9
- package/dist/resources/extensions/gsd/auto/phases.js +37 -30
- package/dist/resources/extensions/gsd/auto/run-unit.js +19 -15
- package/dist/resources/extensions/gsd/auto-dashboard.js +51 -15
- package/dist/resources/extensions/gsd/auto-dispatch.js +10 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +10 -10
- package/dist/resources/extensions/gsd/auto-prompts.js +111 -1
- package/dist/resources/extensions/gsd/auto-recovery.js +154 -8
- package/dist/resources/extensions/gsd/auto-start.js +2 -3
- package/dist/resources/extensions/gsd/auto.js +9 -1
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +15 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +11 -1
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +129 -1
- package/dist/resources/extensions/gsd/clean-root-preflight.js +42 -4
- package/dist/resources/extensions/gsd/commands-extract-learnings.js +17 -12
- package/dist/resources/extensions/gsd/custom-workflow-engine.js +22 -2
- package/dist/resources/extensions/gsd/db-base-schema.js +14 -0
- package/dist/resources/extensions/gsd/db-migration-steps.js +16 -0
- package/dist/resources/extensions/gsd/detection.js +106 -0
- package/dist/resources/extensions/gsd/graph.js +9 -3
- package/dist/resources/extensions/gsd/gsd-db.js +102 -2
- package/dist/resources/extensions/gsd/guided-flow.js +2 -2
- package/dist/resources/extensions/gsd/pr-evidence.js +57 -16
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +7 -8
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +10 -2
- package/dist/resources/extensions/gsd/working-output-messages.js +64 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +16 -14
- 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 +11 -11
- 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.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/onboarding/route.js +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 +11 -11
- package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
- 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 +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/{8336.6f6f30e410419aff.js → 8336.631939fb583761fa.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-d82dbee6356c1733.js → webpack-0481f1221120a7c6.js} +1 -1
- package/package.json +10 -6
- package/packages/contracts/package.json +1 -1
- package/packages/pi-ai/dist/models/fake-model.d.ts +12 -0
- package/packages/pi-ai/dist/models/fake-model.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/fake-model.js +27 -0
- package/packages/pi-ai/dist/models/fake-model.js.map +1 -0
- package/packages/pi-ai/dist/models/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/index.js +8 -0
- package/packages/pi-ai/dist/models/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/fake.d.ts +42 -0
- package/packages/pi-ai/dist/providers/fake.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/fake.js +319 -0
- package/packages/pi-ai/dist/providers/fake.js.map +1 -0
- package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/register-builtins.js +24 -0
- package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
- package/packages/pi-ai/src/models/fake-model.ts +30 -0
- package/packages/pi-ai/src/models/index.ts +9 -0
- package/packages/pi-ai/src/providers/fake.ts +376 -0
- package/packages/pi-ai/src/providers/register-builtins.ts +23 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +74 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +14 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +97 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +5 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
- package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js +6 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +54 -15
- 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/adaptive-layout.d.ts +26 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +112 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +51 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +10 -9
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +7 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +16 -0
- 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 +106 -17
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.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 +60 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +40 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -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 +1 -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 +3 -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 +23 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +20 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js +79 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js +13 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +18 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +36 -27
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js +18 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +48 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -0
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +87 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +108 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +16 -1
- package/packages/pi-coding-agent/src/core/model-registry.ts +4 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +12 -0
- package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +7 -5
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +78 -15
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +59 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +160 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +10 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +10 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +118 -17
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +43 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +75 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +25 -0
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.test.ts +95 -0
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +24 -1
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +13 -0
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +32 -2
- package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +36 -27
- package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +65 -0
- package/packages/pi-coding-agent/src/modes/interactive/tui-mode.ts +29 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/style.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/style.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/style.test.js +63 -0
- package/packages/pi-tui/dist/__tests__/style.test.js.map +1 -0
- package/packages/pi-tui/dist/__tests__/tui.test.js +24 -3
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/index.d.ts +1 -0
- package/packages/pi-tui/dist/index.d.ts.map +1 -1
- package/packages/pi-tui/dist/index.js +2 -0
- package/packages/pi-tui/dist/index.js.map +1 -1
- package/packages/pi-tui/dist/style.d.ts +41 -0
- package/packages/pi-tui/dist/style.d.ts.map +1 -0
- package/packages/pi-tui/dist/style.js +158 -0
- package/packages/pi-tui/dist/style.js.map +1 -0
- package/packages/pi-tui/dist/tui.d.ts +0 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +3 -8
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/__tests__/style.test.ts +76 -0
- package/packages/pi-tui/src/__tests__/tui.test.ts +29 -3
- package/packages/pi-tui/src/index.ts +9 -0
- package/packages/pi-tui/src/style.ts +225 -0
- package/packages/pi-tui/src/tui.ts +3 -8
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/pkg/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
- package/pkg/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme-schema.js +13 -0
- package/pkg/dist/modes/interactive/theme/theme-schema.js.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme.js +18 -1
- package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.js +36 -27
- package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
- package/src/resources/GSD-WORKFLOW.md +2 -2
- package/src/resources/extensions/github-sync/templates.ts +38 -8
- package/src/resources/extensions/github-sync/tests/inline-code.test.ts +66 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/loop.ts +17 -10
- package/src/resources/extensions/gsd/auto/phases.ts +42 -28
- package/src/resources/extensions/gsd/auto/run-unit.ts +24 -14
- package/src/resources/extensions/gsd/auto-dashboard.ts +57 -8
- package/src/resources/extensions/gsd/auto-dispatch.ts +17 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +10 -10
- package/src/resources/extensions/gsd/auto-prompts.ts +116 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +153 -7
- package/src/resources/extensions/gsd/auto-start.ts +7 -6
- package/src/resources/extensions/gsd/auto.ts +12 -1
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +17 -1
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +135 -1
- package/src/resources/extensions/gsd/clean-root-preflight.ts +41 -3
- package/src/resources/extensions/gsd/commands-extract-learnings.ts +17 -12
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +24 -1
- package/src/resources/extensions/gsd/db-base-schema.ts +15 -0
- package/src/resources/extensions/gsd/db-migration-steps.ts +17 -0
- package/src/resources/extensions/gsd/detection.ts +128 -0
- package/src/resources/extensions/gsd/graph.ts +12 -5
- package/src/resources/extensions/gsd/gsd-db.ts +119 -1
- package/src/resources/extensions/gsd/guided-flow.ts +2 -2
- package/src/resources/extensions/gsd/pr-evidence.ts +63 -5
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +7 -8
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -2
- package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +84 -5
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +170 -1
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +88 -2
- package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +112 -6
- package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +40 -2
- package/src/resources/extensions/gsd/tests/db-migration-steps.integration.test.ts +428 -0
- package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/detection.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-basic.md +52 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-empty-optionals.md +42 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +55 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +60 -0
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/pr-evidence-equivalence.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/pr-evidence-hardening.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +46 -2
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/working-output-messages.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +37 -6
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +9 -2
- package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +179 -0
- package/src/resources/extensions/gsd/working-output-messages.ts +120 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +15 -4
- package/packages/contracts/tsconfig.tsbuildinfo +0 -1
- /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → mPZbi5BH9dwokaPZlrYuQ}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → mPZbi5BH9dwokaPZlrYuQ}/_ssgManifest.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-mode.test.js","sourceRoot":"","sources":["../../../src/modes/interactive/tui-mode.test.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAE/C,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,SAAS,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAEzB,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC/B,IAAI,CAAC,wCAAwC,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,KAAK,CACX,cAAc,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,CAAC,EAC1F,OAAO,CACP,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iDAAiD,EAAE,GAAG,EAAE;QAC5D,MAAM,CAAC,KAAK,CACX,cAAc,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,sBAAsB,EAAE,CAAC,EACjH,SAAS,CACT,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,wDAAwD,EAAE,GAAG,EAAE;QACnE,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,aAAa,EAAE,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACtE,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,aAAa,EAAE,GAAG,EAAE,QAAQ,EAAE,sBAAsB,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;QACrG,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,aAAa,EAAE,GAAG,EAAE,QAAQ,EAAE,oBAAoB,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;IACpG,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC9E,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,aAAa,EAAE,GAAG,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;QACrF,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,aAAa,EAAE,GAAG,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IAC7F,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gDAAgD,EAAE,GAAG,EAAE;QAC3D,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACxC,IAAI,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC/D,MAAM,MAAM,GAAG,IAAI,uBAAuB,CAAC,GAAG,EAAE,CAAC,CAAC;YACjD,QAAQ,EAAE,UAAU;YACpB,eAAe,EAAE,CAAC;YAClB,QAAQ,EAAE,cAAc;YACxB,WAAW,EAAE,MAAM;YACnB,GAAG,EAAE,wBAAwB;SAC7B,CAAC,CAAC,CAAC;QAEJ,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAEhD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,gDAAgD,CAAC,CAAC;QAChF,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,EAAE,8BAA8B,CAAC,CAAC;QACrG,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,+BAA+B,CAAC,CAAC;QAC3F,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,EAAE,wCAAwC,CAAC,CAAC;QACrG,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,oDAAoD,CAAC,CAAC;IAC7G,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["// GSD2 - Tests for adaptive TUI mode selection\n\nimport assert from \"node:assert/strict\";\nimport { describe, test } from \"node:test\";\nimport stripAnsi from \"strip-ansi\";\n\nimport { AdaptiveLayoutComponent } from \"./components/adaptive-layout.js\";\nimport { initTheme } from \"./theme/theme.js\";\nimport { resolveTuiMode } from \"./tui-mode.js\";\n\ninitTheme(\"dark\", false);\n\ndescribe(\"resolveTuiMode\", () => {\n\ttest(\"explicit overrides beat auto selection\", () => {\n\t\tassert.equal(\n\t\t\tresolveTuiMode({ terminalWidth: 60, override: \"debug\", gsdPhase: \"validating-milestone\" }),\n\t\t\t\"debug\",\n\t\t);\n\t});\n\n\ttest(\"prioritizes compact layouts on narrow terminals\", () => {\n\t\tassert.equal(\n\t\t\tresolveTuiMode({ terminalWidth: 60, override: \"auto\", hasBlockingError: true, gsdPhase: \"validating-milestone\" }),\n\t\t\t\"compact\",\n\t\t);\n\t});\n\n\ttest(\"uses debug mode for blocking errors on roomy terminals\", () => {\n\t\tassert.equal(resolveTuiMode({ terminalWidth: 100, hasBlockingError: true }), \"debug\");\n\t});\n\n\ttest(\"uses validation mode for validation and completion phases\", () => {\n\t\tassert.equal(resolveTuiMode({ terminalWidth: 100, gsdPhase: \"validating-milestone\" }), \"validation\");\n\t\tassert.equal(resolveTuiMode({ terminalWidth: 100, gsdPhase: \"complete-milestone\" }), \"validation\");\n\t});\n\n\ttest(\"uses workflow mode when tools or non-validation phases are active\", () => {\n\t\tassert.equal(resolveTuiMode({ terminalWidth: 100, activeToolCount: 1 }), \"workflow\");\n\t\tassert.equal(resolveTuiMode({ terminalWidth: 100, gsdPhase: \"execute-phase\" }), \"workflow\");\n\t});\n\n\ttest(\"falls back to chat mode for plain conversation\", () => {\n\t\tassert.equal(resolveTuiMode({ terminalWidth: 100 }), \"chat\");\n\t});\n});\n\ndescribe(\"AdaptiveLayoutComponent\", () => {\n\ttest(\"renders workflow layout with prototype rule frames\", () => {\n\t\tconst layout = new AdaptiveLayoutComponent(() => ({\n\t\t\toverride: \"workflow\",\n\t\t\tactiveToolCount: 2,\n\t\t\tgsdPhase: \"execute-task\",\n\t\t\tsessionName: \"main\",\n\t\t\tcwd: \"/Users/example/project\",\n\t\t}));\n\n\t\tconst plain = layout.render(120).map(stripAnsi);\n\n\t\tassert.match(plain[0], /^─+/, \"workflow layout should start with a rule frame\");\n\t\tassert.ok(plain.some((line) => line.includes(\"GSD Command Center\")), \"workflow title should render\");\n\t\tassert.ok(plain.some((line) => line.includes(\"signals\")), \"inspector title should render\");\n\t\tassert.ok(plain.some((line) => line.includes(\"│ Active\")), \"body rows should keep prototype gutter\");\n\t\tassert.ok(!plain.some((line) => /[╭╮╰╯]/.test(line)), \"workflow layout should not use rounded box corners\");\n\t});\n});\n"]}
|
|
@@ -1002,6 +1002,93 @@ test("chat-controller does not pin when there are no tool calls", async () => {
|
|
|
1002
1002
|
assert.equal(host.pinnedMessageContainer.children.length, 0, "pinned zone should stay empty without tool calls");
|
|
1003
1003
|
});
|
|
1004
1004
|
|
|
1005
|
+
test("chat-controller rolls up only contiguous low-signal tool runs on message_end", async () => {
|
|
1006
|
+
(globalThis as any)[Symbol.for("@gsd/pi-coding-agent:theme")] = {
|
|
1007
|
+
fg: (_key: string, text: string) => text,
|
|
1008
|
+
bg: (_key: string, text: string) => text,
|
|
1009
|
+
bold: (text: string) => text,
|
|
1010
|
+
italic: (text: string) => text,
|
|
1011
|
+
truncate: (text: string) => text,
|
|
1012
|
+
};
|
|
1013
|
+
|
|
1014
|
+
const host = createHost();
|
|
1015
|
+
host.getMarkdownThemeWithSettings = () => ({});
|
|
1016
|
+
|
|
1017
|
+
const t1 = { type: "toolCall", id: "t1", name: "bash", arguments: { command: "true" } };
|
|
1018
|
+
const t2 = { type: "toolCall", id: "t2", name: "bash", arguments: { command: "true" } };
|
|
1019
|
+
const text = { type: "text", text: "middle output" };
|
|
1020
|
+
const t3 = { type: "toolCall", id: "t3", name: "read", arguments: { path: "/tmp/a" } };
|
|
1021
|
+
const t4 = { type: "toolCall", id: "t4", name: "read", arguments: { path: "/tmp/b" } };
|
|
1022
|
+
const content = [t1, t2, text, t3, t4];
|
|
1023
|
+
|
|
1024
|
+
await handleAgentEvent(host, { type: "message_start", message: makeAssistant([]) } as any);
|
|
1025
|
+
await handleAgentEvent(host, {
|
|
1026
|
+
type: "message_update",
|
|
1027
|
+
message: makeAssistant(content),
|
|
1028
|
+
assistantMessageEvent: {
|
|
1029
|
+
type: "text_delta",
|
|
1030
|
+
contentIndex: 2,
|
|
1031
|
+
delta: text.text,
|
|
1032
|
+
partial: makeAssistant(content),
|
|
1033
|
+
},
|
|
1034
|
+
} as any);
|
|
1035
|
+
|
|
1036
|
+
for (const tool of [t1, t2, t3, t4]) {
|
|
1037
|
+
await handleAgentEvent(host, {
|
|
1038
|
+
type: "tool_execution_end",
|
|
1039
|
+
toolCallId: tool.id,
|
|
1040
|
+
isError: false,
|
|
1041
|
+
result: { content: [], details: {} },
|
|
1042
|
+
} as any);
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
await handleAgentEvent(host, { type: "message_end", message: makeAssistant(content) } as any);
|
|
1046
|
+
|
|
1047
|
+
assert.equal(host.chatContainer.children.length, 3, "two separated tool runs should become two summaries around text");
|
|
1048
|
+
assert.equal(host.chatContainer.children[0]?.constructor?.name, "ToolPhaseSummaryComponent");
|
|
1049
|
+
assert.equal(host.chatContainer.children[1]?.constructor?.name, "AssistantMessageComponent");
|
|
1050
|
+
assert.equal(host.chatContainer.children[2]?.constructor?.name, "ToolPhaseSummaryComponent");
|
|
1051
|
+
assert.match(host.chatContainer.children[0].render(120).join("\n"), /Setup \/ shell 2 actions/);
|
|
1052
|
+
assert.match(host.chatContainer.children[2].render(120).join("\n"), /Context reads 2 actions/);
|
|
1053
|
+
assert.equal(host.chatContainer._prevRender, null, "summary reposition must invalidate the chat container render cache");
|
|
1054
|
+
});
|
|
1055
|
+
|
|
1056
|
+
test("chat-controller rolls up low-signal direct tool execution events on agent_end", async () => {
|
|
1057
|
+
(globalThis as any)[Symbol.for("@gsd/pi-coding-agent:theme")] = {
|
|
1058
|
+
fg: (_key: string, text: string) => text,
|
|
1059
|
+
bg: (_key: string, text: string) => text,
|
|
1060
|
+
bold: (text: string) => text,
|
|
1061
|
+
italic: (text: string) => text,
|
|
1062
|
+
truncate: (text: string) => text,
|
|
1063
|
+
};
|
|
1064
|
+
|
|
1065
|
+
const host = createHost();
|
|
1066
|
+
host.getMarkdownThemeWithSettings = () => ({});
|
|
1067
|
+
|
|
1068
|
+
for (const toolCallId of ["bash-1", "bash-2", "bash-3"]) {
|
|
1069
|
+
await handleAgentEvent(host, {
|
|
1070
|
+
type: "tool_execution_start",
|
|
1071
|
+
toolCallId,
|
|
1072
|
+
toolName: "bash",
|
|
1073
|
+
args: { command: "true" },
|
|
1074
|
+
} as any);
|
|
1075
|
+
await handleAgentEvent(host, {
|
|
1076
|
+
type: "tool_execution_end",
|
|
1077
|
+
toolCallId,
|
|
1078
|
+
isError: false,
|
|
1079
|
+
result: { content: [], details: {} },
|
|
1080
|
+
} as any);
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
assert.equal(host.chatContainer.children.length, 3, "direct tool events render as individual rows while running");
|
|
1084
|
+
|
|
1085
|
+
await handleAgentEvent(host, { type: "agent_end" } as any);
|
|
1086
|
+
|
|
1087
|
+
assert.equal(host.chatContainer.children.length, 1, "direct low-signal tool rows should roll up on agent_end");
|
|
1088
|
+
assert.equal(host.chatContainer.children[0]?.constructor?.name, "ToolPhaseSummaryComponent");
|
|
1089
|
+
assert.match(host.chatContainer.children[0].render(120).join("\n"), /Setup \/ shell 3 actions/);
|
|
1090
|
+
});
|
|
1091
|
+
|
|
1005
1092
|
// Regression test for issue #4144: interleaved text/tool content must render in content[] index order.
|
|
1006
1093
|
// Stream: [text "A", toolCall T1, text "B", toolCall T2, text "C"]
|
|
1007
1094
|
// Expected chatContainer order: textRun(A), toolExec(T1), textRun(B), toolExec(T2), textRun(C)
|
|
@@ -102,6 +102,60 @@ describe("ExtensionRunner.emitToolCall", () => {
|
|
|
102
102
|
assert.equal(errors[0].event, "tool_call");
|
|
103
103
|
assert.equal(errors[0].extensionPath, "/test/throwing-ext");
|
|
104
104
|
});
|
|
105
|
+
|
|
106
|
+
it("preserves shutdown in tool_call handler context", async (t) => {
|
|
107
|
+
const dir = mkdtempSync(join(tmpdir(), "runner-test-"));
|
|
108
|
+
t.after(() => {
|
|
109
|
+
rmSync(dir, { recursive: true, force: true });
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const sessionManager = SessionManager.create(dir, dir);
|
|
113
|
+
const authStorage = AuthStorage.create();
|
|
114
|
+
const modelRegistry = new ModelRegistry(authStorage, join(dir, "models.json"));
|
|
115
|
+
const runtime = makeMinimalRuntime();
|
|
116
|
+
let shutdownCount = 0;
|
|
117
|
+
const handlers = new Map();
|
|
118
|
+
handlers.set("tool_call", [
|
|
119
|
+
async (_event: unknown, ctx: { shutdown: () => void }) => {
|
|
120
|
+
ctx.shutdown();
|
|
121
|
+
},
|
|
122
|
+
]);
|
|
123
|
+
const extension = {
|
|
124
|
+
path: "/test/shutdown-on-tool-call",
|
|
125
|
+
handlers,
|
|
126
|
+
commands: new Map(),
|
|
127
|
+
shortcuts: new Map(),
|
|
128
|
+
tools: new Map(),
|
|
129
|
+
flags: new Map(),
|
|
130
|
+
diagnostics: [],
|
|
131
|
+
} as unknown as Extension;
|
|
132
|
+
const runner = new ExtensionRunner([extension], runtime, dir, sessionManager, modelRegistry);
|
|
133
|
+
runner.bindCore({} as any, {
|
|
134
|
+
getModel: () => undefined,
|
|
135
|
+
isIdle: () => true,
|
|
136
|
+
abort: () => {},
|
|
137
|
+
hasPendingMessages: () => false,
|
|
138
|
+
shutdown: () => {
|
|
139
|
+
shutdownCount += 1;
|
|
140
|
+
},
|
|
141
|
+
getContextUsage: () => undefined,
|
|
142
|
+
compact: () => {},
|
|
143
|
+
getSystemPrompt: () => "",
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const errors: any[] = [];
|
|
147
|
+
runner.onError((err) => errors.push(err));
|
|
148
|
+
|
|
149
|
+
await runner.emitToolCall({
|
|
150
|
+
type: "tool_call",
|
|
151
|
+
toolCallId: "test-123",
|
|
152
|
+
toolName: "test_tool",
|
|
153
|
+
input: {},
|
|
154
|
+
} as ToolCallEvent);
|
|
155
|
+
|
|
156
|
+
assert.equal(shutdownCount, 1);
|
|
157
|
+
assert.equal(errors.length, 0);
|
|
158
|
+
});
|
|
105
159
|
});
|
|
106
160
|
|
|
107
161
|
describe("ExtensionRunner.createContext", () => {
|
|
@@ -127,6 +181,60 @@ describe("ExtensionRunner.createContext", () => {
|
|
|
127
181
|
assert.equal(runner.createContext().cwd, realProjectDir);
|
|
128
182
|
assert.equal(runner.createCommandContext().cwd, realProjectDir);
|
|
129
183
|
});
|
|
184
|
+
|
|
185
|
+
it("does not let lifecycle event handlers close the TUI", async (t) => {
|
|
186
|
+
const dir = mkdtempSync(join(tmpdir(), "runner-test-"));
|
|
187
|
+
t.after(() => {
|
|
188
|
+
rmSync(dir, { recursive: true, force: true });
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
const sessionManager = SessionManager.create(dir, dir);
|
|
192
|
+
const authStorage = AuthStorage.create();
|
|
193
|
+
const modelRegistry = new ModelRegistry(authStorage, join(dir, "models.json"));
|
|
194
|
+
const runtime = makeMinimalRuntime();
|
|
195
|
+
let shutdownCount = 0;
|
|
196
|
+
const handlers = new Map();
|
|
197
|
+
handlers.set("agent_end", [
|
|
198
|
+
async (_event: unknown, ctx: { shutdown: () => void }) => {
|
|
199
|
+
ctx.shutdown();
|
|
200
|
+
},
|
|
201
|
+
]);
|
|
202
|
+
const extension = {
|
|
203
|
+
path: "/test/shutdown-on-agent-end",
|
|
204
|
+
handlers,
|
|
205
|
+
commands: new Map(),
|
|
206
|
+
shortcuts: new Map(),
|
|
207
|
+
tools: new Map(),
|
|
208
|
+
flags: new Map(),
|
|
209
|
+
diagnostics: [],
|
|
210
|
+
} as unknown as Extension;
|
|
211
|
+
const runner = new ExtensionRunner([extension], runtime, dir, sessionManager, modelRegistry);
|
|
212
|
+
runner.bindCore({} as any, {
|
|
213
|
+
getModel: () => undefined,
|
|
214
|
+
isIdle: () => true,
|
|
215
|
+
abort: () => {},
|
|
216
|
+
hasPendingMessages: () => false,
|
|
217
|
+
shutdown: () => {
|
|
218
|
+
shutdownCount += 1;
|
|
219
|
+
},
|
|
220
|
+
getContextUsage: () => undefined,
|
|
221
|
+
compact: () => {},
|
|
222
|
+
getSystemPrompt: () => "",
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const errors: any[] = [];
|
|
226
|
+
runner.onError((err) => errors.push(err));
|
|
227
|
+
|
|
228
|
+
await runner.emit({ type: "agent_end", messages: [] } as any);
|
|
229
|
+
|
|
230
|
+
assert.equal(shutdownCount, 0);
|
|
231
|
+
assert.equal(errors.length, 1);
|
|
232
|
+
assert.equal(errors[0].event, "agent_end");
|
|
233
|
+
assert.match(errors[0].error, /cannot request TUI shutdown/);
|
|
234
|
+
|
|
235
|
+
runner.createCommandContext().shutdown();
|
|
236
|
+
assert.equal(shutdownCount, 1);
|
|
237
|
+
});
|
|
130
238
|
});
|
|
131
239
|
|
|
132
240
|
describe("ExtensionRunner protected commands", () => {
|
|
@@ -717,6 +717,19 @@ export class ExtensionRunner {
|
|
|
717
717
|
};
|
|
718
718
|
}
|
|
719
719
|
|
|
720
|
+
private createEventContext(eventType: string): ExtensionContext {
|
|
721
|
+
return {
|
|
722
|
+
...this.createContext(),
|
|
723
|
+
shutdown: () => {
|
|
724
|
+
throw new Error(`Extension event '${eventType}' cannot request TUI shutdown`);
|
|
725
|
+
},
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
private isShutdownGuardedEvent(eventType: string): boolean {
|
|
730
|
+
return eventType === "agent_end" || eventType === "stop" || eventType === "session_end";
|
|
731
|
+
}
|
|
732
|
+
|
|
720
733
|
createCommandContext(): ExtensionCommandContext {
|
|
721
734
|
return {
|
|
722
735
|
...this.createContext(),
|
|
@@ -757,7 +770,9 @@ export class ExtensionRunner {
|
|
|
757
770
|
getEvent: () => unknown,
|
|
758
771
|
processResult: (handlerResult: unknown, extensionPath: string) => { done: boolean },
|
|
759
772
|
): Promise<void> {
|
|
760
|
-
const ctx = this.
|
|
773
|
+
const ctx = this.isShutdownGuardedEvent(eventType)
|
|
774
|
+
? this.createEventContext(eventType)
|
|
775
|
+
: this.createContext();
|
|
761
776
|
|
|
762
777
|
for (const ext of this.extensions) {
|
|
763
778
|
const handlers = ext.handlers.get(eventType);
|
|
@@ -578,6 +578,10 @@ export class ModelRegistry {
|
|
|
578
578
|
* Defaults to "apiKey" for built-ins and providers without explicit mode.
|
|
579
579
|
*/
|
|
580
580
|
getProviderAuthMode(provider: string): ProviderAuthMode {
|
|
581
|
+
// E2E-test-only: the fake provider is keyless. Sentinel is project-
|
|
582
|
+
// internal ("gsd-fake") so it cannot collide with a real provider.
|
|
583
|
+
// See packages/pi-ai/src/providers/fake.ts.
|
|
584
|
+
if (provider === "gsd-fake") return "none";
|
|
581
585
|
const config = this.registeredProviders.get(provider);
|
|
582
586
|
if (!config) return "apiKey";
|
|
583
587
|
if (config.authMode) return config.authMode;
|
|
@@ -32,6 +32,7 @@ export interface RetrySettings {
|
|
|
32
32
|
export interface TerminalSettings {
|
|
33
33
|
showImages?: boolean; // default: true (only relevant if terminal supports images)
|
|
34
34
|
clearOnShrink?: boolean; // default: false (clear empty rows when content shrinks)
|
|
35
|
+
adaptiveMode?: AdaptiveTuiMode; // default: "auto"
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
export interface ImageSettings {
|
|
@@ -149,6 +150,7 @@ export interface HooksSettings {
|
|
|
149
150
|
}
|
|
150
151
|
|
|
151
152
|
export type TransportSetting = Transport;
|
|
153
|
+
export type AdaptiveTuiMode = "auto" | "chat" | "workflow" | "validation" | "debug" | "compact";
|
|
152
154
|
|
|
153
155
|
/**
|
|
154
156
|
* Package source for npm/git packages.
|
|
@@ -978,6 +980,16 @@ export class SettingsManager {
|
|
|
978
980
|
this.setNestedGlobalSetting("terminal", "clearOnShrink", enabled);
|
|
979
981
|
}
|
|
980
982
|
|
|
983
|
+
getAdaptiveMode(): AdaptiveTuiMode {
|
|
984
|
+
const mode = this.settings.terminal?.adaptiveMode;
|
|
985
|
+
const valid: AdaptiveTuiMode[] = ["auto", "chat", "workflow", "validation", "debug", "compact"];
|
|
986
|
+
return mode && valid.includes(mode) ? mode : "auto";
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
setAdaptiveMode(mode: AdaptiveTuiMode): void {
|
|
990
|
+
this.setNestedGlobalSetting("terminal", "adaptiveMode", mode);
|
|
991
|
+
}
|
|
992
|
+
|
|
981
993
|
getImageAutoResize(): boolean {
|
|
982
994
|
return this.settings.images?.autoResize ?? true;
|
|
983
995
|
}
|
|
@@ -38,5 +38,6 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|
|
38
38
|
{ name: "thinking", description: "Set thinking level (off/minimal/low/medium/high/xhigh)" },
|
|
39
39
|
{ name: "edit-mode", description: "Toggle edit mode (standard/hashline)" },
|
|
40
40
|
{ name: "terminal", description: "Run a shell command directly (e.g. /terminal ping -c3 1.1.1.1)" },
|
|
41
|
+
{ name: "tui", description: "Configure TUI layout mode (e.g. /tui mode workflow)" },
|
|
41
42
|
{ name: "quit", description: "Quit pi" },
|
|
42
43
|
];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// GSD2 TUI Tests - Chat frame card visual contract coverage.
|
|
1
2
|
import { test, describe } from "node:test";
|
|
2
3
|
import assert from "node:assert/strict";
|
|
3
4
|
import stripAnsi from "strip-ansi";
|
|
@@ -8,12 +9,12 @@ initTheme("dark", false);
|
|
|
8
9
|
|
|
9
10
|
// Regression tests for the "compaction" tone added to renderChatFrame.
|
|
10
11
|
// The compaction notice shares the same visual frame as user / assistant
|
|
11
|
-
// messages (top rule,
|
|
12
|
+
// messages (top rule, label header, `│ ` body prefix) but uses the
|
|
12
13
|
// purple `customMessageLabel` color key so it is visually distinct from
|
|
13
14
|
// conversation turns.
|
|
14
15
|
|
|
15
16
|
describe("renderChatFrame — compaction tone", () => {
|
|
16
|
-
test("produces a top rule,
|
|
17
|
+
test("produces a top rule, compaction header row, and a │ body margin", () => {
|
|
17
18
|
const lines = renderChatFrame(
|
|
18
19
|
["Compacted from 1,224,262 tokens (ctrl+o to expand)"],
|
|
19
20
|
60,
|
|
@@ -33,11 +34,12 @@ describe("renderChatFrame — compaction tone", () => {
|
|
|
33
34
|
// Top rule is a solid horizontal bar
|
|
34
35
|
assert.match(plain[0], /^─+$/, "first line should be the solid top rule");
|
|
35
36
|
|
|
36
|
-
// Header row contains
|
|
37
|
+
// Header row contains `compaction`
|
|
37
38
|
assert.ok(
|
|
38
|
-
plain[1].includes("
|
|
39
|
-
`expected header to contain "
|
|
39
|
+
plain[1].includes("compaction"),
|
|
40
|
+
`expected header to contain "compaction", got ${JSON.stringify(plain[1])}`,
|
|
40
41
|
);
|
|
42
|
+
assert.ok(!plain[1].includes("•"), `header should not render a bullet prefix, got ${JSON.stringify(plain[1])}`);
|
|
41
43
|
|
|
42
44
|
// Body line(s) start with `│ `
|
|
43
45
|
assert.ok(
|
package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
// GSD-2 Interactive Tool Execution Rendering Tests
|
|
1
2
|
import { describe, test } from "node:test";
|
|
2
3
|
import assert from "node:assert/strict";
|
|
3
4
|
import stripAnsi from "strip-ansi";
|
|
4
|
-
import { ToolExecutionComponent } from "../tool-execution.js";
|
|
5
|
+
import { ToolExecutionComponent, ToolPhaseSummaryComponent, type ToolExecutionPhase } from "../tool-execution.js";
|
|
5
6
|
import { initTheme } from "../../theme/theme.js";
|
|
6
7
|
|
|
7
8
|
initTheme("dark", false);
|
|
@@ -50,25 +51,85 @@ function renderToolCollapsed(
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
describe("ToolExecutionComponent", () => {
|
|
53
|
-
test("renders framed header with
|
|
54
|
+
test("renders framed header with running status while tool is partial", () => {
|
|
54
55
|
const rendered = renderToolCollapsed("mcp__demo__do_thing", { ok: true });
|
|
55
56
|
|
|
56
|
-
assert.match(rendered, /
|
|
57
|
-
assert.
|
|
57
|
+
assert.match(rendered, /demo\u00b7do_thing/);
|
|
58
|
+
assert.doesNotMatch(rendered, /Tool demo\u00b7do_thing/);
|
|
59
|
+
assert.match(rendered, /running/);
|
|
60
|
+
assert.match(rendered, /running · \d+(ms|s)/);
|
|
58
61
|
});
|
|
59
62
|
|
|
60
|
-
test("renders framed header with
|
|
63
|
+
test("renders framed header with failed status for failed tool result", () => {
|
|
61
64
|
const rendered = renderTool(
|
|
62
65
|
"mcp__demo__do_thing",
|
|
63
66
|
{ ok: true },
|
|
64
67
|
{ content: [{ type: "text", text: "boom" }], isError: true },
|
|
65
68
|
);
|
|
66
69
|
|
|
67
|
-
assert.match(rendered, /
|
|
68
|
-
assert.
|
|
70
|
+
assert.match(rendered, /demo\u00b7do_thing/);
|
|
71
|
+
assert.doesNotMatch(rendered, /Tool demo\u00b7do_thing/);
|
|
72
|
+
assert.match(rendered, /failed/);
|
|
73
|
+
assert.match(rendered, /failed · \d+(ms|s)/);
|
|
69
74
|
assert.match(rendered, /boom/);
|
|
70
75
|
});
|
|
71
76
|
|
|
77
|
+
test("collapses successful low-signal tool cards by default", () => {
|
|
78
|
+
const rendered = renderToolCollapsed(
|
|
79
|
+
"mcp__demo__noop",
|
|
80
|
+
{ ok: true },
|
|
81
|
+
{ content: [], isError: false },
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
assert.match(rendered, /success · \d+(ms|s)/);
|
|
85
|
+
assert.match(rendered, /demo\u00b7noop/);
|
|
86
|
+
assert.doesNotMatch(rendered, /Completed/);
|
|
87
|
+
assert.doesNotMatch(rendered, /ok=true/);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("exposes phase metadata for successful low-signal tool rows", () => {
|
|
91
|
+
const component = new ToolExecutionComponent(
|
|
92
|
+
"gsd_requirement_update",
|
|
93
|
+
{ id: "R001" },
|
|
94
|
+
{},
|
|
95
|
+
{ label: "Update Requirement" } as any,
|
|
96
|
+
{ requestRender() {} } as any,
|
|
97
|
+
);
|
|
98
|
+
component.updateResult({ content: [], isError: false });
|
|
99
|
+
|
|
100
|
+
assert.deepEqual(component.getRollupPhase()?.label, "Requirement writes");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test("exposes phase metadata for collapsed output-bearing generic tools", () => {
|
|
104
|
+
const component = new ToolExecutionComponent(
|
|
105
|
+
"mcp__demo__do_thing",
|
|
106
|
+
{ ok: true },
|
|
107
|
+
{},
|
|
108
|
+
undefined,
|
|
109
|
+
{ requestRender() {} } as any,
|
|
110
|
+
);
|
|
111
|
+
component.updateResult({ content: [{ type: "text", text: "important output" }], isError: false });
|
|
112
|
+
|
|
113
|
+
assert.deepEqual(component.getRollupPhase()?.label, "Other tool actions");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("renders phase-based summaries for rolled-up tool executions", () => {
|
|
117
|
+
const phases: ToolExecutionPhase[] = [
|
|
118
|
+
{ label: "Setup / shell", count: 6, durationMs: 12 },
|
|
119
|
+
{ label: "Context reads", count: 4, durationMs: 6 },
|
|
120
|
+
{ label: "Requirement writes", count: 4, durationMs: 4 },
|
|
121
|
+
{ label: "Memory lookups", count: 4, durationMs: 4 },
|
|
122
|
+
{ label: "Finalization", count: 1, durationMs: 1 },
|
|
123
|
+
];
|
|
124
|
+
const rendered = stripAnsi(new ToolPhaseSummaryComponent(phases).render(120).join("\n"));
|
|
125
|
+
|
|
126
|
+
assert.match(rendered, /Setup \/ shell 6 actions\s+success · 12ms/);
|
|
127
|
+
assert.match(rendered, /Context reads 4 actions\s+success · 6ms/);
|
|
128
|
+
assert.match(rendered, /Requirement writes 4 actions\s+success · 4ms/);
|
|
129
|
+
assert.match(rendered, /Memory lookups 4 actions\s+success · 4ms/);
|
|
130
|
+
assert.match(rendered, /Finalization 1 action\s+success · 1ms/);
|
|
131
|
+
});
|
|
132
|
+
|
|
72
133
|
test("passes failed result status to custom result renderers", () => {
|
|
73
134
|
const rendered = renderTool(
|
|
74
135
|
"gsd_requirement_save",
|
|
@@ -85,7 +146,7 @@ describe("ToolExecutionComponent", () => {
|
|
|
85
146
|
},
|
|
86
147
|
);
|
|
87
148
|
|
|
88
|
-
assert.match(rendered, /
|
|
149
|
+
assert.match(rendered, /failed/);
|
|
89
150
|
assert.match(rendered, /custom saw error/);
|
|
90
151
|
assert.doesNotMatch(rendered, /custom saw success/);
|
|
91
152
|
});
|
|
@@ -148,14 +209,16 @@ describe("ToolExecutionComponent", () => {
|
|
|
148
209
|
{ label: "Complete Slice" },
|
|
149
210
|
);
|
|
150
211
|
|
|
151
|
-
assert.match(rendered, /
|
|
212
|
+
assert.match(rendered, /Complete Slice/);
|
|
213
|
+
assert.doesNotMatch(rendered, /Tool Complete Slice/);
|
|
152
214
|
assert.doesNotMatch(rendered, /gsd_slice_complete/);
|
|
153
215
|
});
|
|
154
216
|
|
|
155
217
|
test("frame header strips gsd_ prefix and title-cases when no label is registered", () => {
|
|
156
218
|
const rendered = renderToolCollapsed("gsd_requirement_update", { id: "R005" });
|
|
157
219
|
|
|
158
|
-
assert.match(rendered, /
|
|
220
|
+
assert.match(rendered, /Requirement Update/);
|
|
221
|
+
assert.doesNotMatch(rendered, /Tool Requirement Update/);
|
|
159
222
|
assert.doesNotMatch(rendered, /gsd_requirement_update/);
|
|
160
223
|
});
|
|
161
224
|
|
|
@@ -184,7 +247,7 @@ describe("ToolExecutionComponent", () => {
|
|
|
184
247
|
assert.doesNotMatch(rendered, /…/);
|
|
185
248
|
});
|
|
186
249
|
|
|
187
|
-
test("generic fallback
|
|
250
|
+
test("generic fallback collapses successful output rows until expanded", () => {
|
|
188
251
|
const longOutput = Array.from({ length: 25 }, (_, i) => `line ${i + 1}`).join("\n");
|
|
189
252
|
const rendered = renderToolCollapsed(
|
|
190
253
|
"mcp__demo__do_thing",
|
|
@@ -192,10 +255,10 @@ describe("ToolExecutionComponent", () => {
|
|
|
192
255
|
{ content: [{ type: "text", text: longOutput }], isError: false },
|
|
193
256
|
);
|
|
194
257
|
|
|
195
|
-
assert.match(rendered, /
|
|
196
|
-
assert.match(rendered, /
|
|
197
|
-
assert.doesNotMatch(rendered, /line
|
|
198
|
-
assert.
|
|
258
|
+
assert.match(rendered, /demo\u00b7do_thing/);
|
|
259
|
+
assert.match(rendered, /success · \d+(ms|s)/);
|
|
260
|
+
assert.doesNotMatch(rendered, /line 1\b/);
|
|
261
|
+
assert.doesNotMatch(rendered, /\(15 more lines/);
|
|
199
262
|
});
|
|
200
263
|
|
|
201
264
|
test("generic fallback falls back to truncated JSON for complex args", () => {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// GSD2 - Runtime tests for adaptive terminal layout rendering
|
|
2
|
+
|
|
3
|
+
import assert from "node:assert/strict";
|
|
4
|
+
import { describe, it, before } from "node:test";
|
|
5
|
+
import stripAnsi from "strip-ansi";
|
|
6
|
+
import { AdaptiveLayoutComponent } from "./adaptive-layout.js";
|
|
7
|
+
import { initTheme } from "../theme/theme.js";
|
|
8
|
+
|
|
9
|
+
before(() => {
|
|
10
|
+
initTheme("dark", false);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
function render(component: AdaptiveLayoutComponent, width: number): string {
|
|
14
|
+
return component.render(width).map(stripAnsi).join("\n");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe("AdaptiveLayoutComponent", () => {
|
|
18
|
+
it("renders workflow command center and inspector on wide terminals", () => {
|
|
19
|
+
const component = new AdaptiveLayoutComponent(() => ({
|
|
20
|
+
override: "workflow",
|
|
21
|
+
activeToolCount: 2,
|
|
22
|
+
gsdPhase: "executing milestone M001",
|
|
23
|
+
sessionName: "demo",
|
|
24
|
+
cwd: "/tmp/demo",
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
const output = render(component, 132);
|
|
28
|
+
assert.match(output, /GSD Command Center/);
|
|
29
|
+
assert.match(output, /signals/);
|
|
30
|
+
assert.match(output, /2 running/);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("falls back to a single compact row for narrow workflow terminals", () => {
|
|
34
|
+
const component = new AdaptiveLayoutComponent(() => ({
|
|
35
|
+
override: "workflow",
|
|
36
|
+
activeToolCount: 1,
|
|
37
|
+
gsdPhase: "executing milestone M001",
|
|
38
|
+
cwd: "/tmp/demo",
|
|
39
|
+
}));
|
|
40
|
+
|
|
41
|
+
const output = render(component, 68);
|
|
42
|
+
assert.match(output, /GSD compact/);
|
|
43
|
+
assert.doesNotMatch(output, /signals/);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("renders blocking failure context in debug mode", () => {
|
|
47
|
+
const component = new AdaptiveLayoutComponent(() => ({
|
|
48
|
+
override: "auto",
|
|
49
|
+
activeToolCount: 0,
|
|
50
|
+
lastError: "Cannot find module @gsd/native",
|
|
51
|
+
cwd: "/tmp/demo",
|
|
52
|
+
}));
|
|
53
|
+
|
|
54
|
+
const output = render(component, 120);
|
|
55
|
+
assert.match(output, /blocking failure/);
|
|
56
|
+
assert.match(output, /Cannot find module/);
|
|
57
|
+
assert.match(output, /inspect the failed output/);
|
|
58
|
+
});
|
|
59
|
+
});
|