@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.
Files changed (257) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{activity-store-CLnbVm9G.js → activity-store-CAah-_8h.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DuBewmbW.js → agent-avatar-dicebear-DDH4HgP7.js} +1 -1
  5. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-BDCfJZhh.js +1 -0
  6. package/dist/gateway/static/root/assets/agents-B0ZWgf-U.js +1 -0
  7. package/dist/gateway/static/root/assets/{api-DjBZe303.js → api-B2tKxbcz.js} +1 -1
  8. package/dist/gateway/static/root/assets/app-management-settings-panel-Blfwszzn.js +1 -0
  9. package/dist/gateway/static/root/assets/{appearance-settings-B-iul0RG.js → appearance-settings-C3V7Na75.js} +1 -1
  10. package/dist/gateway/static/root/assets/apps-page-BiEks0-F.js +1 -0
  11. package/dist/gateway/static/root/assets/{archive-plugin-BOx0EJZs.js → archive-plugin-BmSx7wzY.js} +1 -1
  12. package/dist/gateway/static/root/assets/{attachment-load-Cfk1lwBo.js → attachment-load-BS-S4LJ9.js} +1 -1
  13. package/dist/gateway/static/root/assets/{automations-page-BTSGvaeS.js → automations-page-C7Y3L30D.js} +1 -1
  14. package/dist/gateway/static/root/assets/automations-workspace-A3zPkPuo.js +6 -0
  15. package/dist/gateway/static/root/assets/{binary-plugins-ChZyZK45.js → binary-plugins-BM9B5kcm.js} +1 -1
  16. package/dist/gateway/static/root/assets/block-editor-BbnpkYP9.js +185 -0
  17. package/dist/gateway/static/root/assets/browser-settings-page-Dk4FQ7fY.js +8 -0
  18. package/dist/gateway/static/root/assets/{browser-workflow-inputs-jvfcgFG-.js → browser-workflow-inputs-CRnkgZHI.js} +1 -1
  19. package/dist/gateway/static/root/assets/{browser-workflows-page-DrHW7XNi.js → browser-workflows-page-B9qGL-it.js} +2 -2
  20. package/dist/gateway/static/root/assets/{button-CSEbl4zT.js → button-CtTvuElV.js} +1 -1
  21. package/dist/gateway/static/root/assets/capabilities-settings-panel--tR_El9e.js +7 -0
  22. package/dist/gateway/static/root/assets/channels-settings-D347vl_J.js +1 -0
  23. package/dist/gateway/static/root/assets/{channels-status-swr-CC9MFway.js → channels-status-swr-DuY4MGxe.js} +1 -1
  24. package/dist/gateway/static/root/assets/{chat-terminal-dock-DeeZrVbV.js → chat-terminal-dock-DABPvwBT.js} +2 -2
  25. package/dist/gateway/static/root/assets/connectors-page-B-tvJkRJ.js +2 -0
  26. package/dist/gateway/static/root/assets/{cron-expression-CiqQOeQ3.js → cron-expression-D3bsKbNd.js} +1 -1
  27. package/dist/gateway/static/root/assets/{date-picker-CGAMGPfU.js → date-picker-BsGM6Yty.js} +1 -1
  28. package/dist/gateway/static/root/assets/{dependency-picker-CxWeUTsc.js → dependency-picker-Dj3g6YXZ.js} +1 -1
  29. package/dist/gateway/static/root/assets/{desktop-pet-C3QmYO75.js → desktop-pet-C1QT0Sur.js} +1 -1
  30. package/dist/gateway/static/root/assets/{desktop-pet-settings-CAADkWYy.js → desktop-pet-settings-r6kAOnfY.js} +1 -1
  31. package/dist/gateway/static/root/assets/dist-CpzYSoz7.js +1 -0
  32. package/dist/gateway/static/root/assets/{dist-DaxPZj9e.js → dist-DBS3OB8K.js} +1 -1
  33. package/dist/gateway/static/root/assets/dist-DLmwHyAh.js +1 -0
  34. package/dist/gateway/static/root/assets/es2015-BvLh9GaE.js +41 -0
  35. package/dist/gateway/static/root/assets/{extension-debug-page-FQXjDJ8P.js → extension-debug-page-DOkf7nh9.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-page-BJE1D5Ji.js → extension-page-Cq2IA4Ho.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-settings-page-5Ik2tNry.js → extension-settings-page-DQn4qjDZ.js} +1 -1
  38. package/dist/gateway/static/root/assets/{files-DQjhZjr2.js → files-D6vf3S30.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-config-api-cTj71t2a.js → gateway-config-api-DM3poL22.js} +1 -1
  40. package/dist/gateway/static/root/assets/{gateway-config-swr-Bxe_R-JH.js → gateway-config-swr-BC3pgb_P.js} +1 -1
  41. package/dist/gateway/static/root/assets/{gateway-settings-KXBUjNcx.js → gateway-settings-DPgH1hnh.js} +1 -1
  42. package/dist/gateway/static/root/assets/{gateway-startup-retry-DJG-I0wW.js → gateway-startup-retry-uMcSfLru.js} +1 -1
  43. package/dist/gateway/static/root/assets/{heartbeat-settings-C8cVzIcs.js → heartbeat-settings-Bk80-E3b.js} +1 -1
  44. package/dist/gateway/static/root/assets/home-page-DKo5JiMR.js +1 -0
  45. package/dist/gateway/static/root/assets/{image-generation-api-Dc_ojQuj.js → image-generation-api-D1qlQA-A.js} +1 -1
  46. package/dist/gateway/static/root/assets/index-B0WJL9N1.js +71 -0
  47. package/dist/gateway/static/root/assets/index-Dbh5SXyV.css +2 -0
  48. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-pOKl7blR.js → keyboard-shortcuts-settings-BEwvd8ZU.js} +1 -1
  49. package/dist/gateway/static/root/assets/local-app-workbench-page--eJ5rmNj.js +2 -0
  50. package/dist/gateway/static/root/assets/{local-apps-page-Bi6wwKgm.js → local-apps-page-CgkY9E-r.js} +1 -1
  51. package/dist/gateway/static/root/assets/{locale-store-C5wr3_pc.js → locale-store-CMZljTJx.js} +1 -1
  52. package/dist/gateway/static/root/assets/logs-page-Z49Td0J9.js +2 -0
  53. package/dist/gateway/static/root/assets/{management-settings-DGlVizWi.js → management-settings-Dv8NSJKt.js} +1 -1
  54. package/dist/gateway/static/root/assets/{markdown-split-CXP5zBx_.js → markdown-split-Cm0RBB-t.js} +1 -1
  55. package/dist/gateway/static/root/assets/{markdown-view-D6LxlDxr.js → markdown-view-PPCLt7fu.js} +3 -3
  56. package/dist/gateway/static/root/assets/{media-plugins-BsENGLr2.js → media-plugins-Bcr5sU1f.js} +1 -1
  57. package/dist/gateway/static/root/assets/messages-CTSgFlE4.js +3 -0
  58. package/dist/gateway/static/root/assets/mobile-pairing-wizard-kKDiXofY.js +1 -0
  59. package/dist/gateway/static/root/assets/{models-hub-cache-Y7GUjxHx.js → models-hub-cache-ZrbGRiGY.js} +1 -1
  60. package/dist/gateway/static/root/assets/{notes-page-D2EqpDyo.js → notes-page-CgsaRaGi.js} +1 -1
  61. package/dist/gateway/static/root/assets/notes-workbench-C1DEE09k.js +4 -0
  62. package/dist/gateway/static/root/assets/{oauth-api-C5NVcsKE.js → oauth-api-4VeMbkTJ.js} +1 -1
  63. package/dist/gateway/static/root/assets/popover-select-C-Hj-nXR.js +1 -0
  64. package/dist/gateway/static/root/assets/{product-delivery-dUJgmBQZ.js → product-delivery-CV4pDOtG.js} +1 -1
  65. package/dist/gateway/static/root/assets/product-open-page-BU0HiZtv.js +1 -0
  66. package/dist/gateway/static/root/assets/project-detail-page-isRapnp5.js +1 -0
  67. package/dist/gateway/static/root/assets/projects-page-zvsjg0mi.js +1 -0
  68. package/dist/gateway/static/root/assets/{registry-api-FXdFaoWM.js → registry-api-CWOtPFrE.js} +1 -1
  69. package/dist/gateway/static/root/assets/remote-access-hub-C9TGZ9Hc.js +1 -0
  70. package/dist/gateway/static/root/assets/runtime-tools-settings-panel-2zm9edMA.js +5 -0
  71. package/dist/gateway/static/root/assets/{schema-form-BUzdHWx6.js → schema-form-54A5gzkN.js} +1 -1
  72. package/dist/gateway/static/root/assets/{schemas-zIBW3wiV.js → schemas-BHS7bo06.js} +1 -1
  73. package/dist/gateway/static/root/assets/sessions-page-BP8RyiUn.js +1 -0
  74. package/dist/gateway/static/root/assets/settings-advanced-gate-D4EMxWAZ.js +1 -0
  75. package/dist/gateway/static/root/assets/{settings-page-C0OBLqpu.js → settings-page-DzDhoyxv.js} +1 -1
  76. package/dist/gateway/static/root/assets/{setup-status-panel-NpLQkFCh.js → setup-status-panel-uDicHU1w.js} +1 -1
  77. package/dist/gateway/static/root/assets/{share-preview-page-BtbPYaYC.js → share-preview-page-lOmLCWFS.js} +1 -1
  78. package/dist/gateway/static/root/assets/shares-settings-T4Yvouvv.js +1 -0
  79. package/dist/gateway/static/root/assets/skill-reload-api-DVb7nrXz.js +1 -0
  80. package/dist/gateway/static/root/assets/{skills-page-CYk8pN97.js → skills-page-CnyNH3To.js} +1 -1
  81. package/dist/gateway/static/root/assets/skills-page.utils-CgDtf2qs.js +1 -0
  82. package/dist/gateway/static/root/assets/{system-settings-panel-DmCRSvtd.js → system-settings-panel-C8yWfwtR.js} +1 -1
  83. package/dist/gateway/static/root/assets/task-detail-page-Tzfjlbf3.js +1 -0
  84. package/dist/gateway/static/root/assets/{theme-store-DUko1ZnE.js → theme-store-uxUwr10D.js} +1 -1
  85. package/dist/gateway/static/root/assets/tunnel-api-Bvg679no.js +1 -0
  86. package/dist/gateway/static/root/assets/{use-autosave-W_P8Kiv4.js → use-autosave-D88VGoyG.js} +1 -1
  87. package/dist/gateway/static/root/assets/user-context-page-RijPtyfO.js +1 -0
  88. package/dist/gateway/static/root/assets/{voice-api-key-field-BZD0j1jc.js → voice-api-key-field-CBHLsMcc.js} +1 -1
  89. package/dist/gateway/static/root/assets/voice-config-api-MqyI6cgq.js +1 -0
  90. package/dist/gateway/static/root/assets/work-discovery-overlay-GGe2TQ98.js +1 -0
  91. package/dist/gateway/static/root/assets/workflow-run-setup-panel-C0layUE9.js +3 -0
  92. package/dist/gateway/static/root/assets/workflows-page-DQXIzBAc.js +5 -0
  93. package/dist/gateway/static/root/index.html +21 -22
  94. package/dist/package.js +1 -1
  95. package/dist/packages/realtime-protocol/src/voice-audio.js +20 -0
  96. package/dist/packages/realtime-protocol/src/voice.js +208 -0
  97. package/dist/src/agent/agent-manager.js +1 -0
  98. package/dist/src/agent/embedded/run-for-session.d.ts +1 -0
  99. package/dist/src/agent/embedded/run-for-session.js +2 -1
  100. package/dist/src/agent/inbound/turn-dispatcher.d.ts +1 -0
  101. package/dist/src/agent/inbound/turn-dispatcher.js +2 -1
  102. package/dist/src/agent/prompt/voice-presentation.d.ts +2 -0
  103. package/dist/src/agent/prompt/voice-presentation.js +12 -0
  104. package/dist/src/agent/service/direct-turn-helpers.d.ts +1 -0
  105. package/dist/src/agent/service/direct-turn-helpers.js +1 -0
  106. package/dist/src/agent/service/process-direct-streaming.d.ts +1 -0
  107. package/dist/src/agent/service/process-direct-streaming.js +2 -1
  108. package/dist/src/agent/session/session-config-service.js +4 -2
  109. package/dist/src/agent/skills/installer.d.ts +1 -0
  110. package/dist/src/agent/skills/installer.js +9 -6
  111. package/dist/src/agent/tools/factory.d.ts +2 -0
  112. package/dist/src/agent/tools/factory.js +5 -1
  113. package/dist/src/automations/draft/automation-draft-service.js +1 -1
  114. package/dist/src/config/models-json.d.ts +8 -8
  115. package/dist/src/config/schema.d.ts +60 -0
  116. package/dist/src/config/schema.js +36 -4
  117. package/dist/src/extensions/install.js +1 -1
  118. package/dist/src/files/file-service.d.ts +1 -0
  119. package/dist/src/files/file-service.js +4 -0
  120. package/dist/src/gateway/chat-stream/thinking-delta-coalescer.js +8 -3
  121. package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -11
  122. package/dist/src/gateway/hono/lib/config-payload.js +2 -2
  123. package/dist/src/gateway/hono/lib/safe-voice-config.d.ts +14 -0
  124. package/dist/src/gateway/hono/lib/safe-voice-config.js +29 -1
  125. package/dist/src/gateway/hono/routes/config-patch/misc.js +2 -2
  126. package/dist/src/gateway/hono/routes/files.js +7 -0
  127. package/dist/src/gateway/hono/routes/lazy-fallback.js +18 -4
  128. package/dist/src/gateway/hono/routes/runtime-tools.js +7 -1
  129. package/dist/src/gateway/hono/routes/session-input-handler.js +14 -0
  130. package/dist/src/gateway/hono/routes/sessions.js +4 -1
  131. package/dist/src/gateway/hono/routes/voice.js +140 -3
  132. package/dist/src/gateway/server.js +1 -0
  133. package/dist/src/gateway/service/agent-runner.d.ts +1 -0
  134. package/dist/src/gateway/service/agent-runner.js +1 -6
  135. package/dist/src/gateway/service/run-gateway-agent.d.ts +1 -0
  136. package/dist/src/gateway/service/run-gateway-agent.js +19 -1
  137. package/dist/src/gateway/service.d.ts +2 -0
  138. package/dist/src/gateway/service.js +73 -0
  139. package/dist/src/media-understanding/types.d.ts +61 -0
  140. package/dist/src/runtime-tools/archive.js +17 -3
  141. package/dist/src/runtime-tools/command.d.ts +1 -0
  142. package/dist/src/runtime-tools/command.js +29 -8
  143. package/dist/src/runtime-tools/environment.d.ts +1 -0
  144. package/dist/src/runtime-tools/environment.js +11 -16
  145. package/dist/src/runtime-tools/install-lock.d.ts +1 -1
  146. package/dist/src/runtime-tools/install-lock.js +34 -21
  147. package/dist/src/runtime-tools/manager.d.ts +1 -1
  148. package/dist/src/runtime-tools/manager.js +99 -64
  149. package/dist/src/runtime-tools/manifest-store.d.ts +2 -0
  150. package/dist/src/runtime-tools/manifest-store.js +29 -8
  151. package/dist/src/runtime-tools/paths.d.ts +2 -1
  152. package/dist/src/runtime-tools/paths.js +19 -8
  153. package/dist/src/runtime-tools/probe.d.ts +2 -0
  154. package/dist/src/runtime-tools/probe.js +13 -1
  155. package/dist/src/runtime-tools/prune.js +21 -7
  156. package/dist/src/session/client-history.js +12 -0
  157. package/dist/src/session/manager.d.ts +1 -0
  158. package/dist/src/session/session-context-for-llm.js +8 -0
  159. package/dist/src/session/store.d.ts +1 -0
  160. package/dist/src/session/store.js +1 -0
  161. package/dist/src/session/stored-rows-to-file-entries.js +5 -1
  162. package/dist/src/session/voice-transcript.d.ts +9 -0
  163. package/dist/src/session/voice-transcript.js +45 -0
  164. package/dist/src/storage/sqlite/config-repository.js +9 -0
  165. package/dist/src/storage/sqlite/remote-context-repository.d.ts +3 -0
  166. package/dist/src/storage/sqlite/remote-context-repository.js +40 -0
  167. package/dist/src/storage/sqlite/session-repository.js +13 -0
  168. package/dist/src/storage/sqlite/user-context-repository.d.ts +3 -1
  169. package/dist/src/storage/sqlite/user-context-repository.js +50 -4
  170. package/dist/src/tui/tui.js +2 -1
  171. package/dist/src/user-context/automatic-context.d.ts +17 -0
  172. package/dist/src/user-context/automatic-context.js +85 -0
  173. package/dist/src/user-context/changes.d.ts +7 -0
  174. package/dist/src/user-context/changes.js +28 -0
  175. package/dist/src/user-context/planner.js +1 -24
  176. package/dist/src/user-context/retriever.js +10 -11
  177. package/dist/src/user-context/selection-policy.d.ts +20 -0
  178. package/dist/src/user-context/selection-policy.js +33 -0
  179. package/dist/src/user-context/sources/index.js +2 -2
  180. package/dist/src/user-context/sources/repository.d.ts +2 -1
  181. package/dist/src/user-context/sources/repository.js +26 -5
  182. package/dist/src/voice/dashscope/streaming-stt-session.d.ts +2 -0
  183. package/dist/src/voice/dashscope/streaming-stt-session.js +249 -0
  184. package/dist/src/voice/dashscope/streaming-tts-stream.d.ts +12 -0
  185. package/dist/src/voice/dashscope/streaming-tts-stream.js +153 -0
  186. package/dist/src/voice/realtime/agentEngine.d.ts +10 -0
  187. package/dist/src/voice/realtime/agentEngine.js +403 -0
  188. package/dist/src/voice/realtime/audio-playback-window.d.ts +9 -0
  189. package/dist/src/voice/realtime/audio-playback-window.js +49 -0
  190. package/dist/src/voice/realtime/conversation-context.d.ts +11 -0
  191. package/dist/src/voice/realtime/conversation-context.js +76 -0
  192. package/dist/src/voice/realtime/engine.d.ts +13 -0
  193. package/dist/src/voice/realtime/engine.js +1 -0
  194. package/dist/src/voice/realtime/memory-context.d.ts +17 -0
  195. package/dist/src/voice/realtime/memory-context.js +100 -0
  196. package/dist/src/voice/realtime/omniEngine.d.ts +18 -0
  197. package/dist/src/voice/realtime/omniEngine.js +443 -0
  198. package/dist/src/voice/realtime/omniRoute.d.ts +10 -0
  199. package/dist/src/voice/realtime/omniRoute.js +31 -0
  200. package/dist/src/voice/realtime/runtime.d.ts +99 -0
  201. package/dist/src/voice/realtime/runtime.js +622 -0
  202. package/dist/src/voice/realtime/speakable-segmenter.d.ts +10 -0
  203. package/dist/src/voice/realtime/speakable-segmenter.js +87 -0
  204. package/dist/src/voice/stt/list-providers.js +2 -1
  205. package/dist/src/voice/stt/providers/alibaba-transcription.js +13 -1
  206. package/dist/src/voice/stt/providers/xopc-cloud-transcription.js +23 -0
  207. package/dist/src/voice/tts/factory.js +1 -0
  208. package/dist/src/voice/tts/openai-compatible-speech.js +3 -1
  209. package/dist/src/voice/tts/providers/alibaba-speech.d.ts +1 -5
  210. package/dist/src/voice/tts/providers/alibaba-speech.js +25 -8
  211. package/dist/src/voice/tts/providers/edge-speech.js +21 -22
  212. package/dist/src/voice/tts/providers/minimax-speech.js +6 -3
  213. package/dist/src/voice/tts/providers/xopc-cloud-speech.js +26 -1
  214. package/dist/src/voice/tts/speak-core.d.ts +6 -2
  215. package/dist/src/voice/tts/speak-core.js +46 -34
  216. package/dist/src/voice/tts/speech-provider-types.d.ts +1 -0
  217. package/package.json +6 -6
  218. package/dist/gateway/static/root/assets/Combination-14nmIgxH.js +0 -41
  219. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-DbdgX6AA.js +0 -1
  220. package/dist/gateway/static/root/assets/agents-BX3uRVm4.js +0 -1
  221. package/dist/gateway/static/root/assets/app-chrome-BeB4KgOf.js +0 -1
  222. package/dist/gateway/static/root/assets/app-management-settings-panel-D8evZyFQ.js +0 -1
  223. package/dist/gateway/static/root/assets/apps-page-CoZd_cZu.js +0 -1
  224. package/dist/gateway/static/root/assets/automations-workspace-C8RRKT-a.js +0 -6
  225. package/dist/gateway/static/root/assets/block-editor-DCH9b2Ht.js +0 -184
  226. package/dist/gateway/static/root/assets/browser-settings-page-D1GPwIfx.js +0 -8
  227. package/dist/gateway/static/root/assets/capabilities-settings-panel-CrXB1Q-l.js +0 -7
  228. package/dist/gateway/static/root/assets/channels-settings-DWMSYaNZ.js +0 -1
  229. package/dist/gateway/static/root/assets/connectors-page-DXTl1fNB.js +0 -2
  230. package/dist/gateway/static/root/assets/dist-BPoKqzeH.js +0 -1
  231. package/dist/gateway/static/root/assets/dist-DqPZM2MH.js +0 -1
  232. package/dist/gateway/static/root/assets/home-page-NdWtBda5.js +0 -1
  233. package/dist/gateway/static/root/assets/index-7i2P3312.js +0 -70
  234. package/dist/gateway/static/root/assets/index-DTo3IcbW.css +0 -2
  235. package/dist/gateway/static/root/assets/local-app-workbench-page-C_j_od5f.js +0 -2
  236. package/dist/gateway/static/root/assets/logs-page-D6PDZEVP.js +0 -2
  237. package/dist/gateway/static/root/assets/messages-_tYhRAHD.js +0 -3
  238. package/dist/gateway/static/root/assets/mobile-pairing-wizard-DcEz7qcX.js +0 -1
  239. package/dist/gateway/static/root/assets/notes-workbench-Bu0a83Oj.js +0 -4
  240. package/dist/gateway/static/root/assets/popover-select-DrILF6mR.js +0 -1
  241. package/dist/gateway/static/root/assets/product-open-page-DMhf1rdz.js +0 -1
  242. package/dist/gateway/static/root/assets/project-detail-page-DDHi0Y4Q.js +0 -1
  243. package/dist/gateway/static/root/assets/projects-page-CVMFKpmu.js +0 -1
  244. package/dist/gateway/static/root/assets/remote-access-hub-B74aErBY.js +0 -1
  245. package/dist/gateway/static/root/assets/runtime-tools-settings-panel-Bv-akndY.js +0 -5
  246. package/dist/gateway/static/root/assets/sessions-page-D2wmGNZE.js +0 -1
  247. package/dist/gateway/static/root/assets/settings-advanced-gate-CYCCUMEt.js +0 -1
  248. package/dist/gateway/static/root/assets/shares-settings-rf8f1OGq.js +0 -1
  249. package/dist/gateway/static/root/assets/skill-reload-api-BkvclZ_o.js +0 -1
  250. package/dist/gateway/static/root/assets/skills-page.utils-DGjnz-NG.js +0 -1
  251. package/dist/gateway/static/root/assets/task-detail-page-6a2RdDl2.js +0 -1
  252. package/dist/gateway/static/root/assets/tunnel-api-Chfiba_x.js +0 -1
  253. package/dist/gateway/static/root/assets/user-context-page-SeOHP6XO.js +0 -1
  254. package/dist/gateway/static/root/assets/voice-config-api-BO6A8V3Z.js +0 -1
  255. package/dist/gateway/static/root/assets/work-discovery-overlay-BfwEoOGL.js +0 -1
  256. package/dist/gateway/static/root/assets/workflow-run-setup-panel-X7Z5_lRX.js +0 -3
  257. package/dist/gateway/static/root/assets/workflows-page-BklMzkg8.js +0 -5
