@xopcai/xopc 0.0.270 → 0.0.272

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 (245) hide show
  1. package/dist/browser-ext/dist/assets/{auth-cwEj8rFb.js → auth-C1QI-uMG.js} +65 -14
  2. package/dist/browser-ext/dist/background.js +23 -2
  3. package/dist/browser-ext/dist/pairing-handoff.js +51 -0
  4. package/dist/browser-ext/dist/sidepanel.html +1 -1
  5. package/dist/browser-ext/dist/sidepanel.js +39 -27
  6. package/dist/browser-ext/manifest.json +12 -1
  7. package/dist/extensions/telegram/xopc.extension.json +1 -1
  8. package/dist/gateway/static/root/assets/{activity-store-D_0FmdRj.js → activity-store-DffqjeqQ.js} +1 -1
  9. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-IZvEXak_.js → agent-avatar-dicebear-Cwj4HCYY.js} +1 -1
  10. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-6CLfLxVc.js +1 -0
  11. package/dist/gateway/static/root/assets/agents-B6mu64fY.js +1 -0
  12. package/dist/gateway/static/root/assets/{api-O3TTQ4qN.js → api-CGLdye4i.js} +1 -1
  13. package/dist/gateway/static/root/assets/{app-management-settings-panel-Cqqsbzri.js → app-management-settings-panel-BLujSbaw.js} +1 -1
  14. package/dist/gateway/static/root/assets/{appearance-settings-DaJyf32s.js → appearance-settings-BXMcueb8.js} +1 -1
  15. package/dist/gateway/static/root/assets/apps-page-BEgy4hY3.js +1 -0
  16. package/dist/gateway/static/root/assets/{archive-plugin-kDPnDTJI.js → archive-plugin-D4bUampf.js} +1 -1
  17. package/dist/gateway/static/root/assets/{attachment-load-CJ3VceKS.js → attachment-load-CBGNA2Ys.js} +1 -1
  18. package/dist/gateway/static/root/assets/{automations-page-JwMtU8XB.js → automations-page-dQyolNmy.js} +1 -1
  19. package/dist/gateway/static/root/assets/automations-workspace-DxRFrmrV.js +6 -0
  20. package/dist/gateway/static/root/assets/{binary-plugins-DzyZXLBX.js → binary-plugins-bbvp81h2.js} +1 -1
  21. package/dist/gateway/static/root/assets/{block-editor-kTt3gYIJ.js → block-editor-C8e6Wri4.js} +3 -3
  22. package/dist/gateway/static/root/assets/{browser-automation-inputs-BKohPYR4.js → browser-automation-inputs-oJWJtQa6.js} +1 -1
  23. package/dist/gateway/static/root/assets/{browser-automations-page-ktQfFPk-.js → browser-automations-page-CAcJQSjN.js} +2 -2
  24. package/dist/gateway/static/root/assets/browser-settings-page-TLAlqcPo.js +8 -0
  25. package/dist/gateway/static/root/assets/capabilities-settings-panel-z-K_jrZz.js +8 -0
  26. package/dist/gateway/static/root/assets/channels-settings-Dzrk33aB.js +1 -0
  27. package/dist/gateway/static/root/assets/{channels-status-swr-DrqzYmDr.js → channels-status-swr-CfOPNnVr.js} +1 -1
  28. package/dist/gateway/static/root/assets/{chat-terminal-dock-CIFGGLGa.js → chat-terminal-dock-9ZOl92kh.js} +2 -2
  29. package/dist/gateway/static/root/assets/clock-3-DnrAnuyZ.js +1 -0
  30. package/dist/gateway/static/root/assets/connectors-page-B1dIoRNi.js +2 -0
  31. package/dist/gateway/static/root/assets/cron-expression-C26e13YU.js +2 -0
  32. package/dist/gateway/static/root/assets/date-picker-Dj6FRLF9.js +1 -0
  33. package/dist/gateway/static/root/assets/{dependency-picker-D3vNIjRI.js → dependency-picker-D1q89tVc.js} +1 -1
  34. package/dist/gateway/static/root/assets/{desktop-pet-fQwRb_3p.js → desktop-pet-DfqZBvhp.js} +1 -1
  35. package/dist/gateway/static/root/assets/{desktop-pet-settings-DfOJ-GvT.js → desktop-pet-settings-HCEh2MOm.js} +1 -1
  36. package/dist/gateway/static/root/assets/device-pairing-wizard-CPth92s6.js +1 -0
  37. package/dist/gateway/static/root/assets/{extension-debug-page-Cn53jB5-.js → extension-debug-page-C8cAWVoK.js} +1 -1
  38. package/dist/gateway/static/root/assets/{extension-page-IDpLCxpC.js → extension-page-5N87Vaym.js} +1 -1
  39. package/dist/gateway/static/root/assets/extension-settings-page-D85SAUFP.js +1 -0
  40. package/dist/gateway/static/root/assets/{gateway-config-swr-B7dcmP7Q.js → gateway-config-swr-BjsDnB_n.js} +1 -1
  41. package/dist/gateway/static/root/assets/gateway-settings-Dqx8PmcT.js +1 -0
  42. package/dist/gateway/static/root/assets/{gateway-startup-retry-JGhGMhVZ.js → gateway-startup-retry-BIf0eLWX.js} +1 -1
  43. package/dist/gateway/static/root/assets/git-branch-Dh9uxTot.js +1 -0
  44. package/dist/gateway/static/root/assets/heartbeat-settings-BpDWGE1a.js +1 -0
  45. package/dist/gateway/static/root/assets/home-page-DJaqpC8-.js +1 -0
  46. package/dist/gateway/static/root/assets/{image-generation-api-BJLX7Qrh.js → image-generation-api-1m8xTVS_.js} +1 -1
  47. package/dist/gateway/static/root/assets/index-C6PmD0cK.js +74 -0
  48. package/dist/gateway/static/root/assets/index-DKy1Qn1_.css +2 -0
  49. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CBvMTFFx.js → keyboard-shortcuts-settings-Byy8mCSq.js} +1 -1
  50. package/dist/gateway/static/root/assets/local-app-workbench-page-l2AEiG2C.js +2 -0
  51. package/dist/gateway/static/root/assets/{local-apps-page-APCMNDvU.js → local-apps-page-BPo0wBgM.js} +1 -1
  52. package/dist/gateway/static/root/assets/locale-store-CRNble2Z.js +1 -0
  53. package/dist/gateway/static/root/assets/logs-page-X5FdLlXK.js +2 -0
  54. package/dist/gateway/static/root/assets/management-settings-DT6NoIjm.js +1 -0
  55. package/dist/gateway/static/root/assets/{markdown-view-BwjpJVPs.js → markdown-view-AglreSOj.js} +1 -1
  56. package/dist/gateway/static/root/assets/{media-plugins-C10byeaa.js → media-plugins-Bzka9qXu.js} +1 -1
  57. package/dist/gateway/static/root/assets/message-circle-Badhj-4D.js +1 -0
  58. package/dist/gateway/static/root/assets/message-square-fVE7Ghj1.js +1 -0
  59. package/dist/gateway/static/root/assets/{messages-D0V_bgRP.js → messages-DH_HCgmw.js} +3 -3
  60. package/dist/gateway/static/root/assets/note-detail-panel-BUJPoaGZ.js +5 -0
  61. package/dist/gateway/static/root/assets/notes-page-BwFpWRuo.js +8 -0
  62. package/dist/gateway/static/root/assets/{page-tabs-qQ36zncF.js → page-tabs-Ys0p65Lt.js} +1 -1
  63. package/dist/gateway/static/root/assets/popover-select-Dz_Qis2R.js +1 -0
  64. package/dist/gateway/static/root/assets/{preview-open-alternatives-BiAJvvCo.js → preview-open-alternatives-iknB5xEp.js} +1 -1
  65. package/dist/gateway/static/root/assets/{proactive-card-CcNBqHoH.js → proactive-card-BPZDgNNR.js} +1 -1
  66. package/dist/gateway/static/root/assets/{proactive-page-C3K61jve.js → proactive-page-CxdZR-p2.js} +1 -1
  67. package/dist/gateway/static/root/assets/{product-open-page-CunnDP4w.js → product-open-page-W1o3f-kz.js} +1 -1
  68. package/dist/gateway/static/root/assets/project-detail-page-BU1RKAcy.js +1 -0
  69. package/dist/gateway/static/root/assets/projects-page-z0X0tL8G.js +1 -0
  70. package/dist/gateway/static/root/assets/{registry-api-0JSegbNl.js → registry-api-DmYFpjsH.js} +1 -1
  71. package/dist/gateway/static/root/assets/remote-access-hub-NNTut2I8.js +1 -0
  72. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-bu_mwBTr.js → runtime-tools-settings-panel-DP1XyYO8.js} +2 -2
  73. package/dist/gateway/static/root/assets/{schema-form-BE0sgZyz.js → schema-form-BMYKdzsH.js} +1 -1
  74. package/dist/gateway/static/root/assets/sessions-page-B6SsHlz5.js +1 -0
  75. package/dist/gateway/static/root/assets/settings-advanced-gate-BQu8bAcN.js +1 -0
  76. package/dist/gateway/static/root/assets/{settings-form-section-CBo517lV.js → settings-form-section-2LGjz7bu.js} +1 -1
  77. package/dist/gateway/static/root/assets/{settings-page-DBPimx93.js → settings-page-7DjpC9_C.js} +1 -1
  78. package/dist/gateway/static/root/assets/setup-status-panel-Dj9jFWJt.js +1 -0
  79. package/dist/gateway/static/root/assets/{share-preview-page-DdV75VTe.js → share-preview-page-BxYdSi8c.js} +1 -1
  80. package/dist/gateway/static/root/assets/shares-settings-CMqE0KuK.js +1 -0
  81. package/dist/gateway/static/root/assets/skill-reload-api-BXqSJymN.js +1 -0
  82. package/dist/gateway/static/root/assets/{skills-page-Cn_-nvRo.js → skills-page-DNEScMZH.js} +1 -1
  83. package/dist/gateway/static/root/assets/skills-page.utils-q88l65YU.js +1 -0
  84. package/dist/gateway/static/root/assets/system-settings-panel-8NIssGKj.js +1 -0
  85. package/dist/gateway/static/root/assets/task-detail-page-L6dp9v2y.js +1 -0
  86. package/dist/gateway/static/root/assets/{theme-store-1wryLgBQ.js → theme-store-BXZG3S25.js} +1 -1
  87. package/dist/gateway/static/root/assets/tunnel-api-CWsRPM84.js +1 -0
  88. package/dist/gateway/static/root/assets/{use-autosave-N_lm4FdD.js → use-autosave-BwQuoTQU.js} +1 -1
  89. package/dist/gateway/static/root/assets/user-model-page-D4BucMrZ.js +2 -0
  90. package/dist/gateway/static/root/assets/{voice-api-key-field-DMsyVfri.js → voice-api-key-field-Bd03Ic0s.js} +1 -1
  91. package/dist/gateway/static/root/assets/{voice-config-api-QWVmiAp3.js → voice-config-api-gggUp3u9.js} +1 -1
  92. package/dist/gateway/static/root/assets/{work-discovery-overlay-BC0vAxp1.js → work-discovery-overlay-DF8PR_pK.js} +1 -1
  93. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Cz9jQIlP.js → workflow-run-setup-panel-BiAAWlir.js} +2 -2
  94. package/dist/gateway/static/root/assets/workflows-page-DryKUMfA.js +6 -0
  95. package/dist/gateway/static/root/index.html +15 -11
  96. package/dist/package.js +1 -1
  97. package/dist/packages/gateway-contract/src/device-pairing.js +2 -1
  98. package/dist/packages/gateway-contract/src/session-identity.js +37 -0
  99. package/dist/src/agent/memory/compaction-chunks.d.ts +18 -0
  100. package/dist/src/agent/memory/compaction-chunks.js +53 -0
  101. package/dist/src/agent/memory/compaction-request.d.ts +12 -0
  102. package/dist/src/agent/memory/compaction-request.js +72 -0
  103. package/dist/src/agent/memory/compaction.d.ts +3 -0
  104. package/dist/src/agent/memory/compaction.js +166 -118
  105. package/dist/src/agent/service.js +1 -0
  106. package/dist/src/browser/native-messaging-host.js +3 -1
  107. package/dist/src/cli/bin.js +2 -2
  108. package/dist/src/cli/commands/agent.js +2 -2
  109. package/dist/src/cli/commands/auth.js +1 -1
  110. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  111. package/dist/src/cli/commands/extension-dev.js +1 -1
  112. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  113. package/dist/src/cli/commands/extension.js +1 -1
  114. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  115. package/dist/src/cli/commands/gateway-ssh-tunnel.js +1 -1
  116. package/dist/src/cli/commands/models.js +2 -2
  117. package/dist/src/cli/commands/onboard.js +1 -1
  118. package/dist/src/cli/commands/platform.js +1 -1
  119. package/dist/src/cli/commands/profile.js +1 -1
  120. package/dist/src/cli/commands/tunnel.js +6 -1
  121. package/dist/src/cli/commands/update.js +1 -1
  122. package/dist/src/cli/extension-cli-register.js +1 -1
  123. package/dist/src/config/index.js +1 -1
  124. package/dist/src/gateway/heartbeat/service.js +1 -1
  125. package/dist/src/gateway/hono/app.js +1 -0
  126. package/dist/src/gateway/hono/middleware/auth.d.ts +1 -2
  127. package/dist/src/gateway/hono/middleware/auth.js +49 -31
  128. package/dist/src/gateway/hono/middleware/strict-rate-limit.js +11 -15
  129. package/dist/src/gateway/hono/routes/browser-session.d.ts +3 -0
  130. package/dist/src/gateway/hono/routes/browser-session.js +43 -0
  131. package/dist/src/gateway/hono/routes/devices.js +61 -96
  132. package/dist/src/gateway/hono/routes/exposure.js +3 -7
  133. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  134. package/dist/src/gateway/hono/routes/models.js +60 -1
  135. package/dist/src/gateway/hono/routes/notes.js +3 -7
  136. package/dist/src/gateway/hono/routes/sessions.js +11 -0
  137. package/dist/src/gateway/hono/routes/shares.js +8 -20
  138. package/dist/src/gateway/hono/routes/site-shares.js +4 -8
  139. package/dist/src/gateway/hono/routes/tunnel.js +13 -13
  140. package/dist/src/gateway/image-generation-setup.d.ts +17 -0
  141. package/dist/src/gateway/image-generation-setup.js +30 -21
  142. package/dist/src/gateway/rate-limit/buckets.d.ts +3 -0
  143. package/dist/src/gateway/rate-limit/buckets.js +10 -0
  144. package/dist/src/gateway/run-loop.js +1 -1
  145. package/dist/src/gateway/runtime-config.js +2 -0
  146. package/dist/src/gateway/security/browser-session.d.ts +5 -0
  147. package/dist/src/gateway/security/browser-session.js +45 -0
  148. package/dist/src/gateway/security/gateway-principal.d.ts +1 -0
  149. package/dist/src/gateway/server.js +1 -1
  150. package/dist/src/gateway/service.d.ts +1 -0
  151. package/dist/src/gateway/service.js +11 -1
  152. package/dist/src/heartbeat/index.js +1 -1
  153. package/dist/src/infra/rate-limit/keyed-store.d.ts +3 -0
  154. package/dist/src/infra/rate-limit/keyed-store.js +9 -2
  155. package/dist/src/proactive/policy/service.d.ts +1 -1
  156. package/dist/src/realtime/runtime.d.ts +2 -1
  157. package/dist/src/realtime/runtime.js +9 -3
  158. package/dist/src/realtime/tickets.d.ts +1 -0
  159. package/dist/src/realtime/tickets.js +3 -0
  160. package/dist/src/session/store.d.ts +2 -0
  161. package/dist/src/session/store.js +17 -2
  162. package/dist/src/session/types.d.ts +2 -1
  163. package/dist/src/storage/sqlite/browser-session-repository.d.ts +17 -0
  164. package/dist/src/storage/sqlite/browser-session-repository.js +54 -0
  165. package/dist/src/storage/sqlite/device-pairing-approval.js +2 -1
  166. package/dist/src/storage/sqlite/device-pairing-repository.d.ts +4 -10
  167. package/dist/src/storage/sqlite/device-pairing-repository.js +10 -62
  168. package/dist/src/storage/sqlite/index.d.ts +1 -1
  169. package/dist/src/storage/sqlite/index.js +2 -2
  170. package/dist/src/storage/sqlite/migrations/164_browser_sessions.sql +8 -0
  171. package/dist/src/storage/sqlite/migrations/165_device_pairing_target.sql +40 -0
  172. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  173. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  174. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  175. package/dist/src/storage/sqlite/schema.js +1 -1
  176. package/dist/src/storage/sqlite/session-identity-sql.d.ts +2 -0
  177. package/dist/src/storage/sqlite/session-identity-sql.js +18 -0
  178. package/dist/src/storage/sqlite/session-repository.js +26 -22
  179. package/dist/src/tunnel/auth-policy.d.ts +3 -0
  180. package/dist/src/tunnel/auth-policy.js +8 -0
  181. package/dist/src/tunnel/broker-client.d.ts +5 -15
  182. package/dist/src/tunnel/broker-client.js +37 -49
  183. package/dist/src/tunnel/frpc-binary.d.ts +8 -6
  184. package/dist/src/tunnel/frpc-binary.js +76 -88
  185. package/dist/src/tunnel/frpc-config.d.ts +2 -1
  186. package/dist/src/tunnel/frpc-config.js +29 -12
  187. package/dist/src/tunnel/frpc-release.d.ts +27 -0
  188. package/dist/src/tunnel/frpc-release.js +30 -0
  189. package/dist/src/tunnel/gateway-lifecycle.js +8 -2
  190. package/dist/src/tunnel/index.js +2 -1
  191. package/dist/src/tunnel/registration-proof.d.ts +19 -0
  192. package/dist/src/tunnel/registration-proof.js +37 -0
  193. package/dist/src/tunnel/tunnel-persist.js +3 -1
  194. package/dist/src/tunnel/tunnel-service.d.ts +1 -0
  195. package/dist/src/tunnel/tunnel-service.js +35 -8
  196. package/dist/src/tunnel/tunnel-state.js +11 -5
  197. package/dist/src/tunnel/tunnel-types.d.ts +2 -0
  198. package/dist/src/tunnel/well-known.js +5 -1
  199. package/dist/src/user-context/config.js +2 -2
  200. package/dist/src/utils/logger/redact.js +4 -0
  201. package/dist/src/voice/realtime/runtime.d.ts +1 -0
  202. package/dist/src/voice/realtime/runtime.js +17 -1
  203. package/dist/src/voice/realtime/runtime.types.d.ts +1 -0
  204. package/dist/src/workflows/service/workflow-run-service.js +2 -0
  205. package/dist/src/workflows/service/workflow-session-bridge.d.ts +1 -0
  206. package/dist/src/workflows/service/workflow-session-bridge.js +1 -0
  207. package/package.json +4 -4
  208. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CE3ygr3l.js +0 -1
  209. package/dist/gateway/static/root/assets/agents-DzG2qw-c.js +0 -1
  210. package/dist/gateway/static/root/assets/apps-page-B4lX6yoT.js +0 -1
  211. package/dist/gateway/static/root/assets/automations-workspace-BiNBewg0.js +0 -6
  212. package/dist/gateway/static/root/assets/browser-settings-page-Dgdt5uVL.js +0 -8
  213. package/dist/gateway/static/root/assets/capabilities-settings-panel-BpDW-R9f.js +0 -7
  214. package/dist/gateway/static/root/assets/channels-settings-DU4EQnR0.js +0 -1
  215. package/dist/gateway/static/root/assets/connectors-page-CfJqy284.js +0 -2
  216. package/dist/gateway/static/root/assets/cron-expression-BNwbnrEb.js +0 -2
  217. package/dist/gateway/static/root/assets/date-picker-DKyirU4K.js +0 -1
  218. package/dist/gateway/static/root/assets/extension-settings-page-B1dds2bP.js +0 -1
  219. package/dist/gateway/static/root/assets/gateway-settings-pp9jN0wl.js +0 -1
  220. package/dist/gateway/static/root/assets/heartbeat-settings-B8_zTyev.js +0 -1
  221. package/dist/gateway/static/root/assets/home-page-g1KdAdLb.js +0 -1
  222. package/dist/gateway/static/root/assets/index-1zRt56Zt.css +0 -2
  223. package/dist/gateway/static/root/assets/index-OMnem2nr.js +0 -74
  224. package/dist/gateway/static/root/assets/local-app-workbench-page-bj75v2ZE.js +0 -2
  225. package/dist/gateway/static/root/assets/locale-store-BThkG0W5.js +0 -1
  226. package/dist/gateway/static/root/assets/logs-page-BX7n39zV.js +0 -2
  227. package/dist/gateway/static/root/assets/management-settings-CM62j8ZX.js +0 -1
  228. package/dist/gateway/static/root/assets/mobile-pairing-wizard-BCWfwVx3.js +0 -1
  229. package/dist/gateway/static/root/assets/note-detail-panel-koOqb0gX.js +0 -5
  230. package/dist/gateway/static/root/assets/notes-page-BH54rY3B.js +0 -8
  231. package/dist/gateway/static/root/assets/popover-select-CKBYnT3c.js +0 -1
  232. package/dist/gateway/static/root/assets/project-detail-page-SL2g8MZY.js +0 -1
  233. package/dist/gateway/static/root/assets/projects-page-BtxazT5J.js +0 -1
  234. package/dist/gateway/static/root/assets/remote-access-hub-BSb7b67A.js +0 -1
  235. package/dist/gateway/static/root/assets/sessions-page-ljcS2KVz.js +0 -1
  236. package/dist/gateway/static/root/assets/settings-advanced-gate-CR9Y9LQm.js +0 -1
  237. package/dist/gateway/static/root/assets/setup-status-panel-J3AnooPW.js +0 -1
  238. package/dist/gateway/static/root/assets/shares-settings-AAm4Iwcp.js +0 -1
  239. package/dist/gateway/static/root/assets/skill-reload-api-pRCjP5sm.js +0 -1
  240. package/dist/gateway/static/root/assets/skills-page.utils-CfVAc_lu.js +0 -1
  241. package/dist/gateway/static/root/assets/system-settings-panel-B-pzalp-.js +0 -1
  242. package/dist/gateway/static/root/assets/task-detail-page-CmrLy3PO.js +0 -1
  243. package/dist/gateway/static/root/assets/tunnel-api-Cgpnm2fL.js +0 -1
  244. package/dist/gateway/static/root/assets/user-model-page-u3QLDX6L.js +0 -2
  245. package/dist/gateway/static/root/assets/workflows-page-DA6OOK6X.js +0 -6
