@xopcai/xopc 0.0.367 → 0.0.369

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 (263) hide show
  1. package/dist/browser-ext/_locales/en/messages.json +30 -1
  2. package/dist/browser-ext/_locales/zh_CN/messages.json +30 -1
  3. package/dist/browser-ext/dist/assets/{auth-beGtbLPS.js → page-context-BeworyNB.js} +1331 -1355
  4. package/dist/browser-ext/dist/assets/{sidepanel-BT0ojEzG.css → sidepanel-Ccl0eSa1.css} +43 -0
  5. package/dist/browser-ext/dist/background.js +680 -182
  6. package/dist/browser-ext/dist/sidepanel.html +2 -2
  7. package/dist/browser-ext/dist/sidepanel.js +372 -193
  8. package/dist/browser-ext/manifest.json +2 -8
  9. package/dist/extensions/telegram/xopc.extension.json +1 -1
  10. package/dist/gateway/static/root/assets/{activity-store-Cuf3JFFJ.js → activity-store-BQ3PMp2q.js} +1 -1
  11. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DyATPNTe.js → agent-avatar-dicebear-Stj17S9u.js} +1 -1
  12. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CCRfvuov.js +1 -0
  13. package/dist/gateway/static/root/assets/agent-plugin-dialog-CRlzd8El.js +1 -0
  14. package/dist/gateway/static/root/assets/agents-_ug2LCQb.js +66 -0
  15. package/dist/gateway/static/root/assets/{agents-admin-api-D842OcNo.js → agents-admin-api-HBZvVyzF.js} +1 -1
  16. package/dist/gateway/static/root/assets/app-management-settings-panel-pJFe6M6c.js +1 -0
  17. package/dist/gateway/static/root/assets/{appearance-settings-DQr0o6Lm.js → appearance-settings-BrxSpBWa.js} +1 -1
  18. package/dist/gateway/static/root/assets/{apps-page-CltMV4Xp.js → apps-page-DegSl5Lh.js} +1 -1
  19. package/dist/gateway/static/root/assets/{archive-plugin-DT8Nio-r.js → archive-plugin-BO3I9zRP.js} +1 -1
  20. package/dist/gateway/static/root/assets/{automations-page-BIfWS_3Y.js → automations-page-BZQ_VHjp.js} +1 -1
  21. package/dist/gateway/static/root/assets/automations-workspace-BQywN6nG.js +6 -0
  22. package/dist/gateway/static/root/assets/{binary-plugins-7qs3qcW9.js → binary-plugins-gFD7vH9R.js} +1 -1
  23. package/dist/gateway/static/root/assets/{block-editor-BFPUlxJ6.js → block-editor-3XjFv3kK.js} +28 -28
  24. package/dist/gateway/static/root/assets/browser-automation-inputs-DxRoKFun.js +1 -0
  25. package/dist/gateway/static/root/assets/browser-automations-page-yiEuG1v7.js +3 -0
  26. package/dist/gateway/static/root/assets/browser-settings-page-ch2_bQF0.js +3 -0
  27. package/dist/gateway/static/root/assets/{capabilities-K0Zb_lH0.js → capabilities-B48r0DDa.js} +1 -1
  28. package/dist/gateway/static/root/assets/{capabilities-BzWFO_x_.js → capabilities-DO-vfNKI.js} +1 -1
  29. package/dist/gateway/static/root/assets/capabilities-page-BEnFt_dj.js +2 -0
  30. package/dist/gateway/static/root/assets/capabilities-settings-panel-NckMsJ5N.js +8 -0
  31. package/dist/gateway/static/root/assets/{capability-header-actions-AMn_vTNv.js → capability-header-actions-CY8KCO9j.js} +1 -1
  32. package/dist/gateway/static/root/assets/channels-CHOS2CGa.js +1 -0
  33. package/dist/gateway/static/root/assets/{chat-terminal-dock-C7nAROhF.js → chat-terminal-dock-Bwknnb4c.js} +2 -2
  34. package/dist/gateway/static/root/assets/computer-settings-page-B2xeFCSt.js +1 -0
  35. package/dist/gateway/static/root/assets/{connector-service-page-CTx1B8wx.js → connector-service-page-C83DnAqK.js} +1 -1
  36. package/dist/gateway/static/root/assets/connectors-page-D6wTmWA6.js +2 -0
  37. package/dist/gateway/static/root/assets/{date-picker-Cx_xIKvN.js → date-picker-Bq9GR-DU.js} +1 -1
  38. package/dist/gateway/static/root/assets/{dependency-picker-DYm96PDu.js → dependency-picker-BTERkA9X.js} +1 -1
  39. package/dist/gateway/static/root/assets/{desktop-pet-D90OzgeR.js → desktop-pet-BwsbQw8V.js} +1 -1
  40. package/dist/gateway/static/root/assets/{desktop-pet-settings-CmdCecjm.js → desktop-pet-settings-sL9i44pP.js} +1 -1
  41. package/dist/gateway/static/root/assets/device-pairing-wizard-DI2bqaKO.js +1 -0
  42. package/dist/gateway/static/root/assets/{directory-picker-path-field-DZpaoeNa.js → directory-picker-path-field-BFlDmsS5.js} +1 -1
  43. package/dist/gateway/static/root/assets/{extension-debug-page-Bv6QE8kC.js → extension-debug-page-7Z1Tp7-w.js} +1 -1
  44. package/dist/gateway/static/root/assets/{extension-page-CEsq71Cm.js → extension-page-uGqvb8QX.js} +1 -1
  45. package/dist/gateway/static/root/assets/{extension-provider-CX-sK0Tw.js → extension-provider-xlSyz4Z6.js} +1 -1
  46. package/dist/gateway/static/root/assets/{extension-settings-page-UyOHF39P.js → extension-settings-page-CKHgrjOs.js} +1 -1
  47. package/dist/gateway/static/root/assets/{fallback-models-CKv_Wqg8.js → fallback-models-BwQg0G1D.js} +1 -1
  48. package/dist/gateway/static/root/assets/{gateway-config-swr-Cjnkle5J.js → gateway-config-swr-7RKqgU_U.js} +1 -1
  49. package/dist/gateway/static/root/assets/{gateway-realtime-DCCLdyQD.js → gateway-realtime-DDWymi-o.js} +1 -1
  50. package/dist/gateway/static/root/assets/gateway-realtime-store-BheKaO6d.js +1 -0
  51. package/dist/gateway/static/root/assets/gateway-settings-BAQnSEMJ.js +1 -0
  52. package/dist/gateway/static/root/assets/{gateway-startup-retry-CXKmdVzN.js → gateway-startup-retry-jiV5sbEX.js} +1 -1
  53. package/dist/gateway/static/root/assets/home-page-BZDjvwet.js +2 -0
  54. package/dist/gateway/static/root/assets/{image-generation-api-NLHzm4Nc.js → image-generation-api-DO4mXb6I.js} +1 -1
  55. package/dist/gateway/static/root/assets/{imports-page-C7qvlBTQ.js → imports-page-re1_Nh64.js} +1 -1
  56. package/dist/gateway/static/root/assets/index-BB1z8QxA.js +106 -0
  57. package/dist/gateway/static/root/assets/index-D9R6tU7r.css +1 -0
  58. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-pkgFWJb-.js → keyboard-shortcuts-settings-B_xja9LN.js} +1 -1
  59. package/dist/gateway/static/root/assets/{local-app-workbench-page-dMDhZXAi.js → local-app-workbench-page-CErdCrPX.js} +1 -1
  60. package/dist/gateway/static/root/assets/{local-apps-page-TpUAfOn2.js → local-apps-page-BPL2RXdK.js} +1 -1
  61. package/dist/gateway/static/root/assets/{local-session-drafts-Cvv7I0fw.js → local-session-drafts-DRPsDCj1.js} +1 -1
  62. package/dist/gateway/static/root/assets/{locale-store-C8TMD2gn.js → locale-store-COVscAqC.js} +1 -1
  63. package/dist/gateway/static/root/assets/logs-page-DL-BM0xq.js +2 -0
  64. package/dist/gateway/static/root/assets/management-settings-BOVRHhXk.js +1 -0
  65. package/dist/gateway/static/root/assets/{markdown-view-Dse7rkio.js → markdown-view-B_qnAcW2.js} +1 -1
  66. package/dist/gateway/static/root/assets/{media-plugins-BZrnzaBM.js → media-plugins-C0Pc-wSY.js} +1 -1
  67. package/dist/gateway/static/root/assets/messages-Bb2GK-Nj.js +3 -0
  68. package/dist/gateway/static/root/assets/models-hub-cache-DyPPksMP.js +1 -0
  69. package/dist/gateway/static/root/assets/note-detail-panel-DJJK2yL4.js +5 -0
  70. package/dist/gateway/static/root/assets/{notes-api-DKiVeQKG.js → notes-api-sBgBcyLW.js} +1 -1
  71. package/dist/gateway/static/root/assets/notes-page-oCxO7ZTv.js +8 -0
  72. package/dist/gateway/static/root/assets/{page-context-capture-button-Cxzd4QPB.js → page-context-capture-button-tf77xIz3.js} +1 -1
  73. package/dist/gateway/static/root/assets/personal-page-DOk9gUK5.js +1 -0
  74. package/dist/gateway/static/root/assets/{product-open-page-D4hoEWiu.js → product-open-page-Dc3Y-Y7J.js} +1 -1
  75. package/dist/gateway/static/root/assets/{product-preview-content-aR38El2E.js → product-preview-content-MG_hmVA3.js} +1 -1
  76. package/dist/gateway/static/root/assets/{project-detail-page-D20QH4YB.js → project-detail-page-3uAzbW4T.js} +1 -1
  77. package/dist/gateway/static/root/assets/{projects-page-Bf3BIcT6.js → projects-page-MllfNLGA.js} +1 -1
  78. package/dist/gateway/static/root/assets/{registry-api-AdnxowbH.js → registry-api-Bh9UBb-f.js} +1 -1
  79. package/dist/gateway/static/root/assets/remote-access-hub-Bs-C70el.js +1 -0
  80. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-CBN3raz1.js → runtime-tools-settings-panel-DpJ5jNzR.js} +1 -1
  81. package/dist/gateway/static/root/assets/scenes-page-Dpxamkw6.js +2 -0
  82. package/dist/gateway/static/root/assets/{schema-form-CxrMGsT9.js → schema-form-DUeyQ1zh.js} +1 -1
  83. package/dist/gateway/static/root/assets/{send-session-input-CgOzhDZ0.js → send-session-input-Dgn4BRk_.js} +1 -1
  84. package/dist/gateway/static/root/assets/{session-api-_HIN8or3.js → session-api-yjpEz4pP.js} +1 -1
  85. package/dist/gateway/static/root/assets/{session-manager-CzCto5zT.js → session-manager-LInoZ_Yi.js} +1 -1
  86. package/dist/gateway/static/root/assets/sessions-page-BCVlNHtq.js +1 -0
  87. package/dist/gateway/static/root/assets/settings-advanced-gate-Bz-ue9fZ.js +1 -0
  88. package/dist/gateway/static/root/assets/{settings-page-D8Q3H3-o.js → settings-page-DouHuBXt.js} +1 -1
  89. package/dist/gateway/static/root/assets/{setup-status-panel-DvLMMiuS.js → setup-status-panel-B5BoZ-1y.js} +1 -1
  90. package/dist/gateway/static/root/assets/{share-link-dialog-Dg5os066.js → share-link-dialog-DJTabLAM.js} +1 -1
  91. package/dist/gateway/static/root/assets/{share-preview-page-DMvohAyr.js → share-preview-page-jw7h4t_B.js} +1 -1
  92. package/dist/gateway/static/root/assets/{shares-api-C96IO4qJ.js → shares-api-c0dfWz6h.js} +1 -1
  93. package/dist/gateway/static/root/assets/shares-settings-BlnlzGjH.js +1 -0
  94. package/dist/gateway/static/root/assets/{skill-api-C10ML0CH.js → skill-api-CfyX_0zN.js} +1 -1
  95. package/dist/gateway/static/root/assets/{skill-reload-api-DNbJzSfB.js → skill-reload-api-Ge5XymHa.js} +1 -1
  96. package/dist/gateway/static/root/assets/{skills-page-DObMKvA6.js → skills-page-DjdTeYzm.js} +1 -1
  97. package/dist/gateway/static/root/assets/system-settings-panel-DWf256TE.js +1 -0
  98. package/dist/gateway/static/root/assets/{task-detail-page-BR2L1L8l.js → task-detail-page-DE6N1ZQe.js} +2 -2
  99. package/dist/gateway/static/root/assets/{task-expandable-content-DL2Q2gre.js → task-expandable-content-hYcgCEE3.js} +1 -1
  100. package/dist/gateway/static/root/assets/{theme-store-DQ6KJa4l.js → theme-store-BOfCKgl6.js} +1 -1
  101. package/dist/gateway/static/root/assets/{tracing-settings-page-Ed8_GYUT.js → tracing-settings-page-DDWFXcST.js} +1 -1
  102. package/dist/gateway/static/root/assets/{tunnel-api-D3X8jDwo.js → tunnel-api-BBm9esrY.js} +1 -1
  103. package/dist/gateway/static/root/assets/{usage-page-BqzRyyb9.js → usage-page-C93x89uW.js} +1 -1
  104. package/dist/gateway/static/root/assets/{use-autosave-CRFefpzO.js → use-autosave-CSckcjFx.js} +1 -1
  105. package/dist/gateway/static/root/assets/{use-composer-attachments-OLrvSjn5.js → use-composer-attachments-C7Gaaai1.js} +1 -1
  106. package/dist/gateway/static/root/assets/{use-file-preview-expanded-CJvzfQvw.js → use-file-preview-expanded-Db2VYg1b.js} +2 -2
  107. package/dist/gateway/static/root/assets/user-model-page-B74LkVbp.js +2 -0
  108. package/dist/gateway/static/root/assets/{voice-api-key-field-R9zNWYR_.js → voice-api-key-field-GEw5x2fU.js} +1 -1
  109. package/dist/gateway/static/root/assets/{voice-config-api-DLudE9Rc.js → voice-config-api-3yyVwXln.js} +1 -1
  110. package/dist/gateway/static/root/assets/{work-discovery-overlay-DVmQrolV.js → work-discovery-overlay-Bs2MKiTv.js} +1 -1
  111. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DEkmuD3T.js → workflow-run-setup-panel-BR_U_snV.js} +2 -2
  112. package/dist/gateway/static/root/assets/{workflows-page-pqCB3sh4.js → workflows-page-Crk4SxtC.js} +3 -3
  113. package/dist/gateway/static/root/assets/{workspace-api-CdVUhyPo.js → workspace-api-Si2o3inw.js} +2 -2
  114. package/dist/gateway/static/root/index.html +27 -28
  115. package/dist/package.js +1 -1
  116. package/dist/packages/browser-control-contract/src/automation.js +213 -0
  117. package/dist/packages/browser-control-contract/src/index.js +43 -12
  118. package/dist/packages/gateway-contract/src/gateway-scopes.js +3 -1
  119. package/dist/packages/gateway-contract/src/notifications.js +1 -0
  120. package/dist/packages/realtime-protocol/src/voice-catalog.js +7 -1
  121. package/dist/packages/realtime-protocol/src/voice.js +9 -3
  122. package/dist/src/agent/coding/repository-instructions.js +8 -1
  123. package/dist/src/agent/tool-manuals/browser.d.ts +1 -1
  124. package/dist/src/agent/tool-manuals/browser.js +3 -3
  125. package/dist/src/agent/tools/browser/tool/browser-use-tool.js +1 -1
  126. package/dist/src/agent/tools/browser/tool/schemas.d.ts +0 -13
  127. package/dist/src/agent/tools/browser/tool/schemas.js +0 -4
  128. package/dist/src/agent/tools/browser-automation-tool.d.ts +74 -1
  129. package/dist/src/agent/tools/browser-automation-tool.js +52 -6
  130. package/dist/src/agent-config/schema.d.ts +1 -1
  131. package/dist/src/agent-config/schema.js +1 -1
  132. package/dist/src/automations/capabilities/write.d.ts +2 -0
  133. package/dist/src/automations/domain/types.d.ts +11 -0
  134. package/dist/src/automations/domain/validation.d.ts +4 -0
  135. package/dist/src/automations/domain/validation.js +1 -0
  136. package/dist/src/automations/draft/automation-draft-validator.d.ts +1 -0
  137. package/dist/src/automations/service/action-executor.js +11 -3
  138. package/dist/src/automations/service/automation-service.d.ts +1 -0
  139. package/dist/src/automations/service/automation-service.js +13 -1
  140. package/dist/src/bootstrap/application-state.js +3 -1
  141. package/dist/src/browser/automations/repository.d.ts +4 -0
  142. package/dist/src/browser/automations/repository.js +27 -6
  143. package/dist/src/browser/automations/runner.js +101 -9
  144. package/dist/src/browser/automations/runtime-service.js +4 -3
  145. package/dist/src/browser/automations/schema.d.ts +84 -1
  146. package/dist/src/browser/automations/schema.js +68 -2
  147. package/dist/src/browser/automations/service.d.ts +78 -1
  148. package/dist/src/browser/automations/service.js +36 -4
  149. package/dist/src/browser/automations/types.d.ts +19 -4
  150. package/dist/src/browser/drivers/extension-driver.d.ts +5 -5
  151. package/dist/src/browser/drivers/extension-driver.js +10 -10
  152. package/dist/src/browser/drivers/playwright-driver.js +46 -0
  153. package/dist/src/browser/index.d.ts +1 -2
  154. package/dist/src/browser/index.js +2 -3
  155. package/dist/src/browser/policy/browser-policy.d.ts +0 -1
  156. package/dist/src/browser/policy/browser-policy.js +1 -4
  157. package/dist/src/browser/providers/index.d.ts +1 -1
  158. package/dist/src/browser/providers/index.js +2 -2
  159. package/dist/src/browser/providers/realtime-extension.d.ts +1 -1
  160. package/dist/src/browser/providers/realtime-extension.js +5 -1
  161. package/dist/src/browser/recordings/service.d.ts +22 -0
  162. package/dist/src/browser/recordings/service.js +160 -0
  163. package/dist/src/browser/runtime/browser-runtime.d.ts +1 -1
  164. package/dist/src/browser/runtime/browser-runtime.js +19 -56
  165. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  166. package/dist/src/computer/runtime.js +2 -2
  167. package/dist/src/config/schema.d.ts +12 -12
  168. package/dist/src/config/schema.js +12 -12
  169. package/dist/src/endpoint-tools/policy.js +4 -3
  170. package/dist/src/gateway/hono/routes/browser-automations.js +23 -7
  171. package/dist/src/gateway/hono/routes/browser-recordings.d.ts +3 -0
  172. package/dist/src/gateway/hono/routes/browser-recordings.js +78 -0
  173. package/dist/src/gateway/hono/routes/browser.js +1 -34
  174. package/dist/src/gateway/hono/routes/device-push.js +1 -0
  175. package/dist/src/gateway/hono/routes/home.js +1 -1
  176. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  177. package/dist/src/gateway/hono/routes/personal-agent.js +35 -0
  178. package/dist/src/gateway/hono/routes/voice.js +5 -2
  179. package/dist/src/gateway/security/gateway-scopes.js +3 -1
  180. package/dist/src/gateway/service/agent-runner.js +1 -0
  181. package/dist/src/home-intelligence/generator.d.ts +2 -0
  182. package/dist/src/home-intelligence/generator.js +53 -4
  183. package/dist/src/home-intelligence/host.d.ts +2 -1
  184. package/dist/src/home-intelligence/host.js +23 -3
  185. package/dist/src/migrations/cloud-public-models.d.ts +7 -0
  186. package/dist/src/migrations/cloud-public-models.js +157 -0
  187. package/dist/src/notifications/clarification.d.ts +5 -0
  188. package/dist/src/notifications/clarification.js +66 -0
  189. package/dist/src/notifications/device-store.js +1 -0
  190. package/dist/src/notifications/harmony-push.d.ts +1 -0
  191. package/dist/src/notifications/harmony-push.js +3 -1
  192. package/dist/src/notifications/planner.d.ts +1 -0
  193. package/dist/src/notifications/service.d.ts +2 -2
  194. package/dist/src/notifications/service.js +20 -4
  195. package/dist/src/notifications/store.d.ts +2 -0
  196. package/dist/src/notifications/store.js +7 -1
  197. package/dist/src/notifications/types.d.ts +1 -0
  198. package/dist/src/notifications/types.js +1 -0
  199. package/dist/src/providers/model-catalog-persistence.js +2 -2
  200. package/dist/src/providers/presentation.js +1 -0
  201. package/dist/src/providers/xopc-cloud-model-source.js +1 -1
  202. package/dist/src/storage/sqlite/clarification-wait-repository.js +1 -0
  203. package/dist/src/storage/sqlite/migrations/238_browser_record_replay.sql +45 -0
  204. package/dist/src/storage/sqlite/migrations/239_clarification_notifications.sql +26 -0
  205. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  206. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  207. package/dist/src/storage/sqlite/schema.js +1 -1
  208. package/dist/src/tasks/home-query-service.d.ts +1 -1
  209. package/dist/src/tasks/home-query-service.js +6 -2
  210. package/dist/src/voice/dashscope/streaming-tts-stream.d.ts +2 -1
  211. package/dist/src/voice/dashscope/streaming-tts-stream.js +135 -79
  212. package/dist/src/voice/metadata/types.d.ts +1 -0
  213. package/dist/src/voice/platform-catalog.d.ts +4 -0
  214. package/dist/src/voice/platform-settings.js +1 -0
  215. package/dist/src/voice/realtime/agentEngine.js +78 -1
  216. package/dist/src/voice/realtime/speakable-segmenter.d.ts +2 -0
  217. package/dist/src/voice/realtime/speakable-segmenter.js +30 -0
  218. package/dist/src/voice/tts/providers/alibaba-speech.js +17 -1
  219. package/dist/src/voice/tts/providers/xopc-cloud-speech.js +3 -2
  220. package/dist/src/voice/tts/speak-core.d.ts +3 -0
  221. package/dist/src/voice/tts/speak-core.js +21 -1
  222. package/dist/src/voice/tts/speech-provider-types.d.ts +8 -0
  223. package/package.json +3 -3
  224. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-gT9_j4tr.js +0 -1
  225. package/dist/gateway/static/root/assets/agent-plugin-dialog-CLXCJ6JN.js +0 -1
  226. package/dist/gateway/static/root/assets/agents-BAUfOMsq.js +0 -66
  227. package/dist/gateway/static/root/assets/app-management-settings-panel-CoIFxQKH.js +0 -1
  228. package/dist/gateway/static/root/assets/automations-workspace-BCGPjsdU.js +0 -6
  229. package/dist/gateway/static/root/assets/browser-automation-inputs-BUAIKIX0.js +0 -1
  230. package/dist/gateway/static/root/assets/browser-automations-page-CSwu1U1F.js +0 -3
  231. package/dist/gateway/static/root/assets/browser-settings-page-C1ReMNqX.js +0 -3
  232. package/dist/gateway/static/root/assets/capabilities-page-BdTSqloI.js +0 -2
  233. package/dist/gateway/static/root/assets/capabilities-settings-panel-BUblBMZC.js +0 -8
  234. package/dist/gateway/static/root/assets/channels-CXCf5qO6.js +0 -1
  235. package/dist/gateway/static/root/assets/computer-settings-page-B5SuSZ3G.js +0 -1
  236. package/dist/gateway/static/root/assets/connectors-page-DfnK1crf.js +0 -2
  237. package/dist/gateway/static/root/assets/device-pairing-wizard-s2ogSa4l.js +0 -1
  238. package/dist/gateway/static/root/assets/gateway-realtime-store-C_Th8kGg.js +0 -1
  239. package/dist/gateway/static/root/assets/gateway-settings-CZ73IpbP.js +0 -1
  240. package/dist/gateway/static/root/assets/home-page-BQWq4kYi.js +0 -2
  241. package/dist/gateway/static/root/assets/index-BQgqzhQj.js +0 -106
  242. package/dist/gateway/static/root/assets/index-COB4QIJp.css +0 -1
  243. package/dist/gateway/static/root/assets/logs-page-B-Y9oZLh.js +0 -2
  244. package/dist/gateway/static/root/assets/management-settings-B2lzsw6X.js +0 -1
  245. package/dist/gateway/static/root/assets/messages-Dy26npMy.js +0 -3
  246. package/dist/gateway/static/root/assets/models-hub-cache-B1C86nRp.js +0 -1
  247. package/dist/gateway/static/root/assets/note-detail-panel-DL__qP6U.js +0 -5
  248. package/dist/gateway/static/root/assets/notes-page-DTBbg9Hs.js +0 -8
  249. package/dist/gateway/static/root/assets/oauth-api-BwpzpRwC.js +0 -1
  250. package/dist/gateway/static/root/assets/personal-page-CzaTnHeD.js +0 -1
  251. package/dist/gateway/static/root/assets/remote-access-hub-CKxqncqW.js +0 -1
  252. package/dist/gateway/static/root/assets/scenes-page-Cv_5ozfX.js +0 -2
  253. package/dist/gateway/static/root/assets/sessions-page-DZcu6NLJ.js +0 -1
  254. package/dist/gateway/static/root/assets/settings-advanced-gate-DazqeDQ7.js +0 -1
  255. package/dist/gateway/static/root/assets/shares-settings-CsDATuCw.js +0 -1
  256. package/dist/gateway/static/root/assets/system-settings-panel-Bn3khdzb.js +0 -1
  257. package/dist/gateway/static/root/assets/user-model-page-CG6wqIKP.js +0 -2
  258. package/dist/src/browser/policy/approval-store.d.ts +0 -17
  259. package/dist/src/browser/policy/approval-store.js +0 -62
  260. package/dist/src/browser/providers/extension-ws-acquire.d.ts +0 -19
  261. package/dist/src/browser/providers/extension-ws-acquire.js +0 -78
  262. package/dist/src/browser/providers/extension.d.ts +0 -61
  263. package/dist/src/browser/providers/extension.js +0 -378
