@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.
- package/dist/browser-ext/_locales/en/messages.json +30 -1
- package/dist/browser-ext/_locales/zh_CN/messages.json +30 -1
- package/dist/browser-ext/dist/assets/{auth-beGtbLPS.js → page-context-BeworyNB.js} +1331 -1355
- package/dist/browser-ext/dist/assets/{sidepanel-BT0ojEzG.css → sidepanel-Ccl0eSa1.css} +43 -0
- package/dist/browser-ext/dist/background.js +680 -182
- package/dist/browser-ext/dist/sidepanel.html +2 -2
- package/dist/browser-ext/dist/sidepanel.js +372 -193
- package/dist/browser-ext/manifest.json +2 -8
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-Cuf3JFFJ.js → activity-store-BQ3PMp2q.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DyATPNTe.js → agent-avatar-dicebear-Stj17S9u.js} +1 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CCRfvuov.js +1 -0
- package/dist/gateway/static/root/assets/agent-plugin-dialog-CRlzd8El.js +1 -0
- package/dist/gateway/static/root/assets/agents-_ug2LCQb.js +66 -0
- package/dist/gateway/static/root/assets/{agents-admin-api-D842OcNo.js → agents-admin-api-HBZvVyzF.js} +1 -1
- package/dist/gateway/static/root/assets/app-management-settings-panel-pJFe6M6c.js +1 -0
- package/dist/gateway/static/root/assets/{appearance-settings-DQr0o6Lm.js → appearance-settings-BrxSpBWa.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-CltMV4Xp.js → apps-page-DegSl5Lh.js} +1 -1
- package/dist/gateway/static/root/assets/{archive-plugin-DT8Nio-r.js → archive-plugin-BO3I9zRP.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-BIfWS_3Y.js → automations-page-BZQ_VHjp.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-BQywN6nG.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-7qs3qcW9.js → binary-plugins-gFD7vH9R.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-BFPUlxJ6.js → block-editor-3XjFv3kK.js} +28 -28
- package/dist/gateway/static/root/assets/browser-automation-inputs-DxRoKFun.js +1 -0
- package/dist/gateway/static/root/assets/browser-automations-page-yiEuG1v7.js +3 -0
- package/dist/gateway/static/root/assets/browser-settings-page-ch2_bQF0.js +3 -0
- package/dist/gateway/static/root/assets/{capabilities-K0Zb_lH0.js → capabilities-B48r0DDa.js} +1 -1
- package/dist/gateway/static/root/assets/{capabilities-BzWFO_x_.js → capabilities-DO-vfNKI.js} +1 -1
- package/dist/gateway/static/root/assets/capabilities-page-BEnFt_dj.js +2 -0
- package/dist/gateway/static/root/assets/capabilities-settings-panel-NckMsJ5N.js +8 -0
- package/dist/gateway/static/root/assets/{capability-header-actions-AMn_vTNv.js → capability-header-actions-CY8KCO9j.js} +1 -1
- package/dist/gateway/static/root/assets/channels-CHOS2CGa.js +1 -0
- package/dist/gateway/static/root/assets/{chat-terminal-dock-C7nAROhF.js → chat-terminal-dock-Bwknnb4c.js} +2 -2
- package/dist/gateway/static/root/assets/computer-settings-page-B2xeFCSt.js +1 -0
- package/dist/gateway/static/root/assets/{connector-service-page-CTx1B8wx.js → connector-service-page-C83DnAqK.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-D6wTmWA6.js +2 -0
- package/dist/gateway/static/root/assets/{date-picker-Cx_xIKvN.js → date-picker-Bq9GR-DU.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-DYm96PDu.js → dependency-picker-BTERkA9X.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-D90OzgeR.js → desktop-pet-BwsbQw8V.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-CmdCecjm.js → desktop-pet-settings-sL9i44pP.js} +1 -1
- package/dist/gateway/static/root/assets/device-pairing-wizard-DI2bqaKO.js +1 -0
- package/dist/gateway/static/root/assets/{directory-picker-path-field-DZpaoeNa.js → directory-picker-path-field-BFlDmsS5.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-Bv6QE8kC.js → extension-debug-page-7Z1Tp7-w.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CEsq71Cm.js → extension-page-uGqvb8QX.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-provider-CX-sK0Tw.js → extension-provider-xlSyz4Z6.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-UyOHF39P.js → extension-settings-page-CKHgrjOs.js} +1 -1
- package/dist/gateway/static/root/assets/{fallback-models-CKv_Wqg8.js → fallback-models-BwQg0G1D.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-Cjnkle5J.js → gateway-config-swr-7RKqgU_U.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-realtime-DCCLdyQD.js → gateway-realtime-DDWymi-o.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-realtime-store-BheKaO6d.js +1 -0
- package/dist/gateway/static/root/assets/gateway-settings-BAQnSEMJ.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-CXKmdVzN.js → gateway-startup-retry-jiV5sbEX.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-BZDjvwet.js +2 -0
- package/dist/gateway/static/root/assets/{image-generation-api-NLHzm4Nc.js → image-generation-api-DO4mXb6I.js} +1 -1
- package/dist/gateway/static/root/assets/{imports-page-C7qvlBTQ.js → imports-page-re1_Nh64.js} +1 -1
- package/dist/gateway/static/root/assets/index-BB1z8QxA.js +106 -0
- package/dist/gateway/static/root/assets/index-D9R6tU7r.css +1 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-pkgFWJb-.js → keyboard-shortcuts-settings-B_xja9LN.js} +1 -1
- package/dist/gateway/static/root/assets/{local-app-workbench-page-dMDhZXAi.js → local-app-workbench-page-CErdCrPX.js} +1 -1
- package/dist/gateway/static/root/assets/{local-apps-page-TpUAfOn2.js → local-apps-page-BPL2RXdK.js} +1 -1
- package/dist/gateway/static/root/assets/{local-session-drafts-Cvv7I0fw.js → local-session-drafts-DRPsDCj1.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-C8TMD2gn.js → locale-store-COVscAqC.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-DL-BM0xq.js +2 -0
- package/dist/gateway/static/root/assets/management-settings-BOVRHhXk.js +1 -0
- package/dist/gateway/static/root/assets/{markdown-view-Dse7rkio.js → markdown-view-B_qnAcW2.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-BZrnzaBM.js → media-plugins-C0Pc-wSY.js} +1 -1
- package/dist/gateway/static/root/assets/messages-Bb2GK-Nj.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-cache-DyPPksMP.js +1 -0
- package/dist/gateway/static/root/assets/note-detail-panel-DJJK2yL4.js +5 -0
- package/dist/gateway/static/root/assets/{notes-api-DKiVeQKG.js → notes-api-sBgBcyLW.js} +1 -1
- package/dist/gateway/static/root/assets/notes-page-oCxO7ZTv.js +8 -0
- package/dist/gateway/static/root/assets/{page-context-capture-button-Cxzd4QPB.js → page-context-capture-button-tf77xIz3.js} +1 -1
- package/dist/gateway/static/root/assets/personal-page-DOk9gUK5.js +1 -0
- package/dist/gateway/static/root/assets/{product-open-page-D4hoEWiu.js → product-open-page-Dc3Y-Y7J.js} +1 -1
- package/dist/gateway/static/root/assets/{product-preview-content-aR38El2E.js → product-preview-content-MG_hmVA3.js} +1 -1
- package/dist/gateway/static/root/assets/{project-detail-page-D20QH4YB.js → project-detail-page-3uAzbW4T.js} +1 -1
- package/dist/gateway/static/root/assets/{projects-page-Bf3BIcT6.js → projects-page-MllfNLGA.js} +1 -1
- package/dist/gateway/static/root/assets/{registry-api-AdnxowbH.js → registry-api-Bh9UBb-f.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-Bs-C70el.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-CBN3raz1.js → runtime-tools-settings-panel-DpJ5jNzR.js} +1 -1
- package/dist/gateway/static/root/assets/scenes-page-Dpxamkw6.js +2 -0
- package/dist/gateway/static/root/assets/{schema-form-CxrMGsT9.js → schema-form-DUeyQ1zh.js} +1 -1
- package/dist/gateway/static/root/assets/{send-session-input-CgOzhDZ0.js → send-session-input-Dgn4BRk_.js} +1 -1
- package/dist/gateway/static/root/assets/{session-api-_HIN8or3.js → session-api-yjpEz4pP.js} +1 -1
- package/dist/gateway/static/root/assets/{session-manager-CzCto5zT.js → session-manager-LInoZ_Yi.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-BCVlNHtq.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-Bz-ue9fZ.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-D8Q3H3-o.js → settings-page-DouHuBXt.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-DvLMMiuS.js → setup-status-panel-B5BoZ-1y.js} +1 -1
- package/dist/gateway/static/root/assets/{share-link-dialog-Dg5os066.js → share-link-dialog-DJTabLAM.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-DMvohAyr.js → share-preview-page-jw7h4t_B.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-api-C96IO4qJ.js → shares-api-c0dfWz6h.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-BlnlzGjH.js +1 -0
- package/dist/gateway/static/root/assets/{skill-api-C10ML0CH.js → skill-api-CfyX_0zN.js} +1 -1
- package/dist/gateway/static/root/assets/{skill-reload-api-DNbJzSfB.js → skill-reload-api-Ge5XymHa.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page-DObMKvA6.js → skills-page-DjdTeYzm.js} +1 -1
- package/dist/gateway/static/root/assets/system-settings-panel-DWf256TE.js +1 -0
- package/dist/gateway/static/root/assets/{task-detail-page-BR2L1L8l.js → task-detail-page-DE6N1ZQe.js} +2 -2
- package/dist/gateway/static/root/assets/{task-expandable-content-DL2Q2gre.js → task-expandable-content-hYcgCEE3.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-DQ6KJa4l.js → theme-store-BOfCKgl6.js} +1 -1
- package/dist/gateway/static/root/assets/{tracing-settings-page-Ed8_GYUT.js → tracing-settings-page-DDWFXcST.js} +1 -1
- package/dist/gateway/static/root/assets/{tunnel-api-D3X8jDwo.js → tunnel-api-BBm9esrY.js} +1 -1
- package/dist/gateway/static/root/assets/{usage-page-BqzRyyb9.js → usage-page-C93x89uW.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-CRFefpzO.js → use-autosave-CSckcjFx.js} +1 -1
- package/dist/gateway/static/root/assets/{use-composer-attachments-OLrvSjn5.js → use-composer-attachments-C7Gaaai1.js} +1 -1
- package/dist/gateway/static/root/assets/{use-file-preview-expanded-CJvzfQvw.js → use-file-preview-expanded-Db2VYg1b.js} +2 -2
- package/dist/gateway/static/root/assets/user-model-page-B74LkVbp.js +2 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-R9zNWYR_.js → voice-api-key-field-GEw5x2fU.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-DLudE9Rc.js → voice-config-api-3yyVwXln.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-DVmQrolV.js → work-discovery-overlay-Bs2MKiTv.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DEkmuD3T.js → workflow-run-setup-panel-BR_U_snV.js} +2 -2
- package/dist/gateway/static/root/assets/{workflows-page-pqCB3sh4.js → workflows-page-Crk4SxtC.js} +3 -3
- package/dist/gateway/static/root/assets/{workspace-api-CdVUhyPo.js → workspace-api-Si2o3inw.js} +2 -2
- package/dist/gateway/static/root/index.html +27 -28
- package/dist/package.js +1 -1
- package/dist/packages/browser-control-contract/src/automation.js +213 -0
- package/dist/packages/browser-control-contract/src/index.js +43 -12
- package/dist/packages/gateway-contract/src/gateway-scopes.js +3 -1
- package/dist/packages/gateway-contract/src/notifications.js +1 -0
- package/dist/packages/realtime-protocol/src/voice-catalog.js +7 -1
- package/dist/packages/realtime-protocol/src/voice.js +9 -3
- package/dist/src/agent/coding/repository-instructions.js +8 -1
- package/dist/src/agent/tool-manuals/browser.d.ts +1 -1
- package/dist/src/agent/tool-manuals/browser.js +3 -3
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js +1 -1
- package/dist/src/agent/tools/browser/tool/schemas.d.ts +0 -13
- package/dist/src/agent/tools/browser/tool/schemas.js +0 -4
- package/dist/src/agent/tools/browser-automation-tool.d.ts +74 -1
- package/dist/src/agent/tools/browser-automation-tool.js +52 -6
- package/dist/src/agent-config/schema.d.ts +1 -1
- package/dist/src/agent-config/schema.js +1 -1
- package/dist/src/automations/capabilities/write.d.ts +2 -0
- package/dist/src/automations/domain/types.d.ts +11 -0
- package/dist/src/automations/domain/validation.d.ts +4 -0
- package/dist/src/automations/domain/validation.js +1 -0
- package/dist/src/automations/draft/automation-draft-validator.d.ts +1 -0
- package/dist/src/automations/service/action-executor.js +11 -3
- package/dist/src/automations/service/automation-service.d.ts +1 -0
- package/dist/src/automations/service/automation-service.js +13 -1
- package/dist/src/bootstrap/application-state.js +3 -1
- package/dist/src/browser/automations/repository.d.ts +4 -0
- package/dist/src/browser/automations/repository.js +27 -6
- package/dist/src/browser/automations/runner.js +101 -9
- package/dist/src/browser/automations/runtime-service.js +4 -3
- package/dist/src/browser/automations/schema.d.ts +84 -1
- package/dist/src/browser/automations/schema.js +68 -2
- package/dist/src/browser/automations/service.d.ts +78 -1
- package/dist/src/browser/automations/service.js +36 -4
- package/dist/src/browser/automations/types.d.ts +19 -4
- package/dist/src/browser/drivers/extension-driver.d.ts +5 -5
- package/dist/src/browser/drivers/extension-driver.js +10 -10
- package/dist/src/browser/drivers/playwright-driver.js +46 -0
- package/dist/src/browser/index.d.ts +1 -2
- package/dist/src/browser/index.js +2 -3
- package/dist/src/browser/policy/browser-policy.d.ts +0 -1
- package/dist/src/browser/policy/browser-policy.js +1 -4
- package/dist/src/browser/providers/index.d.ts +1 -1
- package/dist/src/browser/providers/index.js +2 -2
- package/dist/src/browser/providers/realtime-extension.d.ts +1 -1
- package/dist/src/browser/providers/realtime-extension.js +5 -1
- package/dist/src/browser/recordings/service.d.ts +22 -0
- package/dist/src/browser/recordings/service.js +160 -0
- package/dist/src/browser/runtime/browser-runtime.d.ts +1 -1
- package/dist/src/browser/runtime/browser-runtime.js +19 -56
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/computer/runtime.js +2 -2
- package/dist/src/config/schema.d.ts +12 -12
- package/dist/src/config/schema.js +12 -12
- package/dist/src/endpoint-tools/policy.js +4 -3
- package/dist/src/gateway/hono/routes/browser-automations.js +23 -7
- package/dist/src/gateway/hono/routes/browser-recordings.d.ts +3 -0
- package/dist/src/gateway/hono/routes/browser-recordings.js +78 -0
- package/dist/src/gateway/hono/routes/browser.js +1 -34
- package/dist/src/gateway/hono/routes/device-push.js +1 -0
- package/dist/src/gateway/hono/routes/home.js +1 -1
- package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
- package/dist/src/gateway/hono/routes/personal-agent.js +35 -0
- package/dist/src/gateway/hono/routes/voice.js +5 -2
- package/dist/src/gateway/security/gateway-scopes.js +3 -1
- package/dist/src/gateway/service/agent-runner.js +1 -0
- package/dist/src/home-intelligence/generator.d.ts +2 -0
- package/dist/src/home-intelligence/generator.js +53 -4
- package/dist/src/home-intelligence/host.d.ts +2 -1
- package/dist/src/home-intelligence/host.js +23 -3
- package/dist/src/migrations/cloud-public-models.d.ts +7 -0
- package/dist/src/migrations/cloud-public-models.js +157 -0
- package/dist/src/notifications/clarification.d.ts +5 -0
- package/dist/src/notifications/clarification.js +66 -0
- package/dist/src/notifications/device-store.js +1 -0
- package/dist/src/notifications/harmony-push.d.ts +1 -0
- package/dist/src/notifications/harmony-push.js +3 -1
- package/dist/src/notifications/planner.d.ts +1 -0
- package/dist/src/notifications/service.d.ts +2 -2
- package/dist/src/notifications/service.js +20 -4
- package/dist/src/notifications/store.d.ts +2 -0
- package/dist/src/notifications/store.js +7 -1
- package/dist/src/notifications/types.d.ts +1 -0
- package/dist/src/notifications/types.js +1 -0
- package/dist/src/providers/model-catalog-persistence.js +2 -2
- package/dist/src/providers/presentation.js +1 -0
- package/dist/src/providers/xopc-cloud-model-source.js +1 -1
- package/dist/src/storage/sqlite/clarification-wait-repository.js +1 -0
- package/dist/src/storage/sqlite/migrations/238_browser_record_replay.sql +45 -0
- package/dist/src/storage/sqlite/migrations/239_clarification_notifications.sql +26 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/tasks/home-query-service.d.ts +1 -1
- package/dist/src/tasks/home-query-service.js +6 -2
- package/dist/src/voice/dashscope/streaming-tts-stream.d.ts +2 -1
- package/dist/src/voice/dashscope/streaming-tts-stream.js +135 -79
- package/dist/src/voice/metadata/types.d.ts +1 -0
- package/dist/src/voice/platform-catalog.d.ts +4 -0
- package/dist/src/voice/platform-settings.js +1 -0
- package/dist/src/voice/realtime/agentEngine.js +78 -1
- package/dist/src/voice/realtime/speakable-segmenter.d.ts +2 -0
- package/dist/src/voice/realtime/speakable-segmenter.js +30 -0
- package/dist/src/voice/tts/providers/alibaba-speech.js +17 -1
- package/dist/src/voice/tts/providers/xopc-cloud-speech.js +3 -2
- package/dist/src/voice/tts/speak-core.d.ts +3 -0
- package/dist/src/voice/tts/speak-core.js +21 -1
- package/dist/src/voice/tts/speech-provider-types.d.ts +8 -0
- package/package.json +3 -3
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-gT9_j4tr.js +0 -1
- package/dist/gateway/static/root/assets/agent-plugin-dialog-CLXCJ6JN.js +0 -1
- package/dist/gateway/static/root/assets/agents-BAUfOMsq.js +0 -66
- package/dist/gateway/static/root/assets/app-management-settings-panel-CoIFxQKH.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-BCGPjsdU.js +0 -6
- package/dist/gateway/static/root/assets/browser-automation-inputs-BUAIKIX0.js +0 -1
- package/dist/gateway/static/root/assets/browser-automations-page-CSwu1U1F.js +0 -3
- package/dist/gateway/static/root/assets/browser-settings-page-C1ReMNqX.js +0 -3
- package/dist/gateway/static/root/assets/capabilities-page-BdTSqloI.js +0 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-BUblBMZC.js +0 -8
- package/dist/gateway/static/root/assets/channels-CXCf5qO6.js +0 -1
- package/dist/gateway/static/root/assets/computer-settings-page-B5SuSZ3G.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-DfnK1crf.js +0 -2
- package/dist/gateway/static/root/assets/device-pairing-wizard-s2ogSa4l.js +0 -1
- package/dist/gateway/static/root/assets/gateway-realtime-store-C_Th8kGg.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-CZ73IpbP.js +0 -1
- package/dist/gateway/static/root/assets/home-page-BQWq4kYi.js +0 -2
- package/dist/gateway/static/root/assets/index-BQgqzhQj.js +0 -106
- package/dist/gateway/static/root/assets/index-COB4QIJp.css +0 -1
- package/dist/gateway/static/root/assets/logs-page-B-Y9oZLh.js +0 -2
- package/dist/gateway/static/root/assets/management-settings-B2lzsw6X.js +0 -1
- package/dist/gateway/static/root/assets/messages-Dy26npMy.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-cache-B1C86nRp.js +0 -1
- package/dist/gateway/static/root/assets/note-detail-panel-DL__qP6U.js +0 -5
- package/dist/gateway/static/root/assets/notes-page-DTBbg9Hs.js +0 -8
- package/dist/gateway/static/root/assets/oauth-api-BwpzpRwC.js +0 -1
- package/dist/gateway/static/root/assets/personal-page-CzaTnHeD.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-CKxqncqW.js +0 -1
- package/dist/gateway/static/root/assets/scenes-page-Cv_5ozfX.js +0 -2
- package/dist/gateway/static/root/assets/sessions-page-DZcu6NLJ.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-DazqeDQ7.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-CsDATuCw.js +0 -1
- package/dist/gateway/static/root/assets/system-settings-panel-Bn3khdzb.js +0 -1
- package/dist/gateway/static/root/assets/user-model-page-CG6wqIKP.js +0 -2
- package/dist/src/browser/policy/approval-store.d.ts +0 -17
- package/dist/src/browser/policy/approval-store.js +0 -62
- package/dist/src/browser/providers/extension-ws-acquire.d.ts +0 -19
- package/dist/src/browser/providers/extension-ws-acquire.js +0 -78
- package/dist/src/browser/providers/extension.d.ts +0 -61
- 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
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
|
83
|
+
ttl
|
|
82
84
|
}
|
|
83
85
|
})
|
|
84
86
|
});
|
|
@@ -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;
|
|
@@ -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(
|
|
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:
|
|
159
|
+
schemaVersion: 2,
|
|
160
160
|
providerId: source.providerId,
|
|
161
161
|
catalogVersion: source.etag,
|
|
162
162
|
fetchedAt: source.lastSuccessAt,
|
|
@@ -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()
|