gsd-pi 2.74.0-dev.b741afb → 2.74.0-dev.ffbcc03
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/extensions/gsd/activity-log.js +16 -0
- package/dist/resources/extensions/gsd/auto/loop.js +147 -10
- package/dist/resources/extensions/gsd/auto/phases.js +113 -3
- package/dist/resources/extensions/gsd/auto/session.js +10 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +11 -1
- package/dist/resources/extensions/gsd/auto-model-selection.js +51 -5
- package/dist/resources/extensions/gsd/auto-post-unit.js +215 -8
- package/dist/resources/extensions/gsd/auto-recovery.js +24 -10
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +18 -0
- package/dist/resources/extensions/gsd/auto-verification.js +100 -2
- package/dist/resources/extensions/gsd/auto.js +28 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +10 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +61 -9
- package/dist/resources/extensions/gsd/cache.js +16 -5
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
- package/dist/resources/extensions/gsd/commands-extract-learnings.js +225 -0
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +14 -1
- package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +144 -0
- package/dist/resources/extensions/gsd/ecosystem/loader.js +145 -0
- package/dist/resources/extensions/gsd/git-service.js +49 -1
- package/dist/resources/extensions/gsd/graph-context.js +98 -7
- package/dist/resources/extensions/gsd/gsd-db.js +260 -2
- package/dist/resources/extensions/gsd/guided-flow.js +24 -1
- package/dist/resources/extensions/gsd/init-wizard.js +1 -0
- package/dist/resources/extensions/gsd/journal.js +27 -0
- package/dist/resources/extensions/gsd/metrics.js +19 -0
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +33 -1
- package/dist/resources/extensions/gsd/preferences-models.js +20 -3
- package/dist/resources/extensions/gsd/preferences-types.js +1 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +108 -2
- package/dist/resources/extensions/gsd/preferences.js +26 -0
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +15 -30
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +12 -2
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +5 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +39 -4
- package/dist/resources/extensions/gsd/unit-ownership.js +1 -1
- package/dist/resources/extensions/gsd/uok/audit-toggle.js +7 -0
- package/dist/resources/extensions/gsd/uok/audit.js +40 -0
- package/dist/resources/extensions/gsd/uok/contracts.js +1 -0
- package/dist/resources/extensions/gsd/uok/execution-graph.js +179 -0
- package/dist/resources/extensions/gsd/uok/flags.js +29 -0
- package/dist/resources/extensions/gsd/uok/gate-runner.js +109 -0
- package/dist/resources/extensions/gsd/uok/gitops.js +53 -0
- package/dist/resources/extensions/gsd/uok/kernel.js +80 -0
- package/dist/resources/extensions/gsd/uok/loop-adapter.js +133 -0
- package/dist/resources/extensions/gsd/uok/model-policy.js +66 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +132 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +22 -0
- package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
- 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 +9 -9
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/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 +9 -9
- 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-manifest.json +5 -5
- 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/package.json +1 -1
- package/packages/mcp-server/dist/readers/graph.d.ts +1 -1
- package/packages/mcp-server/dist/readers/graph.d.ts.map +1 -1
- package/packages/mcp-server/dist/readers/graph.js +107 -0
- package/packages/mcp-server/dist/readers/graph.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +88 -6
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/readers/graph.test.ts +178 -0
- package/packages/mcp-server/src/readers/graph.ts +148 -1
- package/packages/mcp-server/src/workflow-tools.ts +95 -10
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/index.d.ts +1 -9
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -9
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/models/capability-patches.d.ts +19 -0
- package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/capability-patches.js +36 -0
- package/packages/pi-ai/dist/models/capability-patches.js.map +1 -0
- package/packages/pi-ai/dist/{models.custom.d.ts → models/custom.d.ts} +1 -1
- package/packages/pi-ai/dist/models/custom.d.ts.map +1 -0
- package/packages/pi-ai/dist/{models.custom.js → models/custom.js} +4 -4
- package/packages/pi-ai/dist/models/custom.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts +1482 -0
- package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/amazon-bedrock.js +1484 -0
- package/packages/pi-ai/dist/models/generated/amazon-bedrock.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/anthropic.d.ts +377 -0
- package/packages/pi-ai/dist/models/generated/anthropic.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/anthropic.js +379 -0
- package/packages/pi-ai/dist/models/generated/anthropic.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts +700 -0
- package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/azure-openai-responses.js +702 -0
- package/packages/pi-ai/dist/models/generated/azure-openai-responses.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/cerebras.d.ts +71 -0
- package/packages/pi-ai/dist/models/generated/cerebras.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/cerebras.js +73 -0
- package/packages/pi-ai/dist/models/generated/cerebras.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/github-copilot.d.ts +590 -0
- package/packages/pi-ai/dist/models/generated/github-copilot.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/github-copilot.js +444 -0
- package/packages/pi-ai/dist/models/generated/github-copilot.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts +156 -0
- package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-antigravity.js +158 -0
- package/packages/pi-ai/dist/models/generated/google-antigravity.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts +105 -0
- package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-gemini-cli.js +107 -0
- package/packages/pi-ai/dist/models/generated/google-gemini-cli.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-vertex.d.ts +207 -0
- package/packages/pi-ai/dist/models/generated/google-vertex.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-vertex.js +209 -0
- package/packages/pi-ai/dist/models/generated/google-vertex.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/google.d.ts +462 -0
- package/packages/pi-ai/dist/models/generated/google.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/google.js +464 -0
- package/packages/pi-ai/dist/models/generated/google.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/groq.d.ts +309 -0
- package/packages/pi-ai/dist/models/generated/groq.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/groq.js +311 -0
- package/packages/pi-ai/dist/models/generated/groq.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/huggingface.d.ts +383 -0
- package/packages/pi-ai/dist/models/generated/huggingface.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/huggingface.js +347 -0
- package/packages/pi-ai/dist/models/generated/huggingface.js.map +1 -0
- package/packages/pi-ai/dist/{models.generated.d.ts → models/generated/index.d.ts} +1 -1
- package/packages/pi-ai/dist/{models.generated.d.ts.map → models/generated/index.d.ts.map} +1 -1
- package/packages/pi-ai/dist/models/generated/index.js +51 -0
- package/packages/pi-ai/dist/models/generated/index.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts +37 -0
- package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/kimi-coding.js +39 -0
- package/packages/pi-ai/dist/models/generated/kimi-coding.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts +105 -0
- package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/minimax-cn.js +107 -0
- package/packages/pi-ai/dist/models/generated/minimax-cn.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/minimax.d.ts +105 -0
- package/packages/pi-ai/dist/models/generated/minimax.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/minimax.js +107 -0
- package/packages/pi-ai/dist/models/generated/minimax.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/mistral.d.ts +445 -0
- package/packages/pi-ai/dist/models/generated/mistral.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/mistral.js +447 -0
- package/packages/pi-ai/dist/models/generated/mistral.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +139 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.js +141 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/openai.d.ts +700 -0
- package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/openai.js +702 -0
- package/packages/pi-ai/dist/models/generated/openai.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/opencode-go.d.ts +122 -0
- package/packages/pi-ai/dist/models/generated/opencode-go.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/opencode-go.js +124 -0
- package/packages/pi-ai/dist/models/generated/opencode-go.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/opencode.d.ts +530 -0
- package/packages/pi-ai/dist/models/generated/opencode.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/opencode.js +532 -0
- package/packages/pi-ai/dist/models/generated/opencode.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/openrouter.d.ts +4270 -0
- package/packages/pi-ai/dist/models/generated/openrouter.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/openrouter.js +4272 -0
- package/packages/pi-ai/dist/models/generated/openrouter.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts +2604 -0
- package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js +2606 -0
- package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/xai.d.ts +411 -0
- package/packages/pi-ai/dist/models/generated/xai.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/xai.js +413 -0
- package/packages/pi-ai/dist/models/generated/xai.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/zai.d.ts +276 -0
- package/packages/pi-ai/dist/models/generated/zai.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/zai.js +239 -0
- package/packages/pi-ai/dist/models/generated/zai.js.map +1 -0
- package/packages/pi-ai/dist/models/index.d.ts +27 -0
- package/packages/pi-ai/dist/models/index.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/index.js +80 -0
- package/packages/pi-ai/dist/models/index.js.map +1 -0
- package/packages/pi-ai/dist/models.d.ts +1 -36
- package/packages/pi-ai/dist/models.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.test.js +1 -2
- package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
- package/packages/pi-ai/dist/models.js +3 -112
- package/packages/pi-ai/dist/models.js.map +1 -1
- package/packages/pi-ai/dist/models.test.js +6 -5
- package/packages/pi-ai/dist/models.test.js.map +1 -1
- package/packages/pi-ai/scripts/generate-models.ts +74 -40
- package/packages/pi-ai/src/index.ts +1 -9
- package/packages/pi-ai/src/models/capability-patches.ts +40 -0
- package/packages/pi-ai/src/{models.custom.ts → models/custom.ts} +4 -4
- package/packages/pi-ai/src/models/generated/amazon-bedrock.ts +1486 -0
- package/packages/pi-ai/src/models/generated/anthropic.ts +381 -0
- package/packages/pi-ai/src/models/generated/azure-openai-responses.ts +704 -0
- package/packages/pi-ai/src/models/generated/cerebras.ts +75 -0
- package/packages/pi-ai/src/models/generated/github-copilot.ts +446 -0
- package/packages/pi-ai/src/models/generated/google-antigravity.ts +160 -0
- package/packages/pi-ai/src/models/generated/google-gemini-cli.ts +109 -0
- package/packages/pi-ai/src/models/generated/google-vertex.ts +211 -0
- package/packages/pi-ai/src/models/generated/google.ts +466 -0
- package/packages/pi-ai/src/models/generated/groq.ts +313 -0
- package/packages/pi-ai/src/models/generated/huggingface.ts +349 -0
- package/packages/pi-ai/src/models/generated/index.ts +52 -0
- package/packages/pi-ai/src/models/generated/kimi-coding.ts +41 -0
- package/packages/pi-ai/src/models/generated/minimax-cn.ts +109 -0
- package/packages/pi-ai/src/models/generated/minimax.ts +109 -0
- package/packages/pi-ai/src/models/generated/mistral.ts +449 -0
- package/packages/pi-ai/src/models/generated/openai-codex.ts +143 -0
- package/packages/pi-ai/src/models/generated/openai.ts +704 -0
- package/packages/pi-ai/src/models/generated/opencode-go.ts +126 -0
- package/packages/pi-ai/src/models/generated/opencode.ts +534 -0
- package/packages/pi-ai/src/models/generated/openrouter.ts +4274 -0
- package/packages/pi-ai/src/models/generated/vercel-ai-gateway.ts +2608 -0
- package/packages/pi-ai/src/models/generated/xai.ts +415 -0
- package/packages/pi-ai/src/models/generated/zai.ts +241 -0
- package/packages/pi-ai/src/models/index.ts +106 -0
- package/packages/pi-ai/src/models.generated.test.ts +1 -2
- package/packages/pi-ai/src/models.test.ts +6 -5
- package/packages/pi-ai/src/models.ts +3 -153
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +8 -2
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +472 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js +52 -0
- package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +11 -0
- 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/assistant-message.d.ts +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 +23 -9
- 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 +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +47 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +8 -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 +68 -8
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +22 -22
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.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 +232 -18
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +38 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +14 -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 +70 -6
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +12 -6
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +612 -0
- package/packages/pi-coding-agent/src/core/model-registry-env-fallback.test.ts +59 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +2 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +19 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +25 -10
- package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +67 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +83 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +23 -26
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +298 -41
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +44 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +92 -6
- package/packages/pi-coding-agent/src/types/ambient-modules.d.ts +69 -0
- package/packages/pi-coding-agent/tsconfig.json +2 -2
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/gsd/activity-log.ts +21 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +4 -0
- package/src/resources/extensions/gsd/auto/loop.ts +159 -10
- package/src/resources/extensions/gsd/auto/phases.ts +123 -3
- package/src/resources/extensions/gsd/auto/session.ts +10 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +16 -6
- package/src/resources/extensions/gsd/auto-model-selection.ts +66 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +226 -9
- package/src/resources/extensions/gsd/auto-recovery.ts +29 -9
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +25 -1
- package/src/resources/extensions/gsd/auto-verification.ts +129 -2
- package/src/resources/extensions/gsd/auto.ts +34 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +15 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +72 -8
- package/src/resources/extensions/gsd/cache.ts +16 -5
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
- package/src/resources/extensions/gsd/commands-extract-learnings.ts +304 -0
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +14 -1
- package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +228 -0
- package/src/resources/extensions/gsd/ecosystem/loader.ts +201 -0
- package/src/resources/extensions/gsd/git-service.ts +68 -0
- package/src/resources/extensions/gsd/graph-context.ts +139 -12
- package/src/resources/extensions/gsd/gsd-db.ts +321 -3
- package/src/resources/extensions/gsd/guided-flow.ts +33 -1
- package/src/resources/extensions/gsd/init-wizard.ts +3 -2
- package/src/resources/extensions/gsd/journal.ts +30 -0
- package/src/resources/extensions/gsd/metrics.ts +26 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +40 -1
- package/src/resources/extensions/gsd/preferences-models.ts +20 -3
- package/src/resources/extensions/gsd/preferences-types.ts +32 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +107 -2
- package/src/resources/extensions/gsd/preferences.ts +28 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +15 -31
- package/src/resources/extensions/gsd/session-lock.ts +14 -2
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +20 -1
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
- package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +177 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +272 -0
- package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +6 -2
- package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +340 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +10 -7
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -2
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -3
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
- package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +40 -1
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -5
- package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/uok-flags.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/uok-preferences.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +39 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +9 -2
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +48 -3
- package/src/resources/extensions/gsd/types.ts +14 -1
- package/src/resources/extensions/gsd/unit-ownership.ts +2 -2
- package/src/resources/extensions/gsd/uok/audit-toggle.ts +9 -0
- package/src/resources/extensions/gsd/uok/audit.ts +51 -0
- package/src/resources/extensions/gsd/uok/contracts.ts +135 -0
- package/src/resources/extensions/gsd/uok/execution-graph.ts +241 -0
- package/src/resources/extensions/gsd/uok/flags.ts +45 -0
- package/src/resources/extensions/gsd/uok/gate-runner.ts +146 -0
- package/src/resources/extensions/gsd/uok/gitops.ts +75 -0
- package/src/resources/extensions/gsd/uok/kernel.ts +105 -0
- package/src/resources/extensions/gsd/uok/loop-adapter.ts +162 -0
- package/src/resources/extensions/gsd/uok/model-policy.ts +112 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +156 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +27 -1
- package/src/resources/extensions/ttsr/ttsr-manager.ts +10 -5
- package/packages/pi-ai/dist/models.custom.d.ts.map +0 -1
- package/packages/pi-ai/dist/models.custom.js.map +0 -1
- package/packages/pi-ai/dist/models.generated.js +0 -14343
- package/packages/pi-ai/dist/models.generated.js.map +0 -1
- package/packages/pi-ai/src/models.generated.ts +0 -14345
- /package/dist/web/standalone/.next/static/{XnHY5eXUsTCFmNodWHetD → kn6xzWKYnogsxp2b6RpDD}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{XnHY5eXUsTCFmNodWHetD → kn6xzWKYnogsxp2b6RpDD}/_ssgManifest.js +0 -0
|
@@ -16,10 +16,20 @@ let lastContentLength = 0;
|
|
|
16
16
|
|
|
17
17
|
// --- Segment walker state (per streaming assistant turn) ---
|
|
18
18
|
type RenderedSegment =
|
|
19
|
-
| {
|
|
19
|
+
| {
|
|
20
|
+
kind: "text-run";
|
|
21
|
+
startIndex: number;
|
|
22
|
+
endIndex: number;
|
|
23
|
+
contentType: "text" | "thinking";
|
|
24
|
+
component: AssistantMessageComponent;
|
|
25
|
+
}
|
|
20
26
|
| { kind: "tool"; contentIndex: number; component: ToolExecutionComponent };
|
|
21
27
|
|
|
22
28
|
let renderedSegments: RenderedSegment[] = [];
|
|
29
|
+
// When providers reuse one assistant lifecycle across internal sub-turns,
|
|
30
|
+
// a content[] shrink resets renderedSegments. Keep the displaced segments so
|
|
31
|
+
// claude-code MCP pruning can remove stale provisional text later.
|
|
32
|
+
let orphanedSegments: RenderedSegment[] = [];
|
|
23
33
|
|
|
24
34
|
function hasVisibleAssistantContent(message: { content: Array<any> }): boolean {
|
|
25
35
|
return message.content.some(
|
|
@@ -85,6 +95,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
85
95
|
}
|
|
86
96
|
|
|
87
97
|
host.footer.invalidate();
|
|
98
|
+
const timestampFormat = host.settingsManager.getTimestampFormat();
|
|
88
99
|
|
|
89
100
|
// Reset content index tracker and pinned state when a new assistant message starts
|
|
90
101
|
if (event.type === "message_start" && event.message.role === "assistant") {
|
|
@@ -93,6 +104,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
93
104
|
lastPinnedText = "";
|
|
94
105
|
hasToolsInTurn = false;
|
|
95
106
|
renderedSegments = [];
|
|
107
|
+
orphanedSegments = [];
|
|
96
108
|
if (pinnedBorder) pinnedBorder.stopSpinner();
|
|
97
109
|
pinnedBorder = undefined;
|
|
98
110
|
pinnedTextComponent = undefined;
|
|
@@ -113,6 +125,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
113
125
|
lastPinnedText = "";
|
|
114
126
|
hasToolsInTurn = false;
|
|
115
127
|
renderedSegments = [];
|
|
128
|
+
orphanedSegments = [];
|
|
116
129
|
lastContentLength = 0;
|
|
117
130
|
if (pinnedBorder) pinnedBorder.stopSpinner();
|
|
118
131
|
pinnedBorder = undefined;
|
|
@@ -226,6 +239,10 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
226
239
|
// content (#4144 regression). Prior sub-turn children stay in
|
|
227
240
|
// chatContainer as frozen history; new segments append after them.
|
|
228
241
|
if (contentBlocks.length < lastContentLength) {
|
|
242
|
+
// Accumulate across successive shrinks — overwriting would drop
|
|
243
|
+
// segments displaced by an earlier shrink, leaving them stranded
|
|
244
|
+
// in chatContainer once the prune pass finally runs.
|
|
245
|
+
orphanedSegments = [...orphanedSegments, ...renderedSegments];
|
|
229
246
|
renderedSegments = [];
|
|
230
247
|
lastPinnedText = "";
|
|
231
248
|
lastProcessedContentIndex = 0;
|
|
@@ -302,29 +319,130 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
302
319
|
// Build desired segment plan from content[].
|
|
303
320
|
{
|
|
304
321
|
const blocks = host.streamingMessage.content;
|
|
322
|
+
const isClaudeCodeProvider = host.streamingMessage.provider === "claude-code";
|
|
323
|
+
const hasMcpToolBlock = blocks.some((b: any) => {
|
|
324
|
+
if (b?.type === "toolCall") {
|
|
325
|
+
return typeof b?.mcpServer === "string" || String(b?.name ?? "").startsWith("mcp__");
|
|
326
|
+
}
|
|
327
|
+
if (b?.type === "serverToolUse") {
|
|
328
|
+
return typeof b?.mcpServer === "string" || String(b?.name ?? "").startsWith("mcp__");
|
|
329
|
+
}
|
|
330
|
+
return false;
|
|
331
|
+
});
|
|
332
|
+
const firstToolIdx = blocks.findIndex((b: any) => b.type === "toolCall" || b.type === "serverToolUse");
|
|
333
|
+
const hasPostToolText = firstToolIdx >= 0
|
|
334
|
+
&& blocks.some(
|
|
335
|
+
(b: any, idx: number) => (
|
|
336
|
+
idx > firstToolIdx
|
|
337
|
+
&& b?.type === "text"
|
|
338
|
+
&& typeof b?.text === "string"
|
|
339
|
+
&& b.text.trim().length > 0
|
|
340
|
+
),
|
|
341
|
+
);
|
|
342
|
+
// Only prune provisional pre-tool prose after post-tool prose exists,
|
|
343
|
+
// so MCP tool-only windows do not blank the assistant content.
|
|
344
|
+
const shouldDropPreToolProse = isClaudeCodeProvider && hasMcpToolBlock && hasPostToolText;
|
|
305
345
|
type DesiredSegment =
|
|
306
|
-
| { kind: "text-run"; startIndex: number; endIndex: number }
|
|
346
|
+
| { kind: "text-run"; startIndex: number; endIndex: number; contentType: "text" | "thinking" }
|
|
307
347
|
| { kind: "tool"; contentIndex: number; toolId: string };
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
348
|
+
const desired: DesiredSegment[] = [];
|
|
349
|
+
let runStart = -1;
|
|
350
|
+
let runEnd = -1;
|
|
351
|
+
let runType: "text" | "thinking" | undefined;
|
|
352
|
+
const closeRun = () => {
|
|
353
|
+
if (runStart !== -1 && runType) {
|
|
354
|
+
desired.push({ kind: "text-run", startIndex: runStart, endIndex: runEnd, contentType: runType });
|
|
355
|
+
runStart = -1;
|
|
356
|
+
runEnd = -1;
|
|
357
|
+
runType = undefined;
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
361
|
+
const b = blocks[i];
|
|
362
|
+
const blockType = b.type === "text" || b.type === "thinking" ? b.type : undefined;
|
|
363
|
+
const isTextLike = blockType === "text" || blockType === "thinking";
|
|
364
|
+
const isTool = b.type === "toolCall" || b.type === "serverToolUse";
|
|
365
|
+
// For Claude Code MCP turns, prune only pre-tool prose, never thinking.
|
|
366
|
+
const textValue = blockType === "text" && typeof b?.text === "string" ? b.text : "";
|
|
367
|
+
const isLikelyQuestion = blockType === "text" && typeof textValue === "string" && /\?\s*$/.test(textValue.trim());
|
|
368
|
+
const shouldSkipProse = shouldDropPreToolProse
|
|
369
|
+
&& firstToolIdx >= 0
|
|
370
|
+
&& i < firstToolIdx
|
|
371
|
+
&& blockType === "text"
|
|
372
|
+
&& !isLikelyQuestion;
|
|
373
|
+
if (shouldSkipProse) {
|
|
374
|
+
closeRun();
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
if (isTextLike) {
|
|
378
|
+
if (runStart === -1) {
|
|
379
|
+
runStart = i;
|
|
380
|
+
runEnd = i;
|
|
381
|
+
runType = blockType;
|
|
382
|
+
} else if (runType !== blockType) {
|
|
383
|
+
closeRun();
|
|
384
|
+
runStart = i;
|
|
385
|
+
runEnd = i;
|
|
386
|
+
runType = blockType;
|
|
387
|
+
} else {
|
|
388
|
+
runEnd = i;
|
|
320
389
|
}
|
|
390
|
+
} else {
|
|
391
|
+
closeRun();
|
|
321
392
|
if (isTool) {
|
|
322
393
|
desired.push({ kind: "tool", contentIndex: i, toolId: b.id });
|
|
323
394
|
}
|
|
324
395
|
}
|
|
325
396
|
}
|
|
326
|
-
|
|
327
|
-
|
|
397
|
+
closeRun();
|
|
398
|
+
|
|
399
|
+
// Claude Code MCP can emit provisional pre-tool prose that gets
|
|
400
|
+
// superseded by post-tool output. Prune stale text-run segments so
|
|
401
|
+
// the final assistant output remains below tool output.
|
|
402
|
+
if (shouldDropPreToolProse && firstToolIdx >= 0) {
|
|
403
|
+
if (orphanedSegments.length > 0) {
|
|
404
|
+
const remainingOrphans: RenderedSegment[] = [];
|
|
405
|
+
for (const orphan of orphanedSegments) {
|
|
406
|
+
if (orphan.kind === "text-run" && orphan.contentType === "text") {
|
|
407
|
+
host.chatContainer.removeChild(orphan.component);
|
|
408
|
+
if (host.streamingComponent === orphan.component) {
|
|
409
|
+
host.streamingComponent = undefined;
|
|
410
|
+
}
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
remainingOrphans.push(orphan);
|
|
414
|
+
}
|
|
415
|
+
orphanedSegments = remainingOrphans;
|
|
416
|
+
}
|
|
417
|
+
const desiredTextKeys = new Set(
|
|
418
|
+
desired
|
|
419
|
+
.filter((seg): seg is Extract<DesiredSegment, { kind: "text-run" }> => seg.kind === "text-run")
|
|
420
|
+
.map((seg) => `${seg.contentType}:${seg.startIndex}`),
|
|
421
|
+
);
|
|
422
|
+
const desiredToolIndices = new Set(
|
|
423
|
+
desired
|
|
424
|
+
.filter((seg): seg is Extract<DesiredSegment, { kind: "tool" }> => seg.kind === "tool")
|
|
425
|
+
.map((seg) => seg.contentIndex),
|
|
426
|
+
);
|
|
427
|
+
const nextRendered: RenderedSegment[] = [];
|
|
428
|
+
for (const seg of renderedSegments) {
|
|
429
|
+
if (
|
|
430
|
+
seg.kind === "text-run"
|
|
431
|
+
&& seg.contentType === "text"
|
|
432
|
+
&& !desiredTextKeys.has(`${seg.contentType}:${seg.startIndex}`)
|
|
433
|
+
) {
|
|
434
|
+
host.chatContainer.removeChild(seg.component);
|
|
435
|
+
if (host.streamingComponent === seg.component) {
|
|
436
|
+
host.streamingComponent = undefined;
|
|
437
|
+
}
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
if (seg.kind === "tool" && !desiredToolIndices.has(seg.contentIndex)) {
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
nextRendered.push(seg);
|
|
444
|
+
}
|
|
445
|
+
renderedSegments = nextRendered;
|
|
328
446
|
}
|
|
329
447
|
|
|
330
448
|
// Append any newly needed segments (never reorder existing ones).
|
|
@@ -344,18 +462,24 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
344
462
|
} else {
|
|
345
463
|
// text-run segment
|
|
346
464
|
const existing = renderedSegments.find(
|
|
347
|
-
(s) => s.kind === "text-run" && s.startIndex === seg.startIndex,
|
|
465
|
+
(s) => s.kind === "text-run" && s.startIndex === seg.startIndex && s.contentType === seg.contentType,
|
|
348
466
|
);
|
|
349
467
|
if (!existing) {
|
|
350
468
|
const comp = new AssistantMessageComponent(
|
|
351
469
|
undefined,
|
|
352
470
|
host.hideThinkingBlock,
|
|
353
471
|
host.getMarkdownThemeWithSettings(),
|
|
354
|
-
|
|
472
|
+
timestampFormat,
|
|
355
473
|
{ startIndex: seg.startIndex, endIndex: seg.endIndex },
|
|
356
474
|
);
|
|
357
475
|
host.chatContainer.addChild(comp);
|
|
358
|
-
renderedSegments.push({
|
|
476
|
+
renderedSegments.push({
|
|
477
|
+
kind: "text-run",
|
|
478
|
+
startIndex: seg.startIndex,
|
|
479
|
+
endIndex: seg.endIndex,
|
|
480
|
+
contentType: seg.contentType,
|
|
481
|
+
component: comp,
|
|
482
|
+
});
|
|
359
483
|
host.streamingComponent = comp;
|
|
360
484
|
}
|
|
361
485
|
}
|
|
@@ -366,7 +490,9 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
366
490
|
for (const seg of renderedSegments) {
|
|
367
491
|
if (seg.kind === "text-run") {
|
|
368
492
|
// Find corresponding desired segment to get current endIndex
|
|
369
|
-
const d = desired.find(
|
|
493
|
+
const d = desired.find(
|
|
494
|
+
(ds) => ds.kind === "text-run" && ds.startIndex === seg.startIndex && ds.contentType === seg.contentType,
|
|
495
|
+
);
|
|
370
496
|
if (d && d.kind === "text-run" && d.endIndex !== seg.endIndex) {
|
|
371
497
|
seg.endIndex = d.endIndex;
|
|
372
498
|
seg.component.setRange({ startIndex: seg.startIndex, endIndex: seg.endIndex });
|
|
@@ -437,11 +563,11 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
437
563
|
}
|
|
438
564
|
break;
|
|
439
565
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
566
|
+
case "message_end":
|
|
567
|
+
if (event.message.role === "user") break;
|
|
568
|
+
if (event.message.role === "assistant") {
|
|
569
|
+
host.streamingMessage = event.message;
|
|
570
|
+
let errorMessage: string | undefined;
|
|
445
571
|
if (host.streamingMessage.stopReason === "aborted") {
|
|
446
572
|
const retryAttempt = host.session.retryAttempt;
|
|
447
573
|
errorMessage = retryAttempt > 0
|
|
@@ -450,18 +576,144 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
450
576
|
host.streamingMessage.errorMessage = errorMessage;
|
|
451
577
|
}
|
|
452
578
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
579
|
+
const shouldRenderAssistant = hasVisibleAssistantContent(host.streamingMessage)
|
|
580
|
+
|| (
|
|
581
|
+
(host.streamingMessage.stopReason === "aborted" || host.streamingMessage.stopReason === "error")
|
|
582
|
+
&& !hasAssistantToolBlocks(host.streamingMessage)
|
|
583
|
+
);
|
|
584
|
+
|
|
585
|
+
// The final message_end payload can contain additional text/thinking
|
|
586
|
+
// blocks that never arrived via message_update (e.g. SDK result
|
|
587
|
+
// aggregation). Rebuild this in-flight turn from final content so
|
|
588
|
+
// ranges/components don't keep stale partial indices.
|
|
589
|
+
if (renderedSegments.length > 0) {
|
|
590
|
+
const finalBlocks = host.streamingMessage.content;
|
|
591
|
+
type DesiredSegment =
|
|
592
|
+
| { kind: "text-run"; startIndex: number; endIndex: number; contentType: "text" | "thinking" }
|
|
593
|
+
| { kind: "tool"; contentIndex: number; toolId: string };
|
|
594
|
+
const desired: DesiredSegment[] = [];
|
|
595
|
+
let runStart = -1;
|
|
596
|
+
let runEnd = -1;
|
|
597
|
+
let runType: "text" | "thinking" | undefined;
|
|
598
|
+
const closeRun = () => {
|
|
599
|
+
if (runStart !== -1 && runType) {
|
|
600
|
+
desired.push({ kind: "text-run", startIndex: runStart, endIndex: runEnd, contentType: runType });
|
|
601
|
+
runStart = -1;
|
|
602
|
+
runEnd = -1;
|
|
603
|
+
runType = undefined;
|
|
604
|
+
}
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
for (let i = 0; i < finalBlocks.length; i++) {
|
|
608
|
+
const block = finalBlocks[i] as any;
|
|
609
|
+
const blockType = block?.type === "text" || block?.type === "thinking" ? block.type : undefined;
|
|
610
|
+
const isTextLike = blockType === "text" || blockType === "thinking";
|
|
611
|
+
const isTool = block?.type === "toolCall" || block?.type === "serverToolUse";
|
|
612
|
+
|
|
613
|
+
if (isTextLike) {
|
|
614
|
+
if (runStart === -1) {
|
|
615
|
+
runStart = i;
|
|
616
|
+
runEnd = i;
|
|
617
|
+
runType = blockType;
|
|
618
|
+
} else if (runType !== blockType) {
|
|
619
|
+
closeRun();
|
|
620
|
+
runStart = i;
|
|
621
|
+
runEnd = i;
|
|
622
|
+
runType = blockType;
|
|
623
|
+
} else {
|
|
624
|
+
runEnd = i;
|
|
625
|
+
}
|
|
626
|
+
} else {
|
|
627
|
+
closeRun();
|
|
628
|
+
if (isTool) {
|
|
629
|
+
desired.push({ kind: "tool", contentIndex: i, toolId: block.id });
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
closeRun();
|
|
634
|
+
|
|
635
|
+
const toolComponentsById = new Map<string, ToolExecutionComponent>();
|
|
636
|
+
for (const [toolId, component] of host.pendingTools.entries()) {
|
|
637
|
+
toolComponentsById.set(toolId, component);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
for (const seg of renderedSegments) {
|
|
641
|
+
host.chatContainer.removeChild(seg.component);
|
|
642
|
+
if (seg.kind === "tool") {
|
|
643
|
+
const priorBlocks = host.streamingMessage.content;
|
|
644
|
+
const priorBlock = priorBlocks[seg.contentIndex] as any;
|
|
645
|
+
if (priorBlock?.id && !toolComponentsById.has(priorBlock.id)) {
|
|
646
|
+
toolComponentsById.set(priorBlock.id, seg.component);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
renderedSegments = [];
|
|
651
|
+
host.streamingComponent = undefined;
|
|
652
|
+
|
|
653
|
+
for (const seg of desired) {
|
|
654
|
+
if (seg.kind === "tool") {
|
|
655
|
+
const finalBlock = finalBlocks[seg.contentIndex] as any;
|
|
656
|
+
let component = toolComponentsById.get(seg.toolId);
|
|
657
|
+
if (!component && finalBlock?.id) {
|
|
658
|
+
component = host.pendingTools.get(finalBlock.id);
|
|
659
|
+
}
|
|
660
|
+
if (!component && finalBlock?.type === "toolCall") {
|
|
661
|
+
component = new ToolExecutionComponent(
|
|
662
|
+
finalBlock.name,
|
|
663
|
+
finalBlock.arguments,
|
|
664
|
+
{ showImages: host.settingsManager.getShowImages() },
|
|
665
|
+
host.getRegisteredToolDefinition(finalBlock.name),
|
|
666
|
+
host.ui,
|
|
667
|
+
);
|
|
668
|
+
component.setExpanded(host.toolOutputExpanded);
|
|
669
|
+
host.pendingTools.set(finalBlock.id, component);
|
|
670
|
+
toolComponentsById.set(finalBlock.id, component);
|
|
671
|
+
} else if (!component && finalBlock?.type === "serverToolUse") {
|
|
672
|
+
component = new ToolExecutionComponent(
|
|
673
|
+
finalBlock.name,
|
|
674
|
+
finalBlock.input ?? {},
|
|
675
|
+
{ showImages: host.settingsManager.getShowImages() },
|
|
676
|
+
undefined,
|
|
677
|
+
host.ui,
|
|
678
|
+
);
|
|
679
|
+
component.setExpanded(host.toolOutputExpanded);
|
|
680
|
+
host.pendingTools.set(finalBlock.id, component);
|
|
681
|
+
toolComponentsById.set(finalBlock.id, component);
|
|
682
|
+
}
|
|
683
|
+
if (component) {
|
|
684
|
+
host.chatContainer.addChild(component);
|
|
685
|
+
renderedSegments.push({ kind: "tool", contentIndex: seg.contentIndex, component });
|
|
686
|
+
}
|
|
687
|
+
continue;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
const comp = new AssistantMessageComponent(
|
|
691
|
+
undefined,
|
|
692
|
+
host.hideThinkingBlock,
|
|
693
|
+
host.getMarkdownThemeWithSettings(),
|
|
694
|
+
timestampFormat,
|
|
695
|
+
{ startIndex: seg.startIndex, endIndex: seg.endIndex },
|
|
696
|
+
);
|
|
697
|
+
comp.updateContent(host.streamingMessage);
|
|
698
|
+
host.chatContainer.addChild(comp);
|
|
699
|
+
renderedSegments.push({
|
|
700
|
+
kind: "text-run",
|
|
701
|
+
startIndex: seg.startIndex,
|
|
702
|
+
endIndex: seg.endIndex,
|
|
703
|
+
contentType: seg.contentType,
|
|
704
|
+
component: comp,
|
|
705
|
+
});
|
|
706
|
+
host.streamingComponent = comp;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
if (!host.streamingComponent && shouldRenderAssistant) {
|
|
711
|
+
host.streamingComponent = new AssistantMessageComponent(
|
|
712
|
+
undefined,
|
|
713
|
+
host.hideThinkingBlock,
|
|
714
|
+
host.getMarkdownThemeWithSettings(),
|
|
715
|
+
timestampFormat,
|
|
716
|
+
);
|
|
465
717
|
host.chatContainer.addChild(host.streamingComponent);
|
|
466
718
|
}
|
|
467
719
|
if (host.streamingComponent) {
|
|
@@ -490,6 +742,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
490
742
|
host.streamingComponent = undefined;
|
|
491
743
|
host.streamingMessage = undefined;
|
|
492
744
|
renderedSegments = [];
|
|
745
|
+
orphanedSegments = [];
|
|
493
746
|
lastContentLength = 0;
|
|
494
747
|
// Clear pinned output once the message is finalized in the chat
|
|
495
748
|
// container — prevents duplicate display when the agent continues
|
|
@@ -546,11 +799,15 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
546
799
|
host.loadingAnimation = undefined;
|
|
547
800
|
host.statusContainer.clear();
|
|
548
801
|
}
|
|
549
|
-
if (host.streamingComponent) {
|
|
550
|
-
host.
|
|
551
|
-
host.streamingComponent
|
|
552
|
-
host.streamingMessage = undefined;
|
|
802
|
+
if (host.streamingComponent && host.streamingMessage) {
|
|
803
|
+
host.streamingComponent.setShowMetadata(true);
|
|
804
|
+
host.streamingComponent.updateContent(host.streamingMessage);
|
|
553
805
|
}
|
|
806
|
+
host.streamingComponent = undefined;
|
|
807
|
+
host.streamingMessage = undefined;
|
|
808
|
+
renderedSegments = [];
|
|
809
|
+
orphanedSegments = [];
|
|
810
|
+
lastContentLength = 0;
|
|
554
811
|
host.pendingTools.clear();
|
|
555
812
|
// Pinned output is only useful while work is actively streaming.
|
|
556
813
|
// Keep chat history as the single source after completion.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
|
|
4
|
+
import { buildAssistantReplaySegments } from "./interactive-mode.js";
|
|
5
|
+
|
|
6
|
+
test("buildAssistantReplaySegments preserves tool-first ordering", () => {
|
|
7
|
+
const segments = buildAssistantReplaySegments([
|
|
8
|
+
{ type: "toolCall", id: "t1", name: "read", arguments: {} },
|
|
9
|
+
{ type: "text", text: "Done." },
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
assert.deepEqual(segments, [
|
|
13
|
+
{ kind: "tool", contentIndex: 0 },
|
|
14
|
+
{ kind: "assistant", startIndex: 1, endIndex: 1 },
|
|
15
|
+
]);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("buildAssistantReplaySegments preserves interleaved assistant-tool-assistant runs", () => {
|
|
19
|
+
const segments = buildAssistantReplaySegments([
|
|
20
|
+
{ type: "text", text: "Let me check." },
|
|
21
|
+
{ type: "serverToolUse", id: "s1", name: "mcp__fs__glob", input: {} },
|
|
22
|
+
{ type: "thinking", thinking: "Tool result looks good." },
|
|
23
|
+
{ type: "text", text: "Here is the answer." },
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
assert.deepEqual(segments, [
|
|
27
|
+
{ kind: "assistant", startIndex: 0, endIndex: 0 },
|
|
28
|
+
{ kind: "tool", contentIndex: 1 },
|
|
29
|
+
{ kind: "assistant", startIndex: 2, endIndex: 3 },
|
|
30
|
+
]);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("buildAssistantReplaySegments ignores non-rendered non-tool blocks", () => {
|
|
34
|
+
const segments = buildAssistantReplaySegments([
|
|
35
|
+
{ type: "text", text: "before" },
|
|
36
|
+
{ type: "webSearchResult", toolUseId: "s1", content: {} },
|
|
37
|
+
{ type: "text", text: "after" },
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
assert.deepEqual(segments, [
|
|
41
|
+
{ kind: "assistant", startIndex: 0, endIndex: 0 },
|
|
42
|
+
{ kind: "assistant", startIndex: 2, endIndex: 2 },
|
|
43
|
+
]);
|
|
44
|
+
});
|
|
@@ -127,6 +127,45 @@ function isExpandable(obj: unknown): obj is Expandable {
|
|
|
127
127
|
return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
export type AssistantReplaySegment =
|
|
131
|
+
| { kind: "assistant"; startIndex: number; endIndex: number }
|
|
132
|
+
| { kind: "tool"; contentIndex: number };
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Build replay segments for historical assistant messages so rebuild paths
|
|
136
|
+
* preserve the original content[] ordering between assistant prose and tools.
|
|
137
|
+
*/
|
|
138
|
+
export function buildAssistantReplaySegments(contentBlocks: Array<any>): AssistantReplaySegment[] {
|
|
139
|
+
const segments: AssistantReplaySegment[] = [];
|
|
140
|
+
let runStart = -1;
|
|
141
|
+
|
|
142
|
+
for (let i = 0; i < contentBlocks.length; i++) {
|
|
143
|
+
const block = contentBlocks[i];
|
|
144
|
+
const isAssistantText = block?.type === "text" || block?.type === "thinking";
|
|
145
|
+
const isTool = block?.type === "toolCall" || block?.type === "serverToolUse";
|
|
146
|
+
|
|
147
|
+
if (isAssistantText) {
|
|
148
|
+
if (runStart === -1) runStart = i;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (runStart !== -1) {
|
|
153
|
+
segments.push({ kind: "assistant", startIndex: runStart, endIndex: i - 1 });
|
|
154
|
+
runStart = -1;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (isTool) {
|
|
158
|
+
segments.push({ kind: "tool", contentIndex: i });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (runStart !== -1) {
|
|
163
|
+
segments.push({ kind: "assistant", startIndex: runStart, endIndex: contentBlocks.length - 1 });
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return segments;
|
|
167
|
+
}
|
|
168
|
+
|
|
130
169
|
type CompactionQueuedMessage = {
|
|
131
170
|
text: string;
|
|
132
171
|
mode: "steer" | "followUp";
|
|
@@ -1788,6 +1827,8 @@ export class InteractiveMode {
|
|
|
1788
1827
|
this.showError(message);
|
|
1789
1828
|
} else if (type === "warning") {
|
|
1790
1829
|
this.showWarning(message);
|
|
1830
|
+
} else if (type === "success") {
|
|
1831
|
+
this.showSuccess(message);
|
|
1791
1832
|
} else {
|
|
1792
1833
|
this.showStatus(message, { append: true });
|
|
1793
1834
|
}
|
|
@@ -2078,6 +2119,7 @@ export class InteractiveMode {
|
|
|
2078
2119
|
}
|
|
2079
2120
|
|
|
2080
2121
|
private addMessageToChat(message: AgentMessage, options?: { populateHistory?: boolean }): void {
|
|
2122
|
+
const timestampFormat = this.settingsManager.getTimestampFormat();
|
|
2081
2123
|
switch (message.role) {
|
|
2082
2124
|
case "bashExecution": {
|
|
2083
2125
|
const component = new BashExecutionComponent(message.command, this.ui, message.excludeFromContext);
|
|
@@ -2135,12 +2177,12 @@ export class InteractiveMode {
|
|
|
2135
2177
|
skillBlock.userMessage,
|
|
2136
2178
|
this.getMarkdownThemeWithSettings(),
|
|
2137
2179
|
message.timestamp,
|
|
2138
|
-
|
|
2180
|
+
timestampFormat,
|
|
2139
2181
|
);
|
|
2140
2182
|
this.chatContainer.addChild(userComponent);
|
|
2141
2183
|
}
|
|
2142
2184
|
} else {
|
|
2143
|
-
const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings(), message.timestamp,
|
|
2185
|
+
const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings(), message.timestamp, timestampFormat);
|
|
2144
2186
|
this.chatContainer.addChild(userComponent);
|
|
2145
2187
|
}
|
|
2146
2188
|
if (options?.populateHistory) {
|
|
@@ -2154,7 +2196,7 @@ export class InteractiveMode {
|
|
|
2154
2196
|
message,
|
|
2155
2197
|
this.hideThinkingBlock,
|
|
2156
2198
|
this.getMarkdownThemeWithSettings(),
|
|
2157
|
-
|
|
2199
|
+
timestampFormat,
|
|
2158
2200
|
);
|
|
2159
2201
|
this.chatContainer.addChild(assistantComponent);
|
|
2160
2202
|
break;
|
|
@@ -2192,6 +2234,7 @@ export class InteractiveMode {
|
|
|
2192
2234
|
options: { updateFooter?: boolean; populateHistory?: boolean } = {},
|
|
2193
2235
|
): void {
|
|
2194
2236
|
this.pendingTools.clear();
|
|
2237
|
+
const timestampFormat = this.settingsManager.getTimestampFormat();
|
|
2195
2238
|
|
|
2196
2239
|
if (options.updateFooter) {
|
|
2197
2240
|
this.footer.invalidate();
|
|
@@ -2201,9 +2244,30 @@ export class InteractiveMode {
|
|
|
2201
2244
|
for (const message of sessionContext.messages) {
|
|
2202
2245
|
// Assistant messages need special handling for tool calls
|
|
2203
2246
|
if (message.role === "assistant") {
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2247
|
+
const hasToolBlocks = message.content.some((c) => c.type === "toolCall" || c.type === "serverToolUse");
|
|
2248
|
+
if (!hasToolBlocks) {
|
|
2249
|
+
this.addMessageToChat(message);
|
|
2250
|
+
continue;
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2253
|
+
const assistantSegments: AssistantMessageComponent[] = [];
|
|
2254
|
+
const replaySegments = buildAssistantReplaySegments(message.content);
|
|
2255
|
+
|
|
2256
|
+
for (const segment of replaySegments) {
|
|
2257
|
+
if (segment.kind === "assistant") {
|
|
2258
|
+
const assistantComponent = new AssistantMessageComponent(
|
|
2259
|
+
message,
|
|
2260
|
+
this.hideThinkingBlock,
|
|
2261
|
+
this.getMarkdownThemeWithSettings(),
|
|
2262
|
+
timestampFormat,
|
|
2263
|
+
{ startIndex: segment.startIndex, endIndex: segment.endIndex },
|
|
2264
|
+
);
|
|
2265
|
+
this.chatContainer.addChild(assistantComponent);
|
|
2266
|
+
assistantSegments.push(assistantComponent);
|
|
2267
|
+
continue;
|
|
2268
|
+
}
|
|
2269
|
+
|
|
2270
|
+
const content = message.content[segment.contentIndex];
|
|
2207
2271
|
if (content.type === "toolCall") {
|
|
2208
2272
|
const component = new ToolExecutionComponent(
|
|
2209
2273
|
content.name,
|
|
@@ -2259,6 +2323,11 @@ export class InteractiveMode {
|
|
|
2259
2323
|
}
|
|
2260
2324
|
}
|
|
2261
2325
|
}
|
|
2326
|
+
|
|
2327
|
+
// Match streaming-mode behavior: show metadata once on the final
|
|
2328
|
+
// assistant prose segment for this message.
|
|
2329
|
+
const lastAssistantSegment = assistantSegments[assistantSegments.length - 1];
|
|
2330
|
+
lastAssistantSegment?.setShowMetadata(true);
|
|
2262
2331
|
} else if (message.role === "toolResult") {
|
|
2263
2332
|
// Match tool results to pending tool components
|
|
2264
2333
|
const component = this.pendingTools.get(message.toolCallId);
|
|
@@ -2272,6 +2341,12 @@ export class InteractiveMode {
|
|
|
2272
2341
|
}
|
|
2273
2342
|
}
|
|
2274
2343
|
|
|
2344
|
+
// Any pendingTools entries left over after replay are historical tool
|
|
2345
|
+
// calls whose results were squashed out of session context (commonly by
|
|
2346
|
+
// compaction). Mark them finished so the frame stops showing "Running".
|
|
2347
|
+
for (const component of this.pendingTools.values()) {
|
|
2348
|
+
component.markHistoricalNoResult();
|
|
2349
|
+
}
|
|
2275
2350
|
this.pendingTools.clear();
|
|
2276
2351
|
this.trimChatHistory();
|
|
2277
2352
|
this.ui.requestRender();
|
|
@@ -2670,6 +2745,17 @@ export class InteractiveMode {
|
|
|
2670
2745
|
this.ui.requestRender();
|
|
2671
2746
|
}
|
|
2672
2747
|
|
|
2748
|
+
showSuccess(successMessage: string): void {
|
|
2749
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
2750
|
+
this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("success", text)));
|
|
2751
|
+
this.chatContainer.addChild(
|
|
2752
|
+
new Text(theme.fg("success", successMessage), 1, 0),
|
|
2753
|
+
);
|
|
2754
|
+
this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("success", text)));
|
|
2755
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
2756
|
+
this.ui.requestRender();
|
|
2757
|
+
}
|
|
2758
|
+
|
|
2673
2759
|
showTip(message: string): void {
|
|
2674
2760
|
this.chatContainer.addChild(new Spacer(1));
|
|
2675
2761
|
this.chatContainer.addChild(new Text(theme.fg("dim", `💡 ${message}`), 1, 0));
|