@xopcai/xopc 0.0.124 → 0.0.126
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 +56 -102
- package/README.zh-CN.md +51 -98
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/feishu/src/schema/config-schema.d.ts +6 -6
- package/dist/extensions/feishu/src/workflow-progress.js +1 -1
- package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
- package/dist/extensions/telegram/src/config-schema.d.ts +8 -8
- package/dist/extensions/telegram/src/inbound-processor.js +1 -1
- package/dist/extensions/telegram/src/plugin.js +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +2 -2
- package/dist/extensions/telegram/src/workflow-progress.js +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/api/api.js +1 -1
- package/dist/extensions/weixin/src/config-schema.d.ts +3 -3
- package/dist/extensions/weixin/src/plugin.js +1 -1
- package/dist/extensions/weixin/src/workflow-progress.js +1 -1
- package/dist/gateway/static/root/assets/Combination-BzaXOLd9.js +41 -0
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-B5uSVAyJ.js → agent-avatar-dicebear-C70vgt60.js} +1 -1
- package/dist/gateway/static/root/assets/agents-DRYVahI-.js +2 -0
- package/dist/gateway/static/root/assets/app-management-settings-panel-D9-HW6cy.js +1 -0
- package/dist/gateway/static/root/assets/appearance-settings-BHlahIDL.js +1 -0
- package/dist/gateway/static/root/assets/apps-page-BdJ1eQg3.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-CXUGRp2i.js → archive-plugin-B-aoIt0w.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-Cmiub3Wg.js → attachment-load-BD0G0FD5.js} +1 -1
- package/dist/gateway/static/root/assets/automation-suggestion-card-iJRVI7aZ.js +1 -0
- package/dist/gateway/static/root/assets/automations-page-D8hYQbkl.js +4 -0
- package/dist/gateway/static/root/assets/{binary-plugins-0Izz-N3p.js → binary-plugins-B0mNlVSz.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-C1Kv0IkJ.js → block-editor-CJY9Lu5G.js} +3 -3
- package/dist/gateway/static/root/assets/browser-settings-page-CiWEO-Iy.js +8 -0
- package/dist/gateway/static/root/assets/capability-presets-api-Bgc8ag55.js +1 -0
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-B1nIi0TC.js +1 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-BeA2aVor.js → channel-recipient-api-0sauApoC.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-BddPdqVo.js +1 -0
- package/dist/gateway/static/root/assets/code-editor-gbRgS14t.js +1 -0
- package/dist/gateway/static/root/assets/connectors-page-Ba2GDhSE.js +2 -0
- package/dist/gateway/static/root/assets/{directory-picker-path-field-2rjzUu57.js → directory-picker-path-field-CiEc4KmY.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-4bvpk5wr.js +3 -0
- package/dist/gateway/static/root/assets/extension-debug-page-BbyczVZ3.js +1 -0
- package/dist/gateway/static/root/assets/extension-page-DLN1I3DR.js +1 -0
- package/dist/gateway/static/root/assets/extension-settings-page-D9VGHmYJ.js +1 -0
- package/dist/gateway/static/root/assets/{fetch-BU5S0Sn7.js → fetch-5V96dUz3.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-BIPGwrl1.js → gateway-config-api-BtIzObwp.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-KFsGGDhg.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-Cd0Zz30N.js → gateway-startup-retry-DEMad2wt.js} +1 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-4PcF6Sh6.js +1 -0
- package/dist/gateway/static/root/assets/goal-detail-page-B482PSaG.js +1 -0
- package/dist/gateway/static/root/assets/{goals-config-api-B95KdGMj.js → goals-config-api-CVN7-pdM.js} +1 -1
- package/dist/gateway/static/root/assets/goals-page-CUdgJuDn.js +2 -0
- package/dist/gateway/static/root/assets/goals-settings-IYCH3-Pi.js +1 -0
- package/dist/gateway/static/root/assets/heartbeat-settings-Cf_a2Bmz.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-CA2tR2vm.js +256 -0
- package/dist/gateway/static/root/assets/index-Ds3u0LOk.css +1 -0
- package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-lKTg6St7.js +1 -0
- package/dist/gateway/static/root/assets/logs-page-BCporcNH.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-Bv4k6iGJ.js +1 -0
- package/dist/gateway/static/root/assets/{media-plugins-BhIQU5yS.js → media-plugins-Bbi8g3N8.js} +1 -1
- package/dist/gateway/static/root/assets/messages-C22hxE1N.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-panel-D68Pyow7.js +2 -0
- package/dist/gateway/static/root/assets/notes-page-CuUMOiyv.js +1 -0
- package/dist/gateway/static/root/assets/notes-workbench-Dx2N5zTk.js +2 -0
- package/dist/gateway/static/root/assets/page-tabs-Cp395RYD.js +1 -0
- package/dist/gateway/static/root/assets/{preview-open-alternatives-DGzet1d7.js → preview-open-alternatives-DqV5OM4m.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-sB8AzZi3.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-LBnJqWK2.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-Dbj0o6SC.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-Cqgb-jqa.js → save-bar-controls-BItmzAzI.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-DVZcI8Yt.js → schedule-field-BQ8IjjCn.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-Bj7sOxC8.js → schema-form-BRpD6x3d.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-DhDZKspB.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BvXLMNL6.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-BmXn-8N6.js → settings-collapsible-section-BKSPQM4R.js} +1 -1
- package/dist/gateway/static/root/assets/settings-form-section-BmyfthNQ.js +1 -0
- package/dist/gateway/static/root/assets/settings-page-Cfm9UxAr.js +1 -0
- package/dist/gateway/static/root/assets/settings-page-layout-Bls5tfbH.js +1 -0
- package/dist/gateway/static/root/assets/setup-status-panel-kQEsTGAs.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-IB1v8i86.js → share-preview-page-DbYZNAPb.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-BtR4B0kn.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-CJNVOWoK.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-DcWDHrt3.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-BxQ384RC.js → system-settings-panel-DKDAojWM.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-BkcpvFYO.js → typed-models-lib-BCCV4Kkp.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-Cd0FaEQ4.js → use-channel-catalog-NBqg3iFY.js} +1 -1
- package/dist/gateway/static/root/assets/{user-profile-settings-panel-DQ7NnRSY.js → user-profile-settings-panel-suQ2x-LB.js} +1 -1
- package/dist/gateway/static/root/assets/{utils-YKhVf7Ka.js → utils-DPGVr3tS.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-DaJASKFP.js +1 -0
- package/dist/gateway/static/root/assets/work-item-detail-page-BrCZpAWh.js +1 -0
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-BTkRVNAh.js +3 -0
- package/dist/gateway/static/root/assets/{workflow-start-dialog-BNJVCWoS.js → workflow-start-dialog-DAImVtdO.js} +1 -1
- package/dist/gateway/static/root/assets/workflows-page-vyJ8wSXm.js +18 -0
- package/dist/gateway/static/root/index.html +8 -7
- package/dist/package.js +1 -1
- package/dist/src/activity/context.d.ts +11 -0
- package/dist/src/activity/context.js +36 -0
- package/dist/src/activity/context.js.map +1 -0
- package/dist/src/activity/emitter.d.ts +6 -0
- package/dist/src/activity/emitter.js +43 -0
- package/dist/src/activity/emitter.js.map +1 -0
- package/dist/src/activity/index.d.ts +3 -0
- package/dist/src/activity/index.js +3 -0
- package/dist/src/activity/service.d.ts +12 -0
- package/dist/src/activity/service.js +59 -0
- package/dist/src/activity/service.js.map +1 -0
- package/dist/src/activity/types.d.ts +109 -0
- package/dist/src/activity/types.js +1 -0
- package/dist/src/agent/agent-manager.d.ts +7 -0
- package/dist/src/agent/agent-manager.js +12 -5
- 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/project-context.js +2 -2
- package/dist/src/agent/context/workspace-seed.js +2 -2
- package/dist/src/agent/embedded/run-for-session.js +1 -1
- package/dist/src/agent/goals/post-turn.js +2 -2
- package/dist/src/agent/ipc/bus.js +1 -1
- package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
- package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
- package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
- package/dist/src/agent/mcp/mcp-transport.js +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/plugin-discovery.js +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/orchestration/agent-event-handler.d.ts +2 -0
- package/dist/src/agent/orchestration/agent-event-handler.js +13 -0
- 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/sandbox/command-validator.js +12 -0
- package/dist/src/agent/sandbox/command-validator.js.map +1 -1
- package/dist/src/agent/service.d.ts +2 -1
- package/dist/src/agent/service.js +24 -9
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/service.types.d.ts +7 -0
- package/dist/src/agent/session/session-inspector.d.ts +5 -3
- package/dist/src/agent/session/session-inspector.js +17 -8
- package/dist/src/agent/session/session-inspector.js.map +1 -1
- package/dist/src/agent/skills/hub-pull.js +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/tool-manuals/index.js +15 -6
- package/dist/src/agent/tool-manuals/index.js.map +1 -1
- package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -0
- package/dist/src/agent/tool-manuals/xopc-use.js +204 -0
- package/dist/src/agent/tool-manuals/xopc-use.js.map +1 -0
- package/dist/src/agent/tools/apply-patch.js +116 -62
- package/dist/src/agent/tools/apply-patch.js.map +1 -1
- 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/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.js +4 -0
- package/dist/src/agent/tools/exec-command.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 +10 -0
- package/dist/src/agent/tools/factory.js +16 -1
- 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/goal-tool.js +2 -2
- 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 +3 -0
- package/dist/src/agent/tools/index.js +4 -1
- 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/workflow-tool.js +1 -1
- package/dist/src/agent/tools/write.js +6 -0
- package/dist/src/agent/tools/write.js.map +1 -1
- package/dist/src/agent/tools/xopc-use-tool.d.ts +34 -0
- package/dist/src/agent/tools/xopc-use-tool.js +636 -0
- package/dist/src/agent/tools/xopc-use-tool.js.map +1 -0
- 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/agent-manifest/schema.d.ts +27 -27
- package/dist/src/automations/api/routes.js +1 -1
- package/dist/src/automations/domain/validation.d.ts +55 -55
- package/dist/src/automations/draft/automation-draft-validator.d.ts +25 -25
- package/dist/src/automations/service/action-executor.js +2 -2
- package/dist/src/browser/cdp-local-launcher.js +1 -1
- package/dist/src/browser/providers/browser-ext-install.js +3 -3
- package/dist/src/browser/providers/cloakbrowser.js +2 -2
- package/dist/src/browser/providers/playwright-doctor.js +1 -1
- package/dist/src/browser/stealth.js +1 -1
- package/dist/src/chat-commands/agent-edit.js +1 -1
- package/dist/src/chat-commands/builtins/config.js +1 -1
- package/dist/src/chat-commands/builtins/goal.js +2 -2
- package/dist/src/chat-commands/context.js +1 -1
- package/dist/src/cli/commands/agent.js +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +2 -2
- package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +1 -1
- package/dist/src/cli/commands/extension-pack.js +1 -1
- package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
- package/dist/src/cli/commands/goal.js +3 -3
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/commands/project.js +4 -4
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/gateway-bind.js +1 -1
- package/dist/src/config/index.js +1 -1
- package/dist/src/config/loader.js +1 -1
- package/dist/src/config/models-json.d.ts +14 -14
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/config/schema.d.ts +60 -60
- 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/daemon/launchd.js +1 -1
- package/dist/src/daemon/systemd.js +1 -1
- package/dist/src/extensions/discover-extensions.js +1 -1
- package/dist/src/extensions/loader.js +2 -2
- package/dist/src/gateway/agents-admin.js +1 -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/lib/config-payload.d.ts +14 -14
- package/dist/src/gateway/hono/lib/static-ui.js +1 -1
- package/dist/src/gateway/hono/middleware/log-context.js +8 -1
- package/dist/src/gateway/hono/middleware/log-context.js.map +1 -1
- package/dist/src/gateway/hono/routes/activity.d.ts +14 -0
- package/dist/src/gateway/hono/routes/activity.js +72 -0
- package/dist/src/gateway/hono/routes/activity.js.map +1 -0
- 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/goals.js +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/memory.js +2 -2
- package/dist/src/gateway/hono/routes/projects.js +903 -50
- package/dist/src/gateway/hono/routes/projects.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +102 -2
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/workflows.js +2 -2
- package/dist/src/gateway/lock.js +1 -1
- package/dist/src/gateway/ports.js +1 -1
- package/dist/src/gateway/service/sessions-api.d.ts +10 -0
- package/dist/src/gateway/service/sessions-api.js +31 -0
- package/dist/src/gateway/service/sessions-api.js.map +1 -1
- package/dist/src/gateway/service.js +28 -16
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/goals/goal-store.js +1 -1
- package/dist/src/goals/goal-store.js.map +1 -1
- package/dist/src/goals/goal-workflow-judge.js +1 -1
- package/dist/src/infra/ports.js +1 -1
- package/dist/src/infra/ssh-tunnel.js +1 -1
- package/dist/src/infra/update-check.js +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/migrations/runner.js +1 -1
- package/dist/src/notes/service.js +65 -6
- package/dist/src/notes/service.js.map +1 -1
- package/dist/src/notes/store.js +1 -1
- package/dist/src/projects/project-service.d.ts +2 -1
- package/dist/src/projects/project-service.js +59 -2
- package/dist/src/projects/project-service.js.map +1 -1
- package/dist/src/projects/project-store.d.ts +2 -1
- package/dist/src/projects/project-store.js +43 -0
- package/dist/src/projects/project-store.js.map +1 -1
- package/dist/src/projects/types.d.ts +10 -0
- package/dist/src/projects/workspace.js +1 -1
- package/dist/src/routing/agent-session-key.js +1 -1
- package/dist/src/routing/resolve-route.js +1 -1
- package/dist/src/routing/resolve-tui-session-key.js +1 -1
- package/dist/src/session/client-history.d.ts +3 -0
- package/dist/src/session/client-history.js +24 -9
- package/dist/src/session/client-history.js.map +1 -1
- package/dist/src/session/init-session-turn.js +1 -1
- package/dist/src/session/resolve-session.js +1 -1
- package/dist/src/session/session-context-for-llm.d.ts +2 -0
- package/dist/src/session/session-context-for-llm.js +14 -1
- package/dist/src/session/session-context-for-llm.js.map +1 -1
- package/dist/src/session/session-title.js +2 -2
- package/dist/src/session/store.js +3 -3
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/session/types.d.ts +4 -0
- package/dist/src/session/types.js.map +1 -1
- package/dist/src/storage/sqlite/activity-repository.d.ts +8 -0
- package/dist/src/storage/sqlite/activity-repository.js +208 -0
- package/dist/src/storage/sqlite/activity-repository.js.map +1 -0
- package/dist/src/storage/sqlite/connection.js +1 -1
- package/dist/src/storage/sqlite/index.d.ts +1 -0
- package/dist/src/storage/sqlite/index.js +2 -1
- 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/024_activity_events.sql +62 -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/row-mappers.js +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/schema.sql +141 -0
- package/dist/src/storage/sqlite/session-repository.js +11 -0
- package/dist/src/storage/sqlite/session-repository.js.map +1 -1
- package/dist/src/tui/backends/embedded-backend.d.ts +13 -0
- package/dist/src/tui/backends/embedded-backend.js +76 -7
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.d.ts +13 -0
- package/dist/src/tui/backends/gateway-sse-backend.js +53 -0
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/chat-history.js +16 -3
- package/dist/src/tui/chat-history.js.map +1 -1
- package/dist/src/tui/clipboard-image.js +1 -1
- package/dist/src/tui/components/assistant-message.js +12 -2
- package/dist/src/tui/components/assistant-message.js.map +1 -1
- package/dist/src/tui/components/chat-log.d.ts +23 -3
- package/dist/src/tui/components/chat-log.js +68 -9
- package/dist/src/tui/components/chat-log.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/tui-bottom-bar.js +9 -5
- package/dist/src/tui/components/tui-bottom-bar.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-backend.d.ts +16 -0
- package/dist/src/tui/tui-command-formatters.js +2 -2
- package/dist/src/tui/tui-commands.d.ts +9 -0
- package/dist/src/tui/tui-commands.js +95 -6
- package/dist/src/tui/tui-commands.js.map +1 -1
- package/dist/src/tui/tui-picker-overlay.d.ts +1 -0
- package/dist/src/tui/tui-picker-overlay.js +36 -1
- package/dist/src/tui/tui-picker-overlay.js.map +1 -1
- package/dist/src/tui/tui-picker-services.d.ts +13 -0
- package/dist/src/tui/tui-run-state.js +11 -0
- package/dist/src/tui/tui-run-state.js.map +1 -1
- package/dist/src/tui/tui-run-status-format.d.ts +3 -0
- package/dist/src/tui/tui-run-status-format.js +33 -0
- package/dist/src/tui/tui-run-status-format.js.map +1 -0
- package/dist/src/tui/tui-session-actions.d.ts +5 -0
- package/dist/src/tui/tui-session-actions.js +24 -0
- package/dist/src/tui/tui-session-actions.js.map +1 -1
- package/dist/src/tui/tui-timeline-picker.d.ts +19 -0
- package/dist/src/tui/tui-timeline-picker.js +81 -0
- package/dist/src/tui/tui-timeline-picker.js.map +1 -0
- package/dist/src/tui/tui-timeline.d.ts +15 -0
- package/dist/src/tui/tui-timeline.js +65 -0
- package/dist/src/tui/tui-timeline.js.map +1 -0
- 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-types.d.ts +1 -0
- package/dist/src/tui/tui-types.js +1 -0
- package/dist/src/tui/tui-types.js.map +1 -1
- package/dist/src/tui/tui.js +31 -25
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/utils/index.js +1 -1
- package/dist/src/utils/logger/index.js +1 -1
- package/dist/src/utils/logger/stats.d.ts +3 -3
- package/dist/src/utils/logger.js +1 -1
- package/dist/src/work-items/agent-context.d.ts +7 -0
- package/dist/src/work-items/agent-context.js +75 -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 +35 -0
- package/dist/src/work-items/work-item-service.js +277 -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/draft/workflow-draft-service.js +1 -1
- 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 +4 -1
- package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
- package/package.json +5 -5
- package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +0 -41
- package/dist/gateway/static/root/assets/agents-BjIxt67Z.js +0 -2
- package/dist/gateway/static/root/assets/app-management-settings-panel-CYCONLIL.js +0 -1
- package/dist/gateway/static/root/assets/appearance-settings-Clw3ryKg.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-QICTeGjX.js +0 -1
- package/dist/gateway/static/root/assets/automation-suggestion-card-CU0-4nQ-.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-Car-jtiz.js +0 -1
- package/dist/gateway/static/root/assets/browser-settings-page-CMeBJzlS.js +0 -8
- package/dist/gateway/static/root/assets/capability-presets-api-BmQTM9Il.js +0 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-DZEJEoCF.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-kkW-xFau.js +0 -1
- package/dist/gateway/static/root/assets/code-editor-dZTY2dRW.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-BvaQvO5F.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-DnHO686d.js +0 -1
- package/dist/gateway/static/root/assets/extension-debug-page-BGLRuWVN.js +0 -1
- package/dist/gateway/static/root/assets/extension-page-D978ePp9.js +0 -1
- package/dist/gateway/static/root/assets/extension-settings-page-B6Ih4Swx.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-CMEA3r5u.js +0 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-B-KHKeXN.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-BxrSoWdj.js +0 -1
- package/dist/gateway/static/root/assets/goals-page-BTJzIl28.js +0 -2
- package/dist/gateway/static/root/assets/goals-settings-BJyEuLLm.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-wkOjYNQT.js +0 -1
- package/dist/gateway/static/root/assets/index-BLaXr6Ev.css +0 -1
- package/dist/gateway/static/root/assets/index-c_9TVr_C.js +0 -191
- package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-BT8T4DyC.js +0 -1
- package/dist/gateway/static/root/assets/logs-page-CrxBJUgI.js +0 -2
- package/dist/gateway/static/root/assets/markdown-split-Dv66bO2b.js +0 -1
- package/dist/gateway/static/root/assets/messages-O6TAtdFC.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-panel-DOOpz6y1.js +0 -2
- package/dist/gateway/static/root/assets/notes-page-Br16pK9v.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-PSJAi0ZC.js +0 -2
- package/dist/gateway/static/root/assets/project-detail-page-CIGGgKuw.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-B2grhsBt.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-CXMORxBD.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-Bi2wkBzU.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-B1L3G4IA.js +0 -1
- package/dist/gateway/static/root/assets/settings-form-section-BnqYMWHR.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-BfRSHJmO.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-layout-CdWZU1hd.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-CWtPM7RK.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-ngbsBgij.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-BIe442Gv.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-BfchZRVa.js +0 -2
- package/dist/gateway/static/root/assets/voice-api-key-field-C5Ov8Uk_.js +0 -1
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-BYD9BtOq.js +0 -3
- package/dist/gateway/static/root/assets/workflows-page-BYF29ANm.js +0 -18
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { theme } from "../theme.js";
|
|
2
2
|
import { formatKeyIds } from "../format-tui-hotkeys.js";
|
|
3
|
-
import {
|
|
3
|
+
import { displayToolName, formatArgsSummary, formatCollapsedToolSummary, formatExecExpandedOutput, getToolSummaryKind, isExecStyleTool, isReadStyleTool } from "../tool-summary.js";
|
|
4
|
+
import { isDiffFriendlyTool, looksLikeUnifiedDiff, renderPatchSummary, renderUnifiedDiff } from "../tui-tool-diff.js";
|
|
4
5
|
import { parseTuiToolResult } from "../tui-tool-result.js";
|
|
5
|
-
import { truncateToVisualLines } from "./visual-truncate.js";
|
|
6
|
+
import { truncateToVisualLines, truncateToVisualLinesMiddle } from "./visual-truncate.js";
|
|
6
7
|
import { hasStructuredTuiToolRenderer, renderToolCallWithExtensions, renderToolResultWithExtensions, renderToolWithExtensions } from "../extension-host/tool-renderers.js";
|
|
7
|
-
import { basename, dirname } from "node:path";
|
|
8
8
|
import { Container, Image, Spacer, Text, getCapabilities } from "@earendil-works/pi-tui";
|
|
9
9
|
//#region src/tui/components/tool-execution.ts
|
|
10
|
-
const MAX_ARG_VALUE_LENGTH = 120;
|
|
11
10
|
const COLLAPSED_RESULT_VISUAL_LINES = 4;
|
|
11
|
+
const EXPANDED_RESULT_VISUAL_LINES = 80;
|
|
12
12
|
function sanitize(text) {
|
|
13
13
|
return text.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, "");
|
|
14
14
|
}
|
|
@@ -30,65 +30,6 @@ function getToolResultDisplayText(content, options) {
|
|
|
30
30
|
}
|
|
31
31
|
return trimTrailingBlankDisplayLines(parts.filter(Boolean).join("\n"));
|
|
32
32
|
}
|
|
33
|
-
function formatArgsSummary(args, toolName) {
|
|
34
|
-
if (!args || typeof args !== "object") return "";
|
|
35
|
-
const compactRead = isReadStyleTool(toolName) ? formatCompactReadArgs(args) : null;
|
|
36
|
-
if (compactRead) return compactRead;
|
|
37
|
-
const entries = Object.entries(args);
|
|
38
|
-
if (entries.length === 0) return "";
|
|
39
|
-
return entries.map(([key, value]) => {
|
|
40
|
-
const stringValue = formatArgValue(value);
|
|
41
|
-
return `${key}=${stringValue.length > MAX_ARG_VALUE_LENGTH ? `${stringValue.slice(0, MAX_ARG_VALUE_LENGTH - 3)}...` : stringValue}`;
|
|
42
|
-
}).join(", ");
|
|
43
|
-
}
|
|
44
|
-
function isReadStyleTool(toolName) {
|
|
45
|
-
return [
|
|
46
|
-
"read",
|
|
47
|
-
"read_file",
|
|
48
|
-
"memory_get"
|
|
49
|
-
].includes(toolName);
|
|
50
|
-
}
|
|
51
|
-
function formatCompactReadArgs(args) {
|
|
52
|
-
if (!args || typeof args !== "object") return null;
|
|
53
|
-
const record = args;
|
|
54
|
-
const rawPath = typeof record.path === "string" ? record.path : typeof record.file_path === "string" ? record.file_path : void 0;
|
|
55
|
-
if (!rawPath) return null;
|
|
56
|
-
const normalized = rawPath.replace(/\\/g, "/");
|
|
57
|
-
const base = basename(normalized);
|
|
58
|
-
let label = null;
|
|
59
|
-
if (base === "SKILL.md") {
|
|
60
|
-
const parent = basename(dirname(normalized));
|
|
61
|
-
label = parent ? `[skill] ${parent}` : "[skill]";
|
|
62
|
-
} else if (base === "AGENTS.md") label = `read resource ${normalized}`;
|
|
63
|
-
if (!label) return null;
|
|
64
|
-
const start = firstFiniteNumber(record.offset, record.from, record.start, record.line);
|
|
65
|
-
const count = firstFiniteNumber(record.limit, record.lines, record.count);
|
|
66
|
-
if (start != null && count != null && count > 0) label += `:${start}-${start + count - 1}`;
|
|
67
|
-
return label;
|
|
68
|
-
}
|
|
69
|
-
function firstFiniteNumber(...values) {
|
|
70
|
-
for (const value of values) {
|
|
71
|
-
if (typeof value === "number" && Number.isFinite(value)) return Math.floor(value);
|
|
72
|
-
if (typeof value === "string" && value.trim()) {
|
|
73
|
-
const parsed = Number(value);
|
|
74
|
-
if (Number.isFinite(parsed)) return Math.floor(parsed);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
function formatArgValue(value) {
|
|
80
|
-
if (typeof value === "string") return value;
|
|
81
|
-
if (typeof value === "bigint") return `${value.toString()}n`;
|
|
82
|
-
if (typeof value === "function") return "[function]";
|
|
83
|
-
if (typeof value === "symbol") return String(value);
|
|
84
|
-
if (value instanceof Error) return value.message || value.name;
|
|
85
|
-
try {
|
|
86
|
-
const json = JSON.stringify(value);
|
|
87
|
-
return json === void 0 ? String(value) : json;
|
|
88
|
-
} catch {
|
|
89
|
-
return String(value);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
33
|
function isTuiComponent(value) {
|
|
93
34
|
return Boolean(value && typeof value === "object" && typeof value.render === "function");
|
|
94
35
|
}
|
|
@@ -97,6 +38,7 @@ var ToolExecutionComponent = class extends Container {
|
|
|
97
38
|
contentText;
|
|
98
39
|
collapsedOutputComponent = null;
|
|
99
40
|
collapsedReadSummaryComponent = null;
|
|
41
|
+
expandedOutputComponent = null;
|
|
100
42
|
toolName;
|
|
101
43
|
toolCallId;
|
|
102
44
|
args;
|
|
@@ -122,6 +64,8 @@ var ToolExecutionComponent = class extends Container {
|
|
|
122
64
|
isError = false;
|
|
123
65
|
isPartial = true;
|
|
124
66
|
executionStarted = false;
|
|
67
|
+
startedAt = Date.now();
|
|
68
|
+
completedAt;
|
|
125
69
|
constructor(toolName, toolCallId, args, options = {}) {
|
|
126
70
|
super();
|
|
127
71
|
this.toolName = toolName;
|
|
@@ -145,6 +89,7 @@ var ToolExecutionComponent = class extends Container {
|
|
|
145
89
|
}
|
|
146
90
|
markExecutionStarted() {
|
|
147
91
|
this.executionStarted = true;
|
|
92
|
+
this.startedAt = Date.now();
|
|
148
93
|
this.refresh();
|
|
149
94
|
}
|
|
150
95
|
setArgsComplete() {
|
|
@@ -162,6 +107,7 @@ var ToolExecutionComponent = class extends Container {
|
|
|
162
107
|
this.resultDetails = parsed.envelope?.details;
|
|
163
108
|
this.isError = isError;
|
|
164
109
|
this.isPartial = isPartial;
|
|
110
|
+
if (!isPartial) this.completedAt = Date.now();
|
|
165
111
|
this.refresh();
|
|
166
112
|
}
|
|
167
113
|
setImageOptions(options) {
|
|
@@ -180,6 +126,7 @@ var ToolExecutionComponent = class extends Container {
|
|
|
180
126
|
const bgFn = this.isPartial ? (text) => theme.toolPendingBg(text) : this.isError ? (text) => theme.toolErrorBg(text) : (text) => theme.toolSuccessBg(text);
|
|
181
127
|
this.refreshCollapsedOutput(null);
|
|
182
128
|
this.refreshCollapsedReadSummary(null);
|
|
129
|
+
this.refreshExpandedOutput(null);
|
|
183
130
|
if (this.customRendererComponent) {
|
|
184
131
|
this.contentContainer.removeChild(this.customRendererComponent);
|
|
185
132
|
this.customRendererComponent = void 0;
|
|
@@ -290,8 +237,10 @@ var ToolExecutionComponent = class extends Container {
|
|
|
290
237
|
}
|
|
291
238
|
formatToolCallFallback() {
|
|
292
239
|
const argsStr = formatArgsSummary(this.args, this.toolName);
|
|
293
|
-
const titleParts = [theme.toolTitle(theme.bold(this.toolName))];
|
|
240
|
+
const titleParts = [theme.dim(this.toolStatusLabel()), theme.toolTitle(theme.bold(displayToolName(this.toolName)))];
|
|
294
241
|
if (argsStr) titleParts.push(theme.dim(`(${argsStr})`));
|
|
242
|
+
const duration = this.toolDurationLabel();
|
|
243
|
+
if (duration) titleParts.push(theme.dim(duration));
|
|
295
244
|
if (this.isPartial && !this.resultText && !this.resultContent && this.resultDetails === void 0) titleParts.push(theme.dim("…"));
|
|
296
245
|
return titleParts.join(" ");
|
|
297
246
|
}
|
|
@@ -301,18 +250,18 @@ var ToolExecutionComponent = class extends Container {
|
|
|
301
250
|
if (output) {
|
|
302
251
|
const expandKey = this.keybindings ? formatKeyIds(this.keybindings, "app.tools.expand", { capitalize: true }) : "Ctrl+O";
|
|
303
252
|
const lineCount = output.split("\n").length;
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
else if (
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
253
|
+
const useDiff = isDiffFriendlyTool(this.toolName) && looksLikeUnifiedDiff(output);
|
|
254
|
+
if (this.expanded && useDiff) text += renderPatchSummary(output) ?? renderUnifiedDiff(output);
|
|
255
|
+
else if (this.expanded && isExecStyleTool(this.toolName)) this.refreshExpandedOutput(theme.toolOutput(formatExecExpandedOutput(output, this.resultDetails)));
|
|
256
|
+
else if (this.expanded) this.refreshExpandedOutput(theme.toolOutput(output));
|
|
257
|
+
else if (useDiff) text += theme.dim("preview");
|
|
258
|
+
else if (getToolSummaryKind(this.toolName) !== "generic") text += this.collapsedSpecializedSummary(output, expandKey);
|
|
259
|
+
else {
|
|
311
260
|
const suffix = lineCount > COLLAPSED_RESULT_VISUAL_LINES ? theme.dim(` (${lineCount} lines; ${expandKey} to expand)`) : "";
|
|
312
261
|
text += theme.dim(`preview${suffix}`);
|
|
313
262
|
}
|
|
314
263
|
}
|
|
315
|
-
if (this.
|
|
264
|
+
if (this.shouldRenderDetailsPreview()) {
|
|
316
265
|
const detailsText = formatDetailsPreview(this.resultDetails);
|
|
317
266
|
if (detailsText) text = [text, theme.dim(detailsText)].filter(Boolean).join("\n");
|
|
318
267
|
}
|
|
@@ -320,28 +269,62 @@ var ToolExecutionComponent = class extends Container {
|
|
|
320
269
|
}
|
|
321
270
|
formatToolExecution() {
|
|
322
271
|
const argsStr = formatArgsSummary(this.args, this.toolName);
|
|
323
|
-
const titleParts = [theme.toolTitle(theme.bold(this.toolName))];
|
|
272
|
+
const titleParts = [theme.dim(this.toolStatusLabel()), theme.toolTitle(theme.bold(displayToolName(this.toolName)))];
|
|
324
273
|
if (argsStr) titleParts.push(theme.dim(`(${argsStr})`));
|
|
274
|
+
const duration = this.toolDurationLabel();
|
|
275
|
+
if (duration) titleParts.push(theme.dim(duration));
|
|
325
276
|
let text = titleParts.join(" ");
|
|
326
277
|
const output = this.getDisplayResultText();
|
|
327
278
|
if (output) {
|
|
328
279
|
const expandKey = this.keybindings ? formatKeyIds(this.keybindings, "app.tools.expand", { capitalize: true }) : "Ctrl+O";
|
|
329
280
|
const lineCount = output.split("\n").length;
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
else if (
|
|
281
|
+
const useDiff = isDiffFriendlyTool(this.toolName) && looksLikeUnifiedDiff(output);
|
|
282
|
+
if (this.expanded && useDiff) text += `\n${renderPatchSummary(output) ?? renderUnifiedDiff(output)}`;
|
|
283
|
+
else if (this.expanded && isExecStyleTool(this.toolName)) this.refreshExpandedOutput(theme.toolOutput(formatExecExpandedOutput(output, this.resultDetails)));
|
|
284
|
+
else if (this.expanded) this.refreshExpandedOutput(theme.toolOutput(output));
|
|
285
|
+
else if (useDiff) {
|
|
286
|
+
const suffix = output.split("\n").length > COLLAPSED_RESULT_VISUAL_LINES ? theme.dim(` (${output.split("\n").length} lines; ${expandKey} to expand)`) : "";
|
|
287
|
+
text += `\n${theme.dim(`preview${suffix}`)}`;
|
|
288
|
+
} else if (isReadStyleTool(this.toolName)) this.refreshCollapsedReadSummary(output, expandKey);
|
|
289
|
+
else if (getToolSummaryKind(this.toolName) !== "generic") text += `\n${this.collapsedSpecializedSummary(output, expandKey)}`;
|
|
333
290
|
else {
|
|
334
291
|
const suffix = lineCount > COLLAPSED_RESULT_VISUAL_LINES ? theme.dim(` (${lineCount} lines; ${expandKey} to expand)`) : "";
|
|
335
292
|
text += `\n${theme.dim(`preview${suffix}`)}`;
|
|
336
293
|
this.refreshCollapsedOutput(theme.toolOutput(output), lineCount > COLLAPSED_RESULT_VISUAL_LINES ? void 0 : `${expandKey} to expand`);
|
|
337
294
|
}
|
|
338
295
|
} else if (this.isPartial) text += `\n${theme.dim("…")}`;
|
|
339
|
-
if (this.
|
|
296
|
+
if (this.shouldRenderDetailsPreview()) {
|
|
340
297
|
const detailsText = formatDetailsPreview(this.resultDetails);
|
|
341
298
|
if (detailsText) text += `\n${theme.dim(detailsText)}`;
|
|
342
299
|
}
|
|
343
300
|
return text;
|
|
344
301
|
}
|
|
302
|
+
toolStatusLabel() {
|
|
303
|
+
if (this.isError) return "Failed";
|
|
304
|
+
if (this.isPartial && !this.resultText && !this.resultContent && this.resultDetails === void 0) return this.executionStarted ? "Calling" : "Queued";
|
|
305
|
+
if (this.isPartial) return "Calling";
|
|
306
|
+
return "Called";
|
|
307
|
+
}
|
|
308
|
+
toolDurationLabel() {
|
|
309
|
+
if (this.completedAt === void 0) return "";
|
|
310
|
+
const durationMs = Math.max(0, this.completedAt - this.startedAt);
|
|
311
|
+
if (durationMs < 100) return "";
|
|
312
|
+
return `${durationMs}ms`;
|
|
313
|
+
}
|
|
314
|
+
collapsedSpecializedSummary(output, expandKey) {
|
|
315
|
+
return theme.dim(formatCollapsedToolSummary({
|
|
316
|
+
toolName: this.toolName,
|
|
317
|
+
args: this.args,
|
|
318
|
+
output,
|
|
319
|
+
content: this.resultContent,
|
|
320
|
+
details: this.resultDetails,
|
|
321
|
+
isError: this.isError,
|
|
322
|
+
expandKey
|
|
323
|
+
}));
|
|
324
|
+
}
|
|
325
|
+
shouldRenderDetailsPreview() {
|
|
326
|
+
return this.expanded && this.resultDetails !== void 0 && !isExecStyleTool(this.toolName);
|
|
327
|
+
}
|
|
345
328
|
getDisplayResultText() {
|
|
346
329
|
if (!this.resultContent) return trimTrailingBlankDisplayLines(this.resultText);
|
|
347
330
|
return getToolResultDisplayText(this.resultContent, {
|
|
@@ -384,6 +367,15 @@ var ToolExecutionComponent = class extends Container {
|
|
|
384
367
|
this.collapsedReadSummaryComponent = createCollapsedReadSummaryComponent(text, expandKey, 1);
|
|
385
368
|
this.contentContainer.addChild(this.collapsedReadSummaryComponent);
|
|
386
369
|
}
|
|
370
|
+
refreshExpandedOutput(text) {
|
|
371
|
+
if (this.expandedOutputComponent) {
|
|
372
|
+
this.contentContainer.removeChild(this.expandedOutputComponent);
|
|
373
|
+
this.expandedOutputComponent = null;
|
|
374
|
+
}
|
|
375
|
+
if (!text) return;
|
|
376
|
+
this.expandedOutputComponent = createVisualMiddleComponent(text, EXPANDED_RESULT_VISUAL_LINES, 1);
|
|
377
|
+
this.contentContainer.addChild(this.expandedOutputComponent);
|
|
378
|
+
}
|
|
387
379
|
};
|
|
388
380
|
function formatDetailsPreview(details) {
|
|
389
381
|
if (details === null) return "";
|
|
@@ -412,6 +404,24 @@ function createVisualTailComponent(text, maxVisualLines, paddingX, truncationHin
|
|
|
412
404
|
}
|
|
413
405
|
};
|
|
414
406
|
}
|
|
407
|
+
function createVisualMiddleComponent(text, maxVisualLines, paddingX) {
|
|
408
|
+
let cachedWidth;
|
|
409
|
+
let cachedLines;
|
|
410
|
+
return {
|
|
411
|
+
render(width) {
|
|
412
|
+
if (cachedWidth !== width || cachedLines === void 0) {
|
|
413
|
+
const result = truncateToVisualLinesMiddle(text, maxVisualLines, width, paddingX);
|
|
414
|
+
cachedWidth = width;
|
|
415
|
+
cachedLines = result.visualLines;
|
|
416
|
+
}
|
|
417
|
+
return cachedLines;
|
|
418
|
+
},
|
|
419
|
+
invalidate() {
|
|
420
|
+
cachedWidth = void 0;
|
|
421
|
+
cachedLines = void 0;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
}
|
|
415
425
|
function createCollapsedReadSummaryComponent(text, expandKey, paddingX) {
|
|
416
426
|
let cachedWidth;
|
|
417
427
|
let cachedLine;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-execution.js","names":[],"sources":["../../../../src/tui/components/tool-execution.ts"],"sourcesContent":["import {\n Container,\n type Component,\n getCapabilities,\n Image,\n type KeybindingsManager,\n Spacer,\n Text,\n} from '@earendil-works/pi-tui';\nimport { basename, dirname } from 'node:path';\nimport type { AgentToolResult } from '@earendil-works/pi-agent-core';\n\nimport { theme } from '../theme.js';\nimport { formatKeyIds } from '../format-tui-hotkeys.js';\nimport { isDiffFriendlyTool, looksLikeUnifiedDiff, renderUnifiedDiff } from '../tui-tool-diff.js';\nimport {\n hasStructuredTuiToolRenderer,\n renderToolCallWithExtensions,\n renderToolResultWithExtensions,\n renderToolWithExtensions,\n} from '../extension-host/tool-renderers.js';\nimport {\n parseTuiToolResult,\n type TuiToolContentBlock,\n} from '../tui-tool-result.js';\nimport { truncateToVisualLines } from './visual-truncate.js';\n\nconst MAX_ARG_VALUE_LENGTH = 120;\nconst COLLAPSED_RESULT_VISUAL_LINES = 4;\n\nexport interface ToolExecutionOptions {\n showImages?: boolean;\n imageWidthCells?: number;\n keybindings?: KeybindingsManager;\n toolCallId?: string;\n cwd?: string;\n}\n\nfunction sanitize(text: string): string {\n return text.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/g, '');\n}\n\nfunction trimTrailingBlankDisplayLines(text: string): string {\n return text.replace(/(?:\\r?\\n[ \\t]*)+$/g, '');\n}\n\nexport function getToolResultDisplayText(\n content: TuiToolContentBlock[],\n options: { showImages: boolean; supportsInlineImages: boolean },\n): string {\n const parts: string[] = [];\n for (const block of content) {\n if (block.type === 'text') {\n if (block.text) parts.push(sanitize(block.text));\n continue;\n }\n if (block.type === 'image' && (!options.supportsInlineImages || !options.showImages)) {\n parts.push(block.mimeType ? `[image:${block.mimeType}]` : '[image]');\n continue;\n }\n if (block.type !== 'image') {\n parts.push(block.text ? sanitize(block.text) : `[${block.type}]`);\n }\n }\n return trimTrailingBlankDisplayLines(parts.filter(Boolean).join('\\n'));\n}\n\nfunction 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 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\nfunction isReadStyleTool(toolName: string): boolean {\n return ['read', 'read_file', 'memory_get'].includes(toolName);\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 | null = null;\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 ${normalized}`;\n }\n if (!label) return null;\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 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 isTuiComponent(value: unknown): value is Component {\n return Boolean(\n value &&\n typeof value === 'object' &&\n typeof (value as { render?: unknown }).render === 'function',\n );\n}\n\nexport class ToolExecutionComponent extends Container {\n private contentContainer: Container;\n private contentText: Text;\n private collapsedOutputComponent: ReturnType<typeof createVisualTailComponent> | null = null;\n private collapsedReadSummaryComponent: ReturnType<typeof createCollapsedReadSummaryComponent> | null = null;\n private toolName: string;\n private toolCallId: string;\n private args: unknown;\n private argsComplete = true;\n private resultText = '';\n private resultContent: TuiToolContentBlock[] | undefined;\n private resultDetails: unknown;\n private rendererState: Record<string, unknown> = {};\n private lastRendererOutput: string[] | Component | undefined;\n private lastCallRendererOutput: string[] | Component | undefined;\n private lastResultRendererOutput: string[] | Component | undefined;\n private customRendererComponent: Component | undefined;\n private structuredRendererComponents: Component[] = [];\n private contentTextAttached = true;\n private rendererInvalidationQueued = false;\n private imageComponents: Image[] = [];\n private imageSpacers: Spacer[] = [];\n private showImages: boolean;\n private imageWidthCells: number;\n private keybindings: KeybindingsManager | undefined;\n private cwd: string;\n private expanded = false;\n private isError = false;\n private isPartial = true;\n private executionStarted = false;\n\n constructor(toolName: string, toolCallId: string, args: unknown, options: ToolExecutionOptions = {}) {\n super();\n this.toolName = toolName;\n this.toolCallId = toolCallId;\n this.args = args;\n this.showImages = options.showImages ?? true;\n this.imageWidthCells = Math.max(1, Math.floor(options.imageWidthCells ?? 60));\n this.keybindings = options.keybindings;\n this.cwd = options.cwd ?? process.cwd();\n\n this.addChild(new Spacer(1));\n\n const bgFn = (text: string) => theme.toolPendingBg(text);\n this.contentContainer = new Container();\n this.contentText = new Text('', 1, 1, bgFn);\n this.contentContainer.addChild(this.contentText);\n this.addChild(this.contentContainer);\n\n this.refresh();\n }\n\n setArgs(args: unknown): void {\n this.args = args;\n this.refresh();\n }\n\n markExecutionStarted(): void {\n this.executionStarted = true;\n this.refresh();\n }\n\n setArgsComplete(): void {\n this.argsComplete = true;\n this.refresh();\n }\n\n setExpanded(expanded: boolean): void {\n this.expanded = expanded;\n this.refresh();\n }\n\n updateResult(result: AgentToolResult<any> | unknown, isPartial = false, isError = false): void {\n const parsed = parseTuiToolResult(result);\n this.resultText = sanitize(parsed.text);\n this.resultContent = parsed.envelope?.content;\n this.resultDetails = parsed.envelope?.details;\n this.isError = isError;\n this.isPartial = isPartial;\n this.refresh();\n }\n\n setImageOptions(options: ToolExecutionOptions): void {\n if (options.showImages !== undefined) {\n this.showImages = options.showImages;\n }\n if (options.imageWidthCells !== undefined) {\n this.imageWidthCells = Math.max(1, Math.floor(options.imageWidthCells));\n }\n if (options.keybindings !== undefined) {\n this.keybindings = options.keybindings;\n }\n if (options.cwd !== undefined) {\n this.cwd = options.cwd;\n }\n this.refresh();\n }\n\n setPartialDetails(details: unknown): void {\n this.resultDetails = details;\n this.isPartial = true;\n this.refresh();\n }\n\n private refresh(): void {\n const bgFn = this.isPartial\n ? (text: string) => theme.toolPendingBg(text)\n : this.isError\n ? (text: string) => theme.toolErrorBg(text)\n : (text: string) => theme.toolSuccessBg(text);\n this.refreshCollapsedOutput(null);\n this.refreshCollapsedReadSummary(null);\n if (this.customRendererComponent) {\n this.contentContainer.removeChild(this.customRendererComponent);\n this.customRendererComponent = undefined;\n }\n for (const component of this.structuredRendererComponents) {\n this.contentContainer.removeChild(component);\n }\n this.structuredRendererComponents = [];\n this.contentText.setCustomBgFn(bgFn);\n\n if (hasStructuredTuiToolRenderer(this.toolName)) {\n this.detachContentText();\n this.renderStructuredExtensionTool();\n } else {\n const custom = this.renderExtensionTool();\n if (Array.isArray(custom) && custom.length > 0) {\n this.ensureContentTextAttached();\n this.lastRendererOutput = custom;\n this.contentText.setText(custom.join('\\n'));\n } else if (isTuiComponent(custom)) {\n this.detachContentText();\n this.customRendererComponent = custom;\n this.lastRendererOutput = custom;\n this.contentContainer.addChild(custom);\n } else {\n this.ensureContentTextAttached();\n this.lastRendererOutput = undefined;\n this.contentText.setText(this.formatToolExecution());\n }\n }\n this.refreshImages();\n }\n\n private appendRendererResult(result: ReturnType<typeof renderToolWithExtensions>): boolean {\n if (Array.isArray(result) && result.length > 0) {\n const component = new Text(result.join('\\n'), 1, 1);\n this.structuredRendererComponents.push(component);\n this.contentContainer.addChild(component);\n return true;\n }\n if (isTuiComponent(result)) {\n this.structuredRendererComponents.push(result);\n this.contentContainer.addChild(result);\n return true;\n }\n return false;\n }\n\n private renderStructuredExtensionTool(): void {\n const call = this.renderExtensionToolCall();\n if (this.appendRendererResult(call)) {\n this.lastCallRendererOutput = call as string[] | Component;\n } else {\n this.lastCallRendererOutput = undefined;\n this.ensureContentTextAttached();\n this.contentText.setText(this.formatToolCallFallback());\n }\n\n if (!this.isPartial || this.resultDetails !== undefined || this.resultText || this.resultContent) {\n const result = this.renderExtensionToolResult();\n if (this.appendRendererResult(result)) {\n this.lastResultRendererOutput = result as string[] | Component;\n } else {\n this.appendRendererResult([this.formatToolResultFallback()].filter(Boolean));\n this.lastResultRendererOutput = undefined;\n }\n }\n }\n\n private ensureContentTextAttached(): void {\n if (this.contentTextAttached) return;\n this.contentContainer.addChild(this.contentText);\n this.contentTextAttached = true;\n }\n\n private detachContentText(): void {\n if (!this.contentTextAttached) return;\n this.contentContainer.removeChild(this.contentText);\n this.contentTextAttached = false;\n }\n\n private requestRendererInvalidate(): void {\n if (this.rendererInvalidationQueued) return;\n this.rendererInvalidationQueued = true;\n queueMicrotask(() => {\n this.rendererInvalidationQueued = false;\n this.refresh();\n this.invalidate();\n });\n }\n\n private renderExtensionTool(): ReturnType<typeof renderToolWithExtensions> {\n return renderToolWithExtensions(this.createRenderContext(this.lastRendererOutput));\n }\n\n private renderExtensionToolCall(): ReturnType<typeof renderToolWithExtensions> {\n return renderToolCallWithExtensions(\n this.createRenderContext(this.lastCallRendererOutput),\n theme,\n );\n }\n\n private renderExtensionToolResult(): ReturnType<typeof renderToolWithExtensions> {\n return renderToolResultWithExtensions(\n this.createRenderContext(this.lastResultRendererOutput),\n theme,\n );\n }\n\n private createRenderContext(lastComponent: string[] | Component | undefined) {\n return {\n toolName: this.toolName,\n toolCallId: this.toolCallId,\n args: this.args,\n resultText: this.getDisplayResultText(),\n content: this.resultContent,\n details: this.resultDetails,\n invalidate: () => this.requestRendererInvalidate(),\n lastComponent,\n state: this.rendererState,\n cwd: this.cwd,\n executionStarted: this.executionStarted,\n argsComplete: this.argsComplete,\n isError: this.isError,\n isPartial: this.isPartial,\n expanded: this.expanded,\n showImages: this.showImages,\n };\n }\n\n private formatToolCallFallback(): string {\n const argsStr = formatArgsSummary(this.args, this.toolName);\n const titleParts = [theme.toolTitle(theme.bold(this.toolName))];\n if (argsStr) {\n titleParts.push(theme.dim(`(${argsStr})`));\n }\n if (this.isPartial && !this.resultText && !this.resultContent && this.resultDetails === undefined) {\n titleParts.push(theme.dim('…'));\n }\n return titleParts.join(' ');\n }\n\n private formatToolResultFallback(): string {\n const output = this.getDisplayResultText();\n let text = '';\n if (output) {\n const expandKey = this.keybindings\n ? formatKeyIds(this.keybindings, 'app.tools.expand', { capitalize: true })\n : 'Ctrl+O';\n const lineCount = output.split('\\n').length;\n const useDiff =\n this.expanded &&\n isDiffFriendlyTool(this.toolName) &&\n looksLikeUnifiedDiff(output);\n if (useDiff) {\n text += renderUnifiedDiff(output);\n } else if (this.expanded) {\n text += theme.toolOutput(output);\n } else if (isReadStyleTool(this.toolName)) {\n const rows = new Text(output, 1, 0).render(80).length;\n const plural = rows === 1 ? 'row' : 'rows';\n text += theme.dim(` ${rows} ${plural}; ${expandKey} to expand`);\n } else {\n const suffix = lineCount > COLLAPSED_RESULT_VISUAL_LINES\n ? theme.dim(` (${lineCount} lines; ${expandKey} to expand)`)\n : '';\n text += theme.dim(`preview${suffix}`);\n }\n }\n if (this.expanded && this.resultDetails !== undefined) {\n const detailsText = formatDetailsPreview(this.resultDetails);\n if (detailsText) {\n text = [text, theme.dim(detailsText)].filter(Boolean).join('\\n');\n }\n }\n return text;\n }\n\n private formatToolExecution(): string {\n // Title line: 🔧 tool_name (args_summary)\n const argsStr = formatArgsSummary(this.args, this.toolName);\n const titleParts = [theme.toolTitle(theme.bold(this.toolName))];\n if (argsStr) {\n titleParts.push(theme.dim(`(${argsStr})`));\n }\n let text = titleParts.join(' ');\n\n // Output / result — collapsed: single-line summary; expanded: full output\n const output = this.getDisplayResultText();\n if (output) {\n const expandKey = this.keybindings\n ? formatKeyIds(this.keybindings, 'app.tools.expand', { capitalize: true })\n : 'Ctrl+O';\n const lineCount = output.split('\\n').length;\n const useDiff =\n this.expanded &&\n isDiffFriendlyTool(this.toolName) &&\n looksLikeUnifiedDiff(output);\n if (useDiff) {\n text += `\\n${renderUnifiedDiff(output)}`;\n } else if (this.expanded) {\n text += `\\n${theme.toolOutput(output)}`;\n } else if (isReadStyleTool(this.toolName)) {\n this.refreshCollapsedReadSummary(output, expandKey);\n } else {\n const suffix = lineCount > COLLAPSED_RESULT_VISUAL_LINES\n ? theme.dim(` (${lineCount} lines; ${expandKey} to expand)`)\n : '';\n text += `\\n${theme.dim(`preview${suffix}`)}`;\n this.refreshCollapsedOutput(\n theme.toolOutput(output),\n lineCount > COLLAPSED_RESULT_VISUAL_LINES ? undefined : `${expandKey} to expand`,\n );\n }\n } else if (this.isPartial) {\n text += `\\n${theme.dim('…')}`;\n }\n\n if (this.expanded && this.resultDetails !== undefined) {\n const detailsText = formatDetailsPreview(this.resultDetails);\n if (detailsText) {\n text += `\\n${theme.dim(detailsText)}`;\n }\n }\n\n return text;\n }\n\n private getDisplayResultText(): string {\n if (!this.resultContent) {\n return trimTrailingBlankDisplayLines(this.resultText);\n }\n return getToolResultDisplayText(this.resultContent, {\n showImages: this.showImages,\n supportsInlineImages: Boolean(getCapabilities().images),\n });\n }\n\n private refreshImages(): void {\n for (const image of this.imageComponents) {\n this.removeChild(image);\n }\n this.imageComponents = [];\n for (const spacer of this.imageSpacers) {\n this.removeChild(spacer);\n }\n this.imageSpacers = [];\n\n const imageBlocks = this.resultContent?.filter(\n (block) => block.type === 'image' && block.data && block.mimeType,\n ) ?? [];\n if (imageBlocks.length === 0) return;\n\n const capabilities = getCapabilities();\n if (!capabilities.images || !this.showImages) return;\n\n for (const block of imageBlocks) {\n const spacer = new Spacer(1);\n const image = new Image(\n block.data!,\n block.mimeType!,\n { fallbackColor: (text: string) => theme.toolOutput(text) },\n { maxWidthCells: this.imageWidthCells },\n );\n this.imageSpacers.push(spacer);\n this.imageComponents.push(image);\n this.addChild(spacer);\n this.addChild(image);\n }\n }\n\n private refreshCollapsedOutput(text: string | null, truncationHint?: string): void {\n if (this.collapsedOutputComponent) {\n this.contentContainer.removeChild(this.collapsedOutputComponent);\n this.collapsedOutputComponent = null;\n }\n if (!text) return;\n this.collapsedOutputComponent = createVisualTailComponent(\n text,\n COLLAPSED_RESULT_VISUAL_LINES,\n 1,\n truncationHint,\n );\n this.contentContainer.addChild(this.collapsedOutputComponent);\n }\n\n private refreshCollapsedReadSummary(text: string | null, expandKey?: string): void {\n if (this.collapsedReadSummaryComponent) {\n this.contentContainer.removeChild(this.collapsedReadSummaryComponent);\n this.collapsedReadSummaryComponent = null;\n }\n if (!text || !expandKey) return;\n this.collapsedReadSummaryComponent = createCollapsedReadSummaryComponent(text, expandKey, 1);\n this.contentContainer.addChild(this.collapsedReadSummaryComponent);\n }\n}\n\nfunction formatDetailsPreview(details: unknown): string {\n if (details === null) return '';\n if (typeof details === 'string') return details;\n try {\n return JSON.stringify(details, null, 2);\n } catch {\n return String(details);\n }\n}\n\nfunction createVisualTailComponent(\n text: string,\n maxVisualLines: number,\n paddingX: number,\n truncationHint?: string,\n) {\n let cachedWidth: number | undefined;\n let cachedLines: string[] | undefined;\n return {\n render(width: number): string[] {\n if (cachedWidth !== width || cachedLines === undefined) {\n const result = truncateToVisualLines(text, maxVisualLines, width, paddingX);\n cachedWidth = width;\n cachedLines =\n result.skippedCount > 0 && truncationHint\n ? [theme.dim(` (${result.skippedCount} rows hidden; ${truncationHint})`), ...result.visualLines]\n : result.visualLines;\n }\n return cachedLines;\n },\n invalidate(): void {\n cachedWidth = undefined;\n cachedLines = undefined;\n },\n };\n}\n\nfunction createCollapsedReadSummaryComponent(text: string, expandKey: string, paddingX: number) {\n let cachedWidth: number | undefined;\n let cachedLine: string | undefined;\n return {\n render(width: number): string[] {\n if (cachedWidth !== width || cachedLine === undefined) {\n const rows = new Text(text, paddingX, 0).render(width).length;\n const plural = rows === 1 ? 'row' : 'rows';\n cachedWidth = width;\n cachedLine = theme.dim(` ${rows} ${plural}; ${expandKey} to expand`);\n }\n return [cachedLine];\n },\n invalidate(): void {\n cachedWidth = undefined;\n cachedLine = undefined;\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tool-execution.js","names":[],"sources":["../../../../src/tui/components/tool-execution.ts"],"sourcesContent":["import {\n Container,\n type Component,\n getCapabilities,\n Image,\n type KeybindingsManager,\n Spacer,\n Text,\n} from '@earendil-works/pi-tui';\nimport type { AgentToolResult } from '@earendil-works/pi-agent-core';\n\nimport { theme } from '../theme.js';\nimport { formatKeyIds } from '../format-tui-hotkeys.js';\nimport {\n isDiffFriendlyTool,\n looksLikeUnifiedDiff,\n renderPatchSummary,\n renderUnifiedDiff,\n} from '../tui-tool-diff.js';\nimport {\n hasStructuredTuiToolRenderer,\n renderToolCallWithExtensions,\n renderToolResultWithExtensions,\n renderToolWithExtensions,\n} from '../extension-host/tool-renderers.js';\nimport {\n parseTuiToolResult,\n type TuiToolContentBlock,\n} from '../tui-tool-result.js';\nimport {\n displayToolName,\n formatArgsSummary,\n formatCollapsedToolSummary,\n formatExecExpandedOutput,\n getToolSummaryKind,\n isExecStyleTool,\n isReadStyleTool,\n} from '../tool-summary.js';\nimport { truncateToVisualLines, truncateToVisualLinesMiddle } from './visual-truncate.js';\n\nconst COLLAPSED_RESULT_VISUAL_LINES = 4;\nconst EXPANDED_RESULT_VISUAL_LINES = 80;\n\nexport interface ToolExecutionOptions {\n showImages?: boolean;\n imageWidthCells?: number;\n keybindings?: KeybindingsManager;\n toolCallId?: string;\n cwd?: string;\n}\n\nfunction sanitize(text: string): string {\n return text.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/g, '');\n}\n\nfunction trimTrailingBlankDisplayLines(text: string): string {\n return text.replace(/(?:\\r?\\n[ \\t]*)+$/g, '');\n}\n\nexport function getToolResultDisplayText(\n content: TuiToolContentBlock[],\n options: { showImages: boolean; supportsInlineImages: boolean },\n): string {\n const parts: string[] = [];\n for (const block of content) {\n if (block.type === 'text') {\n if (block.text) parts.push(sanitize(block.text));\n continue;\n }\n if (block.type === 'image' && (!options.supportsInlineImages || !options.showImages)) {\n parts.push(block.mimeType ? `[image:${block.mimeType}]` : '[image]');\n continue;\n }\n if (block.type !== 'image') {\n parts.push(block.text ? sanitize(block.text) : `[${block.type}]`);\n }\n }\n return trimTrailingBlankDisplayLines(parts.filter(Boolean).join('\\n'));\n}\n\nfunction isTuiComponent(value: unknown): value is Component {\n return Boolean(\n value &&\n typeof value === 'object' &&\n typeof (value as { render?: unknown }).render === 'function',\n );\n}\n\nexport class ToolExecutionComponent extends Container {\n private contentContainer: Container;\n private contentText: Text;\n private collapsedOutputComponent: ReturnType<typeof createVisualTailComponent> | null = null;\n private collapsedReadSummaryComponent: ReturnType<typeof createCollapsedReadSummaryComponent> | null = null;\n private expandedOutputComponent: ReturnType<typeof createVisualMiddleComponent> | null = null;\n private toolName: string;\n private toolCallId: string;\n private args: unknown;\n private argsComplete = true;\n private resultText = '';\n private resultContent: TuiToolContentBlock[] | undefined;\n private resultDetails: unknown;\n private rendererState: Record<string, unknown> = {};\n private lastRendererOutput: string[] | Component | undefined;\n private lastCallRendererOutput: string[] | Component | undefined;\n private lastResultRendererOutput: string[] | Component | undefined;\n private customRendererComponent: Component | undefined;\n private structuredRendererComponents: Component[] = [];\n private contentTextAttached = true;\n private rendererInvalidationQueued = false;\n private imageComponents: Image[] = [];\n private imageSpacers: Spacer[] = [];\n private showImages: boolean;\n private imageWidthCells: number;\n private keybindings: KeybindingsManager | undefined;\n private cwd: string;\n private expanded = false;\n private isError = false;\n private isPartial = true;\n private executionStarted = false;\n private startedAt = Date.now();\n private completedAt: number | undefined;\n\n constructor(toolName: string, toolCallId: string, args: unknown, options: ToolExecutionOptions = {}) {\n super();\n this.toolName = toolName;\n this.toolCallId = toolCallId;\n this.args = args;\n this.showImages = options.showImages ?? true;\n this.imageWidthCells = Math.max(1, Math.floor(options.imageWidthCells ?? 60));\n this.keybindings = options.keybindings;\n this.cwd = options.cwd ?? process.cwd();\n\n this.addChild(new Spacer(1));\n\n const bgFn = (text: string) => theme.toolPendingBg(text);\n this.contentContainer = new Container();\n this.contentText = new Text('', 1, 1, bgFn);\n this.contentContainer.addChild(this.contentText);\n this.addChild(this.contentContainer);\n\n this.refresh();\n }\n\n setArgs(args: unknown): void {\n this.args = args;\n this.refresh();\n }\n\n markExecutionStarted(): void {\n this.executionStarted = true;\n this.startedAt = Date.now();\n this.refresh();\n }\n\n setArgsComplete(): void {\n this.argsComplete = true;\n this.refresh();\n }\n\n setExpanded(expanded: boolean): void {\n this.expanded = expanded;\n this.refresh();\n }\n\n updateResult(result: AgentToolResult<any> | unknown, isPartial = false, isError = false): void {\n const parsed = parseTuiToolResult(result);\n this.resultText = sanitize(parsed.text);\n this.resultContent = parsed.envelope?.content;\n this.resultDetails = parsed.envelope?.details;\n this.isError = isError;\n this.isPartial = isPartial;\n if (!isPartial) {\n this.completedAt = Date.now();\n }\n this.refresh();\n }\n\n setImageOptions(options: ToolExecutionOptions): void {\n if (options.showImages !== undefined) {\n this.showImages = options.showImages;\n }\n if (options.imageWidthCells !== undefined) {\n this.imageWidthCells = Math.max(1, Math.floor(options.imageWidthCells));\n }\n if (options.keybindings !== undefined) {\n this.keybindings = options.keybindings;\n }\n if (options.cwd !== undefined) {\n this.cwd = options.cwd;\n }\n this.refresh();\n }\n\n setPartialDetails(details: unknown): void {\n this.resultDetails = details;\n this.isPartial = true;\n this.refresh();\n }\n\n private refresh(): void {\n const bgFn = this.isPartial\n ? (text: string) => theme.toolPendingBg(text)\n : this.isError\n ? (text: string) => theme.toolErrorBg(text)\n : (text: string) => theme.toolSuccessBg(text);\n this.refreshCollapsedOutput(null);\n this.refreshCollapsedReadSummary(null);\n this.refreshExpandedOutput(null);\n if (this.customRendererComponent) {\n this.contentContainer.removeChild(this.customRendererComponent);\n this.customRendererComponent = undefined;\n }\n for (const component of this.structuredRendererComponents) {\n this.contentContainer.removeChild(component);\n }\n this.structuredRendererComponents = [];\n this.contentText.setCustomBgFn(bgFn);\n\n if (hasStructuredTuiToolRenderer(this.toolName)) {\n this.detachContentText();\n this.renderStructuredExtensionTool();\n } else {\n const custom = this.renderExtensionTool();\n if (Array.isArray(custom) && custom.length > 0) {\n this.ensureContentTextAttached();\n this.lastRendererOutput = custom;\n this.contentText.setText(custom.join('\\n'));\n } else if (isTuiComponent(custom)) {\n this.detachContentText();\n this.customRendererComponent = custom;\n this.lastRendererOutput = custom;\n this.contentContainer.addChild(custom);\n } else {\n this.ensureContentTextAttached();\n this.lastRendererOutput = undefined;\n this.contentText.setText(this.formatToolExecution());\n }\n }\n this.refreshImages();\n }\n\n private appendRendererResult(result: ReturnType<typeof renderToolWithExtensions>): boolean {\n if (Array.isArray(result) && result.length > 0) {\n const component = new Text(result.join('\\n'), 1, 1);\n this.structuredRendererComponents.push(component);\n this.contentContainer.addChild(component);\n return true;\n }\n if (isTuiComponent(result)) {\n this.structuredRendererComponents.push(result);\n this.contentContainer.addChild(result);\n return true;\n }\n return false;\n }\n\n private renderStructuredExtensionTool(): void {\n const call = this.renderExtensionToolCall();\n if (this.appendRendererResult(call)) {\n this.lastCallRendererOutput = call as string[] | Component;\n } else {\n this.lastCallRendererOutput = undefined;\n this.ensureContentTextAttached();\n this.contentText.setText(this.formatToolCallFallback());\n }\n\n if (!this.isPartial || this.resultDetails !== undefined || this.resultText || this.resultContent) {\n const result = this.renderExtensionToolResult();\n if (this.appendRendererResult(result)) {\n this.lastResultRendererOutput = result as string[] | Component;\n } else {\n this.appendRendererResult([this.formatToolResultFallback()].filter(Boolean));\n this.lastResultRendererOutput = undefined;\n }\n }\n }\n\n private ensureContentTextAttached(): void {\n if (this.contentTextAttached) return;\n this.contentContainer.addChild(this.contentText);\n this.contentTextAttached = true;\n }\n\n private detachContentText(): void {\n if (!this.contentTextAttached) return;\n this.contentContainer.removeChild(this.contentText);\n this.contentTextAttached = false;\n }\n\n private requestRendererInvalidate(): void {\n if (this.rendererInvalidationQueued) return;\n this.rendererInvalidationQueued = true;\n queueMicrotask(() => {\n this.rendererInvalidationQueued = false;\n this.refresh();\n this.invalidate();\n });\n }\n\n private renderExtensionTool(): ReturnType<typeof renderToolWithExtensions> {\n return renderToolWithExtensions(this.createRenderContext(this.lastRendererOutput));\n }\n\n private renderExtensionToolCall(): ReturnType<typeof renderToolWithExtensions> {\n return renderToolCallWithExtensions(\n this.createRenderContext(this.lastCallRendererOutput),\n theme,\n );\n }\n\n private renderExtensionToolResult(): ReturnType<typeof renderToolWithExtensions> {\n return renderToolResultWithExtensions(\n this.createRenderContext(this.lastResultRendererOutput),\n theme,\n );\n }\n\n private createRenderContext(lastComponent: string[] | Component | undefined) {\n return {\n toolName: this.toolName,\n toolCallId: this.toolCallId,\n args: this.args,\n resultText: this.getDisplayResultText(),\n content: this.resultContent,\n details: this.resultDetails,\n invalidate: () => this.requestRendererInvalidate(),\n lastComponent,\n state: this.rendererState,\n cwd: this.cwd,\n executionStarted: this.executionStarted,\n argsComplete: this.argsComplete,\n isError: this.isError,\n isPartial: this.isPartial,\n expanded: this.expanded,\n showImages: this.showImages,\n };\n }\n\n private formatToolCallFallback(): string {\n const argsStr = formatArgsSummary(this.args, this.toolName);\n const titleParts = [\n theme.dim(this.toolStatusLabel()),\n theme.toolTitle(theme.bold(displayToolName(this.toolName))),\n ];\n if (argsStr) {\n titleParts.push(theme.dim(`(${argsStr})`));\n }\n const duration = this.toolDurationLabel();\n if (duration) {\n titleParts.push(theme.dim(duration));\n }\n if (this.isPartial && !this.resultText && !this.resultContent && this.resultDetails === undefined) {\n titleParts.push(theme.dim('…'));\n }\n return titleParts.join(' ');\n }\n\n private formatToolResultFallback(): string {\n const output = this.getDisplayResultText();\n let text = '';\n if (output) {\n const expandKey = this.keybindings\n ? formatKeyIds(this.keybindings, 'app.tools.expand', { capitalize: true })\n : 'Ctrl+O';\n const lineCount = output.split('\\n').length;\n const useDiff =\n isDiffFriendlyTool(this.toolName) &&\n looksLikeUnifiedDiff(output);\n if (this.expanded && useDiff) {\n text += renderPatchSummary(output) ?? renderUnifiedDiff(output);\n } else if (this.expanded && isExecStyleTool(this.toolName)) {\n this.refreshExpandedOutput(theme.toolOutput(formatExecExpandedOutput(output, this.resultDetails)));\n } else if (this.expanded) {\n this.refreshExpandedOutput(theme.toolOutput(output));\n } else if (useDiff) {\n text += theme.dim('preview');\n } else if (getToolSummaryKind(this.toolName) !== 'generic') {\n text += this.collapsedSpecializedSummary(output, expandKey);\n } else {\n const suffix = lineCount > COLLAPSED_RESULT_VISUAL_LINES\n ? theme.dim(` (${lineCount} lines; ${expandKey} to expand)`)\n : '';\n text += theme.dim(`preview${suffix}`);\n }\n }\n if (this.shouldRenderDetailsPreview()) {\n const detailsText = formatDetailsPreview(this.resultDetails);\n if (detailsText) {\n text = [text, theme.dim(detailsText)].filter(Boolean).join('\\n');\n }\n }\n return text;\n }\n\n private formatToolExecution(): string {\n const argsStr = formatArgsSummary(this.args, this.toolName);\n const titleParts = [\n theme.dim(this.toolStatusLabel()),\n theme.toolTitle(theme.bold(displayToolName(this.toolName))),\n ];\n if (argsStr) {\n titleParts.push(theme.dim(`(${argsStr})`));\n }\n const duration = this.toolDurationLabel();\n if (duration) {\n titleParts.push(theme.dim(duration));\n }\n let text = titleParts.join(' ');\n\n // Output / result — collapsed: single-line summary; expanded: full output\n const output = this.getDisplayResultText();\n if (output) {\n const expandKey = this.keybindings\n ? formatKeyIds(this.keybindings, 'app.tools.expand', { capitalize: true })\n : 'Ctrl+O';\n const lineCount = output.split('\\n').length;\n const useDiff =\n isDiffFriendlyTool(this.toolName) &&\n looksLikeUnifiedDiff(output);\n if (this.expanded && useDiff) {\n text += `\\n${renderPatchSummary(output) ?? renderUnifiedDiff(output)}`;\n } else if (this.expanded && isExecStyleTool(this.toolName)) {\n this.refreshExpandedOutput(theme.toolOutput(formatExecExpandedOutput(output, this.resultDetails)));\n } else if (this.expanded) {\n this.refreshExpandedOutput(theme.toolOutput(output));\n } else if (useDiff) {\n const suffix = output.split('\\n').length > COLLAPSED_RESULT_VISUAL_LINES\n ? theme.dim(` (${output.split('\\n').length} lines; ${expandKey} to expand)`)\n : '';\n text += `\\n${theme.dim(`preview${suffix}`)}`;\n } else if (isReadStyleTool(this.toolName)) {\n this.refreshCollapsedReadSummary(output, expandKey);\n } else if (getToolSummaryKind(this.toolName) !== 'generic') {\n text += `\\n${this.collapsedSpecializedSummary(output, expandKey)}`;\n } else {\n const suffix = lineCount > COLLAPSED_RESULT_VISUAL_LINES\n ? theme.dim(` (${lineCount} lines; ${expandKey} to expand)`)\n : '';\n text += `\\n${theme.dim(`preview${suffix}`)}`;\n this.refreshCollapsedOutput(\n theme.toolOutput(output),\n lineCount > COLLAPSED_RESULT_VISUAL_LINES ? undefined : `${expandKey} to expand`,\n );\n }\n } else if (this.isPartial) {\n text += `\\n${theme.dim('…')}`;\n }\n\n if (this.shouldRenderDetailsPreview()) {\n const detailsText = formatDetailsPreview(this.resultDetails);\n if (detailsText) {\n text += `\\n${theme.dim(detailsText)}`;\n }\n }\n\n return text;\n }\n\n private toolStatusLabel(): string {\n if (this.isError) return 'Failed';\n if (this.isPartial && !this.resultText && !this.resultContent && this.resultDetails === undefined) {\n return this.executionStarted ? 'Calling' : 'Queued';\n }\n if (this.isPartial) return 'Calling';\n return 'Called';\n }\n\n private toolDurationLabel(): string {\n if (this.completedAt === undefined) return '';\n const durationMs = Math.max(0, this.completedAt - this.startedAt);\n if (durationMs < 100) return '';\n return `${durationMs}ms`;\n }\n\n private collapsedSpecializedSummary(output: string, expandKey: string): string {\n return theme.dim(formatCollapsedToolSummary({\n toolName: this.toolName,\n args: this.args,\n output,\n content: this.resultContent,\n details: this.resultDetails,\n isError: this.isError,\n expandKey,\n }));\n }\n\n private shouldRenderDetailsPreview(): boolean {\n return this.expanded && this.resultDetails !== undefined && !isExecStyleTool(this.toolName);\n }\n\n private getDisplayResultText(): string {\n if (!this.resultContent) {\n return trimTrailingBlankDisplayLines(this.resultText);\n }\n return getToolResultDisplayText(this.resultContent, {\n showImages: this.showImages,\n supportsInlineImages: Boolean(getCapabilities().images),\n });\n }\n\n private refreshImages(): void {\n for (const image of this.imageComponents) {\n this.removeChild(image);\n }\n this.imageComponents = [];\n for (const spacer of this.imageSpacers) {\n this.removeChild(spacer);\n }\n this.imageSpacers = [];\n\n const imageBlocks = this.resultContent?.filter(\n (block) => block.type === 'image' && block.data && block.mimeType,\n ) ?? [];\n if (imageBlocks.length === 0) return;\n\n const capabilities = getCapabilities();\n if (!capabilities.images || !this.showImages) return;\n\n for (const block of imageBlocks) {\n const spacer = new Spacer(1);\n const image = new Image(\n block.data!,\n block.mimeType!,\n { fallbackColor: (text: string) => theme.toolOutput(text) },\n { maxWidthCells: this.imageWidthCells },\n );\n this.imageSpacers.push(spacer);\n this.imageComponents.push(image);\n this.addChild(spacer);\n this.addChild(image);\n }\n }\n\n private refreshCollapsedOutput(text: string | null, truncationHint?: string): void {\n if (this.collapsedOutputComponent) {\n this.contentContainer.removeChild(this.collapsedOutputComponent);\n this.collapsedOutputComponent = null;\n }\n if (!text) return;\n this.collapsedOutputComponent = createVisualTailComponent(\n text,\n COLLAPSED_RESULT_VISUAL_LINES,\n 1,\n truncationHint,\n );\n this.contentContainer.addChild(this.collapsedOutputComponent);\n }\n\n private refreshCollapsedReadSummary(text: string | null, expandKey?: string): void {\n if (this.collapsedReadSummaryComponent) {\n this.contentContainer.removeChild(this.collapsedReadSummaryComponent);\n this.collapsedReadSummaryComponent = null;\n }\n if (!text || !expandKey) return;\n this.collapsedReadSummaryComponent = createCollapsedReadSummaryComponent(text, expandKey, 1);\n this.contentContainer.addChild(this.collapsedReadSummaryComponent);\n }\n\n private refreshExpandedOutput(text: string | null): void {\n if (this.expandedOutputComponent) {\n this.contentContainer.removeChild(this.expandedOutputComponent);\n this.expandedOutputComponent = null;\n }\n if (!text) return;\n this.expandedOutputComponent = createVisualMiddleComponent(\n text,\n EXPANDED_RESULT_VISUAL_LINES,\n 1,\n );\n this.contentContainer.addChild(this.expandedOutputComponent);\n }\n}\n\nfunction formatDetailsPreview(details: unknown): string {\n if (details === null) return '';\n if (typeof details === 'string') return details;\n try {\n return JSON.stringify(details, null, 2);\n } catch {\n return String(details);\n }\n}\n\nfunction createVisualTailComponent(\n text: string,\n maxVisualLines: number,\n paddingX: number,\n truncationHint?: string,\n) {\n let cachedWidth: number | undefined;\n let cachedLines: string[] | undefined;\n return {\n render(width: number): string[] {\n if (cachedWidth !== width || cachedLines === undefined) {\n const result = truncateToVisualLines(text, maxVisualLines, width, paddingX);\n cachedWidth = width;\n cachedLines =\n result.skippedCount > 0 && truncationHint\n ? [theme.dim(` (${result.skippedCount} rows hidden; ${truncationHint})`), ...result.visualLines]\n : result.visualLines;\n }\n return cachedLines;\n },\n invalidate(): void {\n cachedWidth = undefined;\n cachedLines = undefined;\n },\n };\n}\n\nfunction createVisualMiddleComponent(\n text: string,\n maxVisualLines: number,\n paddingX: number,\n) {\n let cachedWidth: number | undefined;\n let cachedLines: string[] | undefined;\n return {\n render(width: number): string[] {\n if (cachedWidth !== width || cachedLines === undefined) {\n const result = truncateToVisualLinesMiddle(text, maxVisualLines, width, paddingX);\n cachedWidth = width;\n cachedLines = result.visualLines;\n }\n return cachedLines;\n },\n invalidate(): void {\n cachedWidth = undefined;\n cachedLines = undefined;\n },\n };\n}\n\nfunction createCollapsedReadSummaryComponent(text: string, expandKey: string, paddingX: number) {\n let cachedWidth: number | undefined;\n let cachedLine: string | undefined;\n return {\n render(width: number): string[] {\n if (cachedWidth !== width || cachedLine === undefined) {\n const rows = new Text(text, paddingX, 0).render(width).length;\n const plural = rows === 1 ? 'row' : 'rows';\n cachedWidth = width;\n cachedLine = theme.dim(` ${rows} ${plural}; ${expandKey} to expand`);\n }\n return [cachedLine];\n },\n invalidate(): void {\n cachedWidth = undefined;\n cachedLine = undefined;\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { theme } from "../theme.js";
|
|
2
2
|
import { formatContextUsageLabel } from "../tui-context-usage.js";
|
|
3
3
|
import { getGitBranchCached } from "../tui-git-branch.js";
|
|
4
|
+
import { formatActiveRunStatus } from "../tui-run-status-format.js";
|
|
4
5
|
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
5
6
|
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
6
7
|
//#region src/tui/components/tui-bottom-bar.ts
|
|
@@ -8,7 +9,11 @@ const BUSY_ACTIVITY = new Set([
|
|
|
8
9
|
"sending",
|
|
9
10
|
"waiting",
|
|
10
11
|
"streaming",
|
|
11
|
-
"running"
|
|
12
|
+
"running",
|
|
13
|
+
"compacting",
|
|
14
|
+
"stalled",
|
|
15
|
+
"recovering",
|
|
16
|
+
"aborting"
|
|
12
17
|
]);
|
|
13
18
|
/** Compact token counts (aligned with pi coding-agent footer). */
|
|
14
19
|
function formatTokens(count) {
|
|
@@ -86,15 +91,14 @@ var TuiBottomBar = class {
|
|
|
86
91
|
const pwdLine = truncateToWidth(theme.dim(`${cwdWithBranch} · ${sessionLine}`), width, theme.dim("…"));
|
|
87
92
|
const busy = BUSY_ACTIVITY.has(state.activityStatus);
|
|
88
93
|
const leftParts = [state.connectionStatus];
|
|
89
|
-
|
|
94
|
+
const activeRunStatus = formatActiveRunStatus(state);
|
|
95
|
+
if (activeRunStatus) leftParts.push(activeRunStatus);
|
|
96
|
+
else if (!busy && state.activityStatus && state.activityStatus !== "idle") leftParts.push(state.activityStatus);
|
|
90
97
|
if (state.sessionInfo.totalTokens != null) leftParts.push(formatTokens(state.sessionInfo.totalTokens));
|
|
91
98
|
const ctxLabel = formatContextUsageLabel(state.sessionInfo.contextUsagePercent ?? null, state.sessionInfo.contextWindow ?? null);
|
|
92
99
|
if (ctxLabel) leftParts.push(ctxLabel);
|
|
93
100
|
if (state.isCompacting) leftParts.push("compact…");
|
|
94
101
|
else if (state.compactionQueue.length > 0) leftParts.push(`C${state.compactionQueue.length}`);
|
|
95
|
-
if (state.runStatus?.phase === "stalled") leftParts.push("run:stalled");
|
|
96
|
-
else if (state.runStatus?.phase === "recovering") leftParts.push("run:recovering");
|
|
97
|
-
else if (state.runStatus?.source === "agent-resume" && state.activeRunId) leftParts.push("run:resumed");
|
|
98
102
|
if (state.messageFollowUpQueue.length > 0) leftParts.push(`Q${state.messageFollowUpQueue.length}`);
|
|
99
103
|
if (state.steeringQueue.length > 0) leftParts.push(`S${state.steeringQueue.length}`);
|
|
100
104
|
let statsLeft = leftParts.join(" · ");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui-bottom-bar.js","names":[],"sources":["../../../../src/tui/components/tui-bottom-bar.ts"],"sourcesContent":["import { isAbsolute, relative, resolve, sep } from 'node:path';\n\nimport type { Component } from '@earendil-works/pi-tui';\nimport { truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\n\nimport { theme } from '../theme.js';\nimport { formatContextUsageLabel } from '../tui-context-usage.js';\nimport { getGitBranchCached } from '../tui-git-branch.js';\nimport type { TuiState } from '../tui-types.js';\n\nconst BUSY_ACTIVITY = new Set(['sending', 'waiting', 'streaming', 'running']);\n\n/** Compact token counts (aligned with pi coding-agent footer). */\nexport function formatTokens(count: number): string {\n if (count < 1000) return count.toString();\n if (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n if (count < 1_000_000) return `${Math.round(count / 1000)}k`;\n if (count < 10_000_000) return `${(count / 1_000_000).toFixed(1)}M`;\n return `${Math.round(count / 1_000_000)}M`;\n}\n\nexport function sanitizeStatusText(text: string): string {\n return text\n .replace(/[\\r\\n\\t]/g, ' ')\n .replace(/ +/g, ' ')\n .trim();\n}\n\nexport function formatQueuedMessageLines(\n state: TuiState,\n width: number,\n dequeueHint: string,\n): string[] {\n const lines: string[] = [];\n const add = (label: string, text: string) => {\n const sanitized = sanitizeStatusText(text);\n if (!sanitized) return;\n lines.push(\n truncateToWidth(theme.dim(`${label}: ${sanitized}`), width, theme.dim('…')),\n );\n };\n\n for (const message of state.steeringQueue) {\n add('Steering', message);\n }\n for (const message of state.messageFollowUpQueue) {\n add('Follow-up', message);\n }\n for (const message of state.compactionQueue) {\n add('Queued', message);\n }\n if (lines.length > 0) {\n lines.push(\n truncateToWidth(theme.dim(`↳ ${dequeueHint} to edit all queued messages`), width, theme.dim('…')),\n );\n }\n return lines;\n}\n\nexport function formatCwdForFooter(cwd: string, home: string | undefined): string {\n if (!home) return cwd;\n\n const resolvedCwd = resolve(cwd);\n const resolvedHome = resolve(home);\n const relativeToHome = relative(resolvedHome, resolvedCwd);\n const isInsideHome =\n relativeToHome === '' ||\n (relativeToHome !== '..' &&\n !relativeToHome.startsWith(`..${sep}`) &&\n !isAbsolute(relativeToHome));\n\n if (!isInsideHome) return cwd;\n return relativeToHome === '' ? '~' : `~${sep}${relativeToHome}`;\n}\n\nfunction shortenPath(cwd: string): string {\n const formatted = formatCwdForFooter(cwd, process.env.HOME || process.env.USERPROFILE);\n if (formatted !== cwd) return formatted;\n return cwd;\n}\n\n/**\n * Multi-line footer below the input editor (pi coding-agent style):\n * cwd · session, then a single padded row: status/tokens on the left, model on the right.\n */\nexport class TuiBottomBar implements Component {\n private extensionLines: string[] = [];\n private extensionComponents: Component[] = [];\n private extensionStatusParts: string[] = [];\n private customComponent: Component | undefined;\n\n constructor(\n private readonly getState: () => TuiState,\n private readonly getThinkingDefault: () => string | undefined,\n private readonly getDequeueHint: () => string = () => 'Alt+Up',\n ) {}\n\n setExtensionLines(lines: string[]): void {\n this.extensionLines = lines;\n }\n\n setExtensionComponents(components: Component[]): void {\n this.extensionComponents = components;\n }\n\n setExtensionStatusParts(parts: string[]): void {\n this.extensionStatusParts = parts;\n }\n\n setCustomComponent(component: Component | undefined): void {\n this.customComponent = component;\n }\n\n invalidate(): void {}\n\n render(width: number): string[] {\n if (this.customComponent) {\n const rendered = this.customComponent.render(width);\n return rendered.map((line) => truncateToWidth(line, width, theme.dim('…')));\n }\n\n const state = this.getState();\n const cwdRaw = state.sessionInfo.effectiveWorkspacePath;\n const cwdWithBranch = cwdRaw\n ? (() => {\n const cwd = shortenPath(cwdRaw);\n const branch = getGitBranchCached(cwdRaw);\n return branch ? `${cwd} (${branch})` : cwd;\n })()\n : 'workspace loading';\n const sessionLine = state.sessionInfo.displayName ?? `session ${state.currentSessionKey}`;\n const pwdLine = truncateToWidth(\n theme.dim(`${cwdWithBranch} · ${sessionLine}`),\n width,\n theme.dim('…'),\n );\n\n const busy = BUSY_ACTIVITY.has(state.activityStatus);\n const leftParts: string[] = [state.connectionStatus];\n if (!busy && state.activityStatus && state.activityStatus !== 'idle') {\n leftParts.push(state.activityStatus);\n }\n if (state.sessionInfo.totalTokens != null) {\n leftParts.push(formatTokens(state.sessionInfo.totalTokens));\n }\n const ctxLabel = formatContextUsageLabel(\n state.sessionInfo.contextUsagePercent ?? null,\n state.sessionInfo.contextWindow ?? null,\n );\n if (ctxLabel) {\n leftParts.push(ctxLabel);\n }\n if (state.isCompacting) {\n leftParts.push('compact…');\n } else if (state.compactionQueue.length > 0) {\n leftParts.push(`C${state.compactionQueue.length}`);\n }\n if (state.runStatus?.phase === 'stalled') {\n leftParts.push('run:stalled');\n } else if (state.runStatus?.phase === 'recovering') {\n leftParts.push('run:recovering');\n } else if (state.runStatus?.source === 'agent-resume' && state.activeRunId) {\n leftParts.push('run:resumed');\n }\n if (state.messageFollowUpQueue.length > 0) {\n leftParts.push(`Q${state.messageFollowUpQueue.length}`);\n }\n if (state.steeringQueue.length > 0) {\n leftParts.push(`S${state.steeringQueue.length}`);\n }\n let statsLeft = leftParts.join(' · ');\n\n const modelId = state.sessionInfo.model ?? 'unknown';\n const prov = state.sessionInfo.modelProvider;\n const thinkingHint = state.showThinking\n ? `thinking:${this.getThinkingDefault() ?? 'on'}`\n : 'thinking:off';\n let rightSide = prov ? `(${prov}) ${modelId}` : modelId;\n rightSide = `${rightSide} • ${thinkingHint}`;\n\n const minPadding = 2;\n let statsLeftWidth = visibleWidth(statsLeft);\n if (statsLeftWidth > width) {\n statsLeft = truncateToWidth(statsLeft, width, '…');\n statsLeftWidth = visibleWidth(statsLeft);\n }\n\n const rightWidth = visibleWidth(rightSide);\n const totalNeeded = statsLeftWidth + minPadding + rightWidth;\n\n let statsLine: string;\n if (totalNeeded <= width) {\n const padding = ' '.repeat(width - statsLeftWidth - rightWidth);\n statsLine = statsLeft + padding + rightSide;\n } else {\n const availableForRight = width - statsLeftWidth - minPadding;\n if (availableForRight > 0) {\n const truncatedRight = truncateToWidth(rightSide, availableForRight, '');\n const tw = visibleWidth(truncatedRight);\n const padding = ' '.repeat(Math.max(0, width - statsLeftWidth - tw));\n statsLine = statsLeft + padding + truncatedRight;\n } else {\n statsLine = statsLeft;\n }\n }\n\n const statsDimmed = theme.dim(statsLine);\n const lines = [pwdLine, statsDimmed];\n if (this.extensionStatusParts.length > 0) {\n const statusLine = this.extensionStatusParts\n .map((part) => sanitizeStatusText(part))\n .filter(Boolean)\n .join(' ');\n if (statusLine) {\n lines.push(truncateToWidth(theme.dim(statusLine), width, theme.dim('…')));\n }\n }\n lines.push(...formatQueuedMessageLines(state, width, this.getDequeueHint()));\n for (const extLine of this.extensionLines) {\n lines.push(truncateToWidth(theme.dim(sanitizeStatusText(extLine)), width, theme.dim('…')));\n }\n for (const component of this.extensionComponents) {\n for (const line of component.render(width)) {\n lines.push(truncateToWidth(line, width, theme.dim('…')));\n }\n }\n return lines;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tui-bottom-bar.js","names":[],"sources":["../../../../src/tui/components/tui-bottom-bar.ts"],"sourcesContent":["import { isAbsolute, relative, resolve, sep } from 'node:path';\n\nimport type { Component } from '@earendil-works/pi-tui';\nimport { truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\n\nimport { theme } from '../theme.js';\nimport { formatContextUsageLabel } from '../tui-context-usage.js';\nimport { getGitBranchCached } from '../tui-git-branch.js';\nimport { formatActiveRunStatus } from '../tui-run-status-format.js';\nimport type { TuiState } from '../tui-types.js';\n\nconst BUSY_ACTIVITY = new Set([\n 'sending',\n 'waiting',\n 'streaming',\n 'running',\n 'compacting',\n 'stalled',\n 'recovering',\n 'aborting',\n]);\n\n/** Compact token counts (aligned with pi coding-agent footer). */\nexport function formatTokens(count: number): string {\n if (count < 1000) return count.toString();\n if (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n if (count < 1_000_000) return `${Math.round(count / 1000)}k`;\n if (count < 10_000_000) return `${(count / 1_000_000).toFixed(1)}M`;\n return `${Math.round(count / 1_000_000)}M`;\n}\n\nexport function sanitizeStatusText(text: string): string {\n return text\n .replace(/[\\r\\n\\t]/g, ' ')\n .replace(/ +/g, ' ')\n .trim();\n}\n\nexport function formatQueuedMessageLines(\n state: TuiState,\n width: number,\n dequeueHint: string,\n): string[] {\n const lines: string[] = [];\n const add = (label: string, text: string) => {\n const sanitized = sanitizeStatusText(text);\n if (!sanitized) return;\n lines.push(\n truncateToWidth(theme.dim(`${label}: ${sanitized}`), width, theme.dim('…')),\n );\n };\n\n for (const message of state.steeringQueue) {\n add('Steering', message);\n }\n for (const message of state.messageFollowUpQueue) {\n add('Follow-up', message);\n }\n for (const message of state.compactionQueue) {\n add('Queued', message);\n }\n if (lines.length > 0) {\n lines.push(\n truncateToWidth(theme.dim(`↳ ${dequeueHint} to edit all queued messages`), width, theme.dim('…')),\n );\n }\n return lines;\n}\n\nexport function formatCwdForFooter(cwd: string, home: string | undefined): string {\n if (!home) return cwd;\n\n const resolvedCwd = resolve(cwd);\n const resolvedHome = resolve(home);\n const relativeToHome = relative(resolvedHome, resolvedCwd);\n const isInsideHome =\n relativeToHome === '' ||\n (relativeToHome !== '..' &&\n !relativeToHome.startsWith(`..${sep}`) &&\n !isAbsolute(relativeToHome));\n\n if (!isInsideHome) return cwd;\n return relativeToHome === '' ? '~' : `~${sep}${relativeToHome}`;\n}\n\nfunction shortenPath(cwd: string): string {\n const formatted = formatCwdForFooter(cwd, process.env.HOME || process.env.USERPROFILE);\n if (formatted !== cwd) return formatted;\n return cwd;\n}\n\n/**\n * Multi-line footer below the input editor (pi coding-agent style):\n * cwd · session, then a single padded row: status/tokens on the left, model on the right.\n */\nexport class TuiBottomBar implements Component {\n private extensionLines: string[] = [];\n private extensionComponents: Component[] = [];\n private extensionStatusParts: string[] = [];\n private customComponent: Component | undefined;\n\n constructor(\n private readonly getState: () => TuiState,\n private readonly getThinkingDefault: () => string | undefined,\n private readonly getDequeueHint: () => string = () => 'Alt+Up',\n ) {}\n\n setExtensionLines(lines: string[]): void {\n this.extensionLines = lines;\n }\n\n setExtensionComponents(components: Component[]): void {\n this.extensionComponents = components;\n }\n\n setExtensionStatusParts(parts: string[]): void {\n this.extensionStatusParts = parts;\n }\n\n setCustomComponent(component: Component | undefined): void {\n this.customComponent = component;\n }\n\n invalidate(): void {}\n\n render(width: number): string[] {\n if (this.customComponent) {\n const rendered = this.customComponent.render(width);\n return rendered.map((line) => truncateToWidth(line, width, theme.dim('…')));\n }\n\n const state = this.getState();\n const cwdRaw = state.sessionInfo.effectiveWorkspacePath;\n const cwdWithBranch = cwdRaw\n ? (() => {\n const cwd = shortenPath(cwdRaw);\n const branch = getGitBranchCached(cwdRaw);\n return branch ? `${cwd} (${branch})` : cwd;\n })()\n : 'workspace loading';\n const sessionLine = state.sessionInfo.displayName ?? `session ${state.currentSessionKey}`;\n const pwdLine = truncateToWidth(\n theme.dim(`${cwdWithBranch} · ${sessionLine}`),\n width,\n theme.dim('…'),\n );\n\n const busy = BUSY_ACTIVITY.has(state.activityStatus);\n const leftParts: string[] = [state.connectionStatus];\n const activeRunStatus = formatActiveRunStatus(state);\n if (activeRunStatus) {\n leftParts.push(activeRunStatus);\n } else if (!busy && state.activityStatus && state.activityStatus !== 'idle') {\n leftParts.push(state.activityStatus);\n }\n if (state.sessionInfo.totalTokens != null) {\n leftParts.push(formatTokens(state.sessionInfo.totalTokens));\n }\n const ctxLabel = formatContextUsageLabel(\n state.sessionInfo.contextUsagePercent ?? null,\n state.sessionInfo.contextWindow ?? null,\n );\n if (ctxLabel) {\n leftParts.push(ctxLabel);\n }\n if (state.isCompacting) {\n leftParts.push('compact…');\n } else if (state.compactionQueue.length > 0) {\n leftParts.push(`C${state.compactionQueue.length}`);\n }\n if (state.messageFollowUpQueue.length > 0) {\n leftParts.push(`Q${state.messageFollowUpQueue.length}`);\n }\n if (state.steeringQueue.length > 0) {\n leftParts.push(`S${state.steeringQueue.length}`);\n }\n let statsLeft = leftParts.join(' · ');\n\n const modelId = state.sessionInfo.model ?? 'unknown';\n const prov = state.sessionInfo.modelProvider;\n const thinkingHint = state.showThinking\n ? `thinking:${this.getThinkingDefault() ?? 'on'}`\n : 'thinking:off';\n let rightSide = prov ? `(${prov}) ${modelId}` : modelId;\n rightSide = `${rightSide} • ${thinkingHint}`;\n\n const minPadding = 2;\n let statsLeftWidth = visibleWidth(statsLeft);\n if (statsLeftWidth > width) {\n statsLeft = truncateToWidth(statsLeft, width, '…');\n statsLeftWidth = visibleWidth(statsLeft);\n }\n\n const rightWidth = visibleWidth(rightSide);\n const totalNeeded = statsLeftWidth + minPadding + rightWidth;\n\n let statsLine: string;\n if (totalNeeded <= width) {\n const padding = ' '.repeat(width - statsLeftWidth - rightWidth);\n statsLine = statsLeft + padding + rightSide;\n } else {\n const availableForRight = width - statsLeftWidth - minPadding;\n if (availableForRight > 0) {\n const truncatedRight = truncateToWidth(rightSide, availableForRight, '');\n const tw = visibleWidth(truncatedRight);\n const padding = ' '.repeat(Math.max(0, width - statsLeftWidth - tw));\n statsLine = statsLeft + padding + truncatedRight;\n } else {\n statsLine = statsLeft;\n }\n }\n\n const statsDimmed = theme.dim(statsLine);\n const lines = [pwdLine, statsDimmed];\n if (this.extensionStatusParts.length > 0) {\n const statusLine = this.extensionStatusParts\n .map((part) => sanitizeStatusText(part))\n .filter(Boolean)\n .join(' ');\n if (statusLine) {\n lines.push(truncateToWidth(theme.dim(statusLine), width, theme.dim('…')));\n }\n }\n lines.push(...formatQueuedMessageLines(state, width, this.getDequeueHint()));\n for (const extLine of this.extensionLines) {\n lines.push(truncateToWidth(theme.dim(sanitizeStatusText(extLine)), width, theme.dim('…')));\n }\n for (const component of this.extensionComponents) {\n for (const line of component.render(width)) {\n lines.push(truncateToWidth(line, width, theme.dim('…')));\n }\n }\n return lines;\n }\n}\n"],"mappings":"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"}
|
|
@@ -9,3 +9,4 @@ export interface VisualTruncateResult {
|
|
|
9
9
|
* across many terminal rows.
|
|
10
10
|
*/
|
|
11
11
|
export declare function truncateToVisualLines(text: string, maxVisualLines: number, width: number, paddingX?: number): VisualTruncateResult;
|
|
12
|
+
export declare function truncateToVisualLinesMiddle(text: string, maxVisualLines: number, width: number, paddingX?: number): VisualTruncateResult;
|
|
@@ -21,7 +21,34 @@ function truncateToVisualLines(text, maxVisualLines, width, paddingX = 0) {
|
|
|
21
21
|
skippedCount: rendered.length - maxVisualLines
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
+
function truncateToVisualLinesMiddle(text, maxVisualLines, width, paddingX = 0) {
|
|
25
|
+
if (!text || maxVisualLines <= 0) return {
|
|
26
|
+
visualLines: [],
|
|
27
|
+
skippedCount: 0
|
|
28
|
+
};
|
|
29
|
+
const rendered = new Text(text, paddingX, 0).render(width);
|
|
30
|
+
if (rendered.length <= maxVisualLines) return {
|
|
31
|
+
visualLines: rendered,
|
|
32
|
+
skippedCount: 0
|
|
33
|
+
};
|
|
34
|
+
if (maxVisualLines === 1) return {
|
|
35
|
+
visualLines: ["..."],
|
|
36
|
+
skippedCount: rendered.length - 1
|
|
37
|
+
};
|
|
38
|
+
const visibleWithoutMarker = maxVisualLines - 1;
|
|
39
|
+
const headCount = Math.ceil(visibleWithoutMarker / 2);
|
|
40
|
+
const tailCount = Math.floor(visibleWithoutMarker / 2);
|
|
41
|
+
const skippedCount = rendered.length - headCount - tailCount;
|
|
42
|
+
return {
|
|
43
|
+
visualLines: [
|
|
44
|
+
...rendered.slice(0, headCount),
|
|
45
|
+
`... ${skippedCount} rows hidden ...`,
|
|
46
|
+
...rendered.slice(rendered.length - tailCount)
|
|
47
|
+
],
|
|
48
|
+
skippedCount
|
|
49
|
+
};
|
|
50
|
+
}
|
|
24
51
|
//#endregion
|
|
25
|
-
export { truncateToVisualLines };
|
|
52
|
+
export { truncateToVisualLines, truncateToVisualLinesMiddle };
|
|
26
53
|
|
|
27
54
|
//# sourceMappingURL=visual-truncate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visual-truncate.js","names":[],"sources":["../../../../src/tui/components/visual-truncate.ts"],"sourcesContent":["import { Text } from '@earendil-works/pi-tui';\n\nexport interface VisualTruncateResult {\n visualLines: string[];\n skippedCount: number;\n}\n\n/**\n * Truncate text by rendered terminal rows, not source lines.\n *\n * This keeps collapsed previews bounded when one very long logical line wraps\n * across many terminal rows.\n */\nexport function truncateToVisualLines(\n text: string,\n maxVisualLines: number,\n width: number,\n paddingX = 0,\n): VisualTruncateResult {\n if (!text || maxVisualLines <= 0) {\n return { visualLines: [], skippedCount: 0 };\n }\n\n const rendered = new Text(text, paddingX, 0).render(width);\n if (rendered.length <= maxVisualLines) {\n return { visualLines: rendered, skippedCount: 0 };\n }\n\n return {\n visualLines: rendered.slice(-maxVisualLines),\n skippedCount: rendered.length - maxVisualLines,\n };\n}\n"],"mappings":";;;;;;;;AAaA,SAAgB,sBACd,MACA,gBACA,OACA,WAAW,GACW;AACtB,KAAI,CAAC,QAAQ,kBAAkB,EAC7B,QAAO;EAAE,aAAa,EAAE;EAAE,cAAc;EAAG;CAG7C,MAAM,WAAW,IAAI,KAAK,MAAM,UAAU,EAAE,CAAC,OAAO,MAAM;AAC1D,KAAI,SAAS,UAAU,eACrB,QAAO;EAAE,aAAa;EAAU,cAAc;EAAG;AAGnD,QAAO;EACL,aAAa,SAAS,MAAM,CAAC,eAAe;EAC5C,cAAc,SAAS,SAAS;EACjC"}
|
|
1
|
+
{"version":3,"file":"visual-truncate.js","names":[],"sources":["../../../../src/tui/components/visual-truncate.ts"],"sourcesContent":["import { Text } from '@earendil-works/pi-tui';\n\nexport interface VisualTruncateResult {\n visualLines: string[];\n skippedCount: number;\n}\n\n/**\n * Truncate text by rendered terminal rows, not source lines.\n *\n * This keeps collapsed previews bounded when one very long logical line wraps\n * across many terminal rows.\n */\nexport function truncateToVisualLines(\n text: string,\n maxVisualLines: number,\n width: number,\n paddingX = 0,\n): VisualTruncateResult {\n if (!text || maxVisualLines <= 0) {\n return { visualLines: [], skippedCount: 0 };\n }\n\n const rendered = new Text(text, paddingX, 0).render(width);\n if (rendered.length <= maxVisualLines) {\n return { visualLines: rendered, skippedCount: 0 };\n }\n\n return {\n visualLines: rendered.slice(-maxVisualLines),\n skippedCount: rendered.length - maxVisualLines,\n };\n}\n\nexport function truncateToVisualLinesMiddle(\n text: string,\n maxVisualLines: number,\n width: number,\n paddingX = 0,\n): VisualTruncateResult {\n if (!text || maxVisualLines <= 0) {\n return { visualLines: [], skippedCount: 0 };\n }\n\n const rendered = new Text(text, paddingX, 0).render(width);\n if (rendered.length <= maxVisualLines) {\n return { visualLines: rendered, skippedCount: 0 };\n }\n\n if (maxVisualLines === 1) {\n return {\n visualLines: ['...'],\n skippedCount: rendered.length - 1,\n };\n }\n\n const visibleWithoutMarker = maxVisualLines - 1;\n const headCount = Math.ceil(visibleWithoutMarker / 2);\n const tailCount = Math.floor(visibleWithoutMarker / 2);\n const skippedCount = rendered.length - headCount - tailCount;\n return {\n visualLines: [\n ...rendered.slice(0, headCount),\n `... ${skippedCount} rows hidden ...`,\n ...rendered.slice(rendered.length - tailCount),\n ],\n skippedCount,\n };\n}\n"],"mappings":";;;;;;;;AAaA,SAAgB,sBACd,MACA,gBACA,OACA,WAAW,GACW;AACtB,KAAI,CAAC,QAAQ,kBAAkB,EAC7B,QAAO;EAAE,aAAa,EAAE;EAAE,cAAc;EAAG;CAG7C,MAAM,WAAW,IAAI,KAAK,MAAM,UAAU,EAAE,CAAC,OAAO,MAAM;AAC1D,KAAI,SAAS,UAAU,eACrB,QAAO;EAAE,aAAa;EAAU,cAAc;EAAG;AAGnD,QAAO;EACL,aAAa,SAAS,MAAM,CAAC,eAAe;EAC5C,cAAc,SAAS,SAAS;EACjC;;AAGH,SAAgB,4BACd,MACA,gBACA,OACA,WAAW,GACW;AACtB,KAAI,CAAC,QAAQ,kBAAkB,EAC7B,QAAO;EAAE,aAAa,EAAE;EAAE,cAAc;EAAG;CAG7C,MAAM,WAAW,IAAI,KAAK,MAAM,UAAU,EAAE,CAAC,OAAO,MAAM;AAC1D,KAAI,SAAS,UAAU,eACrB,QAAO;EAAE,aAAa;EAAU,cAAc;EAAG;AAGnD,KAAI,mBAAmB,EACrB,QAAO;EACL,aAAa,CAAC,MAAM;EACpB,cAAc,SAAS,SAAS;EACjC;CAGH,MAAM,uBAAuB,iBAAiB;CAC9C,MAAM,YAAY,KAAK,KAAK,uBAAuB,EAAE;CACrD,MAAM,YAAY,KAAK,MAAM,uBAAuB,EAAE;CACtD,MAAM,eAAe,SAAS,SAAS,YAAY;AACnD,QAAO;EACL,aAAa;GACX,GAAG,SAAS,MAAM,GAAG,UAAU;GAC/B,OAAO,aAAa;GACpB,GAAG,SAAS,MAAM,SAAS,SAAS,UAAU;GAC/C;EACD;EACD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { TuiToolContentBlock } from './tui-tool-result.js';
|
|
2
|
+
export type ToolSummaryKind = 'read' | 'search' | 'exec' | 'mcp' | 'generic';
|
|
3
|
+
export interface ToolSummaryContext {
|
|
4
|
+
toolName: string;
|
|
5
|
+
args: unknown;
|
|
6
|
+
output: string;
|
|
7
|
+
content?: TuiToolContentBlock[];
|
|
8
|
+
details: unknown;
|
|
9
|
+
isError: boolean;
|
|
10
|
+
expandKey: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function formatArgsSummary(args: unknown, toolName: string): string;
|
|
13
|
+
export declare function getToolSummaryKind(toolName: string): ToolSummaryKind;
|
|
14
|
+
export declare function isReadStyleTool(toolName: string): boolean;
|
|
15
|
+
export declare function isSearchStyleTool(toolName: string): boolean;
|
|
16
|
+
export declare function isExecStyleTool(toolName: string): boolean;
|
|
17
|
+
export declare function isMcpStyleTool(toolName: string): boolean;
|
|
18
|
+
export declare function displayToolName(toolName: string): string;
|
|
19
|
+
export declare function compactPath(path: string, maxLength?: number): string;
|
|
20
|
+
export declare function formatCollapsedToolSummary(ctx: ToolSummaryContext): string;
|
|
21
|
+
export declare function formatExecExpandedOutput(output: string, details: unknown): string;
|
|
22
|
+
export declare function extractExitCode(details: unknown): number | undefined;
|