@xopcai/xopc 0.0.113 → 0.0.115
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
- package/dist/extensions/feishu/src/workflow-progress.js +1 -1
- package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
- package/dist/extensions/telegram/src/inbound-processor.js +1 -1
- package/dist/extensions/telegram/src/plugin.js +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +2 -2
- package/dist/extensions/telegram/src/update-offset-store.js +1 -1
- package/dist/extensions/telegram/src/workflow-progress.js +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/api/api.js +2 -2
- package/dist/extensions/weixin/src/auth/accounts.js +1 -1
- package/dist/extensions/weixin/src/cdn/upload.js +1 -1
- package/dist/extensions/weixin/src/media/data-url.js +1 -1
- package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
- package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
- package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
- package/dist/extensions/weixin/src/plugin.js +1 -1
- package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
- package/dist/extensions/weixin/src/workflow-progress.js +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CBlklyNr.js → agent-avatar-dicebear-DVnBfANm.js} +1 -1
- package/dist/gateway/static/root/assets/agent-browser-settings-page-DPXc4hz8.js +6 -0
- package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-CTJ0YnRQ.js +1 -0
- package/dist/gateway/static/root/assets/agents-zJXQfJ_W.js +71 -0
- package/dist/gateway/static/root/assets/{app-management-settings-panel-28E_WfMe.js → app-management-settings-panel-DzGbdr04.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-Do1z0XgJ.js → appearance-settings-BQpPSTHD.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-CPjfyzSD.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-BAFlsov_.js → archive-plugin-CXu-Csep.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-V3qGPC3x.js → attachment-load-BAjgOoGY.js} +1 -1
- package/dist/gateway/static/root/assets/{binary-plugins-DT8NvA6W.js → binary-plugins-BSBgB2hO.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CdLMEcHd.js → block-editor-BpXw9TTR.js} +3 -3
- package/dist/gateway/static/root/assets/channels-settings-BbPUpzWB.js +1 -0
- package/dist/gateway/static/root/assets/{config-api-Bf5mjpu7.js → config-api-NOoPiIYz.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-settings-CAXYMOdp.js +2 -0
- package/dist/gateway/static/root/assets/{cron-api--pAB_rps.js → cron-api-C9BOqAXd.js} +1 -1
- package/dist/gateway/static/root/assets/cron-page-DuUbBeKI.js +3 -0
- package/dist/gateway/static/root/assets/{dreaming-settings-6UZE1FSK.js → dreaming-settings-DQ4DtiK1.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-BGhE7msg.js → extension-debug-page-D9kgUHCc.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CvpI45WG.js → extension-page-CGyhXqzR.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DAmR5FUe.js → extension-settings-page-DL8Xquqd.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-NZmjSXLl.js → fetch-D0VXA932.js} +1 -1
- package/dist/gateway/static/root/assets/{format-interval-label-qhth3BMV.js → format-interval-label-Be8SmgUw.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-CaXBt-9R.js → gateway-config-api-C-xjn__h.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-DphpbLBc.js → gateway-settings-BMPwIjKI.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-Be1omjh3.js → gateway-startup-retry-DERUH61L.js} +1 -1
- package/dist/gateway/static/root/assets/goal-detail-page-BJsyjJnF.js +1 -0
- package/dist/gateway/static/root/assets/goals-config-api-BPmqWk90.js +1 -0
- package/dist/gateway/static/root/assets/goals-page-BerDgIhw.js +2 -0
- package/dist/gateway/static/root/assets/goals-settings-ByTjeAto.js +1 -0
- package/dist/gateway/static/root/assets/{heartbeat-config-api-BzO6G4fD.js → heartbeat-config-api-Bfdzr8oV.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-DCST9-du.js → heartbeat-settings-TbHgcjTn.js} +1 -1
- package/dist/gateway/static/root/assets/index-AkTrf6Pb.js +122 -0
- package/dist/gateway/static/root/assets/index-fh5sXTj9.css +1 -0
- package/dist/gateway/static/root/assets/{interval-presets-DJmshV8n.js → interval-presets-utKbuCRY.js} +1 -1
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-9AUUlQ5Q.js → keyboard-shortcuts-settings-CjqS6c6V.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-DGXuPf5B.js +2 -0
- package/dist/gateway/static/root/assets/{markdown-split-CYYELqAr.js → markdown-split-DW8C47iB.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-BEcMR2M8.js → media-plugins-D6HwDhDT.js} +1 -1
- package/dist/gateway/static/root/assets/messages-upgxw6Ub.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-panel-Bot16nn7.js +2 -0
- package/dist/gateway/static/root/assets/note-detail-page-Brlyou8M.js +2 -0
- package/dist/gateway/static/root/assets/{note-image-lightbox-DNAoPcmm.js → note-image-lightbox-pJM35Pz5.js} +1 -1
- package/dist/gateway/static/root/assets/notes-page-DvZ4pwc-.js +1 -0
- package/dist/gateway/static/root/assets/{preview-open-alternatives-BPLz0AIv.js → preview-open-alternatives-CVwHuyN6.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-BZEDmxbZ.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-CrWwWRVK.js → save-bar-controls-Ba-UEk7x.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-CF2sadvN.js → schedule-field-CNN9595U.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-Di5cKjYE.js → schema-form-DnNMmtD5.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-DdGGlsfn.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-DlkEkPf9.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-Chh282jW.js → settings-collapsible-section-CmOz80i5.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-Dq-83cQd.js → settings-form-section-BmK7JJOV.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-DFPTrsPF.js +1 -0
- package/dist/gateway/static/root/assets/setup-status-panel-CYCCfgh4.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-0FXYnSUA.js → share-preview-page-Dp2qGrHC.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-Bff1pGd0.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-CJGKpBur.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-C6ocduTD.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-W1pTcojB.js → system-settings-panel-5jrIEr5b.js} +1 -1
- package/dist/gateway/static/root/assets/{use-agent-defaults-form-BVRvkK7m.js → use-agent-defaults-form-BuiXLIs5.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-CgJibfMM.js → use-channel-catalog-CHlO8J9G.js} +1 -1
- package/dist/gateway/static/root/assets/{use-settings-tab-guard-Bw_qkRQE.js → use-settings-tab-guard-CW5JORnl.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-DDoQyghO.js +1 -0
- package/dist/gateway/static/root/assets/{voice-player-store-C7lziaAx.js → voice-player-store-DDDWYHvg.js} +1 -1
- package/dist/gateway/static/root/assets/workflow-page.utils-CKjeEGqx.js +1 -0
- package/dist/gateway/static/root/assets/workflows-page-B604ehHG.js +18 -0
- package/dist/gateway/static/root/index.html +5 -5
- package/dist/gateway/static/root/logo.svg +4 -3
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +8 -0
- package/dist/src/agent/agent-manager.js +63 -28
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/agent-scope.js +1 -1
- package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
- package/dist/src/agent/bootstrap/project-agents-context.d.ts +2 -0
- package/dist/src/agent/bootstrap/project-agents-context.js +32 -0
- package/dist/src/agent/bootstrap/project-agents-context.js.map +1 -0
- package/dist/src/agent/context/workspace-seed.js +2 -2
- package/dist/src/agent/context/workspace-state.js +1 -1
- package/dist/src/agent/context/workspace.js +1 -1
- package/dist/src/agent/embedded/session-tool-result-guard.js +8 -1
- package/dist/src/agent/embedded/session-tool-result-guard.js.map +1 -1
- package/dist/src/agent/goals/checklist-judge.d.ts +1 -0
- package/dist/src/agent/goals/checklist-judge.js +3 -2
- package/dist/src/agent/goals/checklist-judge.js.map +1 -1
- package/dist/src/agent/goals/evaluate-turn.d.ts +1 -1
- package/dist/src/agent/goals/evaluate-turn.js +1 -0
- package/dist/src/agent/goals/evaluate-turn.js.map +1 -1
- package/dist/src/agent/goals/goal-locale.js +2 -2
- package/dist/src/agent/goals/persistent-goal-service.js +2 -4
- package/dist/src/agent/goals/persistent-goal-service.js.map +1 -1
- package/dist/src/agent/goals/post-turn.d.ts +6 -1
- package/dist/src/agent/goals/post-turn.js +15 -6
- package/dist/src/agent/goals/post-turn.js.map +1 -1
- package/dist/src/agent/image/load-image-media.js +2 -2
- package/dist/src/agent/inbound/inbound-loop.js +5 -1
- package/dist/src/agent/inbound/inbound-loop.js.map +1 -1
- package/dist/src/agent/inbound/turn-dispatcher.d.ts +2 -2
- package/dist/src/agent/inbound/turn-dispatcher.js +2 -2
- package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
- package/dist/src/agent/ipc/inbox.js +3 -3
- package/dist/src/agent/ipc/socket.js +1 -1
- package/dist/src/agent/mcp/bundle-mcp-materialize.d.ts +27 -0
- package/dist/src/agent/mcp/bundle-mcp-materialize.js +50 -2
- package/dist/src/agent/mcp/bundle-mcp-materialize.js.map +1 -1
- package/dist/src/agent/mcp/bundle-mcp-runtime.js +79 -4
- package/dist/src/agent/mcp/bundle-mcp-runtime.js.map +1 -1
- package/dist/src/agent/mcp/bundle-mcp-types.d.ts +19 -0
- package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
- package/dist/src/agent/mcp/mcp-transport.js +1 -1
- package/dist/src/agent/memory/builtin-memory-store.js +1 -1
- package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
- package/dist/src/agent/memory/dreaming/events.js +1 -1
- package/dist/src/agent/memory/dreaming/last-run.js +1 -1
- package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
- package/dist/src/agent/memory/dreaming/preview.js +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
- package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
- package/dist/src/agent/memory/dreaming/utils.js +1 -1
- package/dist/src/agent/memory/memory-flush.js +1 -1
- package/dist/src/agent/memory/plugin-discovery.js +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/prompt/memory/index.js +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
- package/dist/src/agent/reply/post-compaction-context.js +1 -1
- package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
- package/dist/src/agent/sandbox/path-policy.js +2 -2
- package/dist/src/agent/service/btw-query.js +11 -3
- package/dist/src/agent/service/btw-query.js.map +1 -1
- package/dist/src/agent/service/parse-outbound-session-key.js +13 -8
- package/dist/src/agent/service/parse-outbound-session-key.js.map +1 -1
- package/dist/src/agent/service/process-direct-one-shot.d.ts +2 -2
- package/dist/src/agent/service/process-direct-one-shot.js +1 -1
- package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
- package/dist/src/agent/service/process-direct-streaming.d.ts +2 -2
- package/dist/src/agent/service/process-direct-streaming.js +1 -1
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service.d.ts +1 -1
- package/dist/src/agent/service.js +13 -9
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/service.types.d.ts +5 -0
- package/dist/src/agent/session/session-inspector.js +1 -1
- package/dist/src/agent/skills/config.js +2 -2
- package/dist/src/agent/skills/filesystem-watcher.js +5 -4
- package/dist/src/agent/skills/filesystem-watcher.js.map +1 -1
- package/dist/src/agent/skills/hub-hash.js +2 -2
- package/dist/src/agent/skills/hub-lock.js +1 -1
- package/dist/src/agent/skills/hub-pull.js +2 -2
- package/dist/src/agent/skills/index.js +4 -3
- package/dist/src/agent/skills/index.js.map +1 -1
- package/dist/src/agent/skills/installer.js +2 -2
- package/dist/src/agent/skills/managed-store.js +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +3 -2
- package/dist/src/agent/skills/skill-manage-ops.js.map +1 -1
- package/dist/src/agent/skills/skill-manager.js +1 -1
- package/dist/src/agent/skills/skill-view-path.js +1 -1
- package/dist/src/agent/skills/test-framework.js +1 -1
- package/dist/src/agent/skills/types.d.ts +1 -1
- package/dist/src/agent/skills/watcher.js +2 -5
- package/dist/src/agent/skills/watcher.js.map +1 -1
- package/dist/src/agent/skills/workspace-skills-dir.d.ts +1 -0
- package/dist/src/agent/skills/workspace-skills-dir.js +11 -0
- package/dist/src/agent/skills/workspace-skills-dir.js.map +1 -0
- package/dist/src/agent/starter-agents.js +1 -1
- package/dist/src/agent/tool-manuals/browser.d.ts +1 -1
- package/dist/src/agent/tool-manuals/browser.js +62 -3
- package/dist/src/agent/tool-manuals/browser.js.map +1 -1
- package/dist/src/agent/tools/browser/tool/browser-use-tool.d.ts +4 -1
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js +13 -4
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js.map +1 -1
- package/dist/src/agent/tools/browser/tool/schemas.d.ts +0 -2
- package/dist/src/agent/tools/browser/tool/schemas.js +1 -2
- package/dist/src/agent/tools/browser/tool/schemas.js.map +1 -1
- package/dist/src/agent/tools/dreaming-tool.js +1 -1
- package/dist/src/agent/tools/factory.js +1 -10
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/find.js +1 -1
- package/dist/src/agent/tools/grep.js +1 -1
- package/dist/src/agent/tools/image-generate-tool.js +1 -1
- package/dist/src/agent/tools/skill-manage-tool.js +2 -2
- package/dist/src/agent/tools/skill-manage-tool.js.map +1 -1
- package/dist/src/agent/tools/workflow-tool.js +1 -1
- package/dist/src/agent/workflow/catalog.js +1 -1
- package/dist/src/agent/workflow/snapshot.d.ts +10 -0
- package/dist/src/agent/workflow/snapshot.js +136 -1
- package/dist/src/agent/workflow/snapshot.js.map +1 -1
- package/dist/src/agent/workflow/subagent-runner.js +18 -1
- package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
- package/dist/src/ai-assist/text-assist.js +1 -1
- package/dist/src/auth/credentials.js +2 -2
- package/dist/src/auth/profiles/store.js +2 -2
- package/dist/src/auth/sync-provider-auth.js +1 -1
- package/dist/src/browser/actions/extension-registry-bridge.js +91 -7
- package/dist/src/browser/actions/extension-registry-bridge.js.map +1 -1
- package/dist/src/browser/actions/registry.js +383 -7
- package/dist/src/browser/actions/registry.js.map +1 -1
- package/dist/src/browser/actions/types.d.ts +11 -3
- package/dist/src/browser/cache-dir-policy.js +1 -1
- package/dist/src/browser/cdp-local-launcher.js +2 -2
- package/dist/src/browser/index.js +2 -2
- package/dist/src/browser/pipeline/output.d.ts +18 -16
- package/dist/src/browser/pipeline/output.js +28 -20
- package/dist/src/browser/pipeline/output.js.map +1 -1
- package/dist/src/browser/pipeline/runner.d.ts +7 -14
- package/dist/src/browser/pipeline/runner.js +349 -102
- package/dist/src/browser/pipeline/runner.js.map +1 -1
- package/dist/src/browser/pipeline/schema.d.ts +1 -0
- package/dist/src/browser/pipeline/schema.js +35 -58
- package/dist/src/browser/pipeline/schema.js.map +1 -1
- package/dist/src/browser/pipeline/source.d.ts +2 -0
- package/dist/src/browser/pipeline/source.js +10 -1
- package/dist/src/browser/pipeline/source.js.map +1 -1
- package/dist/src/browser/pipeline/template.d.ts +10 -2
- package/dist/src/browser/pipeline/template.js +50 -8
- package/dist/src/browser/pipeline/template.js.map +1 -1
- package/dist/src/browser/providers/browser-ext-install.js +4 -4
- package/dist/src/browser/providers/cloakbrowser.js +5 -5
- package/dist/src/browser/providers/playwright-doctor.js +1 -1
- package/dist/src/browser/stealth.js +1 -1
- package/dist/src/channels/catalog/channel-catalog-service.d.ts +2 -1
- package/dist/src/channels/catalog/channel-catalog-service.js +133 -16
- package/dist/src/channels/catalog/channel-catalog-service.js.map +1 -1
- package/dist/src/channels/catalog/channel-catalog-types.d.ts +13 -0
- package/dist/src/channels/outbound/persist-store.js +1 -1
- package/dist/src/channels/pairing/allow-from-file.js +1 -1
- package/dist/src/channels/pairing/pairing-store.js +2 -2
- package/dist/src/chat-commands/agent-edit.js +2 -2
- package/dist/src/chat-commands/builtins/config.js +5 -7
- package/dist/src/chat-commands/builtins/config.js.map +1 -1
- package/dist/src/chat-commands/context.d.ts +5 -0
- package/dist/src/chat-commands/context.js +18 -9
- package/dist/src/chat-commands/context.js.map +1 -1
- package/dist/src/chat-commands/index.d.ts +1 -1
- package/dist/src/chat-commands/index.js +2 -2
- package/dist/src/chat-commands/index.js.map +1 -1
- package/dist/src/chat-commands/processor.js +22 -21
- package/dist/src/chat-commands/processor.js.map +1 -1
- package/dist/src/chat-commands/session-key.d.ts +3 -15
- package/dist/src/chat-commands/session-key.js +3 -49
- package/dist/src/chat-commands/session-key.js.map +1 -1
- package/dist/src/chat-commands/types.d.ts +4 -0
- package/dist/src/cli/commands/browser-cli-helpers.js +11 -5
- package/dist/src/cli/commands/browser-cli-helpers.js.map +1 -1
- package/dist/src/cli/commands/config.js +1 -1
- package/dist/src/cli/commands/doctor/checks/channel-config.js +14 -1
- package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/doctor/checks/session-integrity.js +8 -8
- package/dist/src/cli/commands/doctor/checks/session-integrity.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
- package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
- package/dist/src/cli/commands/extension-create.js +1 -1
- package/dist/src/cli/commands/extension-dev.js +2 -2
- package/dist/src/cli/commands/extension-marketplace.js +2 -2
- package/dist/src/cli/commands/extension-pack.js +2 -2
- package/dist/src/cli/commands/extension.js +3 -3
- package/dist/src/cli/commands/gateway/logs.js +1 -1
- package/dist/src/cli/commands/image.js +1 -1
- package/dist/src/cli/commands/init.js +2 -2
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/skills-test.js +1 -1
- package/dist/src/cli/templates.js +1 -1
- package/dist/src/cli/utils/gateway-client.js +1 -1
- package/dist/src/cli/utils/init-workspace-core.js +2 -2
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/agent-typed-models.js +1 -1
- package/dist/src/config/gateway-bind.js +1 -1
- package/dist/src/config/index.js +7 -7
- package/dist/src/config/loader.js +4 -4
- package/dist/src/config/models-json.js +2 -2
- package/dist/src/config/paths-state.js +1 -1
- package/dist/src/config/paths.js +1 -1
- package/dist/src/config/profile.js +1 -1
- package/dist/src/config/reload.js +1 -1
- package/dist/src/config/rules.js +5 -0
- package/dist/src/config/rules.js.map +1 -1
- package/dist/src/config/schema.d.ts +8 -0
- package/dist/src/config/schema.js +7 -0
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/config/web-patch.d.ts +1 -0
- package/dist/src/config/web-patch.js +1 -0
- package/dist/src/config/web-patch.js.map +1 -1
- package/dist/src/config/workspace-path.js +1 -1
- package/dist/src/connectors/builtin-catalog.js +180 -1
- package/dist/src/connectors/builtin-catalog.js.map +1 -1
- package/dist/src/connectors/health.js +18 -9
- package/dist/src/connectors/health.js.map +1 -1
- package/dist/src/connectors/types.d.ts +19 -0
- package/dist/src/connectors/usage.js +12 -4
- package/dist/src/connectors/usage.js.map +1 -1
- package/dist/src/cron/executor.js +1 -1
- package/dist/src/cron/service.js +1 -1
- package/dist/src/daemon/constants.js +1 -1
- package/dist/src/daemon/install-plan.js +2 -2
- package/dist/src/daemon/launchd.js +2 -2
- package/dist/src/daemon/schtasks.js +2 -2
- package/dist/src/daemon/systemd.js +2 -2
- package/dist/src/extensions/bundle-mcp.js +1 -1
- package/dist/src/extensions/discover-extensions.js +2 -2
- package/dist/src/extensions/health.js +1 -1
- package/dist/src/extensions/install.js +2 -2
- package/dist/src/extensions/loader.js +2 -2
- package/dist/src/extensions/lockfile.js +3 -3
- package/dist/src/extensions/security.js +1 -1
- package/dist/src/extensions/types/tui.d.ts +2 -0
- package/dist/src/extensions/update.js +2 -2
- package/dist/src/gateway/agents-admin.js +2 -2
- package/dist/src/gateway/file-path-classifier.js +2 -2
- package/dist/src/gateway/heartbeat/service.js +13 -1
- package/dist/src/gateway/heartbeat/service.js.map +1 -1
- package/dist/src/gateway/hono/app.js +18 -5
- package/dist/src/gateway/hono/app.js.map +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +3 -1
- package/dist/src/gateway/hono/lib/config-payload.js +7 -4
- package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
- package/dist/src/gateway/hono/lib/extension-store.js +2 -2
- package/dist/src/gateway/hono/lib/static-ui.js +2 -2
- package/dist/src/gateway/hono/middleware/strict-rate-limit.d.ts +4 -0
- package/dist/src/gateway/hono/middleware/strict-rate-limit.js +19 -5
- package/dist/src/gateway/hono/middleware/strict-rate-limit.js.map +1 -1
- package/dist/src/gateway/hono/oauth-async.js +1 -1
- package/dist/src/gateway/hono/routes/agent-stream.js +6 -6
- package/dist/src/gateway/hono/routes/agent-stream.js.map +1 -1
- package/dist/src/gateway/hono/routes/agents.js +1 -1
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
- package/dist/src/gateway/hono/routes/channels.js +18 -14
- package/dist/src/gateway/hono/routes/channels.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/gateway.d.ts +1 -1
- package/dist/src/gateway/hono/routes/config-patch/gateway.js +6 -0
- package/dist/src/gateway/hono/routes/config-patch/gateway.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
- package/dist/src/gateway/hono/routes/deps.d.ts +1 -0
- package/dist/src/gateway/hono/routes/dreaming.js +1 -1
- package/dist/src/gateway/hono/routes/goals.js +16 -3
- package/dist/src/gateway/hono/routes/goals.js.map +1 -1
- package/dist/src/gateway/hono/routes/host-fs.js +2 -2
- package/dist/src/gateway/hono/routes/logs.js +1 -0
- package/dist/src/gateway/hono/routes/logs.js.map +1 -1
- package/dist/src/gateway/hono/routes/mcp.js +27 -8
- package/dist/src/gateway/hono/routes/mcp.js.map +1 -1
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/hono/routes/notes.js +14 -2
- package/dist/src/gateway/hono/routes/notes.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +62 -4
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/shares.js +1 -1
- package/dist/src/gateway/hono/routes/workflows.js +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +5 -68
- package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
- package/dist/src/gateway/hono/sse.d.ts +2 -2
- package/dist/src/gateway/hono/sse.js +7 -15
- package/dist/src/gateway/hono/sse.js.map +1 -1
- package/dist/src/gateway/lock.js +3 -3
- package/dist/src/gateway/ports.js +1 -1
- package/dist/src/gateway/rate-limit/buckets.d.ts +3 -0
- package/dist/src/gateway/rate-limit/buckets.js +12 -0
- package/dist/src/gateway/rate-limit/buckets.js.map +1 -1
- package/dist/src/gateway/resolve-webchat-session-key.d.ts +2 -6
- package/dist/src/gateway/resolve-webchat-session-key.js +5 -31
- package/dist/src/gateway/resolve-webchat-session-key.js.map +1 -1
- package/dist/src/gateway/service/agent-runner.d.ts +2 -3
- package/dist/src/gateway/service/agent-runner.js +9 -22
- package/dist/src/gateway/service/agent-runner.js.map +1 -1
- package/dist/src/gateway/service/config-coordinator.js +1 -1
- package/dist/src/gateway/service/marketplace-service.js +2 -2
- package/dist/src/gateway/service/run-gateway-agent.js +9 -7
- package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
- package/dist/src/gateway/service/sessions-api.d.ts +9 -0
- package/dist/src/gateway/service/sessions-api.js +11 -0
- package/dist/src/gateway/service/sessions-api.js.map +1 -1
- package/dist/src/gateway/service.d.ts +1 -1
- package/dist/src/gateway/service.js +23 -9
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/workspace-file-search.d.ts +9 -0
- package/dist/src/gateway/workspace-file-search.js +76 -0
- package/dist/src/gateway/workspace-file-search.js.map +1 -0
- package/dist/src/gateway/workspace-fs-file-list.js +1 -1
- package/dist/src/goals/goal-notifications.d.ts +2 -0
- package/dist/src/goals/goal-notifications.js +16 -11
- package/dist/src/goals/goal-notifications.js.map +1 -1
- package/dist/src/goals/goal-service.js +1 -6
- package/dist/src/goals/goal-service.js.map +1 -1
- package/dist/src/goals/goal-workflow-judge.js +2 -2
- package/dist/src/i18n/goals-bundle.js +1 -1
- package/dist/src/i18n/index.js +1 -1
- package/dist/src/i18n/share-tool-bundle.js +2 -2
- package/dist/src/infra/brew.js +1 -1
- package/dist/src/infra/package-json.js +1 -1
- package/dist/src/infra/package-update-steps.js +1 -1
- package/dist/src/infra/path-env.js +2 -2
- package/dist/src/infra/restart.js +1 -1
- package/dist/src/infra/stable-node-path.js +1 -1
- package/dist/src/infra/update-check.js +1 -1
- package/dist/src/infra/update-global.js +1 -1
- package/dist/src/infra/update-lock.js +2 -2
- package/dist/src/infra/update-restart.js +1 -1
- package/dist/src/infra/update-runner.js +1 -1
- package/dist/src/infra/update-startup.js +1 -1
- package/dist/src/infra/write-file-atomic.js +2 -2
- package/dist/src/media/store.js +1 -1
- package/dist/src/notes/agent-context.js +1 -1
- package/dist/src/notes/service.js +1 -1
- package/dist/src/notes/store.js +2 -2
- package/dist/src/project-trust/trust-store.js +4 -2
- package/dist/src/project-trust/trust-store.js.map +1 -1
- package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
- package/dist/src/providers/index.js +1 -1
- package/dist/src/providers/model-registry.js +4 -4
- package/dist/src/session/index.d.ts +1 -1
- package/dist/src/session/index.js +2 -2
- package/dist/src/session/init-session-turn.js +7 -10
- package/dist/src/session/init-session-turn.js.map +1 -1
- package/dist/src/session/manager.d.ts +5 -1
- package/dist/src/session/manager.js +5 -2
- package/dist/src/session/manager.js.map +1 -1
- package/dist/src/session/reset-type.d.ts +0 -2
- package/dist/src/session/reset-type.js +3 -9
- package/dist/src/session/reset-type.js.map +1 -1
- package/dist/src/session/resolve-session.js +10 -21
- package/dist/src/session/resolve-session.js.map +1 -1
- package/dist/src/session/session-title.js +2 -2
- package/dist/src/session/store.d.ts +11 -3
- package/dist/src/session/store.js +30 -14
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/session/types.d.ts +2 -4
- package/dist/src/session/types.js.map +1 -1
- package/dist/src/share/share-auto.js +2 -2
- package/dist/src/share/share-store.js +3 -3
- package/dist/src/share/share-thumbnail.js +2 -2
- package/dist/src/share/share-zip.js +1 -1
- package/dist/src/share/site-share-store.js +3 -3
- package/dist/src/share/site-static-serve.js +1 -1
- package/dist/src/storage/sqlite/connection.js +1 -1
- package/dist/src/storage/sqlite/index.d.ts +2 -2
- package/dist/src/storage/sqlite/index.js +3 -3
- package/dist/src/storage/sqlite/memory-index-repository.js +2 -2
- package/dist/src/storage/sqlite/migrations/010_session_id_identity.sql +30 -0
- package/dist/src/storage/sqlite/migrations/discover.js +1 -1
- package/dist/src/storage/sqlite/migrations/runner.d.ts +2 -2
- package/dist/src/storage/sqlite/migrations/runner.js +5 -5
- package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
- package/dist/src/storage/sqlite/migrations/runner.ts +2 -2
- package/dist/src/storage/sqlite/row-mappers.d.ts +4 -4
- package/dist/src/storage/sqlite/row-mappers.js +11 -14
- package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
- package/dist/src/storage/sqlite/schema.js +4 -4
- package/dist/src/storage/sqlite/schema.js.map +1 -1
- package/dist/src/storage/sqlite/schema.sql +37 -10
- package/dist/src/storage/sqlite/session-metadata.d.ts +2 -7
- package/dist/src/storage/sqlite/session-metadata.js +18 -72
- package/dist/src/storage/sqlite/session-metadata.js.map +1 -1
- package/dist/src/storage/sqlite/session-repository.d.ts +6 -5
- package/dist/src/storage/sqlite/session-repository.js +34 -40
- package/dist/src/storage/sqlite/session-repository.js.map +1 -1
- package/dist/src/storage/sqlite/transcript-repository.d.ts +2 -2
- package/dist/src/storage/sqlite/transcript-repository.js +52 -52
- package/dist/src/storage/sqlite/transcript-repository.js.map +1 -1
- package/dist/src/tui/backends/embedded-backend.d.ts +18 -4
- package/dist/src/tui/backends/embedded-backend.js +100 -1
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.d.ts +5 -1
- package/dist/src/tui/backends/gateway-sse-backend.js +45 -2
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/clipboard-image.js +3 -3
- package/dist/src/tui/components/chat-log.d.ts +2 -0
- package/dist/src/tui/components/chat-log.js +19 -0
- package/dist/src/tui/components/chat-log.js.map +1 -1
- package/dist/src/tui/extension-host/autocomplete.d.ts +3 -2
- package/dist/src/tui/extension-host/autocomplete.js +29 -12
- package/dist/src/tui/extension-host/autocomplete.js.map +1 -1
- package/dist/src/tui/extension-host/load-extensions.js +1 -1
- package/dist/src/tui/extension-host/runtime.d.ts +12 -0
- package/dist/src/tui/extension-host/runtime.js +6 -4
- package/dist/src/tui/extension-host/runtime.js.map +1 -1
- package/dist/src/tui/theme-manager.js +1 -1
- package/dist/src/tui/tui-backend.d.ts +23 -0
- package/dist/src/tui/tui-command-formatters.js +4 -4
- package/dist/src/tui/tui-commands.d.ts +16 -3
- package/dist/src/tui/tui-commands.js +134 -27
- package/dist/src/tui/tui-commands.js.map +1 -1
- package/dist/src/tui/tui-file-autocomplete.d.ts +5 -0
- package/dist/src/tui/tui-file-autocomplete.js +26 -0
- package/dist/src/tui/tui-file-autocomplete.js.map +1 -0
- package/dist/src/tui/tui-keybindings-file.js +1 -1
- package/dist/src/tui/tui-picker-overlay.js +1 -1
- package/dist/src/tui/tui-scoped-models.js +2 -2
- package/dist/src/tui/tui-settings.js +1 -1
- package/dist/src/tui/tui-startup-resources.js +1 -1
- package/dist/src/tui/tui-startup-text.js +1 -1
- package/dist/src/tui/tui-startup-text.js.map +1 -1
- package/dist/src/tui/tui.js +106 -17
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/tunnel/frpc-binary.js +4 -4
- package/dist/src/tunnel/frpc-config.js +1 -1
- package/dist/src/tunnel/frpc-extract.js +1 -1
- package/dist/src/tunnel/tunnel-state.js +1 -1
- package/dist/src/utils/logger/audit.js +1 -1
- package/dist/src/utils/logger/context.d.ts +2 -2
- package/dist/src/utils/logger/context.js +2 -1
- package/dist/src/utils/logger/context.js.map +1 -1
- package/dist/src/utils/logger/log-store.js +2 -1
- package/dist/src/utils/logger/log-store.js.map +1 -1
- package/dist/src/utils/logger/pino-record.js +3 -0
- package/dist/src/utils/logger/pino-record.js.map +1 -1
- package/dist/src/utils/logger/rotation.js +1 -1
- package/dist/src/utils/logger/streams.js +1 -1
- package/dist/src/utils/logger/types.d.ts +5 -0
- package/dist/src/utils/logger/types.js.map +1 -1
- package/dist/src/voice/tts/audio.js +1 -1
- package/dist/src/voice/tts/providers/edge-speech.js +2 -2
- package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
- package/dist/src/workflows/service/workflow-run-service.js +1 -1
- package/dist/src/workflows/service/workflow-session-bridge.js +13 -1
- package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
- package/dist/src/workflows/store/event-store.js +1 -1
- package/dist/src/workflows/store/run-store.js +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/agent-browser-settings-page-rGbKc2Hh.js +0 -6
- package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-CtwVbjOA.js +0 -1
- package/dist/gateway/static/root/assets/agents-CCBmGcwc.js +0 -71
- package/dist/gateway/static/root/assets/apps-page-xwCsJS15.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-C044DcYk.js +0 -1
- package/dist/gateway/static/root/assets/connectors-settings-8VEWUOTj.js +0 -2
- package/dist/gateway/static/root/assets/cron-page-DqmNGNOy.js +0 -3
- package/dist/gateway/static/root/assets/goal-detail-page-bv0VRDaf.js +0 -1
- package/dist/gateway/static/root/assets/goals-page-1Ywnt4Cb.js +0 -2
- package/dist/gateway/static/root/assets/goals-settings-ceEBjnfc.js +0 -1
- package/dist/gateway/static/root/assets/index-Cxm6xsps.js +0 -122
- package/dist/gateway/static/root/assets/index-b_R4tKqt.css +0 -1
- package/dist/gateway/static/root/assets/logs-page-B_wrxhee.js +0 -2
- package/dist/gateway/static/root/assets/messages-CkT-lcgP.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-panel-D0JDSbNu.js +0 -2
- package/dist/gateway/static/root/assets/note-detail-page-DpFV-EO6.js +0 -2
- package/dist/gateway/static/root/assets/notes-page-CdkjTch8.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-DSYVAi96.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-CenkcVjF.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-D9sva86V.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-DL35U0x0.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Ctwbp9Er.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-DIM3JNsr.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-DAlNaNzL.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-CLrHVzAt.js +0 -2
- package/dist/gateway/static/root/assets/voice-api-key-field-vYAO71Gn.js +0 -1
- package/dist/gateway/static/root/assets/workflow-page.utils-sgHjOXOm.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-DYyOTmFx.js +0 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-sse-backend.js","names":[],"sources":["../../../../src/tui/backends/gateway-sse-backend.ts"],"sourcesContent":["import { prependEnvelopeTimestamp } from '../../channels/envelope-timestamp.js';\nimport { parseModelRef } from '../../agent/models/selection.js';\nimport type { ExportFormat } from '../../session/types.js';\nimport type { TranscriptStoredRow } from '../../session/session-context-for-llm.js';\nimport { transcriptRowsToClientHistory } from '../../session/client-history.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { consumeSSEStream, parseSSEData } from '../sse-consumer.js';\nimport type {\n ChatSendOptions,\n HistoryMessage,\n TuiBackend,\n TuiCompactionResult,\n TuiEvent,\n TuiModelChoice,\n TuiShareRequest,\n TuiShareResult,\n TuiSessionStats,\n TuiSessionItem,\n TuiStartupResources,\n TuiTranscriptTreeEntry,\n TuiAgentInfo,\n} from '../tui-backend.js';\nimport type { SessionInfo } from '../tui-types.js';\nimport { computeTuiSessionStats } from '../tui-session-stats.js';\nimport { buildTuiTranscriptTree, transcriptTreeEntryIdToRowNumber } from '../tui-transcript-tree.js';\n\nconst log = createLogger('TUI:GatewaySSE');\n\ninterface GatewaySSEOptions {\n url: string;\n token?: string;\n}\n\nfunction normalizeGatewayModelChoice(model: TuiModelChoice): TuiModelChoice {\n const providerPrefix = `${model.provider}/`;\n const id = model.id.startsWith(providerPrefix)\n ? model.id.slice(providerPrefix.length)\n : model.id;\n return { ...model, id };\n}\n\n/** Fetch wrapper that adds auth headers. */\nasync function gatewayFetch(\n baseUrl: string,\n path: string,\n token: string | undefined,\n init?: RequestInit,\n): Promise<Response> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n ...(init?.headers as Record<string, string> | undefined),\n };\n return fetch(`${baseUrl}${path}`, { ...init, headers });\n}\n\n/**\n * TUI backend that communicates with a running xopc gateway via HTTP + SSE.\n *\n * - Agent streaming: `POST /api/agent` with `Accept: text/event-stream`\n * - Broadcast events: `GET /api/events` via long-lived SSE\n * - REST calls for sessions, models, etc.\n */\nexport class GatewaySseBackend implements TuiBackend {\n private readonly baseUrl: string;\n private readonly token: string | undefined;\n private eventAbort: AbortController | null = null;\n private chatAbort: AbortController | null = null;\n\n onEvent?: (evt: TuiEvent) => void;\n onConnected?: () => void;\n onDisconnected?: (reason: string) => void;\n onGap?: (info: { expected: number; received: number }) => void;\n\n constructor(opts: GatewaySSEOptions) {\n this.baseUrl = opts.url.replace(/\\/+$/, '');\n this.token = opts.token;\n }\n\n get connectionLabel(): string {\n return this.baseUrl;\n }\n\n start(): void {\n this.startEventStream();\n }\n\n stop(): void {\n this.eventAbort?.abort();\n this.eventAbort = null;\n this.chatAbort?.abort();\n this.chatAbort = null;\n }\n\n getActiveSignal(): AbortSignal | undefined {\n const signal = this.chatAbort?.signal;\n return signal && !signal.aborted ? signal : undefined;\n }\n\n // ── Agent chat (POST /api/agent → SSE response body) ──\n\n async sendChat(opts: ChatSendOptions): Promise<{ runId: string }> {\n this.chatAbort?.abort();\n this.chatAbort = new AbortController();\n const signal = this.chatAbort.signal;\n const runId = crypto.randomUUID();\n\n\n // Fire-and-forget: run the HTTP request + SSE consumption in background\n // so the TUI event loop stays responsive for keyboard input.\n void (async () => {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agent', this.token, {\n method: 'POST',\n headers: { Accept: 'text/event-stream' },\n body: JSON.stringify({\n // Prepend envelope timestamp for regular messages so the model knows\n // the current date/time. Skip for slash commands — parseSlashCommand\n // requires lines starting with '/'.\n message: opts.message.trimStart().startsWith('/')\n ? opts.message\n : prependEnvelopeTimestamp(opts.message),\n channel: 'webchat',\n sessionKey: opts.sessionKey,\n attachments: opts.attachments,\n thinking: opts.thinking,\n }),\n signal,\n });\n\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as { error?: { message?: string } };\n this.onEvent?.({\n event: 'error',\n data: {\n type: 'error',\n runId,\n sessionKey: opts.sessionKey,\n timestamp: Date.now(),\n payload: { code: 'GATEWAY_ERROR', message: body.error?.message ?? `Gateway error: ${res.status}` },\n },\n source: 'agent-response',\n });\n return;\n }\n\n const contentType = res.headers.get('Content-Type') ?? '';\n\n if (contentType.includes('text/event-stream') && res.body) {\n await consumeSSEStream(\n res.body,\n (sseEvent) => {\n if (signal.aborted) return;\n const data = parseSSEData<Record<string, unknown>>(sseEvent.data);\n if (!data) return;\n this.onEvent?.({ event: sseEvent.event, data, source: 'agent-response' });\n },\n signal,\n );\n } else {\n const json = (await res.json()) as { ok?: boolean; payload?: { content?: string } };\n if (json.ok && json.payload?.content) {\n const messageId = `msg_${runId}_1`;\n const base = { runId, sessionKey: opts.sessionKey, timestamp: Date.now() };\n this.onEvent?.({ event: 'run_start', data: { ...base, type: 'run_start', payload: { channel: 'webchat' } }, source: 'agent-response' });\n this.onEvent?.({ event: 'assistant_message_start', data: { ...base, type: 'assistant_message_start', payload: { messageId } }, source: 'agent-response' });\n this.onEvent?.({ event: 'assistant_delta', data: { ...base, type: 'assistant_delta', payload: { messageId, delta: json.payload.content } }, source: 'agent-response' });\n this.onEvent?.({ event: 'assistant_message_end', data: { ...base, type: 'assistant_message_end', payload: { messageId } }, source: 'agent-response' });\n this.onEvent?.({ event: 'run_end', data: { ...base, type: 'run_end', payload: { status: 'success' } }, source: 'agent-response' });\n }\n }\n } catch (error) {\n if (signal.aborted) return;\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.onEvent?.({\n event: 'error',\n data: { type: 'error', runId, sessionKey: opts.sessionKey, timestamp: Date.now(), payload: { code: 'NETWORK_ERROR', message: errorMessage } },\n source: 'agent-response',\n });\n }\n })();\n\n return { runId };\n }\n\n async resumeChat(opts: { sessionKey: string; runId: string }): Promise<{ ok: boolean; reason?: string }> {\n this.chatAbort?.abort();\n this.chatAbort = new AbortController();\n const signal = this.chatAbort.signal;\n this.onEvent?.({\n event: 'run_start',\n data: { type: 'run_start', runId: opts.runId, sessionKey: opts.sessionKey, timestamp: Date.now(), payload: { channel: 'webchat' } },\n source: 'agent-resume',\n });\n\n let res: Response;\n try {\n res = await gatewayFetch(this.baseUrl, '/api/agent/resume', this.token, {\n method: 'POST',\n headers: { Accept: 'text/event-stream' },\n body: JSON.stringify({ runId: opts.runId, chatId: opts.sessionKey }),\n signal,\n });\n } catch (error) {\n if (signal.aborted) return { ok: false, reason: 'resume aborted' };\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { ok: false, reason: errorMessage };\n }\n\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as { error?: { message?: string } };\n return { ok: false, reason: body.error?.message ?? `Resume failed: ${res.status}` };\n }\n\n const contentType = res.headers.get('Content-Type') ?? '';\n if (!contentType.includes('text/event-stream') || !res.body) {\n return { ok: false, reason: 'Resume endpoint did not return an SSE stream' };\n }\n\n void (async () => {\n try {\n await consumeSSEStream(\n res.body,\n (sseEvent) => {\n if (signal.aborted) return;\n const data = parseSSEData<Record<string, unknown>>(sseEvent.data);\n if (!data) return;\n this.onEvent?.({ event: sseEvent.event, data, source: 'agent-resume' });\n },\n signal,\n );\n } catch (error) {\n if (signal.aborted) return;\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.onEvent?.({\n event: 'error',\n data: { type: 'error', runId: opts.runId, sessionKey: opts.sessionKey, timestamp: Date.now(), payload: { code: 'NETWORK_ERROR', message: errorMessage } },\n source: 'agent-resume',\n });\n }\n })();\n\n return { ok: true };\n }\n\n async abortChat(opts: { sessionKey: string; runId: string }): Promise<{ ok: boolean }> {\n this.chatAbort?.abort();\n this.chatAbort = null;\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agent/abort', this.token, {\n method: 'POST',\n body: JSON.stringify({ runId: opts.runId }),\n });\n const json = (await res.json()) as { ok?: boolean };\n return { ok: json.ok ?? false };\n } catch {\n return { ok: false };\n }\n }\n\n async steerChat(opts: { sessionKey: string; message: string }): Promise<{ ok: boolean }> {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agent/steer', this.token, {\n method: 'POST',\n body: JSON.stringify({ chatId: opts.sessionKey, message: opts.message }),\n });\n if (!res.ok) return { ok: false };\n const json = (await res.json()) as { ok?: boolean };\n return { ok: json.ok === true };\n } catch {\n return { ok: false };\n }\n }\n\n // ── REST helpers ──\n\n async getStartupResources(sessionKey: string): Promise<TuiStartupResources> {\n const empty: TuiStartupResources = { context: [], skills: [], workflows: [], connectors: [] };\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/tui/startup-resources?sessionKey=${encodeURIComponent(sessionKey)}`,\n this.token,\n );\n if (!res.ok) return empty;\n const json = (await res.json()) as { payload?: Partial<TuiStartupResources> };\n return {\n context: Array.isArray(json.payload?.context) ? json.payload.context : [],\n skills: Array.isArray(json.payload?.skills) ? json.payload.skills : [],\n workflows: Array.isArray(json.payload?.workflows) ? json.payload.workflows : [],\n connectors: Array.isArray(json.payload?.connectors) ? json.payload.connectors : [],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, sessionKey, errorMessage }, `Failed to load startup resources: ${errorMessage}`);\n return empty;\n }\n }\n\n async loadHistory(opts: {\n sessionKey: string;\n limit?: number;\n }): Promise<{ messages: HistoryMessage[] }> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(opts.sessionKey)}?include=transcriptRows`,\n this.token,\n );\n if (!res.ok) return { messages: [] };\n const json = (await res.json()) as {\n session?: { transcriptRows?: unknown[] };\n };\n const rows = Array.isArray(json.session?.transcriptRows)\n ? (json.session.transcriptRows as TranscriptStoredRow[])\n : [];\n return { messages: transcriptRowsToClientHistory(rows, { limit: opts.limit }) };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, errorMessage }, `Failed to load history: ${errorMessage}`);\n return { messages: [] };\n }\n }\n\n async loadTranscriptTree(sessionKey: string): Promise<TuiTranscriptTreeEntry[]> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}?include=transcriptRows`,\n this.token,\n );\n if (!res.ok) return [];\n const json = (await res.json()) as {\n session?: { transcriptRows?: unknown[] };\n };\n const rows = Array.isArray(json.session?.transcriptRows)\n ? (json.session.transcriptRows as TranscriptStoredRow[])\n : [];\n return buildTuiTranscriptTree(rows);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, sessionKey, errorMessage }, `Failed to load transcript tree: ${errorMessage}`);\n return [];\n }\n }\n\n async getSessionStats(sessionKey: string): Promise<TuiSessionStats> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}?include=transcriptRows`,\n this.token,\n );\n if (!res.ok) return computeTuiSessionStats([]);\n const json = (await res.json()) as {\n session?: { transcriptRows?: unknown[] };\n };\n const rows = Array.isArray(json.session?.transcriptRows)\n ? (json.session.transcriptRows as TranscriptStoredRow[])\n : [];\n return computeTuiSessionStats(rows);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, sessionKey, errorMessage }, `Failed to load session stats: ${errorMessage}`);\n return computeTuiSessionStats([]);\n }\n }\n\n async listSessions(): Promise<TuiSessionItem[]> {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/sessions', this.token);\n if (!res.ok) return [];\n const json = (await res.json()) as {\n items?: Array<{\n key: string;\n name?: string;\n updatedAt?: string;\n estimatedTokens?: number;\n messageCount?: number;\n customData?: Record<string, unknown>;\n cwd?: string;\n }>;\n };\n return (json.items ?? []).map((s) => ({\n key: s.key,\n displayName: s.name,\n updatedAt: s.updatedAt ? Date.parse(s.updatedAt) : undefined,\n totalTokens: s.estimatedTokens ?? null,\n messageCount: typeof s.messageCount === 'number' ? s.messageCount : undefined,\n model:\n typeof s.customData?.model === 'string'\n ? s.customData.model\n : typeof s.customData?.modelRef === 'string'\n ? s.customData.modelRef\n : null,\n forkedFromSessionKey:\n typeof s.customData?.forkedFromSessionKey === 'string'\n ? s.customData.forkedFromSessionKey\n : undefined,\n cwd: typeof s.cwd === 'string' ? s.cwd : undefined,\n }));\n } catch {\n return [];\n }\n }\n\n async listAgents(): Promise<TuiAgentInfo[]> {\n const agents = new Map<string, TuiAgentInfo>();\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agents', this.token);\n if (res.ok) {\n const json = (await res.json()) as {\n payload?: { agents?: Array<{ id?: unknown; name?: unknown }> };\n };\n for (const row of json.payload?.agents ?? []) {\n if (typeof row.id !== 'string' || !row.id.trim()) continue;\n const id = row.id.trim().toLowerCase();\n agents.set(id, {\n id,\n enabled: true,\n ...(typeof row.name === 'string' && row.name.trim()\n ? { displayName: row.name.trim() }\n : {}),\n });\n }\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, errorMessage }, `Failed to load agents: ${errorMessage}`);\n }\n return [...agents.values()].sort((a, b) => a.id.localeCompare(b.id));\n }\n\n async getSessionInfo(sessionKey: string): Promise<SessionInfo> {\n const out: SessionInfo = {};\n try {\n const sessionPath = `/api/sessions/${encodeURIComponent(sessionKey)}`;\n const [sessionRes, agentCfgRes] = await Promise.all([\n gatewayFetch(this.baseUrl, sessionPath, this.token),\n gatewayFetch(this.baseUrl, `${sessionPath}/agent-config`, this.token),\n ]);\n\n type SessionRow = {\n name?: string;\n estimatedTokens?: number;\n customData?: Record<string, unknown>;\n };\n let session: SessionRow | undefined;\n\n if (sessionRes.ok) {\n const json = (await sessionRes.json()) as { session?: SessionRow };\n session = json.session;\n if (session) {\n if (session.name) out.displayName = session.name;\n if (session.estimatedTokens != null) out.totalTokens = session.estimatedTokens;\n }\n }\n\n if (agentCfgRes.ok) {\n const json = (await agentCfgRes.json()) as {\n ok?: boolean;\n payload?: {\n model?: string;\n thinkingLevel?: string;\n reasoningLevel?: string;\n verboseLevel?: string;\n effectiveWorkspacePath?: string;\n workingDirectoryLocked?: boolean;\n };\n };\n const p = json.payload;\n if (p?.model && typeof p.model === 'string') {\n const parsed = parseModelRef(p.model);\n if (parsed) {\n out.model = parsed.model;\n out.modelProvider = parsed.provider;\n } else {\n out.model = p.model;\n }\n }\n if (p?.thinkingLevel && typeof p.thinkingLevel === 'string') {\n out.thinkingLevel = p.thinkingLevel;\n }\n if (p?.reasoningLevel && typeof p.reasoningLevel === 'string') {\n out.reasoningLevel = p.reasoningLevel;\n }\n if (p?.verboseLevel && typeof p.verboseLevel === 'string') {\n out.verboseLevel = p.verboseLevel;\n }\n if (p?.effectiveWorkspacePath && typeof p.effectiveWorkspacePath === 'string') {\n out.effectiveWorkspacePath = p.effectiveWorkspacePath;\n }\n if (typeof p?.workingDirectoryLocked === 'boolean') {\n out.workingDirectoryLocked = p.workingDirectoryLocked;\n }\n }\n\n if (!out.model && session?.customData) {\n const cd = session.customData;\n const ref =\n typeof cd.model === 'string'\n ? cd.model\n : typeof cd.modelRef === 'string'\n ? cd.modelRef\n : undefined;\n if (ref) {\n const parsed = parseModelRef(ref);\n if (parsed) {\n out.model = parsed.model;\n out.modelProvider = parsed.provider;\n } else {\n out.model = ref;\n }\n }\n if (!out.modelProvider && typeof cd.modelProvider === 'string') {\n out.modelProvider = cd.modelProvider;\n }\n }\n\n if (out.totalTokens != null) {\n const models = await this.listModels();\n const match = models.find(\n (m) =>\n m.id === out.model &&\n (!out.modelProvider || m.provider === out.modelProvider),\n );\n const contextWindow = match?.contextWindow ?? 128_000;\n out.contextWindow = contextWindow;\n out.contextUsagePercent =\n contextWindow > 0\n ? Math.min(100, Math.round((out.totalTokens / contextWindow) * 100))\n : null;\n }\n\n return out;\n } catch {\n return {};\n }\n }\n\n async listModels(): Promise<TuiModelChoice[]> {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/models', this.token);\n if (!res.ok) return [];\n const json = (await res.json()) as {\n ok?: boolean;\n payload?: { models?: TuiModelChoice[] };\n };\n return (json.payload?.models ?? []).map(normalizeGatewayModelChoice);\n } catch {\n return [];\n }\n }\n\n async resetSession(sessionKey: string): Promise<void> {\n await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/reset`,\n this.token,\n { method: 'POST' },\n ).catch(() => {});\n }\n\n async compactSession(\n sessionKey: string,\n options?: { force?: boolean; instructions?: string },\n ): Promise<TuiCompactionResult> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/compaction/run`,\n this.token,\n {\n method: 'POST',\n body: JSON.stringify({\n force: options?.force ?? true,\n instructions: options?.instructions,\n }),\n },\n );\n if (!res.ok) {\n return { compacted: false, summary: `Compaction failed (${res.status})` };\n }\n const json = (await res.json()) as {\n ok?: boolean;\n payload?: {\n result?: {\n compacted?: boolean;\n summary?: string;\n tokensBefore?: number;\n tokensAfter?: number;\n };\n };\n };\n const result = json.payload?.result;\n if (!result?.compacted) {\n return { compacted: false, summary: 'Nothing to compact' };\n }\n return {\n compacted: true,\n summary: `Compacted (${result.tokensBefore ?? '?'} → ${result.tokensAfter ?? '?'} tokens)`,\n tokensBefore: result.tokensBefore,\n tokensAfter: result.tokensAfter,\n transcriptSummary: result.summary,\n };\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n return { compacted: false, summary: errorMessage };\n }\n }\n\n async exportSession(sessionKey: string, format: ExportFormat): Promise<string> {\n const params = new URLSearchParams({ format });\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/export?${params.toString()}`,\n this.token,\n );\n if (!res.ok) {\n throw new Error(`Export failed (${res.status})`);\n }\n const json = (await res.json()) as { content?: string };\n return json.content ?? '';\n }\n\n async importSession(\n targetSessionKey: string,\n jsonContent: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n const res = await gatewayFetch(\n this.baseUrl,\n '/api/sessions/import',\n this.token,\n { method: 'POST', body: JSON.stringify({ targetKey: targetSessionKey, content: jsonContent }) },\n );\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: string;\n sessionKey?: string;\n rowCount?: number;\n };\n if (!res.ok || json.ok === false || !json.sessionKey) {\n throw new Error(json.error ?? `Import failed (${res.status})`);\n }\n return { sessionKey: json.sessionKey, rowCount: json.rowCount ?? 0 };\n }\n\n async createShare(\n sessionKey: string,\n request: TuiShareRequest,\n options?: { agentId?: string },\n ): Promise<TuiShareResult> {\n const res = await gatewayFetch(this.baseUrl, '/api/shares/auto', this.token, {\n method: 'POST',\n body: JSON.stringify({\n path: request.path,\n audience: request.audience,\n mode: request.mode,\n title: request.title,\n description: request.description,\n sessionKey,\n agentId: options?.agentId,\n }),\n });\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: { message?: string };\n payload?: {\n share?: {\n kind?: string;\n title?: string;\n description?: string;\n shareUrl?: string;\n reachability?: string;\n reachabilityHint?: string | null;\n expiresAt?: string;\n maxViews?: number | null;\n };\n thumbnail?: { url?: string };\n routing?: { reason?: string; hint?: string };\n };\n };\n if (!res.ok || json.ok === false || !json.payload?.share?.shareUrl) {\n throw new Error(json.error?.message ?? `Share failed (${res.status})`);\n }\n const share = json.payload.share;\n return {\n kind: share.kind ?? 'share',\n shareUrl: share.shareUrl,\n title: share.title,\n description: share.description,\n thumbnailUrl: json.payload.thumbnail?.url,\n reachability: share.reachability,\n reachabilityHint: share.reachabilityHint,\n expiresAt: share.expiresAt,\n maxViews: share.maxViews,\n routingReason: json.payload.routing?.reason,\n routingHint: json.payload.routing?.hint,\n };\n }\n\n async btwQuery(sessionKey: string, question: string): Promise<{ text: string; error?: string }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/btw`,\n this.token,\n { method: 'POST', body: JSON.stringify({ question }) },\n );\n if (!res.ok) {\n return { text: '', error: `BTW failed (${res.status})` };\n }\n return (await res.json()) as { text: string; error?: string };\n }\n\n async forkSession(\n sourceSessionKey: string,\n targetSessionKey: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sourceSessionKey)}/fork`,\n this.token,\n { method: 'POST', body: JSON.stringify({ targetKey: targetSessionKey }) },\n );\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: string;\n sessionKey?: string;\n rowCount?: number;\n };\n if (!res.ok || json.ok === false || !json.sessionKey) {\n throw new Error(json.error ?? `Fork failed (${res.status})`);\n }\n return { sessionKey: json.sessionKey, rowCount: json.rowCount ?? 0 };\n }\n\n async forkSessionAt(\n sourceSessionKey: string,\n targetSessionKey: string,\n entryId: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n const throughRow = transcriptTreeEntryIdToRowNumber(entryId);\n if (throughRow == null) {\n throw new Error(`Invalid transcript entry: ${entryId}`);\n }\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sourceSessionKey)}/fork-row`,\n this.token,\n { method: 'POST', body: JSON.stringify({ targetKey: targetSessionKey, throughRow }) },\n );\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: string;\n sessionKey?: string;\n rowCount?: number;\n };\n if (!res.ok || json.ok === false || !json.sessionKey) {\n throw new Error(json.error ?? `Fork failed (${res.status})`);\n }\n return { sessionKey: json.sessionKey, rowCount: json.rowCount ?? 0 };\n }\n\n async setTranscriptLabel(\n sessionKey: string,\n entryId: string,\n label: string | undefined,\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/label`,\n this.token,\n { method: 'POST', body: JSON.stringify({ targetId: entryId, label }) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Label update failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async appendCustomEntry(\n sessionKey: string,\n customType: string,\n data?: unknown,\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/custom`,\n this.token,\n { method: 'POST', body: JSON.stringify({ customType, data }) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Custom entry append failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async appendCustomMessage(\n sessionKey: string,\n message: {\n customType: string;\n content?: string | unknown[];\n display?: boolean;\n details?: unknown;\n },\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/custom-message`,\n this.token,\n { method: 'POST', body: JSON.stringify(message) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Custom message append failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async appendBashExecution(\n sessionKey: string,\n entry: {\n command: string;\n output?: string;\n exitCode?: number | null;\n signal?: string | null;\n excludeFromContext?: boolean;\n truncated?: boolean;\n fullOutputPath?: string;\n },\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/bash`,\n this.token,\n { method: 'POST', body: JSON.stringify(entry) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Bash execution append failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async patchSession(sessionKey: string, patch: Record<string, unknown>): Promise<void> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/agent-config`,\n this.token,\n { method: 'PATCH', body: JSON.stringify(patch) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Session config patch failed (${res.status})`);\n }\n }\n\n async renameSession(sessionKey: string, name: string): Promise<{ ok: boolean }> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/rename`,\n this.token,\n { method: 'POST', body: JSON.stringify({ name }) },\n );\n return { ok: res.ok };\n } catch {\n return { ok: false };\n }\n }\n\n async deleteSession(sessionKey: string): Promise<{ ok: boolean }> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}`,\n this.token,\n { method: 'DELETE' },\n );\n if (!res.ok) return { ok: false };\n const json = (await res.json()) as { deleted?: boolean };\n return { ok: json.deleted !== false };\n } catch {\n return { ok: false };\n }\n }\n\n // ── Broadcast SSE (GET /api/events) ──\n\n private startEventStream(): void {\n this.eventAbort?.abort();\n this.eventAbort = new AbortController();\n\n const url = new URL(`${this.baseUrl}/api/events`);\n if (this.token) url.searchParams.set('token', this.token);\n\n const connect = async () => {\n try {\n const res = await fetch(url.toString(), {\n signal: this.eventAbort!.signal,\n headers: { Accept: 'text/event-stream' },\n });\n\n if (!res.ok || !res.body) {\n this.onDisconnected?.(`event stream error: ${res.status}`);\n this.scheduleReconnect();\n return;\n }\n\n this.onConnected?.();\n\n await consumeSSEStream(\n res.body,\n (sseEvent) => {\n if (sseEvent.event === 'connected') return;\n if (sseEvent.event === 'gap') {\n const gapData = parseSSEData(sseEvent.data) as {\n expected?: unknown;\n received?: unknown;\n } | null;\n if (\n gapData &&\n typeof gapData.expected === 'number' &&\n typeof gapData.received === 'number'\n ) {\n this.onGap?.({ expected: gapData.expected, received: gapData.received });\n }\n return;\n }\n const data = parseSSEData(sseEvent.data);\n if (data !== null) {\n this.onEvent?.({ event: sseEvent.event, data, source: 'broadcast' });\n }\n },\n this.eventAbort!.signal,\n );\n\n // Stream ended normally\n if (!this.eventAbort?.signal.aborted) {\n this.onDisconnected?.('stream closed');\n this.scheduleReconnect();\n }\n } catch (error) {\n if (this.eventAbort?.signal.aborted) return;\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, errorMessage }, `Event stream failed: ${errorMessage}`);\n this.onDisconnected?.(errorMessage);\n this.scheduleReconnect();\n }\n };\n\n void connect();\n }\n\n private scheduleReconnect(): void {\n if (this.eventAbort?.signal.aborted) return;\n setTimeout(() => {\n if (!this.eventAbort?.signal.aborted) {\n this.startEventStream();\n }\n }, 3000);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"gateway-sse-backend.js","names":[],"sources":["../../../../src/tui/backends/gateway-sse-backend.ts"],"sourcesContent":["import { prependEnvelopeTimestamp } from '../../channels/envelope-timestamp.js';\nimport { parseModelRef } from '../../agent/models/selection.js';\nimport type { ExportFormat } from '../../session/types.js';\nimport type { TranscriptStoredRow } from '../../session/session-context-for-llm.js';\nimport { transcriptRowsToClientHistory } from '../../session/client-history.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { consumeSSEStream, parseSSEData } from '../sse-consumer.js';\nimport type {\n ChatSendOptions,\n HistoryMessage,\n TuiBackend,\n TuiCompactionResult,\n TuiEvent,\n TuiModelChoice,\n TuiShareRequest,\n TuiShareResult,\n TuiSessionStats,\n TuiSessionItem,\n TuiStartupResources,\n TuiTranscriptTreeEntry,\n TuiAgentInfo,\n TuiWorkspaceFileSearchEntry,\n TuiWorkflowRunStartRequest,\n TuiWorkflowRunStartResult,\n} from '../tui-backend.js';\nimport type { SessionInfo } from '../tui-types.js';\nimport { computeTuiSessionStats } from '../tui-session-stats.js';\nimport { buildTuiTranscriptTree, transcriptTreeEntryIdToRowNumber } from '../tui-transcript-tree.js';\n\nconst log = createLogger('TUI:GatewaySSE');\n\ninterface GatewaySSEOptions {\n url: string;\n token?: string;\n}\n\nfunction normalizeGatewayModelChoice(model: TuiModelChoice): TuiModelChoice {\n const providerPrefix = `${model.provider}/`;\n const id = model.id.startsWith(providerPrefix)\n ? model.id.slice(providerPrefix.length)\n : model.id;\n return { ...model, id };\n}\n\n/** Fetch wrapper that adds auth headers. */\nasync function gatewayFetch(\n baseUrl: string,\n path: string,\n token: string | undefined,\n init?: RequestInit,\n): Promise<Response> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n ...(init?.headers as Record<string, string> | undefined),\n };\n return fetch(`${baseUrl}${path}`, { ...init, headers });\n}\n\n/**\n * TUI backend that communicates with a running xopc gateway via HTTP + SSE.\n *\n * - Agent streaming: `POST /api/agent` with `Accept: text/event-stream`\n * - Broadcast events: `GET /api/events` via long-lived SSE\n * - REST calls for sessions, models, etc.\n */\nexport class GatewaySseBackend implements TuiBackend {\n private readonly baseUrl: string;\n private readonly token: string | undefined;\n private eventAbort: AbortController | null = null;\n private chatAbort: AbortController | null = null;\n\n onEvent?: (evt: TuiEvent) => void;\n onConnected?: () => void;\n onDisconnected?: (reason: string) => void;\n onGap?: (info: { expected: number; received: number }) => void;\n\n constructor(opts: GatewaySSEOptions) {\n this.baseUrl = opts.url.replace(/\\/+$/, '');\n this.token = opts.token;\n }\n\n get connectionLabel(): string {\n return this.baseUrl;\n }\n\n start(): void {\n this.startEventStream();\n }\n\n stop(): void {\n this.eventAbort?.abort();\n this.eventAbort = null;\n this.chatAbort?.abort();\n this.chatAbort = null;\n }\n\n getActiveSignal(): AbortSignal | undefined {\n const signal = this.chatAbort?.signal;\n return signal && !signal.aborted ? signal : undefined;\n }\n\n // ── Agent chat (POST /api/agent → SSE response body) ──\n\n async sendChat(opts: ChatSendOptions): Promise<{ runId: string }> {\n this.chatAbort?.abort();\n this.chatAbort = new AbortController();\n const signal = this.chatAbort.signal;\n const runId = crypto.randomUUID();\n\n\n // Fire-and-forget: run the HTTP request + SSE consumption in background\n // so the TUI event loop stays responsive for keyboard input.\n void (async () => {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agent', this.token, {\n method: 'POST',\n headers: { Accept: 'text/event-stream' },\n body: JSON.stringify({\n // Prepend envelope timestamp for regular messages so the model knows\n // the current date/time. Skip for slash commands — parseSlashCommand\n // requires lines starting with '/'.\n message: opts.message.trimStart().startsWith('/')\n ? opts.message\n : prependEnvelopeTimestamp(opts.message),\n channel: 'webchat',\n sessionKey: opts.sessionKey,\n attachments: opts.attachments,\n thinking: opts.thinking,\n }),\n signal,\n });\n\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as { error?: { message?: string } };\n this.onEvent?.({\n event: 'error',\n data: {\n type: 'error',\n runId,\n sessionKey: opts.sessionKey,\n timestamp: Date.now(),\n payload: { code: 'GATEWAY_ERROR', message: body.error?.message ?? `Gateway error: ${res.status}` },\n },\n source: 'agent-response',\n });\n return;\n }\n\n const contentType = res.headers.get('Content-Type') ?? '';\n\n if (contentType.includes('text/event-stream') && res.body) {\n await consumeSSEStream(\n res.body,\n (sseEvent) => {\n if (signal.aborted) return;\n const data = parseSSEData<Record<string, unknown>>(sseEvent.data);\n if (!data) return;\n this.onEvent?.({ event: sseEvent.event, data, source: 'agent-response' });\n },\n signal,\n );\n } else {\n const json = (await res.json()) as { ok?: boolean; payload?: { content?: string } };\n if (json.ok && json.payload?.content) {\n const messageId = `msg_${runId}_1`;\n const base = { runId, sessionKey: opts.sessionKey, timestamp: Date.now() };\n this.onEvent?.({ event: 'run_start', data: { ...base, type: 'run_start', payload: { channel: 'webchat' } }, source: 'agent-response' });\n this.onEvent?.({ event: 'assistant_message_start', data: { ...base, type: 'assistant_message_start', payload: { messageId } }, source: 'agent-response' });\n this.onEvent?.({ event: 'assistant_delta', data: { ...base, type: 'assistant_delta', payload: { messageId, delta: json.payload.content } }, source: 'agent-response' });\n this.onEvent?.({ event: 'assistant_message_end', data: { ...base, type: 'assistant_message_end', payload: { messageId } }, source: 'agent-response' });\n this.onEvent?.({ event: 'run_end', data: { ...base, type: 'run_end', payload: { status: 'success' } }, source: 'agent-response' });\n }\n }\n } catch (error) {\n if (signal.aborted) return;\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.onEvent?.({\n event: 'error',\n data: { type: 'error', runId, sessionKey: opts.sessionKey, timestamp: Date.now(), payload: { code: 'NETWORK_ERROR', message: errorMessage } },\n source: 'agent-response',\n });\n }\n })();\n\n return { runId };\n }\n\n async searchWorkspaceFiles(\n sessionKey: string,\n query: string,\n options?: { limit?: number },\n ): Promise<TuiWorkspaceFileSearchEntry[]> {\n try {\n const params = new URLSearchParams();\n params.set('q', query);\n params.set('limit', String(options?.limit ?? 15));\n params.set('sessionKey', sessionKey);\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/workspace/editor/files/search?${params.toString()}`,\n this.token,\n );\n if (!res.ok) return [];\n const json = (await res.json()) as {\n ok?: boolean;\n payload?: { entries?: TuiWorkspaceFileSearchEntry[] };\n };\n return json.payload?.entries ?? [];\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n log.warn({ err, sessionKey, errorMessage }, `Gateway workspace file search failed: ${errorMessage}`);\n return [];\n }\n }\n\n async startWorkflowRun(opts: TuiWorkflowRunStartRequest): Promise<TuiWorkflowRunStartResult> {\n const goal = opts.goal?.trim();\n const res = await gatewayFetch(this.baseUrl, '/api/workflows/runs', this.token, {\n method: 'POST',\n body: JSON.stringify({\n definitionId: opts.definitionId,\n agentId: opts.agentId,\n parentSessionKey: opts.sessionKey,\n source: { kind: 'chat', sessionKey: opts.sessionKey },\n ...(goal ? { goal } : {}),\n ...(opts.input !== undefined ? { input: opts.input } : {}),\n }),\n });\n const json = (await res.json().catch(() => ({}))) as {\n runId?: string;\n sessionKey?: string;\n error?: string;\n code?: string;\n };\n if (!res.ok || !json.runId || !json.sessionKey) {\n throw new Error(json.error ?? `Workflow start failed (${res.status})`);\n }\n return {\n runId: json.runId,\n sessionKey: json.sessionKey,\n definitionId: opts.definitionId,\n };\n }\n\n async resumeChat(opts: { sessionKey: string; runId: string }): Promise<{ ok: boolean; reason?: string }> {\n this.chatAbort?.abort();\n this.chatAbort = new AbortController();\n const signal = this.chatAbort.signal;\n this.onEvent?.({\n event: 'run_start',\n data: { type: 'run_start', runId: opts.runId, sessionKey: opts.sessionKey, timestamp: Date.now(), payload: { channel: 'webchat' } },\n source: 'agent-resume',\n });\n\n let res: Response;\n try {\n res = await gatewayFetch(this.baseUrl, '/api/agent/resume', this.token, {\n method: 'POST',\n headers: { Accept: 'text/event-stream' },\n body: JSON.stringify({ runId: opts.runId, sessionKey: opts.sessionKey }),\n signal,\n });\n } catch (error) {\n if (signal.aborted) return { ok: false, reason: 'resume aborted' };\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { ok: false, reason: errorMessage };\n }\n\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as { error?: { message?: string } };\n return { ok: false, reason: body.error?.message ?? `Resume failed: ${res.status}` };\n }\n\n const contentType = res.headers.get('Content-Type') ?? '';\n if (!contentType.includes('text/event-stream') || !res.body) {\n return { ok: false, reason: 'Resume endpoint did not return an SSE stream' };\n }\n\n void (async () => {\n try {\n await consumeSSEStream(\n res.body,\n (sseEvent) => {\n if (signal.aborted) return;\n const data = parseSSEData<Record<string, unknown>>(sseEvent.data);\n if (!data) return;\n this.onEvent?.({ event: sseEvent.event, data, source: 'agent-resume' });\n },\n signal,\n );\n } catch (error) {\n if (signal.aborted) return;\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.onEvent?.({\n event: 'error',\n data: { type: 'error', runId: opts.runId, sessionKey: opts.sessionKey, timestamp: Date.now(), payload: { code: 'NETWORK_ERROR', message: errorMessage } },\n source: 'agent-resume',\n });\n }\n })();\n\n return { ok: true };\n }\n\n async abortChat(opts: { sessionKey: string; runId: string }): Promise<{ ok: boolean }> {\n this.chatAbort?.abort();\n this.chatAbort = null;\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agent/abort', this.token, {\n method: 'POST',\n body: JSON.stringify({ runId: opts.runId }),\n });\n const json = (await res.json()) as { ok?: boolean };\n return { ok: json.ok ?? false };\n } catch {\n return { ok: false };\n }\n }\n\n async steerChat(opts: { sessionKey: string; message: string }): Promise<{ ok: boolean }> {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agent/steer', this.token, {\n method: 'POST',\n body: JSON.stringify({ sessionKey: opts.sessionKey, message: opts.message }),\n });\n if (!res.ok) return { ok: false };\n const json = (await res.json()) as { ok?: boolean };\n return { ok: json.ok === true };\n } catch {\n return { ok: false };\n }\n }\n\n // ── REST helpers ──\n\n async getStartupResources(sessionKey: string): Promise<TuiStartupResources> {\n const empty: TuiStartupResources = { context: [], skills: [], workflows: [], connectors: [] };\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/tui/startup-resources?sessionKey=${encodeURIComponent(sessionKey)}`,\n this.token,\n );\n if (!res.ok) return empty;\n const json = (await res.json()) as { payload?: Partial<TuiStartupResources> };\n return {\n context: Array.isArray(json.payload?.context) ? json.payload.context : [],\n skills: Array.isArray(json.payload?.skills) ? json.payload.skills : [],\n workflows: Array.isArray(json.payload?.workflows) ? json.payload.workflows : [],\n connectors: Array.isArray(json.payload?.connectors) ? json.payload.connectors : [],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, sessionKey, errorMessage }, `Failed to load startup resources: ${errorMessage}`);\n return empty;\n }\n }\n\n async loadHistory(opts: {\n sessionKey: string;\n limit?: number;\n }): Promise<{ messages: HistoryMessage[] }> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(opts.sessionKey)}?include=transcriptRows`,\n this.token,\n );\n if (!res.ok) return { messages: [] };\n const json = (await res.json()) as {\n session?: { transcriptRows?: unknown[] };\n };\n const rows = Array.isArray(json.session?.transcriptRows)\n ? (json.session.transcriptRows as TranscriptStoredRow[])\n : [];\n return { messages: transcriptRowsToClientHistory(rows, { limit: opts.limit }) };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, errorMessage }, `Failed to load history: ${errorMessage}`);\n return { messages: [] };\n }\n }\n\n async loadTranscriptTree(sessionKey: string): Promise<TuiTranscriptTreeEntry[]> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}?include=transcriptRows`,\n this.token,\n );\n if (!res.ok) return [];\n const json = (await res.json()) as {\n session?: { transcriptRows?: unknown[] };\n };\n const rows = Array.isArray(json.session?.transcriptRows)\n ? (json.session.transcriptRows as TranscriptStoredRow[])\n : [];\n return buildTuiTranscriptTree(rows);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, sessionKey, errorMessage }, `Failed to load transcript tree: ${errorMessage}`);\n return [];\n }\n }\n\n async getSessionStats(sessionKey: string): Promise<TuiSessionStats> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}?include=transcriptRows`,\n this.token,\n );\n if (!res.ok) return computeTuiSessionStats([]);\n const json = (await res.json()) as {\n session?: { transcriptRows?: unknown[] };\n };\n const rows = Array.isArray(json.session?.transcriptRows)\n ? (json.session.transcriptRows as TranscriptStoredRow[])\n : [];\n return computeTuiSessionStats(rows);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, sessionKey, errorMessage }, `Failed to load session stats: ${errorMessage}`);\n return computeTuiSessionStats([]);\n }\n }\n\n async listSessions(): Promise<TuiSessionItem[]> {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/sessions', this.token);\n if (!res.ok) return [];\n const json = (await res.json()) as {\n items?: Array<{\n key: string;\n name?: string;\n updatedAt?: string;\n estimatedTokens?: number;\n messageCount?: number;\n customData?: Record<string, unknown>;\n cwd?: string;\n }>;\n };\n return (json.items ?? []).map((s) => ({\n key: s.key,\n displayName: s.name,\n updatedAt: s.updatedAt ? Date.parse(s.updatedAt) : undefined,\n totalTokens: s.estimatedTokens ?? null,\n messageCount: typeof s.messageCount === 'number' ? s.messageCount : undefined,\n model:\n typeof s.customData?.model === 'string'\n ? s.customData.model\n : typeof s.customData?.modelRef === 'string'\n ? s.customData.modelRef\n : null,\n forkedFromSessionKey:\n typeof s.customData?.forkedFromSessionKey === 'string'\n ? s.customData.forkedFromSessionKey\n : undefined,\n cwd: typeof s.cwd === 'string' ? s.cwd : undefined,\n }));\n } catch {\n return [];\n }\n }\n\n async listAgents(): Promise<TuiAgentInfo[]> {\n const agents = new Map<string, TuiAgentInfo>();\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agents', this.token);\n if (res.ok) {\n const json = (await res.json()) as {\n payload?: { agents?: Array<{ id?: unknown; name?: unknown }> };\n };\n for (const row of json.payload?.agents ?? []) {\n if (typeof row.id !== 'string' || !row.id.trim()) continue;\n const id = row.id.trim().toLowerCase();\n agents.set(id, {\n id,\n enabled: true,\n ...(typeof row.name === 'string' && row.name.trim()\n ? { displayName: row.name.trim() }\n : {}),\n });\n }\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, errorMessage }, `Failed to load agents: ${errorMessage}`);\n }\n return [...agents.values()].sort((a, b) => a.id.localeCompare(b.id));\n }\n\n async getSessionInfo(sessionKey: string): Promise<SessionInfo> {\n const out: SessionInfo = {};\n try {\n const sessionPath = `/api/sessions/${encodeURIComponent(sessionKey)}`;\n const [sessionRes, agentCfgRes] = await Promise.all([\n gatewayFetch(this.baseUrl, sessionPath, this.token),\n gatewayFetch(this.baseUrl, `${sessionPath}/agent-config`, this.token),\n ]);\n\n type SessionRow = {\n name?: string;\n estimatedTokens?: number;\n customData?: Record<string, unknown>;\n };\n let session: SessionRow | undefined;\n\n if (sessionRes.ok) {\n const json = (await sessionRes.json()) as { session?: SessionRow };\n session = json.session;\n if (session) {\n if (session.name) out.displayName = session.name;\n if (session.estimatedTokens != null) out.totalTokens = session.estimatedTokens;\n }\n }\n\n if (agentCfgRes.ok) {\n const json = (await agentCfgRes.json()) as {\n ok?: boolean;\n payload?: {\n model?: string;\n thinkingLevel?: string;\n reasoningLevel?: string;\n verboseLevel?: string;\n effectiveWorkspacePath?: string;\n workingDirectoryLocked?: boolean;\n };\n };\n const p = json.payload;\n if (p?.model && typeof p.model === 'string') {\n const parsed = parseModelRef(p.model);\n if (parsed) {\n out.model = parsed.model;\n out.modelProvider = parsed.provider;\n } else {\n out.model = p.model;\n }\n }\n if (p?.thinkingLevel && typeof p.thinkingLevel === 'string') {\n out.thinkingLevel = p.thinkingLevel;\n }\n if (p?.reasoningLevel && typeof p.reasoningLevel === 'string') {\n out.reasoningLevel = p.reasoningLevel;\n }\n if (p?.verboseLevel && typeof p.verboseLevel === 'string') {\n out.verboseLevel = p.verboseLevel;\n }\n if (p?.effectiveWorkspacePath && typeof p.effectiveWorkspacePath === 'string') {\n out.effectiveWorkspacePath = p.effectiveWorkspacePath;\n }\n if (typeof p?.workingDirectoryLocked === 'boolean') {\n out.workingDirectoryLocked = p.workingDirectoryLocked;\n }\n }\n\n if (!out.model && session?.customData) {\n const cd = session.customData;\n const ref =\n typeof cd.model === 'string'\n ? cd.model\n : typeof cd.modelRef === 'string'\n ? cd.modelRef\n : undefined;\n if (ref) {\n const parsed = parseModelRef(ref);\n if (parsed) {\n out.model = parsed.model;\n out.modelProvider = parsed.provider;\n } else {\n out.model = ref;\n }\n }\n if (!out.modelProvider && typeof cd.modelProvider === 'string') {\n out.modelProvider = cd.modelProvider;\n }\n }\n\n if (out.totalTokens != null) {\n const models = await this.listModels();\n const match = models.find(\n (m) =>\n m.id === out.model &&\n (!out.modelProvider || m.provider === out.modelProvider),\n );\n const contextWindow = match?.contextWindow ?? 128_000;\n out.contextWindow = contextWindow;\n out.contextUsagePercent =\n contextWindow > 0\n ? Math.min(100, Math.round((out.totalTokens / contextWindow) * 100))\n : null;\n }\n\n return out;\n } catch {\n return {};\n }\n }\n\n async listModels(): Promise<TuiModelChoice[]> {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/models', this.token);\n if (!res.ok) return [];\n const json = (await res.json()) as {\n ok?: boolean;\n payload?: { models?: TuiModelChoice[] };\n };\n return (json.payload?.models ?? []).map(normalizeGatewayModelChoice);\n } catch {\n return [];\n }\n }\n\n async resetSession(sessionKey: string): Promise<void> {\n await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/reset`,\n this.token,\n { method: 'POST' },\n ).catch(() => {});\n }\n\n async compactSession(\n sessionKey: string,\n options?: { force?: boolean; instructions?: string },\n ): Promise<TuiCompactionResult> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/compaction/run`,\n this.token,\n {\n method: 'POST',\n body: JSON.stringify({\n force: options?.force ?? true,\n instructions: options?.instructions,\n }),\n },\n );\n if (!res.ok) {\n return { compacted: false, summary: `Compaction failed (${res.status})` };\n }\n const json = (await res.json()) as {\n ok?: boolean;\n payload?: {\n result?: {\n compacted?: boolean;\n summary?: string;\n tokensBefore?: number;\n tokensAfter?: number;\n };\n };\n };\n const result = json.payload?.result;\n if (!result?.compacted) {\n return { compacted: false, summary: 'Nothing to compact' };\n }\n return {\n compacted: true,\n summary: `Compacted (${result.tokensBefore ?? '?'} → ${result.tokensAfter ?? '?'} tokens)`,\n tokensBefore: result.tokensBefore,\n tokensAfter: result.tokensAfter,\n transcriptSummary: result.summary,\n };\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n return { compacted: false, summary: errorMessage };\n }\n }\n\n async exportSession(sessionKey: string, format: ExportFormat): Promise<string> {\n const params = new URLSearchParams({ format });\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/export?${params.toString()}`,\n this.token,\n );\n if (!res.ok) {\n throw new Error(`Export failed (${res.status})`);\n }\n const json = (await res.json()) as { content?: string };\n return json.content ?? '';\n }\n\n async importSession(\n targetSessionKey: string,\n jsonContent: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n const res = await gatewayFetch(\n this.baseUrl,\n '/api/sessions/import',\n this.token,\n { method: 'POST', body: JSON.stringify({ targetKey: targetSessionKey, content: jsonContent }) },\n );\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: string;\n sessionKey?: string;\n rowCount?: number;\n };\n if (!res.ok || json.ok === false || !json.sessionKey) {\n throw new Error(json.error ?? `Import failed (${res.status})`);\n }\n return { sessionKey: json.sessionKey, rowCount: json.rowCount ?? 0 };\n }\n\n async createShare(\n sessionKey: string,\n request: TuiShareRequest,\n options?: { agentId?: string },\n ): Promise<TuiShareResult> {\n const res = await gatewayFetch(this.baseUrl, '/api/shares/auto', this.token, {\n method: 'POST',\n body: JSON.stringify({\n path: request.path,\n audience: request.audience,\n mode: request.mode,\n title: request.title,\n description: request.description,\n sessionKey,\n agentId: options?.agentId,\n }),\n });\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: { message?: string };\n payload?: {\n share?: {\n kind?: string;\n title?: string;\n description?: string;\n shareUrl?: string;\n reachability?: string;\n reachabilityHint?: string | null;\n expiresAt?: string;\n maxViews?: number | null;\n };\n thumbnail?: { url?: string };\n routing?: { reason?: string; hint?: string };\n };\n };\n if (!res.ok || json.ok === false || !json.payload?.share?.shareUrl) {\n throw new Error(json.error?.message ?? `Share failed (${res.status})`);\n }\n const share = json.payload.share;\n return {\n kind: share.kind ?? 'share',\n shareUrl: share.shareUrl,\n title: share.title,\n description: share.description,\n thumbnailUrl: json.payload.thumbnail?.url,\n reachability: share.reachability,\n reachabilityHint: share.reachabilityHint,\n expiresAt: share.expiresAt,\n maxViews: share.maxViews,\n routingReason: json.payload.routing?.reason,\n routingHint: json.payload.routing?.hint,\n };\n }\n\n async btwQuery(sessionKey: string, question: string): Promise<{ text: string; error?: string }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/btw`,\n this.token,\n { method: 'POST', body: JSON.stringify({ question }) },\n );\n if (!res.ok) {\n return { text: '', error: `BTW failed (${res.status})` };\n }\n return (await res.json()) as { text: string; error?: string };\n }\n\n async forkSession(\n sourceSessionKey: string,\n targetSessionKey: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sourceSessionKey)}/fork`,\n this.token,\n { method: 'POST', body: JSON.stringify({ targetKey: targetSessionKey }) },\n );\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: string;\n sessionKey?: string;\n rowCount?: number;\n };\n if (!res.ok || json.ok === false || !json.sessionKey) {\n throw new Error(json.error ?? `Fork failed (${res.status})`);\n }\n return { sessionKey: json.sessionKey, rowCount: json.rowCount ?? 0 };\n }\n\n async forkSessionAt(\n sourceSessionKey: string,\n targetSessionKey: string,\n entryId: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n const throughRow = transcriptTreeEntryIdToRowNumber(entryId);\n if (throughRow == null) {\n throw new Error(`Invalid transcript entry: ${entryId}`);\n }\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sourceSessionKey)}/fork-row`,\n this.token,\n { method: 'POST', body: JSON.stringify({ targetKey: targetSessionKey, throughRow }) },\n );\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: string;\n sessionKey?: string;\n rowCount?: number;\n };\n if (!res.ok || json.ok === false || !json.sessionKey) {\n throw new Error(json.error ?? `Fork failed (${res.status})`);\n }\n return { sessionKey: json.sessionKey, rowCount: json.rowCount ?? 0 };\n }\n\n async setTranscriptLabel(\n sessionKey: string,\n entryId: string,\n label: string | undefined,\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/label`,\n this.token,\n { method: 'POST', body: JSON.stringify({ targetId: entryId, label }) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Label update failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async appendCustomEntry(\n sessionKey: string,\n customType: string,\n data?: unknown,\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/custom`,\n this.token,\n { method: 'POST', body: JSON.stringify({ customType, data }) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Custom entry append failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async appendCustomMessage(\n sessionKey: string,\n message: {\n customType: string;\n content?: string | unknown[];\n display?: boolean;\n details?: unknown;\n },\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/custom-message`,\n this.token,\n { method: 'POST', body: JSON.stringify(message) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Custom message append failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async appendBashExecution(\n sessionKey: string,\n entry: {\n command: string;\n output?: string;\n exitCode?: number | null;\n signal?: string | null;\n excludeFromContext?: boolean;\n truncated?: boolean;\n fullOutputPath?: string;\n },\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/bash`,\n this.token,\n { method: 'POST', body: JSON.stringify(entry) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Bash execution append failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async patchSession(sessionKey: string, patch: Record<string, unknown>): Promise<void> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/agent-config`,\n this.token,\n { method: 'PATCH', body: JSON.stringify(patch) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Session config patch failed (${res.status})`);\n }\n }\n\n async renameSession(sessionKey: string, name: string): Promise<{ ok: boolean }> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/rename`,\n this.token,\n { method: 'POST', body: JSON.stringify({ name }) },\n );\n return { ok: res.ok };\n } catch {\n return { ok: false };\n }\n }\n\n async deleteSession(sessionKey: string): Promise<{ ok: boolean }> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}`,\n this.token,\n { method: 'DELETE' },\n );\n if (!res.ok) return { ok: false };\n const json = (await res.json()) as { deleted?: boolean };\n return { ok: json.deleted !== false };\n } catch {\n return { ok: false };\n }\n }\n\n // ── Broadcast SSE (GET /api/events) ──\n\n private startEventStream(): void {\n this.eventAbort?.abort();\n this.eventAbort = new AbortController();\n\n const url = new URL(`${this.baseUrl}/api/events`);\n if (this.token) url.searchParams.set('token', this.token);\n\n const connect = async () => {\n try {\n const res = await fetch(url.toString(), {\n signal: this.eventAbort!.signal,\n headers: { Accept: 'text/event-stream' },\n });\n\n if (!res.ok || !res.body) {\n this.onDisconnected?.(`event stream error: ${res.status}`);\n this.scheduleReconnect();\n return;\n }\n\n this.onConnected?.();\n\n await consumeSSEStream(\n res.body,\n (sseEvent) => {\n if (sseEvent.event === 'connected') return;\n if (sseEvent.event === 'gap') {\n const gapData = parseSSEData(sseEvent.data) as {\n expected?: unknown;\n received?: unknown;\n } | null;\n if (\n gapData &&\n typeof gapData.expected === 'number' &&\n typeof gapData.received === 'number'\n ) {\n this.onGap?.({ expected: gapData.expected, received: gapData.received });\n }\n return;\n }\n const data = parseSSEData(sseEvent.data);\n if (data !== null) {\n this.onEvent?.({ event: sseEvent.event, data, source: 'broadcast' });\n }\n },\n this.eventAbort!.signal,\n );\n\n // Stream ended normally\n if (!this.eventAbort?.signal.aborted) {\n this.onDisconnected?.('stream closed');\n this.scheduleReconnect();\n }\n } catch (error) {\n if (this.eventAbort?.signal.aborted) return;\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, errorMessage }, `Event stream failed: ${errorMessage}`);\n this.onDisconnected?.(errorMessage);\n this.scheduleReconnect();\n }\n };\n\n void connect();\n }\n\n private scheduleReconnect(): void {\n if (this.eventAbort?.signal.aborted) return;\n setTimeout(() => {\n if (!this.eventAbort?.signal.aborted) {\n this.startEventStream();\n }\n }, 3000);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { join } from "node:path";
|
|
4
1
|
import { tmpdir } from "node:os";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
5
|
import { spawnSync } from "node:child_process";
|
|
6
6
|
//#region src/tui/clipboard-image.ts
|
|
7
7
|
const SUPPORTED_IMAGE_MIME_TYPES = [
|
|
@@ -29,6 +29,7 @@ export declare class ChatLog extends Container {
|
|
|
29
29
|
private lastAssistantText;
|
|
30
30
|
private lastStatusEntry;
|
|
31
31
|
private lastStatusText;
|
|
32
|
+
private workflowStatusByRunId;
|
|
32
33
|
constructor(keybindings?: KeybindingsManager);
|
|
33
34
|
private pruneOverflow;
|
|
34
35
|
private dropReferences;
|
|
@@ -37,6 +38,7 @@ export declare class ChatLog extends Container {
|
|
|
37
38
|
private createAssistantMessage;
|
|
38
39
|
addSystem(text: string): void;
|
|
39
40
|
addStatus(text: string): void;
|
|
41
|
+
updateWorkflowRun(runId: string, text: string): void;
|
|
40
42
|
addCompactionSummary(result: TuiCompactionResult): void;
|
|
41
43
|
addBranchSummary(summary: TuiBranchSummary): void;
|
|
42
44
|
addBranchMessageSummary(summary: BranchMessageSummary): void;
|
|
@@ -41,6 +41,7 @@ var ChatLog = class extends Container {
|
|
|
41
41
|
lastAssistantText = "";
|
|
42
42
|
lastStatusEntry = null;
|
|
43
43
|
lastStatusText = null;
|
|
44
|
+
workflowStatusByRunId = /* @__PURE__ */ new Map();
|
|
44
45
|
constructor(keybindings) {
|
|
45
46
|
super();
|
|
46
47
|
this.keybindings = keybindings;
|
|
@@ -68,6 +69,7 @@ var ChatLog = class extends Container {
|
|
|
68
69
|
this.lastStatusEntry = null;
|
|
69
70
|
this.lastStatusText = null;
|
|
70
71
|
}
|
|
72
|
+
for (const [runId, status] of this.workflowStatusByRunId.entries()) if (status.entry === component) this.workflowStatusByRunId.delete(runId);
|
|
71
73
|
}
|
|
72
74
|
append(component) {
|
|
73
75
|
this.addChild(component);
|
|
@@ -88,6 +90,7 @@ var ChatLog = class extends Container {
|
|
|
88
90
|
this.lastAssistantText = "";
|
|
89
91
|
this.lastStatusEntry = null;
|
|
90
92
|
this.lastStatusText = null;
|
|
93
|
+
this.workflowStatusByRunId.clear();
|
|
91
94
|
}
|
|
92
95
|
createAssistantMessage(message) {
|
|
93
96
|
const component = new AssistantMessageComponent(message, {
|
|
@@ -116,6 +119,22 @@ var ChatLog = class extends Container {
|
|
|
116
119
|
this.lastStatusText = statusText;
|
|
117
120
|
this.append(entry);
|
|
118
121
|
}
|
|
122
|
+
updateWorkflowRun(runId, text) {
|
|
123
|
+
const existing = this.workflowStatusByRunId.get(runId);
|
|
124
|
+
if (existing) {
|
|
125
|
+
existing.text.setText(theme.system(text));
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const entry = new Container();
|
|
129
|
+
const statusText = new Text(theme.system(text), 1, 0);
|
|
130
|
+
entry.addChild(new Spacer(1));
|
|
131
|
+
entry.addChild(statusText);
|
|
132
|
+
this.workflowStatusByRunId.set(runId, {
|
|
133
|
+
entry,
|
|
134
|
+
text: statusText
|
|
135
|
+
});
|
|
136
|
+
this.append(entry);
|
|
137
|
+
}
|
|
119
138
|
addCompactionSummary(result) {
|
|
120
139
|
const component = new CompactionSummaryComponent(result, this.keybindings);
|
|
121
140
|
component.setExpanded(this.toolsExpanded);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-log.js","names":[],"sources":["../../../../src/tui/components/chat-log.ts"],"sourcesContent":["import type { Component, KeybindingsManager } from '@earendil-works/pi-tui';\nimport { Container, Spacer, Text } from '@earendil-works/pi-tui';\nimport type { AgentMessage, AgentToolResult } from '@earendil-works/pi-agent-core';\n\nimport { BashExecutionComponent } from './bash-execution.js';\nimport { BashSummaryComponent, type BashSummary } from './bash-summary.js';\nimport { BranchMessageSummaryComponent, type BranchMessageSummary } from './branch-message-summary.js';\nimport { BranchSummaryComponent } from './branch-summary.js';\nimport { CompactionSummaryComponent } from './compaction-summary.js';\nimport { CustomMessageComponent, type CustomMessageSummary } from './custom-message.js';\nimport type { TuiMessageRenderer } from '../../extensions/types/tui.js';\nimport { theme } from '../theme.js';\nimport { AssistantMessageComponent } from './assistant-message.js';\nimport { ToolExecutionComponent, type ToolExecutionOptions } from './tool-execution.js';\nimport { UserMessageComponent } from './user-message.js';\nimport type { TuiBranchSummary, TuiCompactionResult } from '../tui-backend.js';\n\nconst MAX_COMPONENTS = 180;\n\ntype ExpandableBlock = { setExpanded(expanded: boolean): void };\n\nfunction assistantPlainText(message: AgentMessage): string {\n const content = (message as { content?: unknown }).content;\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return content\n .map((block) => {\n if (!block || typeof block !== 'object') return '';\n const rec = block as { type?: unknown; text?: unknown };\n return rec.type === 'text' && typeof rec.text === 'string' ? rec.text : '';\n })\n .join('');\n}\n\nexport class ChatLog extends Container {\n private toolById = new Map<string, ToolExecutionComponent>();\n private bashBlocks: Array<Component & ExpandableBlock> = [];\n private compactionBlocks: CompactionSummaryComponent[] = [];\n private branchBlocks: BranchSummaryComponent[] = [];\n private branchMessageBlocks: BranchMessageSummaryComponent[] = [];\n private customBlocks: CustomMessageComponent[] = [];\n private customMessageRenderers = new Map<string, TuiMessageRenderer>();\n private assistantMessages: AssistantMessageComponent[] = [];\n private streamingRuns = new Map<string, AssistantMessageComponent>();\n /** After finalizeAssistant, late tool execution events can still arrive; keep the bubble to link tools. */\n private assistantAnchorByRunId = new Map<string, AssistantMessageComponent>();\n private runsWithTools = new Set<string>();\n private toolsExpanded = false;\n private showThinking = true;\n private hiddenThinkingLabel = 'Thinking...';\n private toolImageOptions: ToolExecutionOptions = {};\n private lastAssistantText = '';\n private lastStatusEntry: Container | null = null;\n private lastStatusText: Text | null = null;\n\n constructor(private readonly keybindings?: KeybindingsManager) {\n super();\n if (keybindings) {\n this.toolImageOptions.keybindings = keybindings;\n }\n }\n\n private pruneOverflow(): void {\n while (this.children.length > MAX_COMPONENTS) {\n const oldest = this.children[0];\n if (!oldest) return;\n this.removeChild(oldest);\n this.dropReferences(oldest);\n }\n }\n\n private dropReferences(component: Component): void {\n for (const [id, tool] of this.toolById.entries()) {\n if (tool === component) this.toolById.delete(id);\n }\n for (const [runId, msg] of this.streamingRuns.entries()) {\n if (msg === component) this.streamingRuns.delete(runId);\n }\n for (const [runId, msg] of this.assistantAnchorByRunId.entries()) {\n if (msg === component) this.assistantAnchorByRunId.delete(runId);\n }\n this.bashBlocks = this.bashBlocks.filter((entry) => entry !== component);\n this.compactionBlocks = this.compactionBlocks.filter((entry) => entry !== component);\n this.branchBlocks = this.branchBlocks.filter((entry) => entry !== component);\n this.branchMessageBlocks = this.branchMessageBlocks.filter((entry) => entry !== component);\n this.customBlocks = this.customBlocks.filter((entry) => entry !== component);\n this.assistantMessages = this.assistantMessages.filter((entry) => entry !== component);\n if (this.lastStatusEntry === component) {\n this.lastStatusEntry = null;\n this.lastStatusText = null;\n }\n }\n\n private append(component: Component): void {\n this.addChild(component);\n this.pruneOverflow();\n }\n\n clearAll(): void {\n this.clear();\n this.toolById.clear();\n this.bashBlocks = [];\n this.compactionBlocks = [];\n this.branchBlocks = [];\n this.branchMessageBlocks = [];\n this.customBlocks = [];\n this.assistantMessages = [];\n this.streamingRuns.clear();\n this.assistantAnchorByRunId.clear();\n this.runsWithTools.clear();\n this.lastAssistantText = '';\n this.lastStatusEntry = null;\n this.lastStatusText = null;\n }\n\n private createAssistantMessage(message?: AgentMessage): AssistantMessageComponent {\n const component = new AssistantMessageComponent(message, {\n hideThinkingBlock: !this.showThinking,\n hiddenThinkingLabel: this.hiddenThinkingLabel,\n });\n this.assistantMessages.push(component);\n return component;\n }\n\n addSystem(text: string): void {\n const entry = new Container();\n entry.addChild(new Spacer(1));\n entry.addChild(new Text(theme.system(text), 1, 0));\n this.append(entry);\n }\n\n addStatus(text: string): void {\n if (\n this.lastStatusEntry &&\n this.lastStatusText &&\n this.children[this.children.length - 1] === this.lastStatusEntry\n ) {\n this.lastStatusText.setText(theme.system(text));\n return;\n }\n\n const entry = new Container();\n const statusText = new Text(theme.system(text), 1, 0);\n entry.addChild(new Spacer(1));\n entry.addChild(statusText);\n this.lastStatusEntry = entry;\n this.lastStatusText = statusText;\n this.append(entry);\n }\n\n addCompactionSummary(result: TuiCompactionResult): void {\n const component = new CompactionSummaryComponent(result, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.compactionBlocks.push(component);\n this.append(component);\n }\n\n addBranchSummary(summary: TuiBranchSummary): void {\n const component = new BranchSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.branchBlocks.push(component);\n this.append(component);\n }\n\n addBranchMessageSummary(summary: BranchMessageSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new BranchMessageSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.branchMessageBlocks.push(component);\n this.append(component);\n }\n\n addCustomMessage(summary: CustomMessageSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new CustomMessageComponent(\n summary,\n this.customMessageRenderers.get(summary.customType),\n );\n component.setExpanded(this.toolsExpanded);\n this.customBlocks.push(component);\n this.append(component);\n }\n\n setCustomMessageRenderer(customType: string, renderer: TuiMessageRenderer | undefined): void {\n if (renderer) {\n this.customMessageRenderers.set(customType, renderer);\n } else {\n this.customMessageRenderers.delete(customType);\n }\n for (const block of this.customBlocks) {\n if (block.matchesCustomType(customType)) {\n block.setRenderer(renderer);\n }\n }\n }\n\n addUser(text: string | unknown[]): void {\n this.assistantAnchorByRunId.clear();\n this.append(new UserMessageComponent(text));\n }\n\n /** Stream local `!command` output in a bordered block. */\n addBashExecution(\n command: string,\n ui: import('@earendil-works/pi-tui').TUI,\n excludeFromContext: boolean,\n ): BashExecutionComponent {\n this.assistantAnchorByRunId.clear();\n const component = new BashExecutionComponent(command, ui, excludeFromContext, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.bashBlocks.push(component);\n this.append(component);\n return component;\n }\n\n /** Replay a completed shell execution from persisted transcript history. */\n addBashSummary(summary: BashSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new BashSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.bashBlocks.push(component);\n this.append(component);\n }\n\n startAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (existing) {\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n return;\n }\n const component = this.createAssistantMessage(message);\n component.setHasToolCalls(this.runsWithTools.has(runId));\n this.streamingRuns.set(runId, component);\n this.append(component);\n }\n\n updateAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (!existing) {\n this.startAssistant(message, runId);\n return;\n }\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n }\n\n finalizeAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (existing) {\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n this.streamingRuns.delete(runId);\n this.assistantAnchorByRunId.set(runId, existing);\n return;\n }\n const finalMessage = this.createAssistantMessage(message);\n finalMessage.setHasToolCalls(this.runsWithTools.has(runId));\n this.append(finalMessage);\n if (text.trim()) {\n this.assistantAnchorByRunId.set(runId, finalMessage);\n }\n }\n\n dropAssistant(runId: string): void {\n const existing = this.streamingRuns.get(runId);\n if (!existing) return;\n this.removeChild(existing);\n this.streamingRuns.delete(runId);\n }\n\n startTool(toolCallId: string, toolName: string, args: unknown, runId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (existing) {\n existing.setArgs(args);\n return;\n }\n this.runsWithTools.add(runId);\n const component = new ToolExecutionComponent(toolName, toolCallId, args, {\n ...this.toolImageOptions,\n });\n component.setExpanded(this.toolsExpanded);\n this.toolById.set(toolCallId, component);\n\n const assistant = this.streamingRuns.get(runId) ?? this.assistantAnchorByRunId.get(runId);\n assistant?.setHasToolCalls(true);\n this.addChild(component);\n this.pruneOverflow();\n }\n\n markToolExecutionStarted(toolCallId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.markExecutionStarted();\n }\n\n markToolArgsComplete(toolCallId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setArgsComplete();\n }\n\n updateToolResult(toolCallId: string, result: AgentToolResult<any> | unknown, isError: boolean, isPartial = false): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.updateResult(result, isPartial, isError);\n }\n\n updateToolDetails(toolCallId: string, details: unknown): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setPartialDetails(details);\n }\n\n updateToolArgs(toolCallId: string, args: unknown): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setArgs(args);\n }\n\n setToolsExpanded(expanded: boolean): void {\n this.toolsExpanded = expanded;\n for (const tool of this.toolById.values()) {\n tool.setExpanded(expanded);\n }\n for (const bash of this.bashBlocks) {\n bash.setExpanded(expanded);\n }\n for (const compaction of this.compactionBlocks) {\n compaction.setExpanded(expanded);\n }\n for (const branch of this.branchBlocks) {\n branch.setExpanded(expanded);\n }\n for (const branch of this.branchMessageBlocks) {\n branch.setExpanded(expanded);\n }\n for (const custom of this.customBlocks) {\n custom.setExpanded(expanded);\n }\n }\n\n setShowThinking(showThinking: boolean): void {\n this.showThinking = showThinking;\n for (const assistant of this.assistantMessages) {\n assistant.setHideThinkingBlock(!showThinking);\n }\n }\n\n setHiddenThinkingLabel(label?: string): void {\n this.hiddenThinkingLabel = label ?? 'Thinking...';\n for (const assistant of this.assistantMessages) {\n assistant.setHiddenThinkingLabel(this.hiddenThinkingLabel);\n }\n }\n\n setToolImageOptions(options: ToolExecutionOptions): void {\n this.toolImageOptions = { ...options, keybindings: this.keybindings };\n for (const tool of this.toolById.values()) {\n tool.setImageOptions(this.toolImageOptions);\n }\n }\n\n getLastAssistantText(): string {\n return this.lastAssistantText;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chat-log.js","names":[],"sources":["../../../../src/tui/components/chat-log.ts"],"sourcesContent":["import type { Component, KeybindingsManager } from '@earendil-works/pi-tui';\nimport { Container, Spacer, Text } from '@earendil-works/pi-tui';\nimport type { AgentMessage, AgentToolResult } from '@earendil-works/pi-agent-core';\n\nimport { BashExecutionComponent } from './bash-execution.js';\nimport { BashSummaryComponent, type BashSummary } from './bash-summary.js';\nimport { BranchMessageSummaryComponent, type BranchMessageSummary } from './branch-message-summary.js';\nimport { BranchSummaryComponent } from './branch-summary.js';\nimport { CompactionSummaryComponent } from './compaction-summary.js';\nimport { CustomMessageComponent, type CustomMessageSummary } from './custom-message.js';\nimport type { TuiMessageRenderer } from '../../extensions/types/tui.js';\nimport { theme } from '../theme.js';\nimport { AssistantMessageComponent } from './assistant-message.js';\nimport { ToolExecutionComponent, type ToolExecutionOptions } from './tool-execution.js';\nimport { UserMessageComponent } from './user-message.js';\nimport type { TuiBranchSummary, TuiCompactionResult } from '../tui-backend.js';\n\nconst MAX_COMPONENTS = 180;\n\ntype ExpandableBlock = { setExpanded(expanded: boolean): void };\n\nfunction assistantPlainText(message: AgentMessage): string {\n const content = (message as { content?: unknown }).content;\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return content\n .map((block) => {\n if (!block || typeof block !== 'object') return '';\n const rec = block as { type?: unknown; text?: unknown };\n return rec.type === 'text' && typeof rec.text === 'string' ? rec.text : '';\n })\n .join('');\n}\n\nexport class ChatLog extends Container {\n private toolById = new Map<string, ToolExecutionComponent>();\n private bashBlocks: Array<Component & ExpandableBlock> = [];\n private compactionBlocks: CompactionSummaryComponent[] = [];\n private branchBlocks: BranchSummaryComponent[] = [];\n private branchMessageBlocks: BranchMessageSummaryComponent[] = [];\n private customBlocks: CustomMessageComponent[] = [];\n private customMessageRenderers = new Map<string, TuiMessageRenderer>();\n private assistantMessages: AssistantMessageComponent[] = [];\n private streamingRuns = new Map<string, AssistantMessageComponent>();\n /** After finalizeAssistant, late tool execution events can still arrive; keep the bubble to link tools. */\n private assistantAnchorByRunId = new Map<string, AssistantMessageComponent>();\n private runsWithTools = new Set<string>();\n private toolsExpanded = false;\n private showThinking = true;\n private hiddenThinkingLabel = 'Thinking...';\n private toolImageOptions: ToolExecutionOptions = {};\n private lastAssistantText = '';\n private lastStatusEntry: Container | null = null;\n private lastStatusText: Text | null = null;\n private workflowStatusByRunId = new Map<string, { entry: Container; text: Text }>();\n\n constructor(private readonly keybindings?: KeybindingsManager) {\n super();\n if (keybindings) {\n this.toolImageOptions.keybindings = keybindings;\n }\n }\n\n private pruneOverflow(): void {\n while (this.children.length > MAX_COMPONENTS) {\n const oldest = this.children[0];\n if (!oldest) return;\n this.removeChild(oldest);\n this.dropReferences(oldest);\n }\n }\n\n private dropReferences(component: Component): void {\n for (const [id, tool] of this.toolById.entries()) {\n if (tool === component) this.toolById.delete(id);\n }\n for (const [runId, msg] of this.streamingRuns.entries()) {\n if (msg === component) this.streamingRuns.delete(runId);\n }\n for (const [runId, msg] of this.assistantAnchorByRunId.entries()) {\n if (msg === component) this.assistantAnchorByRunId.delete(runId);\n }\n this.bashBlocks = this.bashBlocks.filter((entry) => entry !== component);\n this.compactionBlocks = this.compactionBlocks.filter((entry) => entry !== component);\n this.branchBlocks = this.branchBlocks.filter((entry) => entry !== component);\n this.branchMessageBlocks = this.branchMessageBlocks.filter((entry) => entry !== component);\n this.customBlocks = this.customBlocks.filter((entry) => entry !== component);\n this.assistantMessages = this.assistantMessages.filter((entry) => entry !== component);\n if (this.lastStatusEntry === component) {\n this.lastStatusEntry = null;\n this.lastStatusText = null;\n }\n for (const [runId, status] of this.workflowStatusByRunId.entries()) {\n if (status.entry === component) this.workflowStatusByRunId.delete(runId);\n }\n }\n\n private append(component: Component): void {\n this.addChild(component);\n this.pruneOverflow();\n }\n\n clearAll(): void {\n this.clear();\n this.toolById.clear();\n this.bashBlocks = [];\n this.compactionBlocks = [];\n this.branchBlocks = [];\n this.branchMessageBlocks = [];\n this.customBlocks = [];\n this.assistantMessages = [];\n this.streamingRuns.clear();\n this.assistantAnchorByRunId.clear();\n this.runsWithTools.clear();\n this.lastAssistantText = '';\n this.lastStatusEntry = null;\n this.lastStatusText = null;\n this.workflowStatusByRunId.clear();\n }\n\n private createAssistantMessage(message?: AgentMessage): AssistantMessageComponent {\n const component = new AssistantMessageComponent(message, {\n hideThinkingBlock: !this.showThinking,\n hiddenThinkingLabel: this.hiddenThinkingLabel,\n });\n this.assistantMessages.push(component);\n return component;\n }\n\n addSystem(text: string): void {\n const entry = new Container();\n entry.addChild(new Spacer(1));\n entry.addChild(new Text(theme.system(text), 1, 0));\n this.append(entry);\n }\n\n addStatus(text: string): void {\n if (\n this.lastStatusEntry &&\n this.lastStatusText &&\n this.children[this.children.length - 1] === this.lastStatusEntry\n ) {\n this.lastStatusText.setText(theme.system(text));\n return;\n }\n\n const entry = new Container();\n const statusText = new Text(theme.system(text), 1, 0);\n entry.addChild(new Spacer(1));\n entry.addChild(statusText);\n this.lastStatusEntry = entry;\n this.lastStatusText = statusText;\n this.append(entry);\n }\n\n updateWorkflowRun(runId: string, text: string): void {\n const existing = this.workflowStatusByRunId.get(runId);\n if (existing) {\n existing.text.setText(theme.system(text));\n return;\n }\n\n const entry = new Container();\n const statusText = new Text(theme.system(text), 1, 0);\n entry.addChild(new Spacer(1));\n entry.addChild(statusText);\n this.workflowStatusByRunId.set(runId, { entry, text: statusText });\n this.append(entry);\n }\n\n addCompactionSummary(result: TuiCompactionResult): void {\n const component = new CompactionSummaryComponent(result, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.compactionBlocks.push(component);\n this.append(component);\n }\n\n addBranchSummary(summary: TuiBranchSummary): void {\n const component = new BranchSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.branchBlocks.push(component);\n this.append(component);\n }\n\n addBranchMessageSummary(summary: BranchMessageSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new BranchMessageSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.branchMessageBlocks.push(component);\n this.append(component);\n }\n\n addCustomMessage(summary: CustomMessageSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new CustomMessageComponent(\n summary,\n this.customMessageRenderers.get(summary.customType),\n );\n component.setExpanded(this.toolsExpanded);\n this.customBlocks.push(component);\n this.append(component);\n }\n\n setCustomMessageRenderer(customType: string, renderer: TuiMessageRenderer | undefined): void {\n if (renderer) {\n this.customMessageRenderers.set(customType, renderer);\n } else {\n this.customMessageRenderers.delete(customType);\n }\n for (const block of this.customBlocks) {\n if (block.matchesCustomType(customType)) {\n block.setRenderer(renderer);\n }\n }\n }\n\n addUser(text: string | unknown[]): void {\n this.assistantAnchorByRunId.clear();\n this.append(new UserMessageComponent(text));\n }\n\n /** Stream local `!command` output in a bordered block. */\n addBashExecution(\n command: string,\n ui: import('@earendil-works/pi-tui').TUI,\n excludeFromContext: boolean,\n ): BashExecutionComponent {\n this.assistantAnchorByRunId.clear();\n const component = new BashExecutionComponent(command, ui, excludeFromContext, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.bashBlocks.push(component);\n this.append(component);\n return component;\n }\n\n /** Replay a completed shell execution from persisted transcript history. */\n addBashSummary(summary: BashSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new BashSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.bashBlocks.push(component);\n this.append(component);\n }\n\n startAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (existing) {\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n return;\n }\n const component = this.createAssistantMessage(message);\n component.setHasToolCalls(this.runsWithTools.has(runId));\n this.streamingRuns.set(runId, component);\n this.append(component);\n }\n\n updateAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (!existing) {\n this.startAssistant(message, runId);\n return;\n }\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n }\n\n finalizeAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (existing) {\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n this.streamingRuns.delete(runId);\n this.assistantAnchorByRunId.set(runId, existing);\n return;\n }\n const finalMessage = this.createAssistantMessage(message);\n finalMessage.setHasToolCalls(this.runsWithTools.has(runId));\n this.append(finalMessage);\n if (text.trim()) {\n this.assistantAnchorByRunId.set(runId, finalMessage);\n }\n }\n\n dropAssistant(runId: string): void {\n const existing = this.streamingRuns.get(runId);\n if (!existing) return;\n this.removeChild(existing);\n this.streamingRuns.delete(runId);\n }\n\n startTool(toolCallId: string, toolName: string, args: unknown, runId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (existing) {\n existing.setArgs(args);\n return;\n }\n this.runsWithTools.add(runId);\n const component = new ToolExecutionComponent(toolName, toolCallId, args, {\n ...this.toolImageOptions,\n });\n component.setExpanded(this.toolsExpanded);\n this.toolById.set(toolCallId, component);\n\n const assistant = this.streamingRuns.get(runId) ?? this.assistantAnchorByRunId.get(runId);\n assistant?.setHasToolCalls(true);\n this.addChild(component);\n this.pruneOverflow();\n }\n\n markToolExecutionStarted(toolCallId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.markExecutionStarted();\n }\n\n markToolArgsComplete(toolCallId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setArgsComplete();\n }\n\n updateToolResult(toolCallId: string, result: AgentToolResult<any> | unknown, isError: boolean, isPartial = false): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.updateResult(result, isPartial, isError);\n }\n\n updateToolDetails(toolCallId: string, details: unknown): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setPartialDetails(details);\n }\n\n updateToolArgs(toolCallId: string, args: unknown): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setArgs(args);\n }\n\n setToolsExpanded(expanded: boolean): void {\n this.toolsExpanded = expanded;\n for (const tool of this.toolById.values()) {\n tool.setExpanded(expanded);\n }\n for (const bash of this.bashBlocks) {\n bash.setExpanded(expanded);\n }\n for (const compaction of this.compactionBlocks) {\n compaction.setExpanded(expanded);\n }\n for (const branch of this.branchBlocks) {\n branch.setExpanded(expanded);\n }\n for (const branch of this.branchMessageBlocks) {\n branch.setExpanded(expanded);\n }\n for (const custom of this.customBlocks) {\n custom.setExpanded(expanded);\n }\n }\n\n setShowThinking(showThinking: boolean): void {\n this.showThinking = showThinking;\n for (const assistant of this.assistantMessages) {\n assistant.setHideThinkingBlock(!showThinking);\n }\n }\n\n setHiddenThinkingLabel(label?: string): void {\n this.hiddenThinkingLabel = label ?? 'Thinking...';\n for (const assistant of this.assistantMessages) {\n assistant.setHiddenThinkingLabel(this.hiddenThinkingLabel);\n }\n }\n\n setToolImageOptions(options: ToolExecutionOptions): void {\n this.toolImageOptions = { ...options, keybindings: this.keybindings };\n for (const tool of this.toolById.values()) {\n tool.setImageOptions(this.toolImageOptions);\n }\n }\n\n getLastAssistantText(): string {\n return this.lastAssistantText;\n }\n}\n"],"mappings":";;;;;;;;;;;;AAiBA,MAAM,iBAAiB;AAIvB,SAAS,mBAAmB,SAA+B;CACzD,MAAM,UAAW,QAAkC;AACnD,KAAI,OAAO,YAAY,SAAU,QAAO;AACxC,KAAI,CAAC,MAAM,QAAQ,QAAQ,CAAE,QAAO;AACpC,QAAO,QACJ,KAAK,UAAU;AACd,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;EAChD,MAAM,MAAM;AACZ,SAAO,IAAI,SAAS,UAAU,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO;GACxE,CACD,KAAK,GAAG;;AAGb,IAAa,UAAb,cAA6B,UAAU;CACrC,2BAAmB,IAAI,KAAqC;CAC5D,aAAyD,EAAE;CAC3D,mBAAyD,EAAE;CAC3D,eAAiD,EAAE;CACnD,sBAA+D,EAAE;CACjE,eAAiD,EAAE;CACnD,yCAAiC,IAAI,KAAiC;CACtE,oBAAyD,EAAE;CAC3D,gCAAwB,IAAI,KAAwC;;CAEpE,yCAAiC,IAAI,KAAwC;CAC7E,gCAAwB,IAAI,KAAa;CACzC,gBAAwB;CACxB,eAAuB;CACvB,sBAA8B;CAC9B,mBAAiD,EAAE;CACnD,oBAA4B;CAC5B,kBAA4C;CAC5C,iBAAsC;CACtC,wCAAgC,IAAI,KAA+C;CAEnF,YAAY,aAAmD;AAC7D,SAAO;AADoB,OAAA,cAAA;AAE3B,MAAI,YACF,MAAK,iBAAiB,cAAc;;CAIxC,gBAA8B;AAC5B,SAAO,KAAK,SAAS,SAAS,gBAAgB;GAC5C,MAAM,SAAS,KAAK,SAAS;AAC7B,OAAI,CAAC,OAAQ;AACb,QAAK,YAAY,OAAO;AACxB,QAAK,eAAe,OAAO;;;CAI/B,eAAuB,WAA4B;AACjD,OAAK,MAAM,CAAC,IAAI,SAAS,KAAK,SAAS,SAAS,CAC9C,KAAI,SAAS,UAAW,MAAK,SAAS,OAAO,GAAG;AAElD,OAAK,MAAM,CAAC,OAAO,QAAQ,KAAK,cAAc,SAAS,CACrD,KAAI,QAAQ,UAAW,MAAK,cAAc,OAAO,MAAM;AAEzD,OAAK,MAAM,CAAC,OAAO,QAAQ,KAAK,uBAAuB,SAAS,CAC9D,KAAI,QAAQ,UAAW,MAAK,uBAAuB,OAAO,MAAM;AAElE,OAAK,aAAa,KAAK,WAAW,QAAQ,UAAU,UAAU,UAAU;AACxE,OAAK,mBAAmB,KAAK,iBAAiB,QAAQ,UAAU,UAAU,UAAU;AACpF,OAAK,eAAe,KAAK,aAAa,QAAQ,UAAU,UAAU,UAAU;AAC5E,OAAK,sBAAsB,KAAK,oBAAoB,QAAQ,UAAU,UAAU,UAAU;AAC1F,OAAK,eAAe,KAAK,aAAa,QAAQ,UAAU,UAAU,UAAU;AAC5E,OAAK,oBAAoB,KAAK,kBAAkB,QAAQ,UAAU,UAAU,UAAU;AACtF,MAAI,KAAK,oBAAoB,WAAW;AACtC,QAAK,kBAAkB;AACvB,QAAK,iBAAiB;;AAExB,OAAK,MAAM,CAAC,OAAO,WAAW,KAAK,sBAAsB,SAAS,CAChE,KAAI,OAAO,UAAU,UAAW,MAAK,sBAAsB,OAAO,MAAM;;CAI5E,OAAe,WAA4B;AACzC,OAAK,SAAS,UAAU;AACxB,OAAK,eAAe;;CAGtB,WAAiB;AACf,OAAK,OAAO;AACZ,OAAK,SAAS,OAAO;AACrB,OAAK,aAAa,EAAE;AACpB,OAAK,mBAAmB,EAAE;AAC1B,OAAK,eAAe,EAAE;AACtB,OAAK,sBAAsB,EAAE;AAC7B,OAAK,eAAe,EAAE;AACtB,OAAK,oBAAoB,EAAE;AAC3B,OAAK,cAAc,OAAO;AAC1B,OAAK,uBAAuB,OAAO;AACnC,OAAK,cAAc,OAAO;AAC1B,OAAK,oBAAoB;AACzB,OAAK,kBAAkB;AACvB,OAAK,iBAAiB;AACtB,OAAK,sBAAsB,OAAO;;CAGpC,uBAA+B,SAAmD;EAChF,MAAM,YAAY,IAAI,0BAA0B,SAAS;GACvD,mBAAmB,CAAC,KAAK;GACzB,qBAAqB,KAAK;GAC3B,CAAC;AACF,OAAK,kBAAkB,KAAK,UAAU;AACtC,SAAO;;CAGT,UAAU,MAAoB;EAC5B,MAAM,QAAQ,IAAI,WAAW;AAC7B,QAAM,SAAS,IAAI,OAAO,EAAE,CAAC;AAC7B,QAAM,SAAS,IAAI,KAAK,MAAM,OAAO,KAAK,EAAE,GAAG,EAAE,CAAC;AAClD,OAAK,OAAO,MAAM;;CAGpB,UAAU,MAAoB;AAC5B,MACE,KAAK,mBACL,KAAK,kBACL,KAAK,SAAS,KAAK,SAAS,SAAS,OAAO,KAAK,iBACjD;AACA,QAAK,eAAe,QAAQ,MAAM,OAAO,KAAK,CAAC;AAC/C;;EAGF,MAAM,QAAQ,IAAI,WAAW;EAC7B,MAAM,aAAa,IAAI,KAAK,MAAM,OAAO,KAAK,EAAE,GAAG,EAAE;AACrD,QAAM,SAAS,IAAI,OAAO,EAAE,CAAC;AAC7B,QAAM,SAAS,WAAW;AAC1B,OAAK,kBAAkB;AACvB,OAAK,iBAAiB;AACtB,OAAK,OAAO,MAAM;;CAGpB,kBAAkB,OAAe,MAAoB;EACnD,MAAM,WAAW,KAAK,sBAAsB,IAAI,MAAM;AACtD,MAAI,UAAU;AACZ,YAAS,KAAK,QAAQ,MAAM,OAAO,KAAK,CAAC;AACzC;;EAGF,MAAM,QAAQ,IAAI,WAAW;EAC7B,MAAM,aAAa,IAAI,KAAK,MAAM,OAAO,KAAK,EAAE,GAAG,EAAE;AACrD,QAAM,SAAS,IAAI,OAAO,EAAE,CAAC;AAC7B,QAAM,SAAS,WAAW;AAC1B,OAAK,sBAAsB,IAAI,OAAO;GAAE;GAAO,MAAM;GAAY,CAAC;AAClE,OAAK,OAAO,MAAM;;CAGpB,qBAAqB,QAAmC;EACtD,MAAM,YAAY,IAAI,2BAA2B,QAAQ,KAAK,YAAY;AAC1E,YAAU,YAAY,KAAK,cAAc;AACzC,OAAK,iBAAiB,KAAK,UAAU;AACrC,OAAK,OAAO,UAAU;;CAGxB,iBAAiB,SAAiC;EAChD,MAAM,YAAY,IAAI,uBAAuB,SAAS,KAAK,YAAY;AACvE,YAAU,YAAY,KAAK,cAAc;AACzC,OAAK,aAAa,KAAK,UAAU;AACjC,OAAK,OAAO,UAAU;;CAGxB,wBAAwB,SAAqC;AAC3D,OAAK,uBAAuB,OAAO;EACnC,MAAM,YAAY,IAAI,8BAA8B,SAAS,KAAK,YAAY;AAC9E,YAAU,YAAY,KAAK,cAAc;AACzC,OAAK,oBAAoB,KAAK,UAAU;AACxC,OAAK,OAAO,UAAU;;CAGxB,iBAAiB,SAAqC;AACpD,OAAK,uBAAuB,OAAO;EACnC,MAAM,YAAY,IAAI,uBACpB,SACA,KAAK,uBAAuB,IAAI,QAAQ,WAAW,CACpD;AACD,YAAU,YAAY,KAAK,cAAc;AACzC,OAAK,aAAa,KAAK,UAAU;AACjC,OAAK,OAAO,UAAU;;CAGxB,yBAAyB,YAAoB,UAAgD;AAC3F,MAAI,SACF,MAAK,uBAAuB,IAAI,YAAY,SAAS;MAErD,MAAK,uBAAuB,OAAO,WAAW;AAEhD,OAAK,MAAM,SAAS,KAAK,aACvB,KAAI,MAAM,kBAAkB,WAAW,CACrC,OAAM,YAAY,SAAS;;CAKjC,QAAQ,MAAgC;AACtC,OAAK,uBAAuB,OAAO;AACnC,OAAK,OAAO,IAAI,qBAAqB,KAAK,CAAC;;;CAI7C,iBACE,SACA,IACA,oBACwB;AACxB,OAAK,uBAAuB,OAAO;EACnC,MAAM,YAAY,IAAI,uBAAuB,SAAS,IAAI,oBAAoB,KAAK,YAAY;AAC/F,YAAU,YAAY,KAAK,cAAc;AACzC,OAAK,WAAW,KAAK,UAAU;AAC/B,OAAK,OAAO,UAAU;AACtB,SAAO;;;CAIT,eAAe,SAA4B;AACzC,OAAK,uBAAuB,OAAO;EACnC,MAAM,YAAY,IAAI,qBAAqB,SAAS,KAAK,YAAY;AACrE,YAAU,YAAY,KAAK,cAAc;AACzC,OAAK,WAAW,KAAK,UAAU;AAC/B,OAAK,OAAO,UAAU;;CAGxB,eAAe,SAAuB,OAAqB;EACzD,MAAM,OAAO,mBAAmB,QAAQ;AACxC,MAAI,KAAK,MAAM,CAAE,MAAK,oBAAoB;EAC1C,MAAM,WAAW,KAAK,cAAc,IAAI,MAAM;AAC9C,MAAI,UAAU;AACZ,YAAS,cAAc,QAAQ;AAC/B,YAAS,gBAAgB,KAAK,cAAc,IAAI,MAAM,CAAC;AACvD;;EAEF,MAAM,YAAY,KAAK,uBAAuB,QAAQ;AACtD,YAAU,gBAAgB,KAAK,cAAc,IAAI,MAAM,CAAC;AACxD,OAAK,cAAc,IAAI,OAAO,UAAU;AACxC,OAAK,OAAO,UAAU;;CAGxB,gBAAgB,SAAuB,OAAqB;EAC1D,MAAM,OAAO,mBAAmB,QAAQ;AACxC,MAAI,KAAK,MAAM,CAAE,MAAK,oBAAoB;EAC1C,MAAM,WAAW,KAAK,cAAc,IAAI,MAAM;AAC9C,MAAI,CAAC,UAAU;AACb,QAAK,eAAe,SAAS,MAAM;AACnC;;AAEF,WAAS,cAAc,QAAQ;AAC/B,WAAS,gBAAgB,KAAK,cAAc,IAAI,MAAM,CAAC;;CAGzD,kBAAkB,SAAuB,OAAqB;EAC5D,MAAM,OAAO,mBAAmB,QAAQ;AACxC,MAAI,KAAK,MAAM,CAAE,MAAK,oBAAoB;EAC1C,MAAM,WAAW,KAAK,cAAc,IAAI,MAAM;AAC9C,MAAI,UAAU;AACZ,YAAS,cAAc,QAAQ;AAC/B,YAAS,gBAAgB,KAAK,cAAc,IAAI,MAAM,CAAC;AACvD,QAAK,cAAc,OAAO,MAAM;AAChC,QAAK,uBAAuB,IAAI,OAAO,SAAS;AAChD;;EAEF,MAAM,eAAe,KAAK,uBAAuB,QAAQ;AACzD,eAAa,gBAAgB,KAAK,cAAc,IAAI,MAAM,CAAC;AAC3D,OAAK,OAAO,aAAa;AACzB,MAAI,KAAK,MAAM,CACb,MAAK,uBAAuB,IAAI,OAAO,aAAa;;CAIxD,cAAc,OAAqB;EACjC,MAAM,WAAW,KAAK,cAAc,IAAI,MAAM;AAC9C,MAAI,CAAC,SAAU;AACf,OAAK,YAAY,SAAS;AAC1B,OAAK,cAAc,OAAO,MAAM;;CAGlC,UAAU,YAAoB,UAAkB,MAAe,OAAqB;EAClF,MAAM,WAAW,KAAK,SAAS,IAAI,WAAW;AAC9C,MAAI,UAAU;AACZ,YAAS,QAAQ,KAAK;AACtB;;AAEF,OAAK,cAAc,IAAI,MAAM;EAC7B,MAAM,YAAY,IAAI,uBAAuB,UAAU,YAAY,MAAM,EACvE,GAAG,KAAK,kBACT,CAAC;AACF,YAAU,YAAY,KAAK,cAAc;AACzC,OAAK,SAAS,IAAI,YAAY,UAAU;AAGxC,GADkB,KAAK,cAAc,IAAI,MAAM,IAAI,KAAK,uBAAuB,IAAI,MAAM,GAC9E,gBAAgB,KAAK;AAChC,OAAK,SAAS,UAAU;AACxB,OAAK,eAAe;;CAGtB,yBAAyB,YAA0B;EACjD,MAAM,WAAW,KAAK,SAAS,IAAI,WAAW;AAC9C,MAAI,CAAC,SAAU;AACf,WAAS,sBAAsB;;CAGjC,qBAAqB,YAA0B;EAC7C,MAAM,WAAW,KAAK,SAAS,IAAI,WAAW;AAC9C,MAAI,CAAC,SAAU;AACf,WAAS,iBAAiB;;CAG5B,iBAAiB,YAAoB,QAAwC,SAAkB,YAAY,OAAa;EACtH,MAAM,WAAW,KAAK,SAAS,IAAI,WAAW;AAC9C,MAAI,CAAC,SAAU;AACf,WAAS,aAAa,QAAQ,WAAW,QAAQ;;CAGnD,kBAAkB,YAAoB,SAAwB;EAC5D,MAAM,WAAW,KAAK,SAAS,IAAI,WAAW;AAC9C,MAAI,CAAC,SAAU;AACf,WAAS,kBAAkB,QAAQ;;CAGrC,eAAe,YAAoB,MAAqB;EACtD,MAAM,WAAW,KAAK,SAAS,IAAI,WAAW;AAC9C,MAAI,CAAC,SAAU;AACf,WAAS,QAAQ,KAAK;;CAGxB,iBAAiB,UAAyB;AACxC,OAAK,gBAAgB;AACrB,OAAK,MAAM,QAAQ,KAAK,SAAS,QAAQ,CACvC,MAAK,YAAY,SAAS;AAE5B,OAAK,MAAM,QAAQ,KAAK,WACtB,MAAK,YAAY,SAAS;AAE5B,OAAK,MAAM,cAAc,KAAK,iBAC5B,YAAW,YAAY,SAAS;AAElC,OAAK,MAAM,UAAU,KAAK,aACxB,QAAO,YAAY,SAAS;AAE9B,OAAK,MAAM,UAAU,KAAK,oBACxB,QAAO,YAAY,SAAS;AAE9B,OAAK,MAAM,UAAU,KAAK,aACxB,QAAO,YAAY,SAAS;;CAIhC,gBAAgB,cAA6B;AAC3C,OAAK,eAAe;AACpB,OAAK,MAAM,aAAa,KAAK,kBAC3B,WAAU,qBAAqB,CAAC,aAAa;;CAIjD,uBAAuB,OAAsB;AAC3C,OAAK,sBAAsB,SAAS;AACpC,OAAK,MAAM,aAAa,KAAK,kBAC3B,WAAU,uBAAuB,KAAK,oBAAoB;;CAI9D,oBAAoB,SAAqC;AACvD,OAAK,mBAAmB;GAAE,GAAG;GAAS,aAAa,KAAK;GAAa;AACrE,OAAK,MAAM,QAAQ,KAAK,SAAS,QAAQ,CACvC,MAAK,gBAAgB,KAAK,iBAAiB;;CAI/C,uBAA+B;AAC7B,SAAO,KAAK"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AutocompleteItem, AutocompleteProvider, AutocompleteSuggestions } from '@earendil-works/pi-tui';
|
|
2
2
|
import type { TuiAutocompleteProvider, TuiAutocompleteProviderFactory } from '../../extensions/types/tui.js';
|
|
3
3
|
export interface ExtensionSlashCommandAutocompleteItem {
|
|
4
|
-
originalName
|
|
4
|
+
originalName?: string;
|
|
5
5
|
name: string;
|
|
6
6
|
description: string;
|
|
7
7
|
}
|
|
@@ -13,7 +13,8 @@ export declare class ChainedAutocompleteProvider implements AutocompleteProvider
|
|
|
13
13
|
private readonly baseSlashCommandNames;
|
|
14
14
|
private readonly getSessionKey;
|
|
15
15
|
private readonly cwd;
|
|
16
|
-
|
|
16
|
+
private readonly additionalSlashCommands;
|
|
17
|
+
constructor(primary: AutocompleteProvider, extraProviders: TuiAutocompleteProvider[], extensionSlashCommands: ExtensionSlashCommandAutocompleteItem[], baseSlashCommandNames: Set<string>, getSessionKey: () => string, cwd: string, additionalSlashCommands?: ExtensionSlashCommandAutocompleteItem[]);
|
|
17
18
|
getSuggestions(lines: string[], cursorLine: number, cursorCol: number, options: {
|
|
18
19
|
signal: AbortSignal;
|
|
19
20
|
force?: boolean;
|
|
@@ -8,22 +8,24 @@ function dedupeAutocompleteItems(items) {
|
|
|
8
8
|
});
|
|
9
9
|
}
|
|
10
10
|
var ChainedAutocompleteProvider = class {
|
|
11
|
-
constructor(primary, extraProviders, extensionSlashCommands, baseSlashCommandNames, getSessionKey, cwd) {
|
|
11
|
+
constructor(primary, extraProviders, extensionSlashCommands, baseSlashCommandNames, getSessionKey, cwd, additionalSlashCommands = []) {
|
|
12
12
|
this.primary = primary;
|
|
13
13
|
this.extraProviders = extraProviders;
|
|
14
14
|
this.extensionSlashCommands = extensionSlashCommands;
|
|
15
15
|
this.baseSlashCommandNames = baseSlashCommandNames;
|
|
16
16
|
this.getSessionKey = getSessionKey;
|
|
17
17
|
this.cwd = cwd;
|
|
18
|
+
this.additionalSlashCommands = additionalSlashCommands;
|
|
18
19
|
}
|
|
19
20
|
async getSuggestions(lines, cursorLine, cursorCol, options) {
|
|
20
21
|
const primary = await this.primary.getSuggestions(lines, cursorLine, cursorCol, options);
|
|
21
22
|
const beforeCursor = (lines[cursorLine] ?? "").slice(0, cursorCol);
|
|
22
23
|
const slashMatch = beforeCursor.match(/^\/([\w:-]*)$/);
|
|
23
|
-
|
|
24
|
+
const slashCommands = [...this.additionalSlashCommands, ...this.extensionSlashCommands];
|
|
25
|
+
if (slashMatch && slashCommands.length > 0) {
|
|
24
26
|
const query = (slashMatch[1] ?? "").toLowerCase();
|
|
25
27
|
const prefix = `/${slashMatch[1] ?? ""}`;
|
|
26
|
-
const items =
|
|
28
|
+
const items = slashCommands.filter((c) => !this.baseSlashCommandNames.has(c.originalName ?? c.name)).filter((c) => !query || c.name.toLowerCase().startsWith(query)).map((c) => ({
|
|
27
29
|
value: `/${c.name}`,
|
|
28
30
|
label: c.name,
|
|
29
31
|
description: c.description
|
|
@@ -41,7 +43,7 @@ var ChainedAutocompleteProvider = class {
|
|
|
41
43
|
};
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
|
-
const atMatch = beforeCursor.match(/@([
|
|
46
|
+
const atMatch = beforeCursor.match(/@([^\s]*)$/);
|
|
45
47
|
if (!atMatch) return primary;
|
|
46
48
|
const query = atMatch[1] ?? "";
|
|
47
49
|
const prefix = `@${query}`;
|
|
@@ -52,22 +54,24 @@ var ChainedAutocompleteProvider = class {
|
|
|
52
54
|
cwd: this.cwd,
|
|
53
55
|
sessionKey
|
|
54
56
|
});
|
|
55
|
-
for (const s of suggestions)
|
|
56
|
-
value
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
for (const s of suggestions) {
|
|
58
|
+
const value = s.value ?? `@${s.name}`;
|
|
59
|
+
items.push({
|
|
60
|
+
value,
|
|
61
|
+
label: s.label ?? s.name,
|
|
62
|
+
description: s.description
|
|
63
|
+
});
|
|
64
|
+
}
|
|
60
65
|
}
|
|
61
66
|
if (items.length === 0) return primary;
|
|
62
|
-
const
|
|
63
|
-
const merged = dedupeAutocompleteItems([...primary?.prefix.startsWith("@") ? primary.items : [], ...filtered]);
|
|
67
|
+
const merged = dedupeAutocompleteItems([...primary?.prefix.startsWith("@") ? primary.items : [], ...items]);
|
|
64
68
|
return {
|
|
65
69
|
prefix: primary?.prefix.startsWith("@") ? primary.prefix : prefix,
|
|
66
70
|
items: merged.slice(0, 30)
|
|
67
71
|
};
|
|
68
72
|
}
|
|
69
73
|
applyCompletion(lines, cursorLine, cursorCol, item, prefix) {
|
|
70
|
-
if (prefix.startsWith("
|
|
74
|
+
if (prefix.startsWith("/") && item.value.startsWith("/")) {
|
|
71
75
|
const line = lines[cursorLine] ?? "";
|
|
72
76
|
const start = line.slice(0, cursorCol).length - prefix.length;
|
|
73
77
|
const nextLine = line.slice(0, start) + item.value + line.slice(cursorCol);
|
|
@@ -79,6 +83,19 @@ var ChainedAutocompleteProvider = class {
|
|
|
79
83
|
cursorCol: start + item.value.length
|
|
80
84
|
};
|
|
81
85
|
}
|
|
86
|
+
if (prefix.startsWith("@")) {
|
|
87
|
+
const line = lines[cursorLine] ?? "";
|
|
88
|
+
const start = line.slice(0, cursorCol).length - prefix.length;
|
|
89
|
+
const suffix = item.value.startsWith("@file:") && !item.value.endsWith("/") ? " " : "";
|
|
90
|
+
const nextLine = line.slice(0, start) + item.value + suffix + line.slice(cursorCol);
|
|
91
|
+
const nextLines = [...lines];
|
|
92
|
+
nextLines[cursorLine] = nextLine;
|
|
93
|
+
return {
|
|
94
|
+
lines: nextLines,
|
|
95
|
+
cursorLine,
|
|
96
|
+
cursorCol: start + item.value.length + suffix.length
|
|
97
|
+
};
|
|
98
|
+
}
|
|
82
99
|
return this.primary.applyCompletion(lines, cursorLine, cursorCol, item, prefix);
|
|
83
100
|
}
|
|
84
101
|
shouldTriggerFileCompletion(lines, cursorLine, cursorCol) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autocomplete.js","names":[],"sources":["../../../../src/tui/extension-host/autocomplete.ts"],"sourcesContent":["import type {\n AutocompleteItem,\n AutocompleteProvider,\n AutocompleteSuggestions,\n} from '@earendil-works/pi-tui';\n\nimport type {\n TuiAutocompleteProvider,\n TuiAutocompleteProviderApi,\n TuiAutocompleteProviderFactory,\n} from '../../extensions/types/tui.js';\n\nexport interface ExtensionSlashCommandAutocompleteItem {\n originalName: string;\n name: string;\n description: string;\n}\n\nexport function dedupeAutocompleteItems(items: AutocompleteItem[]): AutocompleteItem[] {\n const seen = new Set<string>();\n return items.filter((item) => {\n if (seen.has(item.value)) return false;\n seen.add(item.value);\n return true;\n });\n}\n\nexport class ChainedAutocompleteProvider implements AutocompleteProvider {\n constructor(\n private readonly primary: AutocompleteProvider,\n private readonly extraProviders: TuiAutocompleteProvider[],\n private readonly extensionSlashCommands: ExtensionSlashCommandAutocompleteItem[],\n private readonly baseSlashCommandNames: Set<string>,\n private readonly getSessionKey: () => string,\n private readonly cwd: string,\n ) {}\n\n async getSuggestions(\n lines: string[],\n cursorLine: number,\n cursorCol: number,\n options: { signal: AbortSignal; force?: boolean },\n ): Promise<AutocompleteSuggestions | null> {\n const primary = await this.primary.getSuggestions(lines, cursorLine, cursorCol, options);\n\n const line = lines[cursorLine] ?? '';\n const beforeCursor = line.slice(0, cursorCol);\n\n const slashMatch = beforeCursor.match(/^\\/([\\w:-]*)$/);\n if (slashMatch && this.extensionSlashCommands.length > 0) {\n const query = (slashMatch[1] ?? '').toLowerCase();\n const prefix = `/${slashMatch[1] ?? ''}`;\n const items: AutocompleteItem[] = this.extensionSlashCommands\n .filter((c) => !this.baseSlashCommandNames.has(c.originalName))\n .filter((c) => !query || c.name.startsWith(query))\n .map((c) => ({\n value: `/${c.name}`,\n label: c.name,\n description: c.description,\n }));\n if (items.length > 0) {\n const merged = primary?.items ? [...primary.items, ...items] : items;\n const seen = new Set<string>();\n const deduped = merged.filter((item) => {\n if (seen.has(item.value)) return false;\n seen.add(item.value);\n return true;\n });\n return { prefix, items: deduped.slice(0, 30) };\n }\n }\n\n const atMatch = beforeCursor.match(/@([\\w.-]*)$/);\n if (!atMatch) {\n return primary;\n }\n\n const query = atMatch[1] ?? '';\n const prefix = `@${query}`;\n const sessionKey = this.getSessionKey();\n const items: AutocompleteItem[] = [];\n\n for (const provider of this.extraProviders) {\n const suggestions = await provider(query, { cwd: this.cwd, sessionKey });\n for (const s of suggestions) {\n items.push({\n value: `@${s.name}`,\n label: s.name,\n description: s.description,\n });\n }\n }\n\n if (items.length === 0) {\n return primary;\n }\n\n const filtered = query\n ? items.filter((item) => item.label.toLowerCase().includes(query.toLowerCase()))\n : items;\n\n const primaryItems = primary?.prefix.startsWith('@') ? primary.items : [];\n const merged = dedupeAutocompleteItems([...primaryItems, ...filtered]);\n\n return {\n prefix: primary?.prefix.startsWith('@') ? primary.prefix : prefix,\n items: merged.slice(0, 30),\n };\n }\n\n applyCompletion(\n lines: string[],\n cursorLine: number,\n cursorCol: number,\n item: AutocompleteItem,\n prefix: string,\n ) {\n if (prefix.startsWith('@')) {\n const line = lines[cursorLine] ?? '';\n const before = line.slice(0, cursorCol);\n const start = before.length - prefix.length;\n const nextLine = line.slice(0, start) + item.value + line.slice(cursorCol);\n const nextLines = [...lines];\n nextLines[cursorLine] = nextLine;\n return {\n lines: nextLines,\n cursorLine,\n cursorCol: start + item.value.length,\n };\n }\n return this.primary.applyCompletion(lines, cursorLine, cursorCol, item, prefix);\n }\n\n shouldTriggerFileCompletion(\n lines: string[],\n cursorLine: number,\n cursorCol: number,\n ): boolean {\n return this.primary.shouldTriggerFileCompletion?.(lines, cursorLine, cursorCol) ?? false;\n }\n}\n\nexport class WrappedAutocompleteProvider implements AutocompleteProvider {\n constructor(\n private readonly baseProvider: AutocompleteProvider,\n private readonly factories: TuiAutocompleteProviderFactory[],\n ) {}\n\n private currentProvider(): AutocompleteProvider {\n let provider = this.baseProvider as TuiAutocompleteProviderApi;\n const triggerCharacters: string[] = [];\n for (const factory of this.factories) {\n provider = factory(provider);\n triggerCharacters.push(...(provider.triggerCharacters ?? []));\n }\n if (triggerCharacters.length > 0) {\n provider.triggerCharacters = [...new Set(triggerCharacters)];\n }\n return provider as AutocompleteProvider;\n }\n\n getSuggestions(\n lines: string[],\n cursorLine: number,\n cursorCol: number,\n options: { signal: AbortSignal; force?: boolean },\n ): Promise<AutocompleteSuggestions | null> {\n return this.currentProvider().getSuggestions(lines, cursorLine, cursorCol, options);\n }\n\n applyCompletion(\n lines: string[],\n cursorLine: number,\n cursorCol: number,\n item: AutocompleteItem,\n prefix: string,\n ): { lines: string[]; cursorLine: number; cursorCol: number } {\n return this.currentProvider().applyCompletion(lines, cursorLine, cursorCol, item, prefix);\n }\n\n shouldTriggerFileCompletion(\n lines: string[],\n cursorLine: number,\n cursorCol: number,\n ): boolean {\n return this.currentProvider().shouldTriggerFileCompletion?.(lines, cursorLine, cursorCol) ?? false;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"autocomplete.js","names":[],"sources":["../../../../src/tui/extension-host/autocomplete.ts"],"sourcesContent":["import type {\n AutocompleteItem,\n AutocompleteProvider,\n AutocompleteSuggestions,\n} from '@earendil-works/pi-tui';\n\nimport type {\n TuiAutocompleteProvider,\n TuiAutocompleteProviderApi,\n TuiAutocompleteProviderFactory,\n} from '../../extensions/types/tui.js';\n\nexport interface ExtensionSlashCommandAutocompleteItem {\n originalName?: string;\n name: string;\n description: string;\n}\n\nexport function dedupeAutocompleteItems(items: AutocompleteItem[]): AutocompleteItem[] {\n const seen = new Set<string>();\n return items.filter((item) => {\n if (seen.has(item.value)) return false;\n seen.add(item.value);\n return true;\n });\n}\n\nexport class ChainedAutocompleteProvider implements AutocompleteProvider {\n constructor(\n private readonly primary: AutocompleteProvider,\n private readonly extraProviders: TuiAutocompleteProvider[],\n private readonly extensionSlashCommands: ExtensionSlashCommandAutocompleteItem[],\n private readonly baseSlashCommandNames: Set<string>,\n private readonly getSessionKey: () => string,\n private readonly cwd: string,\n private readonly additionalSlashCommands: ExtensionSlashCommandAutocompleteItem[] = [],\n ) {}\n\n async getSuggestions(\n lines: string[],\n cursorLine: number,\n cursorCol: number,\n options: { signal: AbortSignal; force?: boolean },\n ): Promise<AutocompleteSuggestions | null> {\n const primary = await this.primary.getSuggestions(lines, cursorLine, cursorCol, options);\n\n const line = lines[cursorLine] ?? '';\n const beforeCursor = line.slice(0, cursorCol);\n\n const slashMatch = beforeCursor.match(/^\\/([\\w:-]*)$/);\n const slashCommands = [...this.additionalSlashCommands, ...this.extensionSlashCommands];\n if (slashMatch && slashCommands.length > 0) {\n const query = (slashMatch[1] ?? '').toLowerCase();\n const prefix = `/${slashMatch[1] ?? ''}`;\n const items: AutocompleteItem[] = slashCommands\n .filter((c) => !this.baseSlashCommandNames.has(c.originalName ?? c.name))\n .filter((c) => !query || c.name.toLowerCase().startsWith(query))\n .map((c) => ({\n value: `/${c.name}`,\n label: c.name,\n description: c.description,\n }));\n if (items.length > 0) {\n const merged = primary?.items ? [...primary.items, ...items] : items;\n const seen = new Set<string>();\n const deduped = merged.filter((item) => {\n if (seen.has(item.value)) return false;\n seen.add(item.value);\n return true;\n });\n return { prefix, items: deduped.slice(0, 30) };\n }\n }\n\n const atMatch = beforeCursor.match(/@([^\\s]*)$/);\n if (!atMatch) {\n return primary;\n }\n\n const query = atMatch[1] ?? '';\n const prefix = `@${query}`;\n const sessionKey = this.getSessionKey();\n const items: AutocompleteItem[] = [];\n\n for (const provider of this.extraProviders) {\n const suggestions = await provider(query, { cwd: this.cwd, sessionKey });\n for (const s of suggestions) {\n const value = s.value ?? `@${s.name}`;\n items.push({\n value,\n label: s.label ?? s.name,\n description: s.description,\n });\n }\n }\n\n if (items.length === 0) {\n return primary;\n }\n\n const primaryItems = primary?.prefix.startsWith('@') ? primary.items : [];\n const merged = dedupeAutocompleteItems([...primaryItems, ...items]);\n\n return {\n prefix: primary?.prefix.startsWith('@') ? primary.prefix : prefix,\n items: merged.slice(0, 30),\n };\n }\n\n applyCompletion(\n lines: string[],\n cursorLine: number,\n cursorCol: number,\n item: AutocompleteItem,\n prefix: string,\n ) {\n if (prefix.startsWith('/') && item.value.startsWith('/')) {\n const line = lines[cursorLine] ?? '';\n const before = line.slice(0, cursorCol);\n const start = before.length - prefix.length;\n const nextLine = line.slice(0, start) + item.value + line.slice(cursorCol);\n const nextLines = [...lines];\n nextLines[cursorLine] = nextLine;\n return {\n lines: nextLines,\n cursorLine,\n cursorCol: start + item.value.length,\n };\n }\n if (prefix.startsWith('@')) {\n const line = lines[cursorLine] ?? '';\n const before = line.slice(0, cursorCol);\n const start = before.length - prefix.length;\n const suffix = item.value.startsWith('@file:') && !item.value.endsWith('/') ? ' ' : '';\n const nextLine = line.slice(0, start) + item.value + suffix + line.slice(cursorCol);\n const nextLines = [...lines];\n nextLines[cursorLine] = nextLine;\n return {\n lines: nextLines,\n cursorLine,\n cursorCol: start + item.value.length + suffix.length,\n };\n }\n return this.primary.applyCompletion(lines, cursorLine, cursorCol, item, prefix);\n }\n\n shouldTriggerFileCompletion(\n lines: string[],\n cursorLine: number,\n cursorCol: number,\n ): boolean {\n return this.primary.shouldTriggerFileCompletion?.(lines, cursorLine, cursorCol) ?? false;\n }\n}\n\nexport class WrappedAutocompleteProvider implements AutocompleteProvider {\n constructor(\n private readonly baseProvider: AutocompleteProvider,\n private readonly factories: TuiAutocompleteProviderFactory[],\n ) {}\n\n private currentProvider(): AutocompleteProvider {\n let provider = this.baseProvider as TuiAutocompleteProviderApi;\n const triggerCharacters: string[] = [];\n for (const factory of this.factories) {\n provider = factory(provider);\n triggerCharacters.push(...(provider.triggerCharacters ?? []));\n }\n if (triggerCharacters.length > 0) {\n provider.triggerCharacters = [...new Set(triggerCharacters)];\n }\n return provider as AutocompleteProvider;\n }\n\n getSuggestions(\n lines: string[],\n cursorLine: number,\n cursorCol: number,\n options: { signal: AbortSignal; force?: boolean },\n ): Promise<AutocompleteSuggestions | null> {\n return this.currentProvider().getSuggestions(lines, cursorLine, cursorCol, options);\n }\n\n applyCompletion(\n lines: string[],\n cursorLine: number,\n cursorCol: number,\n item: AutocompleteItem,\n prefix: string,\n ): { lines: string[]; cursorLine: number; cursorCol: number } {\n return this.currentProvider().applyCompletion(lines, cursorLine, cursorCol, item, prefix);\n }\n\n shouldTriggerFileCompletion(\n lines: string[],\n cursorLine: number,\n cursorCol: number,\n ): boolean {\n return this.currentProvider().shouldTriggerFileCompletion?.(lines, cursorLine, cursorCol) ?? false;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { init_paths, resolveExtensionsDir } from "../../config/paths.js";
|
|
2
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
3
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { init_paths, resolveExtensionsDir } from "../../config/paths.js";
|
|
4
4
|
import { loadConfig } from "../../config/loader.js";
|
|
5
5
|
import { ExtensionLoader } from "../../extensions/loader.js";
|
|
6
6
|
import { getWorkspacePath } from "../../config/workspace-path-helpers.js";
|