@xopcai/xopc 0.0.123 → 0.0.125
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/Combination-BzaXOLd9.js +41 -0
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-Bicr3ZBg.js → agent-avatar-dicebear-BKDKICZV.js} +1 -1
- package/dist/gateway/static/root/assets/agents-BnTB7-c5.js +2 -0
- package/dist/gateway/static/root/assets/app-management-settings-panel-DI4BqHKW.js +1 -0
- package/dist/gateway/static/root/assets/appearance-settings-6_ie3NQ4.js +1 -0
- package/dist/gateway/static/root/assets/apps-page-B6bG65SW.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-Bpy64GjU.js → archive-plugin-kUHEJ1HK.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-DMkp4xSb.js → attachment-load-Dm-9prpU.js} +1 -1
- package/dist/gateway/static/root/assets/automation-suggestion-card-OTxQTPnC.js +1 -0
- package/dist/gateway/static/root/assets/automations-page-1lVbo0dS.js +1 -0
- package/dist/gateway/static/root/assets/{binary-plugins-DA9C5mCw.js → binary-plugins-DllA_jQ0.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CiSXk_YC.js → block-editor-Cm6CWNj1.js} +5 -5
- package/dist/gateway/static/root/assets/browser-settings-page-CzDBlOK0.js +8 -0
- package/dist/gateway/static/root/assets/capability-presets-api-VJ89b6I2.js +1 -0
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-BaPj8wC2.js +1 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-CDhrhfhN.js → channel-recipient-api-B5PwBEUx.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-Df4m7p1k.js +1 -0
- package/dist/gateway/static/root/assets/code-editor-gbRgS14t.js +1 -0
- package/dist/gateway/static/root/assets/connectors-page-BMTphmHS.js +2 -0
- package/dist/gateway/static/root/assets/{directory-picker-path-field-7jKfbH0J.js → directory-picker-path-field-DySMzOF6.js} +1 -1
- package/dist/gateway/static/root/assets/dist-By6Rh2ee.js +1 -0
- package/dist/gateway/static/root/assets/dist-CkobR7mk.js +1 -0
- package/dist/gateway/static/root/assets/dist-DokQNVMQ.js +1 -0
- package/dist/gateway/static/root/assets/dreaming-settings-D_AjSnV_.js +3 -0
- package/dist/gateway/static/root/assets/extension-debug-page-BaM0FpW7.js +1 -0
- package/dist/gateway/static/root/assets/extension-page-DuZWVOGA.js +1 -0
- package/dist/gateway/static/root/assets/extension-settings-page-DarVtbmJ.js +1 -0
- package/dist/gateway/static/root/assets/{fetch-Dtpbbe0s.js → fetch-NFKfkqrd.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-BN6pyX2c.js → gateway-config-api-CFEm9rgy.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-BMk2S5td.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-BIET2x3y.js → gateway-startup-retry-Dtwh_yGg.js} +1 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-BKP7ylcG.js +1 -0
- package/dist/gateway/static/root/assets/goal-detail-page-C2cTxf71.js +1 -0
- package/dist/gateway/static/root/assets/{goals-config-api-CQm2r1Ty.js → goals-config-api-DTWZNA_Y.js} +1 -1
- package/dist/gateway/static/root/assets/goals-page-CTmA3hWK.js +2 -0
- package/dist/gateway/static/root/assets/goals-settings-Bhct0ZT-.js +1 -0
- package/dist/gateway/static/root/assets/heartbeat-settings-C-UxSU4a.js +1 -0
- package/dist/gateway/static/root/assets/{html-workspace-editor-CQLWDiwE.js → html-workspace-editor-DV90ddkE.js} +1 -1
- package/dist/gateway/static/root/assets/index-BNHDd2j1.css +1 -0
- package/dist/gateway/static/root/assets/index-BPXLPMuY.js +193 -0
- package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-DCjy2y4d.js +1 -0
- package/dist/gateway/static/root/assets/logs-page-CGc3_CQU.js +2 -0
- package/dist/gateway/static/root/assets/{markdown-editor-AssmZFx4.js → markdown-editor-BFOjBBla.js} +2 -2
- package/dist/gateway/static/root/assets/markdown-split-BaqxP-GQ.js +1 -0
- package/dist/gateway/static/root/assets/{media-plugins-DS44pJzr.js → media-plugins-DQ_EXloK.js} +1 -1
- package/dist/gateway/static/root/assets/messages-CjuIJcZl.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-panel-Drz4UQMb.js +2 -0
- package/dist/gateway/static/root/assets/notes-page-CY1ylng1.js +1 -0
- package/dist/gateway/static/root/assets/notes-workbench-X7IaD--t.js +2 -0
- package/dist/gateway/static/root/assets/page-tabs-EIZhLppK.js +1 -0
- package/dist/gateway/static/root/assets/{preview-open-alternatives-Dej6zHnr.js → preview-open-alternatives-r_uB4Epr.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-DE5adRBE.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-CuOb1k6F.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-BOxNrUVA.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-Zu1FzH6z.js → save-bar-controls-B132Uf-2.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-BW78mKc0.js → schedule-field-B5qshALm.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-Cc-IOydE.js → schema-form-CvLmkdS9.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-CY0IQcGW.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-D4NBNVCB.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-DIpIYht_.js → settings-collapsible-section-pRlvqsAf.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-BFxBNxOG.js → settings-form-section-BBYUDLVd.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-C4fivemT.js → settings-page-DaO7zYZM.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-layout-CLx4o2PN.js → settings-page-layout-D8g9PAek.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Bks0CLLT.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-ZswWCrDu.js → share-preview-page-v6-IOp8t.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-CEZsKm9r.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-oTkHbb9W.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-DigsbZ6K.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-3ZNcGRhS.js → system-settings-panel-HUU2FFjM.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-bpzZjiVF.js → typed-models-lib-AH160QHh.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-BCjZLZ3O.js → use-channel-catalog-BXzDmjCQ.js} +1 -1
- package/dist/gateway/static/root/assets/{user-profile-settings-panel-CIXafITi.js → user-profile-settings-panel-DxwnQvQ3.js} +1 -1
- package/dist/gateway/static/root/assets/{utils-DXMtz5j_.js → utils-i5POEtqd.js} +1 -1
- package/dist/gateway/static/root/assets/{vendor-codemirror-CNP1wPe7.js → vendor-codemirror-BvNgyE1Q.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-CEJklEgb.js +1 -0
- package/dist/gateway/static/root/assets/work-item-detail-page-CD6FL_Rs.js +1 -0
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-ClVVMgN-.js +3 -0
- package/dist/gateway/static/root/assets/{workflow-start-dialog-B4sZpTDQ.js → workflow-start-dialog-Dv4ZA1T0.js} +1 -1
- package/dist/gateway/static/root/assets/workflows-page-OLQiUpoW.js +18 -0
- package/dist/gateway/static/root/index.html +8 -7
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +6 -1
- package/dist/src/agent/agent-manager.js +34 -14
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/child-agent-factory.d.ts +2 -0
- package/dist/src/agent/child-agent-factory.js +2 -0
- package/dist/src/agent/child-agent-factory.js.map +1 -1
- package/dist/src/agent/coding/index.d.ts +1 -0
- package/dist/src/agent/coding/index.js +2 -0
- package/dist/src/agent/coding/turn-diff-tracker.d.ts +67 -0
- package/dist/src/agent/coding/turn-diff-tracker.js +233 -0
- package/dist/src/agent/coding/turn-diff-tracker.js.map +1 -0
- 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/dreaming/config.d.ts +2 -2
- package/dist/src/agent/memory/dreaming/config.js +3 -3
- package/dist/src/agent/memory/dreaming/config.js.map +1 -1
- package/dist/src/agent/memory/dreaming/constants.d.ts +1 -1
- package/dist/src/agent/memory/dreaming/constants.js +1 -1
- package/dist/src/agent/memory/dreaming/constants.js.map +1 -1
- package/dist/src/agent/memory/dreaming/deep-promotion.d.ts +1 -0
- package/dist/src/agent/memory/dreaming/deep-promotion.js +11 -20
- package/dist/src/agent/memory/dreaming/deep-promotion.js.map +1 -1
- package/dist/src/agent/memory/dreaming/events.d.ts +3 -3
- package/dist/src/agent/memory/dreaming/events.js +6 -6
- package/dist/src/agent/memory/dreaming/events.js.map +1 -1
- package/dist/src/agent/memory/dreaming/last-run.d.ts +2 -2
- package/dist/src/agent/memory/dreaming/last-run.js +1 -1
- package/dist/src/agent/memory/dreaming/last-run.js.map +1 -1
- package/dist/src/agent/memory/dreaming/light-sweep.d.ts +1 -1
- package/dist/src/agent/memory/dreaming/light-sweep.js +3 -3
- package/dist/src/agent/memory/dreaming/light-sweep.js.map +1 -1
- package/dist/src/agent/memory/dreaming/preview.d.ts +1 -0
- package/dist/src/agent/memory/dreaming/preview.js +2 -2
- package/dist/src/agent/memory/dreaming/preview.js.map +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.d.ts +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.js +13 -13
- package/dist/src/agent/memory/dreaming/rem-patterns.js.map +1 -1
- package/dist/src/agent/memory/dreaming/scope.d.ts +14 -0
- package/dist/src/agent/memory/dreaming/scope.js +27 -0
- package/dist/src/agent/memory/dreaming/scope.js.map +1 -0
- package/dist/src/agent/memory/dreaming/short-term-store.d.ts +4 -4
- package/dist/src/agent/memory/dreaming/short-term-store.js +17 -17
- package/dist/src/agent/memory/dreaming/short-term-store.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.d.ts +2 -0
- package/dist/src/agent/orchestration/agent-event-handler.js +69 -14
- package/dist/src/agent/orchestration/agent-event-handler.js.map +1 -1
- package/dist/src/agent/orchestration/agent-orchestrator.js +22 -12
- package/dist/src/agent/orchestration/agent-orchestrator.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/command-validator.js +12 -0
- package/dist/src/agent/sandbox/command-validator.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.d.ts +2 -1
- package/dist/src/agent/service.js +19 -6
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/session/session-inspector.d.ts +5 -3
- package/dist/src/agent/session/session-inspector.js +16 -7
- package/dist/src/agent/session/session-inspector.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/source-context/types.d.ts +1 -1
- package/dist/src/agent/source-context/types.js +1 -1
- package/dist/src/agent/source-context/types.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 +310 -0
- package/dist/src/agent/tools/apply-patch.js.map +1 -0
- package/dist/src/agent/tools/concurrency.d.ts +8 -0
- package/dist/src/agent/tools/concurrency.js +31 -0
- package/dist/src/agent/tools/concurrency.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/dreaming-tool.d.ts +2 -0
- package/dist/src/agent/tools/dreaming-tool.js +13 -10
- package/dist/src/agent/tools/dreaming-tool.js.map +1 -1
- package/dist/src/agent/tools/exec-command.d.ts +30 -0
- package/dist/src/agent/tools/exec-command.js +228 -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/executor.d.ts +6 -4
- package/dist/src/agent/tools/executor.js +7 -4
- package/dist/src/agent/tools/executor.js.map +1 -1
- package/dist/src/agent/tools/factory.d.ts +6 -3
- package/dist/src/agent/tools/factory.js +14 -9
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/find.js +2 -0
- package/dist/src/agent/tools/find.js.map +1 -1
- package/dist/src/agent/tools/grep.js +2 -0
- package/dist/src/agent/tools/grep.js.map +1 -1
- package/dist/src/agent/tools/index.d.ts +5 -2
- package/dist/src/agent/tools/index.js +7 -4
- package/dist/src/agent/tools/list-dir.js +2 -0
- package/dist/src/agent/tools/list-dir.js.map +1 -1
- package/dist/src/agent/tools/memory-tool.d.ts +1 -0
- package/dist/src/agent/tools/memory-tool.js +2 -2
- package/dist/src/agent/tools/memory-tool.js.map +1 -1
- package/dist/src/agent/tools/metadata.d.ts +15 -0
- package/dist/src/agent/tools/metadata.js +26 -0
- package/dist/src/agent/tools/metadata.js.map +1 -0
- package/dist/src/agent/tools/read.js +2 -0
- package/dist/src/agent/tools/read.js.map +1 -1
- 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/tools/write.js +6 -0
- package/dist/src/agent/tools/write.js.map +1 -1
- 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/agent/workflow/subagent-runner.d.ts +1 -0
- package/dist/src/agent/workflow/subagent-runner.js +5 -1
- package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
- package/dist/src/agent/workflow/workflow-child-tools.js +5 -0
- package/dist/src/agent/workflow/workflow-child-tools.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/connectors/health.d.ts +2 -1
- package/dist/src/connectors/health.js +59 -1
- package/dist/src/connectors/health.js.map +1 -1
- package/dist/src/connectors/install.d.ts +1 -0
- package/dist/src/connectors/install.js +28 -1
- package/dist/src/connectors/install.js.map +1 -1
- package/dist/src/connectors/instances.js +7 -0
- package/dist/src/connectors/instances.js.map +1 -1
- package/dist/src/connectors/materialize.js +2 -1
- package/dist/src/connectors/materialize.js.map +1 -1
- package/dist/src/connectors/registries/modelscope.js +38 -13
- package/dist/src/connectors/registries/modelscope.js.map +1 -1
- package/dist/src/connectors/types.d.ts +2 -0
- 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/dreaming-automation-reconciler.d.ts +1 -0
- package/dist/src/gateway/dreaming-automation-reconciler.js +62 -42
- package/dist/src/gateway/dreaming-automation-reconciler.js.map +1 -1
- package/dist/src/gateway/hono/app.js +7 -1
- package/dist/src/gateway/hono/app.js.map +1 -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/connectors.js +46 -2
- package/dist/src/gateway/hono/routes/connectors.js.map +1 -1
- package/dist/src/gateway/hono/routes/dreaming.js +111 -66
- package/dist/src/gateway/hono/routes/dreaming.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 +886 -45
- 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/hono/routes/sessions.js +1 -0
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/security/dangerous-tools.js +1 -1
- package/dist/src/gateway/security/dangerous-tools.js.map +1 -1
- package/dist/src/gateway/service.js +17 -8
- package/dist/src/gateway/service.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/media/store.js +1 -1
- package/dist/src/media/store.js.map +1 -1
- package/dist/src/media/types.d.ts +1 -1
- package/dist/src/media/uri.js +2 -1
- package/dist/src/media/uri.js.map +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.d.ts +2 -0
- package/dist/src/session/session-context-for-llm.js +165 -1
- package/dist/src/session/session-context-for-llm.js.map +1 -1
- package/dist/src/session/store.js +2 -2
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/storage/sqlite/migrations/021_projects_fts.sql +21 -0
- package/dist/src/storage/sqlite/migrations/022_work_items.sql +61 -0
- package/dist/src/storage/sqlite/migrations/023_work_item_attachments.sql +15 -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/storage/sqlite/schema.sql +78 -0
- 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 +47 -2
- package/dist/src/tui/components/assistant-message.js.map +1 -1
- package/dist/src/tui/components/tool-execution.d.ts +8 -0
- package/dist/src/tui/components/tool-execution.js +87 -77
- package/dist/src/tui/components/tool-execution.js.map +1 -1
- package/dist/src/tui/components/visual-truncate.d.ts +1 -0
- package/dist/src/tui/components/visual-truncate.js +28 -1
- package/dist/src/tui/components/visual-truncate.js.map +1 -1
- package/dist/src/tui/tool-summary.d.ts +22 -0
- package/dist/src/tui/tool-summary.js +212 -0
- package/dist/src/tui/tool-summary.js.map +1 -0
- 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-tool-diff.d.ts +15 -0
- package/dist/src/tui/tui-tool-diff.js +178 -7
- package/dist/src/tui/tui-tool-diff.js.map +1 -1
- package/dist/src/tui/tui.js +16 -3
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/work-items/agent-context.d.ts +3 -0
- package/dist/src/work-items/agent-context.js +39 -0
- package/dist/src/work-items/agent-context.js.map +1 -0
- package/dist/src/work-items/index.d.ts +4 -0
- package/dist/src/work-items/index.js +4 -0
- package/dist/src/work-items/types.d.ts +112 -0
- package/dist/src/work-items/types.js +1 -0
- package/dist/src/work-items/work-item-service.d.ts +33 -0
- package/dist/src/work-items/work-item-service.js +180 -0
- package/dist/src/work-items/work-item-service.js.map +1 -0
- package/dist/src/work-items/work-item-store.d.ts +21 -0
- package/dist/src/work-items/work-item-store.js +302 -0
- package/dist/src/work-items/work-item-store.js.map +1 -0
- package/dist/src/workflows/service/workflow-run-service.js +4 -3
- package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
- package/dist/src/workflows/service/workflow-session-bridge.js +3 -0
- package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +0 -41
- package/dist/gateway/static/root/assets/agents-CxDSFHGx.js +0 -2
- package/dist/gateway/static/root/assets/app-management-settings-panel-CbEy9sR1.js +0 -1
- package/dist/gateway/static/root/assets/appearance-settings-CTHja6n9.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-CyZdgqvm.js +0 -1
- package/dist/gateway/static/root/assets/automation-suggestion-card-KnYaP7NT.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-api-CEJ44WCU.js +0 -1
- 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/code-editor-dZTY2dRW.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-VKstC3sP.js +0 -2
- package/dist/gateway/static/root/assets/dist-Mys7eFJ5.js +0 -1
- package/dist/gateway/static/root/assets/dist-wO9a2_ID.js +0 -1
- package/dist/gateway/static/root/assets/dreaming-settings-m1-wmz4o.js +0 -1
- package/dist/gateway/static/root/assets/extension-debug-page-C9qQQrBS.js +0 -1
- package/dist/gateway/static/root/assets/extension-page-DcBBMEGl.js +0 -1
- package/dist/gateway/static/root/assets/extension-settings-page-BQ-jMMP9.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-hQtgVmSR.js +0 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-BuIMDx6C.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/goals-settings-DDrdRMxB.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-BJVok3Sl.js +0 -1
- package/dist/gateway/static/root/assets/index-CBDr5xjB.css +0 -1
- package/dist/gateway/static/root/assets/index-T0SaNd5a.js +0 -191
- package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-C2TuQppb.js +0 -1
- package/dist/gateway/static/root/assets/logs-page-DwkwPgid.js +0 -2
- package/dist/gateway/static/root/assets/markdown-split-DhONQ81k.js +0 -1
- 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/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
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { basename, dirname } from "node:path";
|
|
2
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
3
|
+
//#region src/tui/tool-summary.ts
|
|
4
|
+
const MAX_ARG_VALUE_LENGTH = 120;
|
|
5
|
+
const MAX_PATH_LABEL_LENGTH = 72;
|
|
6
|
+
function formatArgsSummary(args, toolName) {
|
|
7
|
+
if (!args || typeof args !== "object") return "";
|
|
8
|
+
const compactRead = isReadStyleTool(toolName) ? formatCompactReadArgs(args) : null;
|
|
9
|
+
if (compactRead) return compactRead;
|
|
10
|
+
const command = isExecStyleTool(toolName) ? commandFromArgs(args) : null;
|
|
11
|
+
if (command) return command;
|
|
12
|
+
const entries = Object.entries(args);
|
|
13
|
+
if (entries.length === 0) return "";
|
|
14
|
+
return entries.map(([key, value]) => {
|
|
15
|
+
const stringValue = formatArgValue(value);
|
|
16
|
+
return `${key}=${stringValue.length > MAX_ARG_VALUE_LENGTH ? `${stringValue.slice(0, MAX_ARG_VALUE_LENGTH - 3)}...` : stringValue}`;
|
|
17
|
+
}).join(", ");
|
|
18
|
+
}
|
|
19
|
+
function getToolSummaryKind(toolName) {
|
|
20
|
+
if (isReadStyleTool(toolName)) return "read";
|
|
21
|
+
if (isSearchStyleTool(toolName)) return "search";
|
|
22
|
+
if (isExecStyleTool(toolName)) return "exec";
|
|
23
|
+
if (isMcpStyleTool(toolName)) return "mcp";
|
|
24
|
+
return "generic";
|
|
25
|
+
}
|
|
26
|
+
function isReadStyleTool(toolName) {
|
|
27
|
+
const base = baseToolName(toolName);
|
|
28
|
+
return [
|
|
29
|
+
"read",
|
|
30
|
+
"read_file",
|
|
31
|
+
"memory_get"
|
|
32
|
+
].includes(base);
|
|
33
|
+
}
|
|
34
|
+
function isSearchStyleTool(toolName) {
|
|
35
|
+
const base = baseToolName(toolName);
|
|
36
|
+
return [
|
|
37
|
+
"search",
|
|
38
|
+
"grep",
|
|
39
|
+
"rg",
|
|
40
|
+
"ripgrep",
|
|
41
|
+
"search_code",
|
|
42
|
+
"file_search",
|
|
43
|
+
"list_files"
|
|
44
|
+
].includes(base);
|
|
45
|
+
}
|
|
46
|
+
function isExecStyleTool(toolName) {
|
|
47
|
+
const base = baseToolName(toolName);
|
|
48
|
+
return [
|
|
49
|
+
"bash",
|
|
50
|
+
"shell",
|
|
51
|
+
"exec",
|
|
52
|
+
"run_command",
|
|
53
|
+
"exec_command",
|
|
54
|
+
"terminal"
|
|
55
|
+
].includes(base);
|
|
56
|
+
}
|
|
57
|
+
function isMcpStyleTool(toolName) {
|
|
58
|
+
return toolName.includes("__");
|
|
59
|
+
}
|
|
60
|
+
function displayToolName(toolName) {
|
|
61
|
+
const parts = toolName.split("__");
|
|
62
|
+
if (parts.length === 2 && parts[0] && parts[1]) return `${parts[0]}.${parts[1]}`;
|
|
63
|
+
return toolName;
|
|
64
|
+
}
|
|
65
|
+
function compactPath(path, maxLength = MAX_PATH_LABEL_LENGTH) {
|
|
66
|
+
const normalized = path.replace(/\\/g, "/");
|
|
67
|
+
if (normalized.length <= maxLength) return normalized;
|
|
68
|
+
const base = basename(normalized);
|
|
69
|
+
const parent = basename(dirname(normalized));
|
|
70
|
+
const suffix = parent ? `${parent}/${base}` : base;
|
|
71
|
+
if (suffix.length + 2 <= maxLength) return `.../${suffix}`;
|
|
72
|
+
return `.../${base.slice(Math.max(0, base.length - maxLength + 3))}`;
|
|
73
|
+
}
|
|
74
|
+
function formatCollapsedToolSummary(ctx) {
|
|
75
|
+
if (ctx.isError) {
|
|
76
|
+
const rows = nonBlankLines(ctx.output).length;
|
|
77
|
+
return `error; ${rows === 1 ? "1 error line" : `${rows} error lines`}; ${ctx.expandKey} to expand`;
|
|
78
|
+
}
|
|
79
|
+
switch (getToolSummaryKind(ctx.toolName)) {
|
|
80
|
+
case "read": {
|
|
81
|
+
const rows = new Text(ctx.output, 1, 0).render(80).length;
|
|
82
|
+
return ` ${rows} ${rows === 1 ? "row" : "rows"}; ${ctx.expandKey} to expand`;
|
|
83
|
+
}
|
|
84
|
+
case "search": return formatSearchSummary(ctx.output, ctx.expandKey);
|
|
85
|
+
case "exec": return formatExecSummary(ctx.output, ctx.details, ctx.isError, ctx.expandKey);
|
|
86
|
+
case "mcp": return formatMcpSummary(ctx.output, ctx.content, ctx.expandKey);
|
|
87
|
+
case "generic": return "";
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function formatExecExpandedOutput(output, details) {
|
|
91
|
+
const parsed = parseExecDetails(details);
|
|
92
|
+
const sections = [];
|
|
93
|
+
const stdout = parsed.stdout ?? output;
|
|
94
|
+
if (stdout.trim()) sections.push(`stdout\n${stdout}`);
|
|
95
|
+
if (parsed.stderr?.trim()) sections.push(`stderr\n${parsed.stderr}`);
|
|
96
|
+
if (parsed.exitCode !== void 0) sections.push(`exit ${parsed.exitCode}`);
|
|
97
|
+
return sections.join("\n");
|
|
98
|
+
}
|
|
99
|
+
function extractExitCode(details) {
|
|
100
|
+
return parseExecDetails(details).exitCode;
|
|
101
|
+
}
|
|
102
|
+
function formatCompactReadArgs(args) {
|
|
103
|
+
if (!args || typeof args !== "object") return null;
|
|
104
|
+
const record = args;
|
|
105
|
+
const rawPath = typeof record.path === "string" ? record.path : typeof record.file_path === "string" ? record.file_path : void 0;
|
|
106
|
+
if (!rawPath) return null;
|
|
107
|
+
const normalized = rawPath.replace(/\\/g, "/");
|
|
108
|
+
const base = basename(normalized);
|
|
109
|
+
let label;
|
|
110
|
+
if (base === "SKILL.md") {
|
|
111
|
+
const parent = basename(dirname(normalized));
|
|
112
|
+
label = parent ? `[skill] ${parent}` : "[skill]";
|
|
113
|
+
} else if (base === "AGENTS.md") label = `read resource ${compactPath(normalized)}`;
|
|
114
|
+
else label = compactPath(normalized);
|
|
115
|
+
const start = firstFiniteNumber(record.offset, record.from, record.start, record.line);
|
|
116
|
+
const count = firstFiniteNumber(record.limit, record.lines, record.count);
|
|
117
|
+
if (start != null && count != null && count > 0) label += `:${start}-${start + count - 1}`;
|
|
118
|
+
return label;
|
|
119
|
+
}
|
|
120
|
+
function commandFromArgs(args) {
|
|
121
|
+
if (!args || typeof args !== "object") return null;
|
|
122
|
+
const record = args;
|
|
123
|
+
const raw = record.command ?? record.cmd ?? record.script;
|
|
124
|
+
if (Array.isArray(raw)) return raw.map(String).join(" ");
|
|
125
|
+
if (typeof raw === "string" && raw.trim()) return raw.trim();
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
function baseToolName(toolName) {
|
|
129
|
+
return toolName.split("__").pop()?.toLowerCase() ?? toolName.toLowerCase();
|
|
130
|
+
}
|
|
131
|
+
function firstFiniteNumber(...values) {
|
|
132
|
+
for (const value of values) {
|
|
133
|
+
if (typeof value === "number" && Number.isFinite(value)) return Math.floor(value);
|
|
134
|
+
if (typeof value === "string" && value.trim()) {
|
|
135
|
+
const parsed = Number(value);
|
|
136
|
+
if (Number.isFinite(parsed)) return Math.floor(parsed);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
function formatArgValue(value) {
|
|
142
|
+
if (typeof value === "string") return value;
|
|
143
|
+
if (typeof value === "bigint") return `${value.toString()}n`;
|
|
144
|
+
if (typeof value === "function") return "[function]";
|
|
145
|
+
if (typeof value === "symbol") return String(value);
|
|
146
|
+
if (value instanceof Error) return value.message || value.name;
|
|
147
|
+
try {
|
|
148
|
+
const json = JSON.stringify(value);
|
|
149
|
+
return json === void 0 ? String(value) : json;
|
|
150
|
+
} catch {
|
|
151
|
+
return String(value);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function formatSearchSummary(output, expandKey) {
|
|
155
|
+
const lines = nonBlankLines(output);
|
|
156
|
+
const paths = /* @__PURE__ */ new Set();
|
|
157
|
+
let matchCount = 0;
|
|
158
|
+
for (const line of lines) {
|
|
159
|
+
const path = extractResultPath(line);
|
|
160
|
+
if (path) paths.add(compactPath(path, 48));
|
|
161
|
+
if (line.trim()) matchCount += 1;
|
|
162
|
+
}
|
|
163
|
+
const matchLabel = matchCount === 1 ? "1 result" : `${matchCount} results`;
|
|
164
|
+
const fileLabel = paths.size === 0 ? "" : paths.size === 1 ? ` in ${[...paths][0]}` : ` in ${paths.size} files`;
|
|
165
|
+
const samples = [...paths].slice(0, 3).join(", ");
|
|
166
|
+
return `${matchLabel}${fileLabel}${samples && paths.size > 1 ? `: ${samples}` : ""}; ${expandKey} to expand`;
|
|
167
|
+
}
|
|
168
|
+
function formatExecSummary(output, details, isError, expandKey) {
|
|
169
|
+
const parsed = parseExecDetails(details);
|
|
170
|
+
const rows = nonBlankLines([parsed.stdout, parsed.stderr].filter(Boolean).join("\n") || output).length;
|
|
171
|
+
return `${parsed.exitCode === void 0 ? isError ? "failed" : "completed" : `exit ${parsed.exitCode}`}; ${rows === 1 ? "1 output line" : `${rows} output lines`}; ${expandKey} to expand`;
|
|
172
|
+
}
|
|
173
|
+
function formatMcpSummary(output, content, expandKey) {
|
|
174
|
+
if (content?.length) {
|
|
175
|
+
const counts = /* @__PURE__ */ new Map();
|
|
176
|
+
for (const block of content) counts.set(block.type, (counts.get(block.type) ?? 0) + 1);
|
|
177
|
+
return `${[...counts.entries()].map(([type, count]) => `${count} ${type}`).join(", ")}; ${expandKey} to expand`;
|
|
178
|
+
}
|
|
179
|
+
const rows = nonBlankLines(output).length;
|
|
180
|
+
return `${rows === 1 ? "1 result line" : `${rows} result lines`}; ${expandKey} to expand`;
|
|
181
|
+
}
|
|
182
|
+
function parseExecDetails(details) {
|
|
183
|
+
if (!details || typeof details !== "object") return {};
|
|
184
|
+
const record = details;
|
|
185
|
+
return {
|
|
186
|
+
exitCode: numberValue(record.exitCode ?? record.exit_code ?? record.code ?? record.status),
|
|
187
|
+
stdout: stringValue(record.stdout ?? record.output),
|
|
188
|
+
stderr: stringValue(record.stderr ?? record.errorOutput ?? record.error_output)
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function numberValue(value) {
|
|
192
|
+
if (typeof value === "number" && Number.isFinite(value)) return Math.trunc(value);
|
|
193
|
+
if (typeof value === "string" && /^-?\d+$/.test(value)) return Number(value);
|
|
194
|
+
}
|
|
195
|
+
function stringValue(value) {
|
|
196
|
+
return typeof value === "string" ? value : void 0;
|
|
197
|
+
}
|
|
198
|
+
function nonBlankLines(text) {
|
|
199
|
+
return text.split("\n").filter((line) => line.trim().length > 0);
|
|
200
|
+
}
|
|
201
|
+
function extractResultPath(line) {
|
|
202
|
+
const trimmed = line.trim();
|
|
203
|
+
const colonPath = trimmed.match(/^(.+?):\d+(?::\d+)?:/);
|
|
204
|
+
if (colonPath?.[1]) return colonPath[1];
|
|
205
|
+
const jsonPath = trimmed.match(/"?(?:path|file|file_path)"?\s*[:=]\s*"([^"]+)"/i);
|
|
206
|
+
if (jsonPath?.[1]) return jsonPath[1];
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
//#endregion
|
|
210
|
+
export { compactPath, displayToolName, extractExitCode, formatArgsSummary, formatCollapsedToolSummary, formatExecExpandedOutput, getToolSummaryKind, isExecStyleTool, isMcpStyleTool, isReadStyleTool, isSearchStyleTool };
|
|
211
|
+
|
|
212
|
+
//# sourceMappingURL=tool-summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-summary.js","names":[],"sources":["../../../src/tui/tool-summary.ts"],"sourcesContent":["import { basename, dirname } from 'node:path';\n\nimport { Text } from '@earendil-works/pi-tui';\n\nimport type { TuiToolContentBlock } from './tui-tool-result.js';\n\nconst MAX_ARG_VALUE_LENGTH = 120;\nconst MAX_PATH_LABEL_LENGTH = 72;\n\nexport type ToolSummaryKind = 'read' | 'search' | 'exec' | 'mcp' | 'generic';\n\nexport interface ToolSummaryContext {\n toolName: string;\n args: unknown;\n output: string;\n content?: TuiToolContentBlock[];\n details: unknown;\n isError: boolean;\n expandKey: string;\n}\n\nexport function formatArgsSummary(args: unknown, toolName: string): string {\n if (!args || typeof args !== 'object') return '';\n const compactRead = isReadStyleTool(toolName) ? formatCompactReadArgs(args) : null;\n if (compactRead) return compactRead;\n const command = isExecStyleTool(toolName) ? commandFromArgs(args) : null;\n if (command) return command;\n const entries = Object.entries(args as Record<string, unknown>);\n if (entries.length === 0) return '';\n return entries\n .map(([key, value]) => {\n const stringValue = formatArgValue(value);\n const truncated =\n stringValue.length > MAX_ARG_VALUE_LENGTH\n ? `${stringValue.slice(0, MAX_ARG_VALUE_LENGTH - 3)}...`\n : stringValue;\n return `${key}=${truncated}`;\n })\n .join(', ');\n}\n\nexport function getToolSummaryKind(toolName: string): ToolSummaryKind {\n if (isReadStyleTool(toolName)) return 'read';\n if (isSearchStyleTool(toolName)) return 'search';\n if (isExecStyleTool(toolName)) return 'exec';\n if (isMcpStyleTool(toolName)) return 'mcp';\n return 'generic';\n}\n\nexport function isReadStyleTool(toolName: string): boolean {\n const base = baseToolName(toolName);\n return ['read', 'read_file', 'memory_get'].includes(base);\n}\n\nexport function isSearchStyleTool(toolName: string): boolean {\n const base = baseToolName(toolName);\n return [\n 'search',\n 'grep',\n 'rg',\n 'ripgrep',\n 'search_code',\n 'file_search',\n 'list_files',\n ].includes(base);\n}\n\nexport function isExecStyleTool(toolName: string): boolean {\n const base = baseToolName(toolName);\n return [\n 'bash',\n 'shell',\n 'exec',\n 'run_command',\n 'exec_command',\n 'terminal',\n ].includes(base);\n}\n\nexport function isMcpStyleTool(toolName: string): boolean {\n return toolName.includes('__');\n}\n\nexport function displayToolName(toolName: string): string {\n const parts = toolName.split('__');\n if (parts.length === 2 && parts[0] && parts[1]) {\n return `${parts[0]}.${parts[1]}`;\n }\n return toolName;\n}\n\nexport function compactPath(path: string, maxLength = MAX_PATH_LABEL_LENGTH): string {\n const normalized = path.replace(/\\\\/g, '/');\n if (normalized.length <= maxLength) return normalized;\n const base = basename(normalized);\n const parent = basename(dirname(normalized));\n const suffix = parent ? `${parent}/${base}` : base;\n if (suffix.length + 2 <= maxLength) return `.../${suffix}`;\n return `.../${base.slice(Math.max(0, base.length - maxLength + 3))}`;\n}\n\nexport function formatCollapsedToolSummary(ctx: ToolSummaryContext): string {\n if (ctx.isError) {\n const rows = nonBlankLines(ctx.output).length;\n const rowLabel = rows === 1 ? '1 error line' : `${rows} error lines`;\n return `error; ${rowLabel}; ${ctx.expandKey} to expand`;\n }\n\n switch (getToolSummaryKind(ctx.toolName)) {\n case 'read': {\n const rows = new Text(ctx.output, 1, 0).render(80).length;\n const plural = rows === 1 ? 'row' : 'rows';\n return ` ${rows} ${plural}; ${ctx.expandKey} to expand`;\n }\n case 'search':\n return formatSearchSummary(ctx.output, ctx.expandKey);\n case 'exec':\n return formatExecSummary(ctx.output, ctx.details, ctx.isError, ctx.expandKey);\n case 'mcp':\n return formatMcpSummary(ctx.output, ctx.content, ctx.expandKey);\n case 'generic':\n return '';\n }\n}\n\nexport function formatExecExpandedOutput(output: string, details: unknown): string {\n const parsed = parseExecDetails(details);\n const sections: string[] = [];\n const stdout = parsed.stdout ?? output;\n if (stdout.trim()) {\n sections.push(`stdout\\n${stdout}`);\n }\n if (parsed.stderr?.trim()) {\n sections.push(`stderr\\n${parsed.stderr}`);\n }\n if (parsed.exitCode !== undefined) {\n sections.push(`exit ${parsed.exitCode}`);\n }\n return sections.join('\\n');\n}\n\nexport function extractExitCode(details: unknown): number | undefined {\n return parseExecDetails(details).exitCode;\n}\n\nfunction formatCompactReadArgs(args: unknown): string | null {\n if (!args || typeof args !== 'object') return null;\n const record = args as Record<string, unknown>;\n const rawPath = typeof record.path === 'string'\n ? record.path\n : typeof record.file_path === 'string'\n ? record.file_path\n : undefined;\n if (!rawPath) return null;\n\n const normalized = rawPath.replace(/\\\\/g, '/');\n const base = basename(normalized);\n let label: string;\n if (base === 'SKILL.md') {\n const parent = basename(dirname(normalized));\n label = parent ? `[skill] ${parent}` : '[skill]';\n } else if (base === 'AGENTS.md') {\n label = `read resource ${compactPath(normalized)}`;\n } else {\n label = compactPath(normalized);\n }\n\n const start = firstFiniteNumber(record.offset, record.from, record.start, record.line);\n const count = firstFiniteNumber(record.limit, record.lines, record.count);\n if (start != null && count != null && count > 0) {\n label += `:${start}-${start + count - 1}`;\n }\n return label;\n}\n\nfunction commandFromArgs(args: unknown): string | null {\n if (!args || typeof args !== 'object') return null;\n const record = args as Record<string, unknown>;\n const raw = record.command ?? record.cmd ?? record.script;\n if (Array.isArray(raw)) return raw.map(String).join(' ');\n if (typeof raw === 'string' && raw.trim()) return raw.trim();\n return null;\n}\n\nfunction baseToolName(toolName: string): string {\n return toolName.split('__').pop()?.toLowerCase() ?? toolName.toLowerCase();\n}\n\nfunction firstFiniteNumber(...values: unknown[]): number | null {\n for (const value of values) {\n if (typeof value === 'number' && Number.isFinite(value)) return Math.floor(value);\n if (typeof value === 'string' && value.trim()) {\n const parsed = Number(value);\n if (Number.isFinite(parsed)) return Math.floor(parsed);\n }\n }\n return null;\n}\n\nfunction formatArgValue(value: unknown): string {\n if (typeof value === 'string') return value;\n if (typeof value === 'bigint') return `${value.toString()}n`;\n if (typeof value === 'function') return '[function]';\n if (typeof value === 'symbol') return String(value);\n if (value instanceof Error) return value.message || value.name;\n try {\n const json = JSON.stringify(value);\n return json === undefined ? String(value) : json;\n } catch {\n return String(value);\n }\n}\n\nfunction formatSearchSummary(output: string, expandKey: string): string {\n const lines = nonBlankLines(output);\n const paths = new Set<string>();\n let matchCount = 0;\n for (const line of lines) {\n const path = extractResultPath(line);\n if (path) paths.add(compactPath(path, 48));\n if (line.trim()) matchCount += 1;\n }\n\n const matchLabel = matchCount === 1 ? '1 result' : `${matchCount} results`;\n const fileLabel = paths.size === 0\n ? ''\n : paths.size === 1\n ? ` in ${[...paths][0]}`\n : ` in ${paths.size} files`;\n const samples = [...paths].slice(0, 3).join(', ');\n const sampleSuffix = samples && paths.size > 1 ? `: ${samples}` : '';\n return `${matchLabel}${fileLabel}${sampleSuffix}; ${expandKey} to expand`;\n}\n\nfunction formatExecSummary(\n output: string,\n details: unknown,\n isError: boolean,\n expandKey: string,\n): string {\n const parsed = parseExecDetails(details);\n const outputText = [parsed.stdout, parsed.stderr].filter(Boolean).join('\\n') || output;\n const rows = nonBlankLines(outputText).length;\n const exit = parsed.exitCode === undefined\n ? isError ? 'failed' : 'completed'\n : `exit ${parsed.exitCode}`;\n const rowLabel = rows === 1 ? '1 output line' : `${rows} output lines`;\n return `${exit}; ${rowLabel}; ${expandKey} to expand`;\n}\n\nfunction formatMcpSummary(\n output: string,\n content: TuiToolContentBlock[] | undefined,\n expandKey: string,\n): string {\n if (content?.length) {\n const counts = new Map<string, number>();\n for (const block of content) {\n counts.set(block.type, (counts.get(block.type) ?? 0) + 1);\n }\n const label = [...counts.entries()]\n .map(([type, count]) => `${count} ${type}`)\n .join(', ');\n return `${label}; ${expandKey} to expand`;\n }\n const rows = nonBlankLines(output).length;\n const rowLabel = rows === 1 ? '1 result line' : `${rows} result lines`;\n return `${rowLabel}; ${expandKey} to expand`;\n}\n\nfunction parseExecDetails(details: unknown): {\n exitCode?: number;\n stdout?: string;\n stderr?: string;\n} {\n if (!details || typeof details !== 'object') return {};\n const record = details as Record<string, unknown>;\n return {\n exitCode: numberValue(record.exitCode ?? record.exit_code ?? record.code ?? record.status),\n stdout: stringValue(record.stdout ?? record.output),\n stderr: stringValue(record.stderr ?? record.errorOutput ?? record.error_output),\n };\n}\n\nfunction numberValue(value: unknown): number | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) return Math.trunc(value);\n if (typeof value === 'string' && /^-?\\d+$/.test(value)) return Number(value);\n return undefined;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction nonBlankLines(text: string): string[] {\n return text.split('\\n').filter((line) => line.trim().length > 0);\n}\n\nfunction extractResultPath(line: string): string | null {\n const trimmed = line.trim();\n const colonPath = trimmed.match(/^(.+?):\\d+(?::\\d+)?:/);\n if (colonPath?.[1]) return colonPath[1];\n const jsonPath = trimmed.match(/\"?(?:path|file|file_path)\"?\\s*[:=]\\s*\"([^\"]+)\"/i);\n if (jsonPath?.[1]) return jsonPath[1];\n return null;\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) {
|