@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
|
@@ -6,11 +6,13 @@ import { searchableSelectListTheme, theme } from "./theme.js";
|
|
|
6
6
|
import { formatKeyIds } from "./format-tui-hotkeys.js";
|
|
7
7
|
import { formatSessionPickerDescription } from "./tui-session-format.js";
|
|
8
8
|
import { filterTuiTranscriptTreeEntries } from "./tui-transcript-tree.js";
|
|
9
|
+
import { buildTuiTimelineTurns } from "./tui-timeline.js";
|
|
9
10
|
import { SearchableSelectList } from "./components/searchable-select-list.js";
|
|
10
11
|
import { ScopedModelsSelector } from "./components/scoped-models-selector.js";
|
|
11
12
|
import { SettingsSelector } from "./components/settings-selector.js";
|
|
12
13
|
import { SessionSelector } from "./components/session-selector.js";
|
|
13
14
|
import { ThinkingSelector } from "./components/thinking-selector.js";
|
|
15
|
+
import { TimelineSelectList, formatTimelineOpenedHint } from "./tui-timeline-picker.js";
|
|
14
16
|
import { TranscriptTreeSelectList, defaultTranscriptForkKey, formatTranscriptTreeFilterHint, formatUserMessageForkOpenedHint, userMessageForkSelectItems } from "./tui-transcript-tree-picker.js";
|
|
15
17
|
//#region src/tui/tui-picker-overlay.ts
|
|
16
18
|
init_agent_session_key();
|
|
@@ -61,6 +63,39 @@ function agentSelectItems(agents, currentAgentId) {
|
|
|
61
63
|
function formatSessionTreeOpenedHint(keybindings) {
|
|
62
64
|
return `Session tree (${formatSelectNavigationHint(keybindings)} · type to filter · ${formatKeyIds(keybindings, "tui.select.confirm", { capitalize: true })} resume · ${formatKeyIds(keybindings, "tui.select.cancel", { capitalize: true })} close)`;
|
|
63
65
|
}
|
|
66
|
+
async function openTimelineOverlay(svc, initialQuery) {
|
|
67
|
+
const turns = buildTuiTimelineTurns(await svc.client.loadTimeline(svc.state.currentSessionKey));
|
|
68
|
+
if (turns.length === 0) {
|
|
69
|
+
svc.chatLog.addSystem("No timeline turns found.");
|
|
70
|
+
svc.tui.requestRender();
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const viewState = svc.chatLog.getTimelineViewportState();
|
|
74
|
+
const activeDisplayIndex = viewState.mode === "history" ? viewState.displayIndex : turns[turns.length - 1]?.displayIndex;
|
|
75
|
+
const list = new TimelineSelectList(turns, {
|
|
76
|
+
keybindings: svc.keybindings,
|
|
77
|
+
...activeDisplayIndex !== void 0 ? { activeDisplayIndex } : {},
|
|
78
|
+
...initialQuery ? { initialQuery } : {}
|
|
79
|
+
});
|
|
80
|
+
list.onSelect = (turn) => {
|
|
81
|
+
svc.closeOverlay();
|
|
82
|
+
svc.tui.setFocus(svc.editor);
|
|
83
|
+
(async () => {
|
|
84
|
+
if (!svc.chatLog.jumpToDisplayIndex(turn.displayIndex)) {
|
|
85
|
+
if (!(turn.rowNumber !== void 0 ? await svc.loadHistoryWindow({ rowNumber: turn.rowNumber }) : false) || !svc.chatLog.jumpToDisplayIndex(turn.displayIndex)) svc.chatLog.addSystem(`Turn ${turn.turn} is outside loaded history.`);
|
|
86
|
+
}
|
|
87
|
+
svc.tui.requestRender();
|
|
88
|
+
})();
|
|
89
|
+
};
|
|
90
|
+
list.onCancel = () => {
|
|
91
|
+
svc.closeOverlay();
|
|
92
|
+
svc.tui.setFocus(svc.editor);
|
|
93
|
+
svc.tui.requestRender();
|
|
94
|
+
};
|
|
95
|
+
svc.openOverlay(list);
|
|
96
|
+
svc.chatLog.addSystem(theme.dim(formatTimelineOpenedHint(svc.keybindings)));
|
|
97
|
+
svc.tui.requestRender();
|
|
98
|
+
}
|
|
64
99
|
function resumeSession(svc, sessionKey) {
|
|
65
100
|
svc.setSessionKey(sessionKey);
|
|
66
101
|
svc.clearChatForSessionSwitch();
|
|
@@ -596,6 +631,6 @@ function openProjectTrustOverlay(svc) {
|
|
|
596
631
|
svc.tui.requestRender();
|
|
597
632
|
}
|
|
598
633
|
//#endregion
|
|
599
|
-
export { formatAgentPickerOpenedHint, formatProjectTrustOpenedHint, formatReviewPickerOpenedHint, formatScopedModelsOpenedHint, formatScopedModelsSavedHint, formatSessionTreeOpenedHint, formatSettingsOpenedHint, formatThinkingLevelSavedHint, formatThinkingSelectorHint, openAgentPickerOverlay, openProjectTrustOverlay, openReviewLauncherOverlay, openScopedModelsOverlay, openSessionPickerOverlay, openSessionTreeOverlay, openSettingsOverlay, openThinkingSelectorOverlay, openTranscriptTreeOverlay, openUserMessageForkOverlay, sessionTreeSelectItems };
|
|
634
|
+
export { formatAgentPickerOpenedHint, formatProjectTrustOpenedHint, formatReviewPickerOpenedHint, formatScopedModelsOpenedHint, formatScopedModelsSavedHint, formatSessionTreeOpenedHint, formatSettingsOpenedHint, formatThinkingLevelSavedHint, formatThinkingSelectorHint, openAgentPickerOverlay, openProjectTrustOverlay, openReviewLauncherOverlay, openScopedModelsOverlay, openSessionPickerOverlay, openSessionTreeOverlay, openSettingsOverlay, openThinkingSelectorOverlay, openTimelineOverlay, openTranscriptTreeOverlay, openUserMessageForkOverlay, sessionTreeSelectItems };
|
|
600
635
|
|
|
601
636
|
//# sourceMappingURL=tui-picker-overlay.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui-picker-overlay.js","names":[],"sources":["../../../src/tui/tui-picker-overlay.ts"],"sourcesContent":["import type { KeybindingsManager, SelectItem } from '@earendil-works/pi-tui';\n\nimport { ScopedModelsSelector } from './components/scoped-models-selector.js';\nimport { SettingsSelector } from './components/settings-selector.js';\nimport { SearchableSelectList } from './components/searchable-select-list.js';\nimport { SessionSelector } from './components/session-selector.js';\nimport { ThinkingSelector } from './components/thinking-selector.js';\nimport { formatKeyIds } from './format-tui-hotkeys.js';\nimport type { TuiAgentInfo, TuiSessionItem } from './tui-backend.js';\nimport type { PickerServices } from './tui-picker-services.js';\nimport { formatSessionPickerDescription } from './tui-session-format.js';\nimport { searchableSelectListTheme, theme } from './theme.js';\nimport { filterTuiTranscriptTreeEntries } from './tui-transcript-tree.js';\nimport {\n defaultTranscriptForkKey,\n formatTranscriptTreeFilterHint,\n formatUserMessageForkOpenedHint,\n TranscriptTreeSelectList,\n userMessageForkSelectItems,\n} from './tui-transcript-tree-picker.js';\nimport {\n listThinkingLevels,\n normalizeThinkLevel,\n type ThinkLevel,\n} from '../agent/transcript/thinking-types.js';\nimport { parseAgentSessionKey } from '../routing/agent-session-key.js';\nimport {\n getProjectTrustOptions,\n hasTrustRequiringProjectResources,\n} from '../project-trust/trust-store.js';\nimport type { ReviewContext } from '../review/review-git.js';\n\ntype SearchableSelectItem = SelectItem & { searchText?: string };\n\nfunction formatSelectNavigationHint(keybindings: KeybindingsManager): string {\n const up = formatKeyIds(keybindings, 'tui.select.up', { capitalize: true });\n const down = formatKeyIds(keybindings, 'tui.select.down', { capitalize: true });\n return `${up}/${down}`;\n}\n\nexport function formatScopedModelsOpenedHint(keybindings: KeybindingsManager): string {\n const modelCycle = formatKeyIds(keybindings, 'app.model.cycleForward', { capitalize: true });\n return `Scoped models for ${modelCycle}`;\n}\n\nexport function formatScopedModelsSavedHint(params: {\n refs: string[] | null;\n total: number;\n keybindings: KeybindingsManager;\n}): string {\n const modelCycle = formatKeyIds(params.keybindings, 'app.model.cycleForward', {\n capitalize: true,\n });\n if (params.refs === null) {\n return `${modelCycle} cycles all ${params.total} models`;\n }\n const count = params.refs.length;\n return `${modelCycle} cycles ${count} scoped model${count === 1 ? '' : 's'}`;\n}\n\nexport function formatSettingsOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Settings (${nav} · ${confirm} toggle · ${cancel} close)`;\n}\n\nexport function formatThinkingSelectorHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Thinking level (${nav} · ${confirm} select · ${cancel} close)`;\n}\n\nexport function formatThinkingLevelSavedHint(level: ThinkLevel): string {\n return `Thinking level: ${level}`;\n}\n\nexport function formatProjectTrustOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Project trust (${nav} · ${confirm} select · ${cancel} close)`;\n}\n\nexport function formatReviewPickerOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Review (${nav} · type to filter · ${confirm} select · ${cancel} close)`;\n}\n\nexport function formatAgentPickerOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Switch agent (${nav} · ${confirm} select · ${cancel} close)`;\n}\n\nfunction agentSelectItems(agents: TuiAgentInfo[], currentAgentId?: string): SelectItem[] {\n const current = currentAgentId?.trim().toLowerCase();\n return [...agents]\n .filter((agent) => agent.enabled !== false)\n .sort((a, b) => {\n if (a.id === current && b.id !== current) return -1;\n if (b.id === current && a.id !== current) return 1;\n if (a.id === 'coder' && b.id !== 'coder') return -1;\n if (b.id === 'coder' && a.id !== 'coder') return 1;\n return a.id.localeCompare(b.id);\n })\n .map((agent) => ({\n label: agent.id === current ? `${agent.id} (current)` : agent.id,\n value: agent.id,\n description: agent.displayName,\n }));\n}\n\nexport function formatSessionTreeOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Session tree (${nav} · type to filter · ${confirm} resume · ${cancel} close)`;\n}\n\nfunction resumeSession(svc: PickerServices, sessionKey: string): void {\n svc.setSessionKey(sessionKey);\n svc.clearChatForSessionSwitch();\n svc.chatLog.addSystem(`Session: ${sessionKey}`);\n void svc\n .refreshSessionInfo()\n .then(() => svc.loadSessionHistory())\n .then(() => {\n svc.updateHeader();\n svc.tui.requestRender();\n });\n svc.tui.requestRender();\n}\n\nfunction sessionTreeGroup(session: TuiSessionItem): { agentId: string; root: string; leaf: string } {\n const raw = session.key.trim();\n const parts = raw.split(':').filter(Boolean);\n if (parts.length >= 3 && parts[0] === 'agent') {\n const rest = parts.slice(2);\n return {\n agentId: parts[1] ?? 'main',\n root: rest[0] ?? raw,\n leaf: rest.length > 1 ? rest.slice(1).join(':') : rest.join(':') || raw,\n };\n }\n return { agentId: 'legacy', root: raw || 'session', leaf: raw || 'session' };\n}\n\nexport function sessionTreeSelectItems(\n sessions: TuiSessionItem[],\n currentSessionKey?: string,\n): SelectItem[] {\n const byKey = new Map(sessions.map((session) => [session.key, session]));\n return [...sessions]\n .sort((a, b) => {\n const ga = sessionTreeGroup(a);\n const gb = sessionTreeGroup(b);\n const groupCmp = `${ga.agentId}:${ga.root}`.localeCompare(`${gb.agentId}:${gb.root}`);\n if (groupCmp !== 0) return groupCmp;\n return (b.updatedAt ?? 0) - (a.updatedAt ?? 0);\n })\n .map((session) => {\n const group = sessionTreeGroup(session);\n const current = session.key === currentSessionKey ? '* ' : ' ';\n const label = session.displayName?.trim() || group.leaf;\n const parent = session.forkedFromSessionKey\n ? (byKey.get(session.forkedFromSessionKey)?.displayName?.trim() ?? session.forkedFromSessionKey)\n : null;\n const description = [\n `${group.agentId}/${group.root}`,\n formatSessionPickerDescription(session, { showKey: Boolean(session.displayName) }),\n parent ? `forked from ${parent}` : '',\n ]\n .filter(Boolean)\n .join(' · ');\n return {\n value: session.key,\n label: `${current}${label}`,\n description,\n searchText: `${session.key} ${session.displayName ?? ''} ${session.model ?? ''} ${parent ?? ''}`,\n };\n });\n}\n\n\n\n\n\nexport async function openAgentPickerOverlay(svc: PickerServices): Promise<void> {\n const parsed = parseAgentSessionKey(svc.state.currentSessionKey);\n if (!parsed) {\n svc.chatLog.addSystem('Cannot switch agent: current session is not an agent session.');\n svc.tui.requestRender();\n return;\n }\n if (svc.state.activeRunId) {\n svc.chatLog.addSystem('Cannot switch agent while a run is active. Abort first.');\n svc.tui.requestRender();\n return;\n }\n if (!svc.switchAgentSession) {\n svc.chatLog.addSystem('Agent switching is not available in this mode.');\n svc.tui.requestRender();\n return;\n }\n const agents = await svc.client.listAgents();\n const items = agentSelectItems(agents, parsed.agentId);\n if (items.length === 0) {\n svc.chatLog.addSystem('No agents available.');\n svc.tui.requestRender();\n return;\n }\n svc.chatLog.addSystem(theme.dim(formatAgentPickerOpenedHint(svc.keybindings)));\n const list = new SearchableSelectList(items, Math.min(10, items.length), searchableSelectListTheme, {\n searchPromptText: 'agent> ',\n });\n const closeSelector = svc.openEditorSelector(list, list);\n list.onSelect = (item) => {\n closeSelector();\n const targetAgentId = item.value;\n if (targetAgentId === parsed.agentId) {\n svc.chatLog.addSystem(`Already using agent: ${targetAgentId}`);\n svc.tui.requestRender();\n return;\n }\n const targetSessionKey = `agent:${targetAgentId}:${parsed.rest}`;\n void Promise.resolve(svc.switchAgentSession?.(targetSessionKey, targetAgentId))\n .then(() => {\n svc.chatLog.addSystem(`Switched to agent: ${targetAgentId}\\nSession: ${targetSessionKey}`);\n })\n .catch((err: unknown) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Agent switch failed: ${errorMessage}`);\n })\n .finally(() => svc.tui.requestRender());\n svc.tui.requestRender();\n };\n list.onCancel = () => closeSelector();\n svc.tui.requestRender();\n}\n\nfunction quoteReviewArg(value: string): string {\n return /^[A-Za-z0-9._/@:-]+$/.test(value) ? value : JSON.stringify(value);\n}\n\nfunction formatReviewStatus(status: ReviewContext['status']): string {\n if (status.isClean) return 'working tree clean';\n const parts: string[] = [];\n if (status.changedFiles > 0) parts.push(`${status.changedFiles} changed`);\n if (status.untrackedFiles > 0) parts.push(`${status.untrackedFiles} untracked`);\n return parts.join(', ');\n}\n\nfunction reviewPresetItems(context: ReviewContext): SearchableSelectItem[] {\n return [\n {\n value: 'base',\n label: 'Review against a base branch',\n description: context.defaultBaseBranch ? `PR Style · default ${context.defaultBaseBranch}` : 'PR Style',\n searchText: 'pr pull request base branch merge base',\n },\n {\n value: 'uncommitted',\n label: 'Review uncommitted changes',\n description: formatReviewStatus(context.status),\n searchText: 'workspace working tree uncommitted diff status',\n },\n {\n value: 'commit',\n label: 'Review a commit',\n description: context.commits.length > 0 ? `${context.commits.length} recent commits` : 'no commits found',\n searchText: 'commit sha history log',\n },\n {\n value: 'custom',\n label: 'Custom review instructions',\n description: 'edit prompt before sending',\n searchText: 'custom instructions focus prompt',\n },\n ];\n}\n\nfunction branchSelectItems(context: ReviewContext): SelectItem[] {\n return context.branches\n .filter((branch) => !branch.current)\n .map((branch) => ({\n value: branch.name,\n label: branch.name,\n description: [\n branch.name === context.defaultBaseBranch ? 'default' : '',\n branch.remote ? 'remote' : 'local',\n ].filter(Boolean).join(' · '),\n searchText: branch.name,\n }));\n}\n\nfunction commitSelectItems(context: ReviewContext): SelectItem[] {\n return context.commits.map((commit) => ({\n value: commit.sha,\n label: commit.subject,\n description: [commit.shortSha, commit.date?.slice(0, 10)].filter(Boolean).join(' · '),\n searchText: `${commit.sha} ${commit.shortSha} ${commit.subject}`,\n }));\n}\n\nfunction openReviewBranchSelector(svc: PickerServices, context: ReviewContext): void {\n const items = branchSelectItems(context);\n if (items.length === 0) {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.chatLog.addSystem('No base branches available for review.');\n svc.tui.requestRender();\n return;\n }\n const list = new SearchableSelectList(items, Math.min(10, items.length), searchableSelectListTheme, {\n searchPromptText: 'branch> ',\n });\n const defaultIndex = context.defaultBaseBranch\n ? items.findIndex((item) => item.value === context.defaultBaseBranch)\n : -1;\n if (defaultIndex >= 0) list.setSelectedIndex(defaultIndex);\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.sendMessage(`/review --base ${quoteReviewArg(item.value)}`);\n };\n list.onCancel = () => {\n openReviewPresetSelector(svc, context);\n };\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim('Select a base branch to review'));\n svc.tui.requestRender();\n}\n\nfunction openReviewCommitSelector(svc: PickerServices, context: ReviewContext): void {\n const items = commitSelectItems(context);\n if (items.length === 0) {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.chatLog.addSystem('No commits available for review.');\n svc.tui.requestRender();\n return;\n }\n const list = new SearchableSelectList(items, Math.min(12, items.length), searchableSelectListTheme, {\n searchPromptText: 'commit> ',\n });\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.sendMessage(`/review --commit ${item.value}`);\n };\n list.onCancel = () => {\n openReviewPresetSelector(svc, context);\n };\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim('Select a commit to review'));\n svc.tui.requestRender();\n}\n\nfunction openReviewPresetSelector(svc: PickerServices, context: ReviewContext): void {\n const items = reviewPresetItems(context);\n const list = new SearchableSelectList(items, Math.min(8, items.length), searchableSelectListTheme, {\n searchPromptText: 'review> ',\n });\n list.onSelect = (item) => {\n if (item.value === 'uncommitted') {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.sendMessage('/review --uncommitted');\n return;\n }\n if (item.value === 'custom') {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.setEditorText('/review --custom ');\n svc.tui.requestRender();\n return;\n }\n if (item.value === 'base') {\n openReviewBranchSelector(svc, context);\n return;\n }\n if (item.value === 'commit') {\n openReviewCommitSelector(svc, context);\n }\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatReviewPickerOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\nexport async function openReviewLauncherOverlay(svc: PickerServices): Promise<void> {\n if (!svc.client.getReviewContext) {\n svc.chatLog.addSystem('Review picker is not available in this mode. Use /review --uncommitted, /review --base <branch>, or /review --commit <sha>.');\n svc.tui.requestRender();\n return;\n }\n let context: ReviewContext;\n try {\n context = await svc.client.getReviewContext(svc.state.currentSessionKey);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Review picker failed: ${errorMessage}`);\n svc.tui.requestRender();\n return;\n }\n openReviewPresetSelector(svc, context);\n}\n\n/** Ctrl+Shift+P — session picker with rename/delete. */\nexport async function openSessionPickerOverlay(svc: PickerServices): Promise<void> {\n const sessions = await svc.client.listSessions();\n if (sessions.length === 0) {\n svc.chatLog.addSystem('No sessions listed.');\n svc.tui.requestRender();\n return;\n }\n\n const selector = new SessionSelector(\n sessions,\n {\n onResume: (sessionKey) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n resumeSession(svc, sessionKey);\n },\n onRename: async (sessionKey, name) => {\n const result = await svc.client.renameSession(sessionKey, name);\n return result.ok ? { ok: true } : { ok: false, error: 'Rename failed' };\n },\n onDelete: async (sessionKey) => {\n if (sessionKey === svc.state.currentSessionKey) {\n return { ok: false, error: 'Switch away before deleting the active session' };\n }\n const result = await svc.client.deleteSession(sessionKey);\n return result.ok ? { ok: true } : { ok: false, error: 'Delete failed' };\n },\n onCancel: () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n requestRender: () => svc.tui.requestRender(),\n },\n svc.keybindings,\n sessions.find((s) => s.key === svc.state.currentSessionKey)?.cwd ?? process.cwd(),\n svc.state.currentSessionKey,\n );\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim('Session picker'));\n svc.tui.requestRender();\n}\n\n/** Searchable session tree navigation overlay. */\nexport async function openSessionTreeOverlay(svc: PickerServices): Promise<void> {\n const sessions = await svc.client.listSessions();\n if (sessions.length === 0) {\n svc.chatLog.addSystem('No sessions listed.');\n svc.tui.requestRender();\n return;\n }\n\n const items = sessionTreeSelectItems(sessions, svc.state.currentSessionKey);\n const list = new SearchableSelectList(items, Math.min(14, items.length), searchableSelectListTheme);\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n resumeSession(svc, item.value);\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatSessionTreeOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** Searchable current-transcript tree overlay. */\nexport async function openTranscriptTreeOverlay(svc: PickerServices): Promise<void> {\n const entries = await svc.client.loadTranscriptTree(svc.state.currentSessionKey);\n const filterMode = svc.getTuiSettings().treeFilterMode;\n const visibleEntries = filterTuiTranscriptTreeEntries(entries, filterMode);\n if (visibleEntries.length === 0) {\n svc.chatLog.addSystem('No transcript entries found.');\n svc.tui.requestRender();\n return;\n }\n\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n const list = new TranscriptTreeSelectList(entries, filterMode, svc.keybindings, Math.min(16, visibleEntries.length));\n list.onSelect = (item) => {\n const entry = byId.get(item.value);\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n if (!entry) {\n svc.tui.requestRender();\n return;\n }\n const targetKey = defaultTranscriptForkKey(svc.state.currentSessionKey, entry.id);\n const sourceSessionKey = svc.state.currentSessionKey;\n svc.chatLog.addSystem(theme.dim(`Forking transcript at ${entry.id}...`));\n void svc.client\n .forkSessionAt(sourceSessionKey, targetKey, entry.id)\n .then((result) => {\n resumeSession(svc, result.sessionKey);\n svc.chatLog.addBranchSummary({\n sourceSessionKey,\n targetSessionKey: result.sessionKey,\n rowCount: result.rowCount,\n entryId: entry.id,\n });\n })\n .catch((err) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Fork failed: ${errorMessage}`);\n svc.tui.requestRender();\n });\n svc.tui.requestRender();\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n list.onFilterChange = (mode) => {\n svc.chatLog.addSystem(theme.dim(`Transcript tree filter: ${mode}`));\n svc.tui.requestRender();\n };\n list.onLabelSubmit = (entry, label) => {\n void svc.client\n .setTranscriptLabel(svc.state.currentSessionKey, entry.id, label)\n .then(() => {\n list.updateEntryLabel(entry.id, label);\n svc.chatLog.addSystem(\n theme.dim(label?.trim() ? `Labeled ${entry.id}: ${label.trim()}` : `Cleared label for ${entry.id}`),\n );\n svc.tui.requestRender();\n })\n .catch((err) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Label failed: ${errorMessage}`);\n svc.tui.requestRender();\n });\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatTranscriptTreeFilterHint(svc.keybindings, filterMode)));\n svc.tui.requestRender();\n}\n\n/** Pi-style `/fork` overlay: select a previous user message and branch there. */\nexport async function openUserMessageForkOverlay(svc: PickerServices): Promise<void> {\n const entries = await svc.client.loadTranscriptTree(svc.state.currentSessionKey);\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n const items = userMessageForkSelectItems(entries);\n if (items.length === 0) {\n svc.chatLog.addSystem('No messages to fork from.');\n svc.tui.requestRender();\n return;\n }\n\n const list = new SearchableSelectList(items, Math.min(10, items.length), searchableSelectListTheme, {\n wrapNavigation: true,\n });\n list.setSelectedIndex(items.length - 1);\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n const entry = byId.get(item.value);\n const targetKey = defaultTranscriptForkKey(svc.state.currentSessionKey, item.value);\n const sourceSessionKey = svc.state.currentSessionKey;\n svc.chatLog.addSystem(theme.dim(`Forking from ${item.value}...`));\n void svc.client\n .forkSessionAt(sourceSessionKey, targetKey, item.value)\n .then((result) => {\n resumeSession(svc, result.sessionKey);\n if (entry?.contentText) {\n svc.setEditorText(entry.contentText);\n }\n svc.chatLog.addBranchSummary({\n sourceSessionKey,\n targetSessionKey: result.sessionKey,\n rowCount: result.rowCount,\n entryId: item.value,\n restoredText: entry?.contentText,\n });\n })\n .catch((err) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Fork failed: ${errorMessage}`);\n svc.tui.requestRender();\n });\n svc.tui.requestRender();\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatUserMessageForkOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** `/scoped-models` — limit Ctrl+P model cycle set. */\nexport async function openScopedModelsOverlay(svc: PickerServices): Promise<void> {\n const catalog = await svc.client.listModels();\n svc.setModelChoices(catalog);\n if (catalog.length === 0) {\n svc.chatLog.addSystem('No models available.');\n svc.tui.requestRender();\n return;\n }\n\n const selector = new ScopedModelsSelector(\n catalog,\n svc.getScopedModelRefs(),\n {\n onSave: (refs) => {\n svc.setScopedModelRefs(refs);\n svc.refreshCycleModels();\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.chatLog.addSystem(\n theme.dim(formatScopedModelsSavedHint({\n refs,\n total: catalog.length,\n keybindings: svc.keybindings,\n })),\n );\n svc.tui.requestRender();\n },\n onCancel: () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n requestRender: () => svc.tui.requestRender(),\n },\n svc.keybindings,\n );\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim(formatScopedModelsOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** `/settings` — TUI preferences overlay. */\nexport function openSettingsOverlay(svc: PickerServices): void {\n const selector = new SettingsSelector(svc.getTuiSettings(), {\n onChange: (settings) => svc.applyTuiSettings(settings),\n onThemePreview: (themeId) => svc.previewTheme(themeId),\n onReloadKeybindings: () => svc.reloadKeybindings(),\n onCancel: () => {\n svc.previewTheme(svc.getTuiSettings().theme);\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n });\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim(formatSettingsOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** `/think` — select and persist the current session thinking level. */\nexport function openThinkingSelectorOverlay(svc: PickerServices): void {\n const current = normalizeThinkLevel(svc.state.sessionInfo.thinkingLevel) ?? 'medium';\n const levels = listThinkingLevels(\n svc.state.sessionInfo.modelProvider,\n svc.state.sessionInfo.model,\n ).map((level) => (level === 'on' ? 'low' : level)) as ThinkLevel[];\n const uniqueLevels = [...new Set(levels)];\n\n const selector = new ThinkingSelector(current, uniqueLevels, {\n onSelect: (level) => {\n void svc.setThinkingLevel(level).then(() => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n });\n },\n onCancel: () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n }, svc.keybindings);\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim(formatThinkingSelectorHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\nexport function openProjectTrustOverlay(svc: PickerServices): void {\n const cwd = process.cwd();\n const trustStore = svc.getProjectTrustStore();\n const currentStored = trustStore.getEntry(cwd);\n const sessionDecision = svc.getProjectTrustSessionDecision();\n const hasProjectResources = hasTrustRequiringProjectResources(cwd);\n const options = getProjectTrustOptions(cwd, { includeSessionOnly: true });\n const optionsByLabel = new Map(options.map((option) => [option.label, option]));\n const items: SelectItem[] = options.map((option) => ({\n value: option.label,\n label: option.label,\n description: option.savedPath ?? 'Current TUI session only',\n }));\n const list = new SearchableSelectList(items, Math.min(8, items.length), searchableSelectListTheme, {\n searchPromptText: 'trust: ',\n });\n\n list.onSelect = (item) => {\n const selected = optionsByLabel.get(item.value);\n if (!selected) return;\n if (selected.updates.length > 0) {\n trustStore.setMany(selected.updates);\n svc.setProjectTrustSessionDecision(null);\n } else {\n svc.setProjectTrustSessionDecision(selected.trusted);\n }\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n const scope = selected.savedPath ? `saved for ${selected.savedPath}` : 'this session only';\n svc.chatLog.addSystem(theme.dim(`Project trust: ${selected.trusted ? 'trusted' : 'not trusted'} (${scope})`));\n svc.tui.requestRender();\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n const storedLabel = currentStored\n ? `${currentStored.decision ? 'trusted' : 'not trusted'} from ${currentStored.path}`\n : 'not saved';\n const sessionLabel = sessionDecision === null ? 'none' : sessionDecision ? 'trusted' : 'not trusted';\n svc.chatLog.addSystem(\n theme.dim(\n [\n formatProjectTrustOpenedHint(svc.keybindings),\n `Project resources: ${hasProjectResources ? 'detected' : 'none detected'}`,\n `Stored: ${storedLabel}`,\n `Session: ${sessionLabel}`,\n ].join('\\n'),\n ),\n );\n svc.tui.requestRender();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tui-picker-overlay.js","names":[],"sources":["../../../src/tui/tui-picker-overlay.ts"],"sourcesContent":["import type { KeybindingsManager, SelectItem } from '@earendil-works/pi-tui';\n\nimport { ScopedModelsSelector } from './components/scoped-models-selector.js';\nimport { SettingsSelector } from './components/settings-selector.js';\nimport { SearchableSelectList } from './components/searchable-select-list.js';\nimport { SessionSelector } from './components/session-selector.js';\nimport { ThinkingSelector } from './components/thinking-selector.js';\nimport { formatKeyIds } from './format-tui-hotkeys.js';\nimport type { TuiAgentInfo, TuiSessionItem } from './tui-backend.js';\nimport type { PickerServices } from './tui-picker-services.js';\nimport { formatSessionPickerDescription } from './tui-session-format.js';\nimport { searchableSelectListTheme, theme } from './theme.js';\nimport { buildTuiTimelineTurns } from './tui-timeline.js';\nimport {\n formatTimelineOpenedHint,\n TimelineSelectList,\n} from './tui-timeline-picker.js';\nimport { filterTuiTranscriptTreeEntries } from './tui-transcript-tree.js';\nimport {\n defaultTranscriptForkKey,\n formatTranscriptTreeFilterHint,\n formatUserMessageForkOpenedHint,\n TranscriptTreeSelectList,\n userMessageForkSelectItems,\n} from './tui-transcript-tree-picker.js';\nimport {\n listThinkingLevels,\n normalizeThinkLevel,\n type ThinkLevel,\n} from '../agent/transcript/thinking-types.js';\nimport { parseAgentSessionKey } from '../routing/agent-session-key.js';\nimport {\n getProjectTrustOptions,\n hasTrustRequiringProjectResources,\n} from '../project-trust/trust-store.js';\nimport type { ReviewContext } from '../review/review-git.js';\n\ntype SearchableSelectItem = SelectItem & { searchText?: string };\n\nfunction formatSelectNavigationHint(keybindings: KeybindingsManager): string {\n const up = formatKeyIds(keybindings, 'tui.select.up', { capitalize: true });\n const down = formatKeyIds(keybindings, 'tui.select.down', { capitalize: true });\n return `${up}/${down}`;\n}\n\nexport function formatScopedModelsOpenedHint(keybindings: KeybindingsManager): string {\n const modelCycle = formatKeyIds(keybindings, 'app.model.cycleForward', { capitalize: true });\n return `Scoped models for ${modelCycle}`;\n}\n\nexport function formatScopedModelsSavedHint(params: {\n refs: string[] | null;\n total: number;\n keybindings: KeybindingsManager;\n}): string {\n const modelCycle = formatKeyIds(params.keybindings, 'app.model.cycleForward', {\n capitalize: true,\n });\n if (params.refs === null) {\n return `${modelCycle} cycles all ${params.total} models`;\n }\n const count = params.refs.length;\n return `${modelCycle} cycles ${count} scoped model${count === 1 ? '' : 's'}`;\n}\n\nexport function formatSettingsOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Settings (${nav} · ${confirm} toggle · ${cancel} close)`;\n}\n\nexport function formatThinkingSelectorHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Thinking level (${nav} · ${confirm} select · ${cancel} close)`;\n}\n\nexport function formatThinkingLevelSavedHint(level: ThinkLevel): string {\n return `Thinking level: ${level}`;\n}\n\nexport function formatProjectTrustOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Project trust (${nav} · ${confirm} select · ${cancel} close)`;\n}\n\nexport function formatReviewPickerOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Review (${nav} · type to filter · ${confirm} select · ${cancel} close)`;\n}\n\nexport function formatAgentPickerOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Switch agent (${nav} · ${confirm} select · ${cancel} close)`;\n}\n\nfunction agentSelectItems(agents: TuiAgentInfo[], currentAgentId?: string): SelectItem[] {\n const current = currentAgentId?.trim().toLowerCase();\n return [...agents]\n .filter((agent) => agent.enabled !== false)\n .sort((a, b) => {\n if (a.id === current && b.id !== current) return -1;\n if (b.id === current && a.id !== current) return 1;\n if (a.id === 'coder' && b.id !== 'coder') return -1;\n if (b.id === 'coder' && a.id !== 'coder') return 1;\n return a.id.localeCompare(b.id);\n })\n .map((agent) => ({\n label: agent.id === current ? `${agent.id} (current)` : agent.id,\n value: agent.id,\n description: agent.displayName,\n }));\n}\n\nexport function formatSessionTreeOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Session tree (${nav} · type to filter · ${confirm} resume · ${cancel} close)`;\n}\n\nexport async function openTimelineOverlay(\n svc: PickerServices,\n initialQuery?: string,\n): Promise<void> {\n const items = await svc.client.loadTimeline(svc.state.currentSessionKey);\n const turns = buildTuiTimelineTurns(items);\n if (turns.length === 0) {\n svc.chatLog.addSystem('No timeline turns found.');\n svc.tui.requestRender();\n return;\n }\n\n const viewState = svc.chatLog.getTimelineViewportState();\n const activeDisplayIndex =\n viewState.mode === 'history'\n ? viewState.displayIndex\n : turns[turns.length - 1]?.displayIndex;\n const list = new TimelineSelectList(turns, {\n keybindings: svc.keybindings,\n ...(activeDisplayIndex !== undefined ? { activeDisplayIndex } : {}),\n ...(initialQuery ? { initialQuery } : {}),\n });\n list.onSelect = (turn) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n void (async () => {\n if (!svc.chatLog.jumpToDisplayIndex(turn.displayIndex)) {\n const loaded =\n turn.rowNumber !== undefined\n ? await svc.loadHistoryWindow({ rowNumber: turn.rowNumber })\n : false;\n if (!loaded || !svc.chatLog.jumpToDisplayIndex(turn.displayIndex)) {\n svc.chatLog.addSystem(`Turn ${turn.turn} is outside loaded history.`);\n }\n }\n svc.tui.requestRender();\n })();\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatTimelineOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\nfunction resumeSession(svc: PickerServices, sessionKey: string): void {\n svc.setSessionKey(sessionKey);\n svc.clearChatForSessionSwitch();\n svc.chatLog.addSystem(`Session: ${sessionKey}`);\n void svc\n .refreshSessionInfo()\n .then(() => svc.loadSessionHistory())\n .then(() => {\n svc.updateHeader();\n svc.tui.requestRender();\n });\n svc.tui.requestRender();\n}\n\nfunction sessionTreeGroup(session: TuiSessionItem): { agentId: string; root: string; leaf: string } {\n const raw = session.key.trim();\n const parts = raw.split(':').filter(Boolean);\n if (parts.length >= 3 && parts[0] === 'agent') {\n const rest = parts.slice(2);\n return {\n agentId: parts[1] ?? 'main',\n root: rest[0] ?? raw,\n leaf: rest.length > 1 ? rest.slice(1).join(':') : rest.join(':') || raw,\n };\n }\n return { agentId: 'legacy', root: raw || 'session', leaf: raw || 'session' };\n}\n\nexport function sessionTreeSelectItems(\n sessions: TuiSessionItem[],\n currentSessionKey?: string,\n): SelectItem[] {\n const byKey = new Map(sessions.map((session) => [session.key, session]));\n return [...sessions]\n .sort((a, b) => {\n const ga = sessionTreeGroup(a);\n const gb = sessionTreeGroup(b);\n const groupCmp = `${ga.agentId}:${ga.root}`.localeCompare(`${gb.agentId}:${gb.root}`);\n if (groupCmp !== 0) return groupCmp;\n return (b.updatedAt ?? 0) - (a.updatedAt ?? 0);\n })\n .map((session) => {\n const group = sessionTreeGroup(session);\n const current = session.key === currentSessionKey ? '* ' : ' ';\n const label = session.displayName?.trim() || group.leaf;\n const parent = session.forkedFromSessionKey\n ? (byKey.get(session.forkedFromSessionKey)?.displayName?.trim() ?? session.forkedFromSessionKey)\n : null;\n const description = [\n `${group.agentId}/${group.root}`,\n formatSessionPickerDescription(session, { showKey: Boolean(session.displayName) }),\n parent ? `forked from ${parent}` : '',\n ]\n .filter(Boolean)\n .join(' · ');\n return {\n value: session.key,\n label: `${current}${label}`,\n description,\n searchText: `${session.key} ${session.displayName ?? ''} ${session.model ?? ''} ${parent ?? ''}`,\n };\n });\n}\n\n\n\n\n\nexport async function openAgentPickerOverlay(svc: PickerServices): Promise<void> {\n const parsed = parseAgentSessionKey(svc.state.currentSessionKey);\n if (!parsed) {\n svc.chatLog.addSystem('Cannot switch agent: current session is not an agent session.');\n svc.tui.requestRender();\n return;\n }\n if (svc.state.activeRunId) {\n svc.chatLog.addSystem('Cannot switch agent while a run is active. Abort first.');\n svc.tui.requestRender();\n return;\n }\n if (!svc.switchAgentSession) {\n svc.chatLog.addSystem('Agent switching is not available in this mode.');\n svc.tui.requestRender();\n return;\n }\n const agents = await svc.client.listAgents();\n const items = agentSelectItems(agents, parsed.agentId);\n if (items.length === 0) {\n svc.chatLog.addSystem('No agents available.');\n svc.tui.requestRender();\n return;\n }\n svc.chatLog.addSystem(theme.dim(formatAgentPickerOpenedHint(svc.keybindings)));\n const list = new SearchableSelectList(items, Math.min(10, items.length), searchableSelectListTheme, {\n searchPromptText: 'agent> ',\n });\n const closeSelector = svc.openEditorSelector(list, list);\n list.onSelect = (item) => {\n closeSelector();\n const targetAgentId = item.value;\n if (targetAgentId === parsed.agentId) {\n svc.chatLog.addSystem(`Already using agent: ${targetAgentId}`);\n svc.tui.requestRender();\n return;\n }\n const targetSessionKey = `agent:${targetAgentId}:${parsed.rest}`;\n void Promise.resolve(svc.switchAgentSession?.(targetSessionKey, targetAgentId))\n .then(() => {\n svc.chatLog.addSystem(`Switched to agent: ${targetAgentId}\\nSession: ${targetSessionKey}`);\n })\n .catch((err: unknown) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Agent switch failed: ${errorMessage}`);\n })\n .finally(() => svc.tui.requestRender());\n svc.tui.requestRender();\n };\n list.onCancel = () => closeSelector();\n svc.tui.requestRender();\n}\n\nfunction quoteReviewArg(value: string): string {\n return /^[A-Za-z0-9._/@:-]+$/.test(value) ? value : JSON.stringify(value);\n}\n\nfunction formatReviewStatus(status: ReviewContext['status']): string {\n if (status.isClean) return 'working tree clean';\n const parts: string[] = [];\n if (status.changedFiles > 0) parts.push(`${status.changedFiles} changed`);\n if (status.untrackedFiles > 0) parts.push(`${status.untrackedFiles} untracked`);\n return parts.join(', ');\n}\n\nfunction reviewPresetItems(context: ReviewContext): SearchableSelectItem[] {\n return [\n {\n value: 'base',\n label: 'Review against a base branch',\n description: context.defaultBaseBranch ? `PR Style · default ${context.defaultBaseBranch}` : 'PR Style',\n searchText: 'pr pull request base branch merge base',\n },\n {\n value: 'uncommitted',\n label: 'Review uncommitted changes',\n description: formatReviewStatus(context.status),\n searchText: 'workspace working tree uncommitted diff status',\n },\n {\n value: 'commit',\n label: 'Review a commit',\n description: context.commits.length > 0 ? `${context.commits.length} recent commits` : 'no commits found',\n searchText: 'commit sha history log',\n },\n {\n value: 'custom',\n label: 'Custom review instructions',\n description: 'edit prompt before sending',\n searchText: 'custom instructions focus prompt',\n },\n ];\n}\n\nfunction branchSelectItems(context: ReviewContext): SelectItem[] {\n return context.branches\n .filter((branch) => !branch.current)\n .map((branch) => ({\n value: branch.name,\n label: branch.name,\n description: [\n branch.name === context.defaultBaseBranch ? 'default' : '',\n branch.remote ? 'remote' : 'local',\n ].filter(Boolean).join(' · '),\n searchText: branch.name,\n }));\n}\n\nfunction commitSelectItems(context: ReviewContext): SelectItem[] {\n return context.commits.map((commit) => ({\n value: commit.sha,\n label: commit.subject,\n description: [commit.shortSha, commit.date?.slice(0, 10)].filter(Boolean).join(' · '),\n searchText: `${commit.sha} ${commit.shortSha} ${commit.subject}`,\n }));\n}\n\nfunction openReviewBranchSelector(svc: PickerServices, context: ReviewContext): void {\n const items = branchSelectItems(context);\n if (items.length === 0) {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.chatLog.addSystem('No base branches available for review.');\n svc.tui.requestRender();\n return;\n }\n const list = new SearchableSelectList(items, Math.min(10, items.length), searchableSelectListTheme, {\n searchPromptText: 'branch> ',\n });\n const defaultIndex = context.defaultBaseBranch\n ? items.findIndex((item) => item.value === context.defaultBaseBranch)\n : -1;\n if (defaultIndex >= 0) list.setSelectedIndex(defaultIndex);\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.sendMessage(`/review --base ${quoteReviewArg(item.value)}`);\n };\n list.onCancel = () => {\n openReviewPresetSelector(svc, context);\n };\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim('Select a base branch to review'));\n svc.tui.requestRender();\n}\n\nfunction openReviewCommitSelector(svc: PickerServices, context: ReviewContext): void {\n const items = commitSelectItems(context);\n if (items.length === 0) {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.chatLog.addSystem('No commits available for review.');\n svc.tui.requestRender();\n return;\n }\n const list = new SearchableSelectList(items, Math.min(12, items.length), searchableSelectListTheme, {\n searchPromptText: 'commit> ',\n });\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.sendMessage(`/review --commit ${item.value}`);\n };\n list.onCancel = () => {\n openReviewPresetSelector(svc, context);\n };\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim('Select a commit to review'));\n svc.tui.requestRender();\n}\n\nfunction openReviewPresetSelector(svc: PickerServices, context: ReviewContext): void {\n const items = reviewPresetItems(context);\n const list = new SearchableSelectList(items, Math.min(8, items.length), searchableSelectListTheme, {\n searchPromptText: 'review> ',\n });\n list.onSelect = (item) => {\n if (item.value === 'uncommitted') {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.sendMessage('/review --uncommitted');\n return;\n }\n if (item.value === 'custom') {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.setEditorText('/review --custom ');\n svc.tui.requestRender();\n return;\n }\n if (item.value === 'base') {\n openReviewBranchSelector(svc, context);\n return;\n }\n if (item.value === 'commit') {\n openReviewCommitSelector(svc, context);\n }\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatReviewPickerOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\nexport async function openReviewLauncherOverlay(svc: PickerServices): Promise<void> {\n if (!svc.client.getReviewContext) {\n svc.chatLog.addSystem('Review picker is not available in this mode. Use /review --uncommitted, /review --base <branch>, or /review --commit <sha>.');\n svc.tui.requestRender();\n return;\n }\n let context: ReviewContext;\n try {\n context = await svc.client.getReviewContext(svc.state.currentSessionKey);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Review picker failed: ${errorMessage}`);\n svc.tui.requestRender();\n return;\n }\n openReviewPresetSelector(svc, context);\n}\n\n/** Ctrl+Shift+P — session picker with rename/delete. */\nexport async function openSessionPickerOverlay(svc: PickerServices): Promise<void> {\n const sessions = await svc.client.listSessions();\n if (sessions.length === 0) {\n svc.chatLog.addSystem('No sessions listed.');\n svc.tui.requestRender();\n return;\n }\n\n const selector = new SessionSelector(\n sessions,\n {\n onResume: (sessionKey) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n resumeSession(svc, sessionKey);\n },\n onRename: async (sessionKey, name) => {\n const result = await svc.client.renameSession(sessionKey, name);\n return result.ok ? { ok: true } : { ok: false, error: 'Rename failed' };\n },\n onDelete: async (sessionKey) => {\n if (sessionKey === svc.state.currentSessionKey) {\n return { ok: false, error: 'Switch away before deleting the active session' };\n }\n const result = await svc.client.deleteSession(sessionKey);\n return result.ok ? { ok: true } : { ok: false, error: 'Delete failed' };\n },\n onCancel: () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n requestRender: () => svc.tui.requestRender(),\n },\n svc.keybindings,\n sessions.find((s) => s.key === svc.state.currentSessionKey)?.cwd ?? process.cwd(),\n svc.state.currentSessionKey,\n );\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim('Session picker'));\n svc.tui.requestRender();\n}\n\n/** Searchable session tree navigation overlay. */\nexport async function openSessionTreeOverlay(svc: PickerServices): Promise<void> {\n const sessions = await svc.client.listSessions();\n if (sessions.length === 0) {\n svc.chatLog.addSystem('No sessions listed.');\n svc.tui.requestRender();\n return;\n }\n\n const items = sessionTreeSelectItems(sessions, svc.state.currentSessionKey);\n const list = new SearchableSelectList(items, Math.min(14, items.length), searchableSelectListTheme);\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n resumeSession(svc, item.value);\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatSessionTreeOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** Searchable current-transcript tree overlay. */\nexport async function openTranscriptTreeOverlay(svc: PickerServices): Promise<void> {\n const entries = await svc.client.loadTranscriptTree(svc.state.currentSessionKey);\n const filterMode = svc.getTuiSettings().treeFilterMode;\n const visibleEntries = filterTuiTranscriptTreeEntries(entries, filterMode);\n if (visibleEntries.length === 0) {\n svc.chatLog.addSystem('No transcript entries found.');\n svc.tui.requestRender();\n return;\n }\n\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n const list = new TranscriptTreeSelectList(entries, filterMode, svc.keybindings, Math.min(16, visibleEntries.length));\n list.onSelect = (item) => {\n const entry = byId.get(item.value);\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n if (!entry) {\n svc.tui.requestRender();\n return;\n }\n const targetKey = defaultTranscriptForkKey(svc.state.currentSessionKey, entry.id);\n const sourceSessionKey = svc.state.currentSessionKey;\n svc.chatLog.addSystem(theme.dim(`Forking transcript at ${entry.id}...`));\n void svc.client\n .forkSessionAt(sourceSessionKey, targetKey, entry.id)\n .then((result) => {\n resumeSession(svc, result.sessionKey);\n svc.chatLog.addBranchSummary({\n sourceSessionKey,\n targetSessionKey: result.sessionKey,\n rowCount: result.rowCount,\n entryId: entry.id,\n });\n })\n .catch((err) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Fork failed: ${errorMessage}`);\n svc.tui.requestRender();\n });\n svc.tui.requestRender();\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n list.onFilterChange = (mode) => {\n svc.chatLog.addSystem(theme.dim(`Transcript tree filter: ${mode}`));\n svc.tui.requestRender();\n };\n list.onLabelSubmit = (entry, label) => {\n void svc.client\n .setTranscriptLabel(svc.state.currentSessionKey, entry.id, label)\n .then(() => {\n list.updateEntryLabel(entry.id, label);\n svc.chatLog.addSystem(\n theme.dim(label?.trim() ? `Labeled ${entry.id}: ${label.trim()}` : `Cleared label for ${entry.id}`),\n );\n svc.tui.requestRender();\n })\n .catch((err) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Label failed: ${errorMessage}`);\n svc.tui.requestRender();\n });\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatTranscriptTreeFilterHint(svc.keybindings, filterMode)));\n svc.tui.requestRender();\n}\n\n/** Pi-style `/fork` overlay: select a previous user message and branch there. */\nexport async function openUserMessageForkOverlay(svc: PickerServices): Promise<void> {\n const entries = await svc.client.loadTranscriptTree(svc.state.currentSessionKey);\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n const items = userMessageForkSelectItems(entries);\n if (items.length === 0) {\n svc.chatLog.addSystem('No messages to fork from.');\n svc.tui.requestRender();\n return;\n }\n\n const list = new SearchableSelectList(items, Math.min(10, items.length), searchableSelectListTheme, {\n wrapNavigation: true,\n });\n list.setSelectedIndex(items.length - 1);\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n const entry = byId.get(item.value);\n const targetKey = defaultTranscriptForkKey(svc.state.currentSessionKey, item.value);\n const sourceSessionKey = svc.state.currentSessionKey;\n svc.chatLog.addSystem(theme.dim(`Forking from ${item.value}...`));\n void svc.client\n .forkSessionAt(sourceSessionKey, targetKey, item.value)\n .then((result) => {\n resumeSession(svc, result.sessionKey);\n if (entry?.contentText) {\n svc.setEditorText(entry.contentText);\n }\n svc.chatLog.addBranchSummary({\n sourceSessionKey,\n targetSessionKey: result.sessionKey,\n rowCount: result.rowCount,\n entryId: item.value,\n restoredText: entry?.contentText,\n });\n })\n .catch((err) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Fork failed: ${errorMessage}`);\n svc.tui.requestRender();\n });\n svc.tui.requestRender();\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatUserMessageForkOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** `/scoped-models` — limit Ctrl+P model cycle set. */\nexport async function openScopedModelsOverlay(svc: PickerServices): Promise<void> {\n const catalog = await svc.client.listModels();\n svc.setModelChoices(catalog);\n if (catalog.length === 0) {\n svc.chatLog.addSystem('No models available.');\n svc.tui.requestRender();\n return;\n }\n\n const selector = new ScopedModelsSelector(\n catalog,\n svc.getScopedModelRefs(),\n {\n onSave: (refs) => {\n svc.setScopedModelRefs(refs);\n svc.refreshCycleModels();\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.chatLog.addSystem(\n theme.dim(formatScopedModelsSavedHint({\n refs,\n total: catalog.length,\n keybindings: svc.keybindings,\n })),\n );\n svc.tui.requestRender();\n },\n onCancel: () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n requestRender: () => svc.tui.requestRender(),\n },\n svc.keybindings,\n );\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim(formatScopedModelsOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** `/settings` — TUI preferences overlay. */\nexport function openSettingsOverlay(svc: PickerServices): void {\n const selector = new SettingsSelector(svc.getTuiSettings(), {\n onChange: (settings) => svc.applyTuiSettings(settings),\n onThemePreview: (themeId) => svc.previewTheme(themeId),\n onReloadKeybindings: () => svc.reloadKeybindings(),\n onCancel: () => {\n svc.previewTheme(svc.getTuiSettings().theme);\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n });\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim(formatSettingsOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** `/think` — select and persist the current session thinking level. */\nexport function openThinkingSelectorOverlay(svc: PickerServices): void {\n const current = normalizeThinkLevel(svc.state.sessionInfo.thinkingLevel) ?? 'medium';\n const levels = listThinkingLevels(\n svc.state.sessionInfo.modelProvider,\n svc.state.sessionInfo.model,\n ).map((level) => (level === 'on' ? 'low' : level)) as ThinkLevel[];\n const uniqueLevels = [...new Set(levels)];\n\n const selector = new ThinkingSelector(current, uniqueLevels, {\n onSelect: (level) => {\n void svc.setThinkingLevel(level).then(() => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n });\n },\n onCancel: () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n }, svc.keybindings);\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim(formatThinkingSelectorHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\nexport function openProjectTrustOverlay(svc: PickerServices): void {\n const cwd = process.cwd();\n const trustStore = svc.getProjectTrustStore();\n const currentStored = trustStore.getEntry(cwd);\n const sessionDecision = svc.getProjectTrustSessionDecision();\n const hasProjectResources = hasTrustRequiringProjectResources(cwd);\n const options = getProjectTrustOptions(cwd, { includeSessionOnly: true });\n const optionsByLabel = new Map(options.map((option) => [option.label, option]));\n const items: SelectItem[] = options.map((option) => ({\n value: option.label,\n label: option.label,\n description: option.savedPath ?? 'Current TUI session only',\n }));\n const list = new SearchableSelectList(items, Math.min(8, items.length), searchableSelectListTheme, {\n searchPromptText: 'trust: ',\n });\n\n list.onSelect = (item) => {\n const selected = optionsByLabel.get(item.value);\n if (!selected) return;\n if (selected.updates.length > 0) {\n trustStore.setMany(selected.updates);\n svc.setProjectTrustSessionDecision(null);\n } else {\n svc.setProjectTrustSessionDecision(selected.trusted);\n }\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n const scope = selected.savedPath ? `saved for ${selected.savedPath}` : 'this session only';\n svc.chatLog.addSystem(theme.dim(`Project trust: ${selected.trusted ? 'trusted' : 'not trusted'} (${scope})`));\n svc.tui.requestRender();\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n const storedLabel = currentStored\n ? `${currentStored.decision ? 'trusted' : 'not trusted'} from ${currentStored.path}`\n : 'not saved';\n const sessionLabel = sessionDecision === null ? 'none' : sessionDecision ? 'trusted' : 'not trusted';\n svc.chatLog.addSystem(\n theme.dim(\n [\n formatProjectTrustOpenedHint(svc.keybindings),\n `Project resources: ${hasProjectResources ? 'detected' : 'none detected'}`,\n `Stored: ${storedLabel}`,\n `Session: ${sessionLabel}`,\n ].join('\\n'),\n ),\n );\n svc.tui.requestRender();\n}\n"],"mappings":"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"}
|
|
@@ -12,6 +12,14 @@ export type PickerServices = {
|
|
|
12
12
|
chatLog: {
|
|
13
13
|
addSystem: (t: string) => void;
|
|
14
14
|
addBranchSummary: (summary: TuiBranchSummary) => void;
|
|
15
|
+
getTimelineViewportState: () => {
|
|
16
|
+
mode: 'latest';
|
|
17
|
+
} | {
|
|
18
|
+
mode: 'history';
|
|
19
|
+
displayIndex: number;
|
|
20
|
+
};
|
|
21
|
+
jumpToDisplayIndex: (displayIndex: number) => boolean;
|
|
22
|
+
jumpToLatest: () => void;
|
|
15
23
|
};
|
|
16
24
|
client: TuiBackend;
|
|
17
25
|
sendMessage: (text: string) => void;
|
|
@@ -24,6 +32,11 @@ export type PickerServices = {
|
|
|
24
32
|
switchAgentSession?: (sessionKey: string, agentId: string) => void | Promise<void>;
|
|
25
33
|
clearChatForSessionSwitch: () => void;
|
|
26
34
|
loadSessionHistory: () => Promise<void>;
|
|
35
|
+
loadHistoryWindow: (opts: {
|
|
36
|
+
rowNumber: number;
|
|
37
|
+
before?: number;
|
|
38
|
+
after?: number;
|
|
39
|
+
}) => Promise<boolean>;
|
|
27
40
|
setEditorText: (text: string) => void;
|
|
28
41
|
setModelChoices: (models: TuiModelChoice[]) => void;
|
|
29
42
|
getScopedModelRefs: () => string[] | null;
|
|
@@ -7,6 +7,8 @@ const STALE_WATCH_ACTIVITY = new Set([
|
|
|
7
7
|
]);
|
|
8
8
|
function markRunEvent(state, phase, runId, event, source, nowMs = Date.now()) {
|
|
9
9
|
const directStreamRunId = (source === "agent-response" || source === "agent-resume") && runId ? runId : state.runStatus.directStreamRunId;
|
|
10
|
+
const isStartingNewRun = phase !== "idle" && state.runStatus.phase === "idle" && (runId === null || state.runStatus.runId === null || state.runStatus.runId !== runId);
|
|
11
|
+
const startedAt = phase === "idle" ? null : isStartingNewRun || state.runStatus.startedAt == null ? nowMs : state.runStatus.startedAt;
|
|
10
12
|
state.runStatus = {
|
|
11
13
|
...state.runStatus,
|
|
12
14
|
phase,
|
|
@@ -14,6 +16,7 @@ function markRunEvent(state, phase, runId, event, source, nowMs = Date.now()) {
|
|
|
14
16
|
directStreamRunId,
|
|
15
17
|
source,
|
|
16
18
|
lastEvent: event,
|
|
19
|
+
startedAt,
|
|
17
20
|
lastActivityAt: nowMs,
|
|
18
21
|
stalledAt: null
|
|
19
22
|
};
|
|
@@ -27,6 +30,7 @@ function markRunSending(state, nowMs = Date.now()) {
|
|
|
27
30
|
lastCompletedRunId: null,
|
|
28
31
|
source: "unknown",
|
|
29
32
|
lastEvent: "send",
|
|
33
|
+
startedAt: nowMs,
|
|
30
34
|
lastActivityAt: nowMs,
|
|
31
35
|
stalledAt: null
|
|
32
36
|
};
|
|
@@ -37,6 +41,7 @@ function markRunAborting(state, runId, nowMs = Date.now()) {
|
|
|
37
41
|
phase: "aborting",
|
|
38
42
|
runId,
|
|
39
43
|
lastEvent: "abort",
|
|
44
|
+
startedAt: state.runStatus.startedAt ?? nowMs,
|
|
40
45
|
lastActivityAt: nowMs
|
|
41
46
|
};
|
|
42
47
|
}
|
|
@@ -46,6 +51,7 @@ function markRunIdleAfterAbort(state, nowMs = Date.now()) {
|
|
|
46
51
|
phase: "idle",
|
|
47
52
|
runId: null,
|
|
48
53
|
lastEvent: "abort",
|
|
54
|
+
startedAt: null,
|
|
49
55
|
lastActivityAt: nowMs,
|
|
50
56
|
stalledAt: null
|
|
51
57
|
};
|
|
@@ -62,6 +68,7 @@ function resetRunStatus(state) {
|
|
|
62
68
|
directStreamRunId: null,
|
|
63
69
|
lastCompletedRunId: null,
|
|
64
70
|
lastEvent: null,
|
|
71
|
+
startedAt: null,
|
|
65
72
|
stalledAt: null
|
|
66
73
|
};
|
|
67
74
|
}
|
|
@@ -79,6 +86,7 @@ function markActiveRunStalled(state, nowMs) {
|
|
|
79
86
|
...state.runStatus,
|
|
80
87
|
phase: "stalled",
|
|
81
88
|
runId: state.activeRunId,
|
|
89
|
+
startedAt: state.runStatus.startedAt ?? state.runStatus.lastActivityAt ?? nowMs,
|
|
82
90
|
stalledAt: nowMs
|
|
83
91
|
};
|
|
84
92
|
return true;
|
|
@@ -88,6 +96,7 @@ function markRunRecovering(state, nowMs) {
|
|
|
88
96
|
...state.runStatus,
|
|
89
97
|
phase: "recovering",
|
|
90
98
|
runId: state.activeRunId,
|
|
99
|
+
startedAt: state.runStatus.startedAt ?? state.runStatus.lastActivityAt ?? nowMs,
|
|
91
100
|
recoveredAt: nowMs
|
|
92
101
|
};
|
|
93
102
|
}
|
|
@@ -97,6 +106,7 @@ function markRunRecoveryComplete(state, nowMs) {
|
|
|
97
106
|
...state.runStatus,
|
|
98
107
|
phase: "stalled",
|
|
99
108
|
runId: state.activeRunId,
|
|
109
|
+
startedAt: state.runStatus.startedAt ?? state.runStatus.lastActivityAt ?? nowMs,
|
|
100
110
|
recoveredAt: nowMs
|
|
101
111
|
};
|
|
102
112
|
return;
|
|
@@ -105,6 +115,7 @@ function markRunRecoveryComplete(state, nowMs) {
|
|
|
105
115
|
...state.runStatus,
|
|
106
116
|
phase: "idle",
|
|
107
117
|
runId: null,
|
|
118
|
+
startedAt: null,
|
|
108
119
|
recoveredAt: nowMs
|
|
109
120
|
};
|
|
110
121
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui-run-state.js","names":[],"sources":["../../../src/tui/tui-run-state.ts"],"sourcesContent":["import type { ActivityStatus, TuiEventSource, TuiRunPhase, TuiState } from './tui-types.js';\n\nconst STALE_WATCH_ACTIVITY = new Set<ActivityStatus>(['sending', 'waiting', 'streaming', 'running']);\n\nexport function markRunEvent(\n state: TuiState,\n phase: TuiRunPhase,\n runId: string | null,\n event: string,\n source: TuiEventSource,\n nowMs = Date.now(),\n): void {\n const directStreamRunId =\n (source === 'agent-response' || source === 'agent-resume') && runId\n ? runId\n : state.runStatus.directStreamRunId;\n state.runStatus = {\n ...state.runStatus,\n phase,\n runId,\n directStreamRunId,\n source,\n lastEvent: event,\n lastActivityAt: nowMs,\n stalledAt: null,\n };\n}\n\nexport function markRunSending(state: TuiState, nowMs = Date.now()): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'sending',\n runId: null,\n directStreamRunId: null,\n lastCompletedRunId: null,\n source: 'unknown',\n lastEvent: 'send',\n lastActivityAt: nowMs,\n stalledAt: null,\n };\n}\n\nexport function markRunAborting(state: TuiState, runId: string, nowMs = Date.now()): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'aborting',\n runId,\n lastEvent: 'abort',\n lastActivityAt: nowMs,\n };\n}\n\nexport function markRunIdleAfterAbort(state: TuiState, nowMs = Date.now()): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'idle',\n runId: null,\n lastEvent: 'abort',\n lastActivityAt: nowMs,\n stalledAt: null,\n };\n}\n\nexport function markRunIdleAfterCompletion(\n state: TuiState,\n completedRunId: string,\n event: string,\n source: TuiEventSource,\n nowMs = Date.now(),\n): void {\n markRunEvent(state, 'idle', null, event, source, nowMs);\n state.runStatus.lastCompletedRunId = completedRunId;\n}\n\nexport function resetRunStatus(state: TuiState): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'idle',\n runId: null,\n directStreamRunId: null,\n lastCompletedRunId: null,\n lastEvent: null,\n stalledAt: null,\n };\n}\n\nexport function isActiveRunStreamStale(\n state: TuiState,\n nowMs: number,\n staleAfterMs: number,\n): boolean {\n if (!state.activeRunId) return false;\n if (!STALE_WATCH_ACTIVITY.has(state.activityStatus)) return false;\n if (state.runStatus.phase === 'stalled' || state.runStatus.phase === 'recovering') return false;\n if (state.runStatus.phase === 'aborting') return false;\n const lastActivityAt = state.runStatus.lastActivityAt ?? nowMs;\n return nowMs - lastActivityAt >= staleAfterMs;\n}\n\nexport function markActiveRunStalled(state: TuiState, nowMs: number): boolean {\n if (!state.activeRunId) return false;\n if (state.runStatus.phase === 'stalled' || state.runStatus.phase === 'recovering') {\n return false;\n }\n state.runStatus = {\n ...state.runStatus,\n phase: 'stalled',\n runId: state.activeRunId,\n stalledAt: nowMs,\n };\n return true;\n}\n\nexport function markRunRecovering(state: TuiState, nowMs: number): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'recovering',\n runId: state.activeRunId,\n recoveredAt: nowMs,\n };\n}\n\nexport function markRunRecoveryComplete(state: TuiState, nowMs: number): void {\n if (state.activeRunId) {\n state.runStatus = {\n ...state.runStatus,\n phase: 'stalled',\n runId: state.activeRunId,\n recoveredAt: nowMs,\n };\n return;\n }\n state.runStatus = {\n ...state.runStatus,\n phase: 'idle',\n runId: null,\n recoveredAt: nowMs,\n };\n}\n"],"mappings":";AAEA,MAAM,uBAAuB,IAAI,IAAoB;CAAC;CAAW;CAAW;CAAa;CAAU,CAAC;AAEpG,SAAgB,aACd,OACA,OACA,OACA,OACA,QACA,QAAQ,KAAK,KAAK,EACZ;CACN,MAAM,qBACH,WAAW,oBAAoB,WAAW,mBAAmB,QAC1D,QACA,MAAM,UAAU;
|
|
1
|
+
{"version":3,"file":"tui-run-state.js","names":[],"sources":["../../../src/tui/tui-run-state.ts"],"sourcesContent":["import type { ActivityStatus, TuiEventSource, TuiRunPhase, TuiState } from './tui-types.js';\n\nconst STALE_WATCH_ACTIVITY = new Set<ActivityStatus>(['sending', 'waiting', 'streaming', 'running']);\n\nexport function markRunEvent(\n state: TuiState,\n phase: TuiRunPhase,\n runId: string | null,\n event: string,\n source: TuiEventSource,\n nowMs = Date.now(),\n): void {\n const directStreamRunId =\n (source === 'agent-response' || source === 'agent-resume') && runId\n ? runId\n : state.runStatus.directStreamRunId;\n const isStartingNewRun =\n phase !== 'idle' &&\n state.runStatus.phase === 'idle' &&\n (runId === null || state.runStatus.runId === null || state.runStatus.runId !== runId);\n const startedAt =\n phase === 'idle'\n ? null\n : isStartingNewRun || state.runStatus.startedAt == null\n ? nowMs\n : state.runStatus.startedAt;\n state.runStatus = {\n ...state.runStatus,\n phase,\n runId,\n directStreamRunId,\n source,\n lastEvent: event,\n startedAt,\n lastActivityAt: nowMs,\n stalledAt: null,\n };\n}\n\nexport function markRunSending(state: TuiState, nowMs = Date.now()): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'sending',\n runId: null,\n directStreamRunId: null,\n lastCompletedRunId: null,\n source: 'unknown',\n lastEvent: 'send',\n startedAt: nowMs,\n lastActivityAt: nowMs,\n stalledAt: null,\n };\n}\n\nexport function markRunAborting(state: TuiState, runId: string, nowMs = Date.now()): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'aborting',\n runId,\n lastEvent: 'abort',\n startedAt: state.runStatus.startedAt ?? nowMs,\n lastActivityAt: nowMs,\n };\n}\n\nexport function markRunIdleAfterAbort(state: TuiState, nowMs = Date.now()): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'idle',\n runId: null,\n lastEvent: 'abort',\n startedAt: null,\n lastActivityAt: nowMs,\n stalledAt: null,\n };\n}\n\nexport function markRunIdleAfterCompletion(\n state: TuiState,\n completedRunId: string,\n event: string,\n source: TuiEventSource,\n nowMs = Date.now(),\n): void {\n markRunEvent(state, 'idle', null, event, source, nowMs);\n state.runStatus.lastCompletedRunId = completedRunId;\n}\n\nexport function resetRunStatus(state: TuiState): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'idle',\n runId: null,\n directStreamRunId: null,\n lastCompletedRunId: null,\n lastEvent: null,\n startedAt: null,\n stalledAt: null,\n };\n}\n\nexport function isActiveRunStreamStale(\n state: TuiState,\n nowMs: number,\n staleAfterMs: number,\n): boolean {\n if (!state.activeRunId) return false;\n if (!STALE_WATCH_ACTIVITY.has(state.activityStatus)) return false;\n if (state.runStatus.phase === 'stalled' || state.runStatus.phase === 'recovering') return false;\n if (state.runStatus.phase === 'aborting') return false;\n const lastActivityAt = state.runStatus.lastActivityAt ?? nowMs;\n return nowMs - lastActivityAt >= staleAfterMs;\n}\n\nexport function markActiveRunStalled(state: TuiState, nowMs: number): boolean {\n if (!state.activeRunId) return false;\n if (state.runStatus.phase === 'stalled' || state.runStatus.phase === 'recovering') {\n return false;\n }\n state.runStatus = {\n ...state.runStatus,\n phase: 'stalled',\n runId: state.activeRunId,\n startedAt: state.runStatus.startedAt ?? state.runStatus.lastActivityAt ?? nowMs,\n stalledAt: nowMs,\n };\n return true;\n}\n\nexport function markRunRecovering(state: TuiState, nowMs: number): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'recovering',\n runId: state.activeRunId,\n startedAt: state.runStatus.startedAt ?? state.runStatus.lastActivityAt ?? nowMs,\n recoveredAt: nowMs,\n };\n}\n\nexport function markRunRecoveryComplete(state: TuiState, nowMs: number): void {\n if (state.activeRunId) {\n state.runStatus = {\n ...state.runStatus,\n phase: 'stalled',\n runId: state.activeRunId,\n startedAt: state.runStatus.startedAt ?? state.runStatus.lastActivityAt ?? nowMs,\n recoveredAt: nowMs,\n };\n return;\n }\n state.runStatus = {\n ...state.runStatus,\n phase: 'idle',\n runId: null,\n startedAt: null,\n recoveredAt: nowMs,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//#region src/tui/tui-run-status-format.ts
|
|
2
|
+
const STALE_UPDATE_HINT_MS = 3e4;
|
|
3
|
+
function formatRunDuration(elapsedMs) {
|
|
4
|
+
const totalSeconds = Math.max(0, Math.floor(elapsedMs / 1e3));
|
|
5
|
+
if (totalSeconds < 60) return `${totalSeconds}s`;
|
|
6
|
+
return `${Math.floor(totalSeconds / 60)}m ${totalSeconds % 60}s`;
|
|
7
|
+
}
|
|
8
|
+
function activeRunLabel(state) {
|
|
9
|
+
if (state.runStatus.phase === "aborting" || state.activityStatus === "aborting") return "Stopping";
|
|
10
|
+
if (state.runStatus.phase === "recovering" || state.activityStatus === "recovering") return "Reconnecting output";
|
|
11
|
+
if (state.runStatus.phase === "stalled" || state.activityStatus === "stalled") return "Output stale";
|
|
12
|
+
const message = state.progressMessage?.trim();
|
|
13
|
+
if (message) return message;
|
|
14
|
+
if (state.runStatus.phase === "tool") return "Running tool";
|
|
15
|
+
if (state.activityStatus === "sending") return "Sending";
|
|
16
|
+
return "Working";
|
|
17
|
+
}
|
|
18
|
+
function formatActiveRunStatus(state, nowMs = Date.now()) {
|
|
19
|
+
if (!state.activeRunId) return null;
|
|
20
|
+
const startedAt = state.runStatus.startedAt ?? state.runStatus.lastActivityAt;
|
|
21
|
+
const details = [];
|
|
22
|
+
if (startedAt != null) details.push(formatRunDuration(nowMs - startedAt));
|
|
23
|
+
const lastActivityAt = state.runStatus.lastActivityAt;
|
|
24
|
+
const isStalePhase = state.runStatus.phase === "stalled" || state.runStatus.phase === "recovering" || state.activityStatus === "stalled" || state.activityStatus === "recovering";
|
|
25
|
+
if (lastActivityAt != null && (isStalePhase || nowMs - lastActivityAt >= STALE_UPDATE_HINT_MS)) details.push(`last update ${formatRunDuration(nowMs - lastActivityAt)} ago`);
|
|
26
|
+
if (state.runStatus.phase !== "aborting" && state.activityStatus !== "aborting") details.push("esc to interrupt");
|
|
27
|
+
const label = activeRunLabel(state);
|
|
28
|
+
return details.length > 0 ? `${label} (${details.join(" • ")})` : label;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { formatActiveRunStatus, formatRunDuration };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=tui-run-status-format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-run-status-format.js","names":[],"sources":["../../../src/tui/tui-run-status-format.ts"],"sourcesContent":["import type { TuiState } from './tui-types.js';\n\nconst STALE_UPDATE_HINT_MS = 30_000;\n\nexport function formatRunDuration(elapsedMs: number): string {\n const totalSeconds = Math.max(0, Math.floor(elapsedMs / 1000));\n if (totalSeconds < 60) return `${totalSeconds}s`;\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n return `${minutes}m ${seconds}s`;\n}\n\nfunction activeRunLabel(state: TuiState): string {\n if (state.runStatus.phase === 'aborting' || state.activityStatus === 'aborting') {\n return 'Stopping';\n }\n if (state.runStatus.phase === 'recovering' || state.activityStatus === 'recovering') {\n return 'Reconnecting output';\n }\n if (state.runStatus.phase === 'stalled' || state.activityStatus === 'stalled') {\n return 'Output stale';\n }\n const message = state.progressMessage?.trim();\n if (message) return message;\n if (state.runStatus.phase === 'tool') return 'Running tool';\n if (state.activityStatus === 'sending') return 'Sending';\n return 'Working';\n}\n\nexport function formatActiveRunStatus(state: TuiState, nowMs = Date.now()): string | null {\n if (!state.activeRunId) return null;\n\n const startedAt = state.runStatus.startedAt ?? state.runStatus.lastActivityAt;\n const details: string[] = [];\n if (startedAt != null) {\n details.push(formatRunDuration(nowMs - startedAt));\n }\n\n const lastActivityAt = state.runStatus.lastActivityAt;\n const isStalePhase =\n state.runStatus.phase === 'stalled' ||\n state.runStatus.phase === 'recovering' ||\n state.activityStatus === 'stalled' ||\n state.activityStatus === 'recovering';\n if (\n lastActivityAt != null &&\n (isStalePhase || nowMs - lastActivityAt >= STALE_UPDATE_HINT_MS)\n ) {\n details.push(`last update ${formatRunDuration(nowMs - lastActivityAt)} ago`);\n }\n\n if (state.runStatus.phase !== 'aborting' && state.activityStatus !== 'aborting') {\n details.push('esc to interrupt');\n }\n\n const label = activeRunLabel(state);\n return details.length > 0 ? `${label} (${details.join(' • ')})` : label;\n}\n"],"mappings":";AAEA,MAAM,uBAAuB;AAE7B,SAAgB,kBAAkB,WAA2B;CAC3D,MAAM,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,YAAY,IAAK,CAAC;AAC9D,KAAI,eAAe,GAAI,QAAO,GAAG,aAAa;AAG9C,QAAO,GAFS,KAAK,MAAM,eAAe,GAEzB,CAAC,IADF,eAAe,GACD;;AAGhC,SAAS,eAAe,OAAyB;AAC/C,KAAI,MAAM,UAAU,UAAU,cAAc,MAAM,mBAAmB,WACnE,QAAO;AAET,KAAI,MAAM,UAAU,UAAU,gBAAgB,MAAM,mBAAmB,aACrE,QAAO;AAET,KAAI,MAAM,UAAU,UAAU,aAAa,MAAM,mBAAmB,UAClE,QAAO;CAET,MAAM,UAAU,MAAM,iBAAiB,MAAM;AAC7C,KAAI,QAAS,QAAO;AACpB,KAAI,MAAM,UAAU,UAAU,OAAQ,QAAO;AAC7C,KAAI,MAAM,mBAAmB,UAAW,QAAO;AAC/C,QAAO;;AAGT,SAAgB,sBAAsB,OAAiB,QAAQ,KAAK,KAAK,EAAiB;AACxF,KAAI,CAAC,MAAM,YAAa,QAAO;CAE/B,MAAM,YAAY,MAAM,UAAU,aAAa,MAAM,UAAU;CAC/D,MAAM,UAAoB,EAAE;AAC5B,KAAI,aAAa,KACf,SAAQ,KAAK,kBAAkB,QAAQ,UAAU,CAAC;CAGpD,MAAM,iBAAiB,MAAM,UAAU;CACvC,MAAM,eACJ,MAAM,UAAU,UAAU,aAC1B,MAAM,UAAU,UAAU,gBAC1B,MAAM,mBAAmB,aACzB,MAAM,mBAAmB;AAC3B,KACE,kBAAkB,SACjB,gBAAgB,QAAQ,kBAAkB,sBAE3C,SAAQ,KAAK,eAAe,kBAAkB,QAAQ,eAAe,CAAC,MAAM;AAG9E,KAAI,MAAM,UAAU,UAAU,cAAc,MAAM,mBAAmB,WACnE,SAAQ,KAAK,mBAAmB;CAGlC,MAAM,QAAQ,eAAe,MAAM;AACnC,QAAO,QAAQ,SAAS,IAAI,GAAG,MAAM,IAAI,QAAQ,KAAK,MAAM,CAAC,KAAK"}
|
|
@@ -21,6 +21,11 @@ export declare function createSessionActions(context: SessionActionsContext): {
|
|
|
21
21
|
loadHistory: (opts?: {
|
|
22
22
|
merge?: boolean;
|
|
23
23
|
}) => Promise<void>;
|
|
24
|
+
loadHistoryWindow: (opts: {
|
|
25
|
+
rowNumber: number;
|
|
26
|
+
before?: number;
|
|
27
|
+
after?: number;
|
|
28
|
+
}) => Promise<boolean>;
|
|
24
29
|
setSession: (rawKey: string) => Promise<void>;
|
|
25
30
|
abortActive: (opts?: {
|
|
26
31
|
clearUi?: boolean;
|
|
@@ -55,6 +55,29 @@ function createSessionActions(context) {
|
|
|
55
55
|
tui.requestRender();
|
|
56
56
|
}
|
|
57
57
|
};
|
|
58
|
+
const loadHistoryWindow = async (opts) => {
|
|
59
|
+
if (!client.loadHistoryWindow) return false;
|
|
60
|
+
try {
|
|
61
|
+
const { messages } = await client.loadHistoryWindow({
|
|
62
|
+
sessionKey: state.currentSessionKey,
|
|
63
|
+
rowNumber: opts.rowNumber,
|
|
64
|
+
before: opts.before,
|
|
65
|
+
after: opts.after
|
|
66
|
+
});
|
|
67
|
+
if (messages.length === 0) return false;
|
|
68
|
+
sessionSnapshot?.replaceFromHistory(messages);
|
|
69
|
+
chatLog.clearAll();
|
|
70
|
+
appendHistoryToChatLog(chatLog, messages, state.toolsExpanded, state.showThinking);
|
|
71
|
+
lastHistoryKeys = messages.map(historyMessageKey);
|
|
72
|
+
state.historyLoaded = true;
|
|
73
|
+
return true;
|
|
74
|
+
} catch {
|
|
75
|
+
return false;
|
|
76
|
+
} finally {
|
|
77
|
+
await refreshSessionInfo();
|
|
78
|
+
tui.requestRender();
|
|
79
|
+
}
|
|
80
|
+
};
|
|
58
81
|
const setSession = async (rawKey) => {
|
|
59
82
|
const nextKey = resolveSessionKey(rawKey);
|
|
60
83
|
updateAgentFromSessionKey(nextKey);
|
|
@@ -88,6 +111,7 @@ function createSessionActions(context) {
|
|
|
88
111
|
return {
|
|
89
112
|
refreshSessionInfo,
|
|
90
113
|
loadHistory,
|
|
114
|
+
loadHistoryWindow,
|
|
91
115
|
setSession,
|
|
92
116
|
abortActive,
|
|
93
117
|
resetCurrentSession,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui-session-actions.js","names":[],"sources":["../../../src/tui/tui-session-actions.ts"],"sourcesContent":["import type { TUI } from '@earendil-works/pi-tui';\n\nimport { parseAgentSessionKey } from '../routing/agent-session-key.js';\nimport {\n appendHistoryToChatLog,\n historyKeysHaveAppendOnlyPrefix,\n historyMessageKey,\n} from './chat-history.js';\nimport type { ChatLog } from './components/chat-log.js';\nimport { clearSeenStreamEvents } from './tui-agent-events.js';\nimport type { TuiBackend } from './tui-backend.js';\nimport type { TuiState } from './tui-types.js';\nimport type { TuiSessionSnapshot } from './tui-session-snapshot.js';\nimport {\n markRunAborting,\n markRunIdleAfterAbort,\n resetRunStatus,\n} from './tui-run-state.js';\n\nexport type SessionActionsContext = {\n client: TuiBackend;\n chatLog: ChatLog;\n tui: TUI;\n state: TuiState;\n resolveSessionKey: (raw?: string) => string;\n updateHeader: () => void;\n updateFooter: () => void;\n setActivityStatus: (status: string) => void;\n historyLimit?: number;\n onAgentIdChange?: (agentId: string) => void;\n sessionSnapshot?: TuiSessionSnapshot;\n};\n\nexport function createSessionActions(context: SessionActionsContext) {\n const {\n client,\n chatLog,\n tui,\n state,\n resolveSessionKey,\n updateHeader,\n updateFooter,\n setActivityStatus,\n historyLimit = 200,\n onAgentIdChange,\n sessionSnapshot,\n } = context;\n\n let refreshSessionInfoPromise: Promise<void> = Promise.resolve();\n let lastHistoryKeys: string[] = [];\n\n const updateAgentFromSessionKey = (key: string) => {\n const parsed = parseAgentSessionKey(key);\n if (!parsed?.agentId) {\n return;\n }\n onAgentIdChange?.(parsed.agentId);\n };\n\n const runRefreshSessionInfo = async () => {\n try {\n state.sessionInfo = await client.getSessionInfo(state.currentSessionKey);\n updateFooter();\n tui.requestRender();\n } catch {\n // ignore\n }\n };\n\n const refreshSessionInfo = async () => {\n refreshSessionInfoPromise = refreshSessionInfoPromise.then(\n runRefreshSessionInfo,\n runRefreshSessionInfo,\n );\n await refreshSessionInfoPromise;\n };\n\n const clearChatForSessionSwitch = () => {\n chatLog.clearAll();\n clearSeenStreamEvents();\n sessionSnapshot?.clear();\n lastHistoryKeys = [];\n resetRunStatus(state);\n state.historyLoaded = false;\n state.messageFollowUpQueue.length = 0;\n state.steeringQueue.length = 0;\n };\n\n const loadHistory = async (opts?: { merge?: boolean }) => {\n try {\n const { messages } = await client.loadHistory({\n sessionKey: state.currentSessionKey,\n limit: historyLimit,\n });\n sessionSnapshot?.replaceFromHistory(messages);\n const nextKeys = messages.map(historyMessageKey);\n const canAppend =\n opts?.merge === true &&\n historyKeysHaveAppendOnlyPrefix(lastHistoryKeys, nextKeys);\n if (canAppend) {\n appendHistoryToChatLog(\n chatLog,\n messages.slice(lastHistoryKeys.length),\n state.toolsExpanded,\n state.showThinking,\n { startIndex: lastHistoryKeys.length },\n );\n } else {\n chatLog.clearAll();\n appendHistoryToChatLog(chatLog, messages, state.toolsExpanded, state.showThinking);\n }\n lastHistoryKeys = nextKeys;\n } catch {\n // ignore; footer already hints on disconnect\n } finally {\n state.historyLoaded = true;\n await refreshSessionInfo();\n tui.requestRender();\n }\n };\n\n const setSession = async (rawKey: string) => {\n const nextKey = resolveSessionKey(rawKey);\n updateAgentFromSessionKey(nextKey);\n state.currentSessionKey = nextKey;\n state.activeRunId = null;\n setActivityStatus('idle');\n clearChatForSessionSwitch();\n updateHeader();\n updateFooter();\n await loadHistory();\n };\n\n const abortActive = async (opts?: { clearUi?: boolean }) => {\n if (!state.activeRunId) {\n return;\n }\n const runId = state.activeRunId;\n markRunAborting(state, runId);\n state.activeRunId = null;\n if (opts?.clearUi !== false) {\n chatLog.dropAssistant(runId);\n }\n setActivityStatus('idle');\n markRunIdleAfterAbort(state);\n tui.requestRender();\n await client.abortChat({ sessionKey: state.currentSessionKey, runId }).catch(() => {});\n };\n\n const resetCurrentSession = async () => {\n await client.resetSession(state.currentSessionKey);\n clearChatForSessionSwitch();\n await loadHistory();\n };\n\n return {\n refreshSessionInfo,\n loadHistory,\n setSession,\n abortActive,\n resetCurrentSession,\n clearChatForSessionSwitch,\n };\n}\n"],"mappings":";;;;;;wBAEuE;AA+BvE,SAAgB,qBAAqB,SAAgC;CACnE,MAAM,EACJ,QACA,SACA,KACA,OACA,mBACA,cACA,cACA,mBACA,eAAe,KACf,iBACA,oBACE;CAEJ,IAAI,4BAA2C,QAAQ,SAAS;CAChE,IAAI,kBAA4B,EAAE;CAElC,MAAM,6BAA6B,QAAgB;EACjD,MAAM,SAAS,qBAAqB,IAAI;AACxC,MAAI,CAAC,QAAQ,QACX;AAEF,oBAAkB,OAAO,QAAQ;;CAGnC,MAAM,wBAAwB,YAAY;AACxC,MAAI;AACF,SAAM,cAAc,MAAM,OAAO,eAAe,MAAM,kBAAkB;AACxE,iBAAc;AACd,OAAI,eAAe;UACb;;CAKV,MAAM,qBAAqB,YAAY;AACrC,8BAA4B,0BAA0B,KACpD,uBACA,sBACD;AACD,QAAM;;CAGR,MAAM,kCAAkC;AACtC,UAAQ,UAAU;AAClB,yBAAuB;AACvB,mBAAiB,OAAO;AACxB,oBAAkB,EAAE;AACpB,iBAAe,MAAM;AACrB,QAAM,gBAAgB;AACtB,QAAM,qBAAqB,SAAS;AACpC,QAAM,cAAc,SAAS;;CAG/B,MAAM,cAAc,OAAO,SAA+B;AACxD,MAAI;GACF,MAAM,EAAE,aAAa,MAAM,OAAO,YAAY;IAC5C,YAAY,MAAM;IAClB,OAAO;IACR,CAAC;AACF,oBAAiB,mBAAmB,SAAS;GAC7C,MAAM,WAAW,SAAS,IAAI,kBAAkB;AAIhD,OAFE,MAAM,UAAU,QAChB,gCAAgC,iBAAiB,SAAS,CAE1D,wBACE,SACA,SAAS,MAAM,gBAAgB,OAAO,EACtC,MAAM,eACN,MAAM,cACN,EAAE,YAAY,gBAAgB,QAAQ,CACvC;QACI;AACL,YAAQ,UAAU;AAClB,2BAAuB,SAAS,UAAU,MAAM,eAAe,MAAM,aAAa;;AAEpF,qBAAkB;UACZ,WAEE;AACR,SAAM,gBAAgB;AACtB,SAAM,oBAAoB;AAC1B,OAAI,eAAe;;;CAIvB,MAAM,aAAa,OAAO,WAAmB;EAC3C,MAAM,UAAU,kBAAkB,OAAO;AACzC,4BAA0B,QAAQ;AAClC,QAAM,oBAAoB;AAC1B,QAAM,cAAc;AACpB,oBAAkB,OAAO;AACzB,6BAA2B;AAC3B,gBAAc;AACd,gBAAc;AACd,QAAM,aAAa;;CAGrB,MAAM,cAAc,OAAO,SAAiC;AAC1D,MAAI,CAAC,MAAM,YACT;EAEF,MAAM,QAAQ,MAAM;AACpB,kBAAgB,OAAO,MAAM;AAC7B,QAAM,cAAc;AACpB,MAAI,MAAM,YAAY,MACpB,SAAQ,cAAc,MAAM;AAE9B,oBAAkB,OAAO;AACzB,wBAAsB,MAAM;AAC5B,MAAI,eAAe;AACnB,QAAM,OAAO,UAAU;GAAE,YAAY,MAAM;GAAmB;GAAO,CAAC,CAAC,YAAY,GAAG;;CAGxF,MAAM,sBAAsB,YAAY;AACtC,QAAM,OAAO,aAAa,MAAM,kBAAkB;AAClD,6BAA2B;AAC3B,QAAM,aAAa;;AAGrB,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACD"}
|
|
1
|
+
{"version":3,"file":"tui-session-actions.js","names":[],"sources":["../../../src/tui/tui-session-actions.ts"],"sourcesContent":["import type { TUI } from '@earendil-works/pi-tui';\n\nimport { parseAgentSessionKey } from '../routing/agent-session-key.js';\nimport {\n appendHistoryToChatLog,\n historyKeysHaveAppendOnlyPrefix,\n historyMessageKey,\n} from './chat-history.js';\nimport type { ChatLog } from './components/chat-log.js';\nimport { clearSeenStreamEvents } from './tui-agent-events.js';\nimport type { TuiBackend } from './tui-backend.js';\nimport type { TuiState } from './tui-types.js';\nimport type { TuiSessionSnapshot } from './tui-session-snapshot.js';\nimport {\n markRunAborting,\n markRunIdleAfterAbort,\n resetRunStatus,\n} from './tui-run-state.js';\n\nexport type SessionActionsContext = {\n client: TuiBackend;\n chatLog: ChatLog;\n tui: TUI;\n state: TuiState;\n resolveSessionKey: (raw?: string) => string;\n updateHeader: () => void;\n updateFooter: () => void;\n setActivityStatus: (status: string) => void;\n historyLimit?: number;\n onAgentIdChange?: (agentId: string) => void;\n sessionSnapshot?: TuiSessionSnapshot;\n};\n\nexport function createSessionActions(context: SessionActionsContext) {\n const {\n client,\n chatLog,\n tui,\n state,\n resolveSessionKey,\n updateHeader,\n updateFooter,\n setActivityStatus,\n historyLimit = 200,\n onAgentIdChange,\n sessionSnapshot,\n } = context;\n\n let refreshSessionInfoPromise: Promise<void> = Promise.resolve();\n let lastHistoryKeys: string[] = [];\n\n const updateAgentFromSessionKey = (key: string) => {\n const parsed = parseAgentSessionKey(key);\n if (!parsed?.agentId) {\n return;\n }\n onAgentIdChange?.(parsed.agentId);\n };\n\n const runRefreshSessionInfo = async () => {\n try {\n state.sessionInfo = await client.getSessionInfo(state.currentSessionKey);\n updateFooter();\n tui.requestRender();\n } catch {\n // ignore\n }\n };\n\n const refreshSessionInfo = async () => {\n refreshSessionInfoPromise = refreshSessionInfoPromise.then(\n runRefreshSessionInfo,\n runRefreshSessionInfo,\n );\n await refreshSessionInfoPromise;\n };\n\n const clearChatForSessionSwitch = () => {\n chatLog.clearAll();\n clearSeenStreamEvents();\n sessionSnapshot?.clear();\n lastHistoryKeys = [];\n resetRunStatus(state);\n state.historyLoaded = false;\n state.messageFollowUpQueue.length = 0;\n state.steeringQueue.length = 0;\n };\n\n const loadHistory = async (opts?: { merge?: boolean }) => {\n try {\n const { messages } = await client.loadHistory({\n sessionKey: state.currentSessionKey,\n limit: historyLimit,\n });\n sessionSnapshot?.replaceFromHistory(messages);\n const nextKeys = messages.map(historyMessageKey);\n const canAppend =\n opts?.merge === true &&\n historyKeysHaveAppendOnlyPrefix(lastHistoryKeys, nextKeys);\n if (canAppend) {\n appendHistoryToChatLog(\n chatLog,\n messages.slice(lastHistoryKeys.length),\n state.toolsExpanded,\n state.showThinking,\n { startIndex: lastHistoryKeys.length },\n );\n } else {\n chatLog.clearAll();\n appendHistoryToChatLog(chatLog, messages, state.toolsExpanded, state.showThinking);\n }\n lastHistoryKeys = nextKeys;\n } catch {\n // ignore; footer already hints on disconnect\n } finally {\n state.historyLoaded = true;\n await refreshSessionInfo();\n tui.requestRender();\n }\n };\n\n const loadHistoryWindow = async (opts: {\n rowNumber: number;\n before?: number;\n after?: number;\n }): Promise<boolean> => {\n if (!client.loadHistoryWindow) {\n return false;\n }\n try {\n const { messages } = await client.loadHistoryWindow({\n sessionKey: state.currentSessionKey,\n rowNumber: opts.rowNumber,\n before: opts.before,\n after: opts.after,\n });\n if (messages.length === 0) {\n return false;\n }\n sessionSnapshot?.replaceFromHistory(messages);\n chatLog.clearAll();\n appendHistoryToChatLog(chatLog, messages, state.toolsExpanded, state.showThinking);\n lastHistoryKeys = messages.map(historyMessageKey);\n state.historyLoaded = true;\n return true;\n } catch {\n return false;\n } finally {\n await refreshSessionInfo();\n tui.requestRender();\n }\n };\n\n const setSession = async (rawKey: string) => {\n const nextKey = resolveSessionKey(rawKey);\n updateAgentFromSessionKey(nextKey);\n state.currentSessionKey = nextKey;\n state.activeRunId = null;\n setActivityStatus('idle');\n clearChatForSessionSwitch();\n updateHeader();\n updateFooter();\n await loadHistory();\n };\n\n const abortActive = async (opts?: { clearUi?: boolean }) => {\n if (!state.activeRunId) {\n return;\n }\n const runId = state.activeRunId;\n markRunAborting(state, runId);\n state.activeRunId = null;\n if (opts?.clearUi !== false) {\n chatLog.dropAssistant(runId);\n }\n setActivityStatus('idle');\n markRunIdleAfterAbort(state);\n tui.requestRender();\n await client.abortChat({ sessionKey: state.currentSessionKey, runId }).catch(() => {});\n };\n\n const resetCurrentSession = async () => {\n await client.resetSession(state.currentSessionKey);\n clearChatForSessionSwitch();\n await loadHistory();\n };\n\n return {\n refreshSessionInfo,\n loadHistory,\n loadHistoryWindow,\n setSession,\n abortActive,\n resetCurrentSession,\n clearChatForSessionSwitch,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Component, Focusable, KeybindingsManager } from '@earendil-works/pi-tui';
|
|
2
|
+
import { type TuiTimelineTurn } from './tui-timeline.js';
|
|
3
|
+
export declare function formatTimelineOpenedHint(keybindings: KeybindingsManager): string;
|
|
4
|
+
export declare class TimelineSelectList implements Component, Focusable {
|
|
5
|
+
private readonly list;
|
|
6
|
+
private readonly items;
|
|
7
|
+
onSelect?: (turn: TuiTimelineTurn) => void;
|
|
8
|
+
onCancel?: () => void;
|
|
9
|
+
constructor(turns: readonly TuiTimelineTurn[], options: {
|
|
10
|
+
activeDisplayIndex?: number;
|
|
11
|
+
initialQuery?: string;
|
|
12
|
+
keybindings: KeybindingsManager;
|
|
13
|
+
});
|
|
14
|
+
get focused(): boolean;
|
|
15
|
+
set focused(value: boolean);
|
|
16
|
+
invalidate(): void;
|
|
17
|
+
render(width: number): string[];
|
|
18
|
+
handleInput(keyData: string): void;
|
|
19
|
+
}
|