@xopcai/xopc 0.0.294 → 0.0.296

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 (207) hide show
  1. package/dist/browser-ext/dist/assets/{auth-C8gJZEsn.js → auth-B_9ZuGDx.js} +2 -1
  2. package/dist/browser-ext/dist/background.js +1 -1
  3. package/dist/browser-ext/dist/sidepanel.html +1 -1
  4. package/dist/browser-ext/dist/sidepanel.js +1 -1
  5. package/dist/browser-ext/manifest.json +1 -1
  6. package/dist/extensions/telegram/xopc.extension.json +1 -1
  7. package/dist/gateway/static/root/assets/{activity-store-6lmzUBEr.js → activity-store-DKWpcUF7.js} +1 -1
  8. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BDWrNpJe.js → agent-avatar-dicebear-BCKaf8i6.js} +1 -1
  9. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-mqojcrab.js +1 -0
  10. package/dist/gateway/static/root/assets/agents-DeHJUcOp.js +1 -0
  11. package/dist/gateway/static/root/assets/{api-D6yepxBp.js → api-Bq0dy2ht.js} +1 -1
  12. package/dist/gateway/static/root/assets/api-DPVNGtF-.js +1 -0
  13. package/dist/gateway/static/root/assets/{app-management-settings-panel-CCS9KbKd.js → app-management-settings-panel-BKD7hlU4.js} +1 -1
  14. package/dist/gateway/static/root/assets/{appearance-settings-CuRyhUns.js → appearance-settings-Bk5reOD9.js} +1 -1
  15. package/dist/gateway/static/root/assets/apps-page-B9DyOYwB.js +1 -0
  16. package/dist/gateway/static/root/assets/{archive-plugin-Xj6tLKD2.js → archive-plugin-DZbe2bJP.js} +1 -1
  17. package/dist/gateway/static/root/assets/{attachment-load-CSMv3wDB.js → attachment-load-CoMeh7-l.js} +1 -1
  18. package/dist/gateway/static/root/assets/{automations-page-4Njbwe26.js → automations-page-BlJgwSUG.js} +1 -1
  19. package/dist/gateway/static/root/assets/automations-workspace-ORSqorgI.js +6 -0
  20. package/dist/gateway/static/root/assets/{binary-plugins-ohh8JiqX.js → binary-plugins-CG5vb8MG.js} +1 -1
  21. package/dist/gateway/static/root/assets/{block-editor-ps5gfiDX.js → block-editor-CzLz3nS0.js} +3 -3
  22. package/dist/gateway/static/root/assets/{browser-automation-inputs-Cq4sIJt2.js → browser-automation-inputs-Ba7bkmFQ.js} +1 -1
  23. package/dist/gateway/static/root/assets/{browser-automations-page-DEeymLbJ.js → browser-automations-page-CK__2t2k.js} +2 -2
  24. package/dist/gateway/static/root/assets/browser-settings-page-IWkMJk8D.js +8 -0
  25. package/dist/gateway/static/root/assets/capabilities-settings-panel-BLivAgAc.js +8 -0
  26. package/dist/gateway/static/root/assets/channels-settings-DiFTm5lF.js +1 -0
  27. package/dist/gateway/static/root/assets/{channels-status-swr-CVzEYBpX.js → channels-status-swr-Czx0fIBL.js} +1 -1
  28. package/dist/gateway/static/root/assets/{chat-terminal-dock-Bx56s8Ju.js → chat-terminal-dock-BuotPHE9.js} +2 -2
  29. package/dist/gateway/static/root/assets/{computer-model-settings-DdkdFWic.js → computer-model-settings-CqH6YVvk.js} +1 -1
  30. package/dist/gateway/static/root/assets/computer-settings-page-DZDnkWIw.js +1 -0
  31. package/dist/gateway/static/root/assets/connectors-page-d4saaZj7.js +2 -0
  32. package/dist/gateway/static/root/assets/cron-expression-Ch_GmsmU.js +2 -0
  33. package/dist/gateway/static/root/assets/{date-picker-B_w38QJJ.js → date-picker-BUcTJm_i.js} +1 -1
  34. package/dist/gateway/static/root/assets/{dependency-picker-DG-5rqI3.js → dependency-picker-BA_2cNuR.js} +1 -1
  35. package/dist/gateway/static/root/assets/{desktop-pet-daUwTaBB.js → desktop-pet-CCGNh6Cv.js} +1 -1
  36. package/dist/gateway/static/root/assets/{desktop-pet-settings-wVbuFzeN.js → desktop-pet-settings-Cg8tGIti.js} +1 -1
  37. package/dist/gateway/static/root/assets/device-pairing-wizard-DMlY9mim.js +1 -0
  38. package/dist/gateway/static/root/assets/electron-env-Dit0bHgy.js +1 -0
  39. package/dist/gateway/static/root/assets/{extension-debug-page-DVQCsGO7.js → extension-debug-page-BGDVRcYY.js} +1 -1
  40. package/dist/gateway/static/root/assets/{extension-page-BZd649fz.js → extension-page-BZUOzMV9.js} +1 -1
  41. package/dist/gateway/static/root/assets/{extension-settings-page-CW_qtR_s.js → extension-settings-page-BaXUodRm.js} +1 -1
  42. package/dist/gateway/static/root/assets/{gateway-config-swr-BBovMBQ1.js → gateway-config-swr-Dkc1As9z.js} +1 -1
  43. package/dist/gateway/static/root/assets/gateway-settings-CRb71ODi.js +1 -0
  44. package/dist/gateway/static/root/assets/{gateway-startup-retry-NXDtzZED.js → gateway-startup-retry-DnLnaPev.js} +1 -1
  45. package/dist/gateway/static/root/assets/heartbeat-settings-BfSCOyxZ.js +1 -0
  46. package/dist/gateway/static/root/assets/home-page-DEsvYGCC.js +1 -0
  47. package/dist/gateway/static/root/assets/{image-generation-api-D01ieqGC.js → image-generation-api-DTXI5ZGN.js} +1 -1
  48. package/dist/gateway/static/root/assets/{imports-page-DJG1BJzd.js → imports-page-DTqPlG9Z.js} +1 -1
  49. package/dist/gateway/static/root/assets/{index-Ds8Q4MZJ.css → index-CdrKvNSO.css} +1 -1
  50. package/dist/gateway/static/root/assets/index-D5RrehFN.js +75 -0
  51. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-cLUFwjrj.js +1 -0
  52. package/dist/gateway/static/root/assets/local-app-workbench-page-DAbQW7rx.js +2 -0
  53. package/dist/gateway/static/root/assets/{local-apps-page-BupSkP0s.js → local-apps-page-BIi49k0U.js} +1 -1
  54. package/dist/gateway/static/root/assets/{locale-store-eliqUnBr.js → locale-store-Bvh7i-qf.js} +1 -1
  55. package/dist/gateway/static/root/assets/{logs-page-CbbEPEH6.js → logs-page-CGIXxwnD.js} +2 -2
  56. package/dist/gateway/static/root/assets/{management-settings-uzNsZK9S.js → management-settings-CM3_MVK2.js} +1 -1
  57. package/dist/gateway/static/root/assets/markdown-view-D5qRss8E.js +201 -0
  58. package/dist/gateway/static/root/assets/{media-plugins-Brz0R-XW.js → media-plugins-C9D_2SV4.js} +1 -1
  59. package/dist/gateway/static/root/assets/messages-CRy5Dn65.js +3 -0
  60. package/dist/gateway/static/root/assets/note-detail-panel-CajzGnJk.js +5 -0
  61. package/dist/gateway/static/root/assets/notes-page-BfU7eXZI.js +8 -0
  62. package/dist/gateway/static/root/assets/{page-tabs-B5aqgPVw.js → page-tabs-5xvBmNLr.js} +1 -1
  63. package/dist/gateway/static/root/assets/{preview-open-alternatives-C36n0h3j.js → preview-open-alternatives-CYEcUwgQ.js} +1 -1
  64. package/dist/gateway/static/root/assets/{proactive-page-Bf3fTLFK.js → proactive-page-zCxlG2wm.js} +1 -1
  65. package/dist/gateway/static/root/assets/{product-open-page-DtgWUAwT.js → product-open-page-DZkUoQug.js} +1 -1
  66. package/dist/gateway/static/root/assets/project-detail-page-BiH4CX5l.js +1 -0
  67. package/dist/gateway/static/root/assets/projects-page-D7zEue9F.js +1 -0
  68. package/dist/gateway/static/root/assets/{registry-api-Dpm3N2h0.js → registry-api-Z5aZS7Pw.js} +1 -1
  69. package/dist/gateway/static/root/assets/remote-access-hub-DgIU9Ky0.js +1 -0
  70. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DQrAOOoG.js → runtime-tools-settings-panel-DKw6dReE.js} +2 -2
  71. package/dist/gateway/static/root/assets/{schema-form-CAmYD83K.js → schema-form-DjLqmO4e.js} +1 -1
  72. package/dist/gateway/static/root/assets/sessions-page-Dnok69Zz.js +1 -0
  73. package/dist/gateway/static/root/assets/settings-advanced-gate-CHo2l_qK.js +1 -0
  74. package/dist/gateway/static/root/assets/{settings-form-section-nZ0L21U5.js → settings-form-section-CbMZBzsX.js} +1 -1
  75. package/dist/gateway/static/root/assets/{settings-page-x7y6VkFZ.js → settings-page-BLfyLSxD.js} +1 -1
  76. package/dist/gateway/static/root/assets/setup-status-panel-CJ39WC3I.js +1 -0
  77. package/dist/gateway/static/root/assets/{share-preview-page-B3OpivMd.js → share-preview-page-CrlCpfnx.js} +1 -1
  78. package/dist/gateway/static/root/assets/shares-settings-FXKzrMu5.js +1 -0
  79. package/dist/gateway/static/root/assets/skill-reload-api-D7482ITF.js +1 -0
  80. package/dist/gateway/static/root/assets/{skills-page-BqQln5BZ.js → skills-page-CAB6alxk.js} +1 -1
  81. package/dist/gateway/static/root/assets/{skills-page.utils-gVo88ldk.js → skills-page.utils-C62EqcM6.js} +1 -1
  82. package/dist/gateway/static/root/assets/{system-settings-panel-DJahgDjR.js → system-settings-panel-Bl5STF6Q.js} +1 -1
  83. package/dist/gateway/static/root/assets/task-detail-page-Dfsqavai.js +1 -0
  84. package/dist/gateway/static/root/assets/{theme-store-DUHPzKzv.js → theme-store-DBrRX9jz.js} +1 -1
  85. package/dist/gateway/static/root/assets/{tunnel-api-BvxsNjfv.js → tunnel-api-D47wWIM6.js} +1 -1
  86. package/dist/gateway/static/root/assets/{use-autosave-Bsv3gvqK.js → use-autosave-BUGKjFH9.js} +1 -1
  87. package/dist/gateway/static/root/assets/user-model-page-CXEqmdT7.js +2 -0
  88. package/dist/gateway/static/root/assets/{voice-api-key-field-BHtJeKg9.js → voice-api-key-field-DrkwfDvA.js} +1 -1
  89. package/dist/gateway/static/root/assets/{voice-config-api-Bjy8EFqi.js → voice-config-api-CzjqrH53.js} +1 -1
  90. package/dist/gateway/static/root/assets/{work-discovery-overlay-4WxTZ3b5.js → work-discovery-overlay-DwR3i5Fb.js} +1 -1
  91. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DdnSUVxc.js → workflow-run-setup-panel-dLH85qC7.js} +2 -2
  92. package/dist/gateway/static/root/assets/workflows-page-CYreRGKh.js +6 -0
  93. package/dist/gateway/static/root/index.html +11 -15
  94. package/dist/package.js +1 -1
  95. package/dist/packages/gateway-contract/src/device-pairing.js +9 -7
  96. package/dist/packages/gateway-contract/src/sessions.js +1 -0
  97. package/dist/src/agent/agent-manager.js +4 -4
  98. package/dist/src/agent/background-review/run-background-review.js +1 -1
  99. package/dist/src/agent/embedded/model-runtime.js +1 -1
  100. package/dist/src/agent/embedded/run-for-session.js +1 -1
  101. package/dist/src/agent/image/tool-model-config.js +1 -1
  102. package/dist/src/agent/mcp/oauth/mcp-oauth-store.js +1 -1
  103. package/dist/src/agent/service.js +2 -2
  104. package/dist/src/agent/session/session-inspector.js +1 -1
  105. package/dist/src/agent/skills/hub-lock.js +1 -1
  106. package/dist/src/agent/tasks/task-judge-service.js +3 -3
  107. package/dist/src/agent/tool-manuals/computer.d.ts +1 -1
  108. package/dist/src/agent/tool-manuals/computer.js +1 -1
  109. package/dist/src/agent/tools/computer-use-tool.js +24 -14
  110. package/dist/src/ai-assist/text-assist.js +1 -1
  111. package/dist/src/auth/credentials.js +2 -2
  112. package/dist/src/auth/oauth/xopc-cloud.js +1 -1
  113. package/dist/src/auth/profiles/store.js +1 -1
  114. package/dist/src/auth/sync-provider-auth.js +2 -2
  115. package/dist/src/browser/providers/browser-ext-install.js +1 -1
  116. package/dist/src/chat-commands/agent-edit.js +1 -1
  117. package/dist/src/cli/commands/agent.js +1 -1
  118. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  119. package/dist/src/cli/commands/doctor/checks/provider-auth.js +3 -3
  120. package/dist/src/cli/commands/models.js +1 -1
  121. package/dist/src/computer/errors.d.ts +8 -0
  122. package/dist/src/computer/errors.js +10 -0
  123. package/dist/src/computer/model-adapter.d.ts +5 -0
  124. package/dist/src/computer/model-adapter.js +69 -22
  125. package/dist/src/computer/runtime.d.ts +14 -0
  126. package/dist/src/computer/runtime.js +5 -4
  127. package/dist/src/computer/task-state.d.ts +5 -1
  128. package/dist/src/computer/task-state.js +26 -11
  129. package/dist/src/config/index.js +4 -4
  130. package/dist/src/config/loader.js +2 -2
  131. package/dist/src/config/models-json.js +2 -2
  132. package/dist/src/config/schema.js +1 -1
  133. package/dist/src/extensions/lockfile.js +1 -1
  134. package/dist/src/gateway/agents-admin.js +1 -1
  135. package/dist/src/gateway/file-path-classifier.js +1 -1
  136. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  137. package/dist/src/gateway/hono/routes/device-push.js +11 -1
  138. package/dist/src/gateway/hono/routes/models.js +1 -1
  139. package/dist/src/gateway/hono/routes/notes.js +1 -1
  140. package/dist/src/gateway/hono/routes/voice.js +1 -1
  141. package/dist/src/gateway/hono/routes/workflows.js +1 -1
  142. package/dist/src/gateway/service/config-coordinator.js +1 -1
  143. package/dist/src/gateway/service.js +5 -5
  144. package/dist/src/notes/types.d.ts +1 -1
  145. package/dist/src/notifications/device-store.js +1 -1
  146. package/dist/src/notifications/harmony-push.d.ts +26 -0
  147. package/dist/src/notifications/harmony-push.js +94 -0
  148. package/dist/src/notifications/service.d.ts +2 -0
  149. package/dist/src/notifications/service.js +15 -1
  150. package/dist/src/notifications/store.d.ts +2 -0
  151. package/dist/src/notifications/store.js +2 -1
  152. package/dist/src/notifications/types.d.ts +1 -1
  153. package/dist/src/providers/auth-runtime/resolve-auth.js +1 -1
  154. package/dist/src/providers/index.js +2 -2
  155. package/dist/src/providers/model-catalog-persistence.js +1 -1
  156. package/dist/src/providers/model-registry.js +1 -1
  157. package/dist/src/providers/register-runtime-providers.js +1 -1
  158. package/dist/src/storage/sqlite/device-access-repository.d.ts +1 -1
  159. package/dist/src/storage/sqlite/migrations/179_harmonyos_devices.sql +41 -0
  160. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  161. package/dist/src/storage/sqlite/migrations/runner.js +13 -5
  162. package/dist/src/storage/sqlite/schema.js +1 -1
  163. package/dist/src/tui/backends/embedded-backend.js +1 -1
  164. package/dist/src/tui/tui-commands.js +1 -1
  165. package/dist/src/tui/tui-startup-resources.js +1 -1
  166. package/dist/src/tui/tui.js +2 -2
  167. package/dist/src/work-discovery/service.js +2 -2
  168. package/dist/src/workflows/service/workflow-run-service.js +1 -1
  169. package/package.json +5 -3
  170. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-ESRFnt6Y.js +0 -1
  171. package/dist/gateway/static/root/assets/agents-aTs3RFJB.js +0 -1
  172. package/dist/gateway/static/root/assets/api-Dnfnl1Gd.js +0 -1
  173. package/dist/gateway/static/root/assets/apps-page-DAhcVKc4.js +0 -1
  174. package/dist/gateway/static/root/assets/automations-workspace-CZboHws3.js +0 -6
  175. package/dist/gateway/static/root/assets/browser-settings-page-BkGCUKLR.js +0 -8
  176. package/dist/gateway/static/root/assets/capabilities-settings-panel-Bik37Ina.js +0 -8
  177. package/dist/gateway/static/root/assets/channels-settings-B6O7oGmA.js +0 -1
  178. package/dist/gateway/static/root/assets/clock-3-DnrAnuyZ.js +0 -1
  179. package/dist/gateway/static/root/assets/computer-settings-page-_jWKNIO2.js +0 -1
  180. package/dist/gateway/static/root/assets/connectors-page-h2IMptiJ.js +0 -2
  181. package/dist/gateway/static/root/assets/cron-expression-GDPX4NxC.js +0 -2
  182. package/dist/gateway/static/root/assets/device-pairing-wizard-e8NSnXSQ.js +0 -1
  183. package/dist/gateway/static/root/assets/electron-env-DH5wF8X8.js +0 -1
  184. package/dist/gateway/static/root/assets/gateway-settings-zazNZgv6.js +0 -1
  185. package/dist/gateway/static/root/assets/git-branch-Dh9uxTot.js +0 -1
  186. package/dist/gateway/static/root/assets/heartbeat-settings-DuRKe_y9.js +0 -1
  187. package/dist/gateway/static/root/assets/home-page-BzIm3rF9.js +0 -1
  188. package/dist/gateway/static/root/assets/index-DTDDJnrO.js +0 -75
  189. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-DEGJsaAS.js +0 -1
  190. package/dist/gateway/static/root/assets/local-app-workbench-page-ylC0zfxp.js +0 -2
  191. package/dist/gateway/static/root/assets/markdown-view-BIg7cei7.js +0 -201
  192. package/dist/gateway/static/root/assets/message-circle-Badhj-4D.js +0 -1
  193. package/dist/gateway/static/root/assets/message-square-fVE7Ghj1.js +0 -1
  194. package/dist/gateway/static/root/assets/messages-NYDOR8-j.js +0 -3
  195. package/dist/gateway/static/root/assets/note-detail-panel-Dja38ec0.js +0 -5
  196. package/dist/gateway/static/root/assets/notes-page-DZV1zODX.js +0 -8
  197. package/dist/gateway/static/root/assets/project-detail-page-h8R5De4L.js +0 -1
  198. package/dist/gateway/static/root/assets/projects-page-C4yWYB8l.js +0 -1
  199. package/dist/gateway/static/root/assets/remote-access-hub-C0_N6lUv.js +0 -1
  200. package/dist/gateway/static/root/assets/sessions-page-BdzwFjok.js +0 -1
  201. package/dist/gateway/static/root/assets/settings-advanced-gate-BjgGCe3d.js +0 -1
  202. package/dist/gateway/static/root/assets/setup-status-panel-C65mJ7Xd.js +0 -1
  203. package/dist/gateway/static/root/assets/shares-settings-vClF3hGb.js +0 -1
  204. package/dist/gateway/static/root/assets/skill-reload-api-sAwxVw0W.js +0 -1
  205. package/dist/gateway/static/root/assets/task-detail-page-BXhn4MVL.js +0 -1
  206. package/dist/gateway/static/root/assets/user-model-page-CCVN7AYB.js +0 -2
  207. package/dist/gateway/static/root/assets/workflows-page-Dw6PIPAz.js +0 -6
