@xopcai/xopc 0.0.241 → 0.0.243
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-CLnbVm9G.js → activity-store-CAah-_8h.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DuBewmbW.js → agent-avatar-dicebear-DDH4HgP7.js} +1 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-BDCfJZhh.js +1 -0
- package/dist/gateway/static/root/assets/agents-B0ZWgf-U.js +1 -0
- package/dist/gateway/static/root/assets/{api-DjBZe303.js → api-B2tKxbcz.js} +1 -1
- package/dist/gateway/static/root/assets/app-management-settings-panel-Blfwszzn.js +1 -0
- package/dist/gateway/static/root/assets/{appearance-settings-B-iul0RG.js → appearance-settings-C3V7Na75.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-BiEks0-F.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-Cfk1lwBo.js → attachment-load-BS-S4LJ9.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-BTSGvaeS.js → automations-page-C7Y3L30D.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-A3zPkPuo.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-ChZyZK45.js → binary-plugins-BM9B5kcm.js} +1 -1
- package/dist/gateway/static/root/assets/block-editor-BbnpkYP9.js +185 -0
- package/dist/gateway/static/root/assets/browser-settings-page-Dk4FQ7fY.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-jvfcgFG-.js → browser-workflow-inputs-CRnkgZHI.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-DrHW7XNi.js → browser-workflows-page-B9qGL-it.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--tR_El9e.js +7 -0
- package/dist/gateway/static/root/assets/channels-settings-D347vl_J.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-CC9MFway.js → channels-status-swr-DuY4MGxe.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-DeeZrVbV.js → chat-terminal-dock-DABPvwBT.js} +2 -2
- package/dist/gateway/static/root/assets/connectors-page-B-tvJkRJ.js +2 -0
- package/dist/gateway/static/root/assets/{cron-expression-CiqQOeQ3.js → cron-expression-D3bsKbNd.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-CGAMGPfU.js → date-picker-BsGM6Yty.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-CxWeUTsc.js → dependency-picker-Dj3g6YXZ.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-C3QmYO75.js → desktop-pet-C1QT0Sur.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-CAADkWYy.js → desktop-pet-settings-r6kAOnfY.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-FQXjDJ8P.js → extension-debug-page-DOkf7nh9.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BJE1D5Ji.js → extension-page-Cq2IA4Ho.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-5Ik2tNry.js → extension-settings-page-DQn4qjDZ.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-cTj71t2a.js → gateway-config-api-DM3poL22.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-Bxe_R-JH.js → gateway-config-swr-BC3pgb_P.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-KXBUjNcx.js → gateway-settings-DPgH1hnh.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-DJG-I0wW.js → gateway-startup-retry-uMcSfLru.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-C8cVzIcs.js → heartbeat-settings-Bk80-E3b.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-DKo5JiMR.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-Dc_ojQuj.js → image-generation-api-D1qlQA-A.js} +1 -1
- package/dist/gateway/static/root/assets/index-B0WJL9N1.js +71 -0
- package/dist/gateway/static/root/assets/index-Dbh5SXyV.css +2 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-pOKl7blR.js → keyboard-shortcuts-settings-BEwvd8ZU.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page--eJ5rmNj.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-Bi6wwKgm.js → local-apps-page-CgkY9E-r.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-C5wr3_pc.js → locale-store-CMZljTJx.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-Z49Td0J9.js +2 -0
- package/dist/gateway/static/root/assets/{management-settings-DGlVizWi.js → management-settings-Dv8NSJKt.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-CXP5zBx_.js → markdown-split-Cm0RBB-t.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-D6LxlDxr.js → markdown-view-PPCLt7fu.js} +3 -3
- package/dist/gateway/static/root/assets/{media-plugins-BsENGLr2.js → media-plugins-Bcr5sU1f.js} +1 -1
- package/dist/gateway/static/root/assets/messages-CTSgFlE4.js +3 -0
- package/dist/gateway/static/root/assets/mobile-pairing-wizard-kKDiXofY.js +1 -0
- package/dist/gateway/static/root/assets/{models-hub-cache-Y7GUjxHx.js → models-hub-cache-ZrbGRiGY.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-page-D2EqpDyo.js → notes-page-CgsaRaGi.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-C1DEE09k.js +4 -0
- package/dist/gateway/static/root/assets/{oauth-api-C5NVcsKE.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-isRapnp5.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-zvsjg0mi.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-FXdFaoWM.js → registry-api-CWOtPFrE.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-C9TGZ9Hc.js +1 -0
- package/dist/gateway/static/root/assets/runtime-tools-settings-panel-2zm9edMA.js +5 -0
- package/dist/gateway/static/root/assets/{schema-form-BUzdHWx6.js → schema-form-54A5gzkN.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-BP8RyiUn.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-D4EMxWAZ.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-C0OBLqpu.js → settings-page-DzDhoyxv.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-NpLQkFCh.js → setup-status-panel-uDicHU1w.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-BtbPYaYC.js → share-preview-page-lOmLCWFS.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-T4Yvouvv.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-DVb7nrXz.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-CYk8pN97.js → skills-page-CnyNH3To.js} +1 -1
- package/dist/gateway/static/root/assets/skills-page.utils-CgDtf2qs.js +1 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-DmCRSvtd.js → system-settings-panel-C8yWfwtR.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-Tzfjlbf3.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-DUko1ZnE.js → theme-store-uxUwr10D.js} +1 -1
- package/dist/gateway/static/root/assets/tunnel-api-Bvg679no.js +1 -0
- package/dist/gateway/static/root/assets/{use-autosave-W_P8Kiv4.js → use-autosave-D88VGoyG.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-RijPtyfO.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-BZD0j1jc.js → voice-api-key-field-CBHLsMcc.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-GGe2TQ98.js +1 -0
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-C0layUE9.js +3 -0
- package/dist/gateway/static/root/assets/workflows-page-DQXIzBAc.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 +1 -0
- package/dist/src/agent/embedded/run-for-session.d.ts +1 -0
- package/dist/src/agent/embedded/run-for-session.js +2 -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/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/session/session-config-service.js +4 -2
- package/dist/src/agent/skills/installer.d.ts +1 -0
- package/dist/src/agent/skills/installer.js +9 -6
- package/dist/src/agent/tools/factory.d.ts +2 -0
- package/dist/src/agent/tools/factory.js +5 -1
- package/dist/src/automations/draft/automation-draft-service.js +1 -1
- package/dist/src/config/models-json.d.ts +8 -8
- package/dist/src/config/schema.d.ts +60 -0
- package/dist/src/config/schema.js +36 -4
- package/dist/src/extensions/install.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/chat-stream/thinking-delta-coalescer.js +8 -3
- package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -11
- package/dist/src/gateway/hono/lib/config-payload.js +2 -2
- 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/files.js +7 -0
- package/dist/src/gateway/hono/routes/lazy-fallback.js +18 -4
- package/dist/src/gateway/hono/routes/runtime-tools.js +7 -1
- package/dist/src/gateway/hono/routes/session-input-handler.js +14 -0
- package/dist/src/gateway/hono/routes/sessions.js +4 -1
- package/dist/src/gateway/hono/routes/voice.js +140 -3
- 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/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 +73 -0
- package/dist/src/media-understanding/types.d.ts +61 -0
- package/dist/src/runtime-tools/archive.js +17 -3
- package/dist/src/runtime-tools/command.d.ts +1 -0
- package/dist/src/runtime-tools/command.js +29 -8
- package/dist/src/runtime-tools/environment.d.ts +1 -0
- package/dist/src/runtime-tools/environment.js +11 -16
- package/dist/src/runtime-tools/install-lock.d.ts +1 -1
- package/dist/src/runtime-tools/install-lock.js +34 -21
- package/dist/src/runtime-tools/manager.d.ts +1 -1
- package/dist/src/runtime-tools/manager.js +99 -64
- package/dist/src/runtime-tools/manifest-store.d.ts +2 -0
- package/dist/src/runtime-tools/manifest-store.js +29 -8
- package/dist/src/runtime-tools/paths.d.ts +2 -1
- package/dist/src/runtime-tools/paths.js +19 -8
- package/dist/src/runtime-tools/probe.d.ts +2 -0
- package/dist/src/runtime-tools/probe.js +13 -1
- package/dist/src/runtime-tools/prune.js +21 -7
- 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/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.js +2 -1
- 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/package.json +6 -6
- package/dist/gateway/static/root/assets/Combination-14nmIgxH.js +0 -41
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-DbdgX6AA.js +0 -1
- package/dist/gateway/static/root/assets/agents-BX3uRVm4.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-D8evZyFQ.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-CoZd_cZu.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-C8RRKT-a.js +0 -6
- package/dist/gateway/static/root/assets/block-editor-DCH9b2Ht.js +0 -184
- package/dist/gateway/static/root/assets/browser-settings-page-D1GPwIfx.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-CrXB1Q-l.js +0 -7
- package/dist/gateway/static/root/assets/channels-settings-DWMSYaNZ.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-DXTl1fNB.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-NdWtBda5.js +0 -1
- package/dist/gateway/static/root/assets/index-7i2P3312.js +0 -70
- package/dist/gateway/static/root/assets/index-DTo3IcbW.css +0 -2
- package/dist/gateway/static/root/assets/local-app-workbench-page-C_j_od5f.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-D6PDZEVP.js +0 -2
- package/dist/gateway/static/root/assets/messages-_tYhRAHD.js +0 -3
- package/dist/gateway/static/root/assets/mobile-pairing-wizard-DcEz7qcX.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-Bu0a83Oj.js +0 -4
- package/dist/gateway/static/root/assets/popover-select-DrILF6mR.js +0 -1
- package/dist/gateway/static/root/assets/product-open-page-DMhf1rdz.js +0 -1
- package/dist/gateway/static/root/assets/project-detail-page-DDHi0Y4Q.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-CVMFKpmu.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-B74aErBY.js +0 -1
- package/dist/gateway/static/root/assets/runtime-tools-settings-panel-Bv-akndY.js +0 -5
- package/dist/gateway/static/root/assets/sessions-page-D2wmGNZE.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-CYCCUMEt.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-rf8f1OGq.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-BkvclZ_o.js +0 -1
- package/dist/gateway/static/root/assets/skills-page.utils-DGjnz-NG.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-6a2RdDl2.js +0 -1
- package/dist/gateway/static/root/assets/tunnel-api-Chfiba_x.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-SeOHP6XO.js +0 -1
- package/dist/gateway/static/root/assets/voice-config-api-BO6A8V3Z.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-overlay-BfwEoOGL.js +0 -1
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-X7Z5_lRX.js +0 -3
- package/dist/gateway/static/root/assets/workflows-page-BklMzkg8.js +0 -5
|
@@ -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>;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import crypto from "node:crypto";
|
|
3
|
+
//#region src/voice/dashscope/streaming-tts-stream.ts
|
|
4
|
+
const { WebSocket } = createRequire(import.meta.url)("ws");
|
|
5
|
+
const DEFAULT_REALTIME_URL = "wss://dashscope.aliyuncs.com/api-ws/v1/realtime";
|
|
6
|
+
function realtimeUrl(baseUrl, model) {
|
|
7
|
+
const configured = baseUrl ? new URL(baseUrl) : new URL(DEFAULT_REALTIME_URL);
|
|
8
|
+
const wasWebSocket = configured.protocol === "ws:" || configured.protocol === "wss:";
|
|
9
|
+
configured.protocol = configured.protocol === "http:" ? "ws:" : configured.protocol === "https:" ? "wss:" : configured.protocol;
|
|
10
|
+
if (configured.protocol !== "ws:" && configured.protocol !== "wss:") throw new Error("DashScope realtime TTS base URL must use HTTP or WebSocket");
|
|
11
|
+
if (!wasWebSocket) configured.pathname = "/api-ws/v1/realtime";
|
|
12
|
+
configured.searchParams.set("model", model);
|
|
13
|
+
return configured.toString();
|
|
14
|
+
}
|
|
15
|
+
function rawText(data) {
|
|
16
|
+
if (typeof data === "string") return data;
|
|
17
|
+
if (data instanceof ArrayBuffer) return Buffer.from(data).toString("utf8");
|
|
18
|
+
if (Array.isArray(data)) return Buffer.concat(data).toString("utf8");
|
|
19
|
+
return data.toString("utf8");
|
|
20
|
+
}
|
|
21
|
+
function event(type, extra = {}) {
|
|
22
|
+
return JSON.stringify({
|
|
23
|
+
event_id: crypto.randomUUID(),
|
|
24
|
+
type,
|
|
25
|
+
...extra
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
async function openDashScopeStreamingTts(request) {
|
|
29
|
+
if (!request.apiKey) throw new Error("DashScope TTS API key is unavailable");
|
|
30
|
+
if (request.signal.aborted) throw request.signal.reason;
|
|
31
|
+
const socket = new WebSocket(realtimeUrl(request.baseUrl, request.model), {
|
|
32
|
+
headers: { Authorization: `Bearer ${request.apiKey}` },
|
|
33
|
+
perMessageDeflate: false
|
|
34
|
+
});
|
|
35
|
+
let controller;
|
|
36
|
+
let settled = false;
|
|
37
|
+
let streamClosed = false;
|
|
38
|
+
let resolveReady;
|
|
39
|
+
let rejectReady;
|
|
40
|
+
const readyPromise = new Promise((resolve, reject) => {
|
|
41
|
+
resolveReady = resolve;
|
|
42
|
+
rejectReady = reject;
|
|
43
|
+
});
|
|
44
|
+
const audioStream = new ReadableStream({
|
|
45
|
+
start(next) {
|
|
46
|
+
controller = next;
|
|
47
|
+
},
|
|
48
|
+
cancel() {
|
|
49
|
+
streamClosed = true;
|
|
50
|
+
socket.close(1e3, "Consumer cancelled");
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const fail = (error, closeSocket = true) => {
|
|
54
|
+
if (!settled) rejectReady(error);
|
|
55
|
+
if (!streamClosed) {
|
|
56
|
+
streamClosed = true;
|
|
57
|
+
controller?.error(error);
|
|
58
|
+
}
|
|
59
|
+
if (closeSocket) {
|
|
60
|
+
if (socket.readyState === WebSocket.OPEN) socket.close(1011, "Provider stream failed");
|
|
61
|
+
else if (socket.readyState === WebSocket.CONNECTING) socket.terminate();
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const finishStream = () => {
|
|
65
|
+
if (streamClosed) return;
|
|
66
|
+
streamClosed = true;
|
|
67
|
+
controller?.close();
|
|
68
|
+
};
|
|
69
|
+
const onAbort = () => {
|
|
70
|
+
fail(request.signal.reason instanceof Error ? request.signal.reason : new DOMException("Realtime TTS aborted", "AbortError"), false);
|
|
71
|
+
if (socket.readyState === WebSocket.OPEN) socket.close(1e3, "Aborted");
|
|
72
|
+
else if (socket.readyState === WebSocket.CONNECTING) socket.terminate();
|
|
73
|
+
};
|
|
74
|
+
request.signal.addEventListener("abort", onAbort, { once: true });
|
|
75
|
+
socket.on("message", (data, isBinary) => {
|
|
76
|
+
if (streamClosed || request.signal.aborted) return;
|
|
77
|
+
if (isBinary) return;
|
|
78
|
+
let message;
|
|
79
|
+
try {
|
|
80
|
+
message = JSON.parse(rawText(data));
|
|
81
|
+
} catch {
|
|
82
|
+
fail(/* @__PURE__ */ new Error("DashScope realtime TTS returned invalid JSON"));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (message.type === "session.created") {
|
|
86
|
+
socket.send(event("session.update", { session: {
|
|
87
|
+
voice: request.voice,
|
|
88
|
+
mode: "commit",
|
|
89
|
+
language_type: "Auto",
|
|
90
|
+
response_format: "pcm",
|
|
91
|
+
sample_rate: 24e3,
|
|
92
|
+
...request.instructions ? {
|
|
93
|
+
instructions: request.instructions,
|
|
94
|
+
optimize_instructions: false
|
|
95
|
+
} : {}
|
|
96
|
+
} }));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (message.type === "session.updated") {
|
|
100
|
+
settled = true;
|
|
101
|
+
resolveReady();
|
|
102
|
+
socket.send(event("input_text_buffer.append", { text: request.text }));
|
|
103
|
+
socket.send(event("input_text_buffer.commit"));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (message.type === "response.audio.delta") {
|
|
107
|
+
if (streamClosed) return;
|
|
108
|
+
if (typeof message.delta !== "string") {
|
|
109
|
+
fail(/* @__PURE__ */ new Error("DashScope realtime TTS returned invalid audio"));
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
controller?.enqueue(Buffer.from(message.delta, "base64"));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (message.type === "response.audio.done") {
|
|
116
|
+
finishStream();
|
|
117
|
+
socket.send(event("session.finish"));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (message.type === "error") {
|
|
121
|
+
const code = typeof message.error?.code === "string" ? message.error.code : void 0;
|
|
122
|
+
const detail = typeof message.error?.message === "string" ? message.error.message : void 0;
|
|
123
|
+
fail(new Error([code, detail].filter(Boolean).join(": ") || "DashScope realtime TTS failed"));
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
socket.on("error", (error) => fail(error));
|
|
127
|
+
socket.on("close", () => {
|
|
128
|
+
request.signal.removeEventListener("abort", onAbort);
|
|
129
|
+
if (!streamClosed) fail(/* @__PURE__ */ new Error("DashScope realtime TTS connection closed unexpectedly"));
|
|
130
|
+
});
|
|
131
|
+
const timeout = setTimeout(() => {
|
|
132
|
+
fail(/* @__PURE__ */ new Error("DashScope realtime TTS setup timed out"));
|
|
133
|
+
socket.close(1011, "Setup timeout");
|
|
134
|
+
}, request.timeoutMs);
|
|
135
|
+
try {
|
|
136
|
+
await readyPromise;
|
|
137
|
+
} finally {
|
|
138
|
+
clearTimeout(timeout);
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
audioStream,
|
|
142
|
+
outputFormat: "pcm",
|
|
143
|
+
fileExtension: "pcm",
|
|
144
|
+
voiceCompatible: false,
|
|
145
|
+
release: async () => {
|
|
146
|
+
request.signal.removeEventListener("abort", onAbort);
|
|
147
|
+
finishStream();
|
|
148
|
+
if (socket.readyState === WebSocket.OPEN) socket.close(1e3, "Released");
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
153
|
+
export { openDashScopeStreamingTts };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { VoiceTicketClaim, VoiceRealtimeRuntimeOptions } from './runtime.js';
|
|
2
|
+
import type { VoiceEngine, VoiceEventSink } from './engine.js';
|
|
3
|
+
export declare function createAgentVoiceEngine(options: {
|
|
4
|
+
claim: VoiceTicketClaim;
|
|
5
|
+
runtime: VoiceRealtimeRuntimeOptions;
|
|
6
|
+
signal: AbortSignal;
|
|
7
|
+
send: VoiceEventSink;
|
|
8
|
+
sendAudio: (responseId: string, bytes: Uint8Array) => void;
|
|
9
|
+
onClose: (reason: string, notify: boolean) => Promise<void>;
|
|
10
|
+
}): VoiceEngine;
|