@xopcai/xopc 0.0.125 → 0.0.127
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/{agent-avatar-dicebear-BKDKICZV.js → agent-avatar-dicebear-CgGgO4OV.js} +1 -1
- package/dist/gateway/static/root/assets/agents-k59l7NMb.js +2 -0
- package/dist/gateway/static/root/assets/{app-management-settings-panel-DI4BqHKW.js → app-management-settings-panel-DeQsTsyy.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-6_ie3NQ4.js → appearance-settings-BnHQW7Hv.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-BG9b4abG.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-kUHEJ1HK.js → archive-plugin-5NXT7Zqv.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-Dm-9prpU.js → attachment-load-DghwhYe0.js} +1 -1
- package/dist/gateway/static/root/assets/{automation-suggestion-card-OTxQTPnC.js → automation-suggestion-card-DYmESgwl.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-De8mVutL.js +4 -0
- package/dist/gateway/static/root/assets/{binary-plugins-DllA_jQ0.js → binary-plugins-DSbPKdWX.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-Cm6CWNj1.js → block-editor-CoZ-_np-.js} +28 -28
- package/dist/gateway/static/root/assets/browser-settings-page-C_ZRa4LF.js +8 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-VJ89b6I2.js → capability-presets-api-hny224j-.js} +1 -1
- package/dist/gateway/static/root/assets/{capability-presets-settings-panel-BaPj8wC2.js → capability-presets-settings-panel-Drc0qLsw.js} +1 -1
- package/dist/gateway/static/root/assets/{channel-recipient-api-B5PwBEUx.js → channel-recipient-api-DAlOHxKJ.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-CA20zBV9.js +1 -0
- package/dist/gateway/static/root/assets/connectors-page-qMyMB5te.js +2 -0
- package/dist/gateway/static/root/assets/desktop-pet-XG6Vb_fZ.js +1 -0
- package/dist/gateway/static/root/assets/desktop-pet-settings-npJ0Oh5p.js +1 -0
- package/dist/gateway/static/root/assets/desktop-pet-sprite-DqZ6fbIj.js +1 -0
- package/dist/gateway/static/root/assets/directory-picker-path-field-BR2ItBuf.js +1 -0
- package/dist/gateway/static/root/assets/dreaming-settings-CkUZ997f.js +3 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-BaM0FpW7.js → extension-debug-page-Tl0f1rNv.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DuZWVOGA.js → extension-page-Ck7QuwE3.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DarVtbmJ.js → extension-settings-page-3RMhQtZ3.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-NFKfkqrd.js → fetch-pg2ErdAk.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-CFEm9rgy.js → gateway-config-api-DbG97ia2.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-B8cyqKk-.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-Dtwh_yGg.js → gateway-startup-retry-Yh8h3hkj.js} +1 -1
- package/dist/gateway/static/root/assets/{goal-create-dialog-BKP7ylcG.js → goal-create-dialog-DmeW7Zz3.js} +1 -1
- package/dist/gateway/static/root/assets/goal-detail-page-DrTyGbVD.js +1 -0
- package/dist/gateway/static/root/assets/{goals-config-api-DTWZNA_Y.js → goals-config-api-CxCWGIBB.js} +1 -1
- package/dist/gateway/static/root/assets/goals-page-DV1bJhIh.js +2 -0
- package/dist/gateway/static/root/assets/{goals-settings-Bhct0ZT-.js → goals-settings-9DrfOkP5.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-C-UxSU4a.js → heartbeat-settings-KaDpZrv0.js} +1 -1
- package/dist/gateway/static/root/assets/index-C2F0Clvm.js +256 -0
- package/dist/gateway/static/root/assets/index-COQSX5d_.css +1 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-DCjy2y4d.js → keyboard-shortcuts-settings-CfQrt_Rb.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-C9dpiNTF.js +2 -0
- package/dist/gateway/static/root/assets/{markdown-split-BaqxP-GQ.js → markdown-split-BwiMdCf_.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-DQ_EXloK.js → media-plugins-DhoizyZv.js} +1 -1
- package/dist/gateway/static/root/assets/messages-DmnbiNxU.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-panel-zdCdmBmH.js +2 -0
- package/dist/gateway/static/root/assets/notes-page-MpGeFfPt.js +1 -0
- package/dist/gateway/static/root/assets/notes-workbench-DYCM3yd2.js +2 -0
- package/dist/gateway/static/root/assets/{page-tabs-EIZhLppK.js → page-tabs-DDC2t4Z8.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-r_uB4Epr.js → preview-open-alternatives-BTmk-XDM.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-Cu0ElRnS.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-DakNaUjZ.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-DYKjt7L9.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-B132Uf-2.js → save-bar-controls-DqU-yKIh.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-B5qshALm.js → schedule-field-CUttkoSB.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-CvLmkdS9.js → schema-form-CVSQA9nI.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-CcGHDsz1.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-CuFdeKNu.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-pRlvqsAf.js → settings-collapsible-section-CK7ogS-P.js} +1 -1
- package/dist/gateway/static/root/assets/settings-form-section-Bugp38Fa.js +1 -0
- package/dist/gateway/static/root/assets/settings-page-0AJoUvxi.js +1 -0
- package/dist/gateway/static/root/assets/settings-page-layout-DBRWwdhh.js +1 -0
- package/dist/gateway/static/root/assets/setup-status-panel-D6a_hEk7.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-v6-IOp8t.js → share-preview-page-BtsuETKF.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-CcEFT7S9.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-BcN_RuTD.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-BbRZZZA5.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-HUU2FFjM.js → system-settings-panel-DJ6YuLqR.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-AH160QHh.js → typed-models-lib-B0T7N8Km.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-BXzDmjCQ.js → use-channel-catalog-C6vrxdzZ.js} +1 -1
- package/dist/gateway/static/root/assets/{user-profile-settings-panel-DxwnQvQ3.js → user-profile-settings-panel-DZ0nKMgj.js} +1 -1
- package/dist/gateway/static/root/assets/{utils-i5POEtqd.js → utils-CehXcWAY.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-2QKflCx8.js +1 -0
- package/dist/gateway/static/root/assets/work-item-detail-page-DfJnuWq1.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-ClVVMgN-.js → workflow-run-setup-panel-c4jeaohQ.js} +2 -2
- package/dist/gateway/static/root/assets/{workflow-start-dialog-Dv4ZA1T0.js → workflow-start-dialog-ENRHjoqa.js} +1 -1
- package/dist/gateway/static/root/assets/workflows-page-BJwwFTm_.js +18 -0
- package/dist/gateway/static/root/index.html +5 -5
- 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-instance-gateway.d.ts +5 -0
- package/dist/src/agent/agent-manager.d.ts +21 -0
- package/dist/src/agent/agent-manager.js +118 -6
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/capabilities/definitions.d.ts +153 -0
- package/dist/src/agent/capabilities/definitions.js +156 -0
- package/dist/src/agent/capabilities/definitions.js.map +1 -0
- package/dist/src/agent/capabilities/index.d.ts +2 -0
- package/dist/src/agent/capabilities/index.js +3 -0
- package/dist/src/agent/capabilities/registry.d.ts +10 -0
- package/dist/src/agent/capabilities/registry.js +51 -0
- package/dist/src/agent/capabilities/registry.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/plugin-discovery.js +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/orchestration/agent-orchestrator.js +1 -1
- package/dist/src/agent/service/process-direct-one-shot.js +5 -3
- package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
- package/dist/src/agent/service/process-direct-streaming.js +4 -3
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service.d.ts +2 -0
- package/dist/src/agent/service.js +9 -3
- 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.js +1 -1
- package/dist/src/agent/skills/hub-pull.js +1 -1
- package/dist/src/agent/skills/parse-skill-metadata.js +9 -1
- package/dist/src/agent/skills/parse-skill-metadata.js.map +1 -1
- package/dist/src/agent/skills/skill-manager.d.ts +4 -0
- package/dist/src/agent/skills/skill-manager.js +17 -0
- package/dist/src/agent/skills/skill-manager.js.map +1 -1
- package/dist/src/agent/skills/types.d.ts +5 -0
- 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/desktop-pet-tool.d.ts +24 -0
- package/dist/src/agent/tools/desktop-pet-tool.js +90 -0
- package/dist/src/agent/tools/desktop-pet-tool.js.map +1 -0
- package/dist/src/agent/tools/factory.d.ts +9 -0
- package/dist/src/agent/tools/factory.js +26 -0
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/goal-tool.js +2 -2
- package/dist/src/agent/tools/index.d.ts +2 -0
- package/dist/src/agent/tools/index.js +3 -1
- package/dist/src/agent/tools/workflow-tool.js +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-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-service.js +1 -1
- 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 +3 -3
- 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/models.js +1 -1
- package/dist/src/cli/commands/onboard.js +1 -1
- package/dist/src/cli/commands/profile.js +1 -1
- package/dist/src/cli/commands/project.js +4 -4
- package/dist/src/cli/commands/tunnel.js +1 -1
- package/dist/src/cli/commands/update.js +1 -1
- package/dist/src/cli/extension-cli-register.js +1 -1
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/gateway-bind.js +1 -1
- package/dist/src/config/index.js +2 -2
- 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/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/agent-builtin-tools.d.ts +1 -1
- package/dist/src/gateway/agent-builtin-tools.js +1 -0
- package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
- package/dist/src/gateway/agents-admin.js +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/commands-skills.js +7 -0
- package/dist/src/gateway/hono/routes/commands-skills.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/lazy-bundles.js +2 -1
- package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
- package/dist/src/gateway/hono/routes/memory.js +2 -2
- package/dist/src/gateway/hono/routes/projects.js +93 -15
- package/dist/src/gateway/hono/routes/projects.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +101 -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/run-loop.js +1 -1
- package/dist/src/gateway/service/run-gateway-agent.js +6 -2
- package/dist/src/gateway/service/run-gateway-agent.js.map +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 +12 -9
- 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/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/pets/factory.d.ts +25 -0
- package/dist/src/pets/factory.js +327 -0
- package/dist/src/pets/factory.js.map +1 -0
- package/dist/src/pets/manifest.d.ts +2 -0
- package/dist/src/pets/manifest.js +16 -0
- package/dist/src/pets/manifest.js.map +1 -0
- package/dist/src/pets/validator.d.ts +12 -0
- package/dist/src/pets/validator.js +175 -0
- package/dist/src/pets/validator.js.map +1 -0
- package/dist/src/projects/project-service.d.ts +4 -1
- package/dist/src/projects/project-service.js +65 -2
- package/dist/src/projects/project-service.js.map +1 -1
- package/dist/src/projects/project-store.d.ts +3 -1
- package/dist/src/projects/project-store.js +56 -6
- package/dist/src/projects/project-store.js.map +1 -1
- package/dist/src/projects/types.d.ts +12 -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-title.js +24 -4
- package/dist/src/session/session-title.js.map +1 -1
- package/dist/src/session/store.js +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/024_activity_events.sql +62 -0
- package/dist/src/storage/sqlite/migrations/025_project_pinned_at.sql +5 -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 +63 -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/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/tui-bottom-bar.js +9 -5
- package/dist/src/tui/components/tui-bottom-bar.js.map +1 -1
- 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-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 +5 -1
- package/dist/src/work-items/agent-context.js +39 -3
- package/dist/src/work-items/agent-context.js.map +1 -1
- package/dist/src/work-items/work-item-service.d.ts +2 -0
- package/dist/src/work-items/work-item-service.js +97 -0
- package/dist/src/work-items/work-item-service.js.map +1 -1
- package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
- package/dist/src/workflows/service/workflow-session-bridge.js +1 -1
- package/package.json +5 -5
- package/skills/creative/hatch-pet/SKILL.md +63 -0
- package/dist/gateway/static/root/assets/agents-BnTB7-c5.js +0 -2
- package/dist/gateway/static/root/assets/apps-page-B6bG65SW.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-1lVbo0dS.js +0 -1
- package/dist/gateway/static/root/assets/browser-settings-page-CzDBlOK0.js +0 -8
- package/dist/gateway/static/root/assets/channels-settings-Df4m7p1k.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-BMTphmHS.js +0 -2
- package/dist/gateway/static/root/assets/directory-picker-path-field-DySMzOF6.js +0 -1
- package/dist/gateway/static/root/assets/dist-By6Rh2ee.js +0 -1
- package/dist/gateway/static/root/assets/dreaming-settings-D_AjSnV_.js +0 -3
- package/dist/gateway/static/root/assets/gateway-settings-BMk2S5td.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-C2cTxf71.js +0 -1
- package/dist/gateway/static/root/assets/goals-page-CTmA3hWK.js +0 -2
- package/dist/gateway/static/root/assets/index-BNHDd2j1.css +0 -1
- package/dist/gateway/static/root/assets/index-BPXLPMuY.js +0 -193
- package/dist/gateway/static/root/assets/logs-page-CGc3_CQU.js +0 -2
- package/dist/gateway/static/root/assets/messages-CjuIJcZl.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-panel-Drz4UQMb.js +0 -2
- package/dist/gateway/static/root/assets/notes-page-CY1ylng1.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-X7IaD--t.js +0 -2
- package/dist/gateway/static/root/assets/project-detail-page-DE5adRBE.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-CuOb1k6F.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-BOxNrUVA.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-CY0IQcGW.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-D4NBNVCB.js +0 -1
- package/dist/gateway/static/root/assets/settings-form-section-BBYUDLVd.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-DaO7zYZM.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-layout-D8g9PAek.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Bks0CLLT.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-CEZsKm9r.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-oTkHbb9W.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-DigsbZ6K.js +0 -2
- package/dist/gateway/static/root/assets/voice-api-key-field-CEJklEgb.js +0 -1
- package/dist/gateway/static/root/assets/work-item-detail-page-CD6FL_Rs.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-OLQiUpoW.js +0 -18
|
@@ -40,6 +40,7 @@ function appendHistoryToChatLog(chatLog, messages, toolsExpanded, showThinking =
|
|
|
40
40
|
chatLog.setShowThinking(showThinking);
|
|
41
41
|
messages.forEach((hm, idx) => {
|
|
42
42
|
const historyIndex = (opts?.startIndex ?? 0) + idx;
|
|
43
|
+
const displayIndex = hm.displayIndex ?? historyIndex;
|
|
43
44
|
const runId = `history:${historyIndex}`;
|
|
44
45
|
if (hm.kind === "bash") {
|
|
45
46
|
if (hm.bash) chatLog.addBashSummary(hm.bash);
|
|
@@ -76,14 +77,26 @@ function appendHistoryToChatLog(chatLog, messages, toolsExpanded, showThinking =
|
|
|
76
77
|
return;
|
|
77
78
|
}
|
|
78
79
|
if (hm.role === "user") {
|
|
79
|
-
chatLog.addUser(historyContentText(hm.content)
|
|
80
|
+
chatLog.addUser(historyContentText(hm.content), {
|
|
81
|
+
displayIndex,
|
|
82
|
+
historyIndex,
|
|
83
|
+
role: "user"
|
|
84
|
+
});
|
|
80
85
|
return;
|
|
81
86
|
}
|
|
82
87
|
if (hm.role === "system") {
|
|
83
|
-
chatLog.addSystem(historyContentText(hm.content)
|
|
88
|
+
chatLog.addSystem(historyContentText(hm.content), {
|
|
89
|
+
displayIndex,
|
|
90
|
+
historyIndex,
|
|
91
|
+
role: "system"
|
|
92
|
+
});
|
|
84
93
|
return;
|
|
85
94
|
}
|
|
86
|
-
chatLog.finalizeAssistant(assistantHistoryMessage(hm.content), runId
|
|
95
|
+
chatLog.finalizeAssistant(assistantHistoryMessage(hm.content), runId, {
|
|
96
|
+
displayIndex,
|
|
97
|
+
historyIndex,
|
|
98
|
+
role: "assistant"
|
|
99
|
+
});
|
|
87
100
|
const tools = hm.toolCalls ?? [];
|
|
88
101
|
for (let t = 0; t < tools.length; t++) {
|
|
89
102
|
const tc = tools[t];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-history.js","names":[],"sources":["../../../src/tui/chat-history.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport type { HistoryMessage } from './tui-backend.js';\nimport { ChatLog } from './components/chat-log.js';\nimport { createAssistantMessageFromText } from './components/assistant-message.js';\n\nexport function historyMessageKey(message: HistoryMessage, index: number): string {\n if (message.id) return `id:${message.id}`;\n return [\n 'fallback',\n index,\n message.kind ?? 'message',\n message.role,\n message.timestamp ?? '',\n JSON.stringify(message.content),\n ].join(':');\n}\n\nfunction historyContentText(content: unknown): string {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return content\n .map((block) => {\n if (!block || typeof block !== 'object') return '';\n const rec = block as { type?: unknown; text?: unknown; thinking?: unknown };\n if (rec.type === 'text' && typeof rec.text === 'string') return rec.text;\n if (rec.type === 'thinking' && typeof rec.thinking === 'string') return rec.thinking;\n return '';\n })\n .filter(Boolean)\n .join('\\n');\n}\n\nfunction assistantHistoryMessage(content: unknown): AgentMessage {\n if (typeof content === 'string') {\n return createAssistantMessageFromText(content.trim() ? content : ' ');\n }\n if (Array.isArray(content)) {\n return {\n role: 'assistant',\n content,\n timestamp: Date.now(),\n } as AgentMessage;\n }\n return createAssistantMessageFromText(' ');\n}\n\nexport function historyKeysHaveAppendOnlyPrefix(\n previousKeys: readonly string[],\n nextKeys: readonly string[],\n): boolean {\n return (\n previousKeys.length > 0 &&\n previousKeys.length <= nextKeys.length &&\n previousKeys.every((key, index) => nextKeys[index] === key)\n );\n}\n\n/** Replay persisted transcript into the scroll log (synthetic run ids per assistant row). */\nexport function appendHistoryToChatLog(\n chatLog: ChatLog,\n messages: HistoryMessage[],\n toolsExpanded: boolean,\n showThinking = true,\n opts?: { startIndex?: number },\n): void {\n chatLog.setToolsExpanded(toolsExpanded);\n chatLog.setShowThinking(showThinking);\n\n messages.forEach((hm, idx) => {\n const historyIndex = (opts?.startIndex ?? 0) + idx;\n const runId = `history:${historyIndex}`;\n\n if (hm.kind === 'bash') {\n if (hm.bash) {\n chatLog.addBashSummary(hm.bash);\n } else {\n chatLog.addSystem(historyContentText(hm.content));\n }\n return;\n }\n\n if (hm.kind === 'custom') {\n if (hm.custom) {\n if (hm.custom.state) return;\n if (hm.custom.display === false) return;\n chatLog.addCustomMessage({\n customType: hm.custom.customType,\n content: historyContentText(hm.content),\n rawContent: hm.rawContent,\n details: hm.custom.details,\n display: hm.custom.display,\n });\n } else {\n chatLog.addSystem(historyContentText(hm.content));\n }\n return;\n }\n\n if (hm.kind === 'branch') {\n if (hm.branch) {\n chatLog.addBranchMessageSummary(hm.branch);\n } else {\n chatLog.addSystem(historyContentText(hm.content));\n }\n return;\n }\n\n if (hm.kind === 'compaction') {\n chatLog.addCompactionSummary({\n compacted: true,\n summary: historyContentText(hm.content),\n tokensBefore: hm.tokensBefore,\n tokensAfter: hm.tokensAfter,\n transcriptSummary: historyContentText(hm.content),\n });\n return;\n }\n\n if (hm.role === 'user') {\n chatLog.addUser(historyContentText(hm.content));\n return;\n }\n\n if (hm.role === 'system') {\n chatLog.addSystem(historyContentText(hm.content));\n return;\n }\n\n chatLog.finalizeAssistant(assistantHistoryMessage(hm.content), runId);\n\n const tools = hm.toolCalls ?? [];\n for (let t = 0; t < tools.length; t++) {\n const tc = tools[t]!;\n const tid = `history:${historyIndex}:t:${t}`;\n chatLog.startTool(tid, tc.name, tc.args ?? {}, runId);\n if (tc.result !== undefined) {\n chatLog.updateToolResult(tid, tc.result, tc.isError ?? false);\n }\n }\n });\n}\n"],"mappings":";;AAMA,SAAgB,kBAAkB,SAAyB,OAAuB;AAChF,KAAI,QAAQ,GAAI,QAAO,MAAM,QAAQ;AACrC,QAAO;EACL;EACA;EACA,QAAQ,QAAQ;EAChB,QAAQ;EACR,QAAQ,aAAa;EACrB,KAAK,UAAU,QAAQ,QAAQ;EAChC,CAAC,KAAK,IAAI;;AAGb,SAAS,mBAAmB,SAA0B;AACpD,KAAI,OAAO,YAAY,SAAU,QAAO;AACxC,KAAI,CAAC,MAAM,QAAQ,QAAQ,CAAE,QAAO;AACpC,QAAO,QACJ,KAAK,UAAU;AACd,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;EAChD,MAAM,MAAM;AACZ,MAAI,IAAI,SAAS,UAAU,OAAO,IAAI,SAAS,SAAU,QAAO,IAAI;AACpE,MAAI,IAAI,SAAS,cAAc,OAAO,IAAI,aAAa,SAAU,QAAO,IAAI;AAC5E,SAAO;GACP,CACD,OAAO,QAAQ,CACf,KAAK,KAAK;;AAGf,SAAS,wBAAwB,SAAgC;AAC/D,KAAI,OAAO,YAAY,SACrB,QAAO,+BAA+B,QAAQ,MAAM,GAAG,UAAU,IAAI;AAEvE,KAAI,MAAM,QAAQ,QAAQ,CACxB,QAAO;EACL,MAAM;EACN;EACA,WAAW,KAAK,KAAK;EACtB;AAEH,QAAO,+BAA+B,IAAI;;AAG5C,SAAgB,gCACd,cACA,UACS;AACT,QACE,aAAa,SAAS,KACtB,aAAa,UAAU,SAAS,UAChC,aAAa,OAAO,KAAK,UAAU,SAAS,WAAW,IAAI;;;AAK/D,SAAgB,uBACd,SACA,UACA,eACA,eAAe,MACf,MACM;AACN,SAAQ,iBAAiB,cAAc;AACvC,SAAQ,gBAAgB,aAAa;AAErC,UAAS,SAAS,IAAI,QAAQ;EAC5B,MAAM,gBAAgB,MAAM,cAAc,KAAK;EAC/C,MAAM,QAAQ,WAAW;AAEzB,MAAI,GAAG,SAAS,QAAQ;AACtB,OAAI,GAAG,KACL,SAAQ,eAAe,GAAG,KAAK;OAE/B,SAAQ,UAAU,mBAAmB,GAAG,QAAQ,CAAC;AAEnD;;AAGF,MAAI,GAAG,SAAS,UAAU;AACxB,OAAI,GAAG,QAAQ;AACb,QAAI,GAAG,OAAO,MAAO;AACrB,QAAI,GAAG,OAAO,YAAY,MAAO;AACjC,YAAQ,iBAAiB;KACvB,YAAY,GAAG,OAAO;KACtB,SAAS,mBAAmB,GAAG,QAAQ;KACvC,YAAY,GAAG;KACf,SAAS,GAAG,OAAO;KACnB,SAAS,GAAG,OAAO;KACpB,CAAC;SAEF,SAAQ,UAAU,mBAAmB,GAAG,QAAQ,CAAC;AAEnD;;AAGF,MAAI,GAAG,SAAS,UAAU;AACxB,OAAI,GAAG,OACL,SAAQ,wBAAwB,GAAG,OAAO;OAE1C,SAAQ,UAAU,mBAAmB,GAAG,QAAQ,CAAC;AAEnD;;AAGF,MAAI,GAAG,SAAS,cAAc;AAC5B,WAAQ,qBAAqB;IAC3B,WAAW;IACX,SAAS,mBAAmB,GAAG,QAAQ;IACvC,cAAc,GAAG;IACjB,aAAa,GAAG;IAChB,mBAAmB,mBAAmB,GAAG,QAAQ;IAClD,CAAC;AACF;;AAGF,MAAI,GAAG,SAAS,QAAQ;AACtB,WAAQ,QAAQ,mBAAmB,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"chat-history.js","names":[],"sources":["../../../src/tui/chat-history.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport type { HistoryMessage } from './tui-backend.js';\nimport { ChatLog } from './components/chat-log.js';\nimport { createAssistantMessageFromText } from './components/assistant-message.js';\n\nexport function historyMessageKey(message: HistoryMessage, index: number): string {\n if (message.id) return `id:${message.id}`;\n return [\n 'fallback',\n index,\n message.kind ?? 'message',\n message.role,\n message.timestamp ?? '',\n JSON.stringify(message.content),\n ].join(':');\n}\n\nfunction historyContentText(content: unknown): string {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return content\n .map((block) => {\n if (!block || typeof block !== 'object') return '';\n const rec = block as { type?: unknown; text?: unknown; thinking?: unknown };\n if (rec.type === 'text' && typeof rec.text === 'string') return rec.text;\n if (rec.type === 'thinking' && typeof rec.thinking === 'string') return rec.thinking;\n return '';\n })\n .filter(Boolean)\n .join('\\n');\n}\n\nfunction assistantHistoryMessage(content: unknown): AgentMessage {\n if (typeof content === 'string') {\n return createAssistantMessageFromText(content.trim() ? content : ' ');\n }\n if (Array.isArray(content)) {\n return {\n role: 'assistant',\n content,\n timestamp: Date.now(),\n } as AgentMessage;\n }\n return createAssistantMessageFromText(' ');\n}\n\nexport function historyKeysHaveAppendOnlyPrefix(\n previousKeys: readonly string[],\n nextKeys: readonly string[],\n): boolean {\n return (\n previousKeys.length > 0 &&\n previousKeys.length <= nextKeys.length &&\n previousKeys.every((key, index) => nextKeys[index] === key)\n );\n}\n\n/** Replay persisted transcript into the scroll log (synthetic run ids per assistant row). */\nexport function appendHistoryToChatLog(\n chatLog: ChatLog,\n messages: HistoryMessage[],\n toolsExpanded: boolean,\n showThinking = true,\n opts?: { startIndex?: number },\n): void {\n chatLog.setToolsExpanded(toolsExpanded);\n chatLog.setShowThinking(showThinking);\n\n messages.forEach((hm, idx) => {\n const historyIndex = (opts?.startIndex ?? 0) + idx;\n const displayIndex = hm.displayIndex ?? historyIndex;\n const runId = `history:${historyIndex}`;\n\n if (hm.kind === 'bash') {\n if (hm.bash) {\n chatLog.addBashSummary(hm.bash);\n } else {\n chatLog.addSystem(historyContentText(hm.content));\n }\n return;\n }\n\n if (hm.kind === 'custom') {\n if (hm.custom) {\n if (hm.custom.state) return;\n if (hm.custom.display === false) return;\n chatLog.addCustomMessage({\n customType: hm.custom.customType,\n content: historyContentText(hm.content),\n rawContent: hm.rawContent,\n details: hm.custom.details,\n display: hm.custom.display,\n });\n } else {\n chatLog.addSystem(historyContentText(hm.content));\n }\n return;\n }\n\n if (hm.kind === 'branch') {\n if (hm.branch) {\n chatLog.addBranchMessageSummary(hm.branch);\n } else {\n chatLog.addSystem(historyContentText(hm.content));\n }\n return;\n }\n\n if (hm.kind === 'compaction') {\n chatLog.addCompactionSummary({\n compacted: true,\n summary: historyContentText(hm.content),\n tokensBefore: hm.tokensBefore,\n tokensAfter: hm.tokensAfter,\n transcriptSummary: historyContentText(hm.content),\n });\n return;\n }\n\n if (hm.role === 'user') {\n chatLog.addUser(historyContentText(hm.content), {\n displayIndex,\n historyIndex,\n role: 'user',\n });\n return;\n }\n\n if (hm.role === 'system') {\n chatLog.addSystem(historyContentText(hm.content), {\n displayIndex,\n historyIndex,\n role: 'system',\n });\n return;\n }\n\n chatLog.finalizeAssistant(assistantHistoryMessage(hm.content), runId, {\n displayIndex,\n historyIndex,\n role: 'assistant',\n });\n\n const tools = hm.toolCalls ?? [];\n for (let t = 0; t < tools.length; t++) {\n const tc = tools[t]!;\n const tid = `history:${historyIndex}:t:${t}`;\n chatLog.startTool(tid, tc.name, tc.args ?? {}, runId);\n if (tc.result !== undefined) {\n chatLog.updateToolResult(tid, tc.result, tc.isError ?? false);\n }\n }\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { tmpdir } from "node:os";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
4
|
-
import { randomUUID } from "node:crypto";
|
|
5
4
|
import { spawnSync } from "node:child_process";
|
|
5
|
+
import { randomUUID } from "node:crypto";
|
|
6
6
|
//#region src/tui/clipboard-image.ts
|
|
7
7
|
const SUPPORTED_IMAGE_MIME_TYPES = [
|
|
8
8
|
"image/png",
|
|
@@ -8,6 +8,12 @@ import { type CustomMessageSummary } from './custom-message.js';
|
|
|
8
8
|
import type { TuiMessageRenderer } from '../../extensions/types/tui.js';
|
|
9
9
|
import { type ToolExecutionOptions } from './tool-execution.js';
|
|
10
10
|
import type { TuiBranchSummary, TuiCompactionResult } from '../tui-backend.js';
|
|
11
|
+
export type ChatLogEntryMeta = {
|
|
12
|
+
displayIndex?: number;
|
|
13
|
+
historyIndex?: number;
|
|
14
|
+
rowNumber?: number;
|
|
15
|
+
role?: 'user' | 'assistant' | 'system';
|
|
16
|
+
};
|
|
11
17
|
export declare class ChatLog extends Container {
|
|
12
18
|
private readonly keybindings?;
|
|
13
19
|
private toolById;
|
|
@@ -30,13 +36,16 @@ export declare class ChatLog extends Container {
|
|
|
30
36
|
private lastStatusEntry;
|
|
31
37
|
private lastStatusText;
|
|
32
38
|
private workflowStatusByRunId;
|
|
39
|
+
private entryRecords;
|
|
40
|
+
private viewportRowsProvider;
|
|
41
|
+
private historyViewDisplayIndex;
|
|
33
42
|
constructor(keybindings?: KeybindingsManager);
|
|
34
43
|
private pruneOverflow;
|
|
35
44
|
private dropReferences;
|
|
36
45
|
private append;
|
|
37
46
|
clearAll(): void;
|
|
38
47
|
private createAssistantMessage;
|
|
39
|
-
addSystem(text: string): void;
|
|
48
|
+
addSystem(text: string, meta?: ChatLogEntryMeta): void;
|
|
40
49
|
addStatus(text: string): void;
|
|
41
50
|
updateWorkflowRun(runId: string, text: string): void;
|
|
42
51
|
addCompactionSummary(result: TuiCompactionResult): void;
|
|
@@ -44,14 +53,14 @@ export declare class ChatLog extends Container {
|
|
|
44
53
|
addBranchMessageSummary(summary: BranchMessageSummary): void;
|
|
45
54
|
addCustomMessage(summary: CustomMessageSummary): void;
|
|
46
55
|
setCustomMessageRenderer(customType: string, renderer: TuiMessageRenderer | undefined): void;
|
|
47
|
-
addUser(text: string | unknown[]): void;
|
|
56
|
+
addUser(text: string | unknown[], meta?: ChatLogEntryMeta): void;
|
|
48
57
|
/** Stream local `!command` output in a bordered block. */
|
|
49
58
|
addBashExecution(command: string, ui: import('@earendil-works/pi-tui').TUI, excludeFromContext: boolean): BashExecutionComponent;
|
|
50
59
|
/** Replay a completed shell execution from persisted transcript history. */
|
|
51
60
|
addBashSummary(summary: BashSummary): void;
|
|
52
61
|
startAssistant(message: AgentMessage, runId: string): void;
|
|
53
62
|
updateAssistant(message: AgentMessage, runId: string): void;
|
|
54
|
-
finalizeAssistant(message: AgentMessage, runId: string): void;
|
|
63
|
+
finalizeAssistant(message: AgentMessage, runId: string, meta?: ChatLogEntryMeta): void;
|
|
55
64
|
dropAssistant(runId: string): void;
|
|
56
65
|
startTool(toolCallId: string, toolName: string, args: unknown, runId: string): void;
|
|
57
66
|
markToolExecutionStarted(toolCallId: string): void;
|
|
@@ -64,4 +73,15 @@ export declare class ChatLog extends Container {
|
|
|
64
73
|
setHiddenThinkingLabel(label?: string): void;
|
|
65
74
|
setToolImageOptions(options: ToolExecutionOptions): void;
|
|
66
75
|
getLastAssistantText(): string;
|
|
76
|
+
setViewportRowsProvider(provider: (() => number) | undefined): void;
|
|
77
|
+
jumpToDisplayIndex(displayIndex: number): boolean;
|
|
78
|
+
jumpToLatest(): void;
|
|
79
|
+
getTimelineViewportState(): {
|
|
80
|
+
mode: 'latest';
|
|
81
|
+
} | {
|
|
82
|
+
mode: 'history';
|
|
83
|
+
displayIndex: number;
|
|
84
|
+
};
|
|
85
|
+
render(width: number): string[];
|
|
86
|
+
private findEntryRecord;
|
|
67
87
|
}
|
|
@@ -42,6 +42,9 @@ var ChatLog = class extends Container {
|
|
|
42
42
|
lastStatusEntry = null;
|
|
43
43
|
lastStatusText = null;
|
|
44
44
|
workflowStatusByRunId = /* @__PURE__ */ new Map();
|
|
45
|
+
entryRecords = [];
|
|
46
|
+
viewportRowsProvider;
|
|
47
|
+
historyViewDisplayIndex = null;
|
|
45
48
|
constructor(keybindings) {
|
|
46
49
|
super();
|
|
47
50
|
this.keybindings = keybindings;
|
|
@@ -70,9 +73,15 @@ var ChatLog = class extends Container {
|
|
|
70
73
|
this.lastStatusText = null;
|
|
71
74
|
}
|
|
72
75
|
for (const [runId, status] of this.workflowStatusByRunId.entries()) if (status.entry === component) this.workflowStatusByRunId.delete(runId);
|
|
76
|
+
this.entryRecords = this.entryRecords.filter((entry) => entry.component !== component);
|
|
77
|
+
if (!this.findEntryRecord(this.historyViewDisplayIndex)) this.historyViewDisplayIndex = null;
|
|
73
78
|
}
|
|
74
|
-
append(component) {
|
|
79
|
+
append(component, meta) {
|
|
75
80
|
this.addChild(component);
|
|
81
|
+
if (meta) this.entryRecords.push({
|
|
82
|
+
component,
|
|
83
|
+
...meta
|
|
84
|
+
});
|
|
76
85
|
this.pruneOverflow();
|
|
77
86
|
}
|
|
78
87
|
clearAll() {
|
|
@@ -91,6 +100,8 @@ var ChatLog = class extends Container {
|
|
|
91
100
|
this.lastStatusEntry = null;
|
|
92
101
|
this.lastStatusText = null;
|
|
93
102
|
this.workflowStatusByRunId.clear();
|
|
103
|
+
this.entryRecords = [];
|
|
104
|
+
this.historyViewDisplayIndex = null;
|
|
94
105
|
}
|
|
95
106
|
createAssistantMessage(message) {
|
|
96
107
|
const component = new AssistantMessageComponent(message, {
|
|
@@ -100,11 +111,11 @@ var ChatLog = class extends Container {
|
|
|
100
111
|
this.assistantMessages.push(component);
|
|
101
112
|
return component;
|
|
102
113
|
}
|
|
103
|
-
addSystem(text) {
|
|
114
|
+
addSystem(text, meta) {
|
|
104
115
|
const entry = new Container();
|
|
105
116
|
entry.addChild(new Spacer(1));
|
|
106
117
|
entry.addChild(new Text(theme.system(text), 1, 0));
|
|
107
|
-
this.append(entry);
|
|
118
|
+
this.append(entry, meta);
|
|
108
119
|
}
|
|
109
120
|
addStatus(text) {
|
|
110
121
|
if (this.lastStatusEntry && this.lastStatusText && this.children[this.children.length - 1] === this.lastStatusEntry) {
|
|
@@ -166,9 +177,9 @@ var ChatLog = class extends Container {
|
|
|
166
177
|
else this.customMessageRenderers.delete(customType);
|
|
167
178
|
for (const block of this.customBlocks) if (block.matchesCustomType(customType)) block.setRenderer(renderer);
|
|
168
179
|
}
|
|
169
|
-
addUser(text) {
|
|
180
|
+
addUser(text, meta) {
|
|
170
181
|
this.assistantAnchorByRunId.clear();
|
|
171
|
-
this.append(new UserMessageComponent(text));
|
|
182
|
+
this.append(new UserMessageComponent(text), meta);
|
|
172
183
|
}
|
|
173
184
|
/** Stream local `!command` output in a bordered block. */
|
|
174
185
|
addBashExecution(command, ui, excludeFromContext) {
|
|
@@ -212,7 +223,7 @@ var ChatLog = class extends Container {
|
|
|
212
223
|
existing.updateContent(message);
|
|
213
224
|
existing.setHasToolCalls(this.runsWithTools.has(runId));
|
|
214
225
|
}
|
|
215
|
-
finalizeAssistant(message, runId) {
|
|
226
|
+
finalizeAssistant(message, runId, meta) {
|
|
216
227
|
const text = assistantPlainText(message);
|
|
217
228
|
if (text.trim()) this.lastAssistantText = text;
|
|
218
229
|
const existing = this.streamingRuns.get(runId);
|
|
@@ -225,7 +236,7 @@ var ChatLog = class extends Container {
|
|
|
225
236
|
}
|
|
226
237
|
const finalMessage = this.createAssistantMessage(message);
|
|
227
238
|
finalMessage.setHasToolCalls(this.runsWithTools.has(runId));
|
|
228
|
-
this.append(finalMessage);
|
|
239
|
+
this.append(finalMessage, meta);
|
|
229
240
|
if (text.trim()) this.assistantAnchorByRunId.set(runId, finalMessage);
|
|
230
241
|
}
|
|
231
242
|
dropAssistant(runId) {
|
|
@@ -245,8 +256,7 @@ var ChatLog = class extends Container {
|
|
|
245
256
|
component.setExpanded(this.toolsExpanded);
|
|
246
257
|
this.toolById.set(toolCallId, component);
|
|
247
258
|
(this.streamingRuns.get(runId) ?? this.assistantAnchorByRunId.get(runId))?.setHasToolCalls(true);
|
|
248
|
-
this.
|
|
249
|
-
this.pruneOverflow();
|
|
259
|
+
this.append(component);
|
|
250
260
|
}
|
|
251
261
|
markToolExecutionStarted(toolCallId) {
|
|
252
262
|
const existing = this.toolById.get(toolCallId);
|
|
@@ -300,6 +310,55 @@ var ChatLog = class extends Container {
|
|
|
300
310
|
getLastAssistantText() {
|
|
301
311
|
return this.lastAssistantText;
|
|
302
312
|
}
|
|
313
|
+
setViewportRowsProvider(provider) {
|
|
314
|
+
this.viewportRowsProvider = provider;
|
|
315
|
+
}
|
|
316
|
+
jumpToDisplayIndex(displayIndex) {
|
|
317
|
+
const target = this.findEntryRecord(displayIndex);
|
|
318
|
+
if (!target) return false;
|
|
319
|
+
this.historyViewDisplayIndex = target.displayIndex ?? null;
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
jumpToLatest() {
|
|
323
|
+
this.historyViewDisplayIndex = null;
|
|
324
|
+
}
|
|
325
|
+
getTimelineViewportState() {
|
|
326
|
+
if (this.historyViewDisplayIndex === null) return { mode: "latest" };
|
|
327
|
+
return {
|
|
328
|
+
mode: "history",
|
|
329
|
+
displayIndex: this.historyViewDisplayIndex
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
render(width) {
|
|
333
|
+
const allLines = [];
|
|
334
|
+
const ranges = [];
|
|
335
|
+
for (const child of this.children) {
|
|
336
|
+
const start = allLines.length;
|
|
337
|
+
const childLines = child.render(width);
|
|
338
|
+
allLines.push(...childLines);
|
|
339
|
+
const record = this.entryRecords.find((entry) => entry.component === child);
|
|
340
|
+
if (record) ranges.push({
|
|
341
|
+
record,
|
|
342
|
+
start,
|
|
343
|
+
end: allLines.length
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
if (this.historyViewDisplayIndex === null) return allLines;
|
|
347
|
+
const target = this.findEntryRecord(this.historyViewDisplayIndex);
|
|
348
|
+
const range = target ? ranges.find((candidate) => candidate.record.component === target.component) : void 0;
|
|
349
|
+
if (!range) {
|
|
350
|
+
this.historyViewDisplayIndex = null;
|
|
351
|
+
return allLines;
|
|
352
|
+
}
|
|
353
|
+
const viewportRows = Math.max(8, Math.floor(this.viewportRowsProvider?.() ?? 24));
|
|
354
|
+
const start = Math.max(0, range.start - 1);
|
|
355
|
+
const end = Math.min(allLines.length, start + Math.max(1, viewportRows - 1));
|
|
356
|
+
return [theme.dim("Viewing previous transcript - /timeline latest returns to live view."), ...allLines.slice(start, end)];
|
|
357
|
+
}
|
|
358
|
+
findEntryRecord(displayIndex) {
|
|
359
|
+
if (displayIndex === null || !Number.isFinite(displayIndex)) return void 0;
|
|
360
|
+
return this.entryRecords.find((entry) => entry.displayIndex === displayIndex);
|
|
361
|
+
}
|
|
303
362
|
};
|
|
304
363
|
//#endregion
|
|
305
364
|
export { ChatLog };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-log.js","names":[],"sources":["../../../../src/tui/components/chat-log.ts"],"sourcesContent":["import type { Component, KeybindingsManager } from '@earendil-works/pi-tui';\nimport { Container, Spacer, Text } from '@earendil-works/pi-tui';\nimport type { AgentMessage, AgentToolResult } from '@earendil-works/pi-agent-core';\n\nimport { BashExecutionComponent } from './bash-execution.js';\nimport { BashSummaryComponent, type BashSummary } from './bash-summary.js';\nimport { BranchMessageSummaryComponent, type BranchMessageSummary } from './branch-message-summary.js';\nimport { BranchSummaryComponent } from './branch-summary.js';\nimport { CompactionSummaryComponent } from './compaction-summary.js';\nimport { CustomMessageComponent, type CustomMessageSummary } from './custom-message.js';\nimport type { TuiMessageRenderer } from '../../extensions/types/tui.js';\nimport { theme } from '../theme.js';\nimport { AssistantMessageComponent } from './assistant-message.js';\nimport { ToolExecutionComponent, type ToolExecutionOptions } from './tool-execution.js';\nimport { UserMessageComponent } from './user-message.js';\nimport type { TuiBranchSummary, TuiCompactionResult } from '../tui-backend.js';\n\nconst MAX_COMPONENTS = 180;\n\ntype ExpandableBlock = { setExpanded(expanded: boolean): void };\n\nfunction assistantPlainText(message: AgentMessage): string {\n const content = (message as { content?: unknown }).content;\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return content\n .map((block) => {\n if (!block || typeof block !== 'object') return '';\n const rec = block as { type?: unknown; text?: unknown };\n return rec.type === 'text' && typeof rec.text === 'string' ? rec.text : '';\n })\n .join('');\n}\n\nexport class ChatLog extends Container {\n private toolById = new Map<string, ToolExecutionComponent>();\n private bashBlocks: Array<Component & ExpandableBlock> = [];\n private compactionBlocks: CompactionSummaryComponent[] = [];\n private branchBlocks: BranchSummaryComponent[] = [];\n private branchMessageBlocks: BranchMessageSummaryComponent[] = [];\n private customBlocks: CustomMessageComponent[] = [];\n private customMessageRenderers = new Map<string, TuiMessageRenderer>();\n private assistantMessages: AssistantMessageComponent[] = [];\n private streamingRuns = new Map<string, AssistantMessageComponent>();\n /** After finalizeAssistant, late tool execution events can still arrive; keep the bubble to link tools. */\n private assistantAnchorByRunId = new Map<string, AssistantMessageComponent>();\n private runsWithTools = new Set<string>();\n private toolsExpanded = false;\n private showThinking = true;\n private hiddenThinkingLabel = 'Thinking...';\n private toolImageOptions: ToolExecutionOptions = {};\n private lastAssistantText = '';\n private lastStatusEntry: Container | null = null;\n private lastStatusText: Text | null = null;\n private workflowStatusByRunId = new Map<string, { entry: Container; text: Text }>();\n\n constructor(private readonly keybindings?: KeybindingsManager) {\n super();\n if (keybindings) {\n this.toolImageOptions.keybindings = keybindings;\n }\n }\n\n private pruneOverflow(): void {\n while (this.children.length > MAX_COMPONENTS) {\n const oldest = this.children[0];\n if (!oldest) return;\n this.removeChild(oldest);\n this.dropReferences(oldest);\n }\n }\n\n private dropReferences(component: Component): void {\n for (const [id, tool] of this.toolById.entries()) {\n if (tool === component) this.toolById.delete(id);\n }\n for (const [runId, msg] of this.streamingRuns.entries()) {\n if (msg === component) this.streamingRuns.delete(runId);\n }\n for (const [runId, msg] of this.assistantAnchorByRunId.entries()) {\n if (msg === component) this.assistantAnchorByRunId.delete(runId);\n }\n this.bashBlocks = this.bashBlocks.filter((entry) => entry !== component);\n this.compactionBlocks = this.compactionBlocks.filter((entry) => entry !== component);\n this.branchBlocks = this.branchBlocks.filter((entry) => entry !== component);\n this.branchMessageBlocks = this.branchMessageBlocks.filter((entry) => entry !== component);\n this.customBlocks = this.customBlocks.filter((entry) => entry !== component);\n this.assistantMessages = this.assistantMessages.filter((entry) => entry !== component);\n if (this.lastStatusEntry === component) {\n this.lastStatusEntry = null;\n this.lastStatusText = null;\n }\n for (const [runId, status] of this.workflowStatusByRunId.entries()) {\n if (status.entry === component) this.workflowStatusByRunId.delete(runId);\n }\n }\n\n private append(component: Component): void {\n this.addChild(component);\n this.pruneOverflow();\n }\n\n clearAll(): void {\n this.clear();\n this.toolById.clear();\n this.bashBlocks = [];\n this.compactionBlocks = [];\n this.branchBlocks = [];\n this.branchMessageBlocks = [];\n this.customBlocks = [];\n this.assistantMessages = [];\n this.streamingRuns.clear();\n this.assistantAnchorByRunId.clear();\n this.runsWithTools.clear();\n this.lastAssistantText = '';\n this.lastStatusEntry = null;\n this.lastStatusText = null;\n this.workflowStatusByRunId.clear();\n }\n\n private createAssistantMessage(message?: AgentMessage): AssistantMessageComponent {\n const component = new AssistantMessageComponent(message, {\n hideThinkingBlock: !this.showThinking,\n hiddenThinkingLabel: this.hiddenThinkingLabel,\n });\n this.assistantMessages.push(component);\n return component;\n }\n\n addSystem(text: string): void {\n const entry = new Container();\n entry.addChild(new Spacer(1));\n entry.addChild(new Text(theme.system(text), 1, 0));\n this.append(entry);\n }\n\n addStatus(text: string): void {\n if (\n this.lastStatusEntry &&\n this.lastStatusText &&\n this.children[this.children.length - 1] === this.lastStatusEntry\n ) {\n this.lastStatusText.setText(theme.system(text));\n return;\n }\n\n const entry = new Container();\n const statusText = new Text(theme.system(text), 1, 0);\n entry.addChild(new Spacer(1));\n entry.addChild(statusText);\n this.lastStatusEntry = entry;\n this.lastStatusText = statusText;\n this.append(entry);\n }\n\n updateWorkflowRun(runId: string, text: string): void {\n const existing = this.workflowStatusByRunId.get(runId);\n if (existing) {\n existing.text.setText(theme.system(text));\n return;\n }\n\n const entry = new Container();\n const statusText = new Text(theme.system(text), 1, 0);\n entry.addChild(new Spacer(1));\n entry.addChild(statusText);\n this.workflowStatusByRunId.set(runId, { entry, text: statusText });\n this.append(entry);\n }\n\n addCompactionSummary(result: TuiCompactionResult): void {\n const component = new CompactionSummaryComponent(result, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.compactionBlocks.push(component);\n this.append(component);\n }\n\n addBranchSummary(summary: TuiBranchSummary): void {\n const component = new BranchSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.branchBlocks.push(component);\n this.append(component);\n }\n\n addBranchMessageSummary(summary: BranchMessageSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new BranchMessageSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.branchMessageBlocks.push(component);\n this.append(component);\n }\n\n addCustomMessage(summary: CustomMessageSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new CustomMessageComponent(\n summary,\n this.customMessageRenderers.get(summary.customType),\n );\n component.setExpanded(this.toolsExpanded);\n this.customBlocks.push(component);\n this.append(component);\n }\n\n setCustomMessageRenderer(customType: string, renderer: TuiMessageRenderer | undefined): void {\n if (renderer) {\n this.customMessageRenderers.set(customType, renderer);\n } else {\n this.customMessageRenderers.delete(customType);\n }\n for (const block of this.customBlocks) {\n if (block.matchesCustomType(customType)) {\n block.setRenderer(renderer);\n }\n }\n }\n\n addUser(text: string | unknown[]): void {\n this.assistantAnchorByRunId.clear();\n this.append(new UserMessageComponent(text));\n }\n\n /** Stream local `!command` output in a bordered block. */\n addBashExecution(\n command: string,\n ui: import('@earendil-works/pi-tui').TUI,\n excludeFromContext: boolean,\n ): BashExecutionComponent {\n this.assistantAnchorByRunId.clear();\n const component = new BashExecutionComponent(command, ui, excludeFromContext, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.bashBlocks.push(component);\n this.append(component);\n return component;\n }\n\n /** Replay a completed shell execution from persisted transcript history. */\n addBashSummary(summary: BashSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new BashSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.bashBlocks.push(component);\n this.append(component);\n }\n\n startAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (existing) {\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n return;\n }\n const component = this.createAssistantMessage(message);\n component.setHasToolCalls(this.runsWithTools.has(runId));\n this.streamingRuns.set(runId, component);\n this.append(component);\n }\n\n updateAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (!existing) {\n this.startAssistant(message, runId);\n return;\n }\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n }\n\n finalizeAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (existing) {\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n this.streamingRuns.delete(runId);\n this.assistantAnchorByRunId.set(runId, existing);\n return;\n }\n const finalMessage = this.createAssistantMessage(message);\n finalMessage.setHasToolCalls(this.runsWithTools.has(runId));\n this.append(finalMessage);\n if (text.trim()) {\n this.assistantAnchorByRunId.set(runId, finalMessage);\n }\n }\n\n dropAssistant(runId: string): void {\n const existing = this.streamingRuns.get(runId);\n if (!existing) return;\n this.removeChild(existing);\n this.streamingRuns.delete(runId);\n }\n\n startTool(toolCallId: string, toolName: string, args: unknown, runId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (existing) {\n existing.setArgs(args);\n return;\n }\n this.runsWithTools.add(runId);\n const component = new ToolExecutionComponent(toolName, toolCallId, args, {\n ...this.toolImageOptions,\n });\n component.setExpanded(this.toolsExpanded);\n this.toolById.set(toolCallId, component);\n\n const assistant = this.streamingRuns.get(runId) ?? this.assistantAnchorByRunId.get(runId);\n assistant?.setHasToolCalls(true);\n this.addChild(component);\n this.pruneOverflow();\n }\n\n markToolExecutionStarted(toolCallId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.markExecutionStarted();\n }\n\n markToolArgsComplete(toolCallId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setArgsComplete();\n }\n\n updateToolResult(toolCallId: string, result: AgentToolResult<any> | unknown, isError: boolean, isPartial = false): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.updateResult(result, isPartial, isError);\n }\n\n updateToolDetails(toolCallId: string, details: unknown): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setPartialDetails(details);\n }\n\n updateToolArgs(toolCallId: string, args: unknown): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setArgs(args);\n }\n\n setToolsExpanded(expanded: boolean): void {\n this.toolsExpanded = expanded;\n for (const tool of this.toolById.values()) {\n tool.setExpanded(expanded);\n }\n for (const bash of this.bashBlocks) {\n bash.setExpanded(expanded);\n }\n for (const compaction of this.compactionBlocks) {\n compaction.setExpanded(expanded);\n }\n for (const branch of this.branchBlocks) {\n branch.setExpanded(expanded);\n }\n for (const branch of this.branchMessageBlocks) {\n branch.setExpanded(expanded);\n }\n for (const custom of this.customBlocks) {\n custom.setExpanded(expanded);\n }\n }\n\n setShowThinking(showThinking: boolean): void {\n this.showThinking = showThinking;\n for (const assistant of this.assistantMessages) {\n assistant.setHideThinkingBlock(!showThinking);\n }\n }\n\n setHiddenThinkingLabel(label?: string): void {\n this.hiddenThinkingLabel = label ?? 'Thinking...';\n for (const assistant of this.assistantMessages) {\n assistant.setHiddenThinkingLabel(this.hiddenThinkingLabel);\n }\n }\n\n setToolImageOptions(options: ToolExecutionOptions): void {\n this.toolImageOptions = { ...options, keybindings: this.keybindings };\n for (const tool of this.toolById.values()) {\n tool.setImageOptions(this.toolImageOptions);\n }\n }\n\n getLastAssistantText(): string {\n return this.lastAssistantText;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chat-log.js","names":[],"sources":["../../../../src/tui/components/chat-log.ts"],"sourcesContent":["import type { Component, KeybindingsManager } from '@earendil-works/pi-tui';\nimport { Container, Spacer, Text } from '@earendil-works/pi-tui';\nimport type { AgentMessage, AgentToolResult } from '@earendil-works/pi-agent-core';\n\nimport { BashExecutionComponent } from './bash-execution.js';\nimport { BashSummaryComponent, type BashSummary } from './bash-summary.js';\nimport { BranchMessageSummaryComponent, type BranchMessageSummary } from './branch-message-summary.js';\nimport { BranchSummaryComponent } from './branch-summary.js';\nimport { CompactionSummaryComponent } from './compaction-summary.js';\nimport { CustomMessageComponent, type CustomMessageSummary } from './custom-message.js';\nimport type { TuiMessageRenderer } from '../../extensions/types/tui.js';\nimport { theme } from '../theme.js';\nimport { AssistantMessageComponent } from './assistant-message.js';\nimport { ToolExecutionComponent, type ToolExecutionOptions } from './tool-execution.js';\nimport { UserMessageComponent } from './user-message.js';\nimport type { TuiBranchSummary, TuiCompactionResult } from '../tui-backend.js';\n\nconst MAX_COMPONENTS = 180;\n\ntype ExpandableBlock = { setExpanded(expanded: boolean): void };\nexport type ChatLogEntryMeta = {\n displayIndex?: number;\n historyIndex?: number;\n rowNumber?: number;\n role?: 'user' | 'assistant' | 'system';\n};\n\ntype ChatLogEntryRecord = ChatLogEntryMeta & { component: Component };\n\nfunction assistantPlainText(message: AgentMessage): string {\n const content = (message as { content?: unknown }).content;\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return content\n .map((block) => {\n if (!block || typeof block !== 'object') return '';\n const rec = block as { type?: unknown; text?: unknown };\n return rec.type === 'text' && typeof rec.text === 'string' ? rec.text : '';\n })\n .join('');\n}\n\nexport class ChatLog extends Container {\n private toolById = new Map<string, ToolExecutionComponent>();\n private bashBlocks: Array<Component & ExpandableBlock> = [];\n private compactionBlocks: CompactionSummaryComponent[] = [];\n private branchBlocks: BranchSummaryComponent[] = [];\n private branchMessageBlocks: BranchMessageSummaryComponent[] = [];\n private customBlocks: CustomMessageComponent[] = [];\n private customMessageRenderers = new Map<string, TuiMessageRenderer>();\n private assistantMessages: AssistantMessageComponent[] = [];\n private streamingRuns = new Map<string, AssistantMessageComponent>();\n /** After finalizeAssistant, late tool execution events can still arrive; keep the bubble to link tools. */\n private assistantAnchorByRunId = new Map<string, AssistantMessageComponent>();\n private runsWithTools = new Set<string>();\n private toolsExpanded = false;\n private showThinking = true;\n private hiddenThinkingLabel = 'Thinking...';\n private toolImageOptions: ToolExecutionOptions = {};\n private lastAssistantText = '';\n private lastStatusEntry: Container | null = null;\n private lastStatusText: Text | null = null;\n private workflowStatusByRunId = new Map<string, { entry: Container; text: Text }>();\n private entryRecords: ChatLogEntryRecord[] = [];\n private viewportRowsProvider: (() => number) | undefined;\n private historyViewDisplayIndex: number | null = null;\n\n constructor(private readonly keybindings?: KeybindingsManager) {\n super();\n if (keybindings) {\n this.toolImageOptions.keybindings = keybindings;\n }\n }\n\n private pruneOverflow(): void {\n while (this.children.length > MAX_COMPONENTS) {\n const oldest = this.children[0];\n if (!oldest) return;\n this.removeChild(oldest);\n this.dropReferences(oldest);\n }\n }\n\n private dropReferences(component: Component): void {\n for (const [id, tool] of this.toolById.entries()) {\n if (tool === component) this.toolById.delete(id);\n }\n for (const [runId, msg] of this.streamingRuns.entries()) {\n if (msg === component) this.streamingRuns.delete(runId);\n }\n for (const [runId, msg] of this.assistantAnchorByRunId.entries()) {\n if (msg === component) this.assistantAnchorByRunId.delete(runId);\n }\n this.bashBlocks = this.bashBlocks.filter((entry) => entry !== component);\n this.compactionBlocks = this.compactionBlocks.filter((entry) => entry !== component);\n this.branchBlocks = this.branchBlocks.filter((entry) => entry !== component);\n this.branchMessageBlocks = this.branchMessageBlocks.filter((entry) => entry !== component);\n this.customBlocks = this.customBlocks.filter((entry) => entry !== component);\n this.assistantMessages = this.assistantMessages.filter((entry) => entry !== component);\n if (this.lastStatusEntry === component) {\n this.lastStatusEntry = null;\n this.lastStatusText = null;\n }\n for (const [runId, status] of this.workflowStatusByRunId.entries()) {\n if (status.entry === component) this.workflowStatusByRunId.delete(runId);\n }\n this.entryRecords = this.entryRecords.filter((entry) => entry.component !== component);\n if (!this.findEntryRecord(this.historyViewDisplayIndex)) {\n this.historyViewDisplayIndex = null;\n }\n }\n\n private append(component: Component, meta?: ChatLogEntryMeta): void {\n this.addChild(component);\n if (meta) {\n this.entryRecords.push({ component, ...meta });\n }\n this.pruneOverflow();\n }\n\n clearAll(): void {\n this.clear();\n this.toolById.clear();\n this.bashBlocks = [];\n this.compactionBlocks = [];\n this.branchBlocks = [];\n this.branchMessageBlocks = [];\n this.customBlocks = [];\n this.assistantMessages = [];\n this.streamingRuns.clear();\n this.assistantAnchorByRunId.clear();\n this.runsWithTools.clear();\n this.lastAssistantText = '';\n this.lastStatusEntry = null;\n this.lastStatusText = null;\n this.workflowStatusByRunId.clear();\n this.entryRecords = [];\n this.historyViewDisplayIndex = null;\n }\n\n private createAssistantMessage(message?: AgentMessage): AssistantMessageComponent {\n const component = new AssistantMessageComponent(message, {\n hideThinkingBlock: !this.showThinking,\n hiddenThinkingLabel: this.hiddenThinkingLabel,\n });\n this.assistantMessages.push(component);\n return component;\n }\n\n addSystem(text: string, meta?: ChatLogEntryMeta): void {\n const entry = new Container();\n entry.addChild(new Spacer(1));\n entry.addChild(new Text(theme.system(text), 1, 0));\n this.append(entry, meta);\n }\n\n addStatus(text: string): void {\n if (\n this.lastStatusEntry &&\n this.lastStatusText &&\n this.children[this.children.length - 1] === this.lastStatusEntry\n ) {\n this.lastStatusText.setText(theme.system(text));\n return;\n }\n\n const entry = new Container();\n const statusText = new Text(theme.system(text), 1, 0);\n entry.addChild(new Spacer(1));\n entry.addChild(statusText);\n this.lastStatusEntry = entry;\n this.lastStatusText = statusText;\n this.append(entry);\n }\n\n updateWorkflowRun(runId: string, text: string): void {\n const existing = this.workflowStatusByRunId.get(runId);\n if (existing) {\n existing.text.setText(theme.system(text));\n return;\n }\n\n const entry = new Container();\n const statusText = new Text(theme.system(text), 1, 0);\n entry.addChild(new Spacer(1));\n entry.addChild(statusText);\n this.workflowStatusByRunId.set(runId, { entry, text: statusText });\n this.append(entry);\n }\n\n addCompactionSummary(result: TuiCompactionResult): void {\n const component = new CompactionSummaryComponent(result, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.compactionBlocks.push(component);\n this.append(component);\n }\n\n addBranchSummary(summary: TuiBranchSummary): void {\n const component = new BranchSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.branchBlocks.push(component);\n this.append(component);\n }\n\n addBranchMessageSummary(summary: BranchMessageSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new BranchMessageSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.branchMessageBlocks.push(component);\n this.append(component);\n }\n\n addCustomMessage(summary: CustomMessageSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new CustomMessageComponent(\n summary,\n this.customMessageRenderers.get(summary.customType),\n );\n component.setExpanded(this.toolsExpanded);\n this.customBlocks.push(component);\n this.append(component);\n }\n\n setCustomMessageRenderer(customType: string, renderer: TuiMessageRenderer | undefined): void {\n if (renderer) {\n this.customMessageRenderers.set(customType, renderer);\n } else {\n this.customMessageRenderers.delete(customType);\n }\n for (const block of this.customBlocks) {\n if (block.matchesCustomType(customType)) {\n block.setRenderer(renderer);\n }\n }\n }\n\n addUser(text: string | unknown[], meta?: ChatLogEntryMeta): void {\n this.assistantAnchorByRunId.clear();\n this.append(new UserMessageComponent(text), meta);\n }\n\n /** Stream local `!command` output in a bordered block. */\n addBashExecution(\n command: string,\n ui: import('@earendil-works/pi-tui').TUI,\n excludeFromContext: boolean,\n ): BashExecutionComponent {\n this.assistantAnchorByRunId.clear();\n const component = new BashExecutionComponent(command, ui, excludeFromContext, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.bashBlocks.push(component);\n this.append(component);\n return component;\n }\n\n /** Replay a completed shell execution from persisted transcript history. */\n addBashSummary(summary: BashSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new BashSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.bashBlocks.push(component);\n this.append(component);\n }\n\n startAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (existing) {\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n return;\n }\n const component = this.createAssistantMessage(message);\n component.setHasToolCalls(this.runsWithTools.has(runId));\n this.streamingRuns.set(runId, component);\n this.append(component);\n }\n\n updateAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (!existing) {\n this.startAssistant(message, runId);\n return;\n }\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n }\n\n finalizeAssistant(message: AgentMessage, runId: string, meta?: ChatLogEntryMeta): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (existing) {\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n this.streamingRuns.delete(runId);\n this.assistantAnchorByRunId.set(runId, existing);\n return;\n }\n const finalMessage = this.createAssistantMessage(message);\n finalMessage.setHasToolCalls(this.runsWithTools.has(runId));\n this.append(finalMessage, meta);\n if (text.trim()) {\n this.assistantAnchorByRunId.set(runId, finalMessage);\n }\n }\n\n dropAssistant(runId: string): void {\n const existing = this.streamingRuns.get(runId);\n if (!existing) return;\n this.removeChild(existing);\n this.streamingRuns.delete(runId);\n }\n\n startTool(toolCallId: string, toolName: string, args: unknown, runId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (existing) {\n existing.setArgs(args);\n return;\n }\n this.runsWithTools.add(runId);\n const component = new ToolExecutionComponent(toolName, toolCallId, args, {\n ...this.toolImageOptions,\n });\n component.setExpanded(this.toolsExpanded);\n this.toolById.set(toolCallId, component);\n\n const assistant = this.streamingRuns.get(runId) ?? this.assistantAnchorByRunId.get(runId);\n assistant?.setHasToolCalls(true);\n this.append(component);\n }\n\n markToolExecutionStarted(toolCallId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.markExecutionStarted();\n }\n\n markToolArgsComplete(toolCallId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setArgsComplete();\n }\n\n updateToolResult(toolCallId: string, result: AgentToolResult<any> | unknown, isError: boolean, isPartial = false): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.updateResult(result, isPartial, isError);\n }\n\n updateToolDetails(toolCallId: string, details: unknown): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setPartialDetails(details);\n }\n\n updateToolArgs(toolCallId: string, args: unknown): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setArgs(args);\n }\n\n setToolsExpanded(expanded: boolean): void {\n this.toolsExpanded = expanded;\n for (const tool of this.toolById.values()) {\n tool.setExpanded(expanded);\n }\n for (const bash of this.bashBlocks) {\n bash.setExpanded(expanded);\n }\n for (const compaction of this.compactionBlocks) {\n compaction.setExpanded(expanded);\n }\n for (const branch of this.branchBlocks) {\n branch.setExpanded(expanded);\n }\n for (const branch of this.branchMessageBlocks) {\n branch.setExpanded(expanded);\n }\n for (const custom of this.customBlocks) {\n custom.setExpanded(expanded);\n }\n }\n\n setShowThinking(showThinking: boolean): void {\n this.showThinking = showThinking;\n for (const assistant of this.assistantMessages) {\n assistant.setHideThinkingBlock(!showThinking);\n }\n }\n\n setHiddenThinkingLabel(label?: string): void {\n this.hiddenThinkingLabel = label ?? 'Thinking...';\n for (const assistant of this.assistantMessages) {\n assistant.setHiddenThinkingLabel(this.hiddenThinkingLabel);\n }\n }\n\n setToolImageOptions(options: ToolExecutionOptions): void {\n this.toolImageOptions = { ...options, keybindings: this.keybindings };\n for (const tool of this.toolById.values()) {\n tool.setImageOptions(this.toolImageOptions);\n }\n }\n\n getLastAssistantText(): string {\n return this.lastAssistantText;\n }\n\n setViewportRowsProvider(provider: (() => number) | undefined): void {\n this.viewportRowsProvider = provider;\n }\n\n jumpToDisplayIndex(displayIndex: number): boolean {\n const target = this.findEntryRecord(displayIndex);\n if (!target) return false;\n this.historyViewDisplayIndex = target.displayIndex ?? null;\n return true;\n }\n\n jumpToLatest(): void {\n this.historyViewDisplayIndex = null;\n }\n\n getTimelineViewportState(): { mode: 'latest' } | { mode: 'history'; displayIndex: number } {\n if (this.historyViewDisplayIndex === null) return { mode: 'latest' };\n return { mode: 'history', displayIndex: this.historyViewDisplayIndex };\n }\n\n override render(width: number): string[] {\n const allLines: string[] = [];\n const ranges: Array<{ record: ChatLogEntryRecord; start: number; end: number }> = [];\n for (const child of this.children) {\n const start = allLines.length;\n const childLines = child.render(width);\n allLines.push(...childLines);\n const record = this.entryRecords.find((entry) => entry.component === child);\n if (record) {\n ranges.push({ record, start, end: allLines.length });\n }\n }\n\n if (this.historyViewDisplayIndex === null) return allLines;\n\n const target = this.findEntryRecord(this.historyViewDisplayIndex);\n const range = target\n ? ranges.find((candidate) => candidate.record.component === target.component)\n : undefined;\n if (!range) {\n this.historyViewDisplayIndex = null;\n return allLines;\n }\n\n const viewportRows = Math.max(8, Math.floor(this.viewportRowsProvider?.() ?? 24));\n const start = Math.max(0, range.start - 1);\n const end = Math.min(allLines.length, start + Math.max(1, viewportRows - 1));\n return [\n theme.dim('Viewing previous transcript - /timeline latest returns to live view.'),\n ...allLines.slice(start, end),\n ];\n }\n\n private findEntryRecord(displayIndex: number | null): ChatLogEntryRecord | undefined {\n if (displayIndex === null || !Number.isFinite(displayIndex)) return undefined;\n return this.entryRecords.find((entry) => entry.displayIndex === displayIndex);\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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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ClientHistoryMessage } from '../session/client-history.js';
|
|
2
|
+
import type { SessionTimelineItem } from '../session/transcript-outline.js';
|
|
2
3
|
import type { ExportFormat } from '../session/types.js';
|
|
3
4
|
import type { ReviewContext } from '../review/review-git.js';
|
|
4
5
|
import type { SessionInfo, TuiEventSource } from './tui-types.js';
|
|
@@ -62,6 +63,12 @@ export interface TuiSessionStats {
|
|
|
62
63
|
total: number;
|
|
63
64
|
};
|
|
64
65
|
}
|
|
66
|
+
export interface TuiHistoryWindow {
|
|
67
|
+
messages: HistoryMessage[];
|
|
68
|
+
startRowNumber: number;
|
|
69
|
+
endRowNumber: number;
|
|
70
|
+
totalRows: number;
|
|
71
|
+
}
|
|
65
72
|
export type TuiExportFormat = ExportFormat | 'html';
|
|
66
73
|
export interface TuiCompactionResult {
|
|
67
74
|
compacted: boolean;
|
|
@@ -223,8 +230,17 @@ export interface TuiBackend {
|
|
|
223
230
|
}): Promise<{
|
|
224
231
|
messages: HistoryMessage[];
|
|
225
232
|
}>;
|
|
233
|
+
/** Load a bounded transcript window around a persisted row number. */
|
|
234
|
+
loadHistoryWindow?(opts: {
|
|
235
|
+
sessionKey: string;
|
|
236
|
+
rowNumber: number;
|
|
237
|
+
before?: number;
|
|
238
|
+
after?: number;
|
|
239
|
+
}): Promise<TuiHistoryWindow>;
|
|
226
240
|
/** Load current transcript rows as a tree-shaped list. */
|
|
227
241
|
loadTranscriptTree(sessionKey: string): Promise<TuiTranscriptTreeEntry[]>;
|
|
242
|
+
/** Load current transcript rows as timeline items for turn navigation. */
|
|
243
|
+
loadTimeline(sessionKey: string): Promise<SessionTimelineItem[]>;
|
|
228
244
|
/** Compute transcript message/token statistics. */
|
|
229
245
|
getSessionStats(sessionKey: string): Promise<TuiSessionStats>;
|
|
230
246
|
/** List sessions. */
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { parseAgentSessionKey } from "../routing/session-key-utils.js";
|
|
2
|
-
import { init_agent_session_key } from "../routing/agent-session-key.js";
|
|
3
1
|
import { getLogDir } from "../utils/logger/config.js";
|
|
4
2
|
import { getRuntimeLogStats } from "../utils/logger/stats.js";
|
|
5
3
|
import { init_logger } from "../utils/logger.js";
|
|
4
|
+
import { parseAgentSessionKey } from "../routing/session-key-utils.js";
|
|
5
|
+
import { init_agent_session_key } from "../routing/agent-session-key.js";
|
|
6
6
|
import { resolveConfigPath } from "../config/paths.js";
|
|
7
7
|
import { getProviderDisplayName, getSortedProviders, init_providers, providerSupportsApiKey, providerSupportsOAuth } from "../providers/index.js";
|
|
8
8
|
import { createWorkflowCatalog } from "../agent/workflow/catalog.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { KeybindingsManager, TUI } from '@earendil-works/pi-tui';
|
|
2
2
|
import type { TuiCompactionResult, TuiModelChoice, TuiShareRequest, TuiSessionStats, TuiSessionItem, TuiStartupResources, TuiTranscriptTreeEntry, TuiAgentInfo } from './tui-backend.js';
|
|
3
3
|
import type { ChatLog } from './components/chat-log.js';
|
|
4
|
+
import type { SessionTimelineItem } from '../session/transcript-outline.js';
|
|
4
5
|
import { type TuiHotkeyExtensionShortcut } from './format-tui-hotkeys.js';
|
|
5
6
|
import type { TuiState } from './tui-types.js';
|
|
6
7
|
import { type ReasoningLevel, type ThinkLevel, type VerboseLevel } from '../agent/transcript/thinking-types.js';
|
|
@@ -37,6 +38,7 @@ export type CommandHandlerDeps = {
|
|
|
37
38
|
openSessionPicker: () => void;
|
|
38
39
|
openSessionTree: () => void;
|
|
39
40
|
openTranscriptTree: () => void;
|
|
41
|
+
openTimeline: (initialSearch?: string) => void;
|
|
40
42
|
openUserMessageFork: () => void;
|
|
41
43
|
openScopedModels: () => void;
|
|
42
44
|
openThinkingSelector: () => void;
|
|
@@ -63,6 +65,13 @@ export type CommandHandlerDeps = {
|
|
|
63
65
|
getSessionStats?: () => TuiSessionStats | Promise<TuiSessionStats>;
|
|
64
66
|
getStartupResources?: () => TuiStartupResources | undefined;
|
|
65
67
|
loadTranscriptTree?: () => TuiTranscriptTreeEntry[] | Promise<TuiTranscriptTreeEntry[]>;
|
|
68
|
+
loadTimeline?: () => SessionTimelineItem[] | Promise<SessionTimelineItem[]>;
|
|
69
|
+
loadHistoryWindow?: (opts: {
|
|
70
|
+
rowNumber: number;
|
|
71
|
+
before?: number;
|
|
72
|
+
after?: number;
|
|
73
|
+
}) => boolean | Promise<boolean>;
|
|
74
|
+
loadSessionHistory?: () => void | Promise<void>;
|
|
66
75
|
exportSession?: (request: TuiExportRequest) => void | Promise<void>;
|
|
67
76
|
importSession?: (request: TuiImportRequest) => void | Promise<void>;
|
|
68
77
|
createShare?: (request: TuiShareRequest) => void | Promise<void>;
|