@@ -109,6 +109,8 @@ export declare const HomeModelResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject
109
109
  }, z.core.$strict>], "state">;
110
110
  export type HomeModelCandidate = z.infer<typeof HomeModelCandidateSchema>;
111
111
  export type HomeModelResult = z.infer<typeof HomeModelResultSchema>;
112
+ /** Check prose rather than identifiers so English evidence cannot override Chinese output. */
113
+ export declare function isHomeProseLocalized(values: readonly string[], locale: HomeContextSnapshot['locale']): boolean;
112
114
  export interface HomeModelGeneration {
113
115
  result: HomeModelResult;
114
116
  modelRef: string;
@@ -102,7 +102,8 @@ function buildSystemPrompt(locale) {
102
102
  "Prefer outcomes over feature promotion. Mention a connector or skill only when it materially enables the outcome.",
103
103
  "When useful work remains possible without a missing capability, provide degradedActionPrompt using only supplied evidence.",
104
104
  "External writes always require user confirmation.",
105
- `Write only user-visible prose values such as title, rationale, steps, and prompts in ${locale === "zh" ? "Simplified Chinese" : "English"}. Machine values listed above must remain in English.`
105
+ `Write all user-visible prose values (title, outcome, rationale, proposedSteps, verification, actionPrompt, degradedActionPrompt, question, and option labels) in ${locale === "zh" ? "Simplified Chinese" : "English"}. Machine values listed above must remain in English. Translate English source material into the requested language; keep technical identifiers and proper names intact.`,
106
+ "Use plain text in prose values. Do not HTML-encode characters or include HTML markup."
106
107
  ].join("\n");
107
108
  }