@@ -131,7 +131,8 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
131
131
  const eventStream = agentService.turnDispatcher.processDirectStreaming(stampedMessage, sessionKey, origin, prepared, thinking, {
132
132
  signal: mergedSignal,
133
133
  runId,
134
- sourceContexts: runOptions?.sourceContexts
134
+ sourceContexts: runOptions?.sourceContexts,
135
+ presentation: runOptions?.presentation
135
136
  });
136
137
  const mappedEvents = (async function* () {
137
138
  for await (const event of eventStream) yield* mapper.map(event);
@@ -150,6 +151,18 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
150
151
  summary: mergedSignal.aborted ? "Interrupted" : "Message processed successfully"
151
152
  };
152
153
  } catch (error) {
154
+ if (mergedSignal.aborted) {
155
+ terminalStatus = "cancelled";
156
+ taskRunStatus = "cancelled";
157
+ taskRunSummary = "Interrupted";
158
+ yield* emitAndYield(mapper.end("cancelled", "Interrupted"));
159
+ completeRealtimeTopic(`run:${runId}`);
160
+ runTopicCompleted = true;
161
+ return {
162
+ status: "aborted",
163
+ summary: "Interrupted"
164
+ };
165
+ }
153
166
  const em = error instanceof Error ? error.message : String(error);
154
167
  log.error({
155
168
  err: error,
@@ -173,6 +186,11 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
173
186
  summary: streamError
174
187
  };
175
188
  } finally {
189
+ if (mergedSignal.aborted) {
190
+ terminalStatus = "cancelled";
191
+ taskRunStatus = "cancelled";
192
+ taskRunSummary = "Interrupted";
193
+ }
176
194
  if (registeredActiveWebchatRun && activeWebchatRunBySession.get(sessionKey) === runId) {
177
195
  activeWebchatRunBySession.delete(sessionKey);
178
196
  publishRealtime("sessions", "run.completed", {
@@ -19,6 +19,7 @@ import { GatewaySessionsApi } from './service/sessions-api.js';
19
19
  import { GatewayMarketplaceService } from './service/marketplace-service.js';
20
20
  import { GatewayAgentRunner } from './service/agent-runner.js';
21
21
  import { RealtimeRuntime } from '../realtime/runtime.js';
22
+ import { VoiceRealtimeRuntime } from '../voice/realtime/runtime.js';
22
23
  import type { GatewayServiceConfig } from './service/types.js';
23
24
  import { type GatewayReadinessSnapshot } from './startup-readiness.js';
24
25
  import { type ConnectorLearningCoordinator } from '../connectors/learning-coordinator.js';
@@ -51,6 +52,7 @@ export declare class GatewayService {
51
52
  private auth;
52
53
  readonly endpointTools: EndpointToolRuntime;
53
54
  readonly realtime: RealtimeRuntime;
55
+ readonly voiceRealtime: VoiceRealtimeRuntime;
54
56
  getConfig(): Config;
55
57
  getModelCatalogSync(): ModelCatalogSyncService;
56
58
  get browserRecipes(): BrowserRecipeService;
@@ -6,6 +6,8 @@ import { getRuntimeLogStats } from "../utils/logger/stats.js";
6
6
  import { createLogger } from "../utils/logger/index.js";
7
7
  import { init_logger } from "../utils/logger.js";
8
8
  import { closeXopcDatabase, openXopcDatabase } from "../storage/sqlite/connection.js";
9
+ import { notifyUserContextChange } from "../user-context/changes.js";
10
+ import { getSessionConfig } from "../storage/sqlite/config-repository.js";
9
11
  import "../storage/sqlite/index.js";
10
12
  import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
11
13
  import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveDefaultAgentId } from "../agent/agent-scope.js";
@@ -18,6 +20,7 @@ import { loadConfig, saveConfig } from "../config/loader.js";
18
20
  import { buildSessionKey, init_session_key, sanitizeSegment } from "../routing/session-key.js";
19
21
  import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
20
22
  import { init_providers, providers_exports } from "../providers/index.js";
23
+ import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
21
24
  import { TaskRepository } from "../tasks/task-repository.js";
22
25
  import { TaskConversationRepository } from "../tasks/task-conversation-repository.js";
23
26
  import { disposeAllSessionMcpRuntimes } from "../agent/mcp/bundle-mcp-runtime.js";
@@ -68,6 +71,8 @@ import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validate
68
71
  import { prepareAutomationAgentSession } from "./automation-agent-session.js";
69
72
  import { stopTailscaleExposure } from "./tailscale-lifecycle.js";
70
73
  import { reconcileDreamingAutomations } from "./dreaming-automation-reconciler.js";
74
+ import { buildVoiceMemoryContext } from "../voice/realtime/memory-context.js";
75
+ import { voiceMemoryBudget } from "../voice/realtime/conversation-context.js";
71
76
  import { NotesStore } from "../notes/store.js";
72
77
  import { buildNoteAgentContext } from "../notes/agent-context.js";
73
78
  import { NotesService } from "../notes/service.js";
@@ -114,6 +119,7 @@ import { GatewayMarketplaceService } from "./service/marketplace-service.js";
114
119
  import { GatewayConfigCoordinator } from "./service/config-coordinator.js";
115
120
  import { GatewayAgentRunner } from "./service/agent-runner.js";
116
121
  import { RealtimeRuntime } from "../realtime/runtime.js";
122
+ import { VoiceRealtimeRuntime } from "../voice/realtime/runtime.js";
117
123
  import { GatewayReadiness } from "./startup-readiness.js";
118
124
  import { createGatewayStartupTrace } from "./startup-trace.js";
119
125
  import { applyAutomaticVoiceLanguage, inferProductLanguageFromEnvironment, initializeVoiceDefaults } from "../voice/language-profile.js";
@@ -158,6 +164,71 @@ var GatewayService = class {
158
164
  auth;
159
165
  endpointTools = new EndpointToolRuntime();
160
166
  realtime = new RealtimeRuntime(this.endpointTools);
167
+ voiceRealtime = new VoiceRealtimeRuntime({
168
+ getConversationContext: async (sessionKey, expectedSessionId) => {
169
+ if ((await this.sessionIndex.getSessionMetadata(sessionKey))?.sessionId !== expectedSessionId) throw new Error("Conversation changed before voice connection");
170
+ const messages = await this.sessionIndex.loadMessages(sessionKey);
171
+ const after = await this.sessionIndex.getSessionMetadata(sessionKey);
172
+ if (after?.sessionId !== expectedSessionId) throw new Error("Conversation changed while loading voice context");
173
+ const profile = resolveEffectiveAgentProfileForSession(this.config, sessionKey);
174
+ const context = {
175
+ identity: [`Your name is ${profile.config.profile?.name ?? profile.agentId}.`, profile.customInstructions ?? ""].join("\n"),
176
+ history: messages
177
+ };
178
+ const memory = buildVoiceMemoryContext({
179
+ getConfig: () => this.config,
180
+ sessionKey,
181
+ workspaceId: getSessionConfig(sessionKey)?.workingDirectoryOverride ?? profile.resolvedWorkspacePath,
182
+ projectId: after?.projectId,
183
+ history: messages,
184
+ maxChars: voiceMemoryBudget(this.config.voice.realtime.omni.instructions, context)
185
+ });
186
+ return {
187
+ ...context,
188
+ ...memory ? { memory } : {}
189
+ };
190
+ },
191
+ getSessionIdentity: async (sessionKey) => (await this.sessionIndex.getSessionMetadata(sessionKey))?.sessionId,
192
+ recordOmniTranscript: async (sessionKey, callId, entry, expectedSessionId) => {
193
+ await this.sessionIndex.appendTranscriptCustomMessageEntry(sessionKey, {
194
+ expectedSessionId,
195
+ customType: "voice_omni_transcript",
196
+ content: entry.text,
197
+ display: true,
198
+ details: {
199
+ callId,
200
+ itemId: entry.itemId,
201
+ role: entry.role,
202
+ interrupted: entry.interrupted,
203
+ engine: "omni"
204
+ }
205
+ });
206
+ this.emit("session.transcript_updated", { key: sessionKey });
207
+ },
208
+ getConfig: () => this.config,
209
+ sessionExists: async (sessionKey) => Boolean(await this.sessionIndex.getSessionMetadata(sessionKey)),
210
+ sessionBusy: (sessionKey) => Boolean(this.agentRunner.getActiveRunId(sessionKey)) || this.agentRunner.inputs.snapshot(sessionKey).inputs.some((input) => input.status === "queued"),
211
+ recordInterruption: (entry) => this.sessionIndex.appendTranscriptContextEntry(entry.sessionKey, {
212
+ text: "Voice response was interrupted before playback completed.",
213
+ data: {
214
+ type: "voice_response_interrupted",
215
+ responseId: entry.responseId,
216
+ reason: entry.reason,
217
+ generatedCharacters: entry.generatedCharacters,
218
+ interruptedDuring: entry.interruptedDuring
219
+ }
220
+ }),
221
+ runAgent: (text, sessionKey, signal) => {
222
+ if (this.agentRunner.hasActiveRun(sessionKey)) throw new Error("Conversation session already has an active response");
223
+ return this.agentRunner.runAgent(text, "webchat", sessionKey, {
224
+ type: "channel",
225
+ channel: "webchat"
226
+ }, void 0, void 0, {
227
+ signal,
228
+ presentation: "voice"
229
+ });
230
+ }
231
+ });
161
232
  getConfig() {
162
233
  return this.config;
163
234
  }
@@ -1097,6 +1168,7 @@ var GatewayService = class {
1097
1168
  this.endpointTools.close();
1098
1169
  await this.sideChats.disposeAll();
1099
1170
  this.realtime.close();
1171
+ this.voiceRealtime.close();
1100
1172
  await this.proactiveWorker.stop();
1101
1173
  await this.discussionWorker.stop();
1102
1174
  await this.discussionSealer.stop();
@@ -1543,6 +1615,7 @@ var GatewayService = class {
1543
1615
  });
1544
1616
  }
1545
1617
  emit(type, payload) {
1618
+ if (type === "config.reload") notifyUserContextChange({ kind: "policy" });
1546
1619
  this.realtime.broker.publish("gateway", type, payload);
1547
1620
  this.createNotificationService().handleGatewayEvent(type, payload);
1548
1621
  }
@@ -112,6 +112,65 @@ export interface AudioTranscriptionResult {
112
112
  /** Audio duration in seconds, when reported. */
113
113
  durationSeconds?: number;
114
114
  }
115
+ export interface PcmAudioFormat {
116
+ encoding: 'pcm_s16le';
117
+ sampleRate: 16_000 | 24_000;
118
+ channels: 1;
119
+ }
120
+ export interface StreamingSttCapabilities {
121
+ inputSampleRates: readonly number[];
122
+ turnDetection: readonly 'server_vad'[];
123
+ defaultModel: string;
124
+ models: readonly string[];
125
+ }
126
+ export type StreamingSttEvent = {
127
+ type: 'ready';
128
+ } | {
129
+ type: 'speech_started';
130
+ utteranceId: string;
131
+ } | {
132
+ type: 'speech_stopped';
133
+ utteranceId: string;
134
+ } | {
135
+ type: 'transcript_delta';
136
+ utteranceId: string;
137
+ revision: number;
138
+ text: string;
139
+ } | {
140
+ type: 'transcript_final';
141
+ utteranceId: string;
142
+ revision: number;
143
+ text: string;
144
+ language?: string;
145
+ } | {
146
+ type: 'usage';
147
+ inputAudioMs: number;
148
+ } | {
149
+ type: 'error';
150
+ error: Error;
151
+ };
152
+ export interface StreamingSttOpenRequest {
153
+ model: string;
154
+ inputFormat: PcmAudioFormat;
155
+ apiKey?: string;
156
+ baseUrl?: string;
157
+ headers?: Record<string, string>;
158
+ language?: string;
159
+ prompt?: string;
160
+ turnDetection: {
161
+ mode: 'server_vad';
162
+ silenceDurationMs: number;
163
+ };
164
+ timeoutMs: number;
165
+ signal: AbortSignal;
166
+ onEvent: (event: StreamingSttEvent) => void;
167
+ }
168
+ export interface StreamingSttSession {
169
+ appendAudio(chunk: Uint8Array): void;
170
+ commit(): Promise<void>;
171
+ close(): Promise<void>;
172
+ abort(reason: string): void;
173
+ }
115
174
  export interface ImageDescriptionRequest {
116
175
  buffer: Buffer;
117
176
  fileName: string;
@@ -170,6 +229,8 @@ export interface MediaUnderstandingProvider {
170
229
  /** True when the provider can natively ingest PDF (no OCR pre-step needed). */
171
230
  nativeDocumentInputs?: ReadonlyArray<'pdf'>;
172
231
  transcribeAudio?: (req: AudioTranscriptionRequest) => Promise<AudioTranscriptionResult>;
232
+ streamingAudio?: StreamingSttCapabilities;
233
+ openAudioStream?: (req: StreamingSttOpenRequest) => Promise<StreamingSttSession>;
173
234
  describeImage?: (req: ImageDescriptionRequest) => Promise<ImageDescriptionResult>;
174
235
  describeVideo?: (req: VideoDescriptionRequest) => Promise<VideoDescriptionResult>;
175
236
  }
@@ -5,12 +5,15 @@ import { lstat, mkdir, readdir, readlink, rename, rm, stat } from "node:fs/promi
5
5
  import AdmZip from "adm-zip";
6
6
  //#region src/runtime-tools/archive.ts
7
7
  const MAX_ARCHIVE_ENTRIES = 5e4;
8
+ const MAX_TAR_OUTPUT_BYTES = 16 * 1024 * 1024;
9
+ const MAX_EXTRACTED_BYTES = 2 * 1024 * 1024 * 1024;
8
10
  function validateMemberPath(memberPath) {
9
11
  const portablePath = memberPath.replaceAll("\\", "/");
10
12
  const normalized = posix.normalize(portablePath);
11
13
  if (!memberPath || isAbsolute(memberPath) || portablePath.startsWith("/") || normalized === ".." || normalized.startsWith("../")) throw new Error(`Unsafe archive member: ${memberPath}`);
12
14
  }
13
15
  async function validateExtractedTree(root, current = root) {
16
+ let totalBytes = 0;
14
17
  for (const entry of await readdir(current)) {
15
18
  const entryPath = join(current, entry);
16
19
  const details = await lstat(entryPath);
@@ -19,8 +22,10 @@ async function validateExtractedTree(root, current = root) {
19
22
  if (relativeTarget.split(/[\\/]/)[0] === ".." || isAbsolute(relativeTarget)) throw new Error(`Archive symlink escapes extraction root: ${entryPath}`);
20
23
  continue;
21
24
  }
22
- if (details.isDirectory()) await validateExtractedTree(root, entryPath);
25
+ totalBytes += details.isDirectory() ? await validateExtractedTree(root, entryPath) : details.size;
26
+ if (totalBytes > MAX_EXTRACTED_BYTES) throw new Error("Extracted archive exceeds size limit");
23
27
  }
28
+ return totalBytes;
24
29
  }
25
30
  async function runTar(args) {
26
31
  return await new Promise((resolvePromise, reject) => {
@@ -30,11 +35,19 @@ async function runTar(args) {
30
35
  shell: false,
31
36
  windowsHide: true
32
37
  });
38
+ const append = (current, chunk) => {
39
+ if (Buffer.byteLength(current) + chunk.byteLength > MAX_TAR_OUTPUT_BYTES) {
40
+ child.kill("SIGKILL");
41
+ reject(/* @__PURE__ */ new Error("tar output exceeds size limit"));
42
+ return current;
43
+ }
44
+ return current + chunk.toString();
45
+ };
33
46
  child.stdout?.on("data", (chunk) => {
34
- stdout += chunk.toString();
47
+ stdout = append(stdout, chunk);
35
48
  });
36
49
  child.stderr?.on("data", (chunk) => {
37
- stderr += chunk.toString();
50
+ stderr = append(stderr, chunk);
38
51
  });
39
52
  child.once("error", reject);
40
53
  child.once("close", (code) => {
@@ -47,6 +60,7 @@ async function extractZip(archivePath, destination) {
47
60
  const zip = new AdmZip(archivePath);
48
61
  const entries = zip.getEntries();
49
62
  if (entries.length > MAX_ARCHIVE_ENTRIES) throw new Error("Archive contains too many entries");
63
+ if (entries.reduce((total, entry) => total + entry.header.size, 0) > MAX_EXTRACTED_BYTES) throw new Error("Extracted archive exceeds size limit");
50
64
  for (const entry of entries) validateMemberPath(entry.entryName);
51
65
  zip.extractAllTo(destination, true, false);
52
66
  }
@@ -5,6 +5,7 @@ export interface RuntimeCommandResult {
5
5
  exitCode: number | null;
6
6
  timedOut: boolean;
7
7
  aborted: boolean;
8
+ outputTruncated: boolean;
8
9
  }
9
10
  export declare function runRuntimeCommand(params: {
10
11
  command: string;
@@ -1,6 +1,7 @@
1
1
  import { spawn } from "node:child_process";
2
2
  //#region src/runtime-tools/command.ts
3
3
  const DEFAULT_COMMAND_TIMEOUT_MS = 5e3;
4
+ const MAX_COMMAND_OUTPUT_BYTES = 1024 * 1024;
4
5
  async function runRuntimeCommand(params) {
5
6
  return await new Promise((resolve) => {
6
7
  let stdout = "";
@@ -8,7 +9,10 @@ async function runRuntimeCommand(params) {
8
9
  let settled = false;
9
10
  let timedOut = false;
10
11
  let aborted = false;
12
+ let outputTruncated = false;
13
+ let timeout;
11
14
  const child = spawn(params.command, params.args, {
15
+ detached: process.platform !== "win32",
12
16
  env: params.env,
13
17
  shell: false,
14
18
  windowsHide: process.platform === "win32",
@@ -18,36 +22,53 @@ async function runRuntimeCommand(params) {
18
22
  "pipe"
19
23
  ]
20
24
  });
25
+ const killChild = () => {
26
+ if (process.platform !== "win32" && child.pid) try {
27
+ process.kill(-child.pid, "SIGKILL");
28
+ return;
29
+ } catch {}
30
+ child.kill("SIGKILL");
31
+ };
21
32
  const finish = (exitCode) => {
22
33
  if (settled) return;
23
34
  settled = true;
24
- clearTimeout(timeout);
35
+ if (timeout) clearTimeout(timeout);
25
36
  params.signal?.removeEventListener("abort", abort);
26
37
  resolve({
27
- ok: exitCode === 0 && !timedOut && !aborted,
38
+ ok: exitCode === 0 && !timedOut && !aborted && !outputTruncated,
28
39
  stdout: stdout.trim(),
29
40
  stderr: stderr.trim(),
30
41
  exitCode,
31
42
  timedOut,
32
- aborted
43
+ aborted,
44
+ outputTruncated
33
45
  });
34
46
  };
35
47
  const abort = () => {
36
48
  aborted = true;
37
- child.kill("SIGKILL");
49
+ killChild();
38
50
  finish(null);
39
51
  };
52
+ const appendOutput = (current, chunk) => {
53
+ const remaining = MAX_COMMAND_OUTPUT_BYTES - Buffer.byteLength(current);
54
+ if (remaining <= 0 || chunk.byteLength > remaining) {
55
+ outputTruncated = true;
56
+ killChild();
57
+ return remaining > 0 ? current + chunk.subarray(0, remaining).toString() : current;
58
+ }
59
+ return current + chunk.toString();
60
+ };
40
61
  child.stdout?.on("data", (chunk) => {
41
- stdout += chunk.toString();
62
+ stdout = appendOutput(stdout, chunk);
42
63
  });
43
64
  child.stderr?.on("data", (chunk) => {
44
- stderr += chunk.toString();
65
+ stderr = appendOutput(stderr, chunk);
45
66
  });
46
67
  child.once("error", () => finish(null));
47
68
  child.once("close", finish);
48
- const timeout = setTimeout(() => {
69
+ timeout = setTimeout(() => {
49
70
  timedOut = true;
50
- child.kill("SIGKILL");
71
+ killChild();
51
72
  finish(null);
52
73
  }, params.timeoutMs ?? DEFAULT_COMMAND_TIMEOUT_MS);
53
74
  timeout.unref();
@@ -6,6 +6,7 @@ export interface RuntimeEnvironmentOptions {
6
6
  baseEnv: Record<string, string>;
7
7
  runtimes?: RuntimeKind[];
8
8
  extraBinDirs?: string[];
9
+ skillEnvironmentIds?: string[];
9
10
  }
10
11
  export interface RuntimeEnvironmentResult {
11
12
  env: Record<string, string>;
@@ -1,7 +1,7 @@
1
- import { applyPathPrepend } from "../infra/path-prepend.js";
1
+ import { applyPathPrepend, findPathKey, normalizePathPrepend } from "../infra/path-prepend.js";
2
2
  import { ManagedRuntimeManager } from "./manager.js";
3
- import { dirname, join } from "node:path";
4
- import { access, readdir } from "node:fs/promises";
3
+ import { delimiter, dirname, join } from "node:path";
4
+ import { access } from "node:fs/promises";
5
5
  //#region src/runtime-tools/environment.ts
6
6
  const POLLUTING_ENV_KEYS = [
7
7
  "NODE_OPTIONS",
@@ -19,14 +19,8 @@ const POLLUTING_ENV_KEYS = [
19
19
  "UV_CACHE_DIR",
20
20
  "UV_PYTHON_INSTALL_MIRROR"
21
21
  ];
22
- async function skillEnvironmentBinDirs(stateDir) {
22
+ async function skillEnvironmentBinDirs(stateDir, environmentIds) {
23
23
  const root = join(stateDir, "tools", "environments", "skills");
24
- let environmentIds;
25
- try {
26
- environmentIds = await readdir(root);
27
- } catch {
28
- return [];
29
- }
30
24
  const candidates = environmentIds.flatMap((id) => [join(root, id, "bin"), join(root, id, "node_modules", ".bin")]);
31
25
  return (await Promise.all(candidates.map(async (candidate) => {
32
26
  try {
@@ -37,6 +31,10 @@ async function skillEnvironmentBinDirs(stateDir) {
37
31
  }
38
32
  }))).filter((candidate) => candidate !== null);
39
33
  }
34
+ function appendPathEntries(env, entries) {
35
+ const pathKey = findPathKey(env);
36
+ env[pathKey] = normalizePathPrepend([...(env[pathKey] ?? "").split(delimiter).filter(Boolean), ...entries]).join(delimiter);
37
+ }
40
38
  async function buildRuntimeEnvironment(options) {
41
39
  const env = { ...options.baseEnv };
42
40
  for (const key of POLLUTING_ENV_KEYS) delete env[key];
@@ -60,12 +58,9 @@ async function buildRuntimeEnvironment(options) {
60
58
  }
61
59
  }))).filter((item) => item !== null);
62
60
  const managedBinDirs = resolved.filter((item) => item.source === "managed").map((item) => dirname(item.executable));
63
- const skillBinDirs = await skillEnvironmentBinDirs(options.stateDir);
64
- applyPathPrepend(env, [
65
- ...managedBinDirs,
66
- ...skillBinDirs,
67
- ...options.extraBinDirs ?? []
68
- ]);
61
+ const skillBinDirs = await skillEnvironmentBinDirs(options.stateDir, options.skillEnvironmentIds ?? []);
62
+ applyPathPrepend(env, [...managedBinDirs, ...options.extraBinDirs ?? []]);
63
+ appendPathEntries(env, skillBinDirs);
69
64
  if (resolved.some((item) => item.runtime === "python")) {
70
65
  env.PYTHONNOUSERSITE = "1";
71
66
  env.PIP_REQUIRE_VIRTUALENV = "1";
@@ -1 +1 @@
1
- export declare function withInstallLock<T>(path: string, metadata: Record<string, unknown>, fn: () => Promise<T>): Promise<T>;
1
+ export declare function withInstallLock<T>(path: string, metadata: Record<string, unknown>, fn: () => Promise<T>, signal?: AbortSignal): Promise<T>;
@@ -7,38 +7,51 @@ function isProcessAlive(pid) {
7
7
  try {
8
8
  process.kill(pid, 0);
9
9
  return true;
10
- } catch {
11
- return false;
10
+ } catch (error) {
11
+ return error.code === "EPERM";
12
12
  }
13
13
  }
14
14
  async function staleLock(path) {
15
15
  try {
16
16
  const value = JSON.parse(await readFile(path, "utf8"));
17
- const pid = typeof value.pid === "number" ? value.pid : 0;
18
- const createdAt = typeof value.createdAt === "number" ? value.createdAt : 0;
19
- return !isProcessAlive(pid) && Date.now() - createdAt > LOCK_STALE_MS;
17
+ return !isProcessAlive(typeof value.pid === "number" ? value.pid : 0);
20
18
  } catch {
21
19
  return true;
22
20
  }
23
21
  }
24
- async function withInstallLock(path, metadata, fn) {
22
+ async function withInstallLock(path, metadata, fn, signal) {
25
23
  await mkdir(dirname(path), { recursive: true });
26
- while (true) try {
27
- const handle = await open(path, "wx", 384);
28
- await handle.writeFile(JSON.stringify({
29
- pid: process.pid,
30
- createdAt: Date.now(),
31
- ...metadata
32
- }));
33
- await handle.close();
34
- break;
35
- } catch (error) {
36
- if (error.code !== "EEXIST") throw error;
37
- if (await staleLock(path)) {
38
- await unlink(path).catch(() => void 0);
39
- continue;
24
+ const waitStartedAt = Date.now();
25
+ while (true) {
26
+ if (signal?.aborted) throw signal.reason ?? /* @__PURE__ */ new Error("Runtime installation was aborted");
27
+ try {
28
+ const handle = await open(path, "wx", 384);
29
+ await handle.writeFile(JSON.stringify({
30
+ pid: process.pid,
31
+ createdAt: Date.now(),
32
+ ...metadata
33
+ }));
34
+ await handle.close();
35
+ break;
36
+ } catch (error) {
37
+ if (error.code !== "EEXIST") throw error;
38
+ if (await staleLock(path)) {
39
+ await unlink(path).catch(() => void 0);
40
+ continue;
41
+ }
42
+ if (Date.now() - waitStartedAt > LOCK_STALE_MS) throw new Error(`Timed out waiting for runtime installation lock: ${path}`);
43
+ await new Promise((resolve, reject) => {
44
+ const timeout = setTimeout(() => {
45
+ signal?.removeEventListener("abort", abort);
46
+ resolve();
47
+ }, LOCK_WAIT_MS);
48
+ const abort = () => {
49
+ clearTimeout(timeout);
50
+ reject(signal?.reason ?? /* @__PURE__ */ new Error("Runtime installation was aborted"));
51
+ };
52
+ signal?.addEventListener("abort", abort, { once: true });
53
+ });
40
54
  }
41
- await new Promise((resolve) => setTimeout(resolve, LOCK_WAIT_MS));
42
55
  }
43
56
  try {
44
57
  return await fn();
@@ -15,6 +15,6 @@ export declare class ManagedRuntimeManager extends EventEmitter {
15
15
  private uvEnvironment;
16
16
  status(runtime: RuntimeKind): Promise<RuntimeStatus>;
17
17
  statusAll(): Promise<RuntimeStatus[]>;
18
- repair(runtime: RuntimeKind): Promise<ResolvedRuntime>;
18
+ repair(runtime: RuntimeKind, requestedVersion?: string): Promise<ResolvedRuntime>;
19
19
  private progress;
20
20
  }