@@ -1,9 +1,9 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
- import { resolveEffectiveAgentConfigForSession } from "../config/agent-profile.js";
4
3
  import { COMPUTER_CONTROL_TOOL, ComputerAppSchema, ComputerObservationSchema, ComputerWindowSchema, init_src } from "../../packages/computer-control-contract/src/index.js";
5
4
  import { ComputerServiceLimitsSchema, computerModelProfile, init_model_policy } from "./model-policy.js";
6
5
  import { getApiKey, init_providers, resolveModel } from "../providers/index.js";
6
+ import { resolveEffectiveAgentConfigForSession } from "../config/agent-profile.js";
7
7
  import { enterComputerControl, leaveComputerControl } from "./control-guard.js";
8
8
  import { ComputerDiagnosticSchema, ComputerOperationError, computerDiagnostic, computerRecovery } from "./errors.js";
9
9
  import { ComputerModelAdapter, predictComputerStep, readComputerJson } from "./model-adapter.js";
@@ -274,7 +274,7 @@ var ComputerRuntime = class {
274
274
  verified: verification?.status === "satisfied",
275
275
  budget: this.budget(s)
276
276
  };
277
- if (input.op === "step" && verification?.status === "satisfied") return {
277
+ if (input.op === "step" && input.expect?.kind !== "text" && verification?.status === "satisfied") return {
278
278
  status: "condition_satisfied",
279
279
  sessionId: s.id,
280
280
  verification,
@@ -387,14 +387,15 @@ var ComputerRuntime = class {
387
387
  };
388
388
  }
389
389
  const context = s.pendingContext;
390
- const verification = verifyComputerExpectation(context?.expectation, reply.value.observation);
390
+ const verification = verifyComputerExpectation(context?.expectation, reply.value.observation, context?.before);
391
391
  if (context && reply.value.receipt) s.task.record(context.goal, envelope.action, context.before, reply.value.receipt, reply.value.observation, verification);
392
392
  if (!s.pending) s.pendingContext = void 0;
393
393
  if (reply.value.status === "stopped") this.forget(s);
394
394
  return {
395
395
  ...this.present(reply.value),
396
396
  verification,
397
- verified: verification?.status === "satisfied",
397
+ verified: verification?.status === "satisfied" && !verification.preexisting,
398
+ ...verification?.preexisting ? { nextAction: "The expected text was already visible before this action; it does not verify the requested change. Observe the selected control or page-specific result before claiming success." } : {},
398
399
  ...reply.value.status !== "stopped" ? { budget: this.budget(s) } : {}
399
400
  };
400
401
  }
