@xopcai/xopc 0.0.103 → 0.0.104
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -4
- package/README.zh-CN.md +7 -4
- package/dist/_virtual/_rolldown/runtime.js +2 -3
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/feishu/src/adapters/cli-login.d.ts +1 -1
- package/dist/extensions/feishu/src/adapters/cli-login.js +1 -1
- package/dist/extensions/feishu/src/adapters/cli-login.js.map +1 -1
- package/dist/extensions/feishu/src/adapters/gateway-setup.d.ts +2 -0
- package/dist/extensions/feishu/src/adapters/gateway-setup.js +225 -0
- package/dist/extensions/feishu/src/adapters/gateway-setup.js.map +1 -0
- package/dist/extensions/feishu/src/index.d.ts +8 -1
- package/dist/extensions/feishu/src/index.js +14 -1
- package/dist/extensions/feishu/src/index.js.map +1 -0
- package/dist/extensions/feishu/src/outbound/outbound-adapter.js +1 -1
- package/dist/extensions/feishu/src/plugin.d.ts +2 -1
- package/dist/extensions/feishu/src/plugin.js +2 -0
- package/dist/extensions/feishu/src/plugin.js.map +1 -1
- package/dist/extensions/feishu/src/streaming/streaming-adapter.js +1 -1
- package/dist/extensions/feishu/src/transport/webhook/monitor.js +1 -1
- package/dist/extensions/feishu/xopc.extension.json +66 -1
- package/dist/extensions/telegram/src/adapters/gateway-setup.d.ts +2 -0
- package/dist/extensions/telegram/src/adapters/gateway-setup.js +146 -0
- package/dist/extensions/telegram/src/adapters/gateway-setup.js.map +1 -0
- package/dist/extensions/telegram/src/adapters/security-adapter.js +1 -1
- package/dist/extensions/telegram/src/command-handler.js +1 -2
- package/dist/extensions/telegram/src/command-handler.js.map +1 -1
- package/dist/extensions/telegram/src/config-schema.js +2 -2
- package/dist/extensions/telegram/src/config-schema.js.map +1 -1
- package/dist/extensions/telegram/src/doctor.d.ts +1 -0
- package/dist/extensions/telegram/src/doctor.js +68 -0
- package/dist/extensions/telegram/src/doctor.js.map +1 -1
- package/dist/extensions/telegram/src/index.d.ts +8 -1
- package/dist/extensions/telegram/src/index.js +15 -2
- package/dist/extensions/telegram/src/index.js.map +1 -0
- package/dist/extensions/telegram/src/plugin.d.ts +13 -5
- package/dist/extensions/telegram/src/plugin.js +32 -12
- package/dist/extensions/telegram/src/plugin.js.map +1 -1
- package/dist/extensions/telegram/src/proxy-fetch.js +22 -5
- package/dist/extensions/telegram/src/proxy-fetch.js.map +1 -1
- package/dist/extensions/telegram/xopc.extension.json +412 -5
- package/dist/extensions/weixin/src/adapters/onboard-cli.js +2 -2
- package/dist/extensions/weixin/src/adapters/onboard-cli.js.map +1 -1
- package/dist/extensions/weixin/src/api/api.js +1 -1
- package/dist/extensions/weixin/src/index.d.ts +8 -0
- package/dist/extensions/weixin/src/index.js +12 -1
- package/dist/extensions/weixin/src/index.js.map +1 -0
- package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
- package/dist/extensions/weixin/src/plugin.d.ts +2 -1
- package/dist/extensions/weixin/src/plugin.js +77 -2
- package/dist/extensions/weixin/src/plugin.js.map +1 -1
- package/dist/extensions/weixin/xopc.extension.json +52 -0
- package/dist/gateway/static/root/assets/agents-CvsBrBfi.js +396 -0
- package/dist/gateway/static/root/assets/{apps-page-C5RmwmTT.js → apps-page-L-IwQTe0.js} +1 -1
- package/dist/gateway/static/root/assets/browser-BLJWD7WI.js +8 -0
- package/dist/gateway/static/root/assets/channels-settings-D95KuPeP.js +1 -0
- package/dist/gateway/static/root/assets/cron-page-CfkWXDAI.js +1 -0
- package/dist/gateway/static/root/assets/{dist-CWm8hTXZ.js → dist-C6vclgEL.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-BzYgTkS9.js → extension-debug-page-D4JYAbsX.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BmTZH6gL.js → extension-page-_T62gi6e.js} +1 -1
- package/dist/gateway/static/root/assets/extension-settings-page-CkJbjyM-.js +1 -0
- package/dist/gateway/static/root/assets/{fetch-CMoWY2Si.js → fetch-B5aiIguv.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-startup-retry-DqmLXhs6.js +1 -0
- package/dist/gateway/static/root/assets/heartbeat-config-api-HwJV1K_Y.js +1 -0
- package/dist/gateway/static/root/assets/index-BPYKW7FB.css +1 -0
- package/dist/gateway/static/root/assets/index-DvTb6wNR.js +4845 -0
- package/dist/gateway/static/root/assets/{logs-page-BjdQjHwk.js → logs-page-DsjtTjBy.js} +2 -2
- package/dist/gateway/static/root/assets/{note-detail-page-8Er4197b.js → note-detail-page-B2V7RhgD.js} +43 -43
- package/dist/gateway/static/root/assets/{note-time-CF3vf1jm.js → note-time-BG8GCTr4.js} +1 -1
- package/dist/gateway/static/root/assets/notes-page-xrcVBQ6Z.js +1 -0
- package/dist/gateway/static/root/assets/schema-form-S-QUvhul.js +1 -0
- package/dist/gateway/static/root/assets/sessions-page-CrQer6Au.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-DujQl9c7.js +2 -0
- package/dist/gateway/static/root/assets/{settings-form-section-C7qA7y0J.js → settings-form-section-r1V7dRV6.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-C9nrONQ2.js +3 -0
- package/dist/gateway/static/root/assets/{share-preview-page-Tvr5Mtq5.js → share-preview-page-DOFy0FNt.js} +1 -1
- package/dist/gateway/static/root/assets/skills-page-DmTsrs_a.js +2 -0
- package/dist/gateway/static/root/assets/{theme-store-HTvJlFLL.js → theme-store-Bo3j5Ovv.js} +1 -1
- package/dist/gateway/static/root/assets/url-WgQIjFZu.js +3 -0
- package/dist/gateway/static/root/assets/voice-api-key-field-AjmUAlEQ.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-page.utils-CeBkAjP7.js → workflow-page.utils-DLEJ92gK.js} +1 -1
- package/dist/gateway/static/root/assets/workflows-page-BnjjKrM1.js +27 -0
- package/dist/gateway/static/root/index.html +6 -5
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +18 -6
- package/dist/src/agent/agent-manager.js +60 -35
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/builtin-agent-ids.d.ts +2 -0
- package/dist/src/agent/builtin-agent-ids.js +17 -0
- package/dist/src/agent/builtin-agent-ids.js.map +1 -0
- package/dist/src/agent/child-agent-factory.d.ts +4 -0
- package/dist/src/agent/child-agent-factory.js +28 -8
- package/dist/src/agent/child-agent-factory.js.map +1 -1
- package/dist/src/agent/context/workspace-seed.js +1 -1
- package/dist/src/agent/context/workspace-templates/AGENTS.md +23 -184
- package/dist/src/agent/embedded/run-turn.js +8 -2
- package/dist/src/agent/embedded/run-turn.js.map +1 -1
- package/dist/src/agent/embedded/session-tool-result-guard.js +1 -1
- package/dist/src/agent/embedded/subscribe-session.js +33 -51
- package/dist/src/agent/embedded/subscribe-session.js.map +1 -1
- package/dist/src/agent/embedded/types.d.ts +36 -35
- package/dist/src/agent/fallback/candidates.js +1 -1
- package/dist/src/agent/fallback/candidates.js.map +1 -1
- package/dist/src/agent/inbound/inbound-loop.js +1 -1
- package/dist/src/agent/inbound/turn-dispatcher.d.ts +1 -0
- package/dist/src/agent/inbound/turn-dispatcher.js +24 -5
- package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
- package/dist/src/agent/models/manager.d.ts +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/models/manager.js.map +1 -1
- package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.d.ts +1 -1
- package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js +1 -1
- package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js.map +1 -1
- package/dist/src/agent/prompt/sections/tooling.js +4 -0
- package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
- package/dist/src/agent/service/direct-turn-helpers.d.ts +1 -0
- package/dist/src/agent/service/direct-turn-helpers.js +1 -1
- package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
- package/dist/src/agent/service/process-direct-streaming.d.ts +1 -0
- package/dist/src/agent/service/process-direct-streaming.js +35 -18
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service-inbound-utils.d.ts +0 -1
- package/dist/src/agent/service-inbound-utils.js +1 -17
- package/dist/src/agent/service-inbound-utils.js.map +1 -1
- package/dist/src/agent/service.d.ts +4 -4
- package/dist/src/agent/service.js +27 -15
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/session/session-config-service.d.ts +1 -0
- package/dist/src/agent/session/session-config-service.js +9 -1
- package/dist/src/agent/session/session-config-service.js.map +1 -1
- package/dist/src/agent/session/session-inspector.d.ts +2 -1
- package/dist/src/agent/session/session-inspector.js +4 -0
- package/dist/src/agent/session/session-inspector.js.map +1 -1
- package/dist/src/agent/skills/config.js +1 -3
- package/dist/src/agent/skills/config.js.map +1 -1
- package/dist/src/agent/skills/format-skills-prompt.d.ts +1 -0
- package/dist/src/agent/skills/format-skills-prompt.js +3 -2
- package/dist/src/agent/skills/format-skills-prompt.js.map +1 -1
- package/dist/src/agent/skills/hub-pull.js +1 -1
- package/dist/src/agent/skills/index.js +20 -5
- package/dist/src/agent/skills/index.js.map +1 -1
- package/dist/src/agent/skills/installer.js +14 -27
- package/dist/src/agent/skills/installer.js.map +1 -1
- package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js +11 -1
- package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js.map +1 -1
- package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js +18 -4
- package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js.map +1 -1
- package/dist/src/agent/skills/marketplace/adapters/store/adapter.js +11 -2
- package/dist/src/agent/skills/marketplace/adapters/store/adapter.js.map +1 -1
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +2 -2
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js.map +1 -1
- package/dist/src/agent/skills/skill-manager.d.ts +4 -1
- package/dist/src/agent/skills/skill-manager.js +3 -3
- package/dist/src/agent/skills/skill-manager.js.map +1 -1
- package/dist/src/agent/skills/skill-view-path.d.ts +1 -17
- package/dist/src/agent/skills/skill-view-path.js +3 -66
- package/dist/src/agent/skills/skill-view-path.js.map +1 -1
- package/dist/src/agent/skills/test-framework.js +2 -3
- package/dist/src/agent/skills/test-framework.js.map +1 -1
- package/dist/src/agent/streaming/reasoning-visibility-sse.js +1 -0
- package/dist/src/agent/streaming/reasoning-visibility-sse.js.map +1 -1
- package/dist/src/agent/tool-manuals/browser.d.ts +1 -0
- package/{skills/browser/SKILL.md → dist/src/agent/tool-manuals/browser.js} +51 -54
- package/dist/src/agent/tool-manuals/browser.js.map +1 -0
- package/dist/src/agent/tool-manuals/index.d.ts +10 -0
- package/dist/src/agent/tool-manuals/index.js +28 -0
- package/dist/src/agent/tool-manuals/index.js.map +1 -0
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js +1 -1
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js.map +1 -1
- package/dist/src/agent/tools/factory.js +7 -5
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/index.d.ts +1 -0
- package/dist/src/agent/tools/index.js +5 -4
- package/dist/src/agent/tools/session-search-tool.js +1 -1
- package/dist/src/agent/tools/shell.js +1 -1
- package/dist/src/agent/tools/skills-tools.js +37 -8
- package/dist/src/agent/tools/skills-tools.js.map +1 -1
- package/dist/src/agent/tools/tool-manual-tool.d.ts +6 -0
- package/dist/src/agent/tools/tool-manual-tool.js +34 -0
- package/dist/src/agent/tools/tool-manual-tool.js.map +1 -0
- package/dist/src/agent/tools/web-extract.js +2 -2
- package/dist/src/agent/tools/web.js +1 -1
- package/dist/src/agent/workflow/catalog.d.ts +7 -2
- package/dist/src/agent/workflow/catalog.js +66 -25
- package/dist/src/agent/workflow/catalog.js.map +1 -1
- package/dist/src/agent/workflow/subagent-runner.d.ts +3 -0
- package/dist/src/agent/workflow/subagent-runner.js +50 -4
- package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
- package/dist/src/agent/workflow/types.d.ts +10 -0
- package/dist/src/auth/credentials.js +10 -5
- package/dist/src/auth/credentials.js.map +1 -1
- package/dist/src/browser/actions/extension-registry-bridge.js +1 -1
- package/dist/src/browser/actions/registry.js +2 -2
- package/dist/src/browser/cdp-local-launcher.js +1 -1
- package/dist/src/browser/index.js +3 -3
- package/dist/src/browser/providers/browser-ext-install.js +1 -1
- package/dist/src/browser/providers/cloakbrowser.js +1 -1
- package/dist/src/channels/catalog/channel-catalog-service.d.ts +11 -0
- package/dist/src/channels/catalog/channel-catalog-service.js +168 -0
- package/dist/src/channels/catalog/channel-catalog-service.js.map +1 -0
- package/dist/src/channels/catalog/channel-catalog-types.d.ts +22 -0
- package/dist/src/channels/catalog/channel-catalog-types.js +1 -0
- package/dist/src/channels/dock.d.ts +0 -7
- package/dist/src/channels/dock.js +1 -21
- package/dist/src/channels/index.d.ts +1 -3
- package/dist/src/channels/index.js +1 -5
- package/dist/src/channels/lifecycle-supervisor.d.ts +1 -0
- package/dist/src/channels/lifecycle-supervisor.js +11 -0
- package/dist/src/channels/lifecycle-supervisor.js.map +1 -1
- package/dist/src/channels/manager.d.ts +1 -0
- package/dist/src/channels/manager.js +3 -0
- package/dist/src/channels/manager.js.map +1 -1
- package/dist/src/channels/pairing/pairing-channel.d.ts +2 -3
- package/dist/src/channels/pairing/pairing-messages.js +1 -1
- package/dist/src/channels/pairing/pairing-messages.js.map +1 -1
- package/dist/src/channels/pairing/pairing-service.d.ts +1 -1
- package/dist/src/channels/pairing/pairing-service.js +8 -27
- package/dist/src/channels/pairing/pairing-service.js.map +1 -1
- package/dist/src/channels/plugin-types.d.ts +3 -1
- package/dist/src/channels/plugins/types.adapters.d.ts +55 -2
- package/dist/src/channels/telegram/index.js +1 -1
- package/dist/src/chat-commands/builtins/config.js +4 -4
- package/dist/src/chat-commands/builtins/config.js.map +1 -1
- package/dist/src/chat-commands/config-paths.js +1 -1
- package/dist/src/chat-commands/config-paths.js.map +1 -1
- package/dist/src/chat-commands/context.js +1 -1
- package/dist/src/chat-commands/context.js.map +1 -1
- package/dist/src/cli/bin.js +1 -1
- package/dist/src/cli/command-manifest.js +1 -1
- package/dist/src/cli/command-manifest.js.map +1 -1
- package/dist/src/cli/commands/agent.js +2 -2
- package/dist/src/cli/commands/agent.js.map +1 -1
- package/dist/src/cli/commands/agents.js +2 -4
- package/dist/src/cli/commands/agents.js.map +1 -1
- package/dist/src/cli/commands/auth.js +1 -1
- package/dist/src/cli/commands/browser-cli-helpers.js +1 -1
- package/dist/src/cli/commands/channels.d.ts +1 -5
- package/dist/src/cli/commands/channels.js +115 -281
- package/dist/src/cli/commands/channels.js.map +1 -1
- package/dist/src/cli/commands/config.js +2 -2
- package/dist/src/cli/commands/config.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/channel-config.js +16 -69
- package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/channel-pairing-pending.js +6 -4
- package/dist/src/cli/commands/doctor/checks/channel-pairing-pending.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/channel-plugins.js +2 -2
- package/dist/src/cli/commands/doctor/checks/channel-plugins.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +13 -9
- package/dist/src/cli/commands/doctor/checks/provider-auth.js.map +1 -1
- package/dist/src/cli/commands/extension-dev.js +2 -1
- package/dist/src/cli/commands/extension-dev.js.map +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +2 -1
- package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
- package/dist/src/cli/commands/extension-pack.js +2 -1
- package/dist/src/cli/commands/extension-pack.js.map +1 -1
- package/dist/src/cli/commands/models.js +7 -4
- package/dist/src/cli/commands/models.js.map +1 -1
- package/dist/src/cli/commands/onboard/channels/index.js +1 -1
- package/dist/src/cli/commands/onboard/channels/index.js.map +1 -1
- package/dist/src/cli/commands/onboard/channels/registry.d.ts +2 -1
- package/dist/src/cli/commands/onboard/channels/registry.js +32 -8
- package/dist/src/cli/commands/onboard/channels/registry.js.map +1 -1
- package/dist/src/cli/commands/onboard/model.js +8 -5
- package/dist/src/cli/commands/onboard/model.js.map +1 -1
- package/dist/src/cli/commands/onboard.js +4 -6
- package/dist/src/cli/commands/onboard.js.map +1 -1
- package/dist/src/cli/commands/setup-shared/runner.d.ts +1 -1
- package/dist/src/cli/commands/setup-shared/runner.js.map +1 -1
- package/dist/src/cli/commands/setup-shared/types.d.ts +1 -1
- package/dist/src/cli/commands/setup-shared/types.js.map +1 -1
- package/dist/src/cli/commands/tui.js +13 -5
- package/dist/src/cli/commands/tui.js.map +1 -1
- package/dist/src/cli/extension-cli-register.js +1 -1
- package/dist/src/commands/agents.config.d.ts +3 -3
- package/dist/src/commands/agents.config.js +7 -7
- package/dist/src/commands/agents.config.js.map +1 -1
- package/dist/src/config/agent-profile.d.ts +1 -1
- package/dist/src/config/agent-profile.js +6 -2
- package/dist/src/config/agent-profile.js.map +1 -1
- package/dist/src/config/agent-typed-models.d.ts +2 -2
- package/dist/src/config/agent-typed-models.js +13 -2
- package/dist/src/config/agent-typed-models.js.map +1 -1
- package/dist/src/config/index.js +3 -3
- package/dist/src/config/integration.d.ts +1 -1
- package/dist/src/config/loader.d.ts +0 -1
- package/dist/src/config/loader.js +4 -9
- package/dist/src/config/loader.js.map +1 -1
- package/dist/src/config/models-json.d.ts +6 -6
- package/dist/src/config/rules.js +2 -12
- package/dist/src/config/rules.js.map +1 -1
- package/dist/src/config/schema.d.ts +74 -47
- package/dist/src/config/schema.js +28 -66
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/config/validate-channel-configs.d.ts +0 -3
- package/dist/src/config/validate-channel-configs.js +29 -10
- package/dist/src/config/validate-channel-configs.js.map +1 -1
- package/dist/src/cron/executor.js +1 -4
- package/dist/src/cron/executor.js.map +1 -1
- package/dist/src/extensions/activation-context.js +3 -1
- package/dist/src/extensions/activation-context.js.map +1 -1
- package/dist/src/extensions/activation-planner.js +12 -0
- package/dist/src/extensions/activation-planner.js.map +1 -1
- package/dist/src/extensions/api.d.ts +5 -1
- package/dist/src/extensions/api.js +12 -0
- package/dist/src/extensions/api.js.map +1 -1
- package/dist/src/extensions/discover-extensions.js +17 -13
- package/dist/src/extensions/discover-extensions.js.map +1 -1
- package/dist/src/extensions/extension-metadata-snapshot.js +11 -5
- package/dist/src/extensions/extension-metadata-snapshot.js.map +1 -1
- package/dist/src/extensions/index.js +12 -4
- package/dist/src/extensions/index.js.map +1 -0
- package/dist/src/extensions/loader.d.ts +5 -1
- package/dist/src/extensions/loader.js +12 -11
- package/dist/src/extensions/loader.js.map +1 -1
- package/dist/src/extensions/manifest-registry.js +98 -93
- package/dist/src/extensions/manifest-registry.js.map +1 -1
- package/dist/src/extensions/normalize-manifest.js +91 -15
- package/dist/src/extensions/normalize-manifest.js.map +1 -1
- package/dist/src/extensions/sdk/index.js +1 -1
- package/dist/src/extensions/sdk/testing.js +4 -0
- package/dist/src/extensions/sdk/testing.js.map +1 -1
- package/dist/src/extensions/types/core.d.ts +32 -1
- package/dist/src/extensions/types/manifest.d.ts +60 -0
- package/dist/src/extensions/types/tui.d.ts +414 -5
- package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
- package/dist/src/gateway/agent-builtin-tools.js +16 -0
- package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
- package/dist/src/gateway/agent-run-relay.d.ts +2 -3
- package/dist/src/gateway/agent-run-relay.js +10 -3
- package/dist/src/gateway/agent-run-relay.js.map +1 -1
- package/dist/src/gateway/agents-admin.d.ts +32 -19
- package/dist/src/gateway/agents-admin.js +113 -93
- package/dist/src/gateway/agents-admin.js.map +1 -1
- package/dist/src/gateway/chat-stream/mapper.d.ts +34 -0
- package/dist/src/gateway/chat-stream/mapper.js +244 -0
- package/dist/src/gateway/chat-stream/mapper.js.map +1 -0
- package/dist/src/gateway/chat-stream/protocol.d.ts +100 -0
- package/dist/src/gateway/chat-stream/protocol.js +1 -0
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/lib/agent-model.d.ts +4 -4
- package/dist/src/gateway/hono/lib/agent-model.js +13 -11
- package/dist/src/gateway/hono/lib/agent-model.js.map +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +19 -7
- package/dist/src/gateway/hono/lib/config-payload.js +16 -15
- package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
- package/dist/src/gateway/hono/routes/agents.js +83 -48
- package/dist/src/gateway/hono/routes/agents.js.map +1 -1
- package/dist/src/gateway/hono/routes/channels.js +134 -214
- package/dist/src/gateway/hono/routes/channels.js.map +1 -1
- package/dist/src/gateway/hono/routes/commands-skills.js +10 -4
- package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/agents.js +26 -13
- package/dist/src/gateway/hono/routes/config-patch/agents.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/channels.d.ts +1 -11
- package/dist/src/gateway/hono/routes/config-patch/channels.js +18 -165
- package/dist/src/gateway/hono/routes/config-patch/channels.js.map +1 -1
- package/dist/src/gateway/hono/routes/config.js +5 -2
- package/dist/src/gateway/hono/routes/config.js.map +1 -1
- package/dist/src/gateway/hono/routes/dreaming.js +1 -1
- package/dist/src/gateway/hono/routes/lazy-bundles.js +13 -1
- package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
- package/dist/src/gateway/hono/routes/public-gateway.js +2 -4
- package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +179 -0
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/tui.d.ts +3 -0
- package/dist/src/gateway/hono/routes/tui.js +16 -0
- package/dist/src/gateway/hono/routes/tui.js.map +1 -0
- package/dist/src/gateway/hono/routes/workflows.js +25 -1
- package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
- package/dist/src/gateway/hono/sse.d.ts +5 -7
- package/dist/src/gateway/hono/sse.js +21 -38
- package/dist/src/gateway/hono/sse.js.map +1 -1
- package/dist/src/gateway/protocol.js.map +1 -1
- package/dist/src/gateway/service/agent-runner.d.ts +2 -4
- package/dist/src/gateway/service/agent-runner.js +1 -1
- package/dist/src/gateway/service/agent-runner.js.map +1 -1
- package/dist/src/gateway/service/marketplace-service.d.ts +4 -3
- package/dist/src/gateway/service/marketplace-service.js +7 -4
- package/dist/src/gateway/service/marketplace-service.js.map +1 -1
- package/dist/src/gateway/service/run-gateway-agent.d.ts +2 -6
- package/dist/src/gateway/service/run-gateway-agent.js +63 -36
- package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
- package/dist/src/gateway/service/sessions-api.d.ts +19 -0
- package/dist/src/gateway/service/sessions-api.js +12 -0
- package/dist/src/gateway/service/sessions-api.js.map +1 -1
- package/dist/src/gateway/service.d.ts +6 -0
- package/dist/src/gateway/service.js +73 -57
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/mcp/channel-bridge.js +1 -1
- package/dist/src/project-trust/trust-store.d.ts +30 -0
- package/dist/src/project-trust/trust-store.js +194 -0
- package/dist/src/project-trust/trust-store.js.map +1 -0
- package/dist/src/providers/index.d.ts +1 -1
- package/dist/src/providers/index.js +18 -7
- package/dist/src/providers/index.js.map +1 -1
- package/dist/src/routing/resolve-route.d.ts +0 -3
- package/dist/src/routing/resolve-route.js.map +1 -1
- package/dist/src/routing/resolve-tui-session-key.d.ts +2 -0
- package/dist/src/routing/resolve-tui-session-key.js +8 -3
- package/dist/src/routing/resolve-tui-session-key.js.map +1 -1
- package/dist/src/session/client-history.d.ts +32 -0
- package/dist/src/session/client-history.js +232 -1
- package/dist/src/session/client-history.js.map +1 -1
- package/dist/src/session/manager.d.ts +37 -4
- package/dist/src/session/manager.js +39 -15
- package/dist/src/session/manager.js.map +1 -1
- package/dist/src/session/session-context-for-llm.d.ts +93 -1
- package/dist/src/session/session-context-for-llm.js +105 -2
- package/dist/src/session/session-context-for-llm.js.map +1 -1
- package/dist/src/session/store.d.ts +37 -0
- package/dist/src/session/store.js +127 -2
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/session/stored-rows-to-file-entries.js +37 -1
- package/dist/src/session/stored-rows-to-file-entries.js.map +1 -1
- package/dist/src/session/types.d.ts +14 -1
- package/dist/src/session/types.js.map +1 -1
- package/dist/src/share/share-thumbnail.js +1 -1
- package/dist/src/storage/sqlite/migrations/004_add_session_type_metadata.sql +15 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/row-mappers.d.ts +14 -1
- package/dist/src/storage/sqlite/row-mappers.js +14 -1
- package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/session-metadata.js +1 -0
- package/dist/src/storage/sqlite/session-metadata.js.map +1 -1
- package/dist/src/storage/sqlite/session-repository.js +52 -25
- package/dist/src/storage/sqlite/session-repository.js.map +1 -1
- package/dist/src/tui/backends/embedded-backend.d.ts +53 -4
- package/dist/src/tui/backends/embedded-backend.js +227 -39
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.d.ts +59 -3
- package/dist/src/tui/backends/gateway-sse-backend.js +416 -26
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/chat-history.d.ts +5 -1
- package/dist/src/tui/chat-history.js +78 -8
- package/dist/src/tui/chat-history.js.map +1 -1
- package/dist/src/tui/clipboard-text.d.ts +5 -0
- package/dist/src/tui/clipboard-text.js +46 -0
- package/dist/src/tui/clipboard-text.js.map +1 -0
- package/dist/src/tui/components/assistant-message.d.ts +19 -3
- package/dist/src/tui/components/assistant-message.js +115 -9
- package/dist/src/tui/components/assistant-message.js.map +1 -1
- package/dist/src/tui/components/bash-execution.d.ts +3 -2
- package/dist/src/tui/components/bash-execution.js +31 -3
- package/dist/src/tui/components/bash-execution.js.map +1 -1
- package/dist/src/tui/components/bash-summary.d.ts +23 -0
- package/dist/src/tui/components/bash-summary.js +87 -0
- package/dist/src/tui/components/bash-summary.js.map +1 -0
- package/dist/src/tui/components/branch-message-summary.d.ts +17 -0
- package/dist/src/tui/components/branch-message-summary.js +43 -0
- package/dist/src/tui/components/branch-message-summary.js.map +1 -0
- package/dist/src/tui/components/branch-summary.d.ts +13 -0
- package/dist/src/tui/components/branch-summary.js +51 -0
- package/dist/src/tui/components/branch-summary.js.map +1 -0
- package/dist/src/tui/components/chat-log.d.ts +46 -6
- package/dist/src/tui/components/chat-log.js +183 -21
- package/dist/src/tui/components/chat-log.js.map +1 -1
- package/dist/src/tui/components/compaction-summary.d.ts +13 -0
- package/dist/src/tui/components/compaction-summary.js +46 -0
- package/dist/src/tui/components/compaction-summary.js.map +1 -0
- package/dist/src/tui/components/custom-editor.d.ts +1 -0
- package/dist/src/tui/components/custom-editor.js +2 -0
- package/dist/src/tui/components/custom-editor.js.map +1 -1
- package/dist/src/tui/components/custom-message.d.ts +23 -0
- package/dist/src/tui/components/custom-message.js +65 -0
- package/dist/src/tui/components/custom-message.js.map +1 -0
- package/dist/src/tui/components/extension-dialog.d.ts +42 -0
- package/dist/src/tui/components/extension-dialog.js +127 -0
- package/dist/src/tui/components/extension-dialog.js.map +1 -0
- package/dist/src/tui/components/scoped-models-selector.d.ts +7 -2
- package/dist/src/tui/components/scoped-models-selector.js +89 -16
- package/dist/src/tui/components/scoped-models-selector.js.map +1 -1
- package/dist/src/tui/components/searchable-select-list.d.ts +30 -3
- package/dist/src/tui/components/searchable-select-list.js +82 -10
- package/dist/src/tui/components/searchable-select-list.js.map +1 -1
- package/dist/src/tui/components/session-selector.d.ts +18 -4
- package/dist/src/tui/components/session-selector.js +207 -40
- package/dist/src/tui/components/session-selector.js.map +1 -1
- package/dist/src/tui/components/settings-selector.d.ts +6 -2
- package/dist/src/tui/components/settings-selector.js +126 -7
- package/dist/src/tui/components/settings-selector.js.map +1 -1
- package/dist/src/tui/components/thinking-selector.d.ts +12 -0
- package/dist/src/tui/components/thinking-selector.js +48 -0
- package/dist/src/tui/components/thinking-selector.js.map +1 -0
- package/dist/src/tui/components/tool-execution.d.ts +57 -3
- package/dist/src/tui/components/tool-execution.js +378 -28
- package/dist/src/tui/components/tool-execution.js.map +1 -1
- package/dist/src/tui/components/tui-bottom-bar.d.ts +9 -1
- package/dist/src/tui/components/tui-bottom-bar.js +56 -11
- package/dist/src/tui/components/tui-bottom-bar.js.map +1 -1
- package/dist/src/tui/components/tui-header.d.ts +9 -2
- package/dist/src/tui/components/tui-header.js +25 -5
- package/dist/src/tui/components/tui-header.js.map +1 -1
- package/dist/src/tui/components/user-message.d.ts +4 -2
- package/dist/src/tui/components/user-message.js +42 -9
- package/dist/src/tui/components/user-message.js.map +1 -1
- package/dist/src/tui/components/visual-truncate.d.ts +11 -0
- package/dist/src/tui/components/visual-truncate.js +27 -0
- package/dist/src/tui/components/visual-truncate.js.map +1 -0
- package/dist/src/tui/extension-host/autocomplete.d.ts +43 -0
- package/dist/src/tui/extension-host/autocomplete.js +116 -0
- package/dist/src/tui/extension-host/autocomplete.js.map +1 -0
- package/dist/src/tui/extension-host/host.d.ts +31 -1
- package/dist/src/tui/extension-host/host.js +123 -6
- package/dist/src/tui/extension-host/host.js.map +1 -1
- package/dist/src/tui/extension-host/load-extensions.d.ts +6 -1
- package/dist/src/tui/extension-host/load-extensions.js +4 -3
- package/dist/src/tui/extension-host/load-extensions.js.map +1 -1
- package/dist/src/tui/extension-host/runtime-context.d.ts +21 -0
- package/dist/src/tui/extension-host/runtime-context.js +152 -0
- package/dist/src/tui/extension-host/runtime-context.js.map +1 -0
- package/dist/src/tui/extension-host/runtime.d.ts +52 -4
- package/dist/src/tui/extension-host/runtime.js +547 -85
- package/dist/src/tui/extension-host/runtime.js.map +1 -1
- package/dist/src/tui/extension-host/surface.d.ts +20 -0
- package/dist/src/tui/extension-host/surface.js +30 -6
- package/dist/src/tui/extension-host/surface.js.map +1 -1
- package/dist/src/tui/extension-host/tool-renderers.d.ts +6 -3
- package/dist/src/tui/extension-host/tool-renderers.js +43 -5
- package/dist/src/tui/extension-host/tool-renderers.js.map +1 -1
- package/dist/src/tui/format-tui-hotkeys.d.ts +12 -2
- package/dist/src/tui/format-tui-hotkeys.js +22 -5
- package/dist/src/tui/format-tui-hotkeys.js.map +1 -1
- package/dist/src/tui/tui-agent-events.d.ts +8 -6
- package/dist/src/tui/tui-agent-events.js +200 -59
- package/dist/src/tui/tui-agent-events.js.map +1 -1
- package/dist/src/tui/tui-backend.d.ts +169 -3
- package/dist/src/tui/tui-command-formatters.d.ts +76 -0
- package/dist/src/tui/tui-command-formatters.js +594 -0
- package/dist/src/tui/tui-command-formatters.js.map +1 -0
- package/dist/src/tui/tui-commands.d.ts +57 -7
- package/dist/src/tui/tui-commands.js +639 -43
- package/dist/src/tui/tui-commands.js.map +1 -1
- package/dist/src/tui/tui-context-usage.d.ts +1 -1
- package/dist/src/tui/tui-context-usage.js +9 -1
- package/dist/src/tui/tui-context-usage.js.map +1 -1
- package/dist/src/tui/tui-extension-user-message.d.ts +8 -0
- package/dist/src/tui/tui-extension-user-message.js +32 -0
- package/dist/src/tui/tui-extension-user-message.js.map +1 -0
- package/dist/src/tui/tui-follow-up-queue.d.ts +9 -0
- package/dist/src/tui/tui-follow-up-queue.js +18 -0
- package/dist/src/tui/tui-follow-up-queue.js.map +1 -0
- package/dist/src/tui/tui-local-shell.d.ts +11 -1
- package/dist/src/tui/tui-local-shell.js +50 -8
- package/dist/src/tui/tui-local-shell.js.map +1 -1
- package/dist/src/tui/tui-model-picker.d.ts +26 -0
- package/dist/src/tui/tui-model-picker.js +152 -0
- package/dist/src/tui/tui-model-picker.js.map +1 -0
- package/dist/src/tui/tui-oauth-login.d.ts +16 -0
- package/dist/src/tui/tui-oauth-login.js +189 -0
- package/dist/src/tui/tui-oauth-login.js.map +1 -0
- package/dist/src/tui/tui-overlays.d.ts +3 -3
- package/dist/src/tui/tui-overlays.js +6 -7
- package/dist/src/tui/tui-overlays.js.map +1 -1
- package/dist/src/tui/tui-picker-overlay.d.ts +27 -32
- package/dist/src/tui/tui-picker-overlay.js +340 -30
- package/dist/src/tui/tui-picker-overlay.js.map +1 -1
- package/dist/src/tui/tui-picker-services.d.ts +41 -0
- package/dist/src/tui/tui-picker-services.js +1 -0
- package/dist/src/tui/tui-run-state.d.ts +11 -0
- package/dist/src/tui/tui-run-state.js +114 -0
- package/dist/src/tui/tui-run-state.js.map +1 -0
- package/dist/src/tui/tui-runtime-hints.d.ts +4 -0
- package/dist/src/tui/tui-runtime-hints.js +18 -0
- package/dist/src/tui/tui-runtime-hints.js.map +1 -0
- package/dist/src/tui/tui-scoped-models.d.ts +1 -1
- package/dist/src/tui/tui-scoped-models.js +2 -2
- package/dist/src/tui/tui-scoped-models.js.map +1 -1
- package/dist/src/tui/tui-session-actions.d.ts +5 -3
- package/dist/src/tui/tui-session-actions.js +21 -9
- package/dist/src/tui/tui-session-actions.js.map +1 -1
- package/dist/src/tui/tui-session-format.d.ts +4 -1
- package/dist/src/tui/tui-session-format.js +17 -3
- package/dist/src/tui/tui-session-format.js.map +1 -1
- package/dist/src/tui/tui-session-snapshot.d.ts +82 -0
- package/dist/src/tui/tui-session-snapshot.js +184 -0
- package/dist/src/tui/tui-session-snapshot.js.map +1 -0
- package/dist/src/tui/tui-session-stats.d.ts +3 -0
- package/dist/src/tui/tui-session-stats.js +59 -0
- package/dist/src/tui/tui-session-stats.js.map +1 -0
- package/dist/src/tui/tui-settings.d.ts +21 -0
- package/dist/src/tui/tui-settings.js +28 -1
- package/dist/src/tui/tui-settings.js.map +1 -1
- package/dist/src/tui/tui-skills-autocomplete.js +1 -1
- package/dist/src/tui/tui-skills-autocomplete.js.map +1 -1
- package/dist/src/tui/tui-startup-resources.d.ts +3 -0
- package/dist/src/tui/tui-startup-resources.js +39 -0
- package/dist/src/tui/tui-startup-resources.js.map +1 -0
- package/dist/src/tui/tui-startup-text.d.ts +10 -0
- package/dist/src/tui/tui-startup-text.js +58 -0
- package/dist/src/tui/tui-startup-text.js.map +1 -0
- package/dist/src/tui/tui-stdio-filter.d.ts +1 -0
- package/dist/src/tui/tui-stdio-filter.js +11 -7
- package/dist/src/tui/tui-stdio-filter.js.map +1 -1
- package/dist/src/tui/tui-submit.d.ts +2 -0
- package/dist/src/tui/tui-submit.js +2 -1
- package/dist/src/tui/tui-submit.js.map +1 -1
- package/dist/src/tui/tui-tool-diff.js +61 -7
- package/dist/src/tui/tui-tool-diff.js.map +1 -1
- package/dist/src/tui/tui-tool-result.d.ts +17 -0
- package/dist/src/tui/tui-tool-result.js +74 -0
- package/dist/src/tui/tui-tool-result.js.map +1 -0
- package/dist/src/tui/tui-transcript-tree-picker.d.ts +57 -0
- package/dist/src/tui/tui-transcript-tree-picker.js +604 -0
- package/dist/src/tui/tui-transcript-tree-picker.js.map +1 -0
- package/dist/src/tui/tui-transcript-tree.d.ts +7 -0
- package/dist/src/tui/tui-transcript-tree.js +316 -0
- package/dist/src/tui/tui-transcript-tree.js.map +1 -0
- package/dist/src/tui/tui-types.d.ts +25 -34
- package/dist/src/tui/tui-types.js +12 -0
- package/dist/src/tui/tui-types.js.map +1 -1
- package/dist/src/tui/tui.js +1288 -112
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/tui/xopc-tui-keybindings.d.ts +127 -2
- package/dist/src/tui/xopc-tui-keybindings.js +127 -2
- package/dist/src/tui/xopc-tui-keybindings.js.map +1 -1
- package/dist/src/workflows/domain/definition-utils.d.ts +2 -1
- package/dist/src/workflows/domain/definition-utils.js +18 -8
- package/dist/src/workflows/domain/definition-utils.js.map +1 -1
- package/dist/src/workflows/domain/definition.d.ts +25 -0
- package/dist/src/workflows/domain/event.d.ts +1 -0
- package/dist/src/workflows/domain/result.d.ts +15 -0
- package/dist/src/workflows/domain/run.d.ts +2 -0
- package/dist/src/workflows/domain/run.js.map +1 -1
- package/dist/src/workflows/engine/projector.js +4 -0
- package/dist/src/workflows/engine/projector.js.map +1 -1
- package/dist/src/workflows/engine/workflow-engine.d.ts +37 -1
- package/dist/src/workflows/engine/workflow-engine.js +75 -11
- package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
- package/dist/src/workflows/index.d.ts +1 -0
- package/dist/src/workflows/index.js +4 -1
- package/dist/src/workflows/registry/catalog-workflow-definition-registry.d.ts +9 -0
- package/dist/src/workflows/registry/catalog-workflow-definition-registry.js +40 -0
- package/dist/src/workflows/registry/catalog-workflow-definition-registry.js.map +1 -0
- package/dist/src/workflows/registry/index.d.ts +2 -0
- package/dist/src/workflows/registry/index.js +2 -0
- package/dist/src/workflows/registry/workflow-definition-registry.d.ts +15 -0
- package/dist/src/workflows/registry/workflow-definition-registry.js +1 -0
- package/dist/src/workflows/runtime/index.d.ts +2 -0
- package/dist/src/workflows/runtime/index.js +2 -1
- package/dist/src/workflows/runtime/script-workflow-runtime.d.ts +5 -0
- package/dist/src/workflows/runtime/script-workflow-runtime.js +15 -0
- package/dist/src/workflows/runtime/script-workflow-runtime.js.map +1 -0
- package/dist/src/workflows/runtime/workflow-runtime-port.d.ts +16 -0
- package/dist/src/workflows/runtime/workflow-runtime-port.js +1 -0
- package/dist/src/workflows/service/run-view-to-snapshot.js +3 -0
- package/dist/src/workflows/service/run-view-to-snapshot.js.map +1 -1
- package/dist/src/workflows/service/workflow-run-service.d.ts +3 -0
- package/dist/src/workflows/service/workflow-run-service.js +10 -15
- package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
- package/dist/src/workflows/service/workflow-session-bridge.d.ts +1 -1
- package/dist/src/workflows/service/workflow-session-bridge.js +4 -1
- package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
- package/package.json +21 -15
- package/skills/creative/frontend-design/SKILL.md +1 -1
- package/skills/creative/theme-factory/SKILL.md +1 -1
- package/skills/documents/xlsx/SKILL.md +1 -1
- package/skills/engineering/diagnose/SKILL.md +2 -2
- package/skills/engineering/tdd/SKILL.md +1 -1
- package/skills/tools/github/SKILL.md +6 -1
- package/skills/tools/webapp-testing/SKILL.md +4 -1
- package/dist/extensions/telegram/src/adapters/config-surface.d.ts +0 -2
- package/dist/extensions/telegram/src/adapters/config-surface.js +0 -26
- package/dist/extensions/telegram/src/adapters/config-surface.js.map +0 -1
- package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js +0 -158
- package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js.map +0 -1
- package/dist/gateway/static/root/assets/agents-BwXkia_W.js +0 -222
- package/dist/gateway/static/root/assets/channels-settings-tlOTdaXw.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-D4XjqwqC.js +0 -8
- package/dist/gateway/static/root/assets/cron-api-DcmfGuj0.js +0 -1
- package/dist/gateway/static/root/assets/cron-page-CijJ4G6F.js +0 -1
- package/dist/gateway/static/root/assets/extension-settings-page-CyJk_G64.js +0 -1
- package/dist/gateway/static/root/assets/field-primitives-C4GpxsDo.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-config-api-CLD0Gpi3.js +0 -1
- package/dist/gateway/static/root/assets/index-0HmunJW9.js +0 -4845
- package/dist/gateway/static/root/assets/index-Bk75Phrd.css +0 -1
- package/dist/gateway/static/root/assets/notes-page-BBnTh0uI.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-B0riYK7j.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-DiP_WHu_.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-1ZPhcCZ9.js +0 -3
- package/dist/gateway/static/root/assets/skills-page-BQ1hllKD.js +0 -2
- package/dist/gateway/static/root/assets/url-F3_D_6zZ.js +0 -3
- package/dist/gateway/static/root/assets/utils-CPr3FBh2.js +0 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-BkbDl6dH.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-D059ysoF.js +0 -27
- package/dist/src/agent/embedded/map-stream-events.d.ts +0 -9
- package/dist/src/agent/embedded/map-stream-events.js +0 -63
- package/dist/src/agent/embedded/map-stream-events.js.map +0 -1
- package/dist/src/channels/dock.js.map +0 -1
- package/dist/src/channels/plugins/bundled.d.ts +0 -11
- package/dist/src/channels/plugins/bundled.js +0 -10
- package/dist/src/channels/plugins/bundled.js.map +0 -1
- package/dist/src/channels/registry.d.ts +0 -25
- package/dist/src/channels/registry.js +0 -82
- package/dist/src/channels/registry.js.map +0 -1
- package/dist/src/config/localized-text.d.ts +0 -6
- package/dist/src/config/localized-text.js +0 -42
- package/dist/src/config/localized-text.js.map +0 -1
- package/dist/src/generated/bundled-channel-plugins.d.ts +0 -10
- package/dist/src/generated/bundled-channel-plugins.js +0 -16
- package/dist/src/generated/bundled-channel-plugins.js.map +0 -1
- package/dist/src/tui/stream-assembler.d.ts +0 -22
- package/dist/src/tui/stream-assembler.js +0 -63
- package/dist/src/tui/stream-assembler.js.map +0 -1
- package/skills/browser/SKILL-zh.md +0 -188
- package/skills/business/company-values/SKILL-zh.md +0 -80
- package/skills/business/company-values/SKILL.md +0 -80
- package/skills/business/find-community/SKILL-zh.md +0 -50
- package/skills/business/find-community/SKILL.md +0 -50
- package/skills/business/first-customers/SKILL-zh.md +0 -76
- package/skills/business/first-customers/SKILL.md +0 -76
- package/skills/business/grow-sustainably/SKILL-zh.md +0 -92
- package/skills/business/grow-sustainably/SKILL.md +0 -92
- package/skills/business/marketing-plan/SKILL-zh.md +0 -100
- package/skills/business/marketing-plan/SKILL.md +0 -100
- package/skills/business/minimalist-review/SKILL-zh.md +0 -82
- package/skills/business/minimalist-review/SKILL.md +0 -82
- package/skills/business/mvp/SKILL-zh.md +0 -81
- package/skills/business/mvp/SKILL.md +0 -81
- package/skills/business/pricing/SKILL-zh.md +0 -64
- package/skills/business/pricing/SKILL.md +0 -64
- package/skills/business/processize/SKILL-zh.md +0 -91
- package/skills/business/processize/SKILL.md +0 -91
- package/skills/business/validate-idea/SKILL-zh.md +0 -68
- package/skills/business/validate-idea/SKILL.md +0 -68
- package/skills/creative/algorithmic-art/LICENSE.txt +0 -202
- package/skills/creative/algorithmic-art/SKILL-zh.md +0 -405
- package/skills/creative/algorithmic-art/SKILL.md +0 -405
- package/skills/creative/algorithmic-art/templates/generator_template.js +0 -223
- package/skills/creative/algorithmic-art/templates/viewer.html +0 -599
- package/skills/creative/frontend-design/SKILL-zh.md +0 -42
- package/skills/creative/theme-factory/SKILL-zh.md +0 -59
- package/skills/creative/web-artifacts-builder/LICENSE.txt +0 -202
- package/skills/creative/web-artifacts-builder/SKILL-zh.md +0 -74
- package/skills/creative/web-artifacts-builder/SKILL.md +0 -74
- package/skills/creative/web-artifacts-builder/scripts/bundle-artifact.sh +0 -54
- package/skills/creative/web-artifacts-builder/scripts/init-artifact.sh +0 -322
- package/skills/creative/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- package/skills/documents/doc-coauthoring/SKILL-zh.md +0 -375
- package/skills/documents/doc-coauthoring/SKILL.md +0 -375
- package/skills/documents/docx/LICENSE.txt +0 -30
- package/skills/documents/docx/SKILL-zh.md +0 -590
- package/skills/documents/docx/SKILL.md +0 -590
- package/skills/documents/docx/scripts/__init__.py +0 -1
- package/skills/documents/docx/scripts/accept_changes.py +0 -135
- package/skills/documents/docx/scripts/comment.py +0 -318
- package/skills/documents/docx/scripts/office/helpers/__init__.py +0 -0
- package/skills/documents/docx/scripts/office/helpers/merge_runs.py +0 -199
- package/skills/documents/docx/scripts/office/helpers/simplify_redlines.py +0 -197
- package/skills/documents/docx/scripts/office/pack.py +0 -159
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
- package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
- package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
- package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
- package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
- package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
- package/skills/documents/docx/scripts/office/schemas/mce/mc.xsd +0 -75
- package/skills/documents/docx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
- package/skills/documents/docx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
- package/skills/documents/docx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
- package/skills/documents/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
- package/skills/documents/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
- package/skills/documents/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
- package/skills/documents/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
- package/skills/documents/docx/scripts/office/soffice.py +0 -183
- package/skills/documents/docx/scripts/office/unpack.py +0 -132
- package/skills/documents/docx/scripts/office/validate.py +0 -111
- package/skills/documents/docx/scripts/office/validators/__init__.py +0 -15
- package/skills/documents/docx/scripts/office/validators/base.py +0 -847
- package/skills/documents/docx/scripts/office/validators/docx.py +0 -446
- package/skills/documents/docx/scripts/office/validators/pptx.py +0 -275
- package/skills/documents/docx/scripts/office/validators/redlining.py +0 -247
- package/skills/documents/docx/scripts/templates/comments.xml +0 -3
- package/skills/documents/docx/scripts/templates/commentsExtended.xml +0 -3
- package/skills/documents/docx/scripts/templates/commentsExtensible.xml +0 -3
- package/skills/documents/docx/scripts/templates/commentsIds.xml +0 -3
- package/skills/documents/docx/scripts/templates/people.xml +0 -3
- package/skills/documents/pdf/LICENSE.txt +0 -30
- package/skills/documents/pdf/SKILL-zh.md +0 -314
- package/skills/documents/pdf/SKILL.md +0 -314
- package/skills/documents/pdf/forms.md +0 -294
- package/skills/documents/pdf/reference.md +0 -612
- package/skills/documents/pdf/scripts/check_bounding_boxes.py +0 -65
- package/skills/documents/pdf/scripts/check_fillable_fields.py +0 -11
- package/skills/documents/pdf/scripts/convert_pdf_to_images.py +0 -33
- package/skills/documents/pdf/scripts/create_validation_image.py +0 -37
- package/skills/documents/pdf/scripts/extract_form_field_info.py +0 -122
- package/skills/documents/pdf/scripts/extract_form_structure.py +0 -115
- package/skills/documents/pdf/scripts/fill_fillable_fields.py +0 -98
- package/skills/documents/pdf/scripts/fill_pdf_form_with_annotations.py +0 -107
- package/skills/documents/pptx/LICENSE.txt +0 -30
- package/skills/documents/pptx/SKILL-zh.md +0 -232
- package/skills/documents/pptx/SKILL.md +0 -232
- package/skills/documents/pptx/editing.md +0 -205
- package/skills/documents/pptx/pptxgenjs.md +0 -420
- package/skills/documents/pptx/scripts/__init__.py +0 -0
- package/skills/documents/pptx/scripts/add_slide.py +0 -195
- package/skills/documents/pptx/scripts/clean.py +0 -286
- package/skills/documents/pptx/scripts/office/helpers/__init__.py +0 -0
- package/skills/documents/pptx/scripts/office/helpers/merge_runs.py +0 -199
- package/skills/documents/pptx/scripts/office/helpers/simplify_redlines.py +0 -197
- package/skills/documents/pptx/scripts/office/pack.py +0 -159
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
- package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
- package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
- package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
- package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
- package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
- package/skills/documents/pptx/scripts/office/schemas/mce/mc.xsd +0 -75
- package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
- package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
- package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
- package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
- package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
- package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
- package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
- package/skills/documents/pptx/scripts/office/soffice.py +0 -183
- package/skills/documents/pptx/scripts/office/unpack.py +0 -132
- package/skills/documents/pptx/scripts/office/validate.py +0 -111
- package/skills/documents/pptx/scripts/office/validators/__init__.py +0 -15
- package/skills/documents/pptx/scripts/office/validators/base.py +0 -847
- package/skills/documents/pptx/scripts/office/validators/docx.py +0 -446
- package/skills/documents/pptx/scripts/office/validators/pptx.py +0 -275
- package/skills/documents/pptx/scripts/office/validators/redlining.py +0 -247
- package/skills/documents/pptx/scripts/thumbnail.py +0 -289
- package/skills/documents/xlsx/SKILL-zh.md +0 -292
- package/skills/engineering/diagnose/SKILL-zh.md +0 -117
- package/skills/engineering/grill-with-docs/ADR-FORMAT.md +0 -47
- package/skills/engineering/grill-with-docs/CONTEXT-FORMAT.md +0 -77
- package/skills/engineering/grill-with-docs/SKILL-zh.md +0 -88
- package/skills/engineering/grill-with-docs/SKILL.md +0 -88
- package/skills/engineering/improve-codebase-architecture/DEEPENING.md +0 -37
- package/skills/engineering/improve-codebase-architecture/INTERFACE-DESIGN.md +0 -44
- package/skills/engineering/improve-codebase-architecture/LANGUAGE.md +0 -53
- package/skills/engineering/improve-codebase-architecture/SKILL-zh.md +0 -71
- package/skills/engineering/improve-codebase-architecture/SKILL.md +0 -71
- package/skills/engineering/tdd/SKILL-zh.md +0 -109
- package/skills/engineering/to-issues/SKILL-zh.md +0 -81
- package/skills/engineering/to-issues/SKILL.md +0 -81
- package/skills/engineering/to-prd/SKILL-zh.md +0 -76
- package/skills/engineering/to-prd/SKILL.md +0 -74
- package/skills/engineering/zoom-out/SKILL-zh.md +0 -7
- package/skills/engineering/zoom-out/SKILL.md +0 -7
- package/skills/tools/find-skills/SKILL-zh.md +0 -440
- package/skills/tools/github/SKILL-zh.md +0 -48
- package/skills/tools/internal-comms/LICENSE.txt +0 -202
- package/skills/tools/internal-comms/SKILL-zh.md +0 -32
- package/skills/tools/internal-comms/SKILL.md +0 -32
- package/skills/tools/internal-comms/examples/3p-updates.md +0 -47
- package/skills/tools/internal-comms/examples/company-newsletter.md +0 -65
- package/skills/tools/internal-comms/examples/faq-answers.md +0 -30
- package/skills/tools/internal-comms/examples/general-comms.md +0 -16
- package/skills/tools/skill-creator/LICENSE.txt +0 -202
- package/skills/tools/skill-creator/SKILL-zh.md +0 -483
- package/skills/tools/skill-creator/SKILL.md +0 -485
- package/skills/tools/skill-creator/agents/analyzer.md +0 -274
- package/skills/tools/skill-creator/agents/comparator.md +0 -202
- package/skills/tools/skill-creator/agents/grader.md +0 -223
- package/skills/tools/skill-creator/assets/eval_review.html +0 -146
- package/skills/tools/skill-creator/eval-viewer/generate_review.py +0 -471
- package/skills/tools/skill-creator/eval-viewer/viewer.html +0 -1325
- package/skills/tools/skill-creator/references/schemas.md +0 -430
- package/skills/tools/skill-creator/scripts/__init__.py +0 -0
- package/skills/tools/skill-creator/scripts/aggregate_benchmark.py +0 -401
- package/skills/tools/skill-creator/scripts/generate_report.py +0 -326
- package/skills/tools/skill-creator/scripts/improve_description.py +0 -247
- package/skills/tools/skill-creator/scripts/package_skill.py +0 -136
- package/skills/tools/skill-creator/scripts/quick_validate.py +0 -103
- package/skills/tools/skill-creator/scripts/run_eval.py +0 -310
- package/skills/tools/skill-creator/scripts/run_loop.py +0 -328
- package/skills/tools/skill-creator/scripts/utils.py +0 -47
- package/skills/tools/summarize/SKILL-zh.md +0 -47
- package/skills/tools/weather/SKILL-zh.md +0 -46
- package/skills/tools/weather/SKILL.md +0 -46
- package/skills/tools/webapp-testing/SKILL-zh.md +0 -96
package/dist/src/tui/tui.js
CHANGED
|
@@ -1,23 +1,39 @@
|
|
|
1
1
|
import { version } from "../../package.js";
|
|
2
|
+
import { resolveStateDir, resolveXopcDatabasePath } from "../config/paths-state.js";
|
|
3
|
+
import { init_paths } from "../config/paths.js";
|
|
2
4
|
import { loadConfig } from "../config/loader.js";
|
|
3
5
|
import { parseAgentSessionKey } from "../routing/session-key-utils.js";
|
|
4
6
|
import { init_agent_session_key } from "../routing/agent-session-key.js";
|
|
7
|
+
import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
|
|
8
|
+
import { getAllModels, getAllProviders, getApiKey, init_providers, isProviderConfiguredSync } from "../providers/index.js";
|
|
5
9
|
import "../config/index.js";
|
|
10
|
+
import { MAX_WEBCHAT_ATTACHMENT_FILE_BYTES } from "../gateway/chat-limits.js";
|
|
11
|
+
import { ProjectTrustStore, hasTrustRequiringProjectResources } from "../project-trust/trust-store.js";
|
|
6
12
|
import { resolveTuiSessionKey, resolveTuiStartupSessionKey } from "../routing/resolve-tui-session-key.js";
|
|
7
|
-
import {
|
|
8
|
-
import { createXopcTuiKeybindingsManager } from "./tui-keybindings-file.js";
|
|
9
|
-
import { StreamAssembler } from "./stream-assembler.js";
|
|
10
|
-
import { applyThemeById, getBashExcludeBorderColor, getBashModeBorderColor, getThinkingBorderColor, initTuiTheme } from "./theme-manager.js";
|
|
13
|
+
import { applyThemeById, getBashExcludeBorderColor, getBashModeBorderColor, getCustomThemesDir, getThemeExports, getThinkingBorderColor, initTuiTheme, listAvailableThemeIds, resolveThemePalette } from "./theme-manager.js";
|
|
11
14
|
import { editorTheme, theme } from "./theme.js";
|
|
12
|
-
import {
|
|
15
|
+
import { extensionForImageMimeType, readClipboardImage } from "./clipboard-image.js";
|
|
16
|
+
import { copyTextToClipboard } from "./clipboard-text.js";
|
|
17
|
+
import { createXopcTuiKeybindingsManager } from "./tui-keybindings-file.js";
|
|
18
|
+
import { formatKeyIds } from "./format-tui-hotkeys.js";
|
|
19
|
+
import { isActiveRunStreamStale, markActiveRunStalled, markRunRecovering, markRunRecoveryComplete, markRunSending } from "./tui-run-state.js";
|
|
20
|
+
import { clearSeenStreamEvents, clearSeenStreamEventsForRun, dispatchAgentEvent } from "./tui-agent-events.js";
|
|
21
|
+
import { transcriptTreeEntryIdToRowNumber } from "./tui-transcript-tree.js";
|
|
22
|
+
import { formatTuiCompactionResult, formatTuiShareResult } from "./tui-command-formatters.js";
|
|
23
|
+
import { formatTuiStartupText } from "./tui-startup-text.js";
|
|
13
24
|
import { createTuiCommandHandler, getSlashCommands } from "./tui-commands.js";
|
|
25
|
+
import { extensionCustomMessageContentToText, extensionCustomMessageToTurnText, extensionUserMessageContentToText } from "./tui-extension-user-message.js";
|
|
14
26
|
import { resolveFdPath } from "./tui-fd-path.js";
|
|
27
|
+
import { drainFollowUpQueue, restoreQueuedMessages } from "./tui-follow-up-queue.js";
|
|
15
28
|
import { createBackspaceDeduper, drainAndStopTuiSafely, isIgnorableTuiStopError, resolveCtrlCAction, stopTuiSafely } from "./tui-lifecycle.js";
|
|
16
29
|
import { createLocalShellRunner } from "./tui-local-shell.js";
|
|
17
|
-
import { createOverlayHandlers } from "./tui-overlays.js";
|
|
18
30
|
import { filterModelsForCycle, loadScopedModelRefs, saveScopedModelRefs } from "./tui-scoped-models.js";
|
|
19
|
-
import { openModelPickerOverlay
|
|
31
|
+
import { openModelPickerOverlay } from "./tui-model-picker.js";
|
|
32
|
+
import { runTuiOAuthLogin } from "./tui-oauth-login.js";
|
|
33
|
+
import { openAgentPickerOverlay, openProjectTrustOverlay, openScopedModelsOverlay, openSessionPickerOverlay, openSessionTreeOverlay, openSettingsOverlay, openThinkingSelectorOverlay, openTranscriptTreeOverlay, openUserMessageForkOverlay } from "./tui-picker-overlay.js";
|
|
34
|
+
import { formatBusyResponseHint, formatSteerUnavailableHint, formatSuspendUnsupportedHint } from "./tui-runtime-hints.js";
|
|
20
35
|
import { createSessionActions } from "./tui-session-actions.js";
|
|
36
|
+
import { TuiSessionSnapshot } from "./tui-session-snapshot.js";
|
|
21
37
|
import { loadTuiSettings, saveTuiSettings } from "./tui-settings.js";
|
|
22
38
|
import { installTuiStdioFilter } from "./tui-stdio-filter.js";
|
|
23
39
|
import { createEditorSubmitHandler, createSubmitBurstCoalescer, shouldEnableWindowsGitBashPasteFallback } from "./tui-submit.js";
|
|
@@ -31,13 +47,17 @@ import { TuiBottomBar } from "./components/tui-bottom-bar.js";
|
|
|
31
47
|
import { TuiHeader } from "./components/tui-header.js";
|
|
32
48
|
import { loadExtensionsForTuiLocalMode } from "./extension-host/load-extensions.js";
|
|
33
49
|
import { createTuiExtensionRuntime } from "./extension-host/runtime.js";
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
50
|
+
import { randomUUID } from "node:crypto";
|
|
51
|
+
import { mkdirSync, mkdtempSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
52
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
36
53
|
import { tmpdir } from "node:os";
|
|
37
54
|
import { spawnSync } from "node:child_process";
|
|
38
55
|
import { Container, Loader, ProcessTerminal, TUI, setKeybindings } from "@earendil-works/pi-tui";
|
|
56
|
+
import { Buffer } from "node:buffer";
|
|
39
57
|
//#region src/tui/tui.ts
|
|
58
|
+
init_paths();
|
|
40
59
|
init_agent_session_key();
|
|
60
|
+
init_providers();
|
|
41
61
|
const THINK_LEVEL_CYCLE = [
|
|
42
62
|
"off",
|
|
43
63
|
"minimal",
|
|
@@ -54,12 +74,102 @@ function nextThinkLevel(current) {
|
|
|
54
74
|
return THINK_LEVEL_CYCLE[((idx >= 0 ? idx : mediumIdx >= 0 ? mediumIdx : 0) + 1) % THINK_LEVEL_CYCLE.length];
|
|
55
75
|
}
|
|
56
76
|
const DOUBLE_ESCAPE_WINDOW_MS = 500;
|
|
77
|
+
function escapeHtml(text) {
|
|
78
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
79
|
+
}
|
|
80
|
+
function exportExtension(format) {
|
|
81
|
+
if (format === "json") return "json";
|
|
82
|
+
if (format === "markdown") return "md";
|
|
83
|
+
return "html";
|
|
84
|
+
}
|
|
85
|
+
function wrapMarkdownExportAsHtml(markdown) {
|
|
86
|
+
return [
|
|
87
|
+
"<!doctype html>",
|
|
88
|
+
"<html>",
|
|
89
|
+
"<head>",
|
|
90
|
+
"<meta charset=\"utf-8\">",
|
|
91
|
+
"<title>xopc session export</title>",
|
|
92
|
+
"<style>body{font:14px/1.5 system-ui,sans-serif;margin:32px;max-width:960px}pre{white-space:pre-wrap}</style>",
|
|
93
|
+
"</head>",
|
|
94
|
+
"<body>",
|
|
95
|
+
"<pre>",
|
|
96
|
+
escapeHtml(markdown),
|
|
97
|
+
"</pre>",
|
|
98
|
+
"</body>",
|
|
99
|
+
"</html>",
|
|
100
|
+
""
|
|
101
|
+
].join("\n");
|
|
102
|
+
}
|
|
103
|
+
function defaultExportPath(sessionKey, format) {
|
|
104
|
+
const safeKey = sessionKey.replace(/[^a-z0-9_.-]+/gi, "_").replace(/^_+|_+$/g, "") || "session";
|
|
105
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
106
|
+
return resolve(process.cwd(), `xopc-session-${safeKey}-${stamp}.${exportExtension(format)}`);
|
|
107
|
+
}
|
|
108
|
+
function userDisplayContentForAttachments(text, attachments) {
|
|
109
|
+
if (!attachments?.length) return text;
|
|
110
|
+
const blocks = [];
|
|
111
|
+
if (text.trim()) blocks.push({
|
|
112
|
+
type: "text",
|
|
113
|
+
text
|
|
114
|
+
});
|
|
115
|
+
for (const att of attachments) {
|
|
116
|
+
if (att.mimeType?.startsWith("image/") || att.type === "image" || att.type === "photo") {
|
|
117
|
+
blocks.push({
|
|
118
|
+
type: "image",
|
|
119
|
+
name: att.name
|
|
120
|
+
});
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
blocks.push({
|
|
124
|
+
type: "file",
|
|
125
|
+
name: att.name
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
return blocks;
|
|
129
|
+
}
|
|
130
|
+
function shellQuote(value) {
|
|
131
|
+
if (/^[A-Za-z0-9_/:@%+=,.-]+$/.test(value)) return value;
|
|
132
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
133
|
+
}
|
|
134
|
+
function formatTuiResumeCommand(opts, sessionKey) {
|
|
135
|
+
const parts = ["xopc", "tui"];
|
|
136
|
+
if (opts.local === true) parts.push("--local");
|
|
137
|
+
if (opts.url) parts.push("--url", shellQuote(opts.url));
|
|
138
|
+
parts.push("--session", shellQuote(sessionKey));
|
|
139
|
+
return parts.join(" ");
|
|
140
|
+
}
|
|
141
|
+
function isLoopbackGatewayUrl(rawUrl) {
|
|
142
|
+
try {
|
|
143
|
+
const hostname = new URL(rawUrl).hostname.toLowerCase();
|
|
144
|
+
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]";
|
|
145
|
+
} catch {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function resolveStartupWorkingDirectory(opts, isLocalMode) {
|
|
150
|
+
const explicit = opts.workdir?.trim();
|
|
151
|
+
if (explicit) return resolve(explicit);
|
|
152
|
+
if (opts.useStartupCwd === false || opts.session?.trim()) return;
|
|
153
|
+
const gatewayUrl = opts.url ?? "http://localhost:3120";
|
|
154
|
+
if (isLocalMode || isLoopbackGatewayUrl(gatewayUrl)) return process.cwd();
|
|
155
|
+
}
|
|
156
|
+
function assistantMessagePlainText(message) {
|
|
157
|
+
const content = message.content;
|
|
158
|
+
if (typeof content === "string") return content;
|
|
159
|
+
if (!Array.isArray(content)) return "";
|
|
160
|
+
return content.map((block) => {
|
|
161
|
+
if (!block || typeof block !== "object") return "";
|
|
162
|
+
const rec = block;
|
|
163
|
+
return rec.type === "text" && typeof rec.text === "string" ? rec.text : "";
|
|
164
|
+
}).join("");
|
|
165
|
+
}
|
|
57
166
|
async function runTui(opts) {
|
|
58
167
|
const stdioFilter = installTuiStdioFilter();
|
|
59
168
|
const restoreStdio = () => stdioFilter.restore();
|
|
60
169
|
const isLocalMode = opts.local === true;
|
|
170
|
+
const config = loadConfig();
|
|
61
171
|
const startup = resolveTuiStartupSessionKey({
|
|
62
|
-
cfg:
|
|
172
|
+
cfg: config,
|
|
63
173
|
sessionOption: opts.session,
|
|
64
174
|
cwd: process.cwd()
|
|
65
175
|
});
|
|
@@ -75,16 +185,41 @@ async function runTui(opts) {
|
|
|
75
185
|
let tuiSettings = loadTuiSettings();
|
|
76
186
|
initTuiTheme({ themeId: opts.theme ?? tuiSettings.theme });
|
|
77
187
|
const state = createInitialState(startup.sessionKey);
|
|
188
|
+
const projectTrustStore = new ProjectTrustStore();
|
|
189
|
+
let projectTrustSessionDecision = null;
|
|
190
|
+
const isCurrentProjectTrusted = () => {
|
|
191
|
+
if (projectTrustSessionDecision !== null) return projectTrustSessionDecision;
|
|
192
|
+
if (!hasTrustRequiringProjectResources(process.cwd())) return true;
|
|
193
|
+
return projectTrustStore.get(process.cwd()) === true;
|
|
194
|
+
};
|
|
195
|
+
let projectTrustPromptShown = false;
|
|
196
|
+
const sessionStateDir = resolveStateDir();
|
|
197
|
+
const sessionDatabasePath = resolveXopcDatabasePath();
|
|
198
|
+
const sessionSnapshot = new TuiSessionSnapshot(() => state.currentSessionKey, () => process.cwd(), () => state.sessionInfo.displayName, () => `${sessionDatabasePath}#session=${encodeURIComponent(state.currentSessionKey)}`, () => sessionStateDir);
|
|
78
199
|
state.scopedModelRefs = loadScopedModelRefs();
|
|
79
200
|
state.showThinking = tuiSettings.showThinking;
|
|
80
201
|
state.toolsExpanded = tuiSettings.toolsExpanded;
|
|
81
|
-
|
|
202
|
+
let pendingImageAttachments = [];
|
|
203
|
+
const pendingNextTurnCustomMessages = [];
|
|
204
|
+
let lastRetryMessageText = null;
|
|
205
|
+
let setExtensionLabel = (_entryId, _label) => {};
|
|
206
|
+
let sendExtensionUserMessage = (_content, _options) => {};
|
|
207
|
+
let appendExtensionEntry = (_customType, _data) => {};
|
|
208
|
+
let sendExtensionMessage = (_message, _options) => {};
|
|
82
209
|
let extensionRegistry;
|
|
83
|
-
if (isLocalMode) extensionRegistry = await loadExtensionsForTuiLocalMode(
|
|
210
|
+
if (isLocalMode) extensionRegistry = await loadExtensionsForTuiLocalMode({
|
|
211
|
+
setLabel: (entryId, label) => setExtensionLabel(entryId, label),
|
|
212
|
+
sendUserMessage: (content, options) => sendExtensionUserMessage(content, options),
|
|
213
|
+
appendEntry: (customType, data) => appendExtensionEntry(customType, data),
|
|
214
|
+
sendMessage: (message, options) => sendExtensionMessage(message, options)
|
|
215
|
+
});
|
|
84
216
|
const client = isLocalMode ? new EmbeddedBackend({ extensionRegistry }) : new GatewaySseBackend({
|
|
85
217
|
url: opts.url ?? "http://localhost:3120",
|
|
86
218
|
token: opts.token
|
|
87
219
|
});
|
|
220
|
+
const startupWorkingDirectory = resolveStartupWorkingDirectory(opts, isLocalMode);
|
|
221
|
+
if (startupWorkingDirectory) state.sessionInfo.effectiveWorkspacePath = startupWorkingDirectory;
|
|
222
|
+
let startupWorkingDirectoryApplied = false;
|
|
88
223
|
const keybindings = createXopcTuiKeybindingsManager();
|
|
89
224
|
setKeybindings(keybindings);
|
|
90
225
|
let modelChoices = [];
|
|
@@ -94,6 +229,8 @@ async function runTui(opts) {
|
|
|
94
229
|
tui.requestRender();
|
|
95
230
|
};
|
|
96
231
|
const tui = new TUI(new ProcessTerminal());
|
|
232
|
+
tui.setShowHardwareCursor(tuiSettings.showHardwareCursor);
|
|
233
|
+
tui.setClearOnShrink(tuiSettings.clearOnShrink);
|
|
97
234
|
const dedupeBackspace = createBackspaceDeduper();
|
|
98
235
|
tui.addInputListener((data) => {
|
|
99
236
|
const next = dedupeBackspace(data);
|
|
@@ -105,17 +242,108 @@ async function runTui(opts) {
|
|
|
105
242
|
connectionLabel: client.connectionLabel,
|
|
106
243
|
sessionKey: state.currentSessionKey,
|
|
107
244
|
showHints: tuiSettings.showStartupHints
|
|
108
|
-
}));
|
|
245
|
+
}), keybindings);
|
|
109
246
|
const statusContainer = new Container();
|
|
110
|
-
const bottomBar = new TuiBottomBar(() => state, () => opts.thinking);
|
|
111
|
-
const chatLog = new ChatLog();
|
|
247
|
+
const bottomBar = new TuiBottomBar(() => state, () => opts.thinking, () => formatKeyIds(keybindings, "app.message.dequeue", { capitalize: true }));
|
|
248
|
+
const chatLog = new ChatLog(keybindings);
|
|
249
|
+
let startupResources;
|
|
250
|
+
let startupCardShown = false;
|
|
251
|
+
chatLog.setShowThinking(state.showThinking);
|
|
112
252
|
chatLog.setToolsExpanded(state.toolsExpanded);
|
|
113
|
-
|
|
253
|
+
chatLog.setToolImageOptions({
|
|
254
|
+
showImages: tuiSettings.showImages,
|
|
255
|
+
imageWidthCells: tuiSettings.imageWidthCells,
|
|
256
|
+
cwd: process.cwd()
|
|
257
|
+
});
|
|
258
|
+
setExtensionLabel = (entryId, label) => {
|
|
259
|
+
sessionSnapshot.setLabel(entryId, label);
|
|
260
|
+
client.setTranscriptLabel(state.currentSessionKey, entryId, label).catch((err) => {
|
|
261
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
262
|
+
chatLog.addSystem(`Label update failed: ${errorMessage}`);
|
|
263
|
+
}).finally(() => {
|
|
264
|
+
updateFooter();
|
|
265
|
+
tui.requestRender();
|
|
266
|
+
});
|
|
267
|
+
};
|
|
268
|
+
appendExtensionEntry = (customType, data) => {
|
|
269
|
+
const normalized = customType.trim();
|
|
270
|
+
if (!normalized) throw new Error("appendEntry requires customType.");
|
|
271
|
+
sessionSnapshot.appendCustomEntry(normalized, data);
|
|
272
|
+
client.appendCustomEntry(state.currentSessionKey, normalized, data).catch((err) => {
|
|
273
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
274
|
+
chatLog.addSystem(`Custom entry append failed: ${errorMessage}`);
|
|
275
|
+
}).finally(() => {
|
|
276
|
+
updateFooter();
|
|
277
|
+
tui.requestRender();
|
|
278
|
+
});
|
|
279
|
+
};
|
|
280
|
+
sendExtensionMessage = (message, options) => {
|
|
281
|
+
const customType = message.customType.trim();
|
|
282
|
+
if (!customType) throw new Error("sendMessage requires customType.");
|
|
283
|
+
const display = message.display ?? true;
|
|
284
|
+
const nextMessage = {
|
|
285
|
+
customType,
|
|
286
|
+
content: message.content,
|
|
287
|
+
display,
|
|
288
|
+
details: message.details
|
|
289
|
+
};
|
|
290
|
+
sessionSnapshot.appendCustomMessage(nextMessage);
|
|
291
|
+
if (display) {
|
|
292
|
+
chatLog.addCustomMessage({
|
|
293
|
+
customType,
|
|
294
|
+
content: extensionCustomMessageContentToText(message.content),
|
|
295
|
+
rawContent: message.content,
|
|
296
|
+
details: message.details,
|
|
297
|
+
display
|
|
298
|
+
});
|
|
299
|
+
tui.requestRender();
|
|
300
|
+
}
|
|
301
|
+
const persist = client.appendCustomMessage(state.currentSessionKey, nextMessage).catch((err) => {
|
|
302
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
303
|
+
chatLog.addSystem(`Custom message append failed: ${errorMessage}`);
|
|
304
|
+
throw err;
|
|
305
|
+
}).finally(() => {
|
|
306
|
+
updateFooter();
|
|
307
|
+
tui.requestRender();
|
|
308
|
+
});
|
|
309
|
+
const turnText = extensionCustomMessageToTurnText(nextMessage).trim();
|
|
310
|
+
if (!turnText) return;
|
|
311
|
+
persist.then(() => {
|
|
312
|
+
const controlText = `Continue with the extension message "${customType}" above.`;
|
|
313
|
+
if (options?.deliverAs === "nextTurn") {
|
|
314
|
+
pendingNextTurnCustomMessages.push(controlText);
|
|
315
|
+
chatLog.addSystem(theme.dim(`Queued extension message for next turn (${pendingNextTurnCustomMessages.length}).`));
|
|
316
|
+
bottomBar.invalidate();
|
|
317
|
+
tui.requestRender();
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
if (state.activeRunId) {
|
|
321
|
+
if (options?.deliverAs === "followUp") {
|
|
322
|
+
state.messageFollowUpQueue.push(controlText);
|
|
323
|
+
chatLog.addSystem(theme.dim(`Queued extension follow-up (${state.messageFollowUpQueue.length} in queue). ${tuiSettings.followUpMode === "all" ? "All queued messages send together when this reply finishes." : "Next sends when this reply finishes."}`));
|
|
324
|
+
bottomBar.invalidate();
|
|
325
|
+
tui.requestRender();
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
steerMessage(turnText);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
if (options?.triggerTurn) sendMessage(controlText);
|
|
332
|
+
}).catch(() => {});
|
|
333
|
+
};
|
|
334
|
+
const defaultEditor = new CustomEditor(tui, editorTheme, keybindings, {
|
|
335
|
+
paddingX: tuiSettings.editorPaddingX,
|
|
336
|
+
autocompleteMaxVisible: tuiSettings.autocompleteMaxVisible
|
|
337
|
+
});
|
|
338
|
+
let editor = defaultEditor;
|
|
339
|
+
let editorComponentFactory;
|
|
340
|
+
const editorContainer = new Container();
|
|
341
|
+
editorContainer.addChild(editor);
|
|
114
342
|
const root = new Container();
|
|
115
343
|
root.addChild(header);
|
|
116
344
|
root.addChild(chatLog);
|
|
117
345
|
root.addChild(statusContainer);
|
|
118
|
-
root.addChild(
|
|
346
|
+
root.addChild(editorContainer);
|
|
119
347
|
root.addChild(bottomBar);
|
|
120
348
|
tui.addChild(root);
|
|
121
349
|
tui.setFocus(editor);
|
|
@@ -123,7 +351,10 @@ async function runTui(opts) {
|
|
|
123
351
|
let isBashExcludeContext = false;
|
|
124
352
|
const updateEditorBorderColor = () => {
|
|
125
353
|
if (isBashMode) editor.borderColor = isBashExcludeContext ? getBashExcludeBorderColor() : getBashModeBorderColor();
|
|
126
|
-
else
|
|
354
|
+
else {
|
|
355
|
+
const level = state.sessionInfo.thinkingLevel ?? opts.thinking ?? "off";
|
|
356
|
+
editor.borderColor = getThinkingBorderColor(level);
|
|
357
|
+
}
|
|
127
358
|
tui.requestRender();
|
|
128
359
|
};
|
|
129
360
|
editor.onChange = (text) => {
|
|
@@ -136,8 +367,330 @@ async function runTui(opts) {
|
|
|
136
367
|
updateEditorBorderColor();
|
|
137
368
|
}
|
|
138
369
|
};
|
|
139
|
-
const
|
|
140
|
-
|
|
370
|
+
const copyDefaultEditorAppHandlers = (target) => {
|
|
371
|
+
const customEditor = target;
|
|
372
|
+
if (!(customEditor.actionHandlers instanceof Map)) return;
|
|
373
|
+
customEditor.onEscape ??= () => defaultEditor.onEscape?.();
|
|
374
|
+
customEditor.onCtrlD ??= () => defaultEditor.onCtrlD?.();
|
|
375
|
+
customEditor.onPasteImage ??= () => defaultEditor.onPasteImage?.();
|
|
376
|
+
customEditor.onExtensionShortcut ??= (data) => defaultEditor.onExtensionShortcut?.(data) ?? false;
|
|
377
|
+
for (const [action, handler] of defaultEditor.actionHandlers) customEditor.actionHandlers.set(action, handler);
|
|
378
|
+
};
|
|
379
|
+
const setEditorExtensionShortcut = () => {
|
|
380
|
+
const customEditor = editor;
|
|
381
|
+
customEditor.onExtensionShortcut = (data) => extensionRuntime.handleShortcut(data);
|
|
382
|
+
};
|
|
383
|
+
const setEditorComponent = (factory) => {
|
|
384
|
+
editorComponentFactory = factory;
|
|
385
|
+
const currentText = editor.getText();
|
|
386
|
+
editorContainer.clear();
|
|
387
|
+
if (factory) {
|
|
388
|
+
const nextEditor = factory(tui, editorTheme, keybindings);
|
|
389
|
+
nextEditor.onSubmit = defaultEditor.onSubmit;
|
|
390
|
+
nextEditor.onChange = defaultEditor.onChange;
|
|
391
|
+
nextEditor.setText(currentText);
|
|
392
|
+
if (nextEditor.borderColor !== void 0) nextEditor.borderColor = defaultEditor.borderColor;
|
|
393
|
+
nextEditor.setPaddingX?.(tuiSettings.editorPaddingX);
|
|
394
|
+
nextEditor.setAutocompleteMaxVisible?.(tuiSettings.autocompleteMaxVisible);
|
|
395
|
+
nextEditor.setAutocompleteProvider?.(extensionRuntime.autocompleteProvider);
|
|
396
|
+
copyDefaultEditorAppHandlers(nextEditor);
|
|
397
|
+
editor = nextEditor;
|
|
398
|
+
} else {
|
|
399
|
+
defaultEditor.setText(currentText);
|
|
400
|
+
editor = defaultEditor;
|
|
401
|
+
}
|
|
402
|
+
editorContainer.addChild(editor);
|
|
403
|
+
setEditorExtensionShortcut();
|
|
404
|
+
tui.setFocus(editor);
|
|
405
|
+
updateEditorBorderColor();
|
|
406
|
+
tui.requestRender();
|
|
407
|
+
};
|
|
408
|
+
let activeEditorSelectorClose = null;
|
|
409
|
+
const closeEditorSelector = () => {
|
|
410
|
+
activeEditorSelectorClose?.();
|
|
411
|
+
};
|
|
412
|
+
const openEditorSelector = (component, focus = component) => {
|
|
413
|
+
closeEditorSelector();
|
|
414
|
+
editorContainer.clear();
|
|
415
|
+
editorContainer.addChild(component);
|
|
416
|
+
tui.setFocus(focus);
|
|
417
|
+
tui.requestRender();
|
|
418
|
+
const close = () => {
|
|
419
|
+
if (activeEditorSelectorClose !== close) return;
|
|
420
|
+
activeEditorSelectorClose = null;
|
|
421
|
+
editorContainer.clear();
|
|
422
|
+
editorContainer.addChild(editor);
|
|
423
|
+
tui.setFocus(editor);
|
|
424
|
+
tui.requestRender();
|
|
425
|
+
};
|
|
426
|
+
activeEditorSelectorClose = close;
|
|
427
|
+
return close;
|
|
428
|
+
};
|
|
429
|
+
const openCommandOverlay = (component, _options) => {
|
|
430
|
+
let hidden = false;
|
|
431
|
+
let closeCurrent = openEditorSelector(component, component);
|
|
432
|
+
return {
|
|
433
|
+
hide: () => closeCurrent(),
|
|
434
|
+
setHidden: (nextHidden) => {
|
|
435
|
+
hidden = nextHidden;
|
|
436
|
+
if (nextHidden) closeCurrent();
|
|
437
|
+
else closeCurrent = openEditorSelector(component, component);
|
|
438
|
+
},
|
|
439
|
+
isHidden: () => hidden,
|
|
440
|
+
focus: () => tui.setFocus(component),
|
|
441
|
+
unfocus: () => tui.setFocus(editor),
|
|
442
|
+
isFocused: () => false
|
|
443
|
+
};
|
|
444
|
+
};
|
|
445
|
+
const closeCommandOverlay = () => {
|
|
446
|
+
closeEditorSelector();
|
|
447
|
+
};
|
|
448
|
+
const slashCommands = getSlashCommands(isLocalMode, keybindings);
|
|
449
|
+
let extensionWorkingMessage;
|
|
450
|
+
let extensionWorkingVisible = true;
|
|
451
|
+
let extensionWorkingIndicator;
|
|
452
|
+
const getAllExtensionThemes = () => {
|
|
453
|
+
const customDir = getCustomThemesDir();
|
|
454
|
+
return listAvailableThemeIds().map((name) => ({
|
|
455
|
+
name,
|
|
456
|
+
path: name === "auto" || name === "dark" || name === "light" ? void 0 : join(customDir, `${name}.json`)
|
|
457
|
+
}));
|
|
458
|
+
};
|
|
459
|
+
const getExtensionTheme = (name) => {
|
|
460
|
+
const normalized = name.trim().toLowerCase() || "auto";
|
|
461
|
+
if (!listAvailableThemeIds().includes(normalized)) return void 0;
|
|
462
|
+
const currentTheme = tuiSettings.theme;
|
|
463
|
+
applyThemeById(normalized);
|
|
464
|
+
const resolved = getThemeExports().theme;
|
|
465
|
+
applyThemeById(currentTheme);
|
|
466
|
+
return resolved;
|
|
467
|
+
};
|
|
468
|
+
const setExtensionTheme = (nextTheme) => {
|
|
469
|
+
const normalized = nextTheme.trim().toLowerCase() || "auto";
|
|
470
|
+
if (!listAvailableThemeIds().includes(normalized)) return {
|
|
471
|
+
success: false,
|
|
472
|
+
error: `Unknown theme: ${nextTheme}`
|
|
473
|
+
};
|
|
474
|
+
try {
|
|
475
|
+
resolveThemePalette(normalized);
|
|
476
|
+
tuiSettings = {
|
|
477
|
+
...tuiSettings,
|
|
478
|
+
theme: normalized
|
|
479
|
+
};
|
|
480
|
+
saveTuiSettings(tuiSettings);
|
|
481
|
+
applyThemeById(normalized);
|
|
482
|
+
updateEditorBorderColor();
|
|
483
|
+
chatLog.invalidate();
|
|
484
|
+
header.invalidate();
|
|
485
|
+
bottomBar.invalidate();
|
|
486
|
+
tui.requestRender();
|
|
487
|
+
return { success: true };
|
|
488
|
+
} catch (err) {
|
|
489
|
+
return {
|
|
490
|
+
success: false,
|
|
491
|
+
error: err instanceof Error ? err.message : String(err)
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
const getAvailableProviderCount = () => getAllProviders().filter((provider) => isProviderConfiguredSync(provider)).length;
|
|
496
|
+
const getExtensionSystemPrompt = () => resolveEffectiveAgentProfileForSession(config, state.currentSessionKey).systemPromptOverride ?? "";
|
|
497
|
+
const waitForTuiIdle = async () => {
|
|
498
|
+
while (state.activeRunId != null || state.isCompacting || state.activityStatus === "sending" || state.activityStatus === "waiting" || state.activityStatus === "streaming" || state.activityStatus === "running" || state.activityStatus === "compacting") await new Promise((resolveDelay) => setTimeout(resolveDelay, 50));
|
|
499
|
+
};
|
|
500
|
+
const createReplacementContext = () => {
|
|
501
|
+
const model = state.sessionInfo.model ? {
|
|
502
|
+
...state.sessionInfo.modelProvider ? { provider: state.sessionInfo.modelProvider } : {},
|
|
503
|
+
id: state.sessionInfo.model,
|
|
504
|
+
ref: state.sessionInfo.modelProvider ? `${state.sessionInfo.modelProvider}/${state.sessionInfo.model}` : state.sessionInfo.model,
|
|
505
|
+
contextWindow: state.sessionInfo.contextWindow ?? null
|
|
506
|
+
} : void 0;
|
|
507
|
+
return {
|
|
508
|
+
mode: "tui",
|
|
509
|
+
hasUI: true,
|
|
510
|
+
signal: client.getActiveSignal?.(),
|
|
511
|
+
ui: {
|
|
512
|
+
select: async () => void 0,
|
|
513
|
+
confirm: async () => false,
|
|
514
|
+
input: async () => void 0,
|
|
515
|
+
notify: (message, level) => {
|
|
516
|
+
const prefix = level === "error" ? "Error: " : level === "warn" || level === "warning" ? "Warning: " : "";
|
|
517
|
+
chatLog.addSystem(`${prefix}${message}`);
|
|
518
|
+
tui.requestRender();
|
|
519
|
+
},
|
|
520
|
+
onTerminalInput: (handler) => tui.addInputListener(handler),
|
|
521
|
+
setStatus: () => {},
|
|
522
|
+
setWorkingMessage: (message) => {
|
|
523
|
+
extensionWorkingMessage = message?.trim() || void 0;
|
|
524
|
+
renderStatus();
|
|
525
|
+
},
|
|
526
|
+
setWorkingVisible: (visible) => {
|
|
527
|
+
extensionWorkingVisible = visible;
|
|
528
|
+
renderStatus();
|
|
529
|
+
},
|
|
530
|
+
setWorkingIndicator: (indicator) => {
|
|
531
|
+
extensionWorkingIndicator = indicator ?? void 0;
|
|
532
|
+
statusLoader?.setIndicator(indicator ?? void 0);
|
|
533
|
+
renderStatus();
|
|
534
|
+
},
|
|
535
|
+
setHiddenThinkingLabel: (label) => {
|
|
536
|
+
chatLog.setHiddenThinkingLabel(label ?? void 0);
|
|
537
|
+
tui.requestRender();
|
|
538
|
+
},
|
|
539
|
+
setWidget: () => {},
|
|
540
|
+
setFooter: () => {},
|
|
541
|
+
setHeader: () => {},
|
|
542
|
+
custom: async () => void 0,
|
|
543
|
+
setTitle: (title) => tui.terminal.setTitle(title),
|
|
544
|
+
pasteToEditor: (text) => editor.handleInput(`\x1b[200~${text}\x1b[201~`),
|
|
545
|
+
setEditorText: (text) => editor.setText(text),
|
|
546
|
+
getEditorText: () => editor.getExpandedText?.() ?? editor.getText(),
|
|
547
|
+
editor: async () => void 0,
|
|
548
|
+
addAutocompleteProvider: () => () => {},
|
|
549
|
+
setEditorComponent,
|
|
550
|
+
getEditorComponent: () => editorComponentFactory,
|
|
551
|
+
theme,
|
|
552
|
+
getAllThemes: getAllExtensionThemes,
|
|
553
|
+
getTheme: getExtensionTheme,
|
|
554
|
+
setTheme: setExtensionTheme,
|
|
555
|
+
getToolsExpanded: () => state.toolsExpanded,
|
|
556
|
+
setToolsExpanded: (expanded) => {
|
|
557
|
+
state.toolsExpanded = expanded;
|
|
558
|
+
tuiSettings = {
|
|
559
|
+
...tuiSettings,
|
|
560
|
+
toolsExpanded: expanded
|
|
561
|
+
};
|
|
562
|
+
saveTuiSettings(tuiSettings);
|
|
563
|
+
chatLog.setToolsExpanded(expanded);
|
|
564
|
+
updateFooter();
|
|
565
|
+
tui.requestRender();
|
|
566
|
+
}
|
|
567
|
+
},
|
|
568
|
+
sessionManager: sessionSnapshot.manager(),
|
|
569
|
+
modelRegistry: {
|
|
570
|
+
find(provider, modelId) {
|
|
571
|
+
return getAllModels().find((candidate) => candidate.provider === provider && candidate.id === modelId);
|
|
572
|
+
},
|
|
573
|
+
async getApiKeyAndHeaders(nextModel) {
|
|
574
|
+
const provider = typeof nextModel.provider === "string" ? nextModel.provider : void 0;
|
|
575
|
+
if (!provider) return {
|
|
576
|
+
ok: false,
|
|
577
|
+
error: "Model provider is missing."
|
|
578
|
+
};
|
|
579
|
+
try {
|
|
580
|
+
return {
|
|
581
|
+
ok: true,
|
|
582
|
+
apiKey: await getApiKey(provider),
|
|
583
|
+
headers: {}
|
|
584
|
+
};
|
|
585
|
+
} catch (error) {
|
|
586
|
+
return {
|
|
587
|
+
ok: false,
|
|
588
|
+
error: error instanceof Error ? error.message : String(error)
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
},
|
|
593
|
+
model,
|
|
594
|
+
cwd: process.cwd(),
|
|
595
|
+
sessionKey: state.currentSessionKey,
|
|
596
|
+
isProjectTrusted: isCurrentProjectTrusted,
|
|
597
|
+
isIdle: () => !state.activeRunId && !state.isCompacting,
|
|
598
|
+
hasPendingMessages: () => state.messageFollowUpQueue.length > 0 || state.steeringQueue.length > 0 || state.compactionQueue.length > 0,
|
|
599
|
+
abort: () => abortActive(),
|
|
600
|
+
shutdown: () => requestExit(),
|
|
601
|
+
compact: (options) => runCompaction(options?.customInstructions, {
|
|
602
|
+
onComplete: options?.onComplete,
|
|
603
|
+
onError: options?.onError
|
|
604
|
+
}),
|
|
605
|
+
getSystemPrompt: getExtensionSystemPrompt,
|
|
606
|
+
getSystemPromptOptions: () => ({
|
|
607
|
+
cwd: process.cwd(),
|
|
608
|
+
sessionKey: state.currentSessionKey,
|
|
609
|
+
...model ? { model } : {}
|
|
610
|
+
}),
|
|
611
|
+
waitForIdle: waitForTuiIdle,
|
|
612
|
+
newSession: (options) => runExtensionNewSession(options),
|
|
613
|
+
fork: (entryId, options) => runExtensionFork(entryId, options),
|
|
614
|
+
navigateTree: (targetId, options) => runExtensionNavigateTree(targetId, options),
|
|
615
|
+
switchSession: (sessionPath, options) => runExtensionSwitchSession(sessionPath, options),
|
|
616
|
+
reload: async () => {
|
|
617
|
+
await loadSessionHistory({ merge: true });
|
|
618
|
+
await refreshSessionInfoWithBorder();
|
|
619
|
+
},
|
|
620
|
+
getModel: () => model,
|
|
621
|
+
setModel: (modelRef) => switchCurrentModel(modelRef),
|
|
622
|
+
getThinkingLevel: () => state.sessionInfo.thinkingLevel,
|
|
623
|
+
setThinkingLevel,
|
|
624
|
+
getReasoningLevel: () => state.sessionInfo.reasoningLevel,
|
|
625
|
+
setReasoningLevel,
|
|
626
|
+
getVerboseLevel: () => state.sessionInfo.verboseLevel,
|
|
627
|
+
setVerboseLevel,
|
|
628
|
+
getCommands: () => slashCommands.map((command) => ({
|
|
629
|
+
name: command.name,
|
|
630
|
+
description: command.description,
|
|
631
|
+
source: "builtin"
|
|
632
|
+
})),
|
|
633
|
+
getContextUsage: () => {
|
|
634
|
+
const tokens = state.sessionInfo.totalTokens ?? state.sessionInfo.contextTokens ?? null;
|
|
635
|
+
const contextWindow = state.sessionInfo.contextWindow ?? null;
|
|
636
|
+
const percent = state.sessionInfo.contextUsagePercent ?? null;
|
|
637
|
+
if (tokens == null && contextWindow == null) return void 0;
|
|
638
|
+
return {
|
|
639
|
+
estimatedTokens: tokens,
|
|
640
|
+
tokens,
|
|
641
|
+
contextWindow,
|
|
642
|
+
usagePercent: percent,
|
|
643
|
+
percent
|
|
644
|
+
};
|
|
645
|
+
},
|
|
646
|
+
notify: (message, level) => {
|
|
647
|
+
const prefix = level === "error" ? "Error: " : level === "warn" || level === "warning" ? "Warning: " : "";
|
|
648
|
+
chatLog.addSystem(`${prefix}${message}`);
|
|
649
|
+
tui.requestRender();
|
|
650
|
+
},
|
|
651
|
+
sendMessage: async (message, options) => sendExtensionMessage(message, options),
|
|
652
|
+
sendUserMessage: async (content, options) => sendExtensionUserMessage(content, options)
|
|
653
|
+
};
|
|
654
|
+
};
|
|
655
|
+
const runWithReplacementContext = async (callback) => {
|
|
656
|
+
if (callback) await callback(createReplacementContext());
|
|
657
|
+
};
|
|
658
|
+
const runExtensionNewSession = async (options) => {
|
|
659
|
+
await abortActive({ clearUi: false });
|
|
660
|
+
await setSession(resolveSessionKey(`session-${randomUUID()}`));
|
|
661
|
+
await options?.setup?.(sessionSnapshot.manager());
|
|
662
|
+
await runWithReplacementContext(options?.withSession);
|
|
663
|
+
return { cancelled: false };
|
|
664
|
+
};
|
|
665
|
+
const runExtensionFork = async (entryId, options) => {
|
|
666
|
+
const rowNumber = transcriptTreeEntryIdToRowNumber(entryId);
|
|
667
|
+
if (rowNumber == null) throw new Error(`Invalid entry ID for forking: ${entryId}`);
|
|
668
|
+
const throughRow = options?.position === "before" ? rowNumber - 1 : rowNumber;
|
|
669
|
+
if (throughRow <= 0) throw new Error(`Invalid entry ID for forking: ${entryId}`);
|
|
670
|
+
const sourceSessionKey = state.currentSessionKey;
|
|
671
|
+
const targetKey = resolveSessionKey(`fork-${randomUUID()}`);
|
|
672
|
+
await abortActive({ clearUi: false });
|
|
673
|
+
const result = await client.forkSessionAt(sourceSessionKey, targetKey, `row-${throughRow}`);
|
|
674
|
+
await setSession(result.sessionKey);
|
|
675
|
+
chatLog.addBranchSummary({
|
|
676
|
+
sourceSessionKey,
|
|
677
|
+
targetSessionKey: result.sessionKey,
|
|
678
|
+
rowCount: result.rowCount,
|
|
679
|
+
entryId
|
|
680
|
+
});
|
|
681
|
+
await runWithReplacementContext(options?.withSession);
|
|
682
|
+
return { cancelled: false };
|
|
683
|
+
};
|
|
684
|
+
const runExtensionNavigateTree = async (targetId, options) => {
|
|
685
|
+
if (options?.label) setExtensionLabel(targetId, options.label);
|
|
686
|
+
return runExtensionFork(targetId, { position: "at" });
|
|
687
|
+
};
|
|
688
|
+
const runExtensionSwitchSession = async (sessionPath, options) => {
|
|
689
|
+
await abortActive({ clearUi: false });
|
|
690
|
+
await setSession(sessionPath);
|
|
691
|
+
await runWithReplacementContext(options?.withSession);
|
|
692
|
+
return { cancelled: false };
|
|
693
|
+
};
|
|
141
694
|
const extensionRuntime = createTuiExtensionRuntime({
|
|
142
695
|
registry: extensionRegistry,
|
|
143
696
|
tui,
|
|
@@ -146,17 +699,91 @@ async function runTui(opts) {
|
|
|
146
699
|
bottomBar,
|
|
147
700
|
getState: () => state,
|
|
148
701
|
baseSlashCommands: slashCommands,
|
|
702
|
+
keybindings,
|
|
703
|
+
addInputListener: (handler) => tui.addInputListener(handler),
|
|
704
|
+
setTitle: (title) => tui.terminal.setTitle(title),
|
|
705
|
+
pasteToEditor: (text) => editor.handleInput(`\x1b[200~${text}\x1b[201~`),
|
|
706
|
+
setEditorText: (text) => editor.setText(text),
|
|
707
|
+
getEditorText: () => editor.getExpandedText?.() ?? editor.getText(),
|
|
708
|
+
setEditorComponent,
|
|
709
|
+
getEditorComponent: () => editorComponentFactory,
|
|
710
|
+
getThemeObject: () => theme,
|
|
711
|
+
getAllThemes: getAllExtensionThemes,
|
|
712
|
+
getTheme: getExtensionTheme,
|
|
713
|
+
setTheme: setExtensionTheme,
|
|
714
|
+
getToolsExpanded: () => state.toolsExpanded,
|
|
715
|
+
setToolsExpanded: (expanded) => {
|
|
716
|
+
state.toolsExpanded = expanded;
|
|
717
|
+
tuiSettings = {
|
|
718
|
+
...tuiSettings,
|
|
719
|
+
toolsExpanded: expanded
|
|
720
|
+
};
|
|
721
|
+
saveTuiSettings(tuiSettings);
|
|
722
|
+
chatLog.setToolsExpanded(expanded);
|
|
723
|
+
updateFooter();
|
|
724
|
+
tui.requestRender();
|
|
725
|
+
},
|
|
726
|
+
getAvailableProviderCount,
|
|
727
|
+
getActiveSignal: () => client.getActiveSignal?.(),
|
|
728
|
+
isProjectTrusted: isCurrentProjectTrusted,
|
|
729
|
+
getSessionManager: () => sessionSnapshot.manager(),
|
|
730
|
+
getSystemPrompt: getExtensionSystemPrompt,
|
|
731
|
+
getSystemPromptOptions: () => ({
|
|
732
|
+
cwd: process.cwd(),
|
|
733
|
+
sessionKey: state.currentSessionKey,
|
|
734
|
+
...state.sessionInfo.model ? { model: {
|
|
735
|
+
...state.sessionInfo.modelProvider ? { provider: state.sessionInfo.modelProvider } : {},
|
|
736
|
+
id: state.sessionInfo.model,
|
|
737
|
+
ref: state.sessionInfo.modelProvider ? `${state.sessionInfo.modelProvider}/${state.sessionInfo.model}` : state.sessionInfo.model,
|
|
738
|
+
contextWindow: state.sessionInfo.contextWindow ?? null
|
|
739
|
+
} } : {}
|
|
740
|
+
}),
|
|
741
|
+
waitForIdle: waitForTuiIdle,
|
|
742
|
+
newSession: runExtensionNewSession,
|
|
743
|
+
forkSession: runExtensionFork,
|
|
744
|
+
navigateTree: runExtensionNavigateTree,
|
|
745
|
+
switchSession: runExtensionSwitchSession,
|
|
746
|
+
reload: async () => {
|
|
747
|
+
await loadSessionHistory();
|
|
748
|
+
await refreshSessionInfoWithBorder();
|
|
749
|
+
},
|
|
750
|
+
sendUserMessage: async (content, options) => sendExtensionUserMessage(content, options),
|
|
751
|
+
sendMessage: async (message, options) => sendExtensionMessage(message, options),
|
|
149
752
|
cwd: process.cwd(),
|
|
150
753
|
fdPath: resolveFdPath(),
|
|
151
|
-
openOverlay,
|
|
152
|
-
closeOverlay,
|
|
754
|
+
openOverlay: openCommandOverlay,
|
|
755
|
+
closeOverlay: closeCommandOverlay,
|
|
153
756
|
onInvalidate: () => {
|
|
154
757
|
updateHeader();
|
|
155
758
|
updateFooter();
|
|
156
759
|
tui.requestRender();
|
|
760
|
+
},
|
|
761
|
+
abortActive: () => abortActive(),
|
|
762
|
+
requestExit: () => requestExit(),
|
|
763
|
+
compactSession: (options) => runCompaction(options?.customInstructions, {
|
|
764
|
+
onComplete: options?.onComplete,
|
|
765
|
+
onError: options?.onError
|
|
766
|
+
}),
|
|
767
|
+
setModel: (modelRef) => switchCurrentModel(modelRef),
|
|
768
|
+
setThinkingLevel: (level) => setThinkingLevel(level),
|
|
769
|
+
setReasoningLevel: (level) => setReasoningLevel(level),
|
|
770
|
+
setVerboseLevel: (level) => setVerboseLevel(level),
|
|
771
|
+
setWorkingMessage: (message) => {
|
|
772
|
+
extensionWorkingMessage = message?.trim() || void 0;
|
|
773
|
+
renderStatus();
|
|
774
|
+
},
|
|
775
|
+
setWorkingVisible: (visible) => {
|
|
776
|
+
extensionWorkingVisible = visible;
|
|
777
|
+
renderStatus();
|
|
778
|
+
},
|
|
779
|
+
setWorkingIndicator: (indicator) => {
|
|
780
|
+
extensionWorkingIndicator = indicator;
|
|
781
|
+
statusLoader?.setIndicator(indicator);
|
|
782
|
+
renderStatus();
|
|
157
783
|
}
|
|
158
784
|
});
|
|
159
|
-
editor.setAutocompleteProvider(extensionRuntime.autocompleteProvider);
|
|
785
|
+
editor.setAutocompleteProvider?.(extensionRuntime.autocompleteProvider);
|
|
786
|
+
setEditorExtensionShortcut();
|
|
160
787
|
let statusLoader = null;
|
|
161
788
|
let statusStartedAt = null;
|
|
162
789
|
let lastActivityStatus = "";
|
|
@@ -166,7 +793,8 @@ async function runTui(opts) {
|
|
|
166
793
|
"waiting",
|
|
167
794
|
"streaming",
|
|
168
795
|
"running",
|
|
169
|
-
"compacting"
|
|
796
|
+
"compacting",
|
|
797
|
+
"recovering"
|
|
170
798
|
]);
|
|
171
799
|
const syncTerminalProgress = () => {
|
|
172
800
|
if (!tuiSettings.showTerminalProgress) {
|
|
@@ -179,6 +807,11 @@ async function runTui(opts) {
|
|
|
179
807
|
let streamWatchdogId = null;
|
|
180
808
|
const touchStreamingActivity = () => {
|
|
181
809
|
lastStreamActivityAt = Date.now();
|
|
810
|
+
if (state.activeRunId && state.runStatus.lastActivityAt == null) state.runStatus = {
|
|
811
|
+
...state.runStatus,
|
|
812
|
+
runId: state.activeRunId,
|
|
813
|
+
lastActivityAt: lastStreamActivityAt
|
|
814
|
+
};
|
|
182
815
|
};
|
|
183
816
|
const formatElapsed = (startMs) => {
|
|
184
817
|
const totalSeconds = Math.max(0, Math.floor((Date.now() - startMs) / 1e3));
|
|
@@ -186,24 +819,29 @@ async function runTui(opts) {
|
|
|
186
819
|
return `${Math.floor(totalSeconds / 60)}m ${totalSeconds % 60}s`;
|
|
187
820
|
};
|
|
188
821
|
const renderStatus = () => {
|
|
189
|
-
|
|
822
|
+
const isBusy = busyStates.has(state.activityStatus);
|
|
823
|
+
if (isBusy && extensionWorkingVisible) {
|
|
190
824
|
if (!statusStartedAt || lastActivityStatus !== state.activityStatus) statusStartedAt = Date.now();
|
|
191
825
|
if (!statusLoader) {
|
|
192
826
|
statusContainer.clear();
|
|
193
|
-
statusLoader = new Loader(tui, (spinner) => theme.accent(spinner), (text) => theme.bold(theme.accentSoft(text)), "");
|
|
827
|
+
statusLoader = new Loader(tui, (spinner) => theme.accent(spinner), (text) => theme.bold(theme.accentSoft(text)), "", extensionWorkingIndicator);
|
|
194
828
|
statusContainer.addChild(statusLoader);
|
|
195
829
|
}
|
|
196
830
|
const elapsed = formatElapsed(statusStartedAt);
|
|
197
|
-
|
|
831
|
+
const loaderMessage = state.progressMessage ?? extensionWorkingMessage ?? state.activityStatus;
|
|
832
|
+
statusLoader.setMessage(`${loaderMessage} • ${elapsed} | ${state.connectionStatus}`);
|
|
198
833
|
if (!elapsedTimerId) elapsedTimerId = setInterval(() => {
|
|
199
834
|
if (statusStartedAt && statusLoader) {
|
|
200
835
|
const el = formatElapsed(statusStartedAt);
|
|
201
|
-
|
|
836
|
+
const message = state.progressMessage ?? extensionWorkingMessage ?? state.activityStatus;
|
|
837
|
+
statusLoader.setMessage(`${message} • ${el} | ${state.connectionStatus}`);
|
|
202
838
|
}
|
|
203
839
|
}, 1e3);
|
|
204
840
|
} else {
|
|
205
|
-
|
|
206
|
-
|
|
841
|
+
if (!isBusy) {
|
|
842
|
+
state.progressMessage = null;
|
|
843
|
+
statusStartedAt = null;
|
|
844
|
+
}
|
|
207
845
|
if (elapsedTimerId) {
|
|
208
846
|
clearInterval(elapsedTimerId);
|
|
209
847
|
elapsedTimerId = null;
|
|
@@ -262,6 +900,7 @@ async function runTui(opts) {
|
|
|
262
900
|
tui.terminal.setProgress(false);
|
|
263
901
|
drainAndStopTuiSafely(tui).then(() => {
|
|
264
902
|
restoreStdio();
|
|
903
|
+
process.stdout.write(`\nTo resume this session: ${formatTuiResumeCommand(opts, state.currentSessionKey)}\n`);
|
|
265
904
|
finishTui?.();
|
|
266
905
|
process.exit(0);
|
|
267
906
|
});
|
|
@@ -271,11 +910,11 @@ async function runTui(opts) {
|
|
|
271
910
|
chatLog,
|
|
272
911
|
tui,
|
|
273
912
|
state,
|
|
274
|
-
assembler,
|
|
275
913
|
resolveSessionKey,
|
|
276
914
|
updateHeader,
|
|
277
915
|
updateFooter,
|
|
278
916
|
setActivityStatus,
|
|
917
|
+
sessionSnapshot,
|
|
279
918
|
onAgentIdChange: (agentId) => {
|
|
280
919
|
currentAgentId = agentId;
|
|
281
920
|
}
|
|
@@ -284,6 +923,166 @@ async function runTui(opts) {
|
|
|
284
923
|
await refreshSessionInfo();
|
|
285
924
|
updateEditorBorderColor();
|
|
286
925
|
};
|
|
926
|
+
const refreshStartupResources = async () => {
|
|
927
|
+
if (!client.getStartupResources) return;
|
|
928
|
+
try {
|
|
929
|
+
startupResources = await client.getStartupResources(state.currentSessionKey);
|
|
930
|
+
} catch {
|
|
931
|
+
startupResources = void 0;
|
|
932
|
+
}
|
|
933
|
+
};
|
|
934
|
+
const showStartupCardOnce = () => {
|
|
935
|
+
if (startupCardShown) return;
|
|
936
|
+
startupCardShown = true;
|
|
937
|
+
chatLog.addSystem(formatTuiStartupText({
|
|
938
|
+
state,
|
|
939
|
+
isLocal: isLocalMode,
|
|
940
|
+
keybindings,
|
|
941
|
+
resources: startupResources,
|
|
942
|
+
expanded: false
|
|
943
|
+
}));
|
|
944
|
+
};
|
|
945
|
+
const applyStartupWorkingDirectory = async () => {
|
|
946
|
+
if (startupWorkingDirectoryApplied || !startupWorkingDirectory) return;
|
|
947
|
+
startupWorkingDirectoryApplied = true;
|
|
948
|
+
await client.patchSession(state.currentSessionKey, { workingDirectory: startupWorkingDirectory });
|
|
949
|
+
state.sessionInfo.effectiveWorkspacePath = startupWorkingDirectory;
|
|
950
|
+
state.sessionInfo.workingDirectoryLocked = true;
|
|
951
|
+
};
|
|
952
|
+
let streamRecoveryPromise = null;
|
|
953
|
+
const recoverActiveRunFromHistory = (reason) => {
|
|
954
|
+
if (!state.activeRunId) return Promise.resolve();
|
|
955
|
+
if (streamRecoveryPromise) return streamRecoveryPromise;
|
|
956
|
+
const runId = state.activeRunId;
|
|
957
|
+
markRunRecovering(state, Date.now());
|
|
958
|
+
state.progressMessage = "recovering stream history";
|
|
959
|
+
setActivityStatus("recovering");
|
|
960
|
+
streamRecoveryPromise = (async () => {
|
|
961
|
+
try {
|
|
962
|
+
await loadSessionHistory();
|
|
963
|
+
await refreshSessionInfoWithBorder();
|
|
964
|
+
if (state.activeRunId === runId) {
|
|
965
|
+
clearSeenStreamEventsForRun(runId);
|
|
966
|
+
if (client.resumeChat) {
|
|
967
|
+
const resumed = await client.resumeChat({
|
|
968
|
+
sessionKey: state.currentSessionKey,
|
|
969
|
+
runId
|
|
970
|
+
});
|
|
971
|
+
if (resumed.ok) {
|
|
972
|
+
state.progressMessage = "resuming stream";
|
|
973
|
+
setActivityStatus("recovering");
|
|
974
|
+
chatLog.addSystem(theme.dim(`Reattached to active run after ${reason}.`));
|
|
975
|
+
} else {
|
|
976
|
+
markRunRecoveryComplete(state, Date.now());
|
|
977
|
+
state.progressMessage = "stream stalled; resume unavailable";
|
|
978
|
+
setActivityStatus("stalled");
|
|
979
|
+
chatLog.addSystem(theme.dim(`Recovered persisted history after ${reason}, but could not resume stream: ${resumed.reason ?? "run relay unavailable"}. Press Escape or /abort to stop it.`));
|
|
980
|
+
}
|
|
981
|
+
} else {
|
|
982
|
+
markRunRecoveryComplete(state, Date.now());
|
|
983
|
+
state.progressMessage = "stream stalled; waiting for new events or abort";
|
|
984
|
+
setActivityStatus("stalled");
|
|
985
|
+
chatLog.addSystem(theme.dim(`Recovered persisted history after ${reason}. Active run is still marked stalled; press Escape or /abort to stop it.`));
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
} catch (error) {
|
|
989
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
990
|
+
chatLog.addSystem(theme.dim(`Stream recovery failed after ${reason}: ${errorMessage}`));
|
|
991
|
+
if (state.activeRunId === runId) {
|
|
992
|
+
markRunRecoveryComplete(state, Date.now());
|
|
993
|
+
setActivityStatus("stalled");
|
|
994
|
+
}
|
|
995
|
+
} finally {
|
|
996
|
+
streamRecoveryPromise = null;
|
|
997
|
+
updateFooter();
|
|
998
|
+
tui.requestRender();
|
|
999
|
+
}
|
|
1000
|
+
})();
|
|
1001
|
+
return streamRecoveryPromise;
|
|
1002
|
+
};
|
|
1003
|
+
const setThinkingLevel = async (level) => {
|
|
1004
|
+
try {
|
|
1005
|
+
await client.patchSession(state.currentSessionKey, { thinkingLevel: level });
|
|
1006
|
+
state.sessionInfo.thinkingLevel = level;
|
|
1007
|
+
await refreshSessionInfoWithBorder();
|
|
1008
|
+
updateFooter();
|
|
1009
|
+
chatLog.addStatus(theme.dim(`Thinking level: ${level}`));
|
|
1010
|
+
} catch (err) {
|
|
1011
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1012
|
+
chatLog.addSystem(`Thinking level change failed: ${errorMessage}`);
|
|
1013
|
+
} finally {
|
|
1014
|
+
tui.requestRender();
|
|
1015
|
+
}
|
|
1016
|
+
};
|
|
1017
|
+
const setReasoningLevel = async (level) => {
|
|
1018
|
+
try {
|
|
1019
|
+
await client.patchSession(state.currentSessionKey, { reasoningLevel: level });
|
|
1020
|
+
state.sessionInfo.reasoningLevel = level;
|
|
1021
|
+
await refreshSessionInfoWithBorder();
|
|
1022
|
+
updateFooter();
|
|
1023
|
+
chatLog.addStatus(theme.dim(`Reasoning visibility: ${level}`));
|
|
1024
|
+
} catch (err) {
|
|
1025
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1026
|
+
chatLog.addSystem(`Reasoning visibility change failed: ${errorMessage}`);
|
|
1027
|
+
} finally {
|
|
1028
|
+
tui.requestRender();
|
|
1029
|
+
}
|
|
1030
|
+
};
|
|
1031
|
+
const setVerboseLevel = async (level) => {
|
|
1032
|
+
try {
|
|
1033
|
+
await client.patchSession(state.currentSessionKey, { verboseLevel: level });
|
|
1034
|
+
state.sessionInfo.verboseLevel = level;
|
|
1035
|
+
await refreshSessionInfoWithBorder();
|
|
1036
|
+
updateFooter();
|
|
1037
|
+
chatLog.addStatus(theme.dim(`Verbose mode: ${level}`));
|
|
1038
|
+
} catch (err) {
|
|
1039
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1040
|
+
chatLog.addSystem(`Verbose mode change failed: ${errorMessage}`);
|
|
1041
|
+
} finally {
|
|
1042
|
+
tui.requestRender();
|
|
1043
|
+
}
|
|
1044
|
+
};
|
|
1045
|
+
const copyLastAssistant = async () => {
|
|
1046
|
+
const text = chatLog.getLastAssistantText().trim();
|
|
1047
|
+
if (!text) {
|
|
1048
|
+
chatLog.addSystem("No assistant messages to copy yet.");
|
|
1049
|
+
tui.requestRender();
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
try {
|
|
1053
|
+
await copyTextToClipboard(text);
|
|
1054
|
+
chatLog.addStatus(theme.dim("Copied last assistant message to clipboard"));
|
|
1055
|
+
} catch (err) {
|
|
1056
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1057
|
+
chatLog.addSystem(`Copy failed: ${errorMessage}`);
|
|
1058
|
+
} finally {
|
|
1059
|
+
tui.requestRender();
|
|
1060
|
+
}
|
|
1061
|
+
};
|
|
1062
|
+
const renameCurrentSession = async (name) => {
|
|
1063
|
+
const nextName = name.trim();
|
|
1064
|
+
if (!nextName) {
|
|
1065
|
+
chatLog.addSystem("Usage: /name <name>");
|
|
1066
|
+
tui.requestRender();
|
|
1067
|
+
return;
|
|
1068
|
+
}
|
|
1069
|
+
try {
|
|
1070
|
+
if (!(await client.renameSession(state.currentSessionKey, nextName)).ok) {
|
|
1071
|
+
chatLog.addSystem("Session rename failed.");
|
|
1072
|
+
tui.requestRender();
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
1075
|
+
state.sessionInfo.displayName = nextName;
|
|
1076
|
+
updateFooter();
|
|
1077
|
+
updateHeader();
|
|
1078
|
+
chatLog.addStatus(theme.dim(`Session name set: ${nextName}`));
|
|
1079
|
+
} catch (err) {
|
|
1080
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1081
|
+
chatLog.addSystem(`Session rename failed: ${errorMessage}`);
|
|
1082
|
+
} finally {
|
|
1083
|
+
tui.requestRender();
|
|
1084
|
+
}
|
|
1085
|
+
};
|
|
287
1086
|
const resolveModelChoiceIndex = () => {
|
|
288
1087
|
const choices = cycleModelChoices();
|
|
289
1088
|
if (choices.length === 0) return -1;
|
|
@@ -315,11 +1114,140 @@ async function runTui(opts) {
|
|
|
315
1114
|
}
|
|
316
1115
|
const idx = resolveModelChoiceIndex();
|
|
317
1116
|
const next = choices[((idx >= 0 ? idx : 0) + (dir === "forward" ? 1 : -1) + choices.length) % choices.length];
|
|
318
|
-
|
|
1117
|
+
switchCurrentModel(`${next.provider}/${next.id}`);
|
|
1118
|
+
};
|
|
1119
|
+
const listCurrentModels = async () => {
|
|
1120
|
+
if (modelChoices.length === 0) await refreshModelChoices();
|
|
1121
|
+
return modelChoices;
|
|
1122
|
+
};
|
|
1123
|
+
const switchCurrentModel = async (modelRef) => {
|
|
1124
|
+
const trimmed = modelRef.trim();
|
|
1125
|
+
if (!trimmed.includes("/")) {
|
|
1126
|
+
chatLog.addSystem("Usage: /switch <provider/model>");
|
|
1127
|
+
tui.requestRender();
|
|
1128
|
+
return;
|
|
1129
|
+
}
|
|
1130
|
+
if (modelChoices.length === 0) await refreshModelChoices();
|
|
1131
|
+
const [provider, id] = trimmed.split("/", 2);
|
|
1132
|
+
const selected = modelChoices.find((choice) => choice.provider === provider && choice.id === id);
|
|
1133
|
+
if (!selected) {
|
|
1134
|
+
chatLog.addSystem(`Model not found: ${trimmed}`);
|
|
1135
|
+
tui.requestRender();
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
try {
|
|
1139
|
+
await client.patchSession(state.currentSessionKey, { model: trimmed });
|
|
1140
|
+
state.sessionInfo.modelProvider = selected.provider;
|
|
1141
|
+
state.sessionInfo.model = selected.id;
|
|
1142
|
+
if (selected.contextWindow != null) state.sessionInfo.contextWindow = selected.contextWindow;
|
|
1143
|
+
await refreshSessionInfoWithBorder();
|
|
1144
|
+
updateFooter();
|
|
1145
|
+
updateHeader();
|
|
1146
|
+
chatLog.addStatus(theme.dim(`Model: ${trimmed}`));
|
|
1147
|
+
} catch (err) {
|
|
1148
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1149
|
+
chatLog.addSystem(`Model switch failed: ${errorMessage}`);
|
|
1150
|
+
} finally {
|
|
1151
|
+
tui.requestRender();
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
const exportCurrentSession = async (request) => {
|
|
1155
|
+
const outputPath = request.outputPath ? isAbsolute(request.outputPath) ? request.outputPath : resolve(process.cwd(), request.outputPath) : defaultExportPath(state.currentSessionKey, request.format);
|
|
1156
|
+
try {
|
|
1157
|
+
const backendFormat = request.format === "json" ? "json" : "markdown";
|
|
1158
|
+
const raw = await client.exportSession(state.currentSessionKey, backendFormat);
|
|
1159
|
+
const content = request.format === "html" ? wrapMarkdownExportAsHtml(raw) : raw;
|
|
1160
|
+
mkdirSync(dirname(outputPath), { recursive: true });
|
|
1161
|
+
writeFileSync(outputPath, content, "utf8");
|
|
1162
|
+
chatLog.addStatus(theme.dim(`Exported ${request.format} session to: ${outputPath}`));
|
|
1163
|
+
} catch (err) {
|
|
1164
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1165
|
+
chatLog.addSystem(`Export failed: ${errorMessage}`);
|
|
1166
|
+
} finally {
|
|
1167
|
+
tui.requestRender();
|
|
1168
|
+
}
|
|
1169
|
+
};
|
|
1170
|
+
const importSessionExport = async (request) => {
|
|
1171
|
+
const rawPath = request.inputPath?.trim();
|
|
1172
|
+
if (!rawPath) {
|
|
1173
|
+
chatLog.addSystem("Usage: /import <path.json> [target-session]");
|
|
1174
|
+
tui.requestRender();
|
|
1175
|
+
return;
|
|
1176
|
+
}
|
|
1177
|
+
const inputPath = isAbsolute(rawPath) ? rawPath : resolve(process.cwd(), rawPath);
|
|
1178
|
+
const targetKey = resolveSessionKey(request.targetKey?.trim() || `import-${randomUUID()}`);
|
|
1179
|
+
try {
|
|
1180
|
+
const content = readFileSync(inputPath, "utf8");
|
|
1181
|
+
const result = await client.importSession(targetKey, content);
|
|
1182
|
+
await setSession(result.sessionKey);
|
|
1183
|
+
chatLog.addStatus(theme.dim(`Imported ${result.rowCount} transcript rows from: ${inputPath}`));
|
|
1184
|
+
} catch (err) {
|
|
1185
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1186
|
+
chatLog.addSystem(`Import failed: ${errorMessage}`);
|
|
1187
|
+
} finally {
|
|
1188
|
+
tui.requestRender();
|
|
1189
|
+
}
|
|
1190
|
+
};
|
|
1191
|
+
const createShareLink = async (request) => {
|
|
1192
|
+
try {
|
|
1193
|
+
chatLog.addStatus(theme.dim(`Creating share for: ${request.path}`));
|
|
1194
|
+
tui.requestRender();
|
|
1195
|
+
const result = await client.createShare(state.currentSessionKey, request, { agentId: currentAgentId });
|
|
1196
|
+
chatLog.addSystem(formatTuiShareResult(result));
|
|
1197
|
+
} catch (err) {
|
|
1198
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1199
|
+
chatLog.addSystem(`Share failed: ${errorMessage}`);
|
|
1200
|
+
} finally {
|
|
1201
|
+
tui.requestRender();
|
|
1202
|
+
}
|
|
1203
|
+
};
|
|
1204
|
+
const runBtwQuery = async (question) => {
|
|
1205
|
+
const previousStatus = state.activityStatus;
|
|
1206
|
+
try {
|
|
1207
|
+
setActivityStatus("waiting");
|
|
1208
|
+
state.progressMessage = "btw";
|
|
1209
|
+
const result = await client.btwQuery(state.currentSessionKey, question);
|
|
1210
|
+
if (result.error) {
|
|
1211
|
+
chatLog.addSystem(`BTW failed: ${result.error}`);
|
|
1212
|
+
return;
|
|
1213
|
+
}
|
|
1214
|
+
chatLog.addSystem(`BTW\n\n${result.text}`);
|
|
1215
|
+
} catch (err) {
|
|
1216
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1217
|
+
chatLog.addSystem(`BTW failed: ${errorMessage}`);
|
|
1218
|
+
} finally {
|
|
1219
|
+
state.activityStatus = previousStatus;
|
|
1220
|
+
renderStatus();
|
|
1221
|
+
tui.requestRender();
|
|
1222
|
+
}
|
|
1223
|
+
};
|
|
1224
|
+
const forkCurrentSession = async (rawKey) => {
|
|
1225
|
+
const targetKey = resolveSessionKey(rawKey?.trim() || `fork-${randomUUID()}`);
|
|
1226
|
+
if (targetKey === state.currentSessionKey) {
|
|
1227
|
+
chatLog.addSystem("Fork target must be different from the current session.");
|
|
1228
|
+
tui.requestRender();
|
|
1229
|
+
return;
|
|
1230
|
+
}
|
|
1231
|
+
const sourceSessionKey = state.currentSessionKey;
|
|
1232
|
+
try {
|
|
1233
|
+
await abortActive({ clearUi: false });
|
|
1234
|
+
const result = await client.forkSession(sourceSessionKey, targetKey);
|
|
1235
|
+
await setSession(result.sessionKey);
|
|
1236
|
+
chatLog.addBranchSummary({
|
|
1237
|
+
sourceSessionKey,
|
|
1238
|
+
targetSessionKey: result.sessionKey,
|
|
1239
|
+
rowCount: result.rowCount
|
|
1240
|
+
});
|
|
1241
|
+
} catch (err) {
|
|
1242
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1243
|
+
chatLog.addSystem(`Fork failed: ${errorMessage}`);
|
|
1244
|
+
} finally {
|
|
1245
|
+
tui.requestRender();
|
|
1246
|
+
}
|
|
319
1247
|
};
|
|
320
1248
|
const handleCtrlZ = () => {
|
|
321
1249
|
if (process.platform === "win32") {
|
|
322
|
-
chatLog.addSystem(
|
|
1250
|
+
chatLog.addSystem(formatSuspendUnsupportedHint(keybindings));
|
|
323
1251
|
tui.requestRender();
|
|
324
1252
|
return;
|
|
325
1253
|
}
|
|
@@ -361,7 +1289,8 @@ async function runTui(opts) {
|
|
|
361
1289
|
})();
|
|
362
1290
|
};
|
|
363
1291
|
const isAgentBusy = () => state.activeRunId != null || state.isCompacting || busyStates.has(state.activityStatus);
|
|
364
|
-
|
|
1292
|
+
let steeringInFlightForRunId = null;
|
|
1293
|
+
const sendSteeringToActiveRun = (text) => {
|
|
365
1294
|
chatLog.addUser(text);
|
|
366
1295
|
touchStreamingActivity();
|
|
367
1296
|
tui.requestRender();
|
|
@@ -369,7 +1298,7 @@ async function runTui(opts) {
|
|
|
369
1298
|
sessionKey: state.currentSessionKey,
|
|
370
1299
|
message: text
|
|
371
1300
|
}).then(({ ok }) => {
|
|
372
|
-
if (!ok) chatLog.addSystem(theme.dim(
|
|
1301
|
+
if (!ok) chatLog.addSystem(theme.dim(formatSteerUnavailableHint(keybindings)));
|
|
373
1302
|
else chatLog.addSystem(theme.dim("Steered — message injects at the next tool boundary (pi-style)."));
|
|
374
1303
|
tui.requestRender();
|
|
375
1304
|
}).catch((error) => {
|
|
@@ -378,52 +1307,117 @@ async function runTui(opts) {
|
|
|
378
1307
|
tui.requestRender();
|
|
379
1308
|
});
|
|
380
1309
|
};
|
|
1310
|
+
const flushSteeringQueue = () => {
|
|
1311
|
+
if (state.exitRequested) return;
|
|
1312
|
+
if (state.activeRunId) return;
|
|
1313
|
+
const next = drainFollowUpQueue(state.steeringQueue, tuiSettings.steeringMode);
|
|
1314
|
+
if (next === void 0) return;
|
|
1315
|
+
sendMessage(next);
|
|
1316
|
+
};
|
|
1317
|
+
const steerMessage = (text) => {
|
|
1318
|
+
if (!state.activeRunId) {
|
|
1319
|
+
sendMessage(text);
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
if (steeringInFlightForRunId === state.activeRunId) {
|
|
1323
|
+
state.steeringQueue.push(text);
|
|
1324
|
+
chatLog.addSystem(theme.dim(`Queued steering (${state.steeringQueue.length} in queue). ${tuiSettings.steeringMode === "all" ? "All queued steering sends together after this reply." : "Next sends after this reply."}`));
|
|
1325
|
+
bottomBar.invalidate();
|
|
1326
|
+
tui.requestRender();
|
|
1327
|
+
return;
|
|
1328
|
+
}
|
|
1329
|
+
steeringInFlightForRunId = state.activeRunId;
|
|
1330
|
+
sendSteeringToActiveRun(text);
|
|
1331
|
+
};
|
|
381
1332
|
const sendMessage = (text) => {
|
|
1333
|
+
if (state.activeRunId && pendingImageAttachments.length > 0) {
|
|
1334
|
+
chatLog.addSystem(theme.dim("Image attachments cannot be steered into an active run. Wait for this reply to finish, then send."));
|
|
1335
|
+
tui.requestRender();
|
|
1336
|
+
return;
|
|
1337
|
+
}
|
|
1338
|
+
const pendingCustomText = pendingNextTurnCustomMessages.splice(0).join("\n\n").trim();
|
|
1339
|
+
const messageText = [text, pendingCustomText].filter(Boolean).join("\n\n");
|
|
1340
|
+
const attachments = pendingImageAttachments;
|
|
1341
|
+
pendingImageAttachments = [];
|
|
382
1342
|
if (state.isCompacting) {
|
|
383
|
-
state.compactionQueue.push(
|
|
1343
|
+
state.compactionQueue.push(messageText);
|
|
1344
|
+
if (attachments.length > 0) pendingImageAttachments.unshift(...attachments);
|
|
384
1345
|
chatLog.addSystem(theme.dim(`Queued during compaction (${state.compactionQueue.length}). Sends when compact finishes.`));
|
|
385
1346
|
bottomBar.invalidate();
|
|
386
1347
|
tui.requestRender();
|
|
387
1348
|
return;
|
|
388
1349
|
}
|
|
389
1350
|
if (state.activeRunId) {
|
|
390
|
-
chatLog.addSystem(
|
|
1351
|
+
chatLog.addSystem(formatBusyResponseHint(keybindings));
|
|
1352
|
+
if (pendingCustomText) pendingNextTurnCustomMessages.unshift(pendingCustomText);
|
|
1353
|
+
if (attachments.length > 0) pendingImageAttachments.unshift(...attachments);
|
|
391
1354
|
tui.requestRender();
|
|
392
1355
|
return;
|
|
393
1356
|
}
|
|
394
|
-
chatLog.addUser(text);
|
|
1357
|
+
chatLog.addUser(userDisplayContentForAttachments(text, attachments));
|
|
1358
|
+
sessionSnapshot.appendMessage("user", messageText);
|
|
1359
|
+
lastRetryMessageText = messageText;
|
|
1360
|
+
markRunSending(state);
|
|
395
1361
|
setActivityStatus("sending");
|
|
396
1362
|
touchStreamingActivity();
|
|
397
1363
|
tui.requestRender();
|
|
398
1364
|
client.sendChat({
|
|
399
1365
|
sessionKey: state.currentSessionKey,
|
|
400
|
-
message:
|
|
1366
|
+
message: messageText,
|
|
1367
|
+
attachments: attachments.length > 0 ? attachments : void 0,
|
|
401
1368
|
thinking: opts.thinking
|
|
402
1369
|
}).catch((error) => {
|
|
403
1370
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1371
|
+
if (attachments.length > 0) pendingImageAttachments.unshift(...attachments);
|
|
404
1372
|
chatLog.addSystem(`❌ Failed to send: ${errorMessage}`);
|
|
405
1373
|
setActivityStatus("idle");
|
|
406
1374
|
tui.requestRender();
|
|
407
1375
|
});
|
|
408
1376
|
};
|
|
409
|
-
|
|
410
|
-
|
|
1377
|
+
sendExtensionUserMessage = (content, options) => {
|
|
1378
|
+
const text = extensionUserMessageContentToText(content).trim();
|
|
1379
|
+
if (!text) throw new Error("sendUserMessage requires text content.");
|
|
1380
|
+
if (!state.activeRunId) {
|
|
1381
|
+
sendMessage(text);
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1384
|
+
if (options?.deliverAs === "steer") {
|
|
1385
|
+
steerMessage(text);
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
if (options?.deliverAs === "followUp") {
|
|
1389
|
+
state.messageFollowUpQueue.push(text);
|
|
1390
|
+
chatLog.addSystem(theme.dim(`Queued follow-up (${state.messageFollowUpQueue.length} in queue). ${tuiSettings.followUpMode === "all" ? "All queued messages send together when this reply finishes." : "Next sends when this reply finishes."}`));
|
|
1391
|
+
bottomBar.invalidate();
|
|
1392
|
+
tui.requestRender();
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
throw new Error("Agent is busy. Use deliverAs: \"steer\" or \"followUp\".");
|
|
1396
|
+
};
|
|
1397
|
+
const runCompaction = async (instructions, callbacks) => {
|
|
1398
|
+
if (state.isCompacting) return void 0;
|
|
411
1399
|
state.isCompacting = true;
|
|
412
1400
|
setActivityStatus("compacting");
|
|
413
|
-
chatLog.addSystem(theme.dim("Compacting session…"));
|
|
1401
|
+
chatLog.addSystem(theme.dim(instructions ? `Compacting session with instructions: ${instructions}` : "Compacting session…"));
|
|
414
1402
|
tui.requestRender();
|
|
415
1403
|
try {
|
|
416
|
-
const result = await client.compactSession(state.currentSessionKey, {
|
|
417
|
-
|
|
1404
|
+
const result = await client.compactSession(state.currentSessionKey, {
|
|
1405
|
+
force: true,
|
|
1406
|
+
instructions
|
|
1407
|
+
});
|
|
418
1408
|
if (result.compacted) {
|
|
419
|
-
|
|
420
|
-
clearPendingToolCallIds();
|
|
1409
|
+
clearSeenStreamEvents();
|
|
421
1410
|
state.historyLoaded = false;
|
|
422
1411
|
await loadSessionHistory();
|
|
423
|
-
|
|
1412
|
+
chatLog.addCompactionSummary(result);
|
|
1413
|
+
} else chatLog.addSystem(formatTuiCompactionResult(result));
|
|
1414
|
+
callbacks?.onComplete?.(result);
|
|
1415
|
+
return result;
|
|
424
1416
|
} catch (error) {
|
|
425
1417
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
426
1418
|
chatLog.addSystem(`❌ Compaction failed: ${errorMessage}`);
|
|
1419
|
+
callbacks?.onError?.(error instanceof Error ? error : new Error(errorMessage));
|
|
1420
|
+
return;
|
|
427
1421
|
} finally {
|
|
428
1422
|
state.isCompacting = false;
|
|
429
1423
|
setActivityStatus("idle");
|
|
@@ -439,7 +1433,21 @@ async function runTui(opts) {
|
|
|
439
1433
|
saveTuiSettings(tuiSettings);
|
|
440
1434
|
state.showThinking = tuiSettings.showThinking;
|
|
441
1435
|
state.toolsExpanded = tuiSettings.toolsExpanded;
|
|
1436
|
+
chatLog.setShowThinking(tuiSettings.showThinking);
|
|
442
1437
|
chatLog.setToolsExpanded(tuiSettings.toolsExpanded);
|
|
1438
|
+
chatLog.setToolImageOptions({
|
|
1439
|
+
showImages: tuiSettings.showImages,
|
|
1440
|
+
imageWidthCells: tuiSettings.imageWidthCells,
|
|
1441
|
+
cwd: process.cwd()
|
|
1442
|
+
});
|
|
1443
|
+
tui.setShowHardwareCursor(tuiSettings.showHardwareCursor);
|
|
1444
|
+
tui.setClearOnShrink(tuiSettings.clearOnShrink);
|
|
1445
|
+
defaultEditor.setPaddingX(tuiSettings.editorPaddingX);
|
|
1446
|
+
defaultEditor.setAutocompleteMaxVisible(tuiSettings.autocompleteMaxVisible);
|
|
1447
|
+
if (editor !== defaultEditor) {
|
|
1448
|
+
editor.setPaddingX?.(tuiSettings.editorPaddingX);
|
|
1449
|
+
editor.setAutocompleteMaxVisible?.(tuiSettings.autocompleteMaxVisible);
|
|
1450
|
+
}
|
|
443
1451
|
applyThemeById(tuiSettings.theme);
|
|
444
1452
|
header.invalidate();
|
|
445
1453
|
updateEditorBorderColor();
|
|
@@ -452,74 +1460,189 @@ async function runTui(opts) {
|
|
|
452
1460
|
updateEditorBorderColor();
|
|
453
1461
|
tui.requestRender();
|
|
454
1462
|
};
|
|
455
|
-
const
|
|
1463
|
+
const reloadTuiRuntime = async () => {
|
|
1464
|
+
if (state.activeRunId) throw new Error("Wait for the current response to finish before reloading.");
|
|
1465
|
+
if (state.isCompacting) throw new Error("Wait for compaction to finish before reloading.");
|
|
456
1466
|
keybindings.reload();
|
|
457
1467
|
setKeybindings(keybindings);
|
|
1468
|
+
applyTuiSettings(loadTuiSettings());
|
|
1469
|
+
extensionRuntime.dispose();
|
|
1470
|
+
await extensionRuntime.activate();
|
|
1471
|
+
editor.setAutocompleteProvider?.(extensionRuntime.autocompleteProvider);
|
|
1472
|
+
setEditorExtensionShortcut();
|
|
1473
|
+
updateHeader();
|
|
1474
|
+
updateFooter();
|
|
458
1475
|
tui.requestRender();
|
|
459
1476
|
};
|
|
460
1477
|
const uiOverlays = {
|
|
1478
|
+
openModelPicker: (_initialSearch) => {},
|
|
1479
|
+
openAgentPicker: () => {},
|
|
461
1480
|
openSessionPicker: () => {},
|
|
1481
|
+
openSessionTree: () => {},
|
|
1482
|
+
openTranscriptTree: () => {},
|
|
1483
|
+
openUserMessageFork: () => {},
|
|
462
1484
|
openScopedModels: () => {},
|
|
1485
|
+
openThinkingSelector: () => {},
|
|
463
1486
|
openSettings: () => {},
|
|
464
|
-
|
|
1487
|
+
openProjectTrust: () => {},
|
|
1488
|
+
reloadKeybindings: () => reloadTuiRuntime()
|
|
1489
|
+
};
|
|
1490
|
+
const recoverCurrentStream = async () => {
|
|
1491
|
+
if (state.activeRunId) {
|
|
1492
|
+
await recoverActiveRunFromHistory("manual recover");
|
|
1493
|
+
return;
|
|
1494
|
+
}
|
|
1495
|
+
await loadSessionHistory({ merge: true });
|
|
1496
|
+
await refreshSessionInfoWithBorder();
|
|
1497
|
+
chatLog.addSystem(theme.dim("Reloaded persisted history; no active run to recover."));
|
|
1498
|
+
tui.requestRender();
|
|
1499
|
+
};
|
|
1500
|
+
const retryLastMessage = async () => {
|
|
1501
|
+
const message = lastRetryMessageText?.trim();
|
|
1502
|
+
if (!message) {
|
|
1503
|
+
chatLog.addSystem("No previous user message to retry.");
|
|
1504
|
+
return;
|
|
1505
|
+
}
|
|
1506
|
+
if (state.activeRunId) await abortActive({ clearUi: false });
|
|
1507
|
+
sendMessage(message);
|
|
1508
|
+
};
|
|
1509
|
+
const switchAgentSession = async (sessionKey, agentId) => {
|
|
1510
|
+
const previousWorkspace = state.sessionInfo.effectiveWorkspacePath?.trim();
|
|
1511
|
+
await setSession(sessionKey);
|
|
1512
|
+
await refreshStartupResources();
|
|
1513
|
+
if (previousWorkspace && state.sessionInfo.workingDirectoryLocked !== true) try {
|
|
1514
|
+
await client.patchSession(state.currentSessionKey, { workingDirectory: previousWorkspace });
|
|
1515
|
+
state.sessionInfo.effectiveWorkspacePath = previousWorkspace;
|
|
1516
|
+
state.sessionInfo.workingDirectoryLocked = true;
|
|
1517
|
+
await refreshSessionInfoWithBorder();
|
|
1518
|
+
} catch (err) {
|
|
1519
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1520
|
+
chatLog.addSystem(`Switched agent, but workspace was not copied: ${errorMessage}`);
|
|
1521
|
+
}
|
|
1522
|
+
currentAgentId = agentId;
|
|
1523
|
+
updateHeader();
|
|
1524
|
+
updateFooter();
|
|
465
1525
|
};
|
|
466
1526
|
const handleCommand = createTuiCommandHandler({
|
|
467
1527
|
state,
|
|
468
1528
|
chatLog,
|
|
469
1529
|
tui,
|
|
470
|
-
assembler,
|
|
471
1530
|
isLocalMode,
|
|
472
1531
|
abortActive,
|
|
473
1532
|
sendMessage,
|
|
474
1533
|
requestExit,
|
|
475
1534
|
updateFooter,
|
|
476
1535
|
keybindings,
|
|
1536
|
+
recoverStream: recoverCurrentStream,
|
|
1537
|
+
retryLastMessage,
|
|
477
1538
|
uiOverlays,
|
|
1539
|
+
setThinkingLevel,
|
|
1540
|
+
setReasoningLevel,
|
|
1541
|
+
setVerboseLevel,
|
|
1542
|
+
copyLastAssistant,
|
|
1543
|
+
renameCurrentSession,
|
|
478
1544
|
runCompaction,
|
|
1545
|
+
listModels: listCurrentModels,
|
|
1546
|
+
switchModel: switchCurrentModel,
|
|
1547
|
+
listSessions: () => client.listSessions(),
|
|
1548
|
+
listAgents: () => client.listAgents(),
|
|
1549
|
+
switchAgentSession,
|
|
1550
|
+
getSessionStats: () => client.getSessionStats(state.currentSessionKey),
|
|
1551
|
+
getStartupResources: () => startupResources,
|
|
1552
|
+
loadTranscriptTree: () => client.loadTranscriptTree(state.currentSessionKey),
|
|
1553
|
+
exportSession: exportCurrentSession,
|
|
1554
|
+
importSession: importSessionExport,
|
|
1555
|
+
createShare: createShareLink,
|
|
1556
|
+
runBtwQuery,
|
|
1557
|
+
forkSession: forkCurrentSession,
|
|
479
1558
|
extensionSlashCommands: extensionRuntime.slashCommands,
|
|
1559
|
+
extensionShortcuts: extensionRuntime.shortcuts,
|
|
480
1560
|
currentAgentId,
|
|
481
|
-
setSession
|
|
482
|
-
|
|
1561
|
+
setSession: async (rawKey) => {
|
|
1562
|
+
await setSession(rawKey);
|
|
1563
|
+
await refreshStartupResources();
|
|
1564
|
+
},
|
|
1565
|
+
resetSession: resetCurrentSession,
|
|
1566
|
+
projectTrust: {
|
|
1567
|
+
cwd: process.cwd(),
|
|
1568
|
+
hasProjectResources: () => hasTrustRequiringProjectResources(process.cwd()),
|
|
1569
|
+
getStorePath: () => projectTrustStore.getPath(),
|
|
1570
|
+
getEntry: () => projectTrustStore.getEntry(process.cwd()),
|
|
1571
|
+
getSessionDecision: () => projectTrustSessionDecision
|
|
1572
|
+
},
|
|
1573
|
+
runLogin: (provider) => runTuiOAuthLogin(provider, {
|
|
1574
|
+
chatLog,
|
|
1575
|
+
tui,
|
|
1576
|
+
editor,
|
|
1577
|
+
openOverlay: openCommandOverlay,
|
|
1578
|
+
closeOverlay: closeCommandOverlay,
|
|
1579
|
+
keybindings
|
|
1580
|
+
})
|
|
483
1581
|
});
|
|
484
1582
|
const { runLocalShellLine } = createLocalShellRunner({
|
|
485
1583
|
chatLog,
|
|
486
1584
|
tui,
|
|
487
1585
|
editor,
|
|
488
|
-
openOverlay,
|
|
489
|
-
closeOverlay,
|
|
1586
|
+
openOverlay: openCommandOverlay,
|
|
1587
|
+
closeOverlay: closeCommandOverlay,
|
|
490
1588
|
pauseStdioFilter: () => stdioFilter.pause(),
|
|
491
1589
|
resumeStdioFilter: () => stdioFilter.resume(),
|
|
492
1590
|
runWithInheritedStdio: async (work) => {
|
|
493
1591
|
await withTuiSuspended(tui, work);
|
|
1592
|
+
},
|
|
1593
|
+
keybindings,
|
|
1594
|
+
getCwd: () => {
|
|
1595
|
+
const workspace = state.sessionInfo.effectiveWorkspacePath?.trim();
|
|
1596
|
+
if (!workspace) throw new Error("Workspace is not loaded yet.");
|
|
1597
|
+
return workspace;
|
|
1598
|
+
},
|
|
1599
|
+
onComplete: async (entry) => {
|
|
1600
|
+
await client.appendBashExecution(state.currentSessionKey, entry).catch((err) => {
|
|
1601
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1602
|
+
chatLog.addSystem(`Bash transcript append failed: ${errorMessage}`);
|
|
1603
|
+
}).finally(() => {
|
|
1604
|
+
updateFooter();
|
|
1605
|
+
tui.requestRender();
|
|
1606
|
+
});
|
|
494
1607
|
}
|
|
495
1608
|
});
|
|
496
1609
|
const submitBurst = createSubmitBurstCoalescer({
|
|
497
1610
|
submit: createEditorSubmitHandler({
|
|
498
|
-
editor
|
|
1611
|
+
editor: {
|
|
1612
|
+
setText: (value) => editor.setText(value),
|
|
1613
|
+
addToHistory: (value) => editor.addToHistory?.(value)
|
|
1614
|
+
},
|
|
499
1615
|
handleCommand,
|
|
500
1616
|
sendMessage,
|
|
501
1617
|
handleBangLine: runLocalShellLine,
|
|
502
1618
|
isAgentBusy,
|
|
503
|
-
steerWhileBusy: steerMessage
|
|
1619
|
+
steerWhileBusy: steerMessage,
|
|
1620
|
+
hasPendingAttachments: () => pendingImageAttachments.length > 0,
|
|
1621
|
+
defaultAttachmentMessage: "Please analyze the attached image."
|
|
504
1622
|
}),
|
|
505
1623
|
enabled: shouldEnableWindowsGitBashPasteFallback()
|
|
506
1624
|
});
|
|
507
|
-
|
|
1625
|
+
defaultEditor.onSubmit = submitBurst;
|
|
508
1626
|
const flushFollowUpQueue = () => {
|
|
509
1627
|
if (state.exitRequested) return;
|
|
510
1628
|
if (state.activeRunId) return;
|
|
511
|
-
const next = state.messageFollowUpQueue.
|
|
1629
|
+
const next = drainFollowUpQueue(state.messageFollowUpQueue, tuiSettings.followUpMode);
|
|
512
1630
|
if (next === void 0) return;
|
|
513
1631
|
sendMessage(next);
|
|
514
1632
|
};
|
|
515
1633
|
const handleFollowUp = () => {
|
|
516
1634
|
const text = editor.getText().trim();
|
|
517
|
-
if (!text) return;
|
|
1635
|
+
if (!text && pendingImageAttachments.length === 0) return;
|
|
518
1636
|
if (isAgentBusy()) {
|
|
1637
|
+
if (pendingImageAttachments.length > 0) {
|
|
1638
|
+
chatLog.addSystem(theme.dim("Image attachments cannot be queued while the agent is busy. Wait for this reply to finish, then send."));
|
|
1639
|
+
tui.requestRender();
|
|
1640
|
+
return;
|
|
1641
|
+
}
|
|
519
1642
|
editor.addToHistory(text);
|
|
520
1643
|
state.messageFollowUpQueue.push(text);
|
|
521
1644
|
editor.setText("");
|
|
522
|
-
chatLog.addSystem(theme.dim(`Queued follow-up (${state.messageFollowUpQueue.length} in queue). Next sends when this reply finishes
|
|
1645
|
+
chatLog.addSystem(theme.dim(`Queued follow-up (${state.messageFollowUpQueue.length} in queue). ${tuiSettings.followUpMode === "all" ? "All queued messages send together when this reply finishes." : "Next sends when this reply finishes."}`));
|
|
523
1646
|
bottomBar.invalidate();
|
|
524
1647
|
tui.requestRender();
|
|
525
1648
|
return;
|
|
@@ -527,17 +1650,17 @@ async function runTui(opts) {
|
|
|
527
1650
|
submitBurst(text);
|
|
528
1651
|
};
|
|
529
1652
|
const handleDequeue = () => {
|
|
530
|
-
|
|
531
|
-
|
|
1653
|
+
const restored = restoreQueuedMessages({
|
|
1654
|
+
steeringQueue: state.steeringQueue,
|
|
1655
|
+
followUpQueue: state.messageFollowUpQueue
|
|
1656
|
+
}, editor.getText());
|
|
1657
|
+
if (restored.restoredCount === 0) {
|
|
1658
|
+
chatLog.addStatus(theme.dim("No queued messages to restore."));
|
|
532
1659
|
tui.requestRender();
|
|
533
1660
|
return;
|
|
534
1661
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
const current = editor.getText().trim();
|
|
538
|
-
const combined = [queued.join("\n\n"), current].filter(Boolean).join("\n\n");
|
|
539
|
-
editor.setText(combined);
|
|
540
|
-
chatLog.addSystem(theme.dim(`Restored ${queued.length} queued message${queued.length > 1 ? "s" : ""} to editor.`));
|
|
1662
|
+
editor.setText(restored.text);
|
|
1663
|
+
chatLog.addStatus(theme.dim(`Restored ${restored.restoredCount} queued message${restored.restoredCount > 1 ? "s" : ""} to editor.`));
|
|
541
1664
|
bottomBar.invalidate();
|
|
542
1665
|
tui.requestRender();
|
|
543
1666
|
};
|
|
@@ -583,17 +1706,21 @@ async function runTui(opts) {
|
|
|
583
1706
|
const pickerSvc = {
|
|
584
1707
|
tui,
|
|
585
1708
|
editor,
|
|
586
|
-
openOverlay,
|
|
587
|
-
closeOverlay,
|
|
1709
|
+
openOverlay: openCommandOverlay,
|
|
1710
|
+
closeOverlay: closeCommandOverlay,
|
|
588
1711
|
chatLog,
|
|
589
1712
|
client,
|
|
590
1713
|
sendMessage,
|
|
1714
|
+
switchModel: switchCurrentModel,
|
|
1715
|
+
openEditorSelector,
|
|
591
1716
|
refreshSessionInfo,
|
|
592
1717
|
updateHeader,
|
|
593
1718
|
state,
|
|
594
1719
|
setSessionKey,
|
|
1720
|
+
switchAgentSession,
|
|
595
1721
|
clearChatForSessionSwitch,
|
|
596
1722
|
loadSessionHistory,
|
|
1723
|
+
setEditorText: (text) => editor.setText(text),
|
|
597
1724
|
setModelChoices,
|
|
598
1725
|
getScopedModelRefs: () => state.scopedModelRefs,
|
|
599
1726
|
setScopedModelRefs: (refs) => {
|
|
@@ -604,24 +1731,40 @@ async function runTui(opts) {
|
|
|
604
1731
|
getTuiSettings: () => ({ ...tuiSettings }),
|
|
605
1732
|
applyTuiSettings,
|
|
606
1733
|
previewTheme,
|
|
607
|
-
reloadKeybindings
|
|
1734
|
+
reloadKeybindings: reloadTuiRuntime,
|
|
1735
|
+
setThinkingLevel,
|
|
1736
|
+
getProjectTrustStore: () => projectTrustStore,
|
|
1737
|
+
getProjectTrustSessionDecision: () => projectTrustSessionDecision,
|
|
1738
|
+
setProjectTrustSessionDecision: (decision) => {
|
|
1739
|
+
projectTrustSessionDecision = decision;
|
|
1740
|
+
},
|
|
1741
|
+
keybindings
|
|
608
1742
|
};
|
|
1743
|
+
uiOverlays.openModelPicker = (initialSearch) => void openModelPickerOverlay(pickerSvc, initialSearch);
|
|
1744
|
+
uiOverlays.openAgentPicker = () => void openAgentPickerOverlay(pickerSvc);
|
|
609
1745
|
uiOverlays.openSessionPicker = () => void openSessionPickerOverlay(pickerSvc);
|
|
1746
|
+
uiOverlays.openSessionTree = () => void openSessionTreeOverlay(pickerSvc);
|
|
1747
|
+
uiOverlays.openTranscriptTree = () => void openTranscriptTreeOverlay(pickerSvc);
|
|
1748
|
+
uiOverlays.openUserMessageFork = () => void openUserMessageForkOverlay(pickerSvc);
|
|
610
1749
|
uiOverlays.openScopedModels = () => void openScopedModelsOverlay(pickerSvc);
|
|
1750
|
+
uiOverlays.openThinkingSelector = () => openThinkingSelectorOverlay(pickerSvc);
|
|
611
1751
|
uiOverlays.openSettings = () => openSettingsOverlay(pickerSvc);
|
|
1752
|
+
uiOverlays.openProjectTrust = () => openProjectTrustOverlay(pickerSvc);
|
|
1753
|
+
const showSessionTree = () => {
|
|
1754
|
+
uiOverlays.openTranscriptTree();
|
|
1755
|
+
};
|
|
612
1756
|
const handleDoubleEscape = () => {
|
|
613
1757
|
switch (tuiSettings.doubleEscapeAction) {
|
|
614
1758
|
case "tree":
|
|
615
|
-
|
|
1759
|
+
showSessionTree();
|
|
616
1760
|
break;
|
|
617
1761
|
case "fork":
|
|
618
|
-
|
|
1762
|
+
uiOverlays.openUserMessageFork();
|
|
619
1763
|
break;
|
|
620
1764
|
default: break;
|
|
621
1765
|
}
|
|
622
|
-
tui.requestRender();
|
|
623
1766
|
};
|
|
624
|
-
|
|
1767
|
+
defaultEditor.onEscape = () => {
|
|
625
1768
|
if (state.activeRunId) {
|
|
626
1769
|
abortActive();
|
|
627
1770
|
return;
|
|
@@ -635,19 +1778,20 @@ async function runTui(opts) {
|
|
|
635
1778
|
}
|
|
636
1779
|
state.lastEscapeAt = now;
|
|
637
1780
|
};
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
updateEditorBorderColor();
|
|
1781
|
+
defaultEditor.onCtrlD = () => requestExit();
|
|
1782
|
+
defaultEditor.onAction("app.clear", handleCtrlC);
|
|
1783
|
+
defaultEditor.onAction("app.exit", () => requestExit());
|
|
1784
|
+
defaultEditor.onAction("app.suspend", handleCtrlZ);
|
|
1785
|
+
defaultEditor.onAction("app.thinking.cycle", () => {
|
|
1786
|
+
setThinkingLevel(nextThinkLevel(state.sessionInfo.thinkingLevel ?? opts.thinking ?? "medium"));
|
|
645
1787
|
});
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
1788
|
+
defaultEditor.onAction("app.model.cycleForward", () => cycleModel("forward"));
|
|
1789
|
+
defaultEditor.onAction("app.model.cycleBackward", () => cycleModel("backward"));
|
|
1790
|
+
defaultEditor.onAction("app.model.select", () => uiOverlays.openModelPicker());
|
|
1791
|
+
defaultEditor.onAction("app.session.resume", () => void openSessionPickerOverlay(pickerSvc));
|
|
1792
|
+
defaultEditor.onAction("app.session.tree", showSessionTree);
|
|
1793
|
+
defaultEditor.onAction("app.session.fork", () => uiOverlays.openUserMessageFork());
|
|
1794
|
+
defaultEditor.onAction("app.tools.expand", () => {
|
|
651
1795
|
state.toolsExpanded = !state.toolsExpanded;
|
|
652
1796
|
tuiSettings = {
|
|
653
1797
|
...tuiSettings,
|
|
@@ -658,65 +1802,95 @@ async function runTui(opts) {
|
|
|
658
1802
|
setActivityStatus(state.toolsExpanded ? "tools expanded" : "tools collapsed");
|
|
659
1803
|
tui.requestRender();
|
|
660
1804
|
});
|
|
661
|
-
|
|
1805
|
+
defaultEditor.onAction("app.thinking.toggle", () => {
|
|
662
1806
|
state.showThinking = !state.showThinking;
|
|
663
1807
|
tuiSettings = {
|
|
664
1808
|
...tuiSettings,
|
|
665
1809
|
showThinking: state.showThinking
|
|
666
1810
|
};
|
|
667
1811
|
saveTuiSettings(tuiSettings);
|
|
1812
|
+
chatLog.setShowThinking(state.showThinking);
|
|
668
1813
|
updateFooter();
|
|
669
1814
|
tui.requestRender();
|
|
670
1815
|
});
|
|
671
|
-
|
|
672
|
-
|
|
1816
|
+
defaultEditor.onAction("app.editor.external", openExternalEditor);
|
|
1817
|
+
defaultEditor.onPasteImage = () => {
|
|
673
1818
|
(async () => {
|
|
674
|
-
const
|
|
675
|
-
if (!
|
|
676
|
-
|
|
677
|
-
|
|
1819
|
+
const image = await readClipboardImage();
|
|
1820
|
+
if (!image) {
|
|
1821
|
+
chatLog.addStatus(theme.dim("No image found on clipboard."));
|
|
1822
|
+
tui.requestRender();
|
|
1823
|
+
return;
|
|
1824
|
+
}
|
|
1825
|
+
if (pendingImageAttachments.length >= 10) {
|
|
1826
|
+
chatLog.addSystem(`Attachment limit reached (10). Send or clear the current draft first.`);
|
|
1827
|
+
tui.requestRender();
|
|
1828
|
+
return;
|
|
1829
|
+
}
|
|
1830
|
+
if (image.bytes.byteLength > 33554432) {
|
|
1831
|
+
chatLog.addSystem(`Clipboard image is too large (${image.bytes.byteLength} bytes; max ${MAX_WEBCHAT_ATTACHMENT_FILE_BYTES}).`);
|
|
1832
|
+
tui.requestRender();
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
const ext = extensionForImageMimeType(image.mimeType) ?? "png";
|
|
1836
|
+
const name = `clipboard-${pendingImageAttachments.length + 1}.${ext}`;
|
|
1837
|
+
pendingImageAttachments.push({
|
|
1838
|
+
type: "image",
|
|
1839
|
+
mimeType: image.mimeType,
|
|
1840
|
+
data: Buffer.from(image.bytes).toString("base64"),
|
|
1841
|
+
name,
|
|
1842
|
+
size: image.bytes.byteLength
|
|
1843
|
+
});
|
|
1844
|
+
chatLog.addStatus(theme.dim(`Attached image: ${name} (${pendingImageAttachments.length} pending). Send a message to include it.`));
|
|
678
1845
|
tui.requestRender();
|
|
679
1846
|
})();
|
|
680
1847
|
};
|
|
681
|
-
|
|
682
|
-
|
|
1848
|
+
defaultEditor.onAction("app.message.followUp", handleFollowUp);
|
|
1849
|
+
defaultEditor.onAction("app.message.dequeue", handleDequeue);
|
|
683
1850
|
streamWatchdogId = setInterval(() => {
|
|
684
|
-
|
|
685
|
-
if (!
|
|
686
|
-
if (
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
chatLog.addSystem("⚠️ No stream activity for 30s; UI reset (connection may have stalled). Retry or check gateway.");
|
|
691
|
-
state.activeRunId = null;
|
|
692
|
-
setActivityStatus("idle");
|
|
693
|
-
refreshSessionInfoWithBorder().finally(() => {
|
|
694
|
-
updateFooter();
|
|
695
|
-
tui.requestRender();
|
|
696
|
-
});
|
|
697
|
-
flushFollowUpQueue();
|
|
1851
|
+
const now = Date.now();
|
|
1852
|
+
if (!isActiveRunStreamStale(state, now, 3e4)) return;
|
|
1853
|
+
if (!markActiveRunStalled(state, now)) return;
|
|
1854
|
+
chatLog.addSystem(theme.dim("No stream activity for 30s; preserving active run and reloading persisted history."));
|
|
1855
|
+
setActivityStatus("stalled");
|
|
1856
|
+
recoverActiveRunFromHistory("stream watchdog");
|
|
698
1857
|
tui.requestRender();
|
|
699
1858
|
}, 5e3);
|
|
700
1859
|
const onAgentRunEnded = () => {
|
|
701
1860
|
state.progressMessage = null;
|
|
1861
|
+
steeringInFlightForRunId = null;
|
|
702
1862
|
refreshSessionInfoWithBorder().finally(() => {
|
|
703
1863
|
updateFooter();
|
|
704
1864
|
tui.requestRender();
|
|
705
1865
|
});
|
|
1866
|
+
flushSteeringQueue();
|
|
706
1867
|
flushFollowUpQueue();
|
|
707
1868
|
};
|
|
708
1869
|
client.onEvent = (evt) => {
|
|
709
1870
|
const data = evt.data ?? {};
|
|
710
|
-
|
|
1871
|
+
dispatchAgentEvent(evt.event, data, state, chatLog, tui, setActivityStatus, touchStreamingActivity, onAgentRunEnded, (message) => sessionSnapshot.appendMessage("assistant", assistantMessagePlainText(message)), evt.source);
|
|
711
1872
|
};
|
|
712
1873
|
client.onConnected = () => {
|
|
713
1874
|
state.isConnected = true;
|
|
714
1875
|
setConnectionStatus(isLocalMode ? "local ready" : "gateway connected");
|
|
715
1876
|
touchStreamingActivity();
|
|
716
1877
|
(async () => {
|
|
1878
|
+
try {
|
|
1879
|
+
await applyStartupWorkingDirectory();
|
|
1880
|
+
} catch (err) {
|
|
1881
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1882
|
+
chatLog.addSystem(`Working directory not changed: ${errorMessage}`);
|
|
1883
|
+
}
|
|
717
1884
|
await refreshSessionInfoWithBorder();
|
|
718
1885
|
await refreshModelChoices();
|
|
719
|
-
await
|
|
1886
|
+
await refreshStartupResources();
|
|
1887
|
+
await loadSessionHistory({ merge: true });
|
|
1888
|
+
showStartupCardOnce();
|
|
1889
|
+
if (state.activeRunId) recoverActiveRunFromHistory("broadcast reconnect");
|
|
1890
|
+
if (!projectTrustPromptShown && isLocalMode && projectTrustSessionDecision === null && hasTrustRequiringProjectResources(process.cwd()) && projectTrustStore.get(process.cwd()) === null) {
|
|
1891
|
+
projectTrustPromptShown = true;
|
|
1892
|
+
chatLog.addSystem("Project-local xopc resources detected. Use /trust to trust this folder, trust a parent folder, or keep it untrusted.");
|
|
1893
|
+
}
|
|
720
1894
|
updateHeader();
|
|
721
1895
|
updateFooter();
|
|
722
1896
|
tui.requestRender();
|
|
@@ -743,6 +1917,8 @@ async function runTui(opts) {
|
|
|
743
1917
|
client.onGap = (info) => {
|
|
744
1918
|
chatLog.addSystem(`⚠️ Event gap: expected ${info.expected}, received ${info.received}. Some updates may be missing.`);
|
|
745
1919
|
setConnectionStatus(`event gap: expected ${info.expected}, got ${info.received}`);
|
|
1920
|
+
if (state.activeRunId) recoverActiveRunFromHistory("broadcast event gap");
|
|
1921
|
+
else loadSessionHistory({ merge: true });
|
|
746
1922
|
tui.requestRender();
|
|
747
1923
|
};
|
|
748
1924
|
const sigintHandler = () => handleCtrlC();
|