@xopcai/xopc 0.0.242 → 0.0.244
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/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-MU5XrVv8.js → activity-store-CAah-_8h.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-B_Wc0wuL.js → agent-avatar-dicebear-BhXGsupm.js} +1 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-Blzn2H6t.js +1 -0
- package/dist/gateway/static/root/assets/agents-Cmp-z8Y_.js +1 -0
- package/dist/gateway/static/root/assets/{api-DLyc8BQp.js → api-B2tKxbcz.js} +1 -1
- package/dist/gateway/static/root/assets/app-management-settings-panel-CezjAP1K.js +1 -0
- package/dist/gateway/static/root/assets/{appearance-settings-DB5gEQhN.js → appearance-settings-C-CfS05x.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-7Y13_bqZ.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-BOx0EJZs.js → archive-plugin-BmSx7wzY.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-CYnYIyLr.js → attachment-load-DI4CoIga.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-ChTflpmA.js → automations-page-D04Xceck.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-wEO1OWk0.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-BjbLfNwG.js → binary-plugins-BJQe8TRu.js} +1 -1
- package/dist/gateway/static/root/assets/block-editor-BSzGjJC6.js +185 -0
- package/dist/gateway/static/root/assets/browser-settings-page-DjAZ_LF2.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-DGQxD0vD.js → browser-workflow-inputs-CRnkgZHI.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-B9gfdd7L.js → browser-workflows-page-CwbxA3B7.js} +2 -2
- package/dist/gateway/static/root/assets/{button-CSEbl4zT.js → button-CtTvuElV.js} +1 -1
- package/dist/gateway/static/root/assets/capabilities-settings-panel-jt9bqUMK.js +7 -0
- package/dist/gateway/static/root/assets/channels-settings-Cz_TWY3a.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-TkU42f-W.js → channels-status-swr-DuY4MGxe.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-CWMPcnoN.js → chat-terminal-dock-D3gj2D3U.js} +2 -2
- package/dist/gateway/static/root/assets/connectors-page-Shs5vbzx.js +2 -0
- package/dist/gateway/static/root/assets/{cron-expression-3h3rR0cf.js → cron-expression-DgWHw0jX.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-Bz1sLBEx.js → date-picker-CKg-RPbs.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-p9DWR8uU.js → dependency-picker-CVYkw-NN.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-D1TDB_gR.js → desktop-pet-Bf46oXTY.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-DWPZpoB7.js → desktop-pet-settings-BJO_klc7.js} +1 -1
- package/dist/gateway/static/root/assets/dist-CpzYSoz7.js +1 -0
- package/dist/gateway/static/root/assets/{dist-DaxPZj9e.js → dist-DBS3OB8K.js} +1 -1
- package/dist/gateway/static/root/assets/dist-DLmwHyAh.js +1 -0
- package/dist/gateway/static/root/assets/es2015-BvLh9GaE.js +41 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-BrRbK2rJ.js → extension-debug-page-T2PmFFOW.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CD65czfS.js → extension-page-2wAE2RCe.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BRDDKhpi.js → extension-settings-page-Y9ZiCJ21.js} +1 -1
- package/dist/gateway/static/root/assets/{files-DQjhZjr2.js → files-D6vf3S30.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-CjbBsr5M.js → gateway-config-api-DaYY1Gkn.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-HT7sLeO9.js → gateway-config-swr-BC3pgb_P.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-BQjmfYD4.js → gateway-settings-eO3IzW_J.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-iBCtaAuT.js → gateway-startup-retry-uMcSfLru.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-BzZxLgrw.js → heartbeat-settings-BAgrkyHc.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-GTjKH7LK.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-dj9TNEn2.js → image-generation-api-D1qlQA-A.js} +1 -1
- package/dist/gateway/static/root/assets/index-DUz0O54y.js +71 -0
- package/dist/gateway/static/root/assets/index-Dbh5SXyV.css +2 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BEnuEPD3.js → keyboard-shortcuts-settings-CWGqL6o5.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-DKJ-rks0.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-DXQtppWq.js → local-apps-page-Bfidv29d.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-DVzTJSj2.js → locale-store-CMZljTJx.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-DwAHrPbF.js +2 -0
- package/dist/gateway/static/root/assets/{management-settings-DIpBMWrA.js → management-settings-BG7j1I9f.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-BFHyGwNF.js → markdown-split-AnmmpLs6.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-DR3yVwtV.js → markdown-view-PPCLt7fu.js} +3 -3
- package/dist/gateway/static/root/assets/{media-plugins-BjjMxC5_.js → media-plugins-CGS-05cE.js} +1 -1
- package/dist/gateway/static/root/assets/messages-CTSgFlE4.js +3 -0
- package/dist/gateway/static/root/assets/mobile-pairing-wizard-DoKK5GfV.js +1 -0
- package/dist/gateway/static/root/assets/models-hub-cache-ZrbGRiGY.js +1 -0
- package/dist/gateway/static/root/assets/{notes-page-BbvtelJa.js → notes-page-Lr8rsFAR.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-ISWnKLxO.js +4 -0
- package/dist/gateway/static/root/assets/{oauth-api-BB-VYJ5j.js → oauth-api-4VeMbkTJ.js} +1 -1
- package/dist/gateway/static/root/assets/popover-select-C-Hj-nXR.js +1 -0
- package/dist/gateway/static/root/assets/{product-delivery-dUJgmBQZ.js → product-delivery-CV4pDOtG.js} +1 -1
- package/dist/gateway/static/root/assets/product-open-page-BU0HiZtv.js +1 -0
- package/dist/gateway/static/root/assets/project-detail-page-BZqr4yam.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-Dau8733A.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-DXsR8oGN.js → registry-api-CWOtPFrE.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-DdChlvGP.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DoEfLjPB.js → runtime-tools-settings-panel-CmZTNv1W.js} +2 -2
- package/dist/gateway/static/root/assets/{schema-form-BsqpbBDv.js → schema-form-XlVPyiVQ.js} +1 -1
- package/dist/gateway/static/root/assets/{schemas-zIBW3wiV.js → schemas-BHS7bo06.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-C3kADsd4.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-CSYy6SUa.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-CE7ZcCTK.js → settings-page-DblUeM3V.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-CGlne9i0.js → setup-status-panel-bDfRfSnq.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-Bn0qMX8V.js → share-preview-page-DBMWFMN-.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-Bu6lIStj.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-BNMc4l04.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-dRkeYh5P.js → skills-page-CSOseeQe.js} +1 -1
- package/dist/gateway/static/root/assets/skills-page.utils-CniRGhkJ.js +1 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-C0ZCuCM4.js → system-settings-panel-D0GqNpKy.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-BRCq-nR7.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-Cth-eChE.js → theme-store-uxUwr10D.js} +1 -1
- package/dist/gateway/static/root/assets/tunnel-api-BtjS2nrM.js +1 -0
- package/dist/gateway/static/root/assets/{use-autosave-PSV89QuQ.js → use-autosave-TwuAycG8.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-CbqPu8xZ.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-DXWdJ8cR.js → voice-api-key-field-CzwG5plu.js} +1 -1
- package/dist/gateway/static/root/assets/voice-config-api-MqyI6cgq.js +1 -0
- package/dist/gateway/static/root/assets/work-discovery-overlay-DS15FzQA.js +1 -0
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-C_boCemi.js +3 -0
- package/dist/gateway/static/root/assets/workflows-page-CaI2ruyy.js +5 -0
- package/dist/gateway/static/root/index.html +21 -22
- package/dist/package.js +1 -1
- package/dist/packages/realtime-protocol/src/voice-audio.js +20 -0
- package/dist/packages/realtime-protocol/src/voice.js +208 -0
- package/dist/src/agent/agent-manager.js +4 -4
- package/dist/src/agent/background-review/run-background-review.js +1 -1
- package/dist/src/agent/embedded/model-runtime.js +1 -1
- package/dist/src/agent/embedded/run-for-session.d.ts +1 -0
- package/dist/src/agent/embedded/run-for-session.js +3 -2
- package/dist/src/agent/image/tool-model-config.js +1 -1
- package/dist/src/agent/inbound/turn-dispatcher.d.ts +1 -0
- package/dist/src/agent/inbound/turn-dispatcher.js +2 -1
- package/dist/src/agent/ipc/inbox.js +1 -1
- package/dist/src/agent/mcp/oauth/mcp-oauth-store.js +1 -1
- package/dist/src/agent/prompt/voice-presentation.d.ts +2 -0
- package/dist/src/agent/prompt/voice-presentation.js +12 -0
- package/dist/src/agent/service/direct-turn-helpers.d.ts +1 -0
- package/dist/src/agent/service/direct-turn-helpers.js +1 -0
- package/dist/src/agent/service/process-direct-streaming.d.ts +1 -0
- package/dist/src/agent/service/process-direct-streaming.js +2 -1
- package/dist/src/agent/service.js +2 -2
- package/dist/src/agent/session/session-config-service.js +4 -2
- package/dist/src/agent/session/session-inspector.js +1 -1
- package/dist/src/agent/skills/hub-lock.js +1 -1
- package/dist/src/agent/tasks/task-judge-service.js +3 -3
- 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 +1 -1
- package/dist/src/auth/sync-provider-auth.js +2 -2
- package/dist/src/browser/providers/browser-ext-install.js +1 -1
- package/dist/src/cli/commands/agent.js +2 -2
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
- package/dist/src/cli/commands/models.js +2 -2
- package/dist/src/cli/commands/onboard.js +1 -1
- package/dist/src/cli/commands/profile.js +1 -1
- package/dist/src/cli/commands/tunnel.js +1 -1
- package/dist/src/cli/commands/update.js +1 -1
- package/dist/src/cli/extension-cli-register.js +1 -1
- package/dist/src/config/index.js +5 -5
- package/dist/src/config/loader.js +1 -1
- package/dist/src/config/models-json.d.ts +8 -8
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/config/schema.d.ts +60 -0
- package/dist/src/config/schema.js +31 -1
- package/dist/src/extensions/lockfile.js +1 -1
- package/dist/src/files/file-service.d.ts +1 -0
- package/dist/src/files/file-service.js +4 -0
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/chat-stream/thinking-delta-coalescer.js +8 -3
- package/dist/src/gateway/file-path-classifier.js +1 -1
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -11
- package/dist/src/gateway/hono/lib/config-payload.js +3 -3
- package/dist/src/gateway/hono/lib/safe-voice-config.d.ts +14 -0
- package/dist/src/gateway/hono/lib/safe-voice-config.js +29 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +2 -2
- package/dist/src/gateway/hono/routes/connectors.js +23 -23
- package/dist/src/gateway/hono/routes/files.js +7 -0
- package/dist/src/gateway/hono/routes/lazy-fallback.js +18 -4
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/hono/routes/session-input-handler.js +14 -0
- package/dist/src/gateway/hono/routes/sessions.js +3 -0
- package/dist/src/gateway/hono/routes/voice.js +139 -2
- package/dist/src/gateway/run-loop.js +1 -1
- package/dist/src/gateway/server.js +1 -0
- package/dist/src/gateway/service/agent-runner.d.ts +1 -0
- package/dist/src/gateway/service/agent-runner.js +1 -6
- package/dist/src/gateway/service/config-coordinator.js +1 -1
- package/dist/src/gateway/service/run-gateway-agent.d.ts +1 -0
- package/dist/src/gateway/service/run-gateway-agent.js +19 -1
- package/dist/src/gateway/service.d.ts +2 -0
- package/dist/src/gateway/service.js +78 -5
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/media-understanding/types.d.ts +61 -0
- package/dist/src/providers/auth-runtime/resolve-auth.js +1 -1
- package/dist/src/providers/index.js +2 -2
- package/dist/src/providers/model-registry.js +1 -1
- package/dist/src/providers/register-runtime-providers.js +1 -1
- package/dist/src/session/client-history.js +12 -0
- package/dist/src/session/manager.d.ts +1 -0
- package/dist/src/session/session-context-for-llm.js +8 -0
- package/dist/src/session/store.d.ts +1 -0
- package/dist/src/session/store.js +1 -0
- package/dist/src/session/stored-rows-to-file-entries.js +5 -1
- package/dist/src/session/voice-transcript.d.ts +9 -0
- package/dist/src/session/voice-transcript.js +45 -0
- package/dist/src/share/hosted-session-share.js +1 -1
- package/dist/src/storage/sqlite/config-repository.js +9 -0
- package/dist/src/storage/sqlite/remote-context-repository.d.ts +3 -0
- package/dist/src/storage/sqlite/remote-context-repository.js +40 -0
- package/dist/src/storage/sqlite/session-repository.js +13 -0
- package/dist/src/storage/sqlite/user-context-repository.d.ts +3 -1
- package/dist/src/storage/sqlite/user-context-repository.js +50 -4
- package/dist/src/tui/tui-startup-resources.js +1 -1
- package/dist/src/tui/tui.js +3 -2
- package/dist/src/user-context/automatic-context.d.ts +17 -0
- package/dist/src/user-context/automatic-context.js +85 -0
- package/dist/src/user-context/changes.d.ts +7 -0
- package/dist/src/user-context/changes.js +28 -0
- package/dist/src/user-context/planner.js +1 -24
- package/dist/src/user-context/retriever.js +10 -11
- package/dist/src/user-context/selection-policy.d.ts +20 -0
- package/dist/src/user-context/selection-policy.js +33 -0
- package/dist/src/user-context/sources/index.js +2 -2
- package/dist/src/user-context/sources/repository.d.ts +2 -1
- package/dist/src/user-context/sources/repository.js +26 -5
- package/dist/src/voice/dashscope/streaming-stt-session.d.ts +2 -0
- package/dist/src/voice/dashscope/streaming-stt-session.js +249 -0
- package/dist/src/voice/dashscope/streaming-tts-stream.d.ts +12 -0
- package/dist/src/voice/dashscope/streaming-tts-stream.js +153 -0
- package/dist/src/voice/realtime/agentEngine.d.ts +10 -0
- package/dist/src/voice/realtime/agentEngine.js +403 -0
- package/dist/src/voice/realtime/audio-playback-window.d.ts +9 -0
- package/dist/src/voice/realtime/audio-playback-window.js +49 -0
- package/dist/src/voice/realtime/conversation-context.d.ts +11 -0
- package/dist/src/voice/realtime/conversation-context.js +76 -0
- package/dist/src/voice/realtime/engine.d.ts +13 -0
- package/dist/src/voice/realtime/engine.js +1 -0
- package/dist/src/voice/realtime/memory-context.d.ts +17 -0
- package/dist/src/voice/realtime/memory-context.js +100 -0
- package/dist/src/voice/realtime/omniEngine.d.ts +18 -0
- package/dist/src/voice/realtime/omniEngine.js +443 -0
- package/dist/src/voice/realtime/omniRoute.d.ts +10 -0
- package/dist/src/voice/realtime/omniRoute.js +31 -0
- package/dist/src/voice/realtime/runtime.d.ts +99 -0
- package/dist/src/voice/realtime/runtime.js +622 -0
- package/dist/src/voice/realtime/speakable-segmenter.d.ts +10 -0
- package/dist/src/voice/realtime/speakable-segmenter.js +87 -0
- package/dist/src/voice/stt/list-providers.js +2 -1
- package/dist/src/voice/stt/providers/alibaba-transcription.js +13 -1
- package/dist/src/voice/stt/providers/xopc-cloud-transcription.js +23 -0
- package/dist/src/voice/tts/factory.js +1 -0
- package/dist/src/voice/tts/openai-compatible-speech.js +3 -1
- package/dist/src/voice/tts/providers/alibaba-speech.d.ts +1 -5
- package/dist/src/voice/tts/providers/alibaba-speech.js +25 -8
- package/dist/src/voice/tts/providers/edge-speech.js +21 -22
- package/dist/src/voice/tts/providers/minimax-speech.js +6 -3
- package/dist/src/voice/tts/providers/xopc-cloud-speech.js +26 -1
- package/dist/src/voice/tts/speak-core.d.ts +6 -2
- package/dist/src/voice/tts/speak-core.js +46 -34
- package/dist/src/voice/tts/speech-provider-types.d.ts +1 -0
- package/dist/src/workflows/service/workflow-run-service.js +1 -1
- package/package.json +7 -7
- package/dist/gateway/static/root/assets/Combination-14nmIgxH.js +0 -41
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-Cf7U2aUi.js +0 -1
- package/dist/gateway/static/root/assets/agents-Ce9oOnwE.js +0 -1
- package/dist/gateway/static/root/assets/app-chrome-BeB4KgOf.js +0 -1
- package/dist/gateway/static/root/assets/app-management-settings-panel-CACOOS-a.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-BaTFOCmR.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-DK6EreCr.js +0 -6
- package/dist/gateway/static/root/assets/block-editor-DgAs5aJc.js +0 -184
- package/dist/gateway/static/root/assets/browser-settings-page-CHStw5UW.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-JGH6Kfkr.js +0 -7
- package/dist/gateway/static/root/assets/channels-settings-YkUaaWkY.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-BI0FG3gA.js +0 -2
- package/dist/gateway/static/root/assets/dist-BPoKqzeH.js +0 -1
- package/dist/gateway/static/root/assets/dist-DqPZM2MH.js +0 -1
- package/dist/gateway/static/root/assets/home-page--9fKq0mL.js +0 -1
- package/dist/gateway/static/root/assets/index-D499B1qS.css +0 -2
- package/dist/gateway/static/root/assets/index-J3FsIvTs.js +0 -70
- package/dist/gateway/static/root/assets/local-app-workbench-page-FqG00zS1.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-c6CfZ8PA.js +0 -2
- package/dist/gateway/static/root/assets/messages-_tYhRAHD.js +0 -3
- package/dist/gateway/static/root/assets/mobile-pairing-wizard-CHnXZTwb.js +0 -1
- package/dist/gateway/static/root/assets/models-hub-cache-DiXjKuuY.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-DIR37b-K.js +0 -4
- package/dist/gateway/static/root/assets/popover-select-DrILF6mR.js +0 -1
- package/dist/gateway/static/root/assets/product-open-page-CRm9Q66h.js +0 -1
- package/dist/gateway/static/root/assets/project-detail-page-DHiLTiRW.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-God7NCcI.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-YpF0-mx2.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-CP8O1TxR.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-DzdbK3j9.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-B7NeVl4g.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-DDTmi4a7.js +0 -1
- package/dist/gateway/static/root/assets/skills-page.utils--q8p7MAn.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-yiMzii2b.js +0 -1
- package/dist/gateway/static/root/assets/tunnel-api-CC3jOB4n.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-Vtwg7fQc.js +0 -1
- package/dist/gateway/static/root/assets/voice-config-api-BDoeXgww.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-overlay-BV_Jj5iD.js +0 -1
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-DNHbWGPq.js +0 -3
- package/dist/gateway/static/root/assets/workflows-page-BkFIbMrz.js +0 -5
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { consumeContextConsent, ensureContextConsent, getUserProfile, listCollaborationRules, listUnderstandingEvidence, listUnderstandings, recordContextRun } from "../storage/sqlite/user-context-repository.js";
|
|
2
|
-
import { retrievalLexicalSimilarity } from "../retrieval/textFeatures.js";
|
|
3
2
|
import { buildRetrievalQueryProfile } from "../retrieval/queryProfile.js";
|
|
4
3
|
import "../storage/sqlite/index.js";
|
|
5
4
|
import { init_session_key, parseSessionKey } from "../routing/session-key.js";
|
|
@@ -9,6 +8,7 @@ import { buildUserContextBlock } from "../agent/memory/context-fence.js";
|
|
|
9
8
|
import { getUnderstandingSourceGrant, getUnderstandingSourceRun, listUserFocuses } from "./sources/repository.js";
|
|
10
9
|
import { matchesUserContextScope } from "./scope.js";
|
|
11
10
|
import { UserUnderstandingRetriever } from "./retriever.js";
|
|
11
|
+
import { focusRejectionReason, focusScore, rejectionReason } from "./selection-policy.js";
|
|
12
12
|
import { randomUUID } from "node:crypto";
|
|
13
13
|
//#region src/user-context/planner.ts
|
|
14
14
|
init_session_key();
|
|
@@ -103,35 +103,12 @@ function focusSourceDescription(focus) {
|
|
|
103
103
|
label: "Suggested from prior work"
|
|
104
104
|
};
|
|
105
105
|
}
|
|
106
|
-
function rejectionReason(item, input, now, timeHints) {
|
|
107
|
-
const historical = timeHints.includes("historical") && item.validTo !== void 0;
|
|
108
|
-
if (item.status === "needs_review" || item.status === "candidate" || item.status === "stale" && !historical) return "needs_review";
|
|
109
|
-
if (item.status === "rejected" || item.status === "archived" && !historical) return "disabled";
|
|
110
|
-
if (!matchesUserContextScope(item.scope, input)) return "scope_mismatch";
|
|
111
|
-
if (item.validFrom && item.validFrom > now && !timeHints.includes("future")) return "not_yet_valid";
|
|
112
|
-
if ((item.validTo && item.validTo < now || item.expiresAt && item.expiresAt < now) && !historical) return "expired";
|
|
113
|
-
if (item.sensitivity === "secret" || item.sensitivity === "regulated") return "sensitive";
|
|
114
|
-
if (item.conflictGroupId) return "conflict";
|
|
115
|
-
}
|
|
116
106
|
function ruleMatches(rule, input) {
|
|
117
107
|
if (rule.status !== "active" || !matchesUserContextScope(rule.scope, input)) return false;
|
|
118
108
|
const channel = typeof rule.conditions.channel === "string" ? rule.conditions.channel : void 0;
|
|
119
109
|
const agentId = typeof rule.conditions.agentId === "string" ? rule.conditions.agentId : void 0;
|
|
120
110
|
return (!channel || channel === input.channel) && (!agentId || agentId === input.agentId);
|
|
121
111
|
}
|
|
122
|
-
function focusRejectionReason(focus, input, now) {
|
|
123
|
-
if (focus.status !== "active") return "disabled";
|
|
124
|
-
if (!matchesUserContextScope(focus.scope, input)) return "scope_mismatch";
|
|
125
|
-
if (focus.validFrom && focus.validFrom > now) return "not_yet_valid";
|
|
126
|
-
if (focus.validTo && focus.validTo < now) return "expired";
|
|
127
|
-
if (focus.sensitivity === "secret" || focus.sensitivity === "regulated") return "sensitive";
|
|
128
|
-
if (focus.disclosurePolicy === "ask_before_reference") return "requires_consent";
|
|
129
|
-
}
|
|
130
|
-
function focusScore(focus, query, scopeInput) {
|
|
131
|
-
const lexical = retrievalLexicalSimilarity(buildRetrievalQueryProfile(query, scopeInput).normalized, `${focus.title} ${focus.summary}`);
|
|
132
|
-
const scoped = focus.scope.type !== "global" && matchesUserContextScope(focus.scope, scopeInput);
|
|
133
|
-
return Math.min(1, lexical * .75 + focus.confidence * .15 + (scoped ? .25 : 0));
|
|
134
|
-
}
|
|
135
112
|
function renderContextBlock(params) {
|
|
136
113
|
const understandingItems = params.items.filter((item) => item.objectType === "understanding");
|
|
137
114
|
return [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { summarizeUnderstandingFeedback } from "../storage/sqlite/user-context-quality-repository.js";
|
|
2
|
-
import {
|
|
2
|
+
import { listUnderstandings, searchActiveUnderstandings, understandingSourceBuckets } from "../storage/sqlite/user-context-repository.js";
|
|
3
3
|
import { normalizeRetrievalText, retrievalLexicalSimilarity } from "../retrieval/textFeatures.js";
|
|
4
4
|
import { buildRetrievalQueryProfile } from "../retrieval/queryProfile.js";
|
|
5
5
|
import "../storage/sqlite/index.js";
|
|
@@ -32,23 +32,18 @@ function temporalAdjustment(item, hints, now) {
|
|
|
32
32
|
}
|
|
33
33
|
return score;
|
|
34
34
|
}
|
|
35
|
-
function sourceBucket(item) {
|
|
36
|
-
if (item.explicitness === "explicit") return "user";
|
|
37
|
-
const evidence = listUnderstandingEvidence(item.id)[0];
|
|
38
|
-
if (!evidence) return `unknown:${item.id}`;
|
|
39
|
-
if (evidence.sourceInstanceId) return `${evidence.sourceType}:${evidence.sourceInstanceId}`;
|
|
40
|
-
return `${evidence.sourceType}:${evidence.sourceRef.split(":entry:")[0]}`;
|
|
41
|
-
}
|
|
42
35
|
function diversify(results, limit) {
|
|
43
36
|
const remaining = [...results];
|
|
44
37
|
const selected = [];
|
|
45
38
|
const sourceCounts = /* @__PURE__ */ new Map();
|
|
46
|
-
const
|
|
39
|
+
const redundancies = /* @__PURE__ */ new Map();
|
|
40
|
+
const evidenceBuckets = understandingSourceBuckets(results.filter((result) => result.understanding.explicitness !== "explicit").map((result) => result.understanding.id));
|
|
41
|
+
const sourceBuckets = new Map(results.map(({ understanding: item }) => [item.id, item.explicitness === "explicit" ? "user" : evidenceBuckets.get(item.id) ?? `unknown:${item.id}`]));
|
|
47
42
|
while (remaining.length && selected.length < limit) {
|
|
48
43
|
let bestIndex = 0;
|
|
49
44
|
let bestScore = Number.NEGATIVE_INFINITY;
|
|
50
45
|
for (const [index, candidate] of remaining.entries()) {
|
|
51
|
-
const redundancy =
|
|
46
|
+
const redundancy = redundancies.get(candidate.understanding.id) ?? 0;
|
|
52
47
|
const bucket = sourceBuckets.get(candidate.understanding.id);
|
|
53
48
|
const sourcePenalty = candidate.understanding.explicitness === "explicit" ? 0 : (sourceCounts.get(bucket) ?? 0) * .04;
|
|
54
49
|
const adjusted = candidate.score - redundancy * .18 - sourcePenalty;
|
|
@@ -65,6 +60,10 @@ function diversify(results, limit) {
|
|
|
65
60
|
score: Math.max(0, bestScore),
|
|
66
61
|
reasons: bestScore < candidate.score ? [...candidate.reasons, "diversified"] : candidate.reasons
|
|
67
62
|
});
|
|
63
|
+
if (selected.length < limit) for (const remainingItem of remaining) {
|
|
64
|
+
const id = remainingItem.understanding.id;
|
|
65
|
+
redundancies.set(id, Math.max(redundancies.get(id) ?? 0, retrievalLexicalSimilarity(remainingItem.understanding.statement, candidate.understanding.statement)));
|
|
66
|
+
}
|
|
68
67
|
}
|
|
69
68
|
return selected;
|
|
70
69
|
}
|
|
@@ -90,7 +89,7 @@ var UserUnderstandingRetriever = class {
|
|
|
90
89
|
"active",
|
|
91
90
|
"archived",
|
|
92
91
|
"stale"
|
|
93
|
-
] : ["active"]]
|
|
92
|
+
] : ["active"]], void 0, recentLimit);
|
|
94
93
|
const candidates = /* @__PURE__ */ new Map();
|
|
95
94
|
for (const result of fts) candidates.set(result.understanding.id, result.understanding);
|
|
96
95
|
for (const item of recent) candidates.set(item.id, item);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { UserContextRejectionReason } from '../agent/memory/context/types.js';
|
|
2
|
+
import type { UserUnderstanding } from './domain.js';
|
|
3
|
+
import type { UserFocus } from './sources/types.js';
|
|
4
|
+
/** Automatic remote context never uses sensitive, consent-gated or weakly inferred facts. */
|
|
5
|
+
export declare function allowsAutomaticDisclosure(item: Pick<UserUnderstanding, 'sensitivity' | 'disclosurePolicy' | 'explicitness' | 'confidence'>): boolean;
|
|
6
|
+
export declare function rejectionReason(item: UserUnderstanding, input: {
|
|
7
|
+
sessionKey: string;
|
|
8
|
+
workspaceId: string;
|
|
9
|
+
projectId?: string;
|
|
10
|
+
}, now: number, timeHints: string[]): UserContextRejectionReason | undefined;
|
|
11
|
+
export declare function focusRejectionReason(focus: UserFocus, input: {
|
|
12
|
+
sessionKey: string;
|
|
13
|
+
workspaceId: string;
|
|
14
|
+
projectId?: string;
|
|
15
|
+
}, now: number): UserContextRejectionReason | undefined;
|
|
16
|
+
export declare function focusScore(focus: UserFocus, query: string, scopeInput: {
|
|
17
|
+
sessionKey: string;
|
|
18
|
+
workspaceId: string;
|
|
19
|
+
projectId?: string;
|
|
20
|
+
}): number;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { retrievalLexicalSimilarity } from "../retrieval/textFeatures.js";
|
|
2
|
+
import { buildRetrievalQueryProfile } from "../retrieval/queryProfile.js";
|
|
3
|
+
import { matchesUserContextScope } from "./scope.js";
|
|
4
|
+
//#region src/user-context/selection-policy.ts
|
|
5
|
+
/** Automatic remote context never uses sensitive, consent-gated or weakly inferred facts. */
|
|
6
|
+
function allowsAutomaticDisclosure(item) {
|
|
7
|
+
return item.sensitivity === "normal" && item.disclosurePolicy !== "ask_before_reference" && (item.explicitness !== "inferred" || item.confidence >= .8);
|
|
8
|
+
}
|
|
9
|
+
function rejectionReason(item, input, now, timeHints) {
|
|
10
|
+
const historical = timeHints.includes("historical") && item.validTo !== void 0;
|
|
11
|
+
if (item.status === "needs_review" || item.status === "candidate" || item.status === "stale" && !historical) return "needs_review";
|
|
12
|
+
if (item.status === "rejected" || item.status === "archived" && !historical) return "disabled";
|
|
13
|
+
if (!matchesUserContextScope(item.scope, input)) return "scope_mismatch";
|
|
14
|
+
if (item.validFrom && item.validFrom > now && !timeHints.includes("future")) return "not_yet_valid";
|
|
15
|
+
if ((item.validTo && item.validTo < now || item.expiresAt && item.expiresAt < now) && !historical) return "expired";
|
|
16
|
+
if (item.sensitivity === "secret" || item.sensitivity === "regulated") return "sensitive";
|
|
17
|
+
if (item.conflictGroupId) return "conflict";
|
|
18
|
+
}
|
|
19
|
+
function focusRejectionReason(focus, input, now) {
|
|
20
|
+
if (focus.status !== "active") return "disabled";
|
|
21
|
+
if (!matchesUserContextScope(focus.scope, input)) return "scope_mismatch";
|
|
22
|
+
if (focus.validFrom && focus.validFrom > now) return "not_yet_valid";
|
|
23
|
+
if (focus.validTo && focus.validTo < now) return "expired";
|
|
24
|
+
if (focus.sensitivity === "secret" || focus.sensitivity === "regulated") return "sensitive";
|
|
25
|
+
if (focus.disclosurePolicy === "ask_before_reference") return "requires_consent";
|
|
26
|
+
}
|
|
27
|
+
function focusScore(focus, query, scopeInput) {
|
|
28
|
+
const lexical = retrievalLexicalSimilarity(buildRetrievalQueryProfile(query, scopeInput).normalized, `${focus.title} ${focus.summary}`);
|
|
29
|
+
const scoped = focus.scope.type !== "global" && matchesUserContextScope(focus.scope, scopeInput);
|
|
30
|
+
return Math.min(1, lexical * .75 + focus.confidence * .15 + (scoped ? .25 : 0));
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { allowsAutomaticDisclosure, focusRejectionReason, focusScore, rejectionReason };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createUnderstandingSourceRun, deleteUserFocus, getUnderstandingSourceGrant, getUnderstandingSourceRun, listUnderstandingSourceGrants, listUnderstandingSourceRuns, listUserFocusEvidence, listUserFocuses, revokeUnderstandingSourceGrant, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceGrantPolicies, updateUnderstandingSourceRun, updateUserFocus, upsertUnderstandingSourceGrant, upsertUserFocus } from "./repository.js";
|
|
1
|
+
import { createUnderstandingSourceRun, deleteUserFocus, getUnderstandingSourceGrant, getUnderstandingSourceRun, getUserFocus, listUnderstandingSourceGrants, listUnderstandingSourceRuns, listUserFocusEvidence, listUserFocuses, revokeUnderstandingSourceGrant, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceGrantPolicies, updateUnderstandingSourceRun, updateUserFocus, upsertUnderstandingSourceGrant, upsertUserFocus } from "./repository.js";
|
|
2
2
|
import { clusterUnderstandingSignals, tokenizeUnderstandingSignal } from "./signal-clustering.js";
|
|
3
3
|
import { listUnderstandingSourceDefinitions } from "./catalog.js";
|
|
4
|
-
export { clusterUnderstandingSignals, createUnderstandingSourceRun, deleteUserFocus, getUnderstandingSourceGrant, getUnderstandingSourceRun, listUnderstandingSourceDefinitions, listUnderstandingSourceGrants, listUnderstandingSourceRuns, listUserFocusEvidence, listUserFocuses, revokeUnderstandingSourceGrant, tokenizeUnderstandingSignal, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceGrantPolicies, updateUnderstandingSourceRun, updateUserFocus, upsertUnderstandingSourceGrant, upsertUserFocus };
|
|
4
|
+
export { clusterUnderstandingSignals, createUnderstandingSourceRun, deleteUserFocus, getUnderstandingSourceGrant, getUnderstandingSourceRun, getUserFocus, listUnderstandingSourceDefinitions, listUnderstandingSourceGrants, listUnderstandingSourceRuns, listUserFocusEvidence, listUserFocuses, revokeUnderstandingSourceGrant, tokenizeUnderstandingSignal, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceGrantPolicies, updateUnderstandingSourceRun, updateUserFocus, upsertUnderstandingSourceGrant, upsertUserFocus };
|
|
@@ -54,7 +54,8 @@ export declare function updateUnderstandingSourceRun(id: string, patch: {
|
|
|
54
54
|
nowMs?: number;
|
|
55
55
|
}): UnderstandingSourceRun | null;
|
|
56
56
|
export declare function upsertUserFocus(input: UserFocusInput): UserFocus;
|
|
57
|
-
export declare function listUserFocuses(statuses?: UserFocus['status'][]): UserFocus[];
|
|
57
|
+
export declare function listUserFocuses(statuses?: UserFocus['status'][], limit?: number): UserFocus[];
|
|
58
|
+
export declare function getUserFocus(id: string): UserFocus | undefined;
|
|
58
59
|
export declare function updateUserFocus(id: string, patch: Partial<Pick<UserFocus, 'title' | 'summary' | 'status' | 'validFrom' | 'validTo' | 'reviewAt'>>, nowMs?: number): UserFocus | null;
|
|
59
60
|
export declare function deleteUserFocus(id: string): boolean;
|
|
60
61
|
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getSqliteDatabase, runSqliteWriteTransaction } from "../../storage/sqlite/transaction.js";
|
|
2
|
-
import "../domain.js";
|
|
2
|
+
import { USER_CONTEXT_PRINCIPAL_ID } from "../domain.js";
|
|
3
|
+
import { notifyUserContextChange } from "../changes.js";
|
|
3
4
|
import { focusLifecycle } from "../focus-lifecycle.js";
|
|
4
5
|
import { randomUUID } from "node:crypto";
|
|
5
6
|
//#region src/user-context/sources/repository.ts
|
|
@@ -139,6 +140,7 @@ function getUnderstandingSourceGrant(id) {
|
|
|
139
140
|
return row ? grantFromRow(row) : null;
|
|
140
141
|
}
|
|
141
142
|
function upsertUnderstandingSourceGrant(input) {
|
|
143
|
+
notifyUserContextChange({ kind: "policy" });
|
|
142
144
|
const id = randomUUID();
|
|
143
145
|
const now = input.nowMs ?? Date.now();
|
|
144
146
|
const existingRow = getSqliteDatabase().prepare("SELECT * FROM understanding_source_grants WHERE source_key = ?").get(input.sourceKey);
|
|
@@ -169,6 +171,7 @@ function updateUnderstandingSourceGrantCheckpoint(id, input) {
|
|
|
169
171
|
return getUnderstandingSourceGrant(id);
|
|
170
172
|
}
|
|
171
173
|
function updateUnderstandingSourceGrantPolicies(id, patch) {
|
|
174
|
+
notifyUserContextChange({ kind: "policy" });
|
|
172
175
|
const current = getUnderstandingSourceGrant(id);
|
|
173
176
|
if (!current) return null;
|
|
174
177
|
runSqliteWriteTransaction((db) => db.prepare(`
|
|
@@ -179,6 +182,7 @@ function updateUnderstandingSourceGrantPolicies(id, patch) {
|
|
|
179
182
|
return getUnderstandingSourceGrant(id);
|
|
180
183
|
}
|
|
181
184
|
function revokeUnderstandingSourceGrant(id, nowMs = Date.now()) {
|
|
185
|
+
notifyUserContextChange({ kind: "policy" });
|
|
182
186
|
runSqliteWriteTransaction((db) => db.prepare("UPDATE understanding_source_grants SET status = 'revoked', updated_at = ? WHERE grant_id = ?").run(nowMs, id));
|
|
183
187
|
return getUnderstandingSourceGrant(id);
|
|
184
188
|
}
|
|
@@ -218,6 +222,10 @@ function upsertUserFocus(input) {
|
|
|
218
222
|
const disclosurePolicy = input.disclosurePolicy ?? "referenceable";
|
|
219
223
|
const existingRow = getSqliteDatabase().prepare("SELECT * FROM user_focuses WHERE canonical_key = ?").get(input.canonicalKey);
|
|
220
224
|
if (existingRow?.explicitness === "explicit" && explicitness !== "explicit") return focusFromRow(existingRow);
|
|
225
|
+
if (existingRow) notifyUserContextChange({
|
|
226
|
+
kind: "focus",
|
|
227
|
+
id: existingRow.focus_id
|
|
228
|
+
});
|
|
221
229
|
let currentVersionId = existingRow?.current_version_id;
|
|
222
230
|
runSqliteWriteTransaction((db) => {
|
|
223
231
|
db.prepare(`
|
|
@@ -253,12 +261,21 @@ function upsertUserFocus(input) {
|
|
|
253
261
|
if (currentVersionId) linkFocusEvidence(currentVersionId, input.evidenceRefs, input.confidence);
|
|
254
262
|
return focusFromRow(getSqliteDatabase().prepare("SELECT * FROM user_focuses WHERE canonical_key = ?").get(input.canonicalKey));
|
|
255
263
|
}
|
|
256
|
-
function listUserFocuses(statuses) {
|
|
257
|
-
|
|
264
|
+
function listUserFocuses(statuses, limit) {
|
|
265
|
+
const maxRows = limit === void 0 ? -1 : Math.max(1, Math.min(200, Math.floor(limit)));
|
|
266
|
+
if (!statuses?.length) return getSqliteDatabase().prepare("SELECT * FROM user_focuses ORDER BY updated_at DESC LIMIT ?").all(maxRows).map(focusFromRow);
|
|
258
267
|
const placeholders = statuses.map(() => "?").join(", ");
|
|
259
|
-
return getSqliteDatabase().prepare(`SELECT * FROM user_focuses WHERE status IN (${placeholders}) ORDER BY updated_at DESC
|
|
268
|
+
return getSqliteDatabase().prepare(`SELECT * FROM user_focuses WHERE status IN (${placeholders}) ORDER BY updated_at DESC LIMIT ?`).all(...statuses, maxRows).map(focusFromRow);
|
|
269
|
+
}
|
|
270
|
+
function getUserFocus(id) {
|
|
271
|
+
const row = getSqliteDatabase().prepare("SELECT * FROM user_focuses WHERE focus_id = ? AND principal_id = ?").get(id, USER_CONTEXT_PRINCIPAL_ID);
|
|
272
|
+
return row ? focusFromRow(row) : void 0;
|
|
260
273
|
}
|
|
261
274
|
function updateUserFocus(id, patch, nowMs = Date.now()) {
|
|
275
|
+
notifyUserContextChange({
|
|
276
|
+
kind: "focus",
|
|
277
|
+
id
|
|
278
|
+
});
|
|
262
279
|
const currentRow = getSqliteDatabase().prepare("SELECT * FROM user_focuses WHERE focus_id = ?").get(id);
|
|
263
280
|
if (!currentRow) return null;
|
|
264
281
|
const current = focusFromRow(currentRow);
|
|
@@ -283,7 +300,11 @@ function updateUserFocus(id, patch, nowMs = Date.now()) {
|
|
|
283
300
|
return row ? focusFromRow(row) : null;
|
|
284
301
|
}
|
|
285
302
|
function deleteUserFocus(id) {
|
|
303
|
+
notifyUserContextChange({
|
|
304
|
+
kind: "focus",
|
|
305
|
+
id
|
|
306
|
+
});
|
|
286
307
|
return Number(getSqliteDatabase().prepare("DELETE FROM user_focuses WHERE focus_id = ?").run(id).changes) > 0;
|
|
287
308
|
}
|
|
288
309
|
//#endregion
|
|
289
|
-
export { createUnderstandingSourceRun, deleteUserFocus, getUnderstandingSourceGrant, getUnderstandingSourceRun, listUnderstandingSourceGrants, listUnderstandingSourceRuns, listUserFocusEvidence, listUserFocuses, revokeUnderstandingSourceGrant, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceGrantPolicies, updateUnderstandingSourceRun, updateUserFocus, upsertUnderstandingSourceGrant, upsertUserFocus };
|
|
310
|
+
export { createUnderstandingSourceRun, deleteUserFocus, getUnderstandingSourceGrant, getUnderstandingSourceRun, getUserFocus, listUnderstandingSourceGrants, listUnderstandingSourceRuns, listUserFocusEvidence, listUserFocuses, revokeUnderstandingSourceGrant, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceGrantPolicies, updateUnderstandingSourceRun, updateUserFocus, upsertUnderstandingSourceGrant, upsertUserFocus };
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import crypto from "node:crypto";
|
|
3
|
+
//#region src/voice/dashscope/streaming-stt-session.ts
|
|
4
|
+
const { WebSocket: NodeWebSocket } = createRequire(import.meta.url)("ws");
|
|
5
|
+
const DEFAULT_REALTIME_URL = "wss://dashscope.aliyuncs.com/api-ws/v1/inference";
|
|
6
|
+
const MAX_BUFFERED_AUDIO_BYTES = 512 * 1024;
|
|
7
|
+
function realtimeUrl(baseUrl) {
|
|
8
|
+
if (!baseUrl) return DEFAULT_REALTIME_URL;
|
|
9
|
+
const url = new URL(baseUrl);
|
|
10
|
+
const wasWebSocket = url.protocol === "ws:" || url.protocol === "wss:";
|
|
11
|
+
url.protocol = url.protocol === "http:" ? "ws:" : url.protocol === "https:" ? "wss:" : url.protocol;
|
|
12
|
+
if (url.protocol !== "ws:" && url.protocol !== "wss:") throw new Error("DashScope realtime base URL must use HTTP or WebSocket");
|
|
13
|
+
if (!wasWebSocket && !url.pathname.includes("/api-ws/")) {
|
|
14
|
+
url.pathname = "/api-ws/v1/inference";
|
|
15
|
+
url.search = "";
|
|
16
|
+
}
|
|
17
|
+
return url.toString();
|
|
18
|
+
}
|
|
19
|
+
function rawText(data) {
|
|
20
|
+
if (typeof data === "string") return data;
|
|
21
|
+
if (data instanceof ArrayBuffer) return Buffer.from(data).toString("utf8");
|
|
22
|
+
if (Array.isArray(data)) return Buffer.concat(data).toString("utf8");
|
|
23
|
+
return data.toString("utf8");
|
|
24
|
+
}
|
|
25
|
+
function providerError(message) {
|
|
26
|
+
const code = message.header?.error_code;
|
|
27
|
+
const detail = message.header?.error_message;
|
|
28
|
+
return new Error([code, detail].filter(Boolean).join(": ") || "DashScope realtime STT failed");
|
|
29
|
+
}
|
|
30
|
+
async function openDashScopeStreamingStt(request) {
|
|
31
|
+
if (!request.apiKey) throw new Error("DashScope STT API key is unavailable");
|
|
32
|
+
if (request.signal.aborted) throw request.signal.reason instanceof Error ? request.signal.reason : /* @__PURE__ */ new Error("DashScope realtime STT aborted");
|
|
33
|
+
if (request.inputFormat.encoding !== "pcm_s16le" || request.inputFormat.channels !== 1) throw new Error("DashScope realtime STT requires mono PCM16 audio");
|
|
34
|
+
const taskId = crypto.randomUUID();
|
|
35
|
+
const socket = new NodeWebSocket(realtimeUrl(request.baseUrl), {
|
|
36
|
+
headers: {
|
|
37
|
+
Authorization: `Bearer ${request.apiKey}`,
|
|
38
|
+
...request.headers
|
|
39
|
+
},
|
|
40
|
+
perMessageDeflate: false
|
|
41
|
+
});
|
|
42
|
+
let ready = false;
|
|
43
|
+
let finished = false;
|
|
44
|
+
let closing = false;
|
|
45
|
+
let currentUtteranceId;
|
|
46
|
+
let revision = 0;
|
|
47
|
+
let inputBytes = 0;
|
|
48
|
+
let failed = false;
|
|
49
|
+
let resolveReady;
|
|
50
|
+
let rejectReady;
|
|
51
|
+
const readyPromise = new Promise((resolve, reject) => {
|
|
52
|
+
resolveReady = resolve;
|
|
53
|
+
rejectReady = reject;
|
|
54
|
+
});
|
|
55
|
+
let resolveFinished;
|
|
56
|
+
const finishedPromise = new Promise((resolve) => {
|
|
57
|
+
resolveFinished = resolve;
|
|
58
|
+
});
|
|
59
|
+
const fail = (error) => {
|
|
60
|
+
if (failed) return;
|
|
61
|
+
failed = true;
|
|
62
|
+
if (!ready) rejectReady(error);
|
|
63
|
+
request.onEvent({
|
|
64
|
+
type: "error",
|
|
65
|
+
error
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
const finish = () => {
|
|
69
|
+
if (finished) return;
|
|
70
|
+
finished = true;
|
|
71
|
+
resolveFinished();
|
|
72
|
+
};
|
|
73
|
+
const closeSocket = (reason) => {
|
|
74
|
+
closing = true;
|
|
75
|
+
if (socket.readyState === NodeWebSocket.OPEN) socket.close(1e3, reason.slice(0, 120));
|
|
76
|
+
else if (socket.readyState === NodeWebSocket.CONNECTING) socket.terminate();
|
|
77
|
+
};
|
|
78
|
+
socket.on("open", () => {
|
|
79
|
+
socket.send(JSON.stringify({
|
|
80
|
+
header: {
|
|
81
|
+
action: "run-task",
|
|
82
|
+
task_id: taskId,
|
|
83
|
+
streaming: "duplex"
|
|
84
|
+
},
|
|
85
|
+
payload: {
|
|
86
|
+
task_group: "audio",
|
|
87
|
+
task: "asr",
|
|
88
|
+
function: "recognition",
|
|
89
|
+
model: request.model,
|
|
90
|
+
parameters: {
|
|
91
|
+
format: "pcm",
|
|
92
|
+
sample_rate: request.inputFormat.sampleRate,
|
|
93
|
+
semantic_punctuation_enabled: false,
|
|
94
|
+
max_sentence_silence: request.turnDetection.silenceDurationMs,
|
|
95
|
+
...request.language && request.language !== "auto" ? { language_hints: [request.language] } : {}
|
|
96
|
+
},
|
|
97
|
+
input: request.prompt ? { context: [{
|
|
98
|
+
role: "user",
|
|
99
|
+
content: [{
|
|
100
|
+
type: "input_text",
|
|
101
|
+
text: request.prompt.slice(0, 400)
|
|
102
|
+
}]
|
|
103
|
+
}] } : {}
|
|
104
|
+
}
|
|
105
|
+
}));
|
|
106
|
+
});
|
|
107
|
+
socket.on("message", (data, isBinary) => {
|
|
108
|
+
if (isBinary) return;
|
|
109
|
+
let message;
|
|
110
|
+
try {
|
|
111
|
+
message = JSON.parse(rawText(data));
|
|
112
|
+
} catch {
|
|
113
|
+
fail(/* @__PURE__ */ new Error("DashScope realtime STT returned invalid JSON"));
|
|
114
|
+
finish();
|
|
115
|
+
closeSocket("Invalid provider response");
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const event = message.header?.event;
|
|
119
|
+
if (event === "task-started") {
|
|
120
|
+
ready = true;
|
|
121
|
+
resolveReady();
|
|
122
|
+
request.onEvent({ type: "ready" });
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (event === "task-failed") {
|
|
126
|
+
fail(providerError(message));
|
|
127
|
+
finish();
|
|
128
|
+
closeSocket("Provider task failed");
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (event === "task-finished") {
|
|
132
|
+
const duration = Number(message.payload?.usage?.duration);
|
|
133
|
+
const inputAudioMs = Number.isFinite(duration) ? Math.max(0, Math.round(duration)) : Math.round(inputBytes / 2 / request.inputFormat.sampleRate * 1e3);
|
|
134
|
+
request.onEvent({
|
|
135
|
+
type: "usage",
|
|
136
|
+
inputAudioMs
|
|
137
|
+
});
|
|
138
|
+
finish();
|
|
139
|
+
closeSocket("Complete");
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (event !== "result-generated") return;
|
|
143
|
+
const sentence = message.payload?.output?.sentence;
|
|
144
|
+
if (sentence?.heartbeat === true) return;
|
|
145
|
+
const text = sentence?.text;
|
|
146
|
+
if (typeof text !== "string") return;
|
|
147
|
+
if (sentence.sentence_begin === true) {
|
|
148
|
+
currentUtteranceId = crypto.randomUUID();
|
|
149
|
+
revision = 0;
|
|
150
|
+
request.onEvent({
|
|
151
|
+
type: "speech_started",
|
|
152
|
+
utteranceId: currentUtteranceId
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
if (!currentUtteranceId) return;
|
|
156
|
+
revision += 1;
|
|
157
|
+
if (sentence.sentence_end === true) {
|
|
158
|
+
request.onEvent({
|
|
159
|
+
type: "speech_stopped",
|
|
160
|
+
utteranceId: currentUtteranceId
|
|
161
|
+
});
|
|
162
|
+
request.onEvent({
|
|
163
|
+
type: "transcript_final",
|
|
164
|
+
utteranceId: currentUtteranceId,
|
|
165
|
+
revision,
|
|
166
|
+
text,
|
|
167
|
+
...request.language ? { language: request.language } : {}
|
|
168
|
+
});
|
|
169
|
+
currentUtteranceId = void 0;
|
|
170
|
+
revision = 0;
|
|
171
|
+
} else request.onEvent({
|
|
172
|
+
type: "transcript_delta",
|
|
173
|
+
utteranceId: currentUtteranceId,
|
|
174
|
+
revision,
|
|
175
|
+
text
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
socket.on("error", (error) => {
|
|
179
|
+
fail(error);
|
|
180
|
+
finish();
|
|
181
|
+
closeSocket("Provider socket failed");
|
|
182
|
+
});
|
|
183
|
+
socket.on("close", () => {
|
|
184
|
+
request.signal.removeEventListener("abort", onAbort);
|
|
185
|
+
if (!closing && !finished) fail(/* @__PURE__ */ new Error("DashScope realtime STT connection closed unexpectedly"));
|
|
186
|
+
finish();
|
|
187
|
+
});
|
|
188
|
+
const onAbort = () => {
|
|
189
|
+
if (!ready) rejectReady(request.signal.reason instanceof Error ? request.signal.reason : /* @__PURE__ */ new Error("DashScope realtime STT aborted"));
|
|
190
|
+
finish();
|
|
191
|
+
closeSocket("Aborted");
|
|
192
|
+
};
|
|
193
|
+
request.signal.addEventListener("abort", onAbort, { once: true });
|
|
194
|
+
const timeout = setTimeout(() => {
|
|
195
|
+
fail(/* @__PURE__ */ new Error("DashScope realtime STT setup timed out"));
|
|
196
|
+
finish();
|
|
197
|
+
closeSocket("Setup timeout");
|
|
198
|
+
}, request.timeoutMs);
|
|
199
|
+
try {
|
|
200
|
+
await readyPromise;
|
|
201
|
+
} finally {
|
|
202
|
+
clearTimeout(timeout);
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
appendAudio(chunk) {
|
|
206
|
+
if (!ready || closing || finished || socket.readyState !== NodeWebSocket.OPEN) throw new Error("DashScope realtime STT is not writable");
|
|
207
|
+
if (socket.bufferedAmount + chunk.byteLength > MAX_BUFFERED_AUDIO_BYTES) throw new Error("DashScope realtime STT audio backpressure limit exceeded");
|
|
208
|
+
inputBytes += chunk.byteLength;
|
|
209
|
+
socket.send(chunk, { binary: true });
|
|
210
|
+
},
|
|
211
|
+
async commit() {
|
|
212
|
+
if (!closing && !finished) {
|
|
213
|
+
closing = true;
|
|
214
|
+
socket.send(JSON.stringify({
|
|
215
|
+
header: {
|
|
216
|
+
action: "finish-task",
|
|
217
|
+
task_id: taskId,
|
|
218
|
+
streaming: "duplex"
|
|
219
|
+
},
|
|
220
|
+
payload: { input: {} }
|
|
221
|
+
}));
|
|
222
|
+
}
|
|
223
|
+
await finishedPromise;
|
|
224
|
+
closeSocket("Complete");
|
|
225
|
+
},
|
|
226
|
+
async close() {
|
|
227
|
+
if (!closing && !finished) {
|
|
228
|
+
closing = true;
|
|
229
|
+
socket.send(JSON.stringify({
|
|
230
|
+
header: {
|
|
231
|
+
action: "finish-task",
|
|
232
|
+
task_id: taskId,
|
|
233
|
+
streaming: "duplex"
|
|
234
|
+
},
|
|
235
|
+
payload: { input: {} }
|
|
236
|
+
}));
|
|
237
|
+
}
|
|
238
|
+
await finishedPromise;
|
|
239
|
+
request.signal.removeEventListener("abort", onAbort);
|
|
240
|
+
closeSocket("Complete");
|
|
241
|
+
},
|
|
242
|
+
abort(reason) {
|
|
243
|
+
finish();
|
|
244
|
+
closeSocket(reason);
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
//#endregion
|
|
249
|
+
export { openDashScopeStreamingStt };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SpeechSynthesisStreamResult } from '../tts/speech-provider-types.js';
|
|
2
|
+
export interface DashScopeStreamingTtsRequest {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
baseUrl?: string;
|
|
5
|
+
model: string;
|
|
6
|
+
voice: string;
|
|
7
|
+
text: string;
|
|
8
|
+
instructions?: string;
|
|
9
|
+
signal: AbortSignal;
|
|
10
|
+
timeoutMs: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function openDashScopeStreamingTts(request: DashScopeStreamingTtsRequest): Promise<SpeechSynthesisStreamResult>;
|