@@ -7,15 +7,19 @@ export declare const ComputerExpectationSchema: z.ZodDiscriminatedUnion<[z.ZodOb
7
7
  kind: z.ZodLiteral<"field">;
8
8
  label: z.ZodString;
9
9
  value: z.ZodString;
10
+ }, z.core.$strict>, z.ZodObject<{
11
+ kind: z.ZodLiteral<"selected">;
12
+ label: z.ZodString;
10
13
  }, z.core.$strict>], "kind">;
11
14
  export type ComputerExpectation = z.infer<typeof ComputerExpectationSchema>;
12
15
  export type ComputerVerification = {
13
16
  status: 'satisfied' | 'not_met' | 'unavailable';
14
17
  source: 'accessibility';
15
18
  scope: 'expectation';
19
+ preexisting?: boolean;
16
20
  };
17
21
  /** Verify only caller-specified conditions against scoped native evidence, never model prose. */
18
- export declare function verifyComputerExpectation(expectation: ComputerExpectation | undefined, observation?: ComputerObservation): ComputerVerification | undefined;
22
+ export declare function verifyComputerExpectation(expectation: ComputerExpectation | undefined, observation?: ComputerObservation, before?: ComputerObservation): ComputerVerification | undefined;
19
23
  export interface ComputerHistoryEntry {
20
24
  goal: string;
21
25
  action: ComputerAction['kind'];
@@ -1,15 +1,22 @@
1
1
  import { z } from "zod";
2
2
  //#region src/computer/task-state.ts
3
- const ComputerExpectationSchema = z.discriminatedUnion("kind", [z.object({
4
- kind: z.literal("text"),
5
- text: z.string().min(1).max(1e3)
6
- }).strict(), z.object({
7
- kind: z.literal("field"),
8
- label: z.string().min(1).max(300),
9
- value: z.string().max(4e3)
10
- }).strict()]);
3
+ const ComputerExpectationSchema = z.discriminatedUnion("kind", [
4
+ z.object({
5
+ kind: z.literal("text"),
6
+ text: z.string().min(1).max(1e3)
7
+ }).strict(),
8
+ z.object({
9
+ kind: z.literal("field"),
10
+ label: z.string().min(1).max(300),
11
+ value: z.string().max(4e3)
12
+ }).strict(),
13
+ z.object({
14
+ kind: z.literal("selected"),
15
+ label: z.string().min(1).max(300)
16
+ }).strict()
17
+ ]);
11
18
  /** Verify only caller-specified conditions against scoped native evidence, never model prose. */
12
- function verifyComputerExpectation(expectation, observation) {
19
+ function verifyComputerExpectation(expectation, observation, before) {
13
20
  if (!expectation) return;
14
21
  const result = (status) => ({
15
22
  status,
@@ -22,10 +29,18 @@ function verifyComputerExpectation(expectation, observation) {
22
29
  if (!Array.isArray(data.elements) || !data.elements.some((e) => e.role === "AXWindow")) return result("unavailable");
23
30
  if (expectation.kind === "text") {
24
31
  if (typeof data.text !== "string" || !data.text) return result("unavailable");
25
- return result(data.text.includes(expectation.text) ? "satisfied" : "not_met");
32
+ const verification = result(data.text.includes(expectation.text) ? "satisfied" : data.truncated ? "unavailable" : "not_met");
33
+ if (verification.status === "satisfied" && before && verifyComputerExpectation(expectation, before)?.status === "satisfied") verification.preexisting = true;
34
+ return verification;
35
+ }
36
+ if (data.truncated === true) return result("unavailable");
37
+ if (expectation.kind === "selected") {
38
+ const candidates = data.elements.filter((e) => e.label === expectation.label && typeof e.selected === "boolean");
39
+ if (candidates.length !== 1) return result("unavailable");
40
+ return result(candidates[0].selected ? "satisfied" : "not_met");
26
41
  }
27
42
  const fields = data.elements.filter((e) => ["AXTextField", "AXTextArea"].includes(String(e.role)) && e.label === expectation.label);
28
- if (fields.length !== 1 || typeof fields[0].value !== "string") return result("unavailable");
43
+ if (fields.length !== 1 || typeof fields[0].value !== "string" || fields[0].in_web_content === true) return result("unavailable");
29
44
  return result(fields[0].value === expectation.value ? "satisfied" : "not_met");
30
45
  } catch {
31
46
  return result("unavailable");
@@ -2,15 +2,15 @@ import { ENV_VARS, XOPC_DB_FILENAME, resolveHomeDir, resolveStateDir, resolveXop
2
2
  import { TelegramAccountConfigSchema, TelegramConfigSchema, TelegramGroupConfigSchema, TelegramTopicConfigSchema } from "../../extensions/telegram/src/config-schema.js";
3
3
  import { WeixinAccountConfigSchema, WeixinConfigSchema } from "../../extensions/weixin/src/config-schema.js";
4
4
  import { AgentImageGenerationModelSchema, AgentModelRefSchema, AgentModelsSchema, AgentsConfigSchema, BindingMatchSchema, BindingRuleSchema, BindingsConfigSchema, BrowserConfigSchema, ChannelsConfigSchema, CommandsConfigSchema, ConfigSchema, ConnectorsConfigSchema, ExperimentalConfigSchema, ExtensionSecurityConfigSchema, ExtensionSlotsConfigSchema, ExtensionsConfigSchema, GatewayAuthRateLimitSchema, GatewayAuthSchema, GatewayBindModeSchema, GatewayChannelConnectDeferModeSchema, GatewayConfigSchema, GatewayModeSchema, GatewayRemoteSchema, GatewaySecuritySchema, GatewayTailscaleConsentSchema, GatewayTailscaleSchema, GatewayTlsSchema, GatewayTrustedProxySchema, GatewayWebchatConfigSchema, HeartbeatConfigSchema, McpConfigSchema, McpOAuthConfigSchema, McpServerSchema, MediaUnderstandingCapabilitiesSchema, MediaUnderstandingModelSchema, MessagesConfigSchema, ModelCatalogConfigSchema, ModelsDevConfigSchema, ProviderAuthConfigSchema, ProviderAzureConfigSchema, ProviderRequestOverridesSchema, ProvidersConfigSchema, RuntimeToolsConfigSchema, STTConfigSchema, STTFallbackConfigSchema, STTProviderConfigSchema, SearchProviderEntrySchema, SessionConfigSchema, SessionDmScopeSchema, SessionResetByTypeSchema, SessionResetConfigSchema, SessionResetModeSchema, SessionScopeSchema, SessionStorageConfigSchema, TTSConfigSchema, TTSEdgeConfigSchema, TTSFallbackConfigSchema, TTSModelOverridesConfigSchema, TTSProviderConfigSchema, TTSSummarizationConfigSchema, ToolsConfigSchema, ToolsMediaAudioConfigSchema, ToolsMediaConfigSchema, TuiConfigSchema, TunnelConfigSchema, TunnelConsentSchema, UpdateAutoConfigSchema, UpdateConfigSchema, VoiceConfigSchema, VoiceRefinementConfigSchema, WebSearchConfigSchema, WebToolsConfigSchema, WebsiteBlocklistSchema, WorkspaceConfigSchema, WorkspaceImportConfigSchema, getAgentDefaultImageGenerationModelConfig, getAgentDefaultImageModelConfig, getAgentDefaultModelRef, init_schema, parseModelRef } from "./schema.js";
5
- import { applyConfigOverrides, getConfigOverrides, resetConfigOverrides, setConfigOverride, unsetConfigOverride } from "./runtime-overrides.js";
5
+ import { clearConfigValueCache, getAllowedCommands, getCacheStats, init_resolve_config_value, resolveConfigValue, resolveHeaders, testApiKeyResolution } from "./resolve-config-value.js";
6
6
  import { expandWorkspacePathString, init_workspace_path, normalizeWorkspaceDir, resolveWorkspaceRoot } from "./workspace-path.js";
7
7
  import { resolveDefaultAgentWorkspaceDir } from "./workspace-defaults.js";
8
8
  import { resolveAgentDir as resolveAgentDir$1, resolveAgentHomeDir as resolveAgentHomeDir$1, resolveAgentWorkspaceDir } from "../agent/agent-scope.js";
9
- import { extractProfileAgentId, resolveEffectiveAgentConfigForAgent, resolveEffectiveAgentConfigForSession, resolveEffectiveAgentProfile, resolveEffectiveAgentProfileForSession } from "./agent-profile.js";
10
9
  import { FILENAMES, WORKSPACE_FILES, existsSync, hasBundledExtensionManifest, init_paths, resolveAgentAuthProfilesPath, resolveAgentDir, resolveAgentHomeDir, resolveAgentProfileDir, resolveAgentProfileMarkdownPath, resolveAuthProfilesPath, resolveBinDir, resolveBundledExtensionsDir, resolveBundledSkillsDir, resolveConfigPath, resolveCredentialsDir, resolveExtensionSdkPath, resolveExtensionsDir, resolveExtensionsLockPath, resolveInboxDir, resolveInboxMessagePath, resolveInboxPendingDir, resolveInboxProcessedDir, resolveLogPath, resolveLogsDir, resolveMcpOAuthPath, resolveModelsJsonPath, resolveNodeBinDir, resolveNodeBinPath, resolveNodeToolsDir, resolveNpmBinPath, resolveOAuthPath, resolvePidPath, resolveSkillPath, resolveSkillsCachePath, resolveSkillsDir, resolveSkillsLockPath, resolveSocketPath, resolveStatusPath, resolveToolsDir, resolveWorkspaceExtensionsDir, resolveWorkspaceFile, resolveWorkspaceStateDir, resolveWorkspaceStatePath, resolveXopcBinPath } from "./paths.js";
11
- import { init_loader, loadConfig, saveConfig } from "./loader.js";
12
- import { clearConfigValueCache, getAllowedCommands, getCacheStats, init_resolve_config_value, resolveConfigValue, resolveHeaders, testApiKeyResolution } from "./resolve-config-value.js";
13
10
  import { CustomModelSchema, ImageGenerationCapabilitiesSchema, ImageGenerationModelSchema, ImageGenerationProviderSchema, ModelOverrideSchema, ModelsJsonSchema, OpenAICompatSchema, OpenAICompletionsCompatSchema, OpenAIResponsesCompatSchema, OpenRouterRoutingSchema, ProviderConfigSchema, VercelGatewayRoutingSchema, getDefaultModelValues, init_models_json, loadModelsJson, modelsJsonExists, saveModelsJson, validateModelsConfig } from "./models-json.js";
11
+ import { init_loader, loadConfig, saveConfig } from "./loader.js";
12
+ import { applyConfigOverrides, getConfigOverrides, resetConfigOverrides, setConfigOverride, unsetConfigOverride } from "./runtime-overrides.js";
13
+ import { extractProfileAgentId, resolveEffectiveAgentConfigForAgent, resolveEffectiveAgentConfigForSession, resolveEffectiveAgentProfile, resolveEffectiveAgentProfileForSession } from "./agent-profile.js";
14
14
  import { canonicalizeConfiguredMcpServer, isKnownCliMcpTypeAlias, normalizeConfiguredMcpServers, resolveXopcMcpTransportAlias } from "./mcp-config-normalize.js";
15
15
  import { formatThinkingLevels, listThinkingLevels, normalizeElevatedMode, normalizeReasoningLevel, normalizeThinkLevel, normalizeVerboseLevel, thinkLevelToNumber } from "../agent/transcript/thinking-types.js";
16
16
  import { getWorkspacePath } from "./workspace-path-helpers.js";
@@ -2,10 +2,10 @@ import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
2
  import { createLogger } from "../utils/logger/index.js";
3
3
  import { init_logger } from "../utils/logger.js";
4
4
  import { ConfigSchema, init_schema } from "./schema.js";
5
- import { init_paths, resolveConfigPath } from "./paths.js";
6
5
  import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
7
- import { assertChannelPluginConfigs, init_validate_channel_configs } from "./validate-channel-configs.js";
6
+ import { init_paths, resolveConfigPath } from "./paths.js";
8
7
  import { init_resolution, setActivePlatformDiscovery } from "../platform/resolution.js";
8
+ import { assertChannelPluginConfigs, init_validate_channel_configs } from "./validate-channel-configs.js";
9
9
  import { dirname } from "path";
10
10
  import { existsSync, mkdirSync, promises, readFileSync } from "fs";
11
11
  import { config } from "dotenv";
@@ -1,7 +1,7 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
- import { init_paths, resolveModelsJsonPath } from "./paths.js";
3
- import { init_write_file_atomic, writeTextAtomicSync } from "../infra/write-file-atomic.js";
4
2
  import { ComputerProfileSchema, init_src } from "../../packages/computer-control-contract/src/index.js";
3
+ import { init_write_file_atomic, writeTextAtomicSync } from "../infra/write-file-atomic.js";
4
+ import { init_paths, resolveModelsJsonPath } from "./paths.js";
5
5
  import { init_model_policy, isComputerModel } from "../computer/model-policy.js";
6
6
  import { existsSync, readFileSync } from "fs";
7
7
  import { z } from "zod";
@@ -1,7 +1,7 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
- import { ComputerConfigSchema, init_config } from "../computer/config.js";
3
2
  import { AgentModelsOverrideSchema, AgentsConfigSchema as AgentsConfigSchema$1, DEFAULT_AGENT_MODEL_REF, ImageGenerationRouteSchema, ModelRouteSchema } from "../agent-config/schema.js";
4
3
  import { init_agent_config } from "../agent-config/index.js";
4
+ import { ComputerConfigSchema, init_config } from "../computer/config.js";
5
5
  import { DEFAULT_CONTEXT_COMPACTION_POLICY, UserContextConfigSchema, init_config as init_config$1 } from "../user-context/config.js";
6
6
  import { init_default_model } from "./default-model.js";
7
7
  import { init_public_url, validatePublicUrl } from "./public-url.js";
@@ -1,7 +1,7 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
- import { init_paths, resolveExtensionsDir, resolveExtensionsLockPath } from "../config/paths.js";
4
3
  import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
4
+ import { init_paths, resolveExtensionsDir, resolveExtensionsLockPath } from "../config/paths.js";
5
5
  import { dirname, join } from "path";
6
6
  import { existsSync } from "fs";
7
7
  import { mkdir, readFile } from "fs/promises";
@@ -1,6 +1,6 @@
1
1
  import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentDir, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId, resolveUserPath, validateAgentIdForNewAgent } from "../agent/agent-scope.js";
2
- import { resolveEffectiveAgentProfile } from "../config/agent-profile.js";
3
2
  import { WORKSPACE_FILES, init_paths } from "../config/paths.js";
3
+ import { resolveEffectiveAgentProfile } from "../config/agent-profile.js";
4
4
  import { AGENT_PROFILE_MARKDOWN_SYSTEM_FILES, REQUIRED_AGENT_PROFILE_MARKDOWN_FILE_SET } from "../agent/context/workspace.js";
5
5
  import { isPathUnderWorkspace, resolveWorkspaceSafePath } from "./workspace-editor-path.js";
6
6
  import { seedAgentProfileMarkdownFiles } from "../agent/context/workspace-seed.js";
@@ -1,7 +1,7 @@
1
1
  import { init_paths_state, resolveStateDir } from "../config/paths-state.js";
2
2
  import { init_agent_scope, resolveAgentProfileDir } from "../agent/agent-scope.js";
3
- import { extractProfileAgentId } from "../config/agent-profile.js";
4
3
  import { init_paths, resolveConfigPath, resolveSkillsDir } from "../config/paths.js";
4
+ import { extractProfileAgentId } from "../config/agent-profile.js";
5
5
  import { isBareProfileMarkdownFileName, resolveProfileMarkdownPathIfBareName } from "../agent/tools/tool-paths.js";
6
6
  import { isPathUnderWorkspace, resolveWorkspaceSafePath } from "./workspace-editor-path.js";
7
7
  import { basename, isAbsolute, resolve } from "node:path";
@@ -1,9 +1,9 @@
1
1
  import { ContextPlanningConfigSchema, KnowledgeMemoryConfigSchema, UserModelConfigSchema, init_config } from "../../../user-context/config.js";
2
2
  import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveDefaultAgentId } from "../../../agent/agent-scope.js";
3
3
  import { resolveModelsJsonPath } from "../../../config/paths.js";
4
- import { buildChannelCatalogForConfig, buildChannelCatalogFromSnapshot, getChannelSetupStatus, init_channel_catalog_service } from "../../../channels/catalog/channel-catalog-service.js";
5
4
  import { init_models_json, loadModelsJson } from "../../../config/models-json.js";
6
5
  import { CredentialResolver, init_credentials } from "../../../auth/credentials.js";
6
+ import { buildChannelCatalogForConfig, buildChannelCatalogFromSnapshot, getChannelSetupStatus, init_channel_catalog_service } from "../../../channels/catalog/channel-catalog-service.js";
7
7
  import { getProviderRegistry, init_plugin_registry } from "../../../providers/plugin-registry.js";
8
8
  import { getAllProviders, init_providers, isProviderConfigured } from "../../../providers/index.js";
9
9
  import { normalizeConfiguredMcpServers } from "../../../config/mcp-config-normalize.js";
@@ -1,4 +1,6 @@
1
+ import { getDevice } from "../../../storage/sqlite/device-access-repository.js";
1
2
  import { registerNotificationDevice, removeNotificationDevice, updateNotificationDevicePreferences } from "../../../notifications/device-store.js";
3
+ import { harmonyPushConfig } from "../../../notifications/harmony-push.js";
2
4
  import { getGatewayPrincipal } from "../../security/gateway-principal.js";
3
5
  //#region src/gateway/hono/routes/device-push.ts
4
6
  function stringField(value, maxLength) {
@@ -27,7 +29,7 @@ function parsePreferences(value) {
27
29
  return result;
28
30
  }
29
31
  function parsePlatform(value) {
30
- return value === "ios" || value === "android" ? value : null;
32
+ return value === "ios" || value === "android" || value === "harmonyos" ? value : null;
31
33
  }
32
34
  function parsePermission(value) {
33
35
  return value === "granted" || value === "denied" || value === "unknown" ? value : null;
@@ -61,6 +63,14 @@ function registerDevicePushRoutes(authenticated) {
61
63
  ok: false,
62
64
  error: "Invalid push registration"
63
65
  }, 400);
66
+ if (getDevice(deviceId)?.platform !== platform) return c.json({
67
+ ok: false,
68
+ error: "Push platform must match the paired device"
69
+ }, 400);
70
+ if (platform === "harmonyos" && !harmonyPushConfig()) return c.json({
71
+ ok: false,
72
+ error: "Harmony push is not configured on this Gateway"
73
+ }, 503);
64
74
  const device = registerNotificationDevice({
65
75
  deviceId,
66
76
  pushToken,
@@ -1,5 +1,5 @@
1
- import { resolveModelsJsonPath } from "../../../config/paths.js";
2
1
  import { init_resolve_config_value, testApiKeyResolution } from "../../../config/resolve-config-value.js";
2
+ import { resolveModelsJsonPath } from "../../../config/paths.js";
3
3
  import { computerModelProfile, init_model_policy } from "../../../computer/model-policy.js";
4
4
  import { init_models_json, loadModelsJson, saveModelsJson, validateModelsConfig } from "../../../config/models-json.js";
5
5
  import { getModelCatalogStore, init_model_catalog_store } from "../../../providers/model-catalog-store.js";
@@ -51,7 +51,7 @@ function readIdempotencyKey(value) {
51
51
  function parseCaptureSource(body) {
52
52
  return {
53
53
  channel: typeof body.channel === "string" && VALID_CHANNELS.has(body.channel) ? body.channel : "web",
54
- platform: body.platform === "ios" || body.platform === "android" ? body.platform : void 0
54
+ platform: body.platform === "ios" || body.platform === "android" || body.platform === "harmonyos" ? body.platform : void 0
55
55
  };
56
56
  }
57
57
  function buildNotePatch(body) {
@@ -21,8 +21,8 @@ import { VoiceSessionCreationError, resolveStreamingStt, resolveStreamingTts } f
21
21
  import { getGatewayPrincipal } from "../../security/gateway-principal.js";
22
22
  import { createGatewayRouteLogger } from "../lib/route-logger.js";
23
23
  import { selectPlatformVoice, voiceSettingsCatalog } from "../../../voice/platform-settings.js";
24
- import { listTtsProvidersForApi } from "../../../voice/tts/list-providers.js";
25
24
  import { listLocalVoiceModelStatuses, removeLocalVoiceModel, startLocalVoiceModelInstall } from "../../../voice/local/model-manager.js";
25
+ import { listTtsProvidersForApi } from "../../../voice/tts/list-providers.js";
26
26
  import { z } from "zod";
27
27
  //#region src/gateway/hono/routes/voice.ts
28
28
  init_voice();
@@ -9,8 +9,8 @@ import { resolveWorkflowRunArtifactsDir } from "../../../workflows/store/paths.j
9
9
  import { WorkflowDraftService } from "../../../workflows/draft/workflow-draft-service.js";
10
10
  import { WorkflowDraftConflictError, WorkflowDraftStore } from "../../../workflows/authoring/workflow-draft-store.js";
11
11
  import "../../../workflows/authoring/index.js";
12
- import { ProjectWorkflowPresetRepository } from "../../../workflows/project-presets/project-workflow-preset-repository.js";
13
12
  import "../../../workflows/draft/index.js";
13
+ import { ProjectWorkflowPresetRepository } from "../../../workflows/project-presets/project-workflow-preset-repository.js";
14
14
  import { basename, join } from "node:path";
15
15
  import { readFile, stat } from "node:fs/promises";
16
16
  //#region src/gateway/hono/routes/workflows.ts
@@ -1,7 +1,7 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
- import { loadConfig, saveConfig } from "../../config/loader.js";
4
3
  import { getModelRegistry } from "../../providers/model-registry.js";
4
+ import { loadConfig, saveConfig } from "../../config/loader.js";
5
5
  import { init_providers } from "../../providers/index.js";
6
6
  import { disposeAllSessionMcpRuntimes } from "../../agent/mcp/bundle-mcp-runtime.js";
7
7
  import { reloadImageGenerationProviders } from "../../agent/image/generation/provider-registry.js";
@@ -13,17 +13,17 @@ import { getSessionConfig } from "../storage/sqlite/config-repository.js";
13
13
  import "../storage/sqlite/index.js";
14
14
  import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
15
15
  import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agent/agent-scope.js";
16
- import { init_agent_session_key, resolveAgentMainConversationId } from "../routing/agent-session-key.js";
17
- import { init_session_key, resolveConversationId, sanitizeSegment } from "../routing/session-key.js";
18
- import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
19
- import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
20
16
  import { init_paths, resolveConfigPath, resolveExtensionsDir } from "../config/paths.js";
17
+ import { prewarmModelRegistry } from "../providers/model-registry.js";
21
18
  import { areExtensionsGloballyDisabled } from "../extensions/discover-extensions.js";
22
19
  import { buildExtensionMetadataSnapshot } from "../extensions/extension-metadata-snapshot.js";
23
20
  import { buildChannelCatalogForConfig, buildChannelCatalogFromSnapshot, init_channel_catalog_service } from "../channels/catalog/channel-catalog-service.js";
24
21
  import { loadConfig, saveConfig } from "../config/loader.js";
25
- import { prewarmModelRegistry } from "../providers/model-registry.js";
22
+ import { init_agent_session_key, resolveAgentMainConversationId } from "../routing/agent-session-key.js";
23
+ import { init_session_key, resolveConversationId, sanitizeSegment } from "../routing/session-key.js";
24
+ import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
26
25
  import { init_providers, providers_exports } from "../providers/index.js";
26
+ import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
27
27
  import { TaskRepository } from "../tasks/task-repository.js";
28
28
  import { TaskConversationRepository } from "../tasks/task-conversation-repository.js";
29
29
  import { getEmbeddedExecutionSession } from "../agent/embedded/execution-context.js";
@@ -97,7 +97,7 @@ export interface NoteAiDeepMeta {
97
97
  }
98
98
  export interface CaptureSource {
99
99
  channel: CaptureChannel;
100
- platform?: 'ios' | 'android';
100
+ platform?: 'ios' | 'android' | 'harmonyos';
101
101
  }
102
102
  export interface NoteTaskMeta {
103
103
  done: boolean;
@@ -27,7 +27,7 @@ function normalizePreferences(input) {
27
27
  function deviceFromRow(row) {
28
28
  return {
29
29
  id: row.device_id,
30
- platform: row.platform === "android" ? "android" : "ios",
30
+ platform: row.platform === "harmonyos" ? "harmonyos" : row.platform === "android" ? "android" : "ios",
31
31
  pushToken: row.push_token,
32
32
  enabled: row.enabled !== 0,
33
33
  permissions: row.permissions === "granted" || row.permissions === "denied" ? row.permissions : "unknown",
@@ -0,0 +1,26 @@
1
+ import type { NotificationTarget } from '@xopcai/gateway-contract';
2
+ type ServiceAccount = {
3
+ project_id: string;
4
+ key_id: string;
5
+ sub_account: string;
6
+ private_key: string;
7
+ };
8
+ type PushCategory = 'WORK' | 'IM' | 'MARKETING';
9
+ export type HarmonyPushConfig = {
10
+ accountFile: string;
11
+ category: PushCategory;
12
+ testMessage: boolean;
13
+ };
14
+ export type HarmonyNotification = {
15
+ pushToken: string;
16
+ eventId: string;
17
+ title: string;
18
+ body?: string;
19
+ gatewayId?: string;
20
+ target?: NotificationTarget;
21
+ };
22
+ export declare function harmonyPushConfig(env?: NodeJS.ProcessEnv): HarmonyPushConfig | undefined;
23
+ export declare function createHarmonyPushJwt(account: ServiceAccount, now?: number): string;
24
+ /** Uses HarmonyOS V3 service-account authentication, not the Android HMS OAuth flow. */
25
+ export declare function sendHarmonyPush(notification: HarmonyNotification, fetchImpl?: typeof fetch, config?: HarmonyPushConfig | undefined): Promise<string>;
26
+ export {};
@@ -0,0 +1,94 @@
1
+ import { isAbsolute } from "node:path";
2
+ import { constants, createHash, createPrivateKey, sign } from "node:crypto";
3
+ import { readFile } from "node:fs/promises";
4
+ //#region src/notifications/harmony-push.ts
5
+ function harmonyPushConfig(env = process.env) {
6
+ const accountFile = env.XOPC_HARMONY_PUSH_SERVICE_ACCOUNT?.trim();
7
+ const category = env.XOPC_HARMONY_PUSH_CATEGORY;
8
+ if (!accountFile || !isAbsolute(accountFile) || ![
9
+ "WORK",
10
+ "IM",
11
+ "MARKETING"
12
+ ].includes(category ?? "")) return void 0;
13
+ return {
14
+ accountFile,
15
+ category,
16
+ testMessage: env.XOPC_HARMONY_PUSH_TEST_MESSAGE === "true"
17
+ };
18
+ }
19
+ function createHarmonyPushJwt(account, now = Date.now()) {
20
+ if (!/^\d+$/.test(account.project_id) || !account.key_id || !account.sub_account || !account.private_key) throw new Error("Invalid Harmony push service account");
21
+ const key = createPrivateKey(account.private_key);
22
+ if (key.asymmetricKeyType !== "rsa" || (key.asymmetricKeyDetails?.modulusLength ?? 0) < 2048) throw new Error("Harmony push requires an RSA service account key of at least 2048 bits");
23
+ const iat = Math.floor(now / 1e3);
24
+ const input = `${Buffer.from(JSON.stringify({
25
+ alg: "PS256",
26
+ typ: "JWT",
27
+ kid: account.key_id
28
+ })).toString("base64url")}.${Buffer.from(JSON.stringify({
29
+ iss: account.sub_account,
30
+ aud: "https://oauth-login.cloud.huawei.com/oauth2/v3/token",
31
+ iat,
32
+ exp: iat + 3600
33
+ })).toString("base64url")}`;
34
+ return `${input}.${sign("sha256", Buffer.from(input), {
35
+ key,
36
+ padding: constants.RSA_PKCS1_PSS_PADDING,
37
+ saltLength: constants.RSA_PSS_SALTLEN_DIGEST
38
+ }).toString("base64url")}`;
39
+ }
40
+ /** Uses HarmonyOS V3 service-account authentication, not the Android HMS OAuth flow. */
41
+ async function sendHarmonyPush(notification, fetchImpl = fetch, config = harmonyPushConfig()) {
42
+ if (!config) throw new Error("Harmony push is not configured");
43
+ let account;
44
+ let jwt;
45
+ try {
46
+ account = JSON.parse(await readFile(config.accountFile, "utf8"));
47
+ jwt = createHarmonyPushJwt(account);
48
+ } catch {
49
+ throw new Error("Harmony push service account could not be loaded");
50
+ }
51
+ const notifyId = createHash("sha256").update(notification.eventId).digest().readUInt32BE(0) & 2147483647;
52
+ const navigation = notification.gatewayId && notification.target ? Buffer.from(JSON.stringify({
53
+ gatewayId: notification.gatewayId,
54
+ eventId: notification.eventId,
55
+ target: notification.target
56
+ })).toString("base64url") : void 0;
57
+ const response = await fetchImpl(`https://push-api.cloud.huawei.com/v3/${account.project_id}/messages:send`, {
58
+ method: "POST",
59
+ redirect: "error",
60
+ signal: AbortSignal.timeout(1e4),
61
+ headers: {
62
+ "Content-Type": "application/json",
63
+ Authorization: `Bearer ${jwt}`,
64
+ "push-type": "0"
65
+ },
66
+ body: JSON.stringify({
67
+ payload: { notification: {
68
+ category: config.category,
69
+ title: notification.title.slice(0, 100),
70
+ body: (notification.body || notification.title).slice(0, 200),
71
+ clickAction: navigation ? {
72
+ actionType: 1,
73
+ uri: `xopc://notification#p=${navigation}`
74
+ } : { actionType: 0 },
75
+ foregroundShow: false,
76
+ notifyId
77
+ } },
78
+ target: { token: [notification.pushToken] },
79
+ pushOptions: {
80
+ testMessage: config.testMessage,
81
+ ttl: 86400
82
+ }
83
+ })
84
+ });
85
+ if (!response.ok) throw new Error(`Harmony push request failed (${response.status})`);
86
+ const result = await response.json();
87
+ if (result.code !== "80000000" || typeof result.requestId !== "string" || !result.requestId) {
88
+ const code = typeof result.code === "string" && /^\d{8}$/.test(result.code) ? result.code : "invalid_response";
89
+ throw new Error(`Harmony push rejected (${code})`);
90
+ }
91
+ return result.requestId;
92
+ }
93
+ //#endregion
94
+ export { createHarmonyPushJwt, harmonyPushConfig, sendHarmonyPush };
@@ -1,5 +1,6 @@
1
1
  import { type ProactiveChannelSender } from './proactive-channel.js';
2
2
  import { type NotificationPlan } from './planner.js';
3
+ import { sendHarmonyPush } from './harmony-push.js';
3
4
  export declare class NotificationService {
4
5
  private readonly options;
5
6
  private timer;
@@ -9,6 +10,7 @@ export declare class NotificationService {
9
10
  publish: (type: string, payload: unknown) => void;
10
11
  fetch?: typeof fetch;
11
12
  sendChannel?: ProactiveChannelSender;
13
+ sendHarmony?: typeof sendHarmonyPush;
12
14
  });
13
15
  start(): void;
14
16
  stop(): void;
@@ -3,6 +3,7 @@ import { init_logger } from "../utils/logger.js";
3
3
  import { getSqliteDatabase, init_transaction, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
4
4
  import { localizeNotification } from "../../packages/gateway-contract/src/notifications.js";
5
5
  import { init_src } from "../../packages/gateway-contract/src/index.js";
6
+ import { getOrCreateGatewayIdentity } from "../storage/sqlite/gateway-identity-repository.js";
6
7
  import { proactivePreferences } from "../proactive/policy/service.js";
7
8
  import { flushDueDigests } from "../proactive/inbox/digest.js";
8
9
  import { notificationPlanFromGatewayEvent } from "./planner.js";
@@ -11,6 +12,7 @@ import { createNotificationEvent, deferNotificationDelivery, expireUndeliverable
11
12
  import { drainChannelNotifications, enqueueChannelNotification } from "./proactive-channel.js";
12
13
  import { drainBrowserPush, enqueueBrowserPush } from "./web-push.js";
13
14
  import { disableNotificationDeviceForPushToken, listDeliverableNotificationDevices } from "./device-store.js";
15
+ import { sendHarmonyPush } from "./harmony-push.js";
14
16
  //#region src/notifications/service.ts
15
17
  init_transaction();
16
18
  init_src();
@@ -162,6 +164,18 @@ var NotificationService = class {
162
164
  const fetchImpl = this.options.fetch ?? fetch;
163
165
  const localized = localizeNotification(delivery.event, delivery.locale);
164
166
  try {
167
+ if (delivery.platform === "harmonyos") {
168
+ const ticket = await (this.options.sendHarmony ?? sendHarmonyPush)({
169
+ pushToken: delivery.pushToken,
170
+ eventId: delivery.event.id,
171
+ gatewayId: getOrCreateGatewayIdentity().id,
172
+ target: delivery.event.target,
173
+ title: delivery.event.type === "proactive.insight" ? delivery.locale === "zh" ? "有一项工作需要查看" : "A work update is ready" : localized.localizedTitle,
174
+ body: delivery.event.type === "proactive.insight" ? delivery.locale === "zh" ? "打开 xopc 查看详情。" : "Open xopc to review it." : localized.localizedBody
175
+ }, fetchImpl);
176
+ markNotificationDeliveryAccepted(delivery.event.id, delivery.deviceId, ticket, Number.MAX_SAFE_INTEGER);
177
+ return;
178
+ }
165
179
  const response = await fetchImpl(EXPO_PUSH_URL, {
166
180
  method: "POST",
167
181
  headers: {
@@ -200,7 +214,7 @@ var NotificationService = class {
200
214
  }
201
215
  }
202
216
  async checkReceipts() {
203
- const withTickets = listDueNotificationDeliveries("accepted").filter((delivery) => delivery.providerTicketId);
217
+ const withTickets = listDueNotificationDeliveries("accepted").filter((delivery) => delivery.platform !== "harmonyos" && delivery.providerTicketId);
204
218
  if (withTickets.length === 0) return;
205
219
  const fetchImpl = this.options.fetch ?? fetch;
206
220
  try {
@@ -1,8 +1,10 @@
1
1
  import { type ProductNotification } from '@xopcai/gateway-contract';
2
+ import type { NotificationDevicePlatform } from './types.js';
2
3
  export type NotificationDelivery = {
3
4
  event: ProductNotification;
4
5
  deviceId: string;
5
6
  pushToken: string;
7
+ platform: NotificationDevicePlatform;
6
8
  locale: 'en' | 'zh';
7
9
  attempts: number;
8
10
  providerTicketId?: string;
@@ -36,6 +36,7 @@ function deliveryFromRow(row) {
36
36
  event: eventFromRow(row),
37
37
  deviceId: row.device_id,
38
38
  pushToken: row.push_token,
39
+ platform: row.platform,
39
40
  locale: row.locale === "zh" ? "zh" : "en",
40
41
  attempts: row.attempts,
41
42
  ...row.provider_ticket_id ? { providerTicketId: row.provider_ticket_id } : {}
@@ -88,7 +89,7 @@ function acknowledgeNotification(eventId, consumerId, surface) {
88
89
  }
89
90
  const DELIVERY_JOIN = `
90
91
  SELECT e.*, d.device_id, d.attempts, d.provider_ticket_id,
91
- n.push_token, n.locale
92
+ n.push_token, n.locale, n.platform
92
93
  FROM notification_deliveries d
93
94
  JOIN notification_events e ON e.event_id = d.event_id
94
95
  JOIN device_push_endpoints n ON n.device_id = d.device_id
@@ -1,4 +1,4 @@
1
- export type NotificationDevicePlatform = 'ios' | 'android';
1
+ 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 = {
@@ -1,5 +1,5 @@
1
- import { init_sync_provider_auth, resolveProviderApiKeyForAgentSync } from "../../auth/sync-provider-auth.js";
2
1
  import { getApiKeyFromEnv, init_env_keys } from "../env-keys.js";
2
+ import { init_sync_provider_auth, resolveProviderApiKeyForAgentSync } from "../../auth/sync-provider-auth.js";
3
3
  import { getDefaultAuthProfileStore } from "./auth-profile-store.js";
4
4
  //#region src/providers/auth-runtime/resolve-auth.ts
5
5
  init_env_keys();
@@ -1,11 +1,11 @@
1
1
  import { __esmMin, __exportAll } from "../../_virtual/_rolldown/runtime.js";
2
2
  import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
3
- import { getModelOAuthProviderIds, init_registry } from "../auth/oauth/registry.js";
4
- import { hasProviderAuthOnDiskSync, init_sync_provider_auth } from "../auth/sync-provider-auth.js";
5
3
  import { PROVIDER_ENV_MAP, getApiKeyFromEnv, init_env_keys } from "./env-keys.js";
6
4
  import { init_model_ref, splitProviderModelRef } from "./model-ref.js";
7
5
  import { ModelRegistry, getModelRegistry, init_model_registry, prewarmModelRegistry, resetModelRegistry } from "./model-registry.js";
6
+ import { getModelOAuthProviderIds, init_registry } from "../auth/oauth/registry.js";
8
7
  import { CredentialResolver, hasCredentials, init_credentials } from "../auth/credentials.js";
8
+ import { hasProviderAuthOnDiskSync, init_sync_provider_auth } from "../auth/sync-provider-auth.js";
9
9
  import { EXTENSION_PROVIDER_BASE_URL, init_constants } from "./constants.js";
10
10
  import { applyOfficialModelMetadataCorrections, getSupplementalModels, init_model_supplements } from "./model-supplements.js";
11
11
  import { getProviderRegistry, init_plugin_registry } from "./plugin-registry.js";
@@ -1,7 +1,7 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
2
  import { init_paths_state, resolveXopcCloudCatalogCachePath } from "../config/paths-state.js";
3
- import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
4
3
  import { ComputerProfileSchema, init_src } from "../../packages/computer-control-contract/src/index.js";
4
+ import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
5
5
  import { voiceManifestSchema } from "../../packages/realtime-protocol/src/voice-catalog.js";
6
6
  import { init_voice } from "../../packages/realtime-protocol/src/voice.js";
7
7
  import { readFileSync, rmSync } from "node:fs";
@@ -1,8 +1,8 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
2
  import { createLogger } from "../utils/logger/index.js";
3
3
  import { init_logger } from "../utils/logger.js";
4
- import { resolveModelsJsonPath } from "../config/paths.js";
5
4
  import { init_resolve_config_value, resolveConfigValue, resolveHeaders } from "../config/resolve-config-value.js";
5
+ import { resolveModelsJsonPath } from "../config/paths.js";
6
6
  import { getDefaultModelValues, init_models_json, validateModelsConfig } from "../config/models-json.js";
7
7
  import { getApiKeyFromEnv, init_env_keys } from "./env-keys.js";
8
8
  import { getModelCatalogStore, init_model_catalog_store } from "./model-catalog-store.js";