@@ -5655,6 +5655,7 @@ class RealtimeClient {
5655
5655
  }
5656
5656
  }
5657
5657
 
5658
+ _enum(["mobile", "browser"]);
5658
5659
  const devicePairingKeySchema = strictObject({
5659
5660
  kty: literal("EC"),
5660
5661
  crv: literal("P-256"),
@@ -5976,6 +5977,7 @@ async function clearBrowserOutboxes() {
5976
5977
  }
5977
5978
 
5978
5979
  const PROFILE_KEY = "xopc.browser.profile";
5980
+ const PENDING_PAIRING_LINK_KEY = "xopc.browser.pending-pairing-link";
5979
5981
  const AUTO_CONNECT_KEY = "xopc.browser.auto-connect";
5980
5982
  const KEY_DATABASE = "xopc-browser-identity";
5981
5983
  const KEY_STORE = "identity";
@@ -6047,18 +6049,34 @@ function randomNonce(bytes = 24) {
6047
6049
  function createRefreshToken() {
6048
6050
  return `xopc_rt_${crypto.randomUUID()}_${randomNonce(32)}`;
6049
6051
  }
6050
- function parsePairingLink(value) {
6052
+ function parseBrowserPairingLink(value) {
6051
6053
  const url = new URL(value.trim());
6054
+ if (url.protocol !== "https:" || url.hostname !== "link.xopc.ai" || url.pathname !== "/connect") {
6055
+ throw new Error("Pairing link is not from xopc");
6056
+ }
6052
6057
  const encoded = new URLSearchParams(url.hash.slice(1)).get("p");
6053
6058
  if (!encoded) throw new Error("Pairing link is invalid");
6054
6059
  const payload = decodeJson(encoded);
6055
- if (payload.version !== 3 || !payload.gatewayId || !payload.pairingToken || !payload.gatewayPublicKey) {
6060
+ if (payload.version !== 3 || payload.targetKind !== "browser" || !payload.gatewayId || !payload.pairingToken || !payload.gatewayPublicKey || !Array.isArray(payload.routes)) {
6056
6061
  throw new Error("Pairing link version is not supported");
6057
6062
  }
6058
6063
  if (payload.expiresAt <= Date.now()) throw new Error("Pairing link has expired");
6059
6064
  if (!payload.routes.length) throw new Error("Pairing link has no Gateway route");
6065
+ for (const route of payload.routes) {
6066
+ const routeUrl = new URL(route.url);
6067
+ if (!route.id || !["http:", "https:"].includes(routeUrl.protocol)) {
6068
+ throw new Error("Pairing link has an invalid Gateway route");
6069
+ }
6070
+ }
6060
6071
  return payload;
6061
6072
  }
6073
+ async function takePendingPairingLink() {
6074
+ const stored = await chrome.storage.session.get(PENDING_PAIRING_LINK_KEY);
6075
+ const link = stored[PENDING_PAIRING_LINK_KEY];
6076
+ if (typeof link !== "string") return void 0;
6077
+ await chrome.storage.session.remove(PENDING_PAIRING_LINK_KEY);
6078
+ return link;
6079
+ }
6062
6080
  function openIdentityDatabase() {
6063
6081
  return new Promise((resolve, reject) => {
6064
6082
  const request = indexedDB.open(KEY_DATABASE, 1);
@@ -6143,14 +6161,27 @@ async function requestGatewayOriginPermission(origin) {
6143
6161
  throw new Error("Gateway site permission was not granted");
6144
6162
  }
6145
6163
  }
6164
+ class GatewayHttpError extends Error {
6165
+ constructor(message, status) {
6166
+ super(message);
6167
+ this.status = status;
6168
+ this.name = "GatewayHttpError";
6169
+ }
6170
+ status;
6171
+ }
6146
6172
  async function post(origin, path, body) {
6147
6173
  const response = await fetch(`${origin}${path}`, {
6148
6174
  method: "POST",
6149
6175
  headers: { "Content-Type": "application/json" },
6150
6176
  body: JSON.stringify(body)
6151
6177
  });
6152
- const json = await response.json();
6153
- if (!response.ok) throw new Error(json.error?.code ?? json.error?.message ?? `Gateway returned ${response.status}`);
6178
+ const json = await response.json().catch(() => ({}));
6179
+ if (!response.ok) {
6180
+ throw new GatewayHttpError(
6181
+ json.error?.code ?? json.error?.message ?? `Gateway returned ${response.status}`,
6182
+ response.status
6183
+ );
6184
+ }
6154
6185
  return json;
6155
6186
  }
6156
6187
  async function signedPairingRequest(pair, payload, origin, requestId, action, completion) {
@@ -6186,7 +6217,7 @@ async function signedPairingRequest(pair, payload, origin, requestId, action, co
6186
6217
  }
6187
6218
  return decoded;
6188
6219
  }
6189
- async function refreshAccessToken(gatewayUrl, refreshToken, pair) {
6220
+ async function refreshAccessToken(gatewayUrl, refreshToken, pair, gateway) {
6190
6221
  const nextRefreshToken = createRefreshToken();
6191
6222
  const requestId = crypto.randomUUID();
6192
6223
  const timestamp = Date.now();
@@ -6207,22 +6238,42 @@ ${nextRefreshToken}`;
6207
6238
  nonce,
6208
6239
  signature
6209
6240
  });
6210
- if (!response.payload?.accessToken || !response.payload.accessTokenExpiresAt || response.payload.refreshToken !== nextRefreshToken) {
6241
+ if (typeof response.signedPayload !== "string" || typeof response.signature !== "string" || !await verifyGateway(gateway.gatewayPublicKey, response.signedPayload, response.signature)) throw new Error("Gateway identity could not be verified");
6242
+ const responseProof = decodeJson(response.signedPayload);
6243
+ if (responseProof.purpose !== "device-refresh-v3" || responseProof.gatewayId !== gateway.gatewayId || responseProof.requestId !== requestId || responseProof.nonce !== nonce || !(responseProof.expiresAt > Date.now()) || responseProof.expiresAt > Date.now() + 6e4) throw new Error("Gateway refresh response does not match this request");
6244
+ const payload = responseProof.tokens;
6245
+ if (!payload?.accessToken || !payload.accessTokenExpiresAt || payload.refreshToken !== nextRefreshToken) {
6211
6246
  throw new Error("Gateway returned invalid browser credentials");
6212
6247
  }
6213
- return response.payload;
6248
+ return payload;
6214
6249
  }
6215
6250
  function wait(milliseconds) {
6216
6251
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
6217
6252
  }
6218
6253
  async function pairGateway(link, onApproval) {
6219
- const payload = parsePairingLink(link);
6220
- const origin = new URL(payload.routes[0].url).origin;
6221
- await requestGatewayOriginPermission(origin);
6254
+ const payload = parseBrowserPairingLink(link);
6222
6255
  const pair = await getOrCreateKeyPair();
6223
6256
  const requestId = crypto.randomUUID();
6224
6257
  const initialRefreshToken = createRefreshToken();
6225
- let result = await signedPairingRequest(pair, payload, origin, requestId, "request");
6258
+ let origin;
6259
+ let result;
6260
+ let lastRouteError;
6261
+ for (const candidate of [...new Set(payload.routes.map((route) => new URL(route.url).origin))]) {
6262
+ await requestGatewayOriginPermission(candidate);
6263
+ try {
6264
+ result = await signedPairingRequest(pair, payload, candidate, requestId, "request");
6265
+ origin = candidate;
6266
+ break;
6267
+ } catch (cause) {
6268
+ if (cause instanceof GatewayHttpError && cause.status < 500 && ![404, 408, 425, 429].includes(cause.status)) {
6269
+ throw cause;
6270
+ }
6271
+ lastRouteError = cause;
6272
+ }
6273
+ }
6274
+ if (!origin || !result) {
6275
+ throw lastRouteError instanceof Error ? lastRouteError : new Error("No Gateway route could be reached");
6276
+ }
6226
6277
  if (result.request.status === "pending") onApproval(result.request.confirmationCode);
6227
6278
  while (result.request.status === "pending") {
6228
6279
  await wait(1500);
@@ -6238,7 +6289,7 @@ async function pairGateway(link, onApproval) {
6238
6289
  });
6239
6290
  }
6240
6291
  if (!result.request.deviceId) throw new Error("Gateway did not register the browser");
6241
- const tokens = await refreshAccessToken(origin, initialRefreshToken, pair);
6292
+ const tokens = await refreshAccessToken(origin, initialRefreshToken, pair, payload);
6242
6293
  const profile = {
6243
6294
  gatewayId: payload.gatewayId,
6244
6295
  gatewayName: result.gateway.name,
@@ -6263,7 +6314,7 @@ async function getAccessProfile() {
6263
6314
  if (profile.accessTokenExpiresAt > Date.now() + 3e4) return profile;
6264
6315
  if (refreshTask) return refreshTask;
6265
6316
  refreshTask = (async () => {
6266
- const tokens = await refreshAccessToken(profile.gatewayUrl, profile.refreshToken, await getOrCreateKeyPair());
6317
+ const tokens = await refreshAccessToken(profile.gatewayUrl, profile.refreshToken, await getOrCreateKeyPair(), profile);
6267
6318
  const next = { ...profile, ...tokens };
6268
6319
  await chrome.storage.local.set({ [PROFILE_KEY]: next });
6269
6320
  return next;
@@ -6352,4 +6403,4 @@ async function revokeAndForgetProfile() {
6352
6403
  }
6353
6404
  }
6354
6405
 
6355
- export { ENDPOINT_PROTOCOL_VERSION as E, PENDING_CONTEXT_KEY as P, RealtimeClient as R, TAB_BINDING_PREFIX as T, activeTabId as a, captureTabWithPermission as b, canonicalJson as c, createBrowserEndpointHello as d, currentTabDescriptor as e, deleteBrowserOutbox as f, discoverLocalGateway as g, endpointToolContentSchema as h, gatewayFetch as i, getAccessProfile as j, readProfile as k, registerBrowserEndpoint as l, revokeAndForgetProfile as m, runWithTabSiteAccess as n, pairGateway as p, readBrowserOutbox as r, setAutoConnectEnabled as s, writeBrowserOutbox as w };
6406
+ export { ENDPOINT_PROTOCOL_VERSION as E, PENDING_CONTEXT_KEY as P, RealtimeClient as R, TAB_BINDING_PREFIX as T, PENDING_PAIRING_LINK_KEY as a, activeTabId as b, canonicalJson as c, captureTabWithPermission as d, createBrowserEndpointHello as e, currentTabDescriptor as f, deleteBrowserOutbox as g, discoverLocalGateway as h, endpointToolContentSchema as i, gatewayFetch as j, getAccessProfile as k, parseBrowserPairingLink as l, readProfile as m, registerBrowserEndpoint as n, revokeAndForgetProfile as o, pairGateway as p, runWithTabSiteAccess as q, readBrowserOutbox as r, setAutoConnectEnabled as s, takePendingPairingLink as t, writeBrowserOutbox as w };
@@ -1,4 +1,4 @@
1
- import { h as endpointToolContentSchema, E as ENDPOINT_PROTOCOL_VERSION, c as canonicalJson, T as TAB_BINDING_PREFIX, b as captureTabWithPermission, P as PENDING_CONTEXT_KEY, k as readProfile, l as registerBrowserEndpoint, j as getAccessProfile, R as RealtimeClient, d as createBrowserEndpointHello, i as gatewayFetch } from './assets/auth-cwEj8rFb.js';
1
+ import { i as endpointToolContentSchema, E as ENDPOINT_PROTOCOL_VERSION, c as canonicalJson, T as TAB_BINDING_PREFIX, d as captureTabWithPermission, P as PENDING_CONTEXT_KEY, l as parseBrowserPairingLink, a as PENDING_PAIRING_LINK_KEY, m as readProfile, n as registerBrowserEndpoint, k as getAccessProfile, R as RealtimeClient, e as createBrowserEndpointHello, j as gatewayFetch } from './assets/auth-C1QI-uMG.js';
2
2
 
3
3
  const BROWSER_EXTENSION_PROTOCOL_VERSION = 4;
4
4
  const BROWSER_CONTROL_ENDPOINT_TOOL_NAME = "browser.control";
@@ -1253,7 +1253,23 @@ function connectWithLogging() {
1253
1253
  if (generation !== connectionGeneration && !realtime) connectWithLogging();
1254
1254
  });
1255
1255
  }
1256
- chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
1256
+ async function stagePairingInvite(message, sender) {
1257
+ if (typeof message.pairingLink !== "string" || !sender.url || !sender.tab?.id) {
1258
+ throw new Error("Pairing handoff is missing its source tab");
1259
+ }
1260
+ const source = new URL(sender.url);
1261
+ const invitation = new URL(message.pairingLink);
1262
+ if (source.href !== invitation.href || source.protocol !== "https:" || source.hostname !== "link.xopc.ai" || source.pathname !== "/connect") {
1263
+ throw new Error("Pairing handoff source is not trusted");
1264
+ }
1265
+ parseBrowserPairingLink(invitation.href);
1266
+ const tasks = [
1267
+ chrome.storage.session.set({ [PENDING_PAIRING_LINK_KEY]: invitation.href })
1268
+ ];
1269
+ if (message.open) tasks.push(chrome.sidePanel.open({ tabId: sender.tab.id }));
1270
+ await Promise.all(tasks);
1271
+ }
1272
+ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1257
1273
  if (message.type === "browser/get-status") {
1258
1274
  sendResponse({ connected: Boolean(endpointClaim), transport: "gateway-realtime", error: lastConnectionError });
1259
1275
  } else if (message.type === "browser/get-endpoint-claim") {
@@ -1262,6 +1278,11 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
1262
1278
  disconnect();
1263
1279
  connectWithLogging();
1264
1280
  sendResponse({ ok: true });
1281
+ } else if (message.type === "browser/stage-pairing-invite") {
1282
+ void stagePairingInvite(message, sender).then(() => sendResponse({ ok: true })).catch((cause) => sendResponse({
1283
+ ok: false,
1284
+ error: cause instanceof Error ? cause.message : String(cause)
1285
+ }));
1265
1286
  } else {
1266
1287
  sendResponse({ ok: false, error: `Unknown message: ${message.type}` });
1267
1288
  }
@@ -0,0 +1,51 @@
1
+ const messageType = "browser/stage-pairing-invite";
2
+ function hasPairingPayload() {
3
+ return new URLSearchParams(location.hash.slice(1)).has("p");
4
+ }
5
+ async function stage(open) {
6
+ return chrome.runtime.sendMessage({
7
+ type: messageType,
8
+ pairingLink: location.href,
9
+ open
10
+ });
11
+ }
12
+ function mountOpenButton() {
13
+ if (document.getElementById("xopc-browser-pairing-handoff")) return;
14
+ const host = document.createElement("div");
15
+ host.id = "xopc-browser-pairing-handoff";
16
+ const root = host.attachShadow({ mode: "closed" });
17
+ const button = document.createElement("button");
18
+ button.type = "button";
19
+ button.textContent = "Open xopc extension";
20
+ button.style.cssText = [
21
+ "position:fixed",
22
+ "right:24px",
23
+ "bottom:24px",
24
+ "z-index:2147483647",
25
+ "border:0",
26
+ "border-radius:10px",
27
+ "padding:12px 18px",
28
+ "background:#2563eb",
29
+ "color:#fff",
30
+ "font:600 14px/20px system-ui,sans-serif",
31
+ "box-shadow:0 8px 24px rgba(15,23,42,.24)",
32
+ "cursor:pointer"
33
+ ].join(";");
34
+ button.addEventListener("click", () => {
35
+ button.disabled = true;
36
+ button.textContent = "Opening…";
37
+ void stage(true).then((result) => {
38
+ button.textContent = result.ok ? "Opened — approve in Gateway" : result.error || "Could not open xopc";
39
+ button.disabled = false;
40
+ }).catch(() => {
41
+ button.textContent = "Could not open xopc";
42
+ button.disabled = false;
43
+ });
44
+ });
45
+ root.append(button);
46
+ document.documentElement.append(host);
47
+ }
48
+ if (hasPairingPayload()) {
49
+ void stage(false).catch(() => void 0);
50
+ mountOpenButton();
51
+ }
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>xopc</title>
7
7
  <script type="module" crossorigin src="./sidepanel.js"></script>
8
- <link rel="modulepreload" crossorigin href="./assets/auth-cwEj8rFb.js">
8
+ <link rel="modulepreload" crossorigin href="./assets/auth-C1QI-uMG.js">
9
9
  <link rel="stylesheet" crossorigin href="./assets/sidepanel-C86O7q5Y.css">
10
10
  </head>
11
11
  <body>
@@ -1,4 +1,4 @@
1
- import { R as RealtimeClient, i as gatewayFetch, a as activeTabId, r as readBrowserOutbox, w as writeBrowserOutbox, f as deleteBrowserOutbox, e as currentTabDescriptor, T as TAB_BINDING_PREFIX, j as getAccessProfile, n as runWithTabSiteAccess, P as PENDING_CONTEXT_KEY, b as captureTabWithPermission, k as readProfile, g as discoverLocalGateway, p as pairGateway, s as setAutoConnectEnabled, m as revokeAndForgetProfile } from './assets/auth-cwEj8rFb.js';
1
+ import { R as RealtimeClient, j as gatewayFetch, b as activeTabId, r as readBrowserOutbox, w as writeBrowserOutbox, g as deleteBrowserOutbox, f as currentTabDescriptor, T as TAB_BINDING_PREFIX, k as getAccessProfile, q as runWithTabSiteAccess, P as PENDING_CONTEXT_KEY, d as captureTabWithPermission, p as pairGateway, s as setAutoConnectEnabled, t as takePendingPairingLink, m as readProfile, h as discoverLocalGateway, a as PENDING_PAIRING_LINK_KEY, o as revokeAndForgetProfile } from './assets/auth-C1QI-uMG.js';
2
2
 
3
3
  true &&(function polyfill() {
4
4
  const relList = document.createElement("link").relList;
@@ -27552,10 +27552,35 @@ function SidePanelApp() {
27552
27552
  const [error, setError] = reactExports.useState("");
27553
27553
  const [localPairingLink, setLocalPairingLink] = reactExports.useState("");
27554
27554
  const initializationStarted = reactExports.useRef(false);
27555
+ const pairingStarted = reactExports.useRef(false);
27556
+ const connect = reactExports.useCallback(async (link) => {
27557
+ if (pairingStarted.current) return;
27558
+ pairingStarted.current = true;
27559
+ setState("pairing");
27560
+ setError("");
27561
+ setPairingLink(link);
27562
+ try {
27563
+ const paired = await pairGateway(link, setConfirmationCode);
27564
+ await setAutoConnectEnabled(true);
27565
+ await reconnectBrowserBridge();
27566
+ setProfile(paired);
27567
+ setState("online");
27568
+ } catch (cause) {
27569
+ setError(cause instanceof Error ? cause.message : String(cause));
27570
+ setState("unpaired");
27571
+ } finally {
27572
+ pairingStarted.current = false;
27573
+ }
27574
+ }, []);
27555
27575
  reactExports.useEffect(() => {
27556
27576
  if (initializationStarted.current) return;
27557
27577
  initializationStarted.current = true;
27558
27578
  void (async () => {
27579
+ const handedOff = await takePendingPairingLink();
27580
+ if (handedOff) {
27581
+ await connect(handedOff);
27582
+ return;
27583
+ }
27559
27584
  const stored = await readProfile();
27560
27585
  if (stored) {
27561
27586
  await reconnectBrowserBridge();
@@ -27569,33 +27594,20 @@ function SidePanelApp() {
27569
27594
  return;
27570
27595
  }
27571
27596
  setLocalPairingLink(local.pairingLink);
27572
- setState("pairing");
27573
- try {
27574
- const paired = await pairGateway(local.pairingLink, setConfirmationCode);
27575
- await reconnectBrowserBridge();
27576
- setProfile(paired);
27577
- setState("online");
27578
- } catch (cause) {
27579
- setError(cause instanceof Error ? cause.message : String(cause));
27580
- setState("unpaired");
27581
- }
27597
+ await connect(local.pairingLink);
27582
27598
  })();
27583
- }, []);
27599
+ }, [connect]);
27600
+ reactExports.useEffect(() => {
27601
+ const handleStorageChange = (changes, area) => {
27602
+ if (area !== "session" || !changes[PENDING_PAIRING_LINK_KEY]?.newValue) return;
27603
+ void takePendingPairingLink().then((link) => {
27604
+ if (link) void connect(link);
27605
+ });
27606
+ };
27607
+ chrome.storage.onChanged.addListener(handleStorageChange);
27608
+ return () => chrome.storage.onChanged.removeListener(handleStorageChange);
27609
+ }, [connect]);
27584
27610
  reactExports.useEffect(() => watchSidePanelTheme(profile?.gatewayUrl), [profile?.gatewayUrl]);
27585
- async function connect(link = pairingLink) {
27586
- setState("pairing");
27587
- setError("");
27588
- try {
27589
- const paired = await pairGateway(link, setConfirmationCode);
27590
- await setAutoConnectEnabled(true);
27591
- await reconnectBrowserBridge();
27592
- setProfile(paired);
27593
- setState("online");
27594
- } catch (cause) {
27595
- setError(cause instanceof Error ? cause.message : String(cause));
27596
- setState("unpaired");
27597
- }
27598
- }
27599
27611
  async function disconnect() {
27600
27612
  await revokeAndForgetProfile();
27601
27613
  setProfile(void 0);
@@ -27648,7 +27660,7 @@ function SidePanelApp() {
27648
27660
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "approval-code", children: confirmationCode })
27649
27661
  ] }) : null,
27650
27662
  error ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "error-text", children: error }) : null,
27651
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "actions", children: /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "primary", onClick: () => void connect(), disabled: !pairingLink.trim() || state === "pairing", children: state === "pairing" ? "Waiting for approval…" : "Connect" }) })
27663
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "actions", children: /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "primary", onClick: () => void connect(pairingLink), disabled: !pairingLink.trim() || state === "pairing", children: state === "pairing" ? "Waiting for approval…" : "Connect" }) })
27652
27664
  ] }) : null
27653
27665
  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChatPanel, {}),
27654
27666
  state === "online" && profile ? /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "disconnect-link", onClick: disconnect, title: `Disconnect ${profile.gatewayName}`, children: "Disconnect" }) : null
@@ -2,7 +2,7 @@
2
2
  "manifest_version": 3,
3
3
  "minimum_chrome_version": "120",
4
4
  "name": "xopc",
5
- "version": "0.0.270",
5
+ "version": "0.0.272",
6
6
  "description": "Chat with xopc and explicitly share or control the current page.",
7
7
  "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqnpr4vpLC/nmvy+wiOWk3SWlp2nEZkFijfk8ivGw7StNZgCK90nOMvwhdEtlkk3GOWDvdVnq8HxCsM3UNQ8FnGUyerpH1FJXqXuradxeHf8ZxFjiQU/mIWfnKbUuONWQORon3/pigyoXoK/VUXgg0Wbm/rbVwsS0bv+25R6m+mZgBspOLeKuoH7ivhL+48WV6POtMBsFPZweY26477EM7ukh+56Ff5ENevB8ymxBBn7qK5ZoeZd2a23U8ioX5TsHfe6fnrjitPWjIxD8G0NoKQxcaa/Mo+xs+T6UiLKxP0wjz5bm7jB5H+CXtkRJqzBWUB0h+RSLJckzZfA8BAJrRwIDAQAB",
8
8
  "permissions": [
@@ -28,6 +28,17 @@
28
28
  "service_worker": "dist/background.js",
29
29
  "type": "module"
30
30
  },
31
+ "content_scripts": [
32
+ {
33
+ "matches": [
34
+ "https://link.xopc.ai/connect*"
35
+ ],
36
+ "js": [
37
+ "dist/pairing-handoff.js"
38
+ ],
39
+ "run_at": "document_idle"
40
+ }
41
+ ],
31
42
  "side_panel": {
32
43
  "default_path": "dist/sidepanel.html"
33
44
  },
@@ -2,7 +2,7 @@
2
2
  "id": "telegram",
3
3
  "name": "Telegram Channel",
4
4
  "description": "Bundled Telegram Bot channel (private workspace sources; ships inside @xopcai/xopc dist/)",
5
- "version": "0.0.270",
5
+ "version": "0.0.272",
6
6
  "kind": "channel",
7
7
  "main": "src/index.js",
8
8
  "channels": [
@@ -1 +1 @@
1
- import{f as e}from"./locale-store-BThkG0W5.js";var t=`xopc.activity-center.v1`,n=80,r=720*60*60*1e3;function i(e){return e===`error`?`failed`:e===`warning`?`attention`:`done`}function a(){if(!(typeof window>`u`))return window.location.hash.replace(/^#/,``)||`${window.location.pathname}${window.location.search}`||void 0}function o(){try{let e=globalThis.localStorage?.getItem(t);if(!e)return[];let i=JSON.parse(e);if(!Array.isArray(i.items))return[];let a=Date.now()-r,o=i.items.filter(e=>e&&typeof e.id==`string`&&typeof e.title==`string`).filter(e=>Number.isFinite(e.updatedAt)&&e.updatedAt>=a).slice(0,n);return o.length!==i.items.length&&s(o),o}catch{return[]}}function s(e){try{globalThis.localStorage?.setItem(t,JSON.stringify({items:e}))}catch{}}function c(e){return`${e.toString(36)}-${Math.random().toString(36).slice(2,8)}`}var l=e(e=>({items:o(),add:t=>e(e=>{let r=t.title.trim();if(!r)return e;let o=Date.now(),l=t.tone??`info`,u=t.dedupeKey?e.items.findIndex(e=>e.dedupeKey===t.dedupeKey):-1,d=[{id:u>=0?e.items[u].id:c(o),tone:l,status:t.status??i(l),title:r,message:t.message?.trim()||void 0,source:t.source?.trim()||void 0,href:t.href??a(),dedupeKey:t.dedupeKey,createdAt:u>=0?e.items[u].createdAt:o,updatedAt:o,read:t.read??!1,occurrences:u>=0?e.items[u].occurrences+1:1},...u>=0?e.items.filter((e,t)=>t!==u):e.items].slice(0,n);return s(d),{items:d}}),markAllRead:()=>e(e=>{let t=e.items.map(e=>({...e,read:!0}));return s(t),{items:t}}),remove:t=>e(e=>{let n=e.items.filter(e=>e.id!==t);return s(n),{items:n}}),clearFinished:()=>e(e=>{let t=e.items.filter(e=>e.status!==`done`);return s(t),{items:t}}),clear:()=>{s([]),e({items:[]})}}));function u(e){l.getState().add(e)}export{u as t};
1
+ import{p as e}from"./locale-store-CRNble2Z.js";var t=`xopc.activity-center.v1`,n=80,r=720*60*60*1e3;function i(e){return e===`error`?`failed`:e===`warning`?`attention`:`done`}function a(){if(!(typeof window>`u`))return window.location.hash.replace(/^#/,``)||`${window.location.pathname}${window.location.search}`||void 0}function o(){try{let e=globalThis.localStorage?.getItem(t);if(!e)return[];let i=JSON.parse(e);if(!Array.isArray(i.items))return[];let a=Date.now()-r,o=i.items.filter(e=>e&&typeof e.id==`string`&&typeof e.title==`string`).filter(e=>Number.isFinite(e.updatedAt)&&e.updatedAt>=a).slice(0,n);return o.length!==i.items.length&&s(o),o}catch{return[]}}function s(e){try{globalThis.localStorage?.setItem(t,JSON.stringify({items:e}))}catch{}}function c(e){return`${e.toString(36)}-${Math.random().toString(36).slice(2,8)}`}var l=e(e=>({items:o(),add:t=>e(e=>{let r=t.title.trim();if(!r)return e;let o=Date.now(),l=t.tone??`info`,u=t.dedupeKey?e.items.findIndex(e=>e.dedupeKey===t.dedupeKey):-1,d=[{id:u>=0?e.items[u].id:c(o),tone:l,status:t.status??i(l),title:r,message:t.message?.trim()||void 0,source:t.source?.trim()||void 0,href:t.href??a(),dedupeKey:t.dedupeKey,createdAt:u>=0?e.items[u].createdAt:o,updatedAt:o,read:t.read??!1,occurrences:u>=0?e.items[u].occurrences+1:1},...u>=0?e.items.filter((e,t)=>t!==u):e.items].slice(0,n);return s(d),{items:d}}),markAllRead:()=>e(e=>{let t=e.items.map(e=>({...e,read:!0}));return s(t),{items:t}}),remove:t=>e(e=>{let n=e.items.filter(e=>e.id!==t);return s(n),{items:n}}),clearFinished:()=>e(e=>{let t=e.items.filter(e=>e.status!==`done`);return s(t),{items:t}}),clear:()=>{s([]),e({items:[]})}}));function u(e){l.getState().add(e)}export{u as t};