@xopcai/xopc 0.0.123 → 0.0.124
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -11
- package/README.zh-CN.md +28 -11
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-Bicr3ZBg.js → agent-avatar-dicebear-B5uSVAyJ.js} +1 -1
- package/dist/gateway/static/root/assets/agents-BjIxt67Z.js +2 -0
- package/dist/gateway/static/root/assets/{app-management-settings-panel-CbEy9sR1.js → app-management-settings-panel-CYCONLIL.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-CTHja6n9.js → appearance-settings-Clw3ryKg.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-QICTeGjX.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-Bpy64GjU.js → archive-plugin-CXUGRp2i.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-DMkp4xSb.js → attachment-load-Cmiub3Wg.js} +1 -1
- package/dist/gateway/static/root/assets/{automation-suggestion-card-KnYaP7NT.js → automation-suggestion-card-CU0-4nQ-.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-Car-jtiz.js +1 -0
- package/dist/gateway/static/root/assets/{binary-plugins-DA9C5mCw.js → binary-plugins-0Izz-N3p.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CiSXk_YC.js → block-editor-C1Kv0IkJ.js} +6 -6
- package/dist/gateway/static/root/assets/browser-settings-page-CMeBJzlS.js +8 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-CEJ44WCU.js → capability-presets-api-BmQTM9Il.js} +1 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-DZEJEoCF.js +1 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-CDhrhfhN.js → channel-recipient-api-BeA2aVor.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-kkW-xFau.js +1 -0
- package/dist/gateway/static/root/assets/connectors-page-BvaQvO5F.js +2 -0
- package/dist/gateway/static/root/assets/{directory-picker-path-field-7jKfbH0J.js → directory-picker-path-field-2rjzUu57.js} +1 -1
- package/dist/gateway/static/root/assets/{dreaming-settings-m1-wmz4o.js → dreaming-settings-DnHO686d.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-C9qQQrBS.js → extension-debug-page-BGLRuWVN.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DcBBMEGl.js → extension-page-D978ePp9.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BQ-jMMP9.js → extension-settings-page-B6Ih4Swx.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-Dtpbbe0s.js → fetch-BU5S0Sn7.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-BN6pyX2c.js → gateway-config-api-BIPGwrl1.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-CMEA3r5u.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-BIET2x3y.js → gateway-startup-retry-Cd0Zz30N.js} +1 -1
- package/dist/gateway/static/root/assets/{goal-create-dialog-BuIMDx6C.js → goal-create-dialog-B-KHKeXN.js} +1 -1
- package/dist/gateway/static/root/assets/goal-detail-page-BxrSoWdj.js +1 -0
- package/dist/gateway/static/root/assets/{goals-config-api-CQm2r1Ty.js → goals-config-api-B95KdGMj.js} +1 -1
- package/dist/gateway/static/root/assets/goals-page-BTJzIl28.js +2 -0
- package/dist/gateway/static/root/assets/{goals-settings-DDrdRMxB.js → goals-settings-BJyEuLLm.js} +1 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-wkOjYNQT.js +1 -0
- package/dist/gateway/static/root/assets/{index-CBDr5xjB.css → index-BLaXr6Ev.css} +1 -1
- package/dist/gateway/static/root/assets/index-c_9TVr_C.js +191 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-C2TuQppb.js → keyboard-shortcuts-settings-BT8T4DyC.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-CrxBJUgI.js +2 -0
- package/dist/gateway/static/root/assets/{markdown-split-DhONQ81k.js → markdown-split-Dv66bO2b.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-DS44pJzr.js → media-plugins-BhIQU5yS.js} +1 -1
- package/dist/gateway/static/root/assets/messages-O6TAtdFC.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-panel-DOOpz6y1.js +2 -0
- package/dist/gateway/static/root/assets/notes-page-Br16pK9v.js +1 -0
- package/dist/gateway/static/root/assets/notes-workbench-PSJAi0ZC.js +2 -0
- package/dist/gateway/static/root/assets/{preview-open-alternatives-Dej6zHnr.js → preview-open-alternatives-DGzet1d7.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-CIGGgKuw.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-B2grhsBt.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-CXMORxBD.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-Zu1FzH6z.js → save-bar-controls-Cqgb-jqa.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-BW78mKc0.js → schedule-field-DVZcI8Yt.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-Cc-IOydE.js → schema-form-Bj7sOxC8.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-Bi2wkBzU.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-B1L3G4IA.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-DIpIYht_.js → settings-collapsible-section-BmXn-8N6.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-BFxBNxOG.js → settings-form-section-BnqYMWHR.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-BfRSHJmO.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-layout-CLx4o2PN.js → settings-page-layout-CdWZU1hd.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-CWtPM7RK.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-ZswWCrDu.js → share-preview-page-IB1v8i86.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-ngbsBgij.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-BIe442Gv.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-BfchZRVa.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-3ZNcGRhS.js → system-settings-panel-BxQ384RC.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-bpzZjiVF.js → typed-models-lib-BkcpvFYO.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-BCjZLZ3O.js → use-channel-catalog-Cd0FaEQ4.js} +1 -1
- package/dist/gateway/static/root/assets/{user-profile-settings-panel-CIXafITi.js → user-profile-settings-panel-DQ7NnRSY.js} +1 -1
- package/dist/gateway/static/root/assets/{utils-DXMtz5j_.js → utils-YKhVf7Ka.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-C5Ov8Uk_.js +1 -0
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-BYD9BtOq.js +3 -0
- package/dist/gateway/static/root/assets/{workflow-start-dialog-B4sZpTDQ.js → workflow-start-dialog-BNJVCWoS.js} +1 -1
- package/dist/gateway/static/root/assets/workflows-page-BYF29ANm.js +18 -0
- package/dist/gateway/static/root/index.html +5 -5
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +6 -1
- package/dist/src/agent/agent-manager.js +28 -12
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/context/workspace-templates/AGENTS.md +1 -1
- package/dist/src/agent/embedded/xopc-tools-bridge.js +11 -7
- package/dist/src/agent/embedded/xopc-tools-bridge.js.map +1 -1
- package/dist/src/agent/lifecycle/progress.js +3 -1
- package/dist/src/agent/lifecycle/progress.js.map +1 -1
- package/dist/src/agent/lifecycle/timeout-wrapper.d.ts +2 -2
- package/dist/src/agent/lifecycle/timeout-wrapper.js +4 -4
- package/dist/src/agent/lifecycle/timeout-wrapper.js.map +1 -1
- package/dist/src/agent/memory/summary-generator.d.ts +1 -1
- package/dist/src/agent/memory/summary-generator.js +1 -2
- package/dist/src/agent/memory/summary-generator.js.map +1 -1
- package/dist/src/agent/middleware/index.d.ts +1 -1
- package/dist/src/agent/middleware/self-verify.d.ts +44 -14
- package/dist/src/agent/middleware/self-verify.js +214 -44
- package/dist/src/agent/middleware/self-verify.js.map +1 -1
- package/dist/src/agent/orchestration/agent-event-handler.js +57 -15
- package/dist/src/agent/orchestration/agent-event-handler.js.map +1 -1
- package/dist/src/agent/prompt/sections/tooling.js +18 -13
- package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
- package/dist/src/agent/prompt/system-reminder.js +2 -2
- package/dist/src/agent/prompt/system-reminder.js.map +1 -1
- package/dist/src/agent/sandbox/sanitize-env-vars.d.ts +2 -2
- package/dist/src/agent/sandbox/sanitize-env-vars.js +2 -2
- package/dist/src/agent/sandbox/sanitize-env-vars.js.map +1 -1
- package/dist/src/agent/sandbox/types.d.ts +2 -2
- package/dist/src/agent/sandbox/types.js.map +1 -1
- package/dist/src/agent/service/btw-query.js +1 -1
- package/dist/src/agent/service/btw-query.js.map +1 -1
- package/dist/src/agent/service/process-direct-one-shot.js +6 -2
- package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
- package/dist/src/agent/service/process-direct-streaming.js +12 -7
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service.js +2 -1
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/skills/skill-tool-gating.js +1 -1
- package/dist/src/agent/skills/skill-tool-gating.js.map +1 -1
- package/dist/src/agent/starter-agents.js +9 -9
- package/dist/src/agent/starter-agents.js.map +1 -1
- package/dist/src/agent/tools/apply-patch.d.ts +25 -0
- package/dist/src/agent/tools/apply-patch.js +256 -0
- package/dist/src/agent/tools/apply-patch.js.map +1 -0
- package/dist/src/agent/tools/delegate-tool.d.ts +1 -1
- package/dist/src/agent/tools/delegate-tool.js +3 -3
- package/dist/src/agent/tools/delegate-tool.js.map +1 -1
- package/dist/src/agent/tools/exec-command.d.ts +30 -0
- package/dist/src/agent/tools/exec-command.js +224 -0
- package/dist/src/agent/tools/exec-command.js.map +1 -0
- package/dist/src/agent/tools/execute-code-tool.js +7 -4
- package/dist/src/agent/tools/execute-code-tool.js.map +1 -1
- package/dist/src/agent/tools/factory.d.ts +3 -3
- package/dist/src/agent/tools/factory.js +7 -8
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/index.d.ts +3 -2
- package/dist/src/agent/tools/index.js +5 -4
- package/dist/src/agent/tools/skills-tools.d.ts +1 -1
- package/dist/src/agent/tools/skills-tools.js.map +1 -1
- package/dist/src/agent/tools/update-plan-tool.d.ts +11 -0
- package/dist/src/agent/tools/update-plan-tool.js +72 -0
- package/dist/src/agent/tools/update-plan-tool.js.map +1 -0
- package/dist/src/agent/workflow/builtins/debug-incident.d.ts +1 -1
- package/dist/src/agent/workflow/builtins/debug-incident.js +1 -1
- package/dist/src/agent/workflow/builtins/debug-incident.js.map +1 -1
- package/dist/src/agent/workflow/builtins/pr-review.d.ts +1 -1
- package/dist/src/agent/workflow/builtins/pr-review.js +1 -1
- package/dist/src/agent/workflow/builtins/pr-review.js.map +1 -1
- package/dist/src/agent/workflow/builtins/release-check.d.ts +1 -1
- package/dist/src/agent/workflow/builtins/release-check.js +1 -1
- package/dist/src/agent/workflow/builtins/release-check.js.map +1 -1
- package/dist/src/agent/workflow/step-labels.js +7 -3
- package/dist/src/agent/workflow/step-labels.js.map +1 -1
- package/dist/src/chat-commands/agent-edit.js +1 -1
- package/dist/src/chat-commands/agent-edit.js.map +1 -1
- package/dist/src/chat-commands/builtins/review.d.ts +1 -0
- package/dist/src/chat-commands/builtins/review.js +167 -0
- package/dist/src/chat-commands/builtins/review.js.map +1 -0
- package/dist/src/chat-commands/index.d.ts +1 -0
- package/dist/src/chat-commands/index.js +3 -1
- package/dist/src/chat-commands/index.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
- package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
- package/dist/src/gateway/agent-builtin-tools.js +3 -2
- package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
- package/dist/src/gateway/chat-stream/mapper.d.ts +6 -0
- package/dist/src/gateway/chat-stream/mapper.js +149 -6
- package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
- package/dist/src/gateway/chat-stream/protocol.d.ts +51 -1
- package/dist/src/gateway/hono/routes/commands-skills.js +21 -0
- package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
- package/dist/src/gateway/hono/routes/index.js +2 -0
- package/dist/src/gateway/hono/routes/index.js.map +1 -1
- package/dist/src/gateway/hono/routes/lazy-bundles.js +1 -0
- package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
- package/dist/src/gateway/hono/routes/projects.js +40 -2
- package/dist/src/gateway/hono/routes/projects.js.map +1 -1
- package/dist/src/gateway/hono/routes/search.d.ts +3 -0
- package/dist/src/gateway/hono/routes/search.js +47 -0
- package/dist/src/gateway/hono/routes/search.js.map +1 -0
- package/dist/src/gateway/security/dangerous-tools.js +1 -1
- package/dist/src/gateway/security/dangerous-tools.js.map +1 -1
- package/dist/src/infra/update-restart.js +1 -1
- package/dist/src/mcp/channel-bridge.js +1 -1
- package/dist/src/projects/index.d.ts +2 -0
- package/dist/src/projects/index.js +3 -1
- package/dist/src/projects/project-agent-suggestion.d.ts +14 -0
- package/dist/src/projects/project-agent-suggestion.js +19 -0
- package/dist/src/projects/project-agent-suggestion.js.map +1 -0
- package/dist/src/projects/project-kind.d.ts +13 -0
- package/dist/src/projects/project-kind.js +147 -0
- package/dist/src/projects/project-kind.js.map +1 -0
- package/dist/src/projects/project-service.d.ts +1 -0
- package/dist/src/projects/project-service.js +1 -1
- package/dist/src/projects/project-service.js.map +1 -1
- package/dist/src/projects/project-store.js +32 -8
- package/dist/src/projects/project-store.js.map +1 -1
- package/dist/src/projects/types.d.ts +1 -0
- package/dist/src/review/review-git.d.ts +48 -0
- package/dist/src/review/review-git.js +333 -0
- package/dist/src/review/review-git.js.map +1 -0
- package/dist/src/review/review-types.d.ts +22 -0
- package/dist/src/review/review-types.js +29 -0
- package/dist/src/review/review-types.js.map +1 -0
- package/dist/src/session/session-context-for-llm.js +151 -0
- package/dist/src/session/session-context-for-llm.js.map +1 -1
- package/dist/src/storage/sqlite/migrations/021_projects_fts.sql +21 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/tui/backends/embedded-backend.d.ts +1 -0
- package/dist/src/tui/backends/embedded-backend.js +20 -0
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.d.ts +2 -0
- package/dist/src/tui/backends/gateway-sse-backend.js +7 -0
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/components/assistant-message.js +35 -0
- package/dist/src/tui/components/assistant-message.js.map +1 -1
- package/dist/src/tui/tui-agent-events.js +25 -0
- package/dist/src/tui/tui-agent-events.js.map +1 -1
- package/dist/src/tui/tui-backend.d.ts +4 -0
- package/dist/src/tui/tui-commands.d.ts +1 -0
- package/dist/src/tui/tui-commands.js +110 -4
- package/dist/src/tui/tui-commands.js.map +1 -1
- package/dist/src/tui/tui-picker-overlay.d.ts +2 -0
- package/dist/src/tui/tui-picker-overlay.js +153 -1
- package/dist/src/tui/tui-picker-overlay.js.map +1 -1
- package/dist/src/tui/tui.js +16 -3
- package/dist/src/tui/tui.js.map +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/agents-CxDSFHGx.js +0 -2
- package/dist/gateway/static/root/assets/apps-page-CyZdgqvm.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-8VLKM4au.js +0 -1
- package/dist/gateway/static/root/assets/browser-settings-page-5tPg0DcP.js +0 -8
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-BJW3aVST.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-CorUCTrs.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-VKstC3sP.js +0 -2
- package/dist/gateway/static/root/assets/gateway-settings-hQtgVmSR.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-FEypCq74.js +0 -1
- package/dist/gateway/static/root/assets/goals-page-C4-2_MLG.js +0 -2
- package/dist/gateway/static/root/assets/heartbeat-settings-BJVok3Sl.js +0 -1
- package/dist/gateway/static/root/assets/index-T0SaNd5a.js +0 -191
- package/dist/gateway/static/root/assets/logs-page-DwkwPgid.js +0 -2
- package/dist/gateway/static/root/assets/messages-avfvyZuQ.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-panel-huNY4A1G.js +0 -2
- package/dist/gateway/static/root/assets/notes-page-DdfGuEZ1.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-B0bT9Hqa.js +0 -2
- package/dist/gateway/static/root/assets/project-detail-page-CjxhPorG.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-C4Z5OJMF.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-CVCOPUVd.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-B4qExXHC.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-Ce8yLTBi.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-C4fivemT.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Kyc4eUf0.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-Bu76CMiC.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-D-CFg86j.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-CUU4f6Ss.js +0 -2
- package/dist/gateway/static/root/assets/voice-api-key-field-C1MrQD8R.js +0 -1
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-DqizIcY5.js +0 -3
- package/dist/gateway/static/root/assets/workflows-page-B3sVNPFk.js +0 -18
- package/dist/src/agent/tools/edit.d.ts +0 -14
- package/dist/src/agent/tools/edit.js +0 -132
- package/dist/src/agent/tools/edit.js.map +0 -1
- package/dist/src/agent/tools/shell.d.ts +0 -15
- package/dist/src/agent/tools/shell.js +0 -158
- package/dist/src/agent/tools/shell.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant-message.js","names":[],"sources":["../../../../src/tui/components/assistant-message.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport { Container, Markdown, Spacer, Text } from '@earendil-works/pi-tui';\n\nimport { markdownTheme, theme } from '../theme.js';\n\nconst OSC133_ZONE_START = '\\x1b]133;A\\x07';\nconst OSC133_ZONE_END = '\\x1b]133;B\\x07';\nconst OSC133_ZONE_FINAL = '\\x1b]133;C\\x07';\n\nexport type AssistantMessageOptions = {\n hideThinkingBlock?: boolean;\n hiddenThinkingLabel?: string;\n};\n\ntype ContentBlock = Record<string, unknown> & { type?: string };\n\nfunction contentBlocks(message: AgentMessage | undefined): ContentBlock[] {\n const content = (message as { content?: unknown } | undefined)?.content;\n if (typeof content === 'string') {\n return content.trim() ? [{ type: 'text', text: content }] : [];\n }\n return Array.isArray(content)\n ? content.filter((block): block is ContentBlock => !!block && typeof block === 'object')\n : [];\n}\n\nfunction blockText(block: ContentBlock, key: 'text' | 'thinking'): string {\n const value = block[key];\n return typeof value === 'string' ? value : '';\n}\n\nfunction hasToolCalls(message: AgentMessage | undefined): boolean {\n return contentBlocks(message).some((block) => block.type === 'toolCall' || block.type === 'tool_use');\n}\n\nfunction stopReason(message: AgentMessage | undefined): string | undefined {\n return (message as { stopReason?: string } | undefined)?.stopReason;\n}\n\nfunction errorMessage(message: AgentMessage | undefined): string | undefined {\n return (message as { errorMessage?: string } | undefined)?.errorMessage;\n}\n\nexport function createAssistantMessageFromText(text: string): AgentMessage {\n return {\n role: 'assistant',\n content: [{ type: 'text', text }],\n timestamp: Date.now(),\n } as AgentMessage;\n}\n\nexport class AssistantMessageComponent extends Container {\n private readonly contentContainer = new Container();\n private message: AgentMessage | undefined;\n private linkedToolCall = false;\n private hideThinkingBlock = false;\n private hiddenThinkingLabel = 'Thinking...';\n\n constructor(message?: AgentMessage, options: AssistantMessageOptions = {}) {\n super();\n this.hideThinkingBlock = options.hideThinkingBlock ?? false;\n this.hiddenThinkingLabel = options.hiddenThinkingLabel ?? 'Thinking...';\n this.addChild(this.contentContainer);\n if (message) {\n this.updateContent(message);\n }\n }\n\n updateContent(message: AgentMessage): void {\n this.message = message;\n this.refresh();\n }\n\n setHasToolCalls(hasTools: boolean): void {\n this.linkedToolCall = hasTools;\n this.refresh();\n }\n\n setHideThinkingBlock(hide: boolean): void {\n if (this.hideThinkingBlock === hide) return;\n this.hideThinkingBlock = hide;\n this.refresh();\n }\n\n setHiddenThinkingLabel(label: string): void {\n if (this.hiddenThinkingLabel === label) return;\n this.hiddenThinkingLabel = label;\n this.refresh();\n }\n\n override invalidate(): void {\n super.invalidate();\n this.refresh();\n }\n\n override render(width: number): string[] {\n const lines = super.render(width);\n if (hasToolCalls(this.message) || this.linkedToolCall || lines.length === 0) return lines;\n lines[0] = OSC133_ZONE_START + lines[0];\n lines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n return lines;\n }\n\n private refresh(): void {\n this.contentContainer.clear();\n const blocks = contentBlocks(this.message);\n const visibleBlocks = blocks.filter((block) => {\n if (block.type === 'text') return blockText(block, 'text').trim().length > 0;\n if (block.type === 'thinking') return blockText(block, 'thinking').trim().length > 0;\n if (block.type === 'image' || block.type === 'image_url') return true;\n return false;\n });\n const reason = stopReason(this.message);\n const hasErrorState =\n !hasToolCalls(this.message) && !this.linkedToolCall && (reason === 'aborted' || reason === 'error');\n if (visibleBlocks.length === 0 && !hasErrorState) return;\n\n this.contentContainer.addChild(new Spacer(1));\n let renderedVisible = 0;\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i]!;\n if (block.type === 'text') {\n const text = blockText(block, 'text').trim();\n if (!text) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.assistantText(line) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n } else if (block.type === 'thinking') {\n const thinking = blockText(block, 'thinking').trim();\n if (!thinking) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n const text = this.hideThinkingBlock ? this.hiddenThinkingLabel : thinking;\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.dim(theme.italic(line)) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n } else if (block.type === 'image' || block.type === 'image_url') {\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(new Text(theme.dim('[image]'), 1, 0));\n renderedVisible++;\n }\n }\n\n if (hasErrorState) {\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n const text =\n reason === 'aborted'\n ? errorMessage(this.message) && errorMessage(this.message) !== 'Request was aborted'\n ? errorMessage(this.message)!\n : 'Operation aborted'\n : `Error: ${errorMessage(this.message) || 'Unknown error'}`;\n this.contentContainer.addChild(new Text(theme.error(text), 1, 0));\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"assistant-message.js","names":[],"sources":["../../../../src/tui/components/assistant-message.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport { Container, Markdown, Spacer, Text } from '@earendil-works/pi-tui';\n\nimport { markdownTheme, theme } from '../theme.js';\n\nconst OSC133_ZONE_START = '\\x1b]133;A\\x07';\nconst OSC133_ZONE_END = '\\x1b]133;B\\x07';\nconst OSC133_ZONE_FINAL = '\\x1b]133;C\\x07';\n\nexport type AssistantMessageOptions = {\n hideThinkingBlock?: boolean;\n hiddenThinkingLabel?: string;\n};\n\ntype ContentBlock = Record<string, unknown> & { type?: string };\n\nfunction contentBlocks(message: AgentMessage | undefined): ContentBlock[] {\n const content = (message as { content?: unknown } | undefined)?.content;\n if (typeof content === 'string') {\n return content.trim() ? [{ type: 'text', text: content }] : [];\n }\n return Array.isArray(content)\n ? content.filter((block): block is ContentBlock => !!block && typeof block === 'object')\n : [];\n}\n\nfunction blockText(block: ContentBlock, key: 'text' | 'thinking'): string {\n const value = block[key];\n return typeof value === 'string' ? value : '';\n}\n\nfunction reviewMarkdown(block: ContentBlock): string {\n const findings = Array.isArray(block.findings) ? block.findings : [];\n const lines: string[] = ['Code review', ''];\n if (findings.length === 0) {\n lines.push('No findings.');\n } else {\n lines.push('Findings:');\n for (const item of findings) {\n if (!item || typeof item !== 'object' || Array.isArray(item)) continue;\n const rec = item as Record<string, unknown>;\n const title = typeof rec.title === 'string' ? rec.title : '';\n const body = typeof rec.body === 'string' ? rec.body : '';\n const priority = typeof rec.priority === 'number' ? rec.priority : 2;\n const filePath = typeof rec.filePath === 'string' ? rec.filePath : '';\n const lineStart = typeof rec.lineStart === 'number' ? rec.lineStart : undefined;\n const lineEnd = typeof rec.lineEnd === 'number' ? rec.lineEnd : undefined;\n const loc = filePath\n ? `${filePath}${lineStart ? `:${lineStart}${lineEnd && lineEnd !== lineStart ? `-${lineEnd}` : ''}` : ''}`\n : '';\n const suffix = loc ? ` - ${loc}` : '';\n lines.push(`- [P${priority}] ${title || body.slice(0, 80)}${suffix}`);\n if (body) lines.push(` ${body.replace(/\\n+/g, '\\n ')}`);\n }\n }\n const correctness = typeof block.overallCorrectness === 'string' ? block.overallCorrectness : 'unknown';\n const explanation = typeof block.overallExplanation === 'string' ? block.overallExplanation : '';\n lines.push('');\n lines.push(`Overall correctness: ${correctness}`);\n if (explanation) lines.push(explanation);\n return lines.join('\\n');\n}\n\nfunction hasToolCalls(message: AgentMessage | undefined): boolean {\n return contentBlocks(message).some((block) => block.type === 'toolCall' || block.type === 'tool_use');\n}\n\nfunction stopReason(message: AgentMessage | undefined): string | undefined {\n return (message as { stopReason?: string } | undefined)?.stopReason;\n}\n\nfunction errorMessage(message: AgentMessage | undefined): string | undefined {\n return (message as { errorMessage?: string } | undefined)?.errorMessage;\n}\n\nexport function createAssistantMessageFromText(text: string): AgentMessage {\n return {\n role: 'assistant',\n content: [{ type: 'text', text }],\n timestamp: Date.now(),\n } as AgentMessage;\n}\n\nexport class AssistantMessageComponent extends Container {\n private readonly contentContainer = new Container();\n private message: AgentMessage | undefined;\n private linkedToolCall = false;\n private hideThinkingBlock = false;\n private hiddenThinkingLabel = 'Thinking...';\n\n constructor(message?: AgentMessage, options: AssistantMessageOptions = {}) {\n super();\n this.hideThinkingBlock = options.hideThinkingBlock ?? false;\n this.hiddenThinkingLabel = options.hiddenThinkingLabel ?? 'Thinking...';\n this.addChild(this.contentContainer);\n if (message) {\n this.updateContent(message);\n }\n }\n\n updateContent(message: AgentMessage): void {\n this.message = message;\n this.refresh();\n }\n\n setHasToolCalls(hasTools: boolean): void {\n this.linkedToolCall = hasTools;\n this.refresh();\n }\n\n setHideThinkingBlock(hide: boolean): void {\n if (this.hideThinkingBlock === hide) return;\n this.hideThinkingBlock = hide;\n this.refresh();\n }\n\n setHiddenThinkingLabel(label: string): void {\n if (this.hiddenThinkingLabel === label) return;\n this.hiddenThinkingLabel = label;\n this.refresh();\n }\n\n override invalidate(): void {\n super.invalidate();\n this.refresh();\n }\n\n override render(width: number): string[] {\n const lines = super.render(width);\n if (hasToolCalls(this.message) || this.linkedToolCall || lines.length === 0) return lines;\n lines[0] = OSC133_ZONE_START + lines[0];\n lines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n return lines;\n }\n\n private refresh(): void {\n this.contentContainer.clear();\n const blocks = contentBlocks(this.message);\n const visibleBlocks = blocks.filter((block) => {\n if (block.type === 'text') return blockText(block, 'text').trim().length > 0;\n if (block.type === 'thinking') return blockText(block, 'thinking').trim().length > 0;\n if (block.type === 'image' || block.type === 'image_url') return true;\n if (block.type === 'review') return true;\n return false;\n });\n const reason = stopReason(this.message);\n const hasErrorState =\n !hasToolCalls(this.message) && !this.linkedToolCall && (reason === 'aborted' || reason === 'error');\n if (visibleBlocks.length === 0 && !hasErrorState) return;\n\n this.contentContainer.addChild(new Spacer(1));\n let renderedVisible = 0;\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i]!;\n if (block.type === 'text') {\n const text = blockText(block, 'text').trim();\n if (!text) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.assistantText(line) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n } else if (block.type === 'thinking') {\n const thinking = blockText(block, 'thinking').trim();\n if (!thinking) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n const text = this.hideThinkingBlock ? this.hiddenThinkingLabel : thinking;\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.dim(theme.italic(line)) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n } else if (block.type === 'image' || block.type === 'image_url') {\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(new Text(theme.dim('[image]'), 1, 0));\n renderedVisible++;\n } else if (block.type === 'review') {\n const text = reviewMarkdown(block).trim();\n if (!text) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.assistantText(line) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n }\n }\n\n if (hasErrorState) {\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n const text =\n reason === 'aborted'\n ? errorMessage(this.message) && errorMessage(this.message) !== 'Request was aborted'\n ? errorMessage(this.message)!\n : 'Operation aborted'\n : `Error: ${errorMessage(this.message) || 'Unknown error'}`;\n this.contentContainer.addChild(new Text(theme.error(text), 1, 0));\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -19,6 +19,7 @@ const STREAM_TOUCH_EVENTS = new Set([
|
|
|
19
19
|
"assistant_delta",
|
|
20
20
|
"thinking_delta",
|
|
21
21
|
"thinking_end",
|
|
22
|
+
"review",
|
|
22
23
|
"tool_start",
|
|
23
24
|
"tool_update",
|
|
24
25
|
"tool_end",
|
|
@@ -95,6 +96,21 @@ function appendThinkingText(message, delta) {
|
|
|
95
96
|
streaming: true
|
|
96
97
|
});
|
|
97
98
|
}
|
|
99
|
+
function appendReviewBlock(message, review) {
|
|
100
|
+
if (!review || typeof review !== "object" || Array.isArray(review)) return;
|
|
101
|
+
const rec = review;
|
|
102
|
+
if (rec.type !== "review") return;
|
|
103
|
+
const msg = message;
|
|
104
|
+
if (!Array.isArray(msg.content)) msg.content = [];
|
|
105
|
+
const content = msg.content;
|
|
106
|
+
const target = typeof rec.target === "string" ? rec.target : "working tree changes";
|
|
107
|
+
const existing = content.findIndex((block) => block.type === "review" && block.target === target);
|
|
108
|
+
if (existing >= 0) {
|
|
109
|
+
content[existing] = review;
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
content.push(review);
|
|
113
|
+
}
|
|
98
114
|
function finalizeThinking(message) {
|
|
99
115
|
const content = message.content;
|
|
100
116
|
if (!Array.isArray(content)) return;
|
|
@@ -170,6 +186,15 @@ function dispatchAgentEvent(event, data, state, chatLog, tui, setActivityStatus,
|
|
|
170
186
|
tui.requestRender();
|
|
171
187
|
break;
|
|
172
188
|
}
|
|
189
|
+
case "review": {
|
|
190
|
+
const message = assistantForRun(runId);
|
|
191
|
+
appendReviewBlock(message, p.review);
|
|
192
|
+
chatLog.updateAssistant(message, runId);
|
|
193
|
+
markRunEvent(state, "streaming", runId, event, source);
|
|
194
|
+
setActivityStatus("streaming");
|
|
195
|
+
tui.requestRender();
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
173
198
|
case "tool_start": {
|
|
174
199
|
const toolName = String(p.toolName ?? "unknown");
|
|
175
200
|
const toolCallId = String(p.toolCallId || "");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui-agent-events.js","names":[],"sources":["../../../src/tui/tui-agent-events.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { TUI } from '@earendil-works/pi-tui';\n\nimport { formatAgentRunErrorForDisplay } from '../agent/client-error-format.js';\nimport type { ChatLog } from './components/chat-log.js';\nimport { createAssistantMessageFromText } from './components/assistant-message.js';\nimport { markRunEvent, markRunIdleAfterCompletion } from './tui-run-state.js';\nimport type { TuiEventSource, TuiState } from './tui-types.js';\n\nconst seenStreamEventKeys = new Set<string>();\nconst assistantByRun = new Map<string, AgentMessage>();\n\nexport function clearSeenStreamEvents(): void {\n seenStreamEventKeys.clear();\n assistantByRun.clear();\n}\n\nexport function clearSeenStreamEventsForRun(runId: string): void {\n const prefix = `${runId}:`;\n for (const key of Array.from(seenStreamEventKeys)) {\n if (key.startsWith(prefix)) seenStreamEventKeys.delete(key);\n }\n assistantByRun.delete(runId);\n}\n\nconst STREAM_TOUCH_EVENTS = new Set([\n 'run_start',\n 'assistant_message_start',\n 'assistant_delta',\n 'thinking_delta',\n 'thinking_end',\n 'tool_start',\n 'tool_update',\n 'tool_end',\n 'assistant_message_end',\n 'progress',\n]);\n\nconst DIRECT_RESPONSE_OWNED_EVENTS = new Set([...STREAM_TOUCH_EVENTS, 'run_end', 'error']);\n\nfunction resolveEventRunId(data: Record<string, unknown>, state: TuiState): string | null {\n if (typeof data.runId === 'string' && data.runId) return data.runId;\n return state.activeRunId ?? state.runStatus.runId ?? state.runStatus.lastCompletedRunId;\n}\n\nexport function shouldSkipDuplicateBroadcastEvent(\n event: string,\n data: Record<string, unknown>,\n state: TuiState,\n source: TuiEventSource,\n): boolean {\n if (source !== 'broadcast') return false;\n if (!DIRECT_RESPONSE_OWNED_EVENTS.has(event)) return false;\n const directRunId = state.runStatus.directStreamRunId;\n if (!directRunId) return false;\n return resolveEventRunId(data, state) === directRunId;\n}\n\nfunction streamEventKey(data: Record<string, unknown>, state: TuiState): string | null {\n const runId = resolveEventRunId(data, state);\n const seq = data.seq;\n if (!runId || typeof seq !== 'number' || !Number.isFinite(seq)) return null;\n return `${runId}:${seq}`;\n}\n\nfunction shouldSkipSeenStreamEvent(\n data: Record<string, unknown>,\n state: TuiState,\n source: TuiEventSource,\n): boolean {\n if (source !== 'agent-response' && source !== 'agent-resume' && source !== 'broadcast') return false;\n const key = streamEventKey(data, state);\n if (!key) return false;\n if (seenStreamEventKeys.has(key)) return true;\n seenStreamEventKeys.add(key);\n return false;\n}\n\nfunction payload(data: Record<string, unknown>): Record<string, unknown> {\n return data.payload && typeof data.payload === 'object' ? data.payload as Record<string, unknown> : {};\n}\n\nfunction assistantForRun(runId: string): AgentMessage {\n let message = assistantByRun.get(runId);\n if (!message) {\n message = createAssistantMessageFromText('') as AgentMessage;\n assistantByRun.set(runId, message);\n }\n return message;\n}\n\nfunction appendAssistantText(message: AgentMessage, delta: string): void {\n const rec = message as { content?: unknown };\n if (!Array.isArray(rec.content)) rec.content = [];\n const content = rec.content as Array<Record<string, unknown>>;\n const last = content[content.length - 1];\n if (last?.type === 'text' && typeof last.text === 'string') {\n last.text += delta;\n return;\n }\n content.push({ type: 'text', text: delta });\n}\n\nfunction appendThinkingText(message: AgentMessage, delta: string): void {\n const rec = message as { content?: unknown };\n if (!Array.isArray(rec.content)) rec.content = [];\n const content = rec.content as Array<Record<string, unknown>>;\n const last = content[content.length - 1];\n if (last?.type === 'thinking' && typeof last.text === 'string') {\n last.text += delta;\n return;\n }\n content.push({ type: 'thinking', text: delta, streaming: true });\n}\n\nfunction finalizeThinking(message: AgentMessage): void {\n const content = (message as { content?: unknown }).content;\n if (!Array.isArray(content)) return;\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n const rec = block as { type?: unknown; streaming?: boolean };\n if (rec.type === 'thinking') rec.streaming = false;\n }\n}\n\nfunction errorAssistantMessage(errorContent: string): AgentMessage {\n return {\n ...createAssistantMessageFromText(''),\n stopReason: 'error',\n errorMessage: errorContent,\n } as AgentMessage;\n}\n\nexport function dispatchAgentEvent(\n event: string,\n data: Record<string, unknown>,\n state: TuiState,\n chatLog: ChatLog,\n tui: TUI,\n setActivityStatus: (status: string) => void,\n touchStreamingActivity?: () => void,\n onRunEnded?: () => void,\n onAssistantFinalized?: (message: AgentMessage, options?: { errorMessage?: string }) => void,\n source: TuiEventSource = 'unknown',\n): void {\n if (shouldSkipSeenStreamEvent(data, state, source)) return;\n if (shouldSkipDuplicateBroadcastEvent(event, data, state, source)) return;\n\n if (STREAM_TOUCH_EVENTS.has(event)) touchStreamingActivity?.();\n\n const runId = resolveEventRunId(data, state) ?? state.activeRunId ?? 'default';\n const p = payload(data);\n\n switch (event) {\n case 'run_start': {\n state.activeRunId = runId;\n markRunEvent(state, 'waiting', runId, event, source);\n setActivityStatus('waiting');\n break;\n }\n case 'user_message': {\n const message = p.message as { content?: unknown } | undefined;\n chatLog.addUser(Array.isArray(message?.content) || typeof message?.content === 'string' ? message.content : []);\n tui.requestRender();\n break;\n }\n case 'user_transcript': {\n chatLog.addUser(String(p.text ?? ''));\n tui.requestRender();\n break;\n }\n case 'assistant_message_start': {\n const message = assistantForRun(runId);\n chatLog.startAssistant(message, runId);\n markRunEvent(state, 'streaming', runId, event, source);\n setActivityStatus('streaming');\n tui.requestRender();\n break;\n }\n case 'assistant_delta': {\n const delta = typeof p.delta === 'string' ? p.delta : '';\n if (!delta) break;\n const message = assistantForRun(runId);\n appendAssistantText(message, delta);\n chatLog.updateAssistant(message, runId);\n markRunEvent(state, 'streaming', runId, event, source);\n setActivityStatus('streaming');\n tui.requestRender();\n break;\n }\n case 'thinking_delta': {\n const delta = typeof p.delta === 'string' ? p.delta : '';\n if (!delta) break;\n const message = assistantForRun(runId);\n appendThinkingText(message, delta);\n chatLog.updateAssistant(message, runId);\n markRunEvent(state, 'streaming', runId, event, source);\n setActivityStatus('streaming');\n tui.requestRender();\n break;\n }\n case 'thinking_end': {\n const message = assistantForRun(runId);\n finalizeThinking(message);\n chatLog.updateAssistant(message, runId);\n tui.requestRender();\n break;\n }\n case 'tool_start': {\n const toolName = String(p.toolName ?? 'unknown');\n const toolCallId = String(p.toolCallId || '');\n if (!toolCallId) break;\n chatLog.startTool(toolCallId, toolName, p.args ?? {}, runId);\n chatLog.markToolExecutionStarted(toolCallId);\n markRunEvent(state, 'tool', runId, event, source);\n setActivityStatus('running');\n tui.requestRender();\n break;\n }\n case 'tool_update': {\n const toolName = String(p.toolName ?? 'unknown');\n const toolCallId = String(p.toolCallId || '');\n if (!toolCallId) break;\n chatLog.startTool(toolCallId, toolName, {}, runId);\n if ('details' in p) chatLog.updateToolDetails(toolCallId, p.details);\n if (typeof p.textDelta === 'string') chatLog.updateToolResult(toolCallId, { text: p.textDelta }, false, true);\n markRunEvent(state, 'tool', runId, event, source);\n setActivityStatus('running');\n tui.requestRender();\n break;\n }\n case 'tool_end': {\n const toolCallId = String(p.toolCallId || '');\n if (!toolCallId) break;\n chatLog.updateToolResult(toolCallId, p.result, p.status === 'error' || p.status === 'cancelled', false);\n markRunEvent(state, 'streaming', runId, event, source);\n setActivityStatus('streaming');\n tui.requestRender();\n break;\n }\n case 'assistant_message_end': {\n const message = assistantForRun(runId);\n finalizeThinking(message);\n chatLog.finalizeAssistant(message, runId);\n assistantByRun.delete(runId);\n onAssistantFinalized?.(message);\n markRunEvent(state, 'streaming', runId, event, source);\n setActivityStatus('streaming');\n tui.requestRender();\n break;\n }\n case 'error': {\n const errorContent = formatAgentRunErrorForDisplay(String(p.message ?? 'Unknown error'));\n const message = errorAssistantMessage(errorContent);\n chatLog.finalizeAssistant(message, runId);\n onAssistantFinalized?.(message, { errorMessage: errorContent });\n assistantByRun.delete(runId);\n state.activeRunId = null;\n markRunIdleAfterCompletion(state, runId, event, source);\n setActivityStatus('idle');\n onRunEnded?.();\n tui.requestRender();\n break;\n }\n case 'run_end': {\n assistantByRun.delete(runId);\n state.activeRunId = null;\n markRunIdleAfterCompletion(state, runId, event, source);\n setActivityStatus('idle');\n onRunEnded?.();\n tui.requestRender();\n break;\n }\n case 'progress': {\n const stage = typeof p.stage === 'string' ? p.stage : '';\n const message = typeof p.message === 'string' ? p.message : stage;\n state.progressMessage = message || null;\n markRunEvent(state, 'progress', runId, event, source);\n setActivityStatus(message ? `progress: ${message}` : 'running');\n tui.requestRender();\n break;\n }\n }\n}\n\nexport const DEFAULT_STREAMING_WATCHDOG_MS = 30_000;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tui-agent-events.js","names":[],"sources":["../../../src/tui/tui-agent-events.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { TUI } from '@earendil-works/pi-tui';\n\nimport { formatAgentRunErrorForDisplay } from '../agent/client-error-format.js';\nimport type { ChatLog } from './components/chat-log.js';\nimport { createAssistantMessageFromText } from './components/assistant-message.js';\nimport { markRunEvent, markRunIdleAfterCompletion } from './tui-run-state.js';\nimport type { TuiEventSource, TuiState } from './tui-types.js';\n\nconst seenStreamEventKeys = new Set<string>();\nconst assistantByRun = new Map<string, AgentMessage>();\n\nexport function clearSeenStreamEvents(): void {\n seenStreamEventKeys.clear();\n assistantByRun.clear();\n}\n\nexport function clearSeenStreamEventsForRun(runId: string): void {\n const prefix = `${runId}:`;\n for (const key of Array.from(seenStreamEventKeys)) {\n if (key.startsWith(prefix)) seenStreamEventKeys.delete(key);\n }\n assistantByRun.delete(runId);\n}\n\nconst STREAM_TOUCH_EVENTS = new Set([\n 'run_start',\n 'assistant_message_start',\n 'assistant_delta',\n 'thinking_delta',\n 'thinking_end',\n 'review',\n 'tool_start',\n 'tool_update',\n 'tool_end',\n 'assistant_message_end',\n 'progress',\n]);\n\nconst DIRECT_RESPONSE_OWNED_EVENTS = new Set([...STREAM_TOUCH_EVENTS, 'run_end', 'error']);\n\nfunction resolveEventRunId(data: Record<string, unknown>, state: TuiState): string | null {\n if (typeof data.runId === 'string' && data.runId) return data.runId;\n return state.activeRunId ?? state.runStatus.runId ?? state.runStatus.lastCompletedRunId;\n}\n\nexport function shouldSkipDuplicateBroadcastEvent(\n event: string,\n data: Record<string, unknown>,\n state: TuiState,\n source: TuiEventSource,\n): boolean {\n if (source !== 'broadcast') return false;\n if (!DIRECT_RESPONSE_OWNED_EVENTS.has(event)) return false;\n const directRunId = state.runStatus.directStreamRunId;\n if (!directRunId) return false;\n return resolveEventRunId(data, state) === directRunId;\n}\n\nfunction streamEventKey(data: Record<string, unknown>, state: TuiState): string | null {\n const runId = resolveEventRunId(data, state);\n const seq = data.seq;\n if (!runId || typeof seq !== 'number' || !Number.isFinite(seq)) return null;\n return `${runId}:${seq}`;\n}\n\nfunction shouldSkipSeenStreamEvent(\n data: Record<string, unknown>,\n state: TuiState,\n source: TuiEventSource,\n): boolean {\n if (source !== 'agent-response' && source !== 'agent-resume' && source !== 'broadcast') return false;\n const key = streamEventKey(data, state);\n if (!key) return false;\n if (seenStreamEventKeys.has(key)) return true;\n seenStreamEventKeys.add(key);\n return false;\n}\n\nfunction payload(data: Record<string, unknown>): Record<string, unknown> {\n return data.payload && typeof data.payload === 'object' ? data.payload as Record<string, unknown> : {};\n}\n\nfunction assistantForRun(runId: string): AgentMessage {\n let message = assistantByRun.get(runId);\n if (!message) {\n message = createAssistantMessageFromText('') as AgentMessage;\n assistantByRun.set(runId, message);\n }\n return message;\n}\n\nfunction appendAssistantText(message: AgentMessage, delta: string): void {\n const rec = message as { content?: unknown };\n if (!Array.isArray(rec.content)) rec.content = [];\n const content = rec.content as Array<Record<string, unknown>>;\n const last = content[content.length - 1];\n if (last?.type === 'text' && typeof last.text === 'string') {\n last.text += delta;\n return;\n }\n content.push({ type: 'text', text: delta });\n}\n\nfunction appendThinkingText(message: AgentMessage, delta: string): void {\n const rec = message as { content?: unknown };\n if (!Array.isArray(rec.content)) rec.content = [];\n const content = rec.content as Array<Record<string, unknown>>;\n const last = content[content.length - 1];\n if (last?.type === 'thinking' && typeof last.text === 'string') {\n last.text += delta;\n return;\n }\n content.push({ type: 'thinking', text: delta, streaming: true });\n}\n\nfunction appendReviewBlock(message: AgentMessage, review: unknown): void {\n if (!review || typeof review !== 'object' || Array.isArray(review)) return;\n const rec = review as { type?: unknown; target?: unknown };\n if (rec.type !== 'review') return;\n const msg = message as { content?: unknown };\n if (!Array.isArray(msg.content)) msg.content = [];\n const content = msg.content as Array<Record<string, unknown>>;\n const target = typeof rec.target === 'string' ? rec.target : 'working tree changes';\n const existing = content.findIndex((block) => block.type === 'review' && block.target === target);\n if (existing >= 0) {\n content[existing] = review as Record<string, unknown>;\n return;\n }\n content.push(review as Record<string, unknown>);\n}\n\nfunction finalizeThinking(message: AgentMessage): void {\n const content = (message as { content?: unknown }).content;\n if (!Array.isArray(content)) return;\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n const rec = block as { type?: unknown; streaming?: boolean };\n if (rec.type === 'thinking') rec.streaming = false;\n }\n}\n\nfunction errorAssistantMessage(errorContent: string): AgentMessage {\n return {\n ...createAssistantMessageFromText(''),\n stopReason: 'error',\n errorMessage: errorContent,\n } as AgentMessage;\n}\n\nexport function dispatchAgentEvent(\n event: string,\n data: Record<string, unknown>,\n state: TuiState,\n chatLog: ChatLog,\n tui: TUI,\n setActivityStatus: (status: string) => void,\n touchStreamingActivity?: () => void,\n onRunEnded?: () => void,\n onAssistantFinalized?: (message: AgentMessage, options?: { errorMessage?: string }) => void,\n source: TuiEventSource = 'unknown',\n): void {\n if (shouldSkipSeenStreamEvent(data, state, source)) return;\n if (shouldSkipDuplicateBroadcastEvent(event, data, state, source)) return;\n\n if (STREAM_TOUCH_EVENTS.has(event)) touchStreamingActivity?.();\n\n const runId = resolveEventRunId(data, state) ?? state.activeRunId ?? 'default';\n const p = payload(data);\n\n switch (event) {\n case 'run_start': {\n state.activeRunId = runId;\n markRunEvent(state, 'waiting', runId, event, source);\n setActivityStatus('waiting');\n break;\n }\n case 'user_message': {\n const message = p.message as { content?: unknown } | undefined;\n chatLog.addUser(Array.isArray(message?.content) || typeof message?.content === 'string' ? message.content : []);\n tui.requestRender();\n break;\n }\n case 'user_transcript': {\n chatLog.addUser(String(p.text ?? ''));\n tui.requestRender();\n break;\n }\n case 'assistant_message_start': {\n const message = assistantForRun(runId);\n chatLog.startAssistant(message, runId);\n markRunEvent(state, 'streaming', runId, event, source);\n setActivityStatus('streaming');\n tui.requestRender();\n break;\n }\n case 'assistant_delta': {\n const delta = typeof p.delta === 'string' ? p.delta : '';\n if (!delta) break;\n const message = assistantForRun(runId);\n appendAssistantText(message, delta);\n chatLog.updateAssistant(message, runId);\n markRunEvent(state, 'streaming', runId, event, source);\n setActivityStatus('streaming');\n tui.requestRender();\n break;\n }\n case 'thinking_delta': {\n const delta = typeof p.delta === 'string' ? p.delta : '';\n if (!delta) break;\n const message = assistantForRun(runId);\n appendThinkingText(message, delta);\n chatLog.updateAssistant(message, runId);\n markRunEvent(state, 'streaming', runId, event, source);\n setActivityStatus('streaming');\n tui.requestRender();\n break;\n }\n case 'thinking_end': {\n const message = assistantForRun(runId);\n finalizeThinking(message);\n chatLog.updateAssistant(message, runId);\n tui.requestRender();\n break;\n }\n case 'review': {\n const message = assistantForRun(runId);\n appendReviewBlock(message, p.review);\n chatLog.updateAssistant(message, runId);\n markRunEvent(state, 'streaming', runId, event, source);\n setActivityStatus('streaming');\n tui.requestRender();\n break;\n }\n case 'tool_start': {\n const toolName = String(p.toolName ?? 'unknown');\n const toolCallId = String(p.toolCallId || '');\n if (!toolCallId) break;\n chatLog.startTool(toolCallId, toolName, p.args ?? {}, runId);\n chatLog.markToolExecutionStarted(toolCallId);\n markRunEvent(state, 'tool', runId, event, source);\n setActivityStatus('running');\n tui.requestRender();\n break;\n }\n case 'tool_update': {\n const toolName = String(p.toolName ?? 'unknown');\n const toolCallId = String(p.toolCallId || '');\n if (!toolCallId) break;\n chatLog.startTool(toolCallId, toolName, {}, runId);\n if ('details' in p) chatLog.updateToolDetails(toolCallId, p.details);\n if (typeof p.textDelta === 'string') chatLog.updateToolResult(toolCallId, { text: p.textDelta }, false, true);\n markRunEvent(state, 'tool', runId, event, source);\n setActivityStatus('running');\n tui.requestRender();\n break;\n }\n case 'tool_end': {\n const toolCallId = String(p.toolCallId || '');\n if (!toolCallId) break;\n chatLog.updateToolResult(toolCallId, p.result, p.status === 'error' || p.status === 'cancelled', false);\n markRunEvent(state, 'streaming', runId, event, source);\n setActivityStatus('streaming');\n tui.requestRender();\n break;\n }\n case 'assistant_message_end': {\n const message = assistantForRun(runId);\n finalizeThinking(message);\n chatLog.finalizeAssistant(message, runId);\n assistantByRun.delete(runId);\n onAssistantFinalized?.(message);\n markRunEvent(state, 'streaming', runId, event, source);\n setActivityStatus('streaming');\n tui.requestRender();\n break;\n }\n case 'error': {\n const errorContent = formatAgentRunErrorForDisplay(String(p.message ?? 'Unknown error'));\n const message = errorAssistantMessage(errorContent);\n chatLog.finalizeAssistant(message, runId);\n onAssistantFinalized?.(message, { errorMessage: errorContent });\n assistantByRun.delete(runId);\n state.activeRunId = null;\n markRunIdleAfterCompletion(state, runId, event, source);\n setActivityStatus('idle');\n onRunEnded?.();\n tui.requestRender();\n break;\n }\n case 'run_end': {\n assistantByRun.delete(runId);\n state.activeRunId = null;\n markRunIdleAfterCompletion(state, runId, event, source);\n setActivityStatus('idle');\n onRunEnded?.();\n tui.requestRender();\n break;\n }\n case 'progress': {\n const stage = typeof p.stage === 'string' ? p.stage : '';\n const message = typeof p.message === 'string' ? p.message : stage;\n state.progressMessage = message || null;\n markRunEvent(state, 'progress', runId, event, source);\n setActivityStatus(message ? `progress: ${message}` : 'running');\n tui.requestRender();\n break;\n }\n }\n}\n\nexport const DEFAULT_STREAMING_WATCHDOG_MS = 30_000;\n"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ClientHistoryMessage } from '../session/client-history.js';
|
|
2
2
|
import type { ExportFormat } from '../session/types.js';
|
|
3
|
+
import type { ReviewContext } from '../review/review-git.js';
|
|
3
4
|
import type { SessionInfo, TuiEventSource } from './tui-types.js';
|
|
4
5
|
/** Options for sending a chat message. */
|
|
5
6
|
export interface ChatSendOptions {
|
|
@@ -125,6 +126,7 @@ export interface TuiStartupProjectResult {
|
|
|
125
126
|
project: {
|
|
126
127
|
id: string;
|
|
127
128
|
name: string;
|
|
129
|
+
defaultAgentId?: string;
|
|
128
130
|
workspaceRoot?: string;
|
|
129
131
|
} | null;
|
|
130
132
|
created?: boolean;
|
|
@@ -212,6 +214,8 @@ export interface TuiBackend {
|
|
|
212
214
|
searchWorkspaceFiles?(sessionKey: string, query: string, options?: {
|
|
213
215
|
limit?: number;
|
|
214
216
|
}): Promise<TuiWorkspaceFileSearchEntry[]>;
|
|
217
|
+
/** Load git branches/commits/status for the interactive review launcher. */
|
|
218
|
+
getReviewContext?(sessionKey: string): Promise<ReviewContext>;
|
|
215
219
|
/** Load chat history for a session. */
|
|
216
220
|
loadHistory(opts: {
|
|
217
221
|
sessionKey: string;
|
|
@@ -33,6 +33,7 @@ export type CommandHandlerDeps = {
|
|
|
33
33
|
uiOverlays?: {
|
|
34
34
|
openModelPicker: (initialSearch?: string) => void;
|
|
35
35
|
openAgentPicker?: () => void;
|
|
36
|
+
openReviewLauncher?: () => void;
|
|
36
37
|
openSessionPicker: () => void;
|
|
37
38
|
openSessionTree: () => void;
|
|
38
39
|
openTranscriptTree: () => void;
|
|
@@ -14,6 +14,7 @@ import { provenanceTracker } from "../extensions/security.js";
|
|
|
14
14
|
import "../config/index.js";
|
|
15
15
|
import { ProjectService } from "../projects/project-service.js";
|
|
16
16
|
import { isValidProjectAgentId, normalizeProjectAgentId } from "../projects/project-agent.js";
|
|
17
|
+
import { inferSuggestedProjectDefaultAgentId } from "../projects/project-agent-suggestion.js";
|
|
17
18
|
import "../projects/index.js";
|
|
18
19
|
import { getTuiKeybindingsPath } from "./tui-keybindings-file.js";
|
|
19
20
|
import { formatKeyIds, formatXopcTuiHotkeys } from "./format-tui-hotkeys.js";
|
|
@@ -95,6 +96,10 @@ function getSlashCommands(_isLocal, keybindings) {
|
|
|
95
96
|
name: "usage",
|
|
96
97
|
description: "Show token usage statistics"
|
|
97
98
|
},
|
|
99
|
+
{
|
|
100
|
+
name: "review",
|
|
101
|
+
description: "Review current workspace changes for correctness issues"
|
|
102
|
+
},
|
|
98
103
|
{
|
|
99
104
|
name: "session",
|
|
100
105
|
description: "Show current session info"
|
|
@@ -373,6 +378,81 @@ function resolveTuiProject(projects, ref) {
|
|
|
373
378
|
function parseTuiProjectStatus(raw) {
|
|
374
379
|
return raw === "active" || raw === "paused" || raw === "archived" ? raw : void 0;
|
|
375
380
|
}
|
|
381
|
+
function parseProjectNewArgs(parts) {
|
|
382
|
+
const nameParts = [];
|
|
383
|
+
let workspaceRoot;
|
|
384
|
+
let projectKind;
|
|
385
|
+
let agentId;
|
|
386
|
+
for (let index = 0; index < parts.length; index += 1) {
|
|
387
|
+
const part = parts[index];
|
|
388
|
+
if (part === "--path" || part === "-p") {
|
|
389
|
+
workspaceRoot = parts[index + 1]?.trim();
|
|
390
|
+
index += 1;
|
|
391
|
+
if (!workspaceRoot) return {
|
|
392
|
+
name: "",
|
|
393
|
+
error: "Missing value for --path"
|
|
394
|
+
};
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
if (part.startsWith("--path=") || part.startsWith("-p=")) {
|
|
398
|
+
workspaceRoot = part.slice(part.indexOf("=") + 1).trim();
|
|
399
|
+
if (!workspaceRoot) return {
|
|
400
|
+
name: "",
|
|
401
|
+
error: "Missing value for --path"
|
|
402
|
+
};
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
if (part === "--type" || part === "-t") {
|
|
406
|
+
projectKind = parts[index + 1]?.trim();
|
|
407
|
+
index += 1;
|
|
408
|
+
if (![
|
|
409
|
+
"auto",
|
|
410
|
+
"coding",
|
|
411
|
+
"general"
|
|
412
|
+
].includes(projectKind ?? "")) return {
|
|
413
|
+
name: "",
|
|
414
|
+
error: "Project type must be auto, coding, or general"
|
|
415
|
+
};
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
if (part.startsWith("--type=") || part.startsWith("-t=")) {
|
|
419
|
+
projectKind = part.slice(part.indexOf("=") + 1).trim();
|
|
420
|
+
if (![
|
|
421
|
+
"auto",
|
|
422
|
+
"coding",
|
|
423
|
+
"general"
|
|
424
|
+
].includes(projectKind)) return {
|
|
425
|
+
name: "",
|
|
426
|
+
error: "Project type must be auto, coding, or general"
|
|
427
|
+
};
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
if (part === "--agent" || part === "-a") {
|
|
431
|
+
agentId = parts[index + 1]?.trim();
|
|
432
|
+
index += 1;
|
|
433
|
+
if (!agentId) return {
|
|
434
|
+
name: "",
|
|
435
|
+
error: "Missing value for --agent"
|
|
436
|
+
};
|
|
437
|
+
continue;
|
|
438
|
+
}
|
|
439
|
+
if (part.startsWith("--agent=") || part.startsWith("-a=")) {
|
|
440
|
+
agentId = part.slice(part.indexOf("=") + 1).trim();
|
|
441
|
+
if (!agentId) return {
|
|
442
|
+
name: "",
|
|
443
|
+
error: "Missing value for --agent"
|
|
444
|
+
};
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
nameParts.push(part);
|
|
448
|
+
}
|
|
449
|
+
return {
|
|
450
|
+
name: nameParts.join(" ").trim(),
|
|
451
|
+
workspaceRoot,
|
|
452
|
+
projectKind,
|
|
453
|
+
agentId
|
|
454
|
+
};
|
|
455
|
+
}
|
|
376
456
|
function formatTuiProject(project) {
|
|
377
457
|
return [
|
|
378
458
|
`${project.name} [${project.status}]`,
|
|
@@ -405,9 +485,24 @@ function runTuiProjectCommand(state, args) {
|
|
|
405
485
|
return ["Projects:", ...result.items.map((project) => `- ${project.slug} [${project.status}] ${project.name}`)].join("\n");
|
|
406
486
|
}
|
|
407
487
|
if (subcommand === "new") {
|
|
408
|
-
const
|
|
409
|
-
if (
|
|
410
|
-
|
|
488
|
+
const parsed = parseProjectNewArgs(parts.slice(1));
|
|
489
|
+
if (parsed.error) return parsed.error;
|
|
490
|
+
if (!parsed.name && !parsed.workspaceRoot) return "Usage: /project new <name> [--path <workspace>] [--type auto|coding|general] [--agent <agent-id>]";
|
|
491
|
+
const cfg = loadConfig(resolveConfigPath());
|
|
492
|
+
const explicitAgentId = normalizeProjectAgentId(parsed.agentId);
|
|
493
|
+
if (parsed.agentId && !isValidProjectAgentId(cfg, explicitAgentId)) return `Agent not found: ${parsed.agentId}`;
|
|
494
|
+
const defaultAgentId = explicitAgentId ?? inferSuggestedProjectDefaultAgentId({
|
|
495
|
+
config: cfg,
|
|
496
|
+
name: parsed.name,
|
|
497
|
+
workspaceRoot: parsed.workspaceRoot,
|
|
498
|
+
projectKind: parsed.projectKind
|
|
499
|
+
});
|
|
500
|
+
const project = projects.create({
|
|
501
|
+
...parsed.name ? { name: parsed.name } : {},
|
|
502
|
+
...parsed.workspaceRoot ? { workspaceRoot: parsed.workspaceRoot } : {},
|
|
503
|
+
...defaultAgentId ? { defaultAgentId } : {},
|
|
504
|
+
...parsed.projectKind ? { projectKind: parsed.projectKind } : {}
|
|
505
|
+
});
|
|
411
506
|
projects.attachSession(state.currentSessionKey, project.id);
|
|
412
507
|
return `Created and attached project:\n${formatTuiProject(project)}`;
|
|
413
508
|
}
|
|
@@ -470,7 +565,7 @@ function runTuiProjectCommand(state, args) {
|
|
|
470
565
|
"Usage:",
|
|
471
566
|
" /project",
|
|
472
567
|
" /project list [active|paused|archived]",
|
|
473
|
-
" /project new <name>",
|
|
568
|
+
" /project new <name> [--path <workspace>] [--type auto|coding|general] [--agent <agent-id>]",
|
|
474
569
|
" /project switch <id-or-slug>",
|
|
475
570
|
" /project attach <id-or-slug>",
|
|
476
571
|
" /project detach",
|
|
@@ -1065,6 +1160,17 @@ function createTuiCommandHandler(deps) {
|
|
|
1065
1160
|
}
|
|
1066
1161
|
deps.runCompaction?.(commandArgs.trim() || void 0);
|
|
1067
1162
|
return;
|
|
1163
|
+
case "review":
|
|
1164
|
+
if (!commandArgs.trim()) {
|
|
1165
|
+
if (uiOverlays?.openReviewLauncher) uiOverlays.openReviewLauncher();
|
|
1166
|
+
else {
|
|
1167
|
+
chatLog.addSystem("Usage: /review --uncommitted | /review --base <branch> | /review --commit <sha> | /review --custom <instructions>");
|
|
1168
|
+
tui.requestRender();
|
|
1169
|
+
}
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
1172
|
+
sendMessage(input);
|
|
1173
|
+
return;
|
|
1068
1174
|
default: break;
|
|
1069
1175
|
}
|
|
1070
1176
|
switch (normalizedCommand) {
|