@xopcai/xopc 0.0.86 → 0.0.87
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/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/feishu/src/adapters/cli-login.js +3 -3
- package/dist/extensions/feishu/src/adapters/cli-login.js.map +1 -1
- package/dist/extensions/telegram/src/delivery-chat-id.d.ts +1 -1
- package/dist/extensions/telegram/src/delivery-chat-id.js +1 -1
- package/dist/extensions/telegram/src/delivery-chat-id.js.map +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +1 -0
- package/dist/extensions/telegram/src/routing-integration.js.map +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js +2 -2
- package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js.map +1 -1
- package/dist/extensions/weixin/src/api/api.js +2 -2
- package/dist/extensions/weixin/src/api/api.js.map +1 -1
- package/dist/extensions/weixin/src/auth/accounts.js +12 -12
- package/dist/extensions/weixin/src/auth/accounts.js.map +1 -1
- package/dist/extensions/weixin/src/delivery-to.js +2 -2
- package/dist/extensions/weixin/src/delivery-to.js.map +1 -1
- package/dist/extensions/weixin/src/messaging/debug-mode.js +5 -5
- package/dist/extensions/weixin/src/messaging/debug-mode.js.map +1 -1
- package/dist/extensions/weixin/src/messaging/inbound.js +11 -11
- package/dist/extensions/weixin/src/messaging/inbound.js.map +1 -1
- package/dist/extensions/weixin/src/storage/sync-buf.js +4 -4
- package/dist/extensions/weixin/src/storage/sync-buf.js.map +1 -1
- package/dist/extensions/weixin/src/workflow-progress.d.ts +1 -1
- package/dist/extensions/weixin/src/workflow-progress.js.map +1 -1
- package/dist/gateway/static/root/assets/{agents-mS3_HpRI.js → agents-BEAbXpuP.js} +6 -6
- package/dist/gateway/static/root/assets/{apps-page-DrfytjOb.js → apps-page-Dg8R-Szf.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-settings-BG6b9KrW.js → channels-settings-yohw9YSu.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-status-swr-Bs5kMCMI.js → channels-status-swr-BSHqqCF1.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-api-BuVcZ5zR.js → cron-api-0h_QT8U3.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-page-BMrloeFH.js → cron-page-BkfKFfFk.js} +1 -1
- package/dist/gateway/static/root/assets/{dist-CKU1OOTf.js → dist-Cmjp2APP.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-BdW_46sN.js → extension-debug-page-CFa9z_1N.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DW47KI82.js → extension-page-BI8eaTPq.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-B-W4x2xP.js → extension-settings-page-x4BB7q1X.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-B2MYHbWg.js → fetch-DRqwef_Q.js} +1 -1
- package/dist/gateway/static/root/assets/{field-primitives-DPG-oJmx.js → field-primitives-BiNHBo2Y.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-C8dNts9i.js → heartbeat-config-api-ZRb8qhuz.js} +1 -1
- package/dist/gateway/static/root/assets/{index-BmVYculr.js → index-Cu7bKuUi.js} +96 -94
- package/dist/gateway/static/root/assets/index-a5gWIdZQ.css +1 -0
- package/dist/gateway/static/root/assets/{logs-page-sTsVWz0X.js → logs-page-BFZ8GgCv.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-FaG_Vlkb.js → sessions-page-CD7AfB-2.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-DuvRQW--.js → settings-form-section-DiqqVs6m.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-Bet1OerL.js → settings-page-BBOjEQW3.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-BtG2kLDh.js → share-preview-page-n1Gprylk.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page-DhUO235y.js → skills-page-CcN_gj--.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-DryYl3qD.js → theme-store-CZOh1nT3.js} +1 -1
- package/dist/gateway/static/root/assets/url-Dd8Q7kZZ.js +3 -0
- package/dist/gateway/static/root/assets/{utils-BY7bU1DT.js → utils-CkWBfxs4.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-CGEydndO.js → voice-api-key-field-O6awz9hi.js} +1 -1
- package/dist/gateway/static/root/index.html +5 -5
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-scope.d.ts +4 -0
- package/dist/src/agent/agent-scope.js +53 -10
- package/dist/src/agent/agent-scope.js.map +1 -1
- package/dist/src/agent/bootstrap/filter-bootstrap-files.js +2 -1
- package/dist/src/agent/bootstrap/filter-bootstrap-files.js.map +1 -1
- package/dist/src/agent/embedded/session-tool-result-guard.js +2 -1
- package/dist/src/agent/embedded/session-tool-result-guard.js.map +1 -1
- package/dist/src/agent/embedded/tool-result-truncation.js +2 -1
- package/dist/src/agent/embedded/tool-result-truncation.js.map +1 -1
- package/dist/src/agent/fallback/candidates.js +2 -2
- package/dist/src/agent/fallback/candidates.js.map +1 -1
- package/dist/src/agent/goals/persistent-goal-apis.d.ts +0 -2
- package/dist/src/agent/goals/persistent-goal-service.js +0 -1
- package/dist/src/agent/goals/persistent-goal-service.js.map +1 -1
- package/dist/src/agent/image/generation/normalization.js +2 -12
- package/dist/src/agent/image/generation/normalization.js.map +1 -1
- package/dist/src/agent/image/generation/provider-registry.d.ts +4 -8
- package/dist/src/agent/image/generation/provider-registry.js.map +1 -1
- package/dist/src/agent/image/generation/runtime.d.ts +2 -2
- package/dist/src/agent/image/generation/runtime.js.map +1 -1
- package/dist/src/agent/image/generation/types.d.ts +0 -18
- package/dist/src/agent/image/image-helpers.js +6 -1
- package/dist/src/agent/image/image-helpers.js.map +1 -1
- package/dist/src/agent/image/index.d.ts +1 -1
- package/dist/src/agent/inbound/inbound-loop.d.ts +5 -0
- package/dist/src/agent/inbound/inbound-loop.js +41 -10
- package/dist/src/agent/inbound/inbound-loop.js.map +1 -1
- package/dist/src/agent/inbound/turn-dispatcher.d.ts +4 -0
- package/dist/src/agent/inbound/turn-dispatcher.js +6 -4
- package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
- package/dist/src/agent/mcp/bundle-mcp-materialize.js +2 -1
- package/dist/src/agent/mcp/bundle-mcp-materialize.js.map +1 -1
- package/dist/src/agent/mcp/bundle-mcp-names.js +2 -1
- package/dist/src/agent/mcp/bundle-mcp-names.js.map +1 -1
- package/dist/src/agent/mcp/bundle-mcp-runtime.js +2 -1
- package/dist/src/agent/mcp/bundle-mcp-runtime.js.map +1 -1
- package/dist/src/agent/mcp/mcp-transport-config.js +2 -1
- package/dist/src/agent/mcp/mcp-transport-config.js.map +1 -1
- package/dist/src/agent/mcp/mcp-transport.js +2 -1
- package/dist/src/agent/mcp/mcp-transport.js.map +1 -1
- package/dist/src/agent/media-generation/runtime-shared.js +2 -9
- package/dist/src/agent/media-generation/runtime-shared.js.map +1 -1
- package/dist/src/agent/messaging/command-handler.d.ts +6 -0
- package/dist/src/agent/messaging/command-handler.js +5 -0
- package/dist/src/agent/messaging/command-handler.js.map +1 -1
- package/dist/src/agent/prompt/safety.d.ts +0 -7
- package/dist/src/agent/prompt/safety.js +1 -20
- package/dist/src/agent/prompt/safety.js.map +1 -1
- package/dist/src/agent/service/build-direct-message-content.js +1 -1
- package/dist/src/agent/service/build-direct-message-content.js.map +1 -1
- package/dist/src/agent/service/direct-turn-helpers.d.ts +3 -1
- package/dist/src/agent/service/direct-turn-helpers.js +6 -1
- package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
- package/dist/src/agent/service/process-direct-one-shot.d.ts +4 -0
- package/dist/src/agent/service/process-direct-one-shot.js +15 -2
- package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
- package/dist/src/agent/service/process-direct-streaming.d.ts +4 -0
- package/dist/src/agent/service/process-direct-streaming.js +34 -4
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service/webchat-tts.js +1 -1
- package/dist/src/agent/service/webchat-tts.js.map +1 -1
- package/dist/src/agent/service.d.ts +8 -0
- package/dist/src/agent/service.js +21 -1
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/tools/create-share-tool.js +27 -20
- package/dist/src/agent/tools/create-share-tool.js.map +1 -1
- package/dist/src/agent/tools/factory.js +1 -1
- package/dist/src/agent/tools/index.d.ts +0 -1
- package/dist/src/agent/tools/index.js +4 -5
- package/dist/src/agent/tools/shell.js +0 -13
- package/dist/src/agent/tools/shell.js.map +1 -1
- package/dist/src/agent/tools/workflow-tool.js +7 -1
- package/dist/src/agent/tools/workflow-tool.js.map +1 -1
- package/dist/src/agent/workflow/channel-capability.d.ts +3 -3
- package/dist/src/agent/workflow/lint.d.ts +38 -0
- package/dist/src/agent/workflow/lint.js +74 -0
- package/dist/src/agent/workflow/lint.js.map +1 -0
- package/dist/src/agent/workflow/parser.js +4 -1
- package/dist/src/agent/workflow/parser.js.map +1 -1
- package/dist/src/agent/workflow/runtime.d.ts +3 -0
- package/dist/src/agent/workflow/runtime.js +76 -3
- package/dist/src/agent/workflow/runtime.js.map +1 -1
- package/dist/src/agent/workflow/types.d.ts +3 -1
- package/dist/src/browser/index.js +4 -4
- package/dist/src/browser/manager.d.ts +1 -3
- package/dist/src/browser/manager.js +0 -6
- package/dist/src/browser/manager.js.map +1 -1
- package/dist/src/browser/providers/browser-ext-install.d.ts +4 -4
- package/dist/src/browser/providers/browser-ext-install.js +38 -85
- package/dist/src/browser/providers/browser-ext-install.js.map +1 -1
- package/dist/src/browser/providers/cloakbrowser.d.ts +0 -5
- package/dist/src/browser/providers/cloakbrowser.js +2 -55
- package/dist/src/browser/providers/cloakbrowser.js.map +1 -1
- package/dist/src/channels/attachments/voice-stt-webchat.js +10 -8
- package/dist/src/channels/attachments/voice-stt-webchat.js.map +1 -1
- package/dist/src/channels/pairing/allow-from-file.js +9 -9
- package/dist/src/channels/pairing/allow-from-file.js.map +1 -1
- package/dist/src/channels/pairing/pairing-store.js +6 -6
- package/dist/src/channels/pairing/pairing-store.js.map +1 -1
- package/dist/src/chat-commands/builtins/session.js +1 -1
- package/dist/src/chat-commands/builtins/session.js.map +1 -1
- package/dist/src/chat-commands/builtins/tts.js +2 -2
- package/dist/src/chat-commands/builtins/tts.js.map +1 -1
- package/dist/src/chat-commands/context.d.ts +3 -0
- package/dist/src/chat-commands/context.js +21 -3
- package/dist/src/chat-commands/context.js.map +1 -1
- package/dist/src/chat-commands/session-key.d.ts +4 -37
- package/dist/src/chat-commands/session-key.js +49 -85
- package/dist/src/chat-commands/session-key.js.map +1 -1
- package/dist/src/chat-commands/types.d.ts +2 -0
- package/dist/src/cli/commands/agent/interactive.js +2 -2
- package/dist/src/cli/commands/agent/interactive.js.map +1 -1
- package/dist/src/cli/commands/agent/sessions.js +2 -2
- package/dist/src/cli/commands/agent/sessions.js.map +1 -1
- package/dist/src/cli/commands/agent.js +4 -5
- package/dist/src/cli/commands/agent.js.map +1 -1
- package/dist/src/cli/commands/channels.js +1 -5
- package/dist/src/cli/commands/channels.js.map +1 -1
- package/dist/src/cli/commands/gateway/lifecycle-core.js +1 -1
- package/dist/src/cli/commands/gateway/lifecycle-core.js.map +1 -1
- package/dist/src/cli/commands/gateway/logs.d.ts +9 -0
- package/dist/src/cli/commands/gateway/logs.js +50 -17
- package/dist/src/cli/commands/gateway/logs.js.map +1 -1
- package/dist/src/cli/commands/image.js +22 -21
- package/dist/src/cli/commands/image.js.map +1 -1
- package/dist/src/cli/commands/session/utils.js +2 -2
- package/dist/src/cli/commands/session/utils.js.map +1 -1
- package/dist/src/cli/commands/update.js +26 -46
- package/dist/src/cli/commands/update.js.map +1 -1
- package/dist/src/cli/utils/session.d.ts +0 -5
- package/dist/src/cli/utils/session.js +1 -6
- package/dist/src/cli/utils/session.js.map +1 -1
- package/dist/src/commands/agents.config.js +1 -1
- package/dist/src/commands/agents.config.js.map +1 -1
- package/dist/src/config/agent-profile.js +5 -27
- package/dist/src/config/agent-profile.js.map +1 -1
- package/dist/src/config/index.js +2 -2
- package/dist/src/config/model-input.js +2 -5
- package/dist/src/config/model-input.js.map +1 -1
- package/dist/src/config/schema.d.ts +201 -217
- package/dist/src/config/schema.js +54 -39
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/config/workspace-path-helpers.d.ts +1 -2
- package/dist/src/config/workspace-path-helpers.js.map +1 -1
- package/dist/src/daemon/install-plan.js +25 -1
- package/dist/src/daemon/install-plan.js.map +1 -1
- package/dist/src/daemon/launchd.d.ts +8 -0
- package/dist/src/daemon/launchd.js +5 -12
- package/dist/src/daemon/launchd.js.map +1 -1
- package/dist/src/daemon/schtasks.d.ts +25 -0
- package/dist/src/daemon/schtasks.js +166 -46
- package/dist/src/daemon/schtasks.js.map +1 -1
- package/dist/src/daemon/service.js +5 -4
- package/dist/src/daemon/service.js.map +1 -1
- package/dist/src/daemon/systemd.d.ts +6 -0
- package/dist/src/daemon/systemd.js +18 -3
- package/dist/src/daemon/systemd.js.map +1 -1
- package/dist/src/extensions/activation-context.js +0 -1
- package/dist/src/extensions/activation-context.js.map +1 -1
- package/dist/src/extensions/normalize-manifest.js +0 -1
- package/dist/src/extensions/normalize-manifest.js.map +1 -1
- package/dist/src/extensions/types/manifest.d.ts +0 -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 +10 -2
- package/dist/src/gateway/agents-admin.js.map +1 -1
- package/dist/src/gateway/heartbeat/service.js +2 -2
- package/dist/src/gateway/heartbeat/service.js.map +1 -1
- package/dist/src/gateway/hono/app.js +1 -1
- package/dist/src/gateway/hono/lib/agent-model.d.ts +18 -10
- package/dist/src/gateway/hono/lib/agent-model.js +24 -35
- package/dist/src/gateway/hono/lib/agent-model.js.map +1 -1
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
- package/dist/src/gateway/hono/lib/safe-voice-config.js +14 -53
- package/dist/src/gateway/hono/lib/safe-voice-config.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/agents.js +17 -5
- package/dist/src/gateway/hono/routes/config-patch/agents.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/channels.js +0 -11
- package/dist/src/gateway/hono/routes/config-patch/channels.js.map +1 -1
- package/dist/src/gateway/hono/routes/goals.js +1 -1
- package/dist/src/gateway/hono/routes/goals.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +28 -7
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/shares.js +14 -12
- package/dist/src/gateway/hono/routes/shares.js.map +1 -1
- package/dist/src/gateway/hono/routes/tunnel.js +1 -1
- package/dist/src/gateway/hono/routes/update.js +4 -2
- package/dist/src/gateway/hono/routes/update.js.map +1 -1
- package/dist/src/gateway/hono/sse.js +16 -33
- package/dist/src/gateway/hono/sse.js.map +1 -1
- package/dist/src/gateway/lock.js +10 -10
- package/dist/src/gateway/lock.js.map +1 -1
- package/dist/src/gateway/ports.js +6 -6
- package/dist/src/gateway/ports.js.map +1 -1
- package/dist/src/gateway/resolve-webchat-session-key.d.ts +19 -0
- package/dist/src/gateway/resolve-webchat-session-key.js +46 -0
- package/dist/src/gateway/resolve-webchat-session-key.js.map +1 -0
- package/dist/src/gateway/service/run-gateway-agent.js +27 -11
- package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
- package/dist/src/gateway/service/sessions-api.d.ts +3 -0
- package/dist/src/gateway/service/sessions-api.js +8 -0
- package/dist/src/gateway/service/sessions-api.js.map +1 -1
- package/dist/src/gateway/service.d.ts +0 -2
- package/dist/src/gateway/service.js +2 -7
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/session-reset-service.d.ts +20 -0
- package/dist/src/gateway/session-reset-service.js +54 -0
- package/dist/src/gateway/session-reset-service.js.map +1 -0
- package/dist/src/gateway/startup-readiness.d.ts +1 -1
- package/dist/src/gateway/startup-readiness.js +1 -0
- package/dist/src/gateway/startup-readiness.js.map +1 -1
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/infra/gateway-processes.js +2 -2
- package/dist/src/infra/gateway-processes.js.map +1 -1
- package/dist/src/infra/run-command.d.ts +16 -0
- package/dist/src/infra/run-command.js +67 -0
- package/dist/src/infra/run-command.js.map +1 -0
- package/dist/src/infra/update-global.d.ts +45 -0
- package/dist/src/infra/update-global.js +224 -0
- package/dist/src/infra/update-global.js.map +1 -0
- package/dist/src/mcp/channel-bridge.js +1 -1
- package/dist/src/mcp/channel-shared.js +2 -1
- package/dist/src/mcp/channel-shared.js.map +1 -1
- package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
- package/dist/src/providers/auth-runtime/auth-profile-store.js.map +1 -1
- package/dist/src/providers/auth-runtime/resolve-auth.js +1 -12
- package/dist/src/providers/auth-runtime/resolve-auth.js.map +1 -1
- package/dist/src/providers/auth-runtime/types.d.ts +6 -12
- package/dist/src/routing/agent-session-key.d.ts +58 -0
- package/dist/src/routing/agent-session-key.js +164 -0
- package/dist/src/routing/agent-session-key.js.map +1 -0
- package/dist/src/routing/index.d.ts +1 -1
- package/dist/src/routing/index.js +4 -2
- package/dist/src/routing/index.js.map +1 -1
- package/dist/src/routing/resolve-route.d.ts +15 -0
- package/dist/src/routing/resolve-route.js +41 -20
- package/dist/src/routing/resolve-route.js.map +1 -1
- package/dist/src/routing/resolve-tui-session-key.d.ts +25 -0
- package/dist/src/routing/resolve-tui-session-key.js +54 -0
- package/dist/src/routing/resolve-tui-session-key.js.map +1 -0
- package/dist/src/routing/session-key-utils.d.ts +24 -0
- package/dist/src/routing/session-key-utils.js +92 -0
- package/dist/src/routing/session-key-utils.js.map +1 -0
- package/dist/src/routing/session-key.d.ts +19 -49
- package/dist/src/routing/session-key.js +143 -116
- package/dist/src/routing/session-key.js.map +1 -1
- package/dist/src/session/index.d.ts +6 -0
- package/dist/src/session/index.js +7 -1
- package/dist/src/session/init-session-turn.d.ts +30 -0
- package/dist/src/session/init-session-turn.js +102 -0
- package/dist/src/session/init-session-turn.js.map +1 -0
- package/dist/src/session/lifecycle-timestamps.d.ts +8 -0
- package/dist/src/session/lifecycle-timestamps.js +16 -0
- package/dist/src/session/lifecycle-timestamps.js.map +1 -0
- package/dist/src/session/manager.d.ts +7 -1
- package/dist/src/session/manager.js +8 -1
- package/dist/src/session/manager.js.map +1 -1
- package/dist/src/session/parity/transcript-paths.js +2 -2
- package/dist/src/session/parity/transcript-paths.js.map +1 -1
- package/dist/src/session/parity/xopc-session-disk-entry.d.ts +6 -0
- package/dist/src/session/reset-policy.d.ts +32 -0
- package/dist/src/session/reset-policy.js +65 -0
- package/dist/src/session/reset-policy.js.map +1 -0
- package/dist/src/session/reset-triggers.d.ts +20 -0
- package/dist/src/session/reset-triggers.js +63 -0
- package/dist/src/session/reset-triggers.js.map +1 -0
- package/dist/src/session/reset-type.d.ts +12 -0
- package/dist/src/session/reset-type.js +25 -0
- package/dist/src/session/reset-type.js.map +1 -0
- package/dist/src/session/resolve-session.d.ts +30 -0
- package/dist/src/session/resolve-session.js +93 -0
- package/dist/src/session/resolve-session.js.map +1 -0
- package/dist/src/session/session-title.js +3 -2
- package/dist/src/session/session-title.js.map +1 -1
- package/dist/src/session/store.d.ts +11 -4
- package/dist/src/session/store.js +57 -6
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/session/transcript-events.js +2 -1
- package/dist/src/session/transcript-events.js.map +1 -1
- package/dist/src/share/share-url.d.ts +33 -0
- package/dist/src/share/share-url.js +56 -14
- package/dist/src/share/share-url.js.map +1 -1
- package/dist/src/tui/backends/embedded-backend.js +4 -9
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.js +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/components/chat-log.js +3 -3
- package/dist/src/tui/components/chat-log.js.map +1 -1
- package/dist/src/tui/theme.d.ts +0 -2
- package/dist/src/tui/theme.js +1 -3
- package/dist/src/tui/theme.js.map +1 -1
- package/dist/src/tui/tui-commands.d.ts +3 -0
- package/dist/src/tui/tui-commands.js +45 -10
- package/dist/src/tui/tui-commands.js.map +1 -1
- package/dist/src/tui/tui-keybindings-file.js +1 -21
- package/dist/src/tui/tui-keybindings-file.js.map +1 -1
- package/dist/src/tui/tui-session-actions.d.ts +28 -0
- package/dist/src/tui/tui-session-actions.js +88 -0
- package/dist/src/tui/tui-session-actions.js.map +1 -0
- package/dist/src/tui/tui.js +52 -47
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/utils/string-coerce.d.ts +2 -0
- package/dist/src/utils/string-coerce.js +10 -1
- package/dist/src/utils/string-coerce.js.map +1 -1
- package/dist/src/voice/stt/config-slice.d.ts +2 -5
- package/dist/src/voice/stt/config-slice.js +5 -26
- package/dist/src/voice/stt/config-slice.js.map +1 -1
- package/dist/src/voice/stt/types.d.ts +1 -18
- package/dist/src/voice/stt/types.js +4 -2
- package/dist/src/voice/stt/types.js.map +1 -1
- package/dist/src/voice/tts/config-slice.d.ts +3 -7
- package/dist/src/voice/tts/config-slice.js +7 -38
- package/dist/src/voice/tts/config-slice.js.map +1 -1
- package/dist/src/voice/tts/merge-config.js +2 -48
- package/dist/src/voice/tts/merge-config.js.map +1 -1
- package/dist/src/voice/tts/providers/alibaba-speech.js +1 -1
- package/dist/src/voice/tts/providers/alibaba-speech.js.map +1 -1
- package/dist/src/voice/tts/types.d.ts +1 -29
- package/dist/src/voice/tts/types.js +19 -17
- package/dist/src/voice/tts/types.js.map +1 -1
- package/package.json +1 -4
- package/dist/gateway/static/root/assets/index-ew_2L2We.css +0 -1
- package/dist/gateway/static/root/assets/url-BwNL6Rgk.js +0 -3
- package/dist/src/agent/tools/browser-legacy-tools.d.ts +0 -17
- package/dist/src/agent/tools/browser-legacy-tools.js +0 -766
- package/dist/src/agent/tools/browser-legacy-tools.js.map +0 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { parseAgentSessionKey } from "../routing/session-key-utils.js";
|
|
2
|
+
import { init_agent_session_key } from "../routing/agent-session-key.js";
|
|
3
|
+
import { appendHistoryToChatLog } from "./chat-history.js";
|
|
4
|
+
import { clearPendingToolCallIds } from "./tui-agent-events.js";
|
|
5
|
+
//#region src/tui/tui-session-actions.ts
|
|
6
|
+
init_agent_session_key();
|
|
7
|
+
function createSessionActions(context) {
|
|
8
|
+
const { client, chatLog, tui, state, assembler, resolveSessionKey, updateHeader, updateFooter, setActivityStatus, historyLimit = 200, onAgentIdChange } = context;
|
|
9
|
+
let refreshSessionInfoPromise = Promise.resolve();
|
|
10
|
+
const updateAgentFromSessionKey = (key) => {
|
|
11
|
+
const parsed = parseAgentSessionKey(key);
|
|
12
|
+
if (!parsed?.agentId) return;
|
|
13
|
+
onAgentIdChange?.(parsed.agentId);
|
|
14
|
+
};
|
|
15
|
+
const runRefreshSessionInfo = async () => {
|
|
16
|
+
try {
|
|
17
|
+
state.sessionInfo = await client.getSessionInfo(state.currentSessionKey);
|
|
18
|
+
updateFooter();
|
|
19
|
+
tui.requestRender();
|
|
20
|
+
} catch {}
|
|
21
|
+
};
|
|
22
|
+
const refreshSessionInfo = async () => {
|
|
23
|
+
refreshSessionInfoPromise = refreshSessionInfoPromise.then(runRefreshSessionInfo, runRefreshSessionInfo);
|
|
24
|
+
await refreshSessionInfoPromise;
|
|
25
|
+
};
|
|
26
|
+
const clearChatForSessionSwitch = () => {
|
|
27
|
+
assembler.clear();
|
|
28
|
+
chatLog.clearAll();
|
|
29
|
+
clearPendingToolCallIds();
|
|
30
|
+
state.historyLoaded = false;
|
|
31
|
+
state.messageFollowUpQueue.length = 0;
|
|
32
|
+
};
|
|
33
|
+
const loadHistory = async () => {
|
|
34
|
+
try {
|
|
35
|
+
const { messages } = await client.loadHistory({
|
|
36
|
+
sessionKey: state.currentSessionKey,
|
|
37
|
+
limit: historyLimit
|
|
38
|
+
});
|
|
39
|
+
chatLog.clearAll();
|
|
40
|
+
appendHistoryToChatLog(chatLog, messages, state.toolsExpanded);
|
|
41
|
+
} catch {} finally {
|
|
42
|
+
state.historyLoaded = true;
|
|
43
|
+
await refreshSessionInfo();
|
|
44
|
+
tui.requestRender();
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const setSession = async (rawKey) => {
|
|
48
|
+
const nextKey = resolveSessionKey(rawKey);
|
|
49
|
+
updateAgentFromSessionKey(nextKey);
|
|
50
|
+
state.currentSessionKey = nextKey;
|
|
51
|
+
state.activeRunId = null;
|
|
52
|
+
setActivityStatus("idle");
|
|
53
|
+
clearChatForSessionSwitch();
|
|
54
|
+
updateHeader();
|
|
55
|
+
updateFooter();
|
|
56
|
+
await loadHistory();
|
|
57
|
+
};
|
|
58
|
+
const abortActive = async (opts) => {
|
|
59
|
+
if (!state.activeRunId) return;
|
|
60
|
+
const runId = state.activeRunId;
|
|
61
|
+
state.activeRunId = null;
|
|
62
|
+
assembler.drop(runId);
|
|
63
|
+
if (opts?.clearUi !== false) chatLog.dropAssistant(runId);
|
|
64
|
+
setActivityStatus("idle");
|
|
65
|
+
tui.requestRender();
|
|
66
|
+
await client.abortChat({
|
|
67
|
+
sessionKey: state.currentSessionKey,
|
|
68
|
+
runId
|
|
69
|
+
}).catch(() => {});
|
|
70
|
+
};
|
|
71
|
+
const resetCurrentSession = async () => {
|
|
72
|
+
await client.resetSession(state.currentSessionKey);
|
|
73
|
+
clearChatForSessionSwitch();
|
|
74
|
+
await loadHistory();
|
|
75
|
+
};
|
|
76
|
+
return {
|
|
77
|
+
refreshSessionInfo,
|
|
78
|
+
loadHistory,
|
|
79
|
+
setSession,
|
|
80
|
+
abortActive,
|
|
81
|
+
resetCurrentSession,
|
|
82
|
+
clearChatForSessionSwitch
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
export { createSessionActions };
|
|
87
|
+
|
|
88
|
+
//# sourceMappingURL=tui-session-actions.js.map
|
|
@@ -0,0 +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 { appendHistoryToChatLog } from './chat-history.js';\nimport type { ChatLog } from './components/chat-log.js';\nimport { clearPendingToolCallIds } from './tui-agent-events.js';\nimport type { TuiBackend } from './tui-backend.js';\nimport type { StreamAssembler } from './stream-assembler.js';\nimport type { TuiState } from './tui-types.js';\n\nexport type SessionActionsContext = {\n client: TuiBackend;\n chatLog: ChatLog;\n tui: TUI;\n state: TuiState;\n assembler: StreamAssembler;\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};\n\nexport function createSessionActions(context: SessionActionsContext) {\n const {\n client,\n chatLog,\n tui,\n state,\n assembler,\n resolveSessionKey,\n updateHeader,\n updateFooter,\n setActivityStatus,\n historyLimit = 200,\n onAgentIdChange,\n } = context;\n\n let refreshSessionInfoPromise: Promise<void> = Promise.resolve();\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 assembler.clear();\n chatLog.clearAll();\n clearPendingToolCallIds();\n state.historyLoaded = false;\n state.messageFollowUpQueue.length = 0;\n };\n\n const loadHistory = async () => {\n try {\n const { messages } = await client.loadHistory({\n sessionKey: state.currentSessionKey,\n limit: historyLimit,\n });\n chatLog.clearAll();\n appendHistoryToChatLog(chatLog, messages, state.toolsExpanded);\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 state.activeRunId = null;\n assembler.drop(runId);\n if (opts?.clearUi !== false) {\n chatLog.dropAssistant(runId);\n }\n setActivityStatus('idle');\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;AAsBvE,SAAgB,qBAAqB,SAAgC;CACnE,MAAM,EACJ,QACA,SACA,KACA,OACA,WACA,mBACA,cACA,cACA,mBACA,eAAe,KACf,oBACE;CAEJ,IAAI,4BAA2C,QAAQ,SAAS;CAEhE,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,YAAU,OAAO;AACjB,UAAQ,UAAU;AAClB,2BAAyB;AACzB,QAAM,gBAAgB;AACtB,QAAM,qBAAqB,SAAS;;CAGtC,MAAM,cAAc,YAAY;AAC9B,MAAI;GACF,MAAM,EAAE,aAAa,MAAM,OAAO,YAAY;IAC5C,YAAY,MAAM;IAClB,OAAO;IACR,CAAC;AACF,WAAQ,UAAU;AAClB,0BAAuB,SAAS,UAAU,MAAM,cAAc;UACxD,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,QAAM,cAAc;AACpB,YAAU,KAAK,MAAM;AACrB,MAAI,MAAM,YAAY,MACpB,SAAQ,cAAc,MAAM;AAE9B,oBAAkB,OAAO;AACzB,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"}
|
package/dist/src/tui/tui.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { version } from "../../package.js";
|
|
2
|
-
import {
|
|
2
|
+
import { parseAgentSessionKey } from "../routing/session-key-utils.js";
|
|
3
|
+
import { init_agent_session_key } from "../routing/agent-session-key.js";
|
|
4
|
+
import { loadConfig } from "../config/loader.js";
|
|
5
|
+
import "../config/index.js";
|
|
6
|
+
import { resolveTuiSessionKey, resolveTuiStartupSessionKey } from "../routing/resolve-tui-session-key.js";
|
|
3
7
|
import { saveClipboardImageToTempFile } from "./clipboard-image.js";
|
|
4
8
|
import { createXopcTuiKeybindingsManager } from "./tui-keybindings-file.js";
|
|
5
9
|
import { StreamAssembler } from "./stream-assembler.js";
|
|
@@ -13,6 +17,7 @@ import { createLocalShellRunner } from "./tui-local-shell.js";
|
|
|
13
17
|
import { createOverlayHandlers } from "./tui-overlays.js";
|
|
14
18
|
import { filterModelsForCycle, loadScopedModelRefs, saveScopedModelRefs } from "./tui-scoped-models.js";
|
|
15
19
|
import { openModelPickerOverlay, openScopedModelsOverlay, openSessionPickerOverlay, openSettingsOverlay } from "./tui-picker-overlay.js";
|
|
20
|
+
import { createSessionActions } from "./tui-session-actions.js";
|
|
16
21
|
import { loadTuiSettings, saveTuiSettings } from "./tui-settings.js";
|
|
17
22
|
import { installTuiStdioFilter } from "./tui-stdio-filter.js";
|
|
18
23
|
import { createEditorSubmitHandler, createSubmitBurstCoalescer, shouldEnableWindowsGitBashPasteFallback } from "./tui-submit.js";
|
|
@@ -32,6 +37,7 @@ import { mkdtempSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
|
32
37
|
import { spawnSync } from "node:child_process";
|
|
33
38
|
import { Container, Loader, ProcessTerminal, TUI, setKeybindings } from "@earendil-works/pi-tui";
|
|
34
39
|
//#region src/tui/tui.ts
|
|
40
|
+
init_agent_session_key();
|
|
35
41
|
const THINK_LEVEL_CYCLE = [
|
|
36
42
|
"off",
|
|
37
43
|
"minimal",
|
|
@@ -52,10 +58,23 @@ async function runTui(opts) {
|
|
|
52
58
|
const stdioFilter = installTuiStdioFilter();
|
|
53
59
|
const restoreStdio = () => stdioFilter.restore();
|
|
54
60
|
const isLocalMode = opts.local === true;
|
|
55
|
-
const
|
|
61
|
+
const startup = resolveTuiStartupSessionKey({
|
|
62
|
+
cfg: loadConfig(),
|
|
63
|
+
sessionOption: opts.session,
|
|
64
|
+
cwd: process.cwd()
|
|
65
|
+
});
|
|
66
|
+
let currentAgentId = startup.agentId;
|
|
67
|
+
const sessionScope = startup.sessionScope;
|
|
68
|
+
const sessionMainKey = startup.sessionMainKey;
|
|
69
|
+
const resolveSessionKey = (raw) => resolveTuiSessionKey({
|
|
70
|
+
raw,
|
|
71
|
+
sessionScope,
|
|
72
|
+
currentAgentId,
|
|
73
|
+
sessionMainKey
|
|
74
|
+
});
|
|
56
75
|
let tuiSettings = loadTuiSettings();
|
|
57
76
|
initTuiTheme({ themeId: opts.theme ?? tuiSettings.theme });
|
|
58
|
-
const state = createInitialState(sessionKey);
|
|
77
|
+
const state = createInitialState(startup.sessionKey);
|
|
59
78
|
state.scopedModelRefs = loadScopedModelRefs();
|
|
60
79
|
state.showThinking = tuiSettings.showThinking;
|
|
61
80
|
state.toolsExpanded = tuiSettings.toolsExpanded;
|
|
@@ -226,14 +245,6 @@ async function runTui(opts) {
|
|
|
226
245
|
bottomBar.invalidate();
|
|
227
246
|
tui.requestRender();
|
|
228
247
|
};
|
|
229
|
-
const refreshSessionInfo = async () => {
|
|
230
|
-
try {
|
|
231
|
-
state.sessionInfo = await client.getSessionInfo(state.currentSessionKey);
|
|
232
|
-
updateEditorBorderColor();
|
|
233
|
-
updateFooter();
|
|
234
|
-
tui.requestRender();
|
|
235
|
-
} catch {}
|
|
236
|
-
};
|
|
237
248
|
let finishTui = null;
|
|
238
249
|
let exitResult = { exitReason: "exit" };
|
|
239
250
|
const requestExit = () => {
|
|
@@ -255,18 +266,23 @@ async function runTui(opts) {
|
|
|
255
266
|
process.exit(0);
|
|
256
267
|
});
|
|
257
268
|
};
|
|
258
|
-
const abortActive
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
269
|
+
const { refreshSessionInfo, loadHistory: loadSessionHistory, setSession, abortActive, resetCurrentSession, clearChatForSessionSwitch } = createSessionActions({
|
|
270
|
+
client,
|
|
271
|
+
chatLog,
|
|
272
|
+
tui,
|
|
273
|
+
state,
|
|
274
|
+
assembler,
|
|
275
|
+
resolveSessionKey,
|
|
276
|
+
updateHeader,
|
|
277
|
+
updateFooter,
|
|
278
|
+
setActivityStatus,
|
|
279
|
+
onAgentIdChange: (agentId) => {
|
|
280
|
+
currentAgentId = agentId;
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
const refreshSessionInfoWithBorder = async () => {
|
|
284
|
+
await refreshSessionInfo();
|
|
285
|
+
updateEditorBorderColor();
|
|
270
286
|
};
|
|
271
287
|
const resolveModelChoiceIndex = () => {
|
|
272
288
|
const choices = cycleModelChoices();
|
|
@@ -411,7 +427,7 @@ async function runTui(opts) {
|
|
|
411
427
|
} finally {
|
|
412
428
|
state.isCompacting = false;
|
|
413
429
|
setActivityStatus("idle");
|
|
414
|
-
await
|
|
430
|
+
await refreshSessionInfoWithBorder();
|
|
415
431
|
const queued = state.compactionQueue.shift();
|
|
416
432
|
if (queued && !state.activeRunId) sendMessage(queued);
|
|
417
433
|
updateFooter();
|
|
@@ -460,7 +476,10 @@ async function runTui(opts) {
|
|
|
460
476
|
keybindings,
|
|
461
477
|
uiOverlays,
|
|
462
478
|
runCompaction,
|
|
463
|
-
extensionSlashCommands: extensionRuntime.slashCommands
|
|
479
|
+
extensionSlashCommands: extensionRuntime.slashCommands,
|
|
480
|
+
currentAgentId,
|
|
481
|
+
setSession,
|
|
482
|
+
resetSession: resetCurrentSession
|
|
464
483
|
});
|
|
465
484
|
const { runLocalShellLine } = createLocalShellRunner({
|
|
466
485
|
chatLog,
|
|
@@ -523,26 +542,12 @@ async function runTui(opts) {
|
|
|
523
542
|
tui.requestRender();
|
|
524
543
|
};
|
|
525
544
|
const setSessionKey = (key) => {
|
|
526
|
-
state.currentSessionKey = key;
|
|
527
|
-
|
|
528
|
-
const clearChatForSessionSwitch = () => {
|
|
529
|
-
assembler.clear();
|
|
530
|
-
chatLog.clearAll();
|
|
531
|
-
clearPendingToolCallIds();
|
|
532
|
-
state.historyLoaded = false;
|
|
533
|
-
state.messageFollowUpQueue.length = 0;
|
|
545
|
+
state.currentSessionKey = resolveSessionKey(key);
|
|
546
|
+
updateAgentFromPicker(key);
|
|
534
547
|
};
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
sessionKey: state.currentSessionKey,
|
|
539
|
-
limit: 200
|
|
540
|
-
});
|
|
541
|
-
appendHistoryToChatLog(chatLog, messages, state.toolsExpanded);
|
|
542
|
-
} catch {} finally {
|
|
543
|
-
state.historyLoaded = true;
|
|
544
|
-
tui.requestRender();
|
|
545
|
-
}
|
|
548
|
+
const updateAgentFromPicker = (key) => {
|
|
549
|
+
const parsed = parseAgentSessionKey(resolveSessionKey(key));
|
|
550
|
+
if (parsed?.agentId) currentAgentId = parsed.agentId;
|
|
546
551
|
};
|
|
547
552
|
let ctrlCHandling = false;
|
|
548
553
|
const handleCtrlC = () => {
|
|
@@ -685,7 +690,7 @@ async function runTui(opts) {
|
|
|
685
690
|
chatLog.addSystem("⚠️ No stream activity for 30s; UI reset (connection may have stalled). Retry or check gateway.");
|
|
686
691
|
state.activeRunId = null;
|
|
687
692
|
setActivityStatus("idle");
|
|
688
|
-
|
|
693
|
+
refreshSessionInfoWithBorder().finally(() => {
|
|
689
694
|
updateFooter();
|
|
690
695
|
tui.requestRender();
|
|
691
696
|
});
|
|
@@ -694,7 +699,7 @@ async function runTui(opts) {
|
|
|
694
699
|
}, 5e3);
|
|
695
700
|
const onAgentRunEnded = () => {
|
|
696
701
|
state.progressMessage = null;
|
|
697
|
-
|
|
702
|
+
refreshSessionInfoWithBorder().finally(() => {
|
|
698
703
|
updateFooter();
|
|
699
704
|
tui.requestRender();
|
|
700
705
|
});
|
|
@@ -709,7 +714,7 @@ async function runTui(opts) {
|
|
|
709
714
|
setConnectionStatus(isLocalMode ? "local ready" : "gateway connected");
|
|
710
715
|
touchStreamingActivity();
|
|
711
716
|
(async () => {
|
|
712
|
-
await
|
|
717
|
+
await refreshSessionInfoWithBorder();
|
|
713
718
|
await refreshModelChoices();
|
|
714
719
|
await loadSessionHistory();
|
|
715
720
|
updateHeader();
|
package/dist/src/tui/tui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui.js","names":["packageJson.version"],"sources":["../../../src/tui/tui.ts"],"sourcesContent":["import {\n Container,\n Loader,\n ProcessTerminal,\n setKeybindings,\n TUI,\n} from '@earendil-works/pi-tui';\nimport { mkdtempSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { spawnSync } from 'node:child_process';\n\nimport type { ThinkLevel } from '../agent/transcript/thinking-types.js';\nimport type { TuiBackend, TuiEvent, TuiModelChoice } from './tui-backend.js';\nimport { EmbeddedBackend } from './backends/embedded-backend.js';\nimport { GatewaySseBackend } from './backends/gateway-sse-backend.js';\nimport {\n clearPendingToolCallIds,\n DEFAULT_STREAMING_WATCHDOG_MS,\n dispatchAgentSSE,\n} from './tui-agent-events.js';\nimport { ChatLog } from './components/chat-log.js';\nimport { CustomEditor } from './components/custom-editor.js';\nimport { TuiBottomBar } from './components/tui-bottom-bar.js';\nimport { TuiHeader } from './components/tui-header.js';\nimport { StreamAssembler } from './stream-assembler.js';\nimport { createTuiCommandHandler, getSlashCommands } from './tui-commands.js';\nimport { createLocalShellRunner } from './tui-local-shell.js';\nimport {\n createBackspaceDeduper,\n drainAndStopTuiSafely,\n resolveCtrlCAction,\n} from './tui-lifecycle.js';\nimport {\n openModelPickerOverlay,\n openScopedModelsOverlay,\n openSessionPickerOverlay,\n openSettingsOverlay,\n} from './tui-picker-overlay.js';\nimport { createOverlayHandlers } from './tui-overlays.js';\nimport {\n createEditorSubmitHandler,\n createSubmitBurstCoalescer,\n shouldEnableWindowsGitBashPasteFallback,\n} from './tui-submit.js';\nimport { appendHistoryToChatLog } from './chat-history.js';\nimport { installTuiStdioFilter } from './tui-stdio-filter.js';\nimport { withTuiSuspended } from './tui-suspend.js';\nimport { saveClipboardImageToTempFile } from './clipboard-image.js';\nimport {\n applyThemeById,\n getBashExcludeBorderColor,\n getBashModeBorderColor,\n getThinkingBorderColor,\n initTuiTheme,\n} from './theme-manager.js';\nimport { editorTheme, theme } from './theme.js';\nimport { loadTuiSettings, saveTuiSettings, type TuiSettings } from './tui-settings.js';\nimport { resolveFdPath } from './tui-fd-path.js';\nimport packageJson from '../../package.json' with { type: 'json' };\nimport { createInitialState, type TuiOptions, type TuiResult, type TuiState } from './tui-types.js';\nimport { createXopcTuiKeybindingsManager } from './tui-keybindings-file.js';\nimport {\n filterModelsForCycle,\n loadScopedModelRefs,\n saveScopedModelRefs,\n} from './tui-scoped-models.js';\nimport { loadExtensionsForTuiLocalMode } from './extension-host/load-extensions.js';\nimport { createTuiExtensionRuntime } from './extension-host/runtime.js';\nimport type { ExtensionRegistryImpl } from '../extensions/loader.js';\n\nexport type { TuiOptions, TuiResult };\n\nexport {\n createBackspaceDeduper,\n drainAndStopTuiSafely,\n type DrainableTui,\n isIgnorableTuiStopError,\n resolveCtrlCAction,\n stopTuiSafely,\n} from './tui-lifecycle.js';\n\nexport { withTuiSuspended } from './tui-suspend.js';\n\nconst THINK_LEVEL_CYCLE: ThinkLevel[] = [\n 'off',\n 'minimal',\n 'low',\n 'medium',\n 'high',\n 'xhigh',\n 'adaptive',\n];\n\nfunction nextThinkLevel(current: string | undefined): ThinkLevel {\n const c = (current ?? 'medium').toLowerCase();\n const idx = THINK_LEVEL_CYCLE.indexOf(c as ThinkLevel);\n const mediumIdx = THINK_LEVEL_CYCLE.indexOf('medium');\n const base = idx >= 0 ? idx : mediumIdx >= 0 ? mediumIdx : 0;\n return THINK_LEVEL_CYCLE[(base + 1) % THINK_LEVEL_CYCLE.length]!;\n}\n\nconst DOUBLE_ESCAPE_WINDOW_MS = 500;\n\nexport async function runTui(opts: TuiOptions): Promise<TuiResult> {\n const stdioFilter = installTuiStdioFilter();\n const restoreStdio = () => stdioFilter.restore();\n\n const isLocalMode = opts.local === true;\n const sessionKey = opts.session ?? 'cli:tui';\n let tuiSettings = loadTuiSettings();\n initTuiTheme({ themeId: opts.theme ?? tuiSettings.theme });\n const state = createInitialState(sessionKey);\n state.scopedModelRefs = loadScopedModelRefs();\n state.showThinking = tuiSettings.showThinking;\n state.toolsExpanded = tuiSettings.toolsExpanded;\n const assembler = new StreamAssembler();\n\n let extensionRegistry: ExtensionRegistryImpl | undefined;\n if (isLocalMode) {\n extensionRegistry = await loadExtensionsForTuiLocalMode();\n }\n\n const client: TuiBackend = isLocalMode\n ? new EmbeddedBackend({ extensionRegistry })\n : new GatewaySseBackend({ url: opts.url ?? 'http://localhost:3120', token: opts.token });\n\n const keybindings = createXopcTuiKeybindingsManager();\n setKeybindings(keybindings);\n\n let modelChoices: TuiModelChoice[] = [];\n const cycleModelChoices = (): TuiModelChoice[] =>\n filterModelsForCycle(modelChoices, state.scopedModelRefs);\n\n const refreshCycleModels = () => {\n bottomBar.invalidate();\n tui.requestRender();\n };\n\n const tui = new TUI(new ProcessTerminal());\n const dedupeBackspace = createBackspaceDeduper();\n tui.addInputListener((data) => {\n const next = dedupeBackspace(data);\n if (next.length === 0) {\n return { consume: true };\n }\n return { data: next };\n });\n\n const header = new TuiHeader(() => ({\n version: packageJson.version ?? 'dev',\n connectionLabel: client.connectionLabel,\n sessionKey: state.currentSessionKey,\n showHints: tuiSettings.showStartupHints,\n }));\n const statusContainer = new Container();\n const bottomBar = new TuiBottomBar(() => state, () => opts.thinking);\n const chatLog = new ChatLog();\n chatLog.setToolsExpanded(state.toolsExpanded);\n const editor = new CustomEditor(tui, editorTheme, keybindings);\n const root = new Container();\n root.addChild(header);\n root.addChild(chatLog);\n root.addChild(statusContainer);\n root.addChild(editor);\n root.addChild(bottomBar);\n tui.addChild(root);\n tui.setFocus(editor);\n\n let isBashMode = false;\n let isBashExcludeContext = false;\n\n const updateEditorBorderColor = () => {\n if (isBashMode) {\n editor.borderColor = isBashExcludeContext\n ? getBashExcludeBorderColor()\n : getBashModeBorderColor();\n } else {\n const level = state.sessionInfo.thinkingLevel ?? opts.thinking ?? 'off';\n editor.borderColor = getThinkingBorderColor(level);\n }\n tui.requestRender();\n };\n\n editor.onChange = (text: string) => {\n const trimmed = text.trimStart();\n const nextExclude = trimmed.startsWith('!!');\n const nextBash = trimmed.startsWith('!');\n if (nextBash !== isBashMode || nextExclude !== isBashExcludeContext) {\n isBashMode = nextBash;\n isBashExcludeContext = nextExclude;\n updateEditorBorderColor();\n }\n };\n\n const { openOverlay, closeOverlay } = createOverlayHandlers(tui, editor);\n\n const slashCommands = getSlashCommands(isLocalMode);\n\n const extensionRuntime = createTuiExtensionRuntime({\n registry: extensionRegistry,\n tui,\n chatLog,\n header,\n bottomBar,\n getState: () => state,\n baseSlashCommands: slashCommands,\n cwd: process.cwd(),\n fdPath: resolveFdPath(),\n openOverlay,\n closeOverlay,\n onInvalidate: () => {\n updateHeader();\n updateFooter();\n tui.requestRender();\n },\n });\n\n editor.setAutocompleteProvider(extensionRuntime.autocompleteProvider);\n\n let statusLoader: Loader | null = null;\n let statusStartedAt: number | null = null;\n let lastActivityStatus = '';\n let elapsedTimerId: ReturnType<typeof setInterval> | null = null;\n const busyStates = new Set(['sending', 'waiting', 'streaming', 'running', 'compacting']);\n\n const syncTerminalProgress = () => {\n if (!tuiSettings.showTerminalProgress) {\n tui.terminal.setProgress(false);\n return;\n }\n tui.terminal.setProgress(busyStates.has(state.activityStatus));\n };\n\n let lastStreamActivityAt = Date.now();\n let streamWatchdogId: ReturnType<typeof setInterval> | null = null;\n\n const touchStreamingActivity = () => {\n lastStreamActivityAt = Date.now();\n };\n\n const formatElapsed = (startMs: number) => {\n const totalSeconds = Math.max(0, Math.floor((Date.now() - startMs) / 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\n const renderStatus = () => {\n const isBusy = busyStates.has(state.activityStatus);\n if (isBusy) {\n if (!statusStartedAt || lastActivityStatus !== state.activityStatus) {\n statusStartedAt = Date.now();\n }\n if (!statusLoader) {\n statusContainer.clear();\n statusLoader = new Loader(\n tui,\n (spinner) => theme.accent(spinner),\n (text) => theme.bold(theme.accentSoft(text)),\n '',\n );\n statusContainer.addChild(statusLoader);\n }\n const elapsed = formatElapsed(statusStartedAt);\n statusLoader.setMessage(\n `${state.progressMessage ?? state.activityStatus} • ${elapsed} | ${state.connectionStatus}`,\n );\n if (!elapsedTimerId) {\n elapsedTimerId = setInterval(() => {\n if (statusStartedAt && statusLoader) {\n const el = formatElapsed(statusStartedAt);\n statusLoader.setMessage(\n `${state.progressMessage ?? state.activityStatus} • ${el} | ${state.connectionStatus}`,\n );\n }\n }, 1000);\n }\n } else {\n state.progressMessage = null;\n statusStartedAt = null;\n if (elapsedTimerId) {\n clearInterval(elapsedTimerId);\n elapsedTimerId = null;\n }\n statusLoader?.stop();\n statusLoader = null;\n statusContainer.clear();\n }\n lastActivityStatus = state.activityStatus;\n bottomBar.invalidate();\n syncTerminalProgress();\n tui.requestRender();\n };\n\n const setActivityStatus = (status: string) => {\n state.activityStatus = status as TuiState['activityStatus'];\n renderStatus();\n };\n\n const setConnectionStatus = (text: string) => {\n state.connectionStatus = text;\n renderStatus();\n };\n\n const updateHeader = () => {\n header.invalidate();\n syncTerminalTitle();\n };\n\n const syncTerminalTitle = () => {\n const shortKey =\n state.currentSessionKey.length > 48\n ? `${state.currentSessionKey.slice(0, 45)}…`\n : state.currentSessionKey;\n tui.terminal.setTitle(`xopc · ${shortKey}`);\n };\n\n const updateFooter = () => {\n bottomBar.invalidate();\n };\n\n const refreshModelChoices = async () => {\n try {\n modelChoices = await client.listModels();\n } catch {\n modelChoices = [];\n }\n bottomBar.invalidate();\n tui.requestRender();\n };\n\n const refreshSessionInfo = async () => {\n try {\n state.sessionInfo = await client.getSessionInfo(state.currentSessionKey);\n updateEditorBorderColor();\n updateFooter();\n tui.requestRender();\n } catch {\n // ignore\n }\n };\n\n let finishTui: (() => void) | null = null;\n let exitResult: TuiResult = { exitReason: 'exit' };\n\n const requestExit = () => {\n if (state.exitRequested) return;\n state.exitRequested = true;\n if (elapsedTimerId) {\n clearInterval(elapsedTimerId);\n elapsedTimerId = null;\n }\n if (streamWatchdogId) {\n clearInterval(streamWatchdogId);\n streamWatchdogId = null;\n }\n client.stop();\n tui.terminal.setProgress(false);\n void drainAndStopTuiSafely(tui).then(() => {\n restoreStdio();\n finishTui?.();\n process.exit(0);\n });\n };\n\n const abortActive = async () => {\n if (!state.activeRunId) return;\n const runId = state.activeRunId;\n state.activeRunId = null;\n assembler.drop(runId);\n chatLog.dropAssistant(runId);\n setActivityStatus('idle');\n tui.requestRender();\n await client.abortChat({ sessionKey: state.currentSessionKey, runId }).catch(() => {});\n };\n\n const resolveModelChoiceIndex = (): number => {\n const choices = cycleModelChoices();\n if (choices.length === 0) return -1;\n const p = state.sessionInfo.modelProvider;\n const m = state.sessionInfo.model;\n if (p && m) {\n const byParts = choices.findIndex((x) => x.provider === p && x.id === m);\n if (byParts >= 0) return byParts;\n }\n if (m?.includes('/')) {\n const [a, b] = m.split('/', 2);\n const bySlash = choices.findIndex((x) => x.provider === a && x.id === b);\n if (bySlash >= 0) return bySlash;\n }\n return 0;\n };\n\n const cycleModel = (dir: 'forward' | 'backward') => {\n const choices = cycleModelChoices();\n if (choices.length === 0) {\n void refreshModelChoices().then(() => {\n if (cycleModelChoices().length === 0) {\n chatLog.addSystem('No models available to cycle.');\n tui.requestRender();\n return;\n }\n cycleModel(dir);\n });\n return;\n }\n const idx = resolveModelChoiceIndex();\n const base = idx >= 0 ? idx : 0;\n const delta = dir === 'forward' ? 1 : -1;\n const next = choices[(base + delta + choices.length) % choices.length]!;\n sendMessage(`/switch ${next.provider}/${next.id}`);\n };\n\n const handleCtrlZ = () => {\n if (process.platform === 'win32') {\n chatLog.addSystem('Suspend (Ctrl+Z) is not supported on Windows.');\n tui.requestRender();\n return;\n }\n const suspendKeepAlive = setInterval(() => {}, 2 ** 30);\n const ignoreSigint = () => {};\n process.on('SIGINT', ignoreSigint);\n process.once('SIGCONT', () => {\n clearInterval(suspendKeepAlive);\n process.removeListener('SIGINT', ignoreSigint);\n tui.start();\n tui.setFocus(editor);\n tui.requestRender(true);\n });\n try {\n tui.stop();\n process.kill(0, 'SIGTSTP');\n } catch {\n clearInterval(suspendKeepAlive);\n process.removeListener('SIGINT', ignoreSigint);\n }\n };\n\n const openExternalEditor = () => {\n const dir = mkdtempSync(join(tmpdir(), 'xopc-tui-edit-'));\n const filePath = join(dir, 'message.md');\n writeFileSync(filePath, editor.getText(), 'utf8');\n const editorBin = process.env.EDITOR || process.env.VISUAL || 'vi';\n void (async () => {\n await withTuiSuspended(tui, async () => {\n spawnSync(editorBin, [filePath], { stdio: 'inherit' });\n });\n try {\n const next = readFileSync(filePath, 'utf8');\n editor.setText(next.replace(/\\r\\n/g, '\\n'));\n } catch {\n // ignore\n }\n try {\n unlinkSync(filePath);\n } catch {\n // ignore\n }\n tui.setFocus(editor);\n tui.requestRender(true);\n })();\n };\n\n const isAgentBusy = () =>\n state.activeRunId != null || state.isCompacting || busyStates.has(state.activityStatus);\n\n const steerMessage = (text: string) => {\n chatLog.addUser(text);\n touchStreamingActivity();\n tui.requestRender();\n void client\n .steerChat({ sessionKey: state.currentSessionKey, message: text })\n .then(({ ok }) => {\n if (!ok) {\n chatLog.addSystem(\n theme.dim(\n 'Could not steer — no active run or steer failed. Press Escape to abort, or Alt+Enter to queue a follow-up.',\n ),\n );\n } else {\n chatLog.addSystem(\n theme.dim('Steered — message injects at the next tool boundary (pi-style).'),\n );\n }\n tui.requestRender();\n })\n .catch((error: unknown) => {\n const errorMessage = error instanceof Error ? error.message : String(error);\n chatLog.addSystem(theme.dim(`Steer failed: ${errorMessage}`));\n tui.requestRender();\n });\n };\n\n const sendMessage = (text: string) => {\n if (state.isCompacting) {\n state.compactionQueue.push(text);\n chatLog.addSystem(\n theme.dim(`Queued during compaction (${state.compactionQueue.length}). Sends when compact finishes.`),\n );\n bottomBar.invalidate();\n tui.requestRender();\n return;\n }\n\n if (state.activeRunId) {\n chatLog.addSystem(\n 'A response is still in progress. Press Enter to steer, Alt+Enter to queue, or Escape to abort.',\n );\n tui.requestRender();\n return;\n }\n\n chatLog.addUser(text);\n setActivityStatus('sending');\n touchStreamingActivity();\n tui.requestRender();\n\n void client\n .sendChat({\n sessionKey: state.currentSessionKey,\n message: text,\n thinking: opts.thinking,\n })\n .catch((error: unknown) => {\n const errorMessage = error instanceof Error ? error.message : String(error);\n chatLog.addSystem(`❌ Failed to send: ${errorMessage}`);\n setActivityStatus('idle');\n tui.requestRender();\n });\n };\n\n const runCompaction = async () => {\n if (state.isCompacting) return;\n state.isCompacting = true;\n setActivityStatus('compacting');\n chatLog.addSystem(theme.dim('Compacting session…'));\n tui.requestRender();\n try {\n const result = await client.compactSession(state.currentSessionKey, { force: true });\n chatLog.addSystem(result.summary ?? (result.compacted ? 'Session compacted' : 'Nothing to compact'));\n if (result.compacted) {\n assembler.clear();\n clearPendingToolCallIds();\n state.historyLoaded = false;\n await loadSessionHistory();\n }\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n chatLog.addSystem(`❌ Compaction failed: ${errorMessage}`);\n } finally {\n state.isCompacting = false;\n setActivityStatus('idle');\n await refreshSessionInfo();\n const queued = state.compactionQueue.shift();\n if (queued && !state.activeRunId) {\n sendMessage(queued);\n }\n updateFooter();\n tui.requestRender();\n }\n };\n\n const applyTuiSettings = (settings: TuiSettings) => {\n tuiSettings = { ...settings };\n saveTuiSettings(tuiSettings);\n state.showThinking = tuiSettings.showThinking;\n state.toolsExpanded = tuiSettings.toolsExpanded;\n chatLog.setToolsExpanded(tuiSettings.toolsExpanded);\n applyThemeById(tuiSettings.theme);\n header.invalidate();\n updateEditorBorderColor();\n syncTerminalProgress();\n bottomBar.invalidate();\n tui.requestRender();\n };\n\n const previewTheme = (themeId: string) => {\n applyThemeById(themeId);\n updateEditorBorderColor();\n tui.requestRender();\n };\n\n const reloadKeybindings = () => {\n keybindings.reload();\n setKeybindings(keybindings);\n tui.requestRender();\n };\n\n const uiOverlays = {\n openSessionPicker: () => {},\n openScopedModels: () => {},\n openSettings: () => {},\n reloadKeybindings: () => reloadKeybindings(),\n };\n\n const handleCommand = createTuiCommandHandler({\n state,\n chatLog,\n tui,\n assembler,\n isLocalMode,\n abortActive,\n sendMessage,\n requestExit,\n updateFooter,\n keybindings,\n uiOverlays,\n runCompaction,\n extensionSlashCommands: extensionRuntime.slashCommands,\n });\n\n const { runLocalShellLine } = createLocalShellRunner({\n chatLog,\n tui,\n editor,\n openOverlay,\n closeOverlay,\n pauseStdioFilter: () => stdioFilter.pause(),\n resumeStdioFilter: () => stdioFilter.resume(),\n runWithInheritedStdio: async (work) => {\n await withTuiSuspended(tui, work);\n },\n });\n\n const submitCore = createEditorSubmitHandler({\n editor,\n handleCommand,\n sendMessage,\n handleBangLine: runLocalShellLine,\n isAgentBusy,\n steerWhileBusy: steerMessage,\n });\n\n const submitBurst = createSubmitBurstCoalescer({\n submit: submitCore,\n enabled: shouldEnableWindowsGitBashPasteFallback(),\n });\n editor.onSubmit = submitBurst;\n\n const flushFollowUpQueue = () => {\n if (state.exitRequested) return;\n if (state.activeRunId) return;\n const next = state.messageFollowUpQueue.shift();\n if (next === undefined) return;\n sendMessage(next);\n };\n\n const handleFollowUp = () => {\n const text = editor.getText().trim();\n if (!text) return;\n if (isAgentBusy()) {\n editor.addToHistory(text);\n state.messageFollowUpQueue.push(text);\n editor.setText('');\n chatLog.addSystem(\n theme.dim(\n `Queued follow-up (${state.messageFollowUpQueue.length} in queue). Next sends when this reply finishes.`,\n ),\n );\n bottomBar.invalidate();\n tui.requestRender();\n return;\n }\n submitBurst(text);\n };\n\n const handleDequeue = () => {\n if (state.messageFollowUpQueue.length === 0) {\n chatLog.addSystem(theme.dim('No queued messages to restore.'));\n tui.requestRender();\n return;\n }\n const queued = [...state.messageFollowUpQueue];\n state.messageFollowUpQueue.length = 0;\n const current = editor.getText().trim();\n const combined = [queued.join('\\n\\n'), current].filter(Boolean).join('\\n\\n');\n editor.setText(combined);\n chatLog.addSystem(\n theme.dim(\n `Restored ${queued.length} queued message${queued.length > 1 ? 's' : ''} to editor.`,\n ),\n );\n bottomBar.invalidate();\n tui.requestRender();\n };\n\n const setSessionKey = (key: string) => {\n state.currentSessionKey = key;\n };\n\n const clearChatForSessionSwitch = () => {\n assembler.clear();\n chatLog.clearAll();\n clearPendingToolCallIds();\n state.historyLoaded = false;\n state.messageFollowUpQueue.length = 0;\n };\n\n const loadSessionHistory = async () => {\n try {\n const { messages } = await client.loadHistory({\n sessionKey: state.currentSessionKey,\n limit: 200,\n });\n appendHistoryToChatLog(chatLog, messages, state.toolsExpanded);\n } catch {\n // ignore; footer already hints on disconnect\n } finally {\n state.historyLoaded = true;\n tui.requestRender();\n }\n };\n\n let ctrlCHandling = false;\n const handleCtrlC = () => {\n if (ctrlCHandling) return;\n ctrlCHandling = true;\n try {\n const now = Date.now();\n const decision = resolveCtrlCAction({\n hasInput: editor.getText().trim().length > 0,\n now,\n lastCtrlCAt: state.lastCtrlCAt,\n });\n state.lastCtrlCAt = decision.nextLastCtrlCAt;\n if (decision.action === 'clear') {\n editor.setText('');\n setActivityStatus('cleared input; press ctrl+c again to exit');\n tui.requestRender();\n return;\n }\n if (decision.action === 'exit') {\n requestExit();\n return;\n }\n setActivityStatus('press ctrl+c again to exit');\n tui.requestRender();\n } finally {\n ctrlCHandling = false;\n }\n };\n\n const setModelChoices = (models: TuiModelChoice[]) => {\n modelChoices = models;\n };\n\n const pickerSvc = {\n tui,\n editor,\n openOverlay,\n closeOverlay,\n chatLog,\n client,\n sendMessage,\n refreshSessionInfo,\n updateHeader,\n state,\n setSessionKey,\n clearChatForSessionSwitch,\n loadSessionHistory,\n setModelChoices,\n getScopedModelRefs: () => state.scopedModelRefs,\n setScopedModelRefs: (refs: string[] | null) => {\n state.scopedModelRefs = refs;\n saveScopedModelRefs(refs);\n },\n refreshCycleModels,\n getTuiSettings: () => ({ ...tuiSettings }),\n applyTuiSettings,\n previewTheme,\n reloadKeybindings,\n };\n\n uiOverlays.openSessionPicker = () => void openSessionPickerOverlay(pickerSvc);\n uiOverlays.openScopedModels = () => void openScopedModelsOverlay(pickerSvc);\n uiOverlays.openSettings = () => openSettingsOverlay(pickerSvc);\n\n const handleDoubleEscape = () => {\n switch (tuiSettings.doubleEscapeAction) {\n case 'tree':\n chatLog.addSystem(theme.dim('Session tree is not available in xopc TUI yet.'));\n break;\n case 'fork':\n chatLog.addSystem(theme.dim('Session fork is not available in xopc TUI yet.'));\n break;\n default:\n break;\n }\n tui.requestRender();\n };\n\n editor.onEscape = () => {\n if (state.activeRunId) {\n void abortActive();\n return;\n }\n if (editor.getText().trim().length > 0) return;\n const now = Date.now();\n if (now - state.lastEscapeAt <= DOUBLE_ESCAPE_WINDOW_MS) {\n state.lastEscapeAt = 0;\n handleDoubleEscape();\n return;\n }\n state.lastEscapeAt = now;\n };\n editor.onCtrlD = () => requestExit();\n\n editor.onAction('app.clear', handleCtrlC);\n editor.onAction('app.exit', () => requestExit());\n editor.onAction('app.suspend', handleCtrlZ);\n editor.onAction('app.thinking.cycle', () => {\n const cur = state.sessionInfo.thinkingLevel ?? opts.thinking ?? 'medium';\n sendMessage(`/think ${nextThinkLevel(cur)}`);\n updateEditorBorderColor();\n });\n editor.onAction('app.model.cycleForward', () => cycleModel('forward'));\n editor.onAction('app.model.cycleBackward', () => cycleModel('backward'));\n editor.onAction('app.model.select', () => void openModelPickerOverlay(pickerSvc));\n editor.onAction('app.session.resume', () => void openSessionPickerOverlay(pickerSvc));\n editor.onAction('app.tools.expand', () => {\n state.toolsExpanded = !state.toolsExpanded;\n tuiSettings = { ...tuiSettings, toolsExpanded: state.toolsExpanded };\n saveTuiSettings(tuiSettings);\n chatLog.setToolsExpanded(state.toolsExpanded);\n setActivityStatus(state.toolsExpanded ? 'tools expanded' : 'tools collapsed');\n tui.requestRender();\n });\n editor.onAction('app.thinking.toggle', () => {\n state.showThinking = !state.showThinking;\n tuiSettings = { ...tuiSettings, showThinking: state.showThinking };\n saveTuiSettings(tuiSettings);\n updateFooter();\n tui.requestRender();\n });\n editor.onAction('app.editor.external', openExternalEditor);\n editor.onPasteImage = () => {\n void (async () => {\n const filePath = await saveClipboardImageToTempFile();\n if (!filePath) return;\n editor.insertTextAtCursor(filePath);\n chatLog.addSystem(theme.dim(`Pasted image path: ${filePath}`));\n tui.requestRender();\n })();\n };\n editor.onAction('app.message.followUp', handleFollowUp);\n editor.onAction('app.message.dequeue', handleDequeue);\n\n streamWatchdogId = setInterval(() => {\n if (!state.activeRunId) return;\n if (!busyStates.has(state.activityStatus)) return;\n if (Date.now() - lastStreamActivityAt < DEFAULT_STREAMING_WATCHDOG_MS) return;\n\n const rid = state.activeRunId;\n const finalText = assembler.finalize(rid, state.showThinking);\n if (finalText) {\n chatLog.finalizeAssistant(finalText, rid);\n }\n chatLog.addSystem(\n '⚠️ No stream activity for 30s; UI reset (connection may have stalled). Retry or check gateway.',\n );\n state.activeRunId = null;\n setActivityStatus('idle');\n void refreshSessionInfo().finally(() => {\n updateFooter();\n tui.requestRender();\n });\n flushFollowUpQueue();\n tui.requestRender();\n }, 5000);\n\n const onAgentRunEnded = () => {\n state.progressMessage = null;\n void refreshSessionInfo().finally(() => {\n updateFooter();\n tui.requestRender();\n });\n flushFollowUpQueue();\n };\n\n client.onEvent = (evt: TuiEvent) => {\n const data = (evt.data ?? {}) as Record<string, unknown>;\n dispatchAgentSSE(\n evt.event,\n data,\n state,\n chatLog,\n assembler,\n tui,\n setActivityStatus,\n touchStreamingActivity,\n onAgentRunEnded,\n );\n };\n\n client.onConnected = () => {\n state.isConnected = true;\n setConnectionStatus(isLocalMode ? 'local ready' : 'gateway connected');\n touchStreamingActivity();\n void (async () => {\n await refreshSessionInfo();\n await refreshModelChoices();\n await loadSessionHistory();\n updateHeader();\n updateFooter();\n tui.requestRender();\n if (!state.autoMessageSent && opts.message) {\n state.autoMessageSent = true;\n sendMessage(opts.message);\n }\n })();\n };\n\n client.onDisconnected = (reason: string) => {\n const wasConnected = state.isConnected;\n state.isConnected = false;\n touchStreamingActivity();\n if (isLocalMode) {\n setConnectionStatus(`local stopped: ${reason}`);\n } else {\n const hint =\n wasConnected || state.historyLoaded\n ? ` (${reason}). Reconnecting broadcast stream…`\n : `. Ensure gateway is running (xopc gateway) or use --local.`;\n setConnectionStatus(`disconnected${hint}`);\n if (!wasConnected && !state.historyLoaded) {\n const gatewayUrl = opts.url ?? 'http://localhost:3120';\n chatLog.addSystem(\n `Cannot reach gateway at ${gatewayUrl}.\\n` +\n 'Start the gateway (`xopc gateway`) or run `xopc tui --local` for embedded mode.',\n );\n }\n }\n tui.requestRender();\n };\n\n client.onGap = (info) => {\n chatLog.addSystem(\n `⚠️ Event gap: expected ${info.expected}, received ${info.received}. Some updates may be missing.`,\n );\n setConnectionStatus(`event gap: expected ${info.expected}, got ${info.received}`);\n tui.requestRender();\n };\n\n const sigintHandler = () => handleCtrlC();\n const sigtermHandler = () => requestExit();\n process.on('SIGINT', sigintHandler);\n process.on('SIGTERM', sigtermHandler);\n\n updateHeader();\n updateEditorBorderColor();\n setConnectionStatus(isLocalMode ? 'starting local runtime' : 'connecting');\n updateFooter();\n await extensionRuntime.activate();\n tui.start();\n client.start();\n\n await new Promise<void>((resolve) => {\n finishTui = () => {\n process.removeListener('SIGINT', sigintHandler);\n process.removeListener('SIGTERM', sigtermHandler);\n if (streamWatchdogId) {\n clearInterval(streamWatchdogId);\n streamWatchdogId = null;\n }\n finishTui = null;\n resolve();\n };\n });\n\n return exitResult;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tui.js","names":["packageJson.version"],"sources":["../../../src/tui/tui.ts"],"sourcesContent":["import {\n Container,\n Loader,\n ProcessTerminal,\n setKeybindings,\n TUI,\n} from '@earendil-works/pi-tui';\nimport { mkdtempSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { spawnSync } from 'node:child_process';\n\nimport type { ThinkLevel } from '../agent/transcript/thinking-types.js';\nimport { loadConfig } from '../config/index.js';\nimport { resolveTuiSessionKey, resolveTuiStartupSessionKey } from '../routing/resolve-tui-session-key.js';\nimport { parseAgentSessionKey } from '../routing/agent-session-key.js';\nimport type { TuiBackend, TuiEvent, TuiModelChoice } from './tui-backend.js';\nimport { EmbeddedBackend } from './backends/embedded-backend.js';\nimport { GatewaySseBackend } from './backends/gateway-sse-backend.js';\nimport {\n clearPendingToolCallIds,\n DEFAULT_STREAMING_WATCHDOG_MS,\n dispatchAgentSSE,\n} from './tui-agent-events.js';\nimport { ChatLog } from './components/chat-log.js';\nimport { CustomEditor } from './components/custom-editor.js';\nimport { TuiBottomBar } from './components/tui-bottom-bar.js';\nimport { TuiHeader } from './components/tui-header.js';\nimport { StreamAssembler } from './stream-assembler.js';\nimport { createTuiCommandHandler, getSlashCommands } from './tui-commands.js';\nimport { createLocalShellRunner } from './tui-local-shell.js';\nimport {\n createBackspaceDeduper,\n drainAndStopTuiSafely,\n resolveCtrlCAction,\n} from './tui-lifecycle.js';\nimport {\n openModelPickerOverlay,\n openScopedModelsOverlay,\n openSessionPickerOverlay,\n openSettingsOverlay,\n} from './tui-picker-overlay.js';\nimport { createOverlayHandlers } from './tui-overlays.js';\nimport {\n createEditorSubmitHandler,\n createSubmitBurstCoalescer,\n shouldEnableWindowsGitBashPasteFallback,\n} from './tui-submit.js';\nimport { installTuiStdioFilter } from './tui-stdio-filter.js';\nimport { withTuiSuspended } from './tui-suspend.js';\nimport { saveClipboardImageToTempFile } from './clipboard-image.js';\nimport {\n applyThemeById,\n getBashExcludeBorderColor,\n getBashModeBorderColor,\n getThinkingBorderColor,\n initTuiTheme,\n} from './theme-manager.js';\nimport { editorTheme, theme } from './theme.js';\nimport { loadTuiSettings, saveTuiSettings, type TuiSettings } from './tui-settings.js';\nimport { resolveFdPath } from './tui-fd-path.js';\nimport packageJson from '../../package.json' with { type: 'json' };\nimport { createSessionActions } from './tui-session-actions.js';\nimport { createInitialState, type TuiOptions, type TuiResult, type TuiState } from './tui-types.js';\nimport { createXopcTuiKeybindingsManager } from './tui-keybindings-file.js';\nimport {\n filterModelsForCycle,\n loadScopedModelRefs,\n saveScopedModelRefs,\n} from './tui-scoped-models.js';\nimport { loadExtensionsForTuiLocalMode } from './extension-host/load-extensions.js';\nimport { createTuiExtensionRuntime } from './extension-host/runtime.js';\nimport type { ExtensionRegistryImpl } from '../extensions/loader.js';\n\nexport type { TuiOptions, TuiResult };\n\nexport {\n createBackspaceDeduper,\n drainAndStopTuiSafely,\n type DrainableTui,\n isIgnorableTuiStopError,\n resolveCtrlCAction,\n stopTuiSafely,\n} from './tui-lifecycle.js';\n\nexport { withTuiSuspended } from './tui-suspend.js';\n\nconst THINK_LEVEL_CYCLE: ThinkLevel[] = [\n 'off',\n 'minimal',\n 'low',\n 'medium',\n 'high',\n 'xhigh',\n 'adaptive',\n];\n\nfunction nextThinkLevel(current: string | undefined): ThinkLevel {\n const c = (current ?? 'medium').toLowerCase();\n const idx = THINK_LEVEL_CYCLE.indexOf(c as ThinkLevel);\n const mediumIdx = THINK_LEVEL_CYCLE.indexOf('medium');\n const base = idx >= 0 ? idx : mediumIdx >= 0 ? mediumIdx : 0;\n return THINK_LEVEL_CYCLE[(base + 1) % THINK_LEVEL_CYCLE.length]!;\n}\n\nconst DOUBLE_ESCAPE_WINDOW_MS = 500;\n\nexport async function runTui(opts: TuiOptions): Promise<TuiResult> {\n const stdioFilter = installTuiStdioFilter();\n const restoreStdio = () => stdioFilter.restore();\n\n const isLocalMode = opts.local === true;\n const config = loadConfig();\n const startup = resolveTuiStartupSessionKey({\n cfg: config,\n sessionOption: opts.session,\n cwd: process.cwd(),\n });\n let currentAgentId = startup.agentId;\n const sessionScope = startup.sessionScope;\n const sessionMainKey = startup.sessionMainKey;\n const resolveSessionKey = (raw?: string) =>\n resolveTuiSessionKey({\n raw,\n sessionScope,\n currentAgentId,\n sessionMainKey,\n });\n let tuiSettings = loadTuiSettings();\n initTuiTheme({ themeId: opts.theme ?? tuiSettings.theme });\n const state = createInitialState(startup.sessionKey);\n state.scopedModelRefs = loadScopedModelRefs();\n state.showThinking = tuiSettings.showThinking;\n state.toolsExpanded = tuiSettings.toolsExpanded;\n const assembler = new StreamAssembler();\n\n let extensionRegistry: ExtensionRegistryImpl | undefined;\n if (isLocalMode) {\n extensionRegistry = await loadExtensionsForTuiLocalMode();\n }\n\n const client: TuiBackend = isLocalMode\n ? new EmbeddedBackend({ extensionRegistry })\n : new GatewaySseBackend({ url: opts.url ?? 'http://localhost:3120', token: opts.token });\n\n const keybindings = createXopcTuiKeybindingsManager();\n setKeybindings(keybindings);\n\n let modelChoices: TuiModelChoice[] = [];\n const cycleModelChoices = (): TuiModelChoice[] =>\n filterModelsForCycle(modelChoices, state.scopedModelRefs);\n\n const refreshCycleModels = () => {\n bottomBar.invalidate();\n tui.requestRender();\n };\n\n const tui = new TUI(new ProcessTerminal());\n const dedupeBackspace = createBackspaceDeduper();\n tui.addInputListener((data) => {\n const next = dedupeBackspace(data);\n if (next.length === 0) {\n return { consume: true };\n }\n return { data: next };\n });\n\n const header = new TuiHeader(() => ({\n version: packageJson.version ?? 'dev',\n connectionLabel: client.connectionLabel,\n sessionKey: state.currentSessionKey,\n showHints: tuiSettings.showStartupHints,\n }));\n const statusContainer = new Container();\n const bottomBar = new TuiBottomBar(() => state, () => opts.thinking);\n const chatLog = new ChatLog();\n chatLog.setToolsExpanded(state.toolsExpanded);\n const editor = new CustomEditor(tui, editorTheme, keybindings);\n const root = new Container();\n root.addChild(header);\n root.addChild(chatLog);\n root.addChild(statusContainer);\n root.addChild(editor);\n root.addChild(bottomBar);\n tui.addChild(root);\n tui.setFocus(editor);\n\n let isBashMode = false;\n let isBashExcludeContext = false;\n\n const updateEditorBorderColor = () => {\n if (isBashMode) {\n editor.borderColor = isBashExcludeContext\n ? getBashExcludeBorderColor()\n : getBashModeBorderColor();\n } else {\n const level = state.sessionInfo.thinkingLevel ?? opts.thinking ?? 'off';\n editor.borderColor = getThinkingBorderColor(level);\n }\n tui.requestRender();\n };\n\n editor.onChange = (text: string) => {\n const trimmed = text.trimStart();\n const nextExclude = trimmed.startsWith('!!');\n const nextBash = trimmed.startsWith('!');\n if (nextBash !== isBashMode || nextExclude !== isBashExcludeContext) {\n isBashMode = nextBash;\n isBashExcludeContext = nextExclude;\n updateEditorBorderColor();\n }\n };\n\n const { openOverlay, closeOverlay } = createOverlayHandlers(tui, editor);\n\n const slashCommands = getSlashCommands(isLocalMode);\n\n const extensionRuntime = createTuiExtensionRuntime({\n registry: extensionRegistry,\n tui,\n chatLog,\n header,\n bottomBar,\n getState: () => state,\n baseSlashCommands: slashCommands,\n cwd: process.cwd(),\n fdPath: resolveFdPath(),\n openOverlay,\n closeOverlay,\n onInvalidate: () => {\n updateHeader();\n updateFooter();\n tui.requestRender();\n },\n });\n\n editor.setAutocompleteProvider(extensionRuntime.autocompleteProvider);\n\n let statusLoader: Loader | null = null;\n let statusStartedAt: number | null = null;\n let lastActivityStatus = '';\n let elapsedTimerId: ReturnType<typeof setInterval> | null = null;\n const busyStates = new Set(['sending', 'waiting', 'streaming', 'running', 'compacting']);\n\n const syncTerminalProgress = () => {\n if (!tuiSettings.showTerminalProgress) {\n tui.terminal.setProgress(false);\n return;\n }\n tui.terminal.setProgress(busyStates.has(state.activityStatus));\n };\n\n let lastStreamActivityAt = Date.now();\n let streamWatchdogId: ReturnType<typeof setInterval> | null = null;\n\n const touchStreamingActivity = () => {\n lastStreamActivityAt = Date.now();\n };\n\n const formatElapsed = (startMs: number) => {\n const totalSeconds = Math.max(0, Math.floor((Date.now() - startMs) / 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\n const renderStatus = () => {\n const isBusy = busyStates.has(state.activityStatus);\n if (isBusy) {\n if (!statusStartedAt || lastActivityStatus !== state.activityStatus) {\n statusStartedAt = Date.now();\n }\n if (!statusLoader) {\n statusContainer.clear();\n statusLoader = new Loader(\n tui,\n (spinner) => theme.accent(spinner),\n (text) => theme.bold(theme.accentSoft(text)),\n '',\n );\n statusContainer.addChild(statusLoader);\n }\n const elapsed = formatElapsed(statusStartedAt);\n statusLoader.setMessage(\n `${state.progressMessage ?? state.activityStatus} • ${elapsed} | ${state.connectionStatus}`,\n );\n if (!elapsedTimerId) {\n elapsedTimerId = setInterval(() => {\n if (statusStartedAt && statusLoader) {\n const el = formatElapsed(statusStartedAt);\n statusLoader.setMessage(\n `${state.progressMessage ?? state.activityStatus} • ${el} | ${state.connectionStatus}`,\n );\n }\n }, 1000);\n }\n } else {\n state.progressMessage = null;\n statusStartedAt = null;\n if (elapsedTimerId) {\n clearInterval(elapsedTimerId);\n elapsedTimerId = null;\n }\n statusLoader?.stop();\n statusLoader = null;\n statusContainer.clear();\n }\n lastActivityStatus = state.activityStatus;\n bottomBar.invalidate();\n syncTerminalProgress();\n tui.requestRender();\n };\n\n const setActivityStatus = (status: string) => {\n state.activityStatus = status as TuiState['activityStatus'];\n renderStatus();\n };\n\n const setConnectionStatus = (text: string) => {\n state.connectionStatus = text;\n renderStatus();\n };\n\n const updateHeader = () => {\n header.invalidate();\n syncTerminalTitle();\n };\n\n const syncTerminalTitle = () => {\n const shortKey =\n state.currentSessionKey.length > 48\n ? `${state.currentSessionKey.slice(0, 45)}…`\n : state.currentSessionKey;\n tui.terminal.setTitle(`xopc · ${shortKey}`);\n };\n\n const updateFooter = () => {\n bottomBar.invalidate();\n };\n\n const refreshModelChoices = async () => {\n try {\n modelChoices = await client.listModels();\n } catch {\n modelChoices = [];\n }\n bottomBar.invalidate();\n tui.requestRender();\n };\n\n let finishTui: (() => void) | null = null;\n let exitResult: TuiResult = { exitReason: 'exit' };\n\n const requestExit = () => {\n if (state.exitRequested) return;\n state.exitRequested = true;\n if (elapsedTimerId) {\n clearInterval(elapsedTimerId);\n elapsedTimerId = null;\n }\n if (streamWatchdogId) {\n clearInterval(streamWatchdogId);\n streamWatchdogId = null;\n }\n client.stop();\n tui.terminal.setProgress(false);\n void drainAndStopTuiSafely(tui).then(() => {\n restoreStdio();\n finishTui?.();\n process.exit(0);\n });\n };\n\n const sessionActions = createSessionActions({\n client,\n chatLog,\n tui,\n state,\n assembler,\n resolveSessionKey,\n updateHeader,\n updateFooter,\n setActivityStatus,\n onAgentIdChange: (agentId) => {\n currentAgentId = agentId;\n },\n });\n\n const {\n refreshSessionInfo,\n loadHistory: loadSessionHistory,\n setSession,\n abortActive,\n resetCurrentSession,\n clearChatForSessionSwitch,\n } = sessionActions;\n\n const refreshSessionInfoWithBorder = async () => {\n await refreshSessionInfo();\n updateEditorBorderColor();\n };\n\n const resolveModelChoiceIndex = (): number => {\n const choices = cycleModelChoices();\n if (choices.length === 0) return -1;\n const p = state.sessionInfo.modelProvider;\n const m = state.sessionInfo.model;\n if (p && m) {\n const byParts = choices.findIndex((x) => x.provider === p && x.id === m);\n if (byParts >= 0) return byParts;\n }\n if (m?.includes('/')) {\n const [a, b] = m.split('/', 2);\n const bySlash = choices.findIndex((x) => x.provider === a && x.id === b);\n if (bySlash >= 0) return bySlash;\n }\n return 0;\n };\n\n const cycleModel = (dir: 'forward' | 'backward') => {\n const choices = cycleModelChoices();\n if (choices.length === 0) {\n void refreshModelChoices().then(() => {\n if (cycleModelChoices().length === 0) {\n chatLog.addSystem('No models available to cycle.');\n tui.requestRender();\n return;\n }\n cycleModel(dir);\n });\n return;\n }\n const idx = resolveModelChoiceIndex();\n const base = idx >= 0 ? idx : 0;\n const delta = dir === 'forward' ? 1 : -1;\n const next = choices[(base + delta + choices.length) % choices.length]!;\n sendMessage(`/switch ${next.provider}/${next.id}`);\n };\n\n const handleCtrlZ = () => {\n if (process.platform === 'win32') {\n chatLog.addSystem('Suspend (Ctrl+Z) is not supported on Windows.');\n tui.requestRender();\n return;\n }\n const suspendKeepAlive = setInterval(() => {}, 2 ** 30);\n const ignoreSigint = () => {};\n process.on('SIGINT', ignoreSigint);\n process.once('SIGCONT', () => {\n clearInterval(suspendKeepAlive);\n process.removeListener('SIGINT', ignoreSigint);\n tui.start();\n tui.setFocus(editor);\n tui.requestRender(true);\n });\n try {\n tui.stop();\n process.kill(0, 'SIGTSTP');\n } catch {\n clearInterval(suspendKeepAlive);\n process.removeListener('SIGINT', ignoreSigint);\n }\n };\n\n const openExternalEditor = () => {\n const dir = mkdtempSync(join(tmpdir(), 'xopc-tui-edit-'));\n const filePath = join(dir, 'message.md');\n writeFileSync(filePath, editor.getText(), 'utf8');\n const editorBin = process.env.EDITOR || process.env.VISUAL || 'vi';\n void (async () => {\n await withTuiSuspended(tui, async () => {\n spawnSync(editorBin, [filePath], { stdio: 'inherit' });\n });\n try {\n const next = readFileSync(filePath, 'utf8');\n editor.setText(next.replace(/\\r\\n/g, '\\n'));\n } catch {\n // ignore\n }\n try {\n unlinkSync(filePath);\n } catch {\n // ignore\n }\n tui.setFocus(editor);\n tui.requestRender(true);\n })();\n };\n\n const isAgentBusy = () =>\n state.activeRunId != null || state.isCompacting || busyStates.has(state.activityStatus);\n\n const steerMessage = (text: string) => {\n chatLog.addUser(text);\n touchStreamingActivity();\n tui.requestRender();\n void client\n .steerChat({ sessionKey: state.currentSessionKey, message: text })\n .then(({ ok }) => {\n if (!ok) {\n chatLog.addSystem(\n theme.dim(\n 'Could not steer — no active run or steer failed. Press Escape to abort, or Alt+Enter to queue a follow-up.',\n ),\n );\n } else {\n chatLog.addSystem(\n theme.dim('Steered — message injects at the next tool boundary (pi-style).'),\n );\n }\n tui.requestRender();\n })\n .catch((error: unknown) => {\n const errorMessage = error instanceof Error ? error.message : String(error);\n chatLog.addSystem(theme.dim(`Steer failed: ${errorMessage}`));\n tui.requestRender();\n });\n };\n\n const sendMessage = (text: string) => {\n if (state.isCompacting) {\n state.compactionQueue.push(text);\n chatLog.addSystem(\n theme.dim(`Queued during compaction (${state.compactionQueue.length}). Sends when compact finishes.`),\n );\n bottomBar.invalidate();\n tui.requestRender();\n return;\n }\n\n if (state.activeRunId) {\n chatLog.addSystem(\n 'A response is still in progress. Press Enter to steer, Alt+Enter to queue, or Escape to abort.',\n );\n tui.requestRender();\n return;\n }\n\n chatLog.addUser(text);\n setActivityStatus('sending');\n touchStreamingActivity();\n tui.requestRender();\n\n void client\n .sendChat({\n sessionKey: state.currentSessionKey,\n message: text,\n thinking: opts.thinking,\n })\n .catch((error: unknown) => {\n const errorMessage = error instanceof Error ? error.message : String(error);\n chatLog.addSystem(`❌ Failed to send: ${errorMessage}`);\n setActivityStatus('idle');\n tui.requestRender();\n });\n };\n\n const runCompaction = async () => {\n if (state.isCompacting) return;\n state.isCompacting = true;\n setActivityStatus('compacting');\n chatLog.addSystem(theme.dim('Compacting session…'));\n tui.requestRender();\n try {\n const result = await client.compactSession(state.currentSessionKey, { force: true });\n chatLog.addSystem(result.summary ?? (result.compacted ? 'Session compacted' : 'Nothing to compact'));\n if (result.compacted) {\n assembler.clear();\n clearPendingToolCallIds();\n state.historyLoaded = false;\n await loadSessionHistory();\n }\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n chatLog.addSystem(`❌ Compaction failed: ${errorMessage}`);\n } finally {\n state.isCompacting = false;\n setActivityStatus('idle');\n await refreshSessionInfoWithBorder();\n const queued = state.compactionQueue.shift();\n if (queued && !state.activeRunId) {\n sendMessage(queued);\n }\n updateFooter();\n tui.requestRender();\n }\n };\n\n const applyTuiSettings = (settings: TuiSettings) => {\n tuiSettings = { ...settings };\n saveTuiSettings(tuiSettings);\n state.showThinking = tuiSettings.showThinking;\n state.toolsExpanded = tuiSettings.toolsExpanded;\n chatLog.setToolsExpanded(tuiSettings.toolsExpanded);\n applyThemeById(tuiSettings.theme);\n header.invalidate();\n updateEditorBorderColor();\n syncTerminalProgress();\n bottomBar.invalidate();\n tui.requestRender();\n };\n\n const previewTheme = (themeId: string) => {\n applyThemeById(themeId);\n updateEditorBorderColor();\n tui.requestRender();\n };\n\n const reloadKeybindings = () => {\n keybindings.reload();\n setKeybindings(keybindings);\n tui.requestRender();\n };\n\n const uiOverlays = {\n openSessionPicker: () => {},\n openScopedModels: () => {},\n openSettings: () => {},\n reloadKeybindings: () => reloadKeybindings(),\n };\n\n const handleCommand = createTuiCommandHandler({\n state,\n chatLog,\n tui,\n assembler,\n isLocalMode,\n abortActive,\n sendMessage,\n requestExit,\n updateFooter,\n keybindings,\n uiOverlays,\n runCompaction,\n extensionSlashCommands: extensionRuntime.slashCommands,\n currentAgentId,\n setSession,\n resetSession: resetCurrentSession,\n });\n\n const { runLocalShellLine } = createLocalShellRunner({\n chatLog,\n tui,\n editor,\n openOverlay,\n closeOverlay,\n pauseStdioFilter: () => stdioFilter.pause(),\n resumeStdioFilter: () => stdioFilter.resume(),\n runWithInheritedStdio: async (work) => {\n await withTuiSuspended(tui, work);\n },\n });\n\n const submitCore = createEditorSubmitHandler({\n editor,\n handleCommand,\n sendMessage,\n handleBangLine: runLocalShellLine,\n isAgentBusy,\n steerWhileBusy: steerMessage,\n });\n\n const submitBurst = createSubmitBurstCoalescer({\n submit: submitCore,\n enabled: shouldEnableWindowsGitBashPasteFallback(),\n });\n editor.onSubmit = submitBurst;\n\n const flushFollowUpQueue = () => {\n if (state.exitRequested) return;\n if (state.activeRunId) return;\n const next = state.messageFollowUpQueue.shift();\n if (next === undefined) return;\n sendMessage(next);\n };\n\n const handleFollowUp = () => {\n const text = editor.getText().trim();\n if (!text) return;\n if (isAgentBusy()) {\n editor.addToHistory(text);\n state.messageFollowUpQueue.push(text);\n editor.setText('');\n chatLog.addSystem(\n theme.dim(\n `Queued follow-up (${state.messageFollowUpQueue.length} in queue). Next sends when this reply finishes.`,\n ),\n );\n bottomBar.invalidate();\n tui.requestRender();\n return;\n }\n submitBurst(text);\n };\n\n const handleDequeue = () => {\n if (state.messageFollowUpQueue.length === 0) {\n chatLog.addSystem(theme.dim('No queued messages to restore.'));\n tui.requestRender();\n return;\n }\n const queued = [...state.messageFollowUpQueue];\n state.messageFollowUpQueue.length = 0;\n const current = editor.getText().trim();\n const combined = [queued.join('\\n\\n'), current].filter(Boolean).join('\\n\\n');\n editor.setText(combined);\n chatLog.addSystem(\n theme.dim(\n `Restored ${queued.length} queued message${queued.length > 1 ? 's' : ''} to editor.`,\n ),\n );\n bottomBar.invalidate();\n tui.requestRender();\n };\n\n const setSessionKey = (key: string) => {\n state.currentSessionKey = resolveSessionKey(key);\n updateAgentFromPicker(key);\n };\n\n const updateAgentFromPicker = (key: string) => {\n const parsed = parseAgentSessionKey(resolveSessionKey(key));\n if (parsed?.agentId) {\n currentAgentId = parsed.agentId;\n }\n };\n\n let ctrlCHandling = false;\n const handleCtrlC = () => {\n if (ctrlCHandling) return;\n ctrlCHandling = true;\n try {\n const now = Date.now();\n const decision = resolveCtrlCAction({\n hasInput: editor.getText().trim().length > 0,\n now,\n lastCtrlCAt: state.lastCtrlCAt,\n });\n state.lastCtrlCAt = decision.nextLastCtrlCAt;\n if (decision.action === 'clear') {\n editor.setText('');\n setActivityStatus('cleared input; press ctrl+c again to exit');\n tui.requestRender();\n return;\n }\n if (decision.action === 'exit') {\n requestExit();\n return;\n }\n setActivityStatus('press ctrl+c again to exit');\n tui.requestRender();\n } finally {\n ctrlCHandling = false;\n }\n };\n\n const setModelChoices = (models: TuiModelChoice[]) => {\n modelChoices = models;\n };\n\n const pickerSvc = {\n tui,\n editor,\n openOverlay,\n closeOverlay,\n chatLog,\n client,\n sendMessage,\n refreshSessionInfo,\n updateHeader,\n state,\n setSessionKey,\n clearChatForSessionSwitch,\n loadSessionHistory,\n setModelChoices,\n getScopedModelRefs: () => state.scopedModelRefs,\n setScopedModelRefs: (refs: string[] | null) => {\n state.scopedModelRefs = refs;\n saveScopedModelRefs(refs);\n },\n refreshCycleModels,\n getTuiSettings: () => ({ ...tuiSettings }),\n applyTuiSettings,\n previewTheme,\n reloadKeybindings,\n };\n\n uiOverlays.openSessionPicker = () => void openSessionPickerOverlay(pickerSvc);\n uiOverlays.openScopedModels = () => void openScopedModelsOverlay(pickerSvc);\n uiOverlays.openSettings = () => openSettingsOverlay(pickerSvc);\n\n const handleDoubleEscape = () => {\n switch (tuiSettings.doubleEscapeAction) {\n case 'tree':\n chatLog.addSystem(theme.dim('Session tree is not available in xopc TUI yet.'));\n break;\n case 'fork':\n chatLog.addSystem(theme.dim('Session fork is not available in xopc TUI yet.'));\n break;\n default:\n break;\n }\n tui.requestRender();\n };\n\n editor.onEscape = () => {\n if (state.activeRunId) {\n void abortActive();\n return;\n }\n if (editor.getText().trim().length > 0) return;\n const now = Date.now();\n if (now - state.lastEscapeAt <= DOUBLE_ESCAPE_WINDOW_MS) {\n state.lastEscapeAt = 0;\n handleDoubleEscape();\n return;\n }\n state.lastEscapeAt = now;\n };\n editor.onCtrlD = () => requestExit();\n\n editor.onAction('app.clear', handleCtrlC);\n editor.onAction('app.exit', () => requestExit());\n editor.onAction('app.suspend', handleCtrlZ);\n editor.onAction('app.thinking.cycle', () => {\n const cur = state.sessionInfo.thinkingLevel ?? opts.thinking ?? 'medium';\n sendMessage(`/think ${nextThinkLevel(cur)}`);\n updateEditorBorderColor();\n });\n editor.onAction('app.model.cycleForward', () => cycleModel('forward'));\n editor.onAction('app.model.cycleBackward', () => cycleModel('backward'));\n editor.onAction('app.model.select', () => void openModelPickerOverlay(pickerSvc));\n editor.onAction('app.session.resume', () => void openSessionPickerOverlay(pickerSvc));\n editor.onAction('app.tools.expand', () => {\n state.toolsExpanded = !state.toolsExpanded;\n tuiSettings = { ...tuiSettings, toolsExpanded: state.toolsExpanded };\n saveTuiSettings(tuiSettings);\n chatLog.setToolsExpanded(state.toolsExpanded);\n setActivityStatus(state.toolsExpanded ? 'tools expanded' : 'tools collapsed');\n tui.requestRender();\n });\n editor.onAction('app.thinking.toggle', () => {\n state.showThinking = !state.showThinking;\n tuiSettings = { ...tuiSettings, showThinking: state.showThinking };\n saveTuiSettings(tuiSettings);\n updateFooter();\n tui.requestRender();\n });\n editor.onAction('app.editor.external', openExternalEditor);\n editor.onPasteImage = () => {\n void (async () => {\n const filePath = await saveClipboardImageToTempFile();\n if (!filePath) return;\n editor.insertTextAtCursor(filePath);\n chatLog.addSystem(theme.dim(`Pasted image path: ${filePath}`));\n tui.requestRender();\n })();\n };\n editor.onAction('app.message.followUp', handleFollowUp);\n editor.onAction('app.message.dequeue', handleDequeue);\n\n streamWatchdogId = setInterval(() => {\n if (!state.activeRunId) return;\n if (!busyStates.has(state.activityStatus)) return;\n if (Date.now() - lastStreamActivityAt < DEFAULT_STREAMING_WATCHDOG_MS) return;\n\n const rid = state.activeRunId;\n const finalText = assembler.finalize(rid, state.showThinking);\n if (finalText) {\n chatLog.finalizeAssistant(finalText, rid);\n }\n chatLog.addSystem(\n '⚠️ No stream activity for 30s; UI reset (connection may have stalled). Retry or check gateway.',\n );\n state.activeRunId = null;\n setActivityStatus('idle');\n void refreshSessionInfoWithBorder().finally(() => {\n updateFooter();\n tui.requestRender();\n });\n flushFollowUpQueue();\n tui.requestRender();\n }, 5000);\n\n const onAgentRunEnded = () => {\n state.progressMessage = null;\n void refreshSessionInfoWithBorder().finally(() => {\n updateFooter();\n tui.requestRender();\n });\n flushFollowUpQueue();\n };\n\n client.onEvent = (evt: TuiEvent) => {\n const data = (evt.data ?? {}) as Record<string, unknown>;\n dispatchAgentSSE(\n evt.event,\n data,\n state,\n chatLog,\n assembler,\n tui,\n setActivityStatus,\n touchStreamingActivity,\n onAgentRunEnded,\n );\n };\n\n client.onConnected = () => {\n state.isConnected = true;\n setConnectionStatus(isLocalMode ? 'local ready' : 'gateway connected');\n touchStreamingActivity();\n void (async () => {\n await refreshSessionInfoWithBorder();\n await refreshModelChoices();\n await loadSessionHistory();\n updateHeader();\n updateFooter();\n tui.requestRender();\n if (!state.autoMessageSent && opts.message) {\n state.autoMessageSent = true;\n sendMessage(opts.message);\n }\n })();\n };\n\n client.onDisconnected = (reason: string) => {\n const wasConnected = state.isConnected;\n state.isConnected = false;\n touchStreamingActivity();\n if (isLocalMode) {\n setConnectionStatus(`local stopped: ${reason}`);\n } else {\n const hint =\n wasConnected || state.historyLoaded\n ? ` (${reason}). Reconnecting broadcast stream…`\n : `. Ensure gateway is running (xopc gateway) or use --local.`;\n setConnectionStatus(`disconnected${hint}`);\n if (!wasConnected && !state.historyLoaded) {\n const gatewayUrl = opts.url ?? 'http://localhost:3120';\n chatLog.addSystem(\n `Cannot reach gateway at ${gatewayUrl}.\\n` +\n 'Start the gateway (`xopc gateway`) or run `xopc tui --local` for embedded mode.',\n );\n }\n }\n tui.requestRender();\n };\n\n client.onGap = (info) => {\n chatLog.addSystem(\n `⚠️ Event gap: expected ${info.expected}, received ${info.received}. Some updates may be missing.`,\n );\n setConnectionStatus(`event gap: expected ${info.expected}, got ${info.received}`);\n tui.requestRender();\n };\n\n const sigintHandler = () => handleCtrlC();\n const sigtermHandler = () => requestExit();\n process.on('SIGINT', sigintHandler);\n process.on('SIGTERM', sigtermHandler);\n\n updateHeader();\n updateEditorBorderColor();\n setConnectionStatus(isLocalMode ? 'starting local runtime' : 'connecting');\n updateFooter();\n await extensionRuntime.activate();\n tui.start();\n client.start();\n\n await new Promise<void>((resolve) => {\n finishTui = () => {\n process.removeListener('SIGINT', sigintHandler);\n process.removeListener('SIGTERM', sigtermHandler);\n if (streamWatchdogId) {\n clearInterval(streamWatchdogId);\n streamWatchdogId = null;\n }\n finishTui = null;\n resolve();\n };\n });\n\n return exitResult;\n}\n"],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
/** Trim non-empty strings; otherwise undefined. */
|
|
2
2
|
export declare function normalizeOptionalString(value: unknown): string | undefined;
|
|
3
3
|
export declare function normalizeLowercaseStringOrEmpty(value: unknown): string;
|
|
4
|
+
/** Lowercase trimmed string, or undefined when empty/missing. */
|
|
5
|
+
export declare function normalizeOptionalLowercaseString(value: unknown): string | undefined;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
|
|
1
2
|
//#region src/utils/string-coerce.ts
|
|
2
3
|
/** Trim non-empty strings; otherwise undefined. */
|
|
3
4
|
function normalizeOptionalString(value) {
|
|
@@ -9,7 +10,15 @@ function normalizeLowercaseStringOrEmpty(value) {
|
|
|
9
10
|
if (typeof value !== "string") return "";
|
|
10
11
|
return value.trim().toLowerCase();
|
|
11
12
|
}
|
|
13
|
+
/** Lowercase trimmed string, or undefined when empty/missing. */
|
|
14
|
+
function normalizeOptionalLowercaseString(value) {
|
|
15
|
+
if (typeof value !== "string") return;
|
|
16
|
+
const trimmed = value.trim().toLowerCase();
|
|
17
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
18
|
+
}
|
|
19
|
+
var init_string_coerce = __esmMin((() => {}));
|
|
12
20
|
//#endregion
|
|
13
|
-
|
|
21
|
+
init_string_coerce();
|
|
22
|
+
export { init_string_coerce, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString };
|
|
14
23
|
|
|
15
24
|
//# sourceMappingURL=string-coerce.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"string-coerce.js","names":[],"sources":["../../../src/utils/string-coerce.ts"],"sourcesContent":["/** Trim non-empty strings; otherwise undefined. */\nexport function normalizeOptionalString(value: unknown): string | undefined {\n if (typeof value !== 'string') {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nexport function normalizeLowercaseStringOrEmpty(value: unknown): string {\n if (typeof value !== 'string') {\n return '';\n }\n return value.trim().toLowerCase();\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"string-coerce.js","names":[],"sources":["../../../src/utils/string-coerce.ts"],"sourcesContent":["/** Trim non-empty strings; otherwise undefined. */\nexport function normalizeOptionalString(value: unknown): string | undefined {\n if (typeof value !== 'string') {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nexport function normalizeLowercaseStringOrEmpty(value: unknown): string {\n if (typeof value !== 'string') {\n return '';\n }\n return value.trim().toLowerCase();\n}\n\n/** Lowercase trimmed string, or undefined when empty/missing. */\nexport function normalizeOptionalLowercaseString(value: unknown): string | undefined {\n if (typeof value !== 'string') {\n return undefined;\n }\n const trimmed = value.trim().toLowerCase();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n"],"mappings":";;;AACA,SAAgB,wBAAwB,OAAoC;AAC1E,KAAI,OAAO,UAAU,SACnB;CAEF,MAAM,UAAU,MAAM,MAAM;AAC5B,QAAO,QAAQ,SAAS,IAAI,UAAU,KAAA;;AAGxC,SAAgB,gCAAgC,OAAwB;AACtE,KAAI,OAAO,UAAU,SACnB,QAAO;AAET,QAAO,MAAM,MAAM,CAAC,aAAa;;;AAInC,SAAgB,iCAAiC,OAAoC;AACnF,KAAI,OAAO,UAAU,SACnB;CAEF,MAAM,UAAU,MAAM,MAAM,CAAC,aAAa;AAC1C,QAAO,QAAQ,SAAS,IAAI,UAAU,KAAA"}
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* STT config slice resolution — maps persisted config to per-provider raw config.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* (`tools.media.audio.openai`, `tools.media.audio.alibaba`, …).
|
|
4
|
+
* Reads `tools.media.audio.providers.<id>` only — there is no legacy flat-key form.
|
|
6
5
|
*/
|
|
7
6
|
import type { STTConfig } from './types.js';
|
|
8
|
-
/** Top-level `tools.media.audio` keys that are not provider config buckets. */
|
|
9
|
-
export declare const STT_CONFIG_RESERVED_KEYS: Set<string>;
|
|
10
7
|
/** Built-in env fallbacks when config slice has no apiKey. */
|
|
11
8
|
export declare const STT_LEGACY_ENV_KEYS: Record<string, string>;
|
|
12
|
-
/** Collect provider-id → raw config entries from providers map
|
|
9
|
+
/** Collect provider-id → raw config entries from the `providers` map. */
|
|
13
10
|
export declare function collectSttProviderConfigEntries(config: Partial<STTConfig> | Record<string, unknown> | undefined): Record<string, Record<string, unknown>>;
|
|
14
11
|
/** Resolve the raw config slice for one provider id. */
|
|
15
12
|
export declare function resolveSttProviderConfigSlice(providerId: string, config: Partial<STTConfig> | Record<string, unknown> | undefined): Record<string, unknown>;
|
|
@@ -1,14 +1,4 @@
|
|
|
1
1
|
//#region src/voice/stt/config-slice.ts
|
|
2
|
-
/** Top-level `tools.media.audio` keys that are not provider config buckets. */
|
|
3
|
-
const STT_CONFIG_RESERVED_KEYS = new Set([
|
|
4
|
-
"enabled",
|
|
5
|
-
"provider",
|
|
6
|
-
"providers",
|
|
7
|
-
"models",
|
|
8
|
-
"fallback",
|
|
9
|
-
"timeoutMs",
|
|
10
|
-
"sharedModels"
|
|
11
|
-
]);
|
|
12
2
|
/** Built-in env fallbacks when config slice has no apiKey. */
|
|
13
3
|
const STT_LEGACY_ENV_KEYS = {
|
|
14
4
|
openai: "OPENAI_API_KEY",
|
|
@@ -17,23 +7,12 @@ const STT_LEGACY_ENV_KEYS = {
|
|
|
17
7
|
function asRecord(value) {
|
|
18
8
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
19
9
|
}
|
|
20
|
-
|
|
21
|
-
return asRecord(value) ?? {};
|
|
22
|
-
}
|
|
23
|
-
/** Collect provider-id → raw config entries from providers map + legacy flat keys. */
|
|
10
|
+
/** Collect provider-id → raw config entries from the `providers` map. */
|
|
24
11
|
function collectSttProviderConfigEntries(config) {
|
|
25
|
-
const
|
|
12
|
+
const providers = asRecord((config ?? {}).providers);
|
|
13
|
+
if (!providers) return {};
|
|
26
14
|
const entries = {};
|
|
27
|
-
const providers = asRecord(
|
|
28
|
-
if (providers) for (const [providerId, value] of Object.entries(providers)) entries[providerId] = {
|
|
29
|
-
...entries[providerId],
|
|
30
|
-
...asProviderConfig(value)
|
|
31
|
-
};
|
|
32
|
-
for (const [key, value] of Object.entries(raw)) {
|
|
33
|
-
if (STT_CONFIG_RESERVED_KEYS.has(key)) continue;
|
|
34
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) continue;
|
|
35
|
-
if (entries[key] === void 0) entries[key] = asProviderConfig(value);
|
|
36
|
-
}
|
|
15
|
+
for (const [providerId, value] of Object.entries(providers)) entries[providerId] = { ...asRecord(value) ?? {} };
|
|
37
16
|
return entries;
|
|
38
17
|
}
|
|
39
18
|
/** Resolve the raw config slice for one provider id. */
|
|
@@ -71,6 +50,6 @@ function readSttProviderFields(slice, entryOverride) {
|
|
|
71
50
|
};
|
|
72
51
|
}
|
|
73
52
|
//#endregion
|
|
74
|
-
export {
|
|
53
|
+
export { STT_LEGACY_ENV_KEYS, collectSttProviderConfigEntries, readSttProviderFields, resolveSttProviderConfigSlice };
|
|
75
54
|
|
|
76
55
|
//# sourceMappingURL=config-slice.js.map
|