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
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
// GSD-2 Interactive Chat Controller
|
|
1
2
|
import { Loader, Markdown, Spacer, Text } from "@gsd/pi-tui";
|
|
2
3
|
|
|
3
4
|
import type { InteractiveModeEvent, InteractiveModeStateHost } from "../interactive-mode-state.js";
|
|
4
5
|
import { theme } from "../theme/theme.js";
|
|
5
6
|
import { AssistantMessageComponent } from "../components/assistant-message.js";
|
|
6
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
ToolExecutionComponent,
|
|
9
|
+
ToolPhaseSummaryComponent,
|
|
10
|
+
type ToolExecutionPhase,
|
|
11
|
+
} from "../components/tool-execution.js";
|
|
7
12
|
import { DynamicBorder } from "../components/dynamic-border.js";
|
|
8
13
|
import { appKey } from "../components/keybinding-hints.js";
|
|
9
14
|
|
|
@@ -100,6 +105,71 @@ let pinnedBorder: DynamicBorder | undefined;
|
|
|
100
105
|
// Reference to the pinned markdown component below the border
|
|
101
106
|
let pinnedTextComponent: Markdown | undefined;
|
|
102
107
|
|
|
108
|
+
function mergeToolPhases(phases: ToolExecutionPhase[]): ToolExecutionPhase[] {
|
|
109
|
+
const merged: ToolExecutionPhase[] = [];
|
|
110
|
+
for (const phase of phases) {
|
|
111
|
+
const previous = merged[merged.length - 1];
|
|
112
|
+
if (previous?.label === phase.label) {
|
|
113
|
+
previous.count += phase.count;
|
|
114
|
+
previous.durationMs += phase.durationMs;
|
|
115
|
+
} else {
|
|
116
|
+
merged.push({ ...phase });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return merged;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function replaceCompactToolRowsWithPhaseSummary(
|
|
123
|
+
host: InteractiveModeStateHost & { ui: { requestRender: () => void } },
|
|
124
|
+
): void {
|
|
125
|
+
let changed = false;
|
|
126
|
+
const nextRenderedSegments: RenderedSegment[] = [];
|
|
127
|
+
let rollupRun: Array<{ seg: Extract<RenderedSegment, { kind: "tool" }>; phase: ToolExecutionPhase }> = [];
|
|
128
|
+
|
|
129
|
+
const flushRollupRun = () => {
|
|
130
|
+
if (rollupRun.length < 2) {
|
|
131
|
+
nextRenderedSegments.push(...rollupRun.map((item) => item.seg));
|
|
132
|
+
rollupRun = [];
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const firstIndex = Math.max(0, host.chatContainer.children.indexOf(rollupRun[0].seg.component));
|
|
137
|
+
const summary = new ToolPhaseSummaryComponent(mergeToolPhases(rollupRun.map((item) => item.phase)));
|
|
138
|
+
|
|
139
|
+
for (const { seg } of rollupRun) {
|
|
140
|
+
host.chatContainer.removeChild(seg.component);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
host.chatContainer.addChild(summary);
|
|
144
|
+
const summaryIndex = host.chatContainer.children.indexOf(summary);
|
|
145
|
+
if (summaryIndex !== -1 && summaryIndex !== firstIndex) {
|
|
146
|
+
host.chatContainer.children.splice(summaryIndex, 1);
|
|
147
|
+
host.chatContainer.children.splice(firstIndex, 0, summary);
|
|
148
|
+
(host.chatContainer as unknown as { _prevRender: string[] | null })._prevRender = null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
changed = true;
|
|
152
|
+
rollupRun = [];
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
for (const seg of renderedSegments) {
|
|
156
|
+
const phase = seg.kind === "tool" ? seg.component.getRollupPhase() : null;
|
|
157
|
+
if (seg.kind === "tool" && phase) {
|
|
158
|
+
rollupRun.push({ seg, phase });
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
flushRollupRun();
|
|
163
|
+
nextRenderedSegments.push(seg);
|
|
164
|
+
}
|
|
165
|
+
flushRollupRun();
|
|
166
|
+
|
|
167
|
+
if (changed) {
|
|
168
|
+
renderedSegments = nextRenderedSegments;
|
|
169
|
+
host.ui.requestRender();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
103
173
|
export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
104
174
|
init: () => Promise<void>;
|
|
105
175
|
getMarkdownThemeWithSettings: () => any;
|
|
@@ -177,6 +247,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
177
247
|
return;
|
|
178
248
|
}
|
|
179
249
|
case "agent_start":
|
|
250
|
+
host.clearBlockingError();
|
|
180
251
|
if (host.retryEscapeHandler) {
|
|
181
252
|
host.defaultEditor.onEscape = host.retryEscapeHandler;
|
|
182
253
|
host.retryEscapeHandler = undefined;
|
|
@@ -772,6 +843,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
772
843
|
host.streamingComponent.setShowMetadata(true);
|
|
773
844
|
host.streamingComponent.updateContent(host.streamingMessage);
|
|
774
845
|
}
|
|
846
|
+
replaceCompactToolRowsWithPhaseSummary(host);
|
|
775
847
|
|
|
776
848
|
if (host.streamingMessage.stopReason === "aborted" || host.streamingMessage.stopReason === "error") {
|
|
777
849
|
if (!errorMessage) {
|
|
@@ -822,6 +894,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
822
894
|
component.setExpanded(host.toolOutputExpanded);
|
|
823
895
|
host.chatContainer.addChild(component);
|
|
824
896
|
host.pendingTools.set(event.toolCallId, component);
|
|
897
|
+
renderedSegments.push({ kind: "tool", contentIndex: Number.MAX_SAFE_INTEGER, component });
|
|
825
898
|
host.ui.requestRender();
|
|
826
899
|
}
|
|
827
900
|
break;
|
|
@@ -855,6 +928,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
855
928
|
host.streamingComponent.setShowMetadata(true);
|
|
856
929
|
host.streamingComponent.updateContent(host.streamingMessage);
|
|
857
930
|
}
|
|
931
|
+
replaceCompactToolRowsWithPhaseSummary(host);
|
|
858
932
|
host.streamingComponent = undefined;
|
|
859
933
|
host.streamingMessage = undefined;
|
|
860
934
|
renderedSegments = [];
|
|
@@ -20,6 +20,7 @@ export interface InteractiveModeStateHost {
|
|
|
20
20
|
isInitialized: boolean;
|
|
21
21
|
loadingAnimation?: any;
|
|
22
22
|
pendingWorkingMessage?: string;
|
|
23
|
+
clearBlockingError(): void;
|
|
23
24
|
defaultWorkingMessage: string;
|
|
24
25
|
streamingComponent?: any;
|
|
25
26
|
streamingMessage?: any;
|
|
@@ -37,4 +38,3 @@ export interface InteractiveModeStateHost {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
export type InteractiveModeEvent = AgentSessionEvent;
|
|
40
|
-
|
|
@@ -64,6 +64,7 @@ import { getChangelogPath, getNewEntries, parseChangelog } from "../../utils/cha
|
|
|
64
64
|
import { readClipboardImage } from "../../utils/clipboard-image.js";
|
|
65
65
|
import { ensureTool } from "../../utils/tools-manager.js";
|
|
66
66
|
import { AssistantMessageComponent } from "./components/assistant-message.js";
|
|
67
|
+
import { AdaptiveLayoutComponent } from "./components/adaptive-layout.js";
|
|
67
68
|
import { BashExecutionComponent } from "./components/bash-execution.js";
|
|
68
69
|
import { BorderedLoader } from "./components/bordered-loader.js";
|
|
69
70
|
import { BranchSummaryMessageComponent } from "./components/branch-summary-message.js";
|
|
@@ -246,6 +247,7 @@ export class InteractiveMode {
|
|
|
246
247
|
private ui: TUI;
|
|
247
248
|
private chatContainer: Container;
|
|
248
249
|
private pendingMessagesContainer: Container;
|
|
250
|
+
private adaptiveLayout: AdaptiveLayoutComponent;
|
|
249
251
|
private statusContainer: Container;
|
|
250
252
|
private pinnedMessageContainer: Container;
|
|
251
253
|
private defaultEditor: CustomEditor;
|
|
@@ -261,6 +263,7 @@ export class InteractiveMode {
|
|
|
261
263
|
private loadingAnimation: Loader | undefined = undefined;
|
|
262
264
|
private pendingWorkingMessage: string | undefined = undefined;
|
|
263
265
|
private readonly defaultWorkingMessage = "Working...";
|
|
266
|
+
private lastBlockingError: string | undefined = undefined;
|
|
264
267
|
|
|
265
268
|
private lastSigintTime = 0;
|
|
266
269
|
private lastEscapeTime = 0;
|
|
@@ -367,6 +370,14 @@ export class InteractiveMode {
|
|
|
367
370
|
this.headerContainer = new Container();
|
|
368
371
|
this.chatContainer = new Container();
|
|
369
372
|
this.pendingMessagesContainer = new Container();
|
|
373
|
+
this.adaptiveLayout = new AdaptiveLayoutComponent(() => ({
|
|
374
|
+
override: this.settingsManager.getAdaptiveMode(),
|
|
375
|
+
activeToolCount: this.pendingTools.size,
|
|
376
|
+
gsdPhase: this.pendingWorkingMessage,
|
|
377
|
+
lastError: this.lastBlockingError,
|
|
378
|
+
sessionName: this.sessionManager.getSessionName(),
|
|
379
|
+
cwd: process.cwd(),
|
|
380
|
+
}));
|
|
370
381
|
this.statusContainer = new Container();
|
|
371
382
|
this.pinnedMessageContainer = new Container();
|
|
372
383
|
this.widgetContainerAbove = new Container();
|
|
@@ -571,6 +582,7 @@ export class InteractiveMode {
|
|
|
571
582
|
}
|
|
572
583
|
}
|
|
573
584
|
|
|
585
|
+
this.ui.addChild(this.adaptiveLayout);
|
|
574
586
|
this.ui.addChild(this.chatContainer);
|
|
575
587
|
this.ui.addChild(this.pendingMessagesContainer);
|
|
576
588
|
this.ui.addChild(this.statusContainer);
|
|
@@ -1221,6 +1233,7 @@ export class InteractiveMode {
|
|
|
1221
1233
|
this.streamingComponent = undefined;
|
|
1222
1234
|
this.streamingMessage = undefined;
|
|
1223
1235
|
this.pendingTools.clear();
|
|
1236
|
+
this.clearBlockingError();
|
|
1224
1237
|
|
|
1225
1238
|
// Render any messages added via setup, or show empty session
|
|
1226
1239
|
this.renderInitialMessages();
|
|
@@ -2880,11 +2893,16 @@ export class InteractiveMode {
|
|
|
2880
2893
|
}
|
|
2881
2894
|
|
|
2882
2895
|
showError(errorMessage: string): void {
|
|
2896
|
+
this.lastBlockingError = errorMessage;
|
|
2883
2897
|
this.chatContainer.addChild(new Spacer(1));
|
|
2884
2898
|
this.chatContainer.addChild(new Text(theme.fg("error", `Error: ${errorMessage}`), 1, 0));
|
|
2885
2899
|
this.ui.requestRender();
|
|
2886
2900
|
}
|
|
2887
2901
|
|
|
2902
|
+
clearBlockingError(): void {
|
|
2903
|
+
this.lastBlockingError = undefined;
|
|
2904
|
+
}
|
|
2905
|
+
|
|
2888
2906
|
showWarning(warningMessage: string): void {
|
|
2889
2907
|
this.chatContainer.addChild(new Spacer(1));
|
|
2890
2908
|
this.chatContainer.addChild(new Text(theme.fg("warning", `Warning: ${warningMessage}`), 1, 0));
|
|
@@ -3195,6 +3213,7 @@ export class InteractiveMode {
|
|
|
3195
3213
|
quietStartup: this.settingsManager.getQuietStartup(),
|
|
3196
3214
|
clearOnShrink: this.settingsManager.getClearOnShrink(),
|
|
3197
3215
|
timestampFormat: this.settingsManager.getTimestampFormat(),
|
|
3216
|
+
adaptiveMode: this.settingsManager.getAdaptiveMode(),
|
|
3198
3217
|
},
|
|
3199
3218
|
{
|
|
3200
3219
|
onAutoCompactChange: (enabled) => {
|
|
@@ -3301,6 +3320,10 @@ export class InteractiveMode {
|
|
|
3301
3320
|
onTimestampFormatChange: (format) => {
|
|
3302
3321
|
this.settingsManager.setTimestampFormat(format);
|
|
3303
3322
|
},
|
|
3323
|
+
onAdaptiveModeChange: (mode) => {
|
|
3324
|
+
this.settingsManager.setAdaptiveMode(mode);
|
|
3325
|
+
this.ui.requestRender();
|
|
3326
|
+
},
|
|
3304
3327
|
onCancel: () => {
|
|
3305
3328
|
done();
|
|
3306
3329
|
this.ui.requestRender();
|
|
@@ -3689,6 +3712,7 @@ export class InteractiveMode {
|
|
|
3689
3712
|
this.streamingComponent = undefined;
|
|
3690
3713
|
this.streamingMessage = undefined;
|
|
3691
3714
|
this.pendingTools.clear();
|
|
3715
|
+
this.clearBlockingError();
|
|
3692
3716
|
|
|
3693
3717
|
// Switch session via AgentSession (emits extension session events)
|
|
3694
3718
|
await this.session.switchSession(sessionPath);
|
|
@@ -4010,6 +4034,7 @@ export class InteractiveMode {
|
|
|
4010
4034
|
this.streamingMessage = undefined;
|
|
4011
4035
|
this.pendingTools.clear();
|
|
4012
4036
|
this.pendingImages.length = 0;
|
|
4037
|
+
this.clearBlockingError();
|
|
4013
4038
|
|
|
4014
4039
|
// Reset contextual tips for the new session
|
|
4015
4040
|
this.contextualTips.reset();
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// GSD2 - Slash command tests for interactive TUI settings commands
|
|
2
|
+
|
|
3
|
+
import assert from "node:assert/strict";
|
|
4
|
+
import { describe, it } from "node:test";
|
|
5
|
+
import { Container } from "@gsd/pi-tui";
|
|
6
|
+
import { SettingsManager } from "../../core/settings-manager.js";
|
|
7
|
+
import { dispatchSlashCommand, type SlashCommandContext } from "./slash-command-handlers.js";
|
|
8
|
+
|
|
9
|
+
function makeContext(settingsManager = SettingsManager.inMemory()): SlashCommandContext {
|
|
10
|
+
const statuses: string[] = [];
|
|
11
|
+
const warnings: string[] = [];
|
|
12
|
+
const renders: string[] = [];
|
|
13
|
+
return {
|
|
14
|
+
session: {} as never,
|
|
15
|
+
ui: {} as never,
|
|
16
|
+
keybindings: {} as never,
|
|
17
|
+
chatContainer: new Container(),
|
|
18
|
+
statusContainer: new Container(),
|
|
19
|
+
editorContainer: new Container(),
|
|
20
|
+
headerContainer: new Container(),
|
|
21
|
+
pendingMessagesContainer: new Container(),
|
|
22
|
+
editor: {} as never,
|
|
23
|
+
defaultEditor: {} as never,
|
|
24
|
+
sessionManager: {} as never,
|
|
25
|
+
settingsManager,
|
|
26
|
+
invalidateFooter() {},
|
|
27
|
+
showStatus(message: string) {
|
|
28
|
+
statuses.push(message);
|
|
29
|
+
},
|
|
30
|
+
showError(message: string) {
|
|
31
|
+
throw new Error(message);
|
|
32
|
+
},
|
|
33
|
+
showWarning(message: string) {
|
|
34
|
+
warnings.push(message);
|
|
35
|
+
},
|
|
36
|
+
showSelector() {},
|
|
37
|
+
updateEditorBorderColor() {},
|
|
38
|
+
getMarkdownThemeWithSettings: () => ({} as never),
|
|
39
|
+
requestRender() {
|
|
40
|
+
renders.push("render");
|
|
41
|
+
},
|
|
42
|
+
updateTerminalTitle() {},
|
|
43
|
+
showSettingsSelector() {},
|
|
44
|
+
showModelsSelector: async () => {},
|
|
45
|
+
handleModelCommand: async () => {},
|
|
46
|
+
showUserMessageSelector() {},
|
|
47
|
+
showTreeSelector() {},
|
|
48
|
+
showProviderManager() {},
|
|
49
|
+
showOAuthSelector: async () => {},
|
|
50
|
+
showSessionSelector() {},
|
|
51
|
+
handleClearCommand: async () => {},
|
|
52
|
+
handleReloadCommand: async () => {},
|
|
53
|
+
handleDebugCommand() {},
|
|
54
|
+
shutdown: async () => {},
|
|
55
|
+
executeCompaction: async () => undefined,
|
|
56
|
+
handleBashCommand: async () => {},
|
|
57
|
+
_testStatuses: statuses,
|
|
58
|
+
_testWarnings: warnings,
|
|
59
|
+
_testRenders: renders,
|
|
60
|
+
} as SlashCommandContext & {
|
|
61
|
+
_testStatuses: string[];
|
|
62
|
+
_testWarnings: string[];
|
|
63
|
+
_testRenders: string[];
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
describe("dispatchSlashCommand /tui", () => {
|
|
68
|
+
it("persists /tui mode validation to terminal adaptive mode", async () => {
|
|
69
|
+
const settingsManager = SettingsManager.inMemory();
|
|
70
|
+
const ctx = makeContext(settingsManager) as SlashCommandContext & {
|
|
71
|
+
_testStatuses: string[];
|
|
72
|
+
_testRenders: string[];
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const handled = await dispatchSlashCommand("/tui mode validation", ctx);
|
|
76
|
+
|
|
77
|
+
assert.equal(handled, true);
|
|
78
|
+
assert.equal(settingsManager.getAdaptiveMode(), "validation");
|
|
79
|
+
assert.deepEqual(ctx._testStatuses, ["TUI mode: validation"]);
|
|
80
|
+
assert.equal(ctx._testRenders.length, 1);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("rejects unknown TUI modes without changing settings", async () => {
|
|
84
|
+
const settingsManager = SettingsManager.inMemory({ terminal: { adaptiveMode: "workflow" } });
|
|
85
|
+
const ctx = makeContext(settingsManager) as SlashCommandContext & {
|
|
86
|
+
_testWarnings: string[];
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const handled = await dispatchSlashCommand("/tui mode poster", ctx);
|
|
90
|
+
|
|
91
|
+
assert.equal(handled, true);
|
|
92
|
+
assert.equal(settingsManager.getAdaptiveMode(), "workflow");
|
|
93
|
+
assert.match(ctx._testWarnings[0], /Usage: \/tui mode/);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
import type { AgentSession } from "../../core/agent-session.js";
|
|
32
32
|
import type { AppAction, KeybindingsManager } from "../../core/keybindings.js";
|
|
33
33
|
import type { SessionManager } from "../../core/session-manager.js";
|
|
34
|
-
import type { SettingsManager } from "../../core/settings-manager.js";
|
|
34
|
+
import type { AdaptiveTuiMode, SettingsManager } from "../../core/settings-manager.js";
|
|
35
35
|
import { copyToClipboard } from "../../utils/clipboard.js";
|
|
36
36
|
import { getChangelogPath, parseChangelog } from "../../utils/changelog.js";
|
|
37
37
|
import { ArminComponent } from "./components/armin.js";
|
|
@@ -235,6 +235,10 @@ export async function dispatchSlashCommand(
|
|
|
235
235
|
await ctx.handleBashCommand(command, { loginShell: true });
|
|
236
236
|
return true;
|
|
237
237
|
}
|
|
238
|
+
if (text === "/tui" || text.startsWith("/tui ")) {
|
|
239
|
+
handleTuiCommand(text, ctx);
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
238
242
|
|
|
239
243
|
return false;
|
|
240
244
|
}
|
|
@@ -665,6 +669,25 @@ function handleEditModeCommand(arg: string | undefined, ctx: SlashCommandContext
|
|
|
665
669
|
ctx.showStatus(`Edit mode: ${next}${next === "hashline" ? " (LINE#ID anchored edits)" : " (text-match edits)"}`);
|
|
666
670
|
}
|
|
667
671
|
|
|
672
|
+
function handleTuiCommand(text: string, ctx: SlashCommandContext): void {
|
|
673
|
+
const parts = text.trim().split(/\s+/);
|
|
674
|
+
const mode = parts[1] === "mode" ? parts[2] : parts[1];
|
|
675
|
+
const valid: AdaptiveTuiMode[] = ["auto", "chat", "workflow", "validation", "debug", "compact"];
|
|
676
|
+
|
|
677
|
+
if (!mode) {
|
|
678
|
+
ctx.showStatus(`TUI mode: ${ctx.settingsManager.getAdaptiveMode()}`);
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
if (!valid.includes(mode as AdaptiveTuiMode)) {
|
|
682
|
+
ctx.showWarning(`Usage: /tui mode ${valid.join("|")}`);
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
ctx.settingsManager.setAdaptiveMode(mode as AdaptiveTuiMode);
|
|
687
|
+
ctx.showStatus(`TUI mode: ${mode}`);
|
|
688
|
+
ctx.requestRender();
|
|
689
|
+
}
|
|
690
|
+
|
|
668
691
|
function handleArminSaysHi(ctx: SlashCommandContext): void {
|
|
669
692
|
ctx.chatContainer.addChild(new Spacer(1));
|
|
670
693
|
ctx.chatContainer.addChild(new ArminComponent(ctx.ui));
|
|
@@ -70,6 +70,19 @@ export const ThemeJsonSchema = Type.Object({
|
|
|
70
70
|
thinkingXhigh: ColorValueSchema,
|
|
71
71
|
// Bash Mode (1 color)
|
|
72
72
|
bashMode: ColorValueSchema,
|
|
73
|
+
// Adaptive TUI semantic tokens (optional; defaults are derived from core colors)
|
|
74
|
+
surfaceBorder: Type.Optional(ColorValueSchema),
|
|
75
|
+
surfaceMuted: Type.Optional(ColorValueSchema),
|
|
76
|
+
surfaceTitle: Type.Optional(ColorValueSchema),
|
|
77
|
+
surfaceAccent: Type.Optional(ColorValueSchema),
|
|
78
|
+
toolRunning: Type.Optional(ColorValueSchema),
|
|
79
|
+
toolSuccess: Type.Optional(ColorValueSchema),
|
|
80
|
+
toolError: Type.Optional(ColorValueSchema),
|
|
81
|
+
toolMuted: Type.Optional(ColorValueSchema),
|
|
82
|
+
modeWorkflow: Type.Optional(ColorValueSchema),
|
|
83
|
+
modeValidation: Type.Optional(ColorValueSchema),
|
|
84
|
+
modeDebug: Type.Optional(ColorValueSchema),
|
|
85
|
+
modeCompact: Type.Optional(ColorValueSchema),
|
|
73
86
|
}),
|
|
74
87
|
export: Type.Optional(
|
|
75
88
|
Type.Object({
|
|
@@ -69,7 +69,19 @@ export type ThemeColor =
|
|
|
69
69
|
| "thinkingMedium"
|
|
70
70
|
| "thinkingHigh"
|
|
71
71
|
| "thinkingXhigh"
|
|
72
|
-
| "bashMode"
|
|
72
|
+
| "bashMode"
|
|
73
|
+
| "surfaceBorder"
|
|
74
|
+
| "surfaceMuted"
|
|
75
|
+
| "surfaceTitle"
|
|
76
|
+
| "surfaceAccent"
|
|
77
|
+
| "toolRunning"
|
|
78
|
+
| "toolSuccess"
|
|
79
|
+
| "toolError"
|
|
80
|
+
| "toolMuted"
|
|
81
|
+
| "modeWorkflow"
|
|
82
|
+
| "modeValidation"
|
|
83
|
+
| "modeDebug"
|
|
84
|
+
| "modeCompact";
|
|
73
85
|
|
|
74
86
|
export type ThemeBg =
|
|
75
87
|
| "selectedBg"
|
|
@@ -374,6 +386,24 @@ function getBuiltinThemes(): Record<string, ThemeJson> {
|
|
|
374
386
|
return builtinThemes;
|
|
375
387
|
}
|
|
376
388
|
|
|
389
|
+
function withSemanticColorDefaults(colors: ThemeJson["colors"]): ThemeJson["colors"] {
|
|
390
|
+
return {
|
|
391
|
+
...colors,
|
|
392
|
+
surfaceBorder: colors.surfaceBorder ?? colors.border,
|
|
393
|
+
surfaceMuted: colors.surfaceMuted ?? colors.borderMuted,
|
|
394
|
+
surfaceTitle: colors.surfaceTitle ?? colors.toolTitle,
|
|
395
|
+
surfaceAccent: colors.surfaceAccent ?? colors.borderAccent,
|
|
396
|
+
toolRunning: colors.toolRunning ?? colors.warning,
|
|
397
|
+
toolSuccess: colors.toolSuccess ?? colors.success,
|
|
398
|
+
toolError: colors.toolError ?? colors.error,
|
|
399
|
+
toolMuted: colors.toolMuted ?? colors.muted,
|
|
400
|
+
modeWorkflow: colors.modeWorkflow ?? colors.accent,
|
|
401
|
+
modeValidation: colors.modeValidation ?? colors.warning,
|
|
402
|
+
modeDebug: colors.modeDebug ?? colors.error,
|
|
403
|
+
modeCompact: colors.modeCompact ?? colors.muted,
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
|
|
377
407
|
export function getAvailableThemes(): string[] {
|
|
378
408
|
const themes = new Set<string>(Object.keys(getBuiltinThemes()));
|
|
379
409
|
const customThemesDir = getCustomThemesDir();
|
|
@@ -493,7 +523,7 @@ function loadThemeJson(name: string): ThemeJson {
|
|
|
493
523
|
|
|
494
524
|
function createTheme(themeJson: ThemeJson, mode?: ColorMode, sourcePath?: string): Theme {
|
|
495
525
|
const colorMode = mode ?? detectColorMode();
|
|
496
|
-
const resolvedColors = resolveThemeColors(themeJson.colors, themeJson.vars);
|
|
526
|
+
const resolvedColors = resolveThemeColors(withSemanticColorDefaults(themeJson.colors), themeJson.vars);
|
|
497
527
|
const fgColors: Record<ThemeColor, string | number> = {} as Record<ThemeColor, string | number>;
|
|
498
528
|
const bgColors: Record<ThemeBg, string | number> = {} as Record<ThemeBg, string | number>;
|
|
499
529
|
const bgColorKeys: Set<string> = new Set([
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// GSD2 TUI - Built-in terminal theme definitions.
|
|
1
2
|
/**
|
|
2
3
|
* Built-in theme definitions.
|
|
3
4
|
*
|
|
@@ -18,27 +19,30 @@ import type { ThemeJson } from "./theme-schema.js";
|
|
|
18
19
|
const dark: ThemeJson = {
|
|
19
20
|
name: "dark",
|
|
20
21
|
vars: {
|
|
21
|
-
cyan: "#
|
|
22
|
-
blue: "#
|
|
23
|
-
green: "#
|
|
24
|
-
red: "#
|
|
25
|
-
yellow: "#
|
|
26
|
-
gray: "#
|
|
27
|
-
dimGray: "#
|
|
28
|
-
darkGray: "#
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
22
|
+
cyan: "#5cc8c8",
|
|
23
|
+
blue: "#79b8ff",
|
|
24
|
+
green: "#7ad38b",
|
|
25
|
+
red: "#f27b7b",
|
|
26
|
+
yellow: "#d6b85f",
|
|
27
|
+
gray: "#87949b",
|
|
28
|
+
dimGray: "#657178",
|
|
29
|
+
darkGray: "#303a40",
|
|
30
|
+
line: "#52616a",
|
|
31
|
+
lineSoft: "#303a40",
|
|
32
|
+
textSoft: "#cbd6dc",
|
|
33
|
+
accent: "#5cc8c8",
|
|
34
|
+
selectedBg: "#1d282a",
|
|
35
|
+
userMsgBg: "#202a2f",
|
|
36
|
+
toolPendingBg: "#252721",
|
|
37
|
+
toolSuccessBg: "#1c251f",
|
|
38
|
+
toolErrorBg: "#251e20",
|
|
39
|
+
customMsgBg: "#202a2f",
|
|
36
40
|
},
|
|
37
41
|
colors: {
|
|
38
42
|
accent: "accent",
|
|
39
|
-
border: "
|
|
40
|
-
borderAccent: "
|
|
41
|
-
borderMuted: "
|
|
43
|
+
border: "line",
|
|
44
|
+
borderAccent: "accent",
|
|
45
|
+
borderMuted: "lineSoft",
|
|
42
46
|
success: "green",
|
|
43
47
|
error: "red",
|
|
44
48
|
warning: "yellow",
|
|
@@ -49,16 +53,21 @@ const dark: ThemeJson = {
|
|
|
49
53
|
|
|
50
54
|
selectedBg: "selectedBg",
|
|
51
55
|
userMessageBg: "userMsgBg",
|
|
52
|
-
userMessageText: "
|
|
53
|
-
assistantMessageText: "",
|
|
56
|
+
userMessageText: "textSoft",
|
|
57
|
+
assistantMessageText: "textSoft",
|
|
54
58
|
customMessageBg: "customMsgBg",
|
|
55
|
-
customMessageText: "",
|
|
56
|
-
customMessageLabel: "
|
|
59
|
+
customMessageText: "textSoft",
|
|
60
|
+
customMessageLabel: "blue",
|
|
57
61
|
toolPendingBg: "toolPendingBg",
|
|
58
62
|
toolSuccessBg: "toolSuccessBg",
|
|
59
63
|
toolErrorBg: "toolErrorBg",
|
|
60
|
-
toolTitle: "
|
|
61
|
-
toolOutput: "
|
|
64
|
+
toolTitle: "gray",
|
|
65
|
+
toolOutput: "textSoft",
|
|
66
|
+
surfaceTitle: "accent",
|
|
67
|
+
surfaceAccent: "accent",
|
|
68
|
+
toolRunning: "yellow",
|
|
69
|
+
toolSuccess: "green",
|
|
70
|
+
toolError: "red",
|
|
62
71
|
|
|
63
72
|
mdHeading: "#fbbf24",
|
|
64
73
|
mdLink: "#93c5fd",
|
|
@@ -95,9 +104,9 @@ const dark: ThemeJson = {
|
|
|
95
104
|
bashMode: "green",
|
|
96
105
|
},
|
|
97
106
|
export: {
|
|
98
|
-
pageBg: "#
|
|
99
|
-
cardBg: "#
|
|
100
|
-
infoBg: "#
|
|
107
|
+
pageBg: "#111416",
|
|
108
|
+
cardBg: "#1e2529",
|
|
109
|
+
infoBg: "#252721",
|
|
101
110
|
},
|
|
102
111
|
};
|
|
103
112
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// GSD2 - Tests for adaptive TUI mode selection
|
|
2
|
+
|
|
3
|
+
import assert from "node:assert/strict";
|
|
4
|
+
import { describe, test } from "node:test";
|
|
5
|
+
import stripAnsi from "strip-ansi";
|
|
6
|
+
|
|
7
|
+
import { AdaptiveLayoutComponent } from "./components/adaptive-layout.js";
|
|
8
|
+
import { initTheme } from "./theme/theme.js";
|
|
9
|
+
import { resolveTuiMode } from "./tui-mode.js";
|
|
10
|
+
|
|
11
|
+
initTheme("dark", false);
|
|
12
|
+
|
|
13
|
+
describe("resolveTuiMode", () => {
|
|
14
|
+
test("explicit overrides beat auto selection", () => {
|
|
15
|
+
assert.equal(
|
|
16
|
+
resolveTuiMode({ terminalWidth: 60, override: "debug", gsdPhase: "validating-milestone" }),
|
|
17
|
+
"debug",
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("prioritizes compact layouts on narrow terminals", () => {
|
|
22
|
+
assert.equal(
|
|
23
|
+
resolveTuiMode({ terminalWidth: 60, override: "auto", hasBlockingError: true, gsdPhase: "validating-milestone" }),
|
|
24
|
+
"compact",
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("uses debug mode for blocking errors on roomy terminals", () => {
|
|
29
|
+
assert.equal(resolveTuiMode({ terminalWidth: 100, hasBlockingError: true }), "debug");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("uses validation mode for validation and completion phases", () => {
|
|
33
|
+
assert.equal(resolveTuiMode({ terminalWidth: 100, gsdPhase: "validating-milestone" }), "validation");
|
|
34
|
+
assert.equal(resolveTuiMode({ terminalWidth: 100, gsdPhase: "complete-milestone" }), "validation");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("uses workflow mode when tools or non-validation phases are active", () => {
|
|
38
|
+
assert.equal(resolveTuiMode({ terminalWidth: 100, activeToolCount: 1 }), "workflow");
|
|
39
|
+
assert.equal(resolveTuiMode({ terminalWidth: 100, gsdPhase: "execute-phase" }), "workflow");
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test("falls back to chat mode for plain conversation", () => {
|
|
43
|
+
assert.equal(resolveTuiMode({ terminalWidth: 100 }), "chat");
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe("AdaptiveLayoutComponent", () => {
|
|
48
|
+
test("renders workflow layout with prototype rule frames", () => {
|
|
49
|
+
const layout = new AdaptiveLayoutComponent(() => ({
|
|
50
|
+
override: "workflow",
|
|
51
|
+
activeToolCount: 2,
|
|
52
|
+
gsdPhase: "execute-task",
|
|
53
|
+
sessionName: "main",
|
|
54
|
+
cwd: "/Users/example/project",
|
|
55
|
+
}));
|
|
56
|
+
|
|
57
|
+
const plain = layout.render(120).map(stripAnsi);
|
|
58
|
+
|
|
59
|
+
assert.match(plain[0], /^─+/, "workflow layout should start with a rule frame");
|
|
60
|
+
assert.ok(plain.some((line) => line.includes("GSD Command Center")), "workflow title should render");
|
|
61
|
+
assert.ok(plain.some((line) => line.includes("signals")), "inspector title should render");
|
|
62
|
+
assert.ok(plain.some((line) => line.includes("│ Active")), "body rows should keep prototype gutter");
|
|
63
|
+
assert.ok(!plain.some((line) => /[╭╮╰╯]/.test(line)), "workflow layout should not use rounded box corners");
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// GSD2 - Adaptive mode selection for the interactive terminal UI
|
|
2
|
+
|
|
3
|
+
export type TuiMode = "chat" | "workflow" | "validation" | "debug" | "compact";
|
|
4
|
+
export type TuiAdaptiveMode = "auto" | TuiMode;
|
|
5
|
+
|
|
6
|
+
export interface TuiModeContext {
|
|
7
|
+
terminalWidth: number;
|
|
8
|
+
override?: TuiAdaptiveMode;
|
|
9
|
+
gsdPhase?: string;
|
|
10
|
+
activeToolCount?: number;
|
|
11
|
+
hasBlockingError?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function resolveTuiMode(context: TuiModeContext): TuiMode {
|
|
15
|
+
if (context.override && context.override !== "auto") return context.override;
|
|
16
|
+
if (context.terminalWidth < 72) return "compact";
|
|
17
|
+
if (context.hasBlockingError) return "debug";
|
|
18
|
+
|
|
19
|
+
const phase = context.gsdPhase?.toLowerCase() ?? "";
|
|
20
|
+
if (phase.includes("validat") || phase.includes("complete") || phase.includes("review")) {
|
|
21
|
+
return "validation";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if ((context.activeToolCount ?? 0) > 0 || phase.length > 0) {
|
|
25
|
+
return "workflow";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return "chat";
|
|
29
|
+
}
|