108
109
  function extractHomeResponseText(response) {
@@ -126,6 +127,54 @@ function parseJson(raw) {
126
127
  }
127
128
  throw new Error("Home intelligence model did not return valid JSON");
128
129
  }
130
+ function decodeProse(value) {
131
+ const named = {
132
+ amp: "&",
133
+ lt: "<",
134
+ gt: ">",
135
+ quot: "\"",
136
+ apos: "'",
137
+ nbsp: " "
138
+ };
139
+ return value.replace(/&(#x[0-9a-f]+|#\d+|amp|lt|gt|quot|apos|nbsp);/gi, (entity, code) => {
140
+ if (!code.startsWith("#")) return named[code.toLowerCase()] ?? entity;
141
+ const point = code.toLowerCase().startsWith("#x") ? parseInt(code.slice(2), 16) : Number(code.slice(1));
142
+ return point > 0 && point <= 1114111 && !(point >= 55296 && point <= 57343) ? String.fromCodePoint(point) : entity;
143
+ });
144
+ }
145
+ /** Check prose rather than identifiers so English evidence cannot override Chinese output. */
146
+ function isHomeProseLocalized(values, locale) {
147
+ return locale !== "zh" || values.every((value) => !/[a-z]/i.test(value) || /\p{Script=Han}/u.test(value));
148
+ }
149
+ function parseLocalizedResult(raw, locale) {
150
+ const result = HomeModelResultSchema.parse(parseJson(raw));
151
+ const prose = [];
152
+ if (result.state === "ready") for (const candidate of result.candidates) {
153
+ candidate.title = decodeProse(candidate.title);
154
+ candidate.outcome = decodeProse(candidate.outcome);
155
+ candidate.rationale = decodeProse(candidate.rationale);
156
+ candidate.proposedSteps = candidate.proposedSteps.map(decodeProse);
157
+ candidate.verification = candidate.verification.map(decodeProse);
158
+ candidate.actionPrompt = decodeProse(candidate.actionPrompt);
159
+ if (candidate.degradedActionPrompt) candidate.degradedActionPrompt = decodeProse(candidate.degradedActionPrompt);
160
+ prose.push(candidate.title, candidate.outcome, candidate.rationale, candidate.actionPrompt);
161
+ prose.push(...[
162
+ ...candidate.proposedSteps,
163
+ ...candidate.verification,
164
+ candidate.degradedActionPrompt ?? ""
165
+ ].filter((value) => (value.match(/[a-z]+/gi)?.length ?? 0) >= 3));
166
+ }
167
+ else if (result.state === "clarification") {
168
+ result.question = decodeProse(result.question);
169
+ result.options = result.options.map((option) => ({
170
+ ...option,
171
+ label: decodeProse(option.label)
172
+ }));
173
+ prose.push(result.question, ...result.options.map((option) => option.label).filter((value) => (value.match(/[a-z]+/gi)?.length ?? 0) >= 3));
174
+ }
175
+ if (!isHomeProseLocalized(prose, locale)) throw new Error("User-visible prose must be in Simplified Chinese; translate English source material while preserving identifiers and evidence IDs");
176
+ return result;
177
+ }
129
178
  function validationSummary(error) {
130
179
  if (!(error instanceof z.ZodError)) return error instanceof Error ? error.message : String(error);
131
180
  return error.issues.slice(0, 20).map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`).join("; ");
@@ -194,7 +243,7 @@ var HomeAdviceGenerator = class {
194
243
  const raw = extractHomeResponseText(response);
195
244
  let result;
196
245
  try {
197
- result = HomeModelResultSchema.parse(parseJson(raw));
246
+ result = parseLocalizedResult(raw, snapshot.locale);
198
247
  } catch (firstError) {
199
248
  const correction = {
200
249
  role: "user",
@@ -221,7 +270,7 @@ var HomeAdviceGenerator = class {
221
270
  trigger: "retry"
222
271
  });
223
272
  try {
224
- result = HomeModelResultSchema.parse(parseJson(extractHomeResponseText(corrected)));
273
+ result = parseLocalizedResult(extractHomeResponseText(corrected), snapshot.locale);
225
274
  } catch (correctionError) {
226
275
  throw new Error(`Home intelligence model returned invalid structured JSON after correction: ${validationSummary(correctionError)}`);
227
276
  }
@@ -239,4 +288,4 @@ var HomeAdviceGenerator = class {
239
288
  }
240
289
  };
241
290
  //#endregion
242
- export { HomeAdviceBudgetExceededError, HomeAdviceGenerator, HomeModelCandidateSchema, HomeModelResultSchema };
291
+ export { HomeAdviceBudgetExceededError, HomeAdviceGenerator, HomeModelCandidateSchema, HomeModelResultSchema, isHomeProseLocalized };
@@ -35,12 +35,13 @@ export declare class HomeIntelligenceHost {
35
35
  private stopped;
36
36
  private abortController;
37
37
  private localeHint;
38
+ private advisorLocale;
38
39
  private contextRefreshTimer?;
39
40
  private readonly pendingContextReasons;
40
41
  constructor(db: DatabaseSync, deps: HomeIntelligenceHostDeps);
41
42
  start(): void;
42
43
  stop(): void;
43
- getAdvisor(): HomeAdvisor;
44
+ getAdvisor(locale?: string): HomeAdvisor;
44
45
  getMetrics(since?: number): HomeAdviceMetrics;
45
46
  getHistory(): HomeOpportunityHistoryItem[];
46
47
  requestRefresh(reason: HomeGenerationReason, idempotencyKey?: string, locale?: string): string;
@@ -1,6 +1,6 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
- import { HomeAdviceBudgetExceededError } from "./generator.js";
3
+ import { HomeAdviceBudgetExceededError, isHomeProseLocalized } from "./generator.js";
4
4
  import { homePatternKey } from "./strategy.js";
5
5
  import { HomeAdvicePolicy } from "./policy.js";
6
6
  import { HomeIntelligenceRepository } from "./repository.js";
@@ -39,6 +39,7 @@ var HomeIntelligenceHost = class {
39
39
  stopped = false;
40
40
  abortController = new AbortController();
41
41
  localeHint;
42
+ advisorLocale;
42
43
  contextRefreshTimer;
43
44
  pendingContextReasons = /* @__PURE__ */ new Set();
44
45
  constructor(db, deps) {
@@ -47,6 +48,7 @@ var HomeIntelligenceHost = class {
47
48
  this.opportunities = new HomeOpportunityApplicationService(db, deps.principal, () => deps.capabilities().agentId);
48
49
  this.now = deps.now ?? Date.now;
49
50
  this.localeHint = deps.locale();
51
+ this.advisorLocale = this.localeHint;
50
52
  }
51
53
  start() {
52
54
  if (this.timer) return;
@@ -65,9 +67,26 @@ var HomeIntelligenceHost = class {
65
67
  this.contextRefreshTimer = void 0;
66
68
  this.pendingContextReasons.clear();
67
69
  }
68
- getAdvisor() {
70
+ getAdvisor(locale) {
69
71
  if (this.deps.enabled?.() === false) return { state: "disabled" };
70
- return this.repository.getAdvisor(this.deps.principal, this.now());
72
+ if (locale) {
73
+ const requestedLocale = locale.toLowerCase().startsWith("zh") ? "zh" : "en";
74
+ if (requestedLocale !== this.localeHint) this.requestRefresh("manual_refresh", `locale:${requestedLocale}:${this.now()}`, requestedLocale);
75
+ }
76
+ const advisor = this.repository.getAdvisor(this.deps.principal, this.now());
77
+ const prose = advisor.state === "ready" ? [advisor.primary, ...advisor.alternatives].flatMap((item) => [
78
+ item.title,
79
+ item.outcome,
80
+ item.rationale
81
+ ]) : advisor.state === "clarification" ? [advisor.question.question] : [];
82
+ if (prose.length > 0 && this.advisorLocale !== this.localeHint || !isHomeProseLocalized(prose, this.localeHint)) return advisor.state === "ready" && advisor.stale ? {
83
+ state: "refreshing",
84
+ requestedAt: this.now()
85
+ } : {
86
+ state: "quiet",
87
+ reason: "generation_failed"
88
+ };
89
+ return advisor;
71
90
  }
72
91
  getMetrics(since = Math.max(0, this.now() - 720 * 60 * 6e4)) {
73
92
  return this.repository.getMetrics(this.deps.principal, since, this.now());
@@ -251,6 +270,7 @@ var HomeIntelligenceHost = class {
251
270
  outcomeReason: result.state === "quiet" ? result.reason : result.state,
252
271
  completedAt
253
272
  });
273
+ this.advisorLocale = snapshot.locale;
254
274
  this.deps.publish("home.advisor.updated", {
255
275
  state: result.state,
256
276
  completedAt
@@ -0,0 +1,7 @@
1
+ type Kind = 'language' | 'image' | 'stt' | 'tts' | 'omni' | 'computer';
2
+ export declare function migrateCloudModelRef(ref: string, kind?: Kind): string;
3
+ /** Only model fields are rewritten; prompts and historical transcripts are untouched. */
4
+ export declare function migrateCloudModelFields(value: unknown, kind?: Kind, cloud?: boolean, modelField?: boolean): unknown;
5
+ /** Replayable file phase followed by a transactional database phase and completion marker. */
6
+ export declare function migrateCloudPublicModelsSync(configPath: string): boolean;
7
+ export {};
@@ -0,0 +1,157 @@
1
+ import { init_paths_state, resolveXopcCloudCatalogCachePath } from "../config/paths-state.js";
2
+ import { getSqliteDatabase, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
3
+ import { init_sqlite } from "../storage/sqlite/index.js";
4
+ import { init_write_file_atomic, writeTextAtomicSync } from "../infra/write-file-atomic.js";
5
+ import { ModelCatalogPersistence, init_model_catalog_persistence } from "../providers/model-catalog-persistence.js";
6
+ import { createWorkflowCatalog } from "../agent/workflow/catalog.js";
7
+ import { dirname } from "node:path";
8
+ import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync } from "node:fs";
9
+ import { randomUUID } from "node:crypto";
10
+ //#region src/migrations/cloud-public-models.ts
11
+ init_paths_state();
12
+ init_write_file_atomic();
13
+ init_sqlite();
14
+ init_model_catalog_persistence();
15
+ const MIGRATION_ID = "cloud-public-models-v1";
16
+ const PUBLIC_IDS = new Set([
17
+ "auto",
18
+ "advanced",
19
+ "image",
20
+ "stt",
21
+ "tts",
22
+ "realtime",
23
+ "computer"
24
+ ]);
25
+ const MODEL_FIELDS = new Set([
26
+ "model",
27
+ "modelRef",
28
+ "modelOverride",
29
+ "primary",
30
+ "fallbacks",
31
+ "imageGeneration",
32
+ "imageUnderstanding",
33
+ "computerUse"
34
+ ]);
35
+ function migrateCloudModelRef(ref, kind = "language") {
36
+ if (!ref.startsWith("xopc-cloud/")) return ref;
37
+ const id = ref.slice(11);
38
+ if (PUBLIC_IDS.has(id) || id.startsWith("openai-codex/")) return ref;
39
+ if (id === "computer-gui-plus-preview" || id === "gui-plus-2026-02-26") return "xopc-cloud/computer";
40
+ return `xopc-cloud/${kind === "omni" ? "realtime" : kind === "language" ? "auto" : kind}`;
41
+ }
42
+ /** Only model fields are rewritten; prompts and historical transcripts are untouched. */
43
+ function migrateCloudModelFields(value, kind = "language", cloud = false, modelField = false) {
44
+ if (typeof value === "string") {
45
+ if (!modelField) return value;
46
+ const next = migrateCloudModelRef(cloud && !value.includes("/") ? `xopc-cloud/${value}` : value, kind);
47
+ return cloud && !value.includes("/") ? next.replace(/^xopc-cloud\//, "") : next;
48
+ }
49
+ if (Array.isArray(value)) {
50
+ const next = value.map((item) => migrateCloudModelFields(item, kind, cloud, modelField));
51
+ return modelField && next.some((item, index) => item !== value[index]) ? [...new Set(next)] : next;
52
+ }
53
+ if (!value || typeof value !== "object") return value;
54
+ const source = value;
55
+ const explicitProvider = source.provider ?? source.providerOverride;
56
+ const isCloud = typeof explicitProvider === "string" ? explicitProvider === "xopc-cloud" : cloud;
57
+ const result = {};
58
+ for (const [key, item] of Object.entries(source)) {
59
+ if (key === "providers" && item && typeof item === "object" && !Array.isArray(item)) {
60
+ result[key] = Object.fromEntries(Object.entries(item).map(([provider, settings]) => [provider, migrateCloudModelFields(settings, kind, provider === "xopc-cloud")]));
61
+ continue;
62
+ }
63
+ result[key] = migrateCloudModelFields(item, key === "imageGeneration" ? "image" : key === "computerUse" ? "computer" : key === "summarization" || key === "refinement" ? "language" : key === "stt" || key === "audio" ? "stt" : key === "tts" ? "tts" : key === "omni" ? "omni" : kind, isCloud || key === "xopc-cloud", MODEL_FIELDS.has(key));
64
+ }
65
+ if (isCloud && (kind === "tts" || kind === "omni") && (source.voice !== void 0 || typeof source.model === "string")) result.voice = "default";
66
+ if (typeof result.primary === "string" && result.primary.startsWith("xopc-cloud/") && (result.primary !== source.primary || JSON.stringify(result.fallbacks) !== JSON.stringify(source.fallbacks)) && Array.isArray(result.fallbacks)) result.fallbacks = result.fallbacks.filter((ref) => ref !== result.primary);
67
+ return result;
68
+ }
69
+ /** Replayable file phase followed by a transactional database phase and completion marker. */
70
+ function migrateCloudPublicModelsSync(configPath) {
71
+ const db = getSqliteDatabase();
72
+ if (db.prepare("SELECT 1 FROM application_migrations WHERE id = ? AND state = ?").get(MIGRATION_ID, "complete")) return false;
73
+ const now = Date.now();
74
+ const databaseBackup = `${configPath}.${MIGRATION_ID}.sqlite.bak`;
75
+ if (!existsSync(databaseBackup)) {
76
+ mkdirSync(dirname(databaseBackup), {
77
+ recursive: true,
78
+ mode: 448
79
+ });
80
+ const temporary = `${databaseBackup}.${randomUUID()}.tmp`;
81
+ try {
82
+ db.prepare("VACUUM INTO ?").run(temporary);
83
+ chmodSync(temporary, 384);
84
+ renameSync(temporary, databaseBackup);
85
+ } finally {
86
+ rmSync(temporary, { force: true });
87
+ }
88
+ }
89
+ const configBackup = `${configPath}.${MIGRATION_ID}.bak`;
90
+ if (existsSync(configPath)) {
91
+ const raw = readFileSync(configPath, "utf8");
92
+ const next = JSON.stringify(migrateCloudModelFields(JSON.parse(raw)), null, 2) + "\n";
93
+ if (JSON.stringify(JSON.parse(raw)) !== JSON.stringify(JSON.parse(next))) {
94
+ if (!existsSync(configBackup)) copyFileSync(configPath, configBackup);
95
+ writeTextAtomicSync(configPath, next);
96
+ }
97
+ }
98
+ const cache = resolveXopcCloudCatalogCachePath();
99
+ if (existsSync(cache) && !existsSync(`${cache}.${MIGRATION_ID}.bak`)) copyFileSync(cache, `${cache}.${MIGRATION_ID}.bak`);
100
+ new ModelCatalogPersistence().clearSync();
101
+ return runSqliteWriteTransaction(() => {
102
+ if (db.prepare("SELECT 1 FROM application_migrations WHERE id = ? AND state = ?").get(MIGRATION_ID, "complete")) return false;
103
+ const migrateJson = (table, key, column, where = "") => {
104
+ const rows = db.prepare(`SELECT ${key} AS id, ${column} AS payload FROM ${table} ${where}`).all();
105
+ for (const row of rows) {
106
+ const before = JSON.parse(row.payload);
107
+ const next = JSON.stringify(migrateCloudModelFields(before));
108
+ if (JSON.stringify(before) !== next) {
109
+ const revision = table === "agents" || table === "agent_catalog_settings" ? ", revision = revision + 1, updated_at = " + now : "";
110
+ db.prepare(`UPDATE ${table} SET ${column} = ? ${revision} WHERE ${key} = ?`).run(next, row.id);
111
+ }
112
+ }
113
+ };
114
+ migrateJson("agent_catalog_settings", "singleton_id", "defaults_json");
115
+ migrateJson("agents", "id", "overrides_json", "WHERE deleted_at IS NULL");
116
+ migrateJson("automations", "automation_id", "action_json");
117
+ const rows = db.prepare("SELECT rowid AS id, payload FROM durable_state WHERE namespace IN ('workflow-drafts')").all();
118
+ for (const row of rows) {
119
+ const before = JSON.parse(row.payload);
120
+ const next = JSON.stringify(migrateCloudModelFields(before));
121
+ if (JSON.stringify(before) !== next) db.prepare("UPDATE durable_state SET payload = ? WHERE rowid = ?").run(next, row.id);
122
+ }
123
+ const catalog = createWorkflowCatalog();
124
+ for (const entry of catalog.list().filter((item) => item.source === "user")) {
125
+ const definition = catalog.load(entry.name);
126
+ const graph = migrateCloudModelFields(definition.graph);
127
+ if (JSON.stringify(graph) !== JSON.stringify(definition.graph)) {
128
+ const { graph: _graph, metadata: _metadata, contentHash: _hash, revision: _revision, ...manifest } = definition;
129
+ catalog.save({
130
+ name: entry.name,
131
+ graph,
132
+ manifest: {
133
+ ...manifest,
134
+ tags: definition.metadata.tags,
135
+ whenToUse: definition.metadata.whenToUse,
136
+ estimatedAgents: definition.metadata.estimatedAgents,
137
+ examplePrompts: definition.metadata.examplePrompts,
138
+ i18n: definition.metadata.i18n
139
+ },
140
+ expectedRevision: definition.revision
141
+ });
142
+ }
143
+ }
144
+ const sessions = db.prepare("SELECT conversation_id, model_override, provider_override FROM session_config WHERE model_override IS NOT NULL").all();
145
+ for (const row of sessions) {
146
+ const ref = row.provider_override === "xopc-cloud" && !row.model_override.includes("/") ? `xopc-cloud/${row.model_override}` : row.model_override;
147
+ const migrated = migrateCloudModelRef(ref);
148
+ const next = ref === row.model_override ? migrated : migrated.replace(/^xopc-cloud\//, "");
149
+ if (next !== row.model_override) db.prepare("UPDATE session_config SET model_override = ?, updated_at = ? WHERE conversation_id = ?").run(next, now, row.conversation_id);
150
+ }
151
+ db.prepare(`INSERT INTO application_migrations(id,state,source_backup_path,database_backup_path,started_at,completed_at,updated_at)
152
+ VALUES(?,?,?,?,?,?,?) ON CONFLICT(id) DO UPDATE SET state=excluded.state, completed_at=excluded.completed_at, updated_at=excluded.updated_at`).run(MIGRATION_ID, "complete", existsSync(configBackup) ? configBackup : null, databaseBackup, now, now, now);
153
+ return true;
154
+ });
155
+ }
156
+ //#endregion
157
+ export { migrateCloudModelFields, migrateCloudModelRef, migrateCloudPublicModelsSync };
@@ -0,0 +1,5 @@
1
+ import type { ProductNotification } from '@xopcai/gateway-contract';
2
+ import type { NotificationPlan } from './planner.js';
3
+ export declare function isClarificationNotificationActionable(notification: Pick<ProductNotification, 'type' | 'payload' | 'target'>): boolean;
4
+ /** Wait creation and intent insertion commit together; publication and settlement do too. */
5
+ export declare function flushClarificationNotifications(persist: (plan: NotificationPlan) => ProductNotification | null): ProductNotification[];
@@ -0,0 +1,66 @@
1
+ import { getSqliteDatabase, init_transaction, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
2
+ import { init_session_instance_repository, readCurrentTranscriptId } from "../storage/sqlite/session-instance-repository.js";
3
+ import { getClarification, init_clarification_wait_repository } from "../storage/sqlite/clarification-wait-repository.js";
4
+ //#region src/notifications/clarification.ts
5
+ init_clarification_wait_repository();
6
+ init_session_instance_repository();
7
+ init_transaction();
8
+ function isClarificationNotificationActionable(notification) {
9
+ if (notification.type !== "chat.needs_input") return true;
10
+ const wait = typeof notification.payload.waitId === "string" ? getClarification(notification.payload.waitId) : void 0;
11
+ return Boolean(wait && wait.status === "open" && notification.target.kind === "chat" && notification.target.conversationId === wait.conversationId && readCurrentTranscriptId(getSqliteDatabase(), wait.conversationId) === wait.transcriptId && (wait.expiresAt === void 0 || wait.expiresAt > Date.now()));
12
+ }
13
+ /** Wait creation and intent insertion commit together; publication and settlement do too. */
14
+ function flushClarificationNotifications(persist) {
15
+ return runSqliteWriteTransaction((db) => {
16
+ const rows = db.prepare(`SELECT wait_id FROM clarification_notification_outbox
17
+ WHERE status = 'pending' ORDER BY created_at, wait_id LIMIT 100`).all();
18
+ const published = [];
19
+ for (const row of rows) {
20
+ const wait = getClarification(String(row.wait_id));
21
+ if (wait && !wait.taskRunId) {
22
+ const personal = db.prepare("SELECT json_extract(custom_data_json, '$.personalAgent') AS personal FROM sessions WHERE conversation_id = ?").get(wait.conversationId)?.personal === 1;
23
+ const notification = {
24
+ type: "chat.needs_input",
25
+ target: {
26
+ kind: "chat",
27
+ conversationId: wait.conversationId,
28
+ ...personal ? { personal: true } : {}
29
+ },
30
+ priority: "high",
31
+ title: wait.kind === "approval" ? {
32
+ en: "Your authorization is needed",
33
+ zh: "需要你的授权"
34
+ } : {
35
+ en: "Your decision is needed",
36
+ zh: "需要你判断后继续"
37
+ },
38
+ body: {
39
+ en: "A question is waiting for your answer. Open the conversation to continue.",
40
+ zh: "有一个问题等待你回答,点击继续。"
41
+ },
42
+ payload: {
43
+ waitId: wait.id,
44
+ transcriptId: wait.transcriptId,
45
+ originRunId: wait.originRunId,
46
+ objectiveRevision: wait.objectiveRevision,
47
+ kind: wait.kind,
48
+ expiresAt: wait.expiresAt
49
+ }
50
+ };
51
+ if (isClarificationNotificationActionable(notification)) {
52
+ const event = persist({
53
+ dedupeKey: `clarification.needs_input:${wait.id}`,
54
+ createdAt: wait.createdAt,
55
+ notification
56
+ });
57
+ if (event) published.push(event);
58
+ }
59
+ }
60
+ db.prepare("UPDATE clarification_notification_outbox SET status = 'settled' WHERE wait_id = ?").run(row.wait_id);
61
+ }
62
+ return published;
63
+ });
64
+ }
65
+ //#endregion
66
+ export { flushClarificationNotifications, isClarificationNotificationActionable };
@@ -13,6 +13,7 @@ function parsePreferences(raw) {
13
13
  }
14
14
  function normalizePreferences(input) {
15
15
  return {
16
+ chatNeedsInput: input?.chatNeedsInput ?? DEFAULT_NOTIFICATION_PREFERENCES.chatNeedsInput,
16
17
  chatCompleted: input?.chatCompleted ?? DEFAULT_NOTIFICATION_PREFERENCES.chatCompleted,
17
18
  chatFailed: input?.chatFailed ?? DEFAULT_NOTIFICATION_PREFERENCES.chatFailed,
18
19
  taskNeedsInput: input?.taskNeedsInput ?? DEFAULT_NOTIFICATION_PREFERENCES.taskNeedsInput,
@@ -18,6 +18,7 @@ export type HarmonyNotification = {
18
18
  body?: string;
19
19
  gatewayId?: string;
20
20
  target?: NotificationTarget;
21
+ expiresAt?: number;
21
22
  };
22
23
  export declare function harmonyPushConfig(env?: NodeJS.ProcessEnv): HarmonyPushConfig | undefined;
23
24
  export declare function createHarmonyPushJwt(account: ServiceAccount, now?: number): string;
@@ -54,6 +54,8 @@ async function sendHarmonyPush(notification, fetchImpl = fetch, config = harmony
54
54
  eventId: notification.eventId,
55
55
  target: notification.target
56
56
  })).toString("base64url") : void 0;
57
+ const ttl = notification.expiresAt === void 0 ? 86400 : Math.min(86400, Math.floor((notification.expiresAt - Date.now()) / 1e3));
58
+ if (ttl <= 0) throw new Error("Notification expired before delivery");
57
59
  const response = await fetchImpl(`https://push-api.cloud.huawei.com/v3/${account.project_id}/messages:send`, {
58
60
  method: "POST",
59
61
  redirect: "error",
@@ -78,7 +80,7 @@ async function sendHarmonyPush(notification, fetchImpl = fetch, config = harmony
78
80
  target: { token: [notification.pushToken] },
79
81
  pushOptions: {
80
82
  testMessage: config.testMessage,
81
- ttl: 86400
83
+ ttl
82
84
  }
83
85
  })
84
86
  });
@@ -1,5 +1,6 @@
1
1
  import { type ProductNotification } from '@xopcai/gateway-contract';
2
2
  export type NotificationPlan = {
3
+ createdAt?: number;
3
4
  dedupeKey: string;
4
5
  notification: Omit<ProductNotification, 'schemaVersion' | 'id' | 'createdAt'>;
5
6
  };
@@ -21,7 +21,7 @@ export declare class NotificationService {
21
21
  persistGatewayEvent(type: string, payload: unknown): {
22
22
  schemaVersion: 1;
23
23
  id: string;
24
- type: "work_discovery.completed" | "work_discovery.failed" | "scene.result" | "scene.digest" | "chat.completed" | "chat.failed" | "task.needs_input" | "task.blocked" | "task.failed" | "task.completed" | "automation.completed" | "automation.failed" | "home.opportunity";
24
+ type: "work_discovery.completed" | "work_discovery.failed" | "scene.result" | "scene.digest" | "chat.needs_input" | "chat.completed" | "chat.failed" | "task.needs_input" | "task.blocked" | "task.failed" | "task.completed" | "automation.completed" | "automation.failed" | "home.opportunity";
25
25
  priority: "normal" | "high";
26
26
  title: {
27
27
  en: string;
@@ -62,7 +62,7 @@ export declare class NotificationService {
62
62
  persistPlan(plan: NotificationPlan): {
63
63
  schemaVersion: 1;
64
64
  id: string;
65
- type: "work_discovery.completed" | "work_discovery.failed" | "scene.result" | "scene.digest" | "chat.completed" | "chat.failed" | "task.needs_input" | "task.blocked" | "task.failed" | "task.completed" | "automation.completed" | "automation.failed" | "home.opportunity";
65
+ type: "work_discovery.completed" | "work_discovery.failed" | "scene.result" | "scene.digest" | "chat.needs_input" | "chat.completed" | "chat.failed" | "task.needs_input" | "task.blocked" | "task.failed" | "task.completed" | "automation.completed" | "automation.failed" | "home.opportunity";
66
66
  priority: "normal" | "high";
67
67
  title: {
68
68
  en: string;
@@ -4,13 +4,14 @@ import { init_transaction, runSqliteWriteTransaction } from "../storage/sqlite/t
4
4
  import { localizeNotification } from "../../packages/gateway-contract/src/notifications.js";
5
5
  import { init_src } from "../../packages/gateway-contract/src/index.js";
6
6
  import { getOrCreateGatewayIdentity, init_gateway_identity_repository } from "../storage/sqlite/gateway-identity-repository.js";
7
- import { listDeliverableNotificationDevices } from "./device-store.js";
7
+ import { getNotificationDevice, listDeliverableNotificationDevices } from "./device-store.js";
8
8
  import { notificationPlanFromGatewayEvent } from "./planner.js";
9
- import { createNotificationEvent, deferNotificationDelivery, expireUndeliverableNotificationDeliveries, listDueNotificationDeliveries, markNotificationDeliveryAccepted, markNotificationDeliveryDead, pruneNotificationEvents, rescheduleNotificationDelivery } from "./store.js";
9
+ import { cancelNotificationDelivery, createNotificationEvent, deferNotificationDelivery, expireUndeliverableNotificationDeliveries, listDueNotificationDeliveries, markNotificationDeliveryAccepted, markNotificationDeliveryDead, pruneNotificationEvents, rescheduleNotificationDelivery } from "./store.js";
10
10
  import { sendHarmonyPush } from "./harmony-push.js";
11
+ import { flushClarificationNotifications, isClarificationNotificationActionable } from "./clarification.js";
11
12
  //#region src/notifications/service.ts
12
- init_transaction();
13
13
  init_src();
14
+ init_transaction();
14
15
  init_logger();
15
16
  init_gateway_identity_repository();
16
17
  const log = createLogger("Notifications");
@@ -23,6 +24,7 @@ const RETRY_DELAYS_MS = [
23
24
  216e5
24
25
  ];
25
26
  const STANDARD_PREFERENCES = {
27
+ "chat.needs_input": "chatNeedsInput",
26
28
  "chat.completed": "chatCompleted",
27
29
  "chat.failed": "chatFailed",
28
30
  "task.needs_input": "taskNeedsInput",
@@ -62,6 +64,10 @@ var NotificationService = class {
62
64
  }
63
65
  handleGatewayEvent(type, payload) {
64
66
  try {
67
+ if (type === "clarification.created") {
68
+ this.drain();
69
+ return;
70
+ }
65
71
  const notification = this.persistGatewayEvent(type, payload);
66
72
  if (!notification) return;
67
73
  this.options.publish("notification.created", notification);
@@ -108,6 +114,7 @@ var NotificationService = class {
108
114
  pruneNotificationEvents(now - 720 * 60 * 60 * 1e3);
109
115
  this.lastMaintenanceAt = now;
110
116
  }
117
+ for (const notification of flushClarificationNotifications((plan) => this.persistPlan(plan))) this.options.publish("notification.created", notification);
111
118
  for (const notification of this.options.domainDelivery?.flush((plan) => this.persistPlan(plan)) ?? []) this.options.publish("notification.created", notification);
112
119
  await this.deliverPending();
113
120
  await this.options.domainDelivery?.drain();
@@ -126,10 +133,18 @@ var NotificationService = class {
126
133
  await Promise.all(deliveries.map((delivery) => this.send(delivery)));
127
134
  }
128
135
  async send(delivery) {
136
+ if (!isClarificationNotificationActionable(delivery.event)) {
137
+ cancelNotificationDelivery(delivery.event.id, delivery.deviceId);
138
+ return;
139
+ }
129
140
  if (this.options.allowsNotification?.(delivery.event) === false) {
130
141
  markNotificationDeliveryDead(delivery.event.id, delivery.deviceId, "Notification policy changed");
131
142
  return;
132
143
  }
144
+ if (delivery.event.type === "chat.needs_input" && !getNotificationDevice(delivery.deviceId)?.preferences.chatNeedsInput) {
145
+ cancelNotificationDelivery(delivery.event.id, delivery.deviceId);
146
+ return;
147
+ }
133
148
  const domain = this.options.domainDelivery?.owns(delivery.event.type) ? this.options.domainDelivery : void 0;
134
149
  if (!domain && !Object.hasOwn(STANDARD_PREFERENCES, delivery.event.type)) {
135
150
  markNotificationDeliveryDead(delivery.event.id, delivery.deviceId, "Notification domain delivery is not installed");
@@ -163,7 +178,8 @@ var NotificationService = class {
163
178
  gatewayId: getOrCreateGatewayIdentity().id,
164
179
  target: delivery.event.target,
165
180
  title: preview.title,
166
- body: preview.body
181
+ body: preview.body,
182
+ ...delivery.event.type === "chat.needs_input" && typeof delivery.event.payload.expiresAt === "number" ? { expiresAt: delivery.event.payload.expiresAt } : {}
167
183
  }, fetchImpl);
168
184
  markNotificationDeliveryAccepted(delivery.event.id, delivery.deviceId, ticket, Number.MAX_SAFE_INTEGER);
169
185
  } catch (err) {
@@ -38,6 +38,7 @@ export declare function notificationDeliveryMetrics(): {
38
38
  accepted: number;
39
39
  delivered: number;
40
40
  dead: number;
41
+ cancelled: number;
41
42
  due: number;
42
43
  devices: {
43
44
  deliverable: number;
@@ -56,3 +57,4 @@ export declare function expireUndeliverableNotificationDeliveries(now?: number):
56
57
  export declare function pruneNotificationEvents(before: number): number;
57
58
  export declare function deferNotificationDelivery(eventId: string, deviceId: string, nextAttemptAt: number): void;
58
59
  export declare function getNotificationEvent(id: string): ProductNotification | null;
60
+ export declare function cancelNotificationDelivery(eventId: string, deviceId: string): void;
@@ -149,6 +149,7 @@ function notificationDeliveryMetrics() {
149
149
  accepted: counts.accepted ?? 0,
150
150
  delivered: counts.delivered ?? 0,
151
151
  dead: counts.dead ?? 0,
152
+ cancelled: counts.cancelled ?? 0,
152
153
  due: due.count,
153
154
  devices: {
154
155
  deliverable: devices.deliverable ?? 0,
@@ -190,5 +191,10 @@ function getNotificationEvent(id) {
190
191
  const row = getSqliteDatabase().prepare("SELECT * FROM notification_events WHERE event_id = ?").get(id);
191
192
  return row ? eventFromRow(row) : null;
192
193
  }
194
+ function cancelNotificationDelivery(eventId, deviceId) {
195
+ getSqliteDatabase().prepare(`UPDATE notification_deliveries SET status = 'cancelled',
196
+ last_error = 'Clarification is no longer actionable', updated_at = ?
197
+ WHERE event_id = ? AND device_id = ? AND status = 'pending'`).run(Date.now(), eventId, deviceId);
198
+ }
193
199
  //#endregion
194
- export { acknowledgeNotification, createNotificationEvent, deferNotificationDelivery, expireUndeliverableNotificationDeliveries, getNotificationEvent, listDueNotificationDeliveries, listNotificationEvents, markNotificationDeliveryAccepted, markNotificationDeliveryDead, markNotificationDeliveryDelivered, notificationDeliveryMetrics, pruneNotificationEvents, rescheduleNotificationDelivery };
200
+ export { acknowledgeNotification, cancelNotificationDelivery, createNotificationEvent, deferNotificationDelivery, expireUndeliverableNotificationDeliveries, getNotificationEvent, listDueNotificationDeliveries, listNotificationEvents, markNotificationDeliveryAccepted, markNotificationDeliveryDead, markNotificationDeliveryDelivered, notificationDeliveryMetrics, pruneNotificationEvents, rescheduleNotificationDelivery };
@@ -2,6 +2,7 @@ export type NotificationDevicePlatform = 'ios' | 'android' | 'harmonyos';
2
2
  export type NotificationPermission = 'granted' | 'denied' | 'unknown';
3
3
  export type NotificationLanguage = 'en' | 'zh';
4
4
  export type NotificationPreferences = {
5
+ chatNeedsInput: boolean;
5
6
  chatCompleted: boolean;
6
7
  chatFailed: boolean;
7
8
  taskNeedsInput: boolean;
@@ -1,5 +1,6 @@
1
1
  //#region src/notifications/types.ts
2
2
  const DEFAULT_NOTIFICATION_PREFERENCES = {
3
+ chatNeedsInput: true,
3
4
  chatCompleted: true,
4
5
  chatFailed: true,
5
6
  taskNeedsInput: true,
@@ -112,7 +112,7 @@ var init_model_catalog_persistence = __esmMin((() => {
112
112
  tts: ttsSchema.optional()
113
113
  }).strict();
114
114
  persistedCatalogSchema = z.object({
115
- schemaVersion: z.literal(1),
115
+ schemaVersion: z.literal(2),
116
116
  providerId: z.literal("xopc-cloud"),
117
117
  catalogVersion: z.string().nullable(),
118
118
  fetchedAt: z.number().int().nonnegative(),
@@ -156,7 +156,7 @@ var init_model_catalog_persistence = __esmMin((() => {
156
156
  async save(source) {
157
157
  if (source.providerId !== "xopc-cloud") throw new Error(`Cannot persist catalog for provider ${source.providerId}`);
158
158
  const payload = persistedCatalogSchema.parse({
159
- schemaVersion: 1,
159
+ schemaVersion: 2,
160
160
  providerId: source.providerId,
161
161
  catalogVersion: source.etag,
162
162
  fetchedAt: source.lastSuccessAt,
@@ -76,6 +76,7 @@ const PROVIDER_HINTS = {
76
76
  "google-antigravity": "Gemini/Antigravity OAuth model access."
77
77
  };
78
78
  const RECOMMENDED_MODEL_PATTERNS = {
79
+ "xopc-cloud": [/^auto$/],
79
80
  openai: [
80
81
  /^gpt-5\.6$/i,
81
82
  /^gpt-5\.6-sol$/i,
@@ -90,7 +90,7 @@ var XopcCloudModelSource = class {
90
90
  baseUrl: this.routerUrl,
91
91
  api: "openai-completions",
92
92
  etag: response.headers.get("x-xopc-model-catalog-version"),
93
- recommendedModel: models.find((model) => !isDedicatedComputerProfile(model.computerUse?.profile))?.id ?? null,
93
+ recommendedModel: models.find((model) => model.id === "auto")?.id ?? models.find((model) => !isDedicatedComputerProfile(model.computerUse?.profile))?.id ?? null,
94
94
  ...Object.keys(recommended).length > 0 ? { recommended } : {},
95
95
  ...search ? { search } : {},
96
96
  lastSuccessAt: Date.now()