@xopcai/xopc 0.0.270 → 0.0.273

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 (255) hide show
  1. package/README.md +1 -5
  2. package/README.zh-CN.md +1 -5
  3. package/dist/browser-ext/dist/assets/{auth-cwEj8rFb.js → auth-DkwOUI6_.js} +132 -33
  4. package/dist/browser-ext/dist/background.js +2 -2
  5. package/dist/browser-ext/dist/sidepanel.html +1 -1
  6. package/dist/browser-ext/dist/sidepanel.js +46 -32
  7. package/dist/browser-ext/manifest.json +1 -1
  8. package/dist/extensions/telegram/xopc.extension.json +1 -1
  9. package/dist/gateway/static/root/assets/{activity-store-D_0FmdRj.js → activity-store-cF7IX2RP.js} +1 -1
  10. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-IZvEXak_.js → agent-avatar-dicebear-BrgxX8nG.js} +1 -1
  11. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-DvhuRCLA.js +1 -0
  12. package/dist/gateway/static/root/assets/agents-C0By2FIo.js +1 -0
  13. package/dist/gateway/static/root/assets/{api-O3TTQ4qN.js → api-CYkdUpkx.js} +1 -1
  14. package/dist/gateway/static/root/assets/app-link-BiBXVEvp.js +1 -0
  15. package/dist/gateway/static/root/assets/{app-management-settings-panel-Cqqsbzri.js → app-management-settings-panel-DfoNzWIa.js} +1 -1
  16. package/dist/gateway/static/root/assets/{appearance-settings-DaJyf32s.js → appearance-settings-czbLdCqj.js} +1 -1
  17. package/dist/gateway/static/root/assets/apps-page-BSJXKWcE.js +1 -0
  18. package/dist/gateway/static/root/assets/{archive-plugin-kDPnDTJI.js → archive-plugin-D14P13mX.js} +1 -1
  19. package/dist/gateway/static/root/assets/{attachment-load-CJ3VceKS.js → attachment-load-Dok_B1Gv.js} +1 -1
  20. package/dist/gateway/static/root/assets/{automations-page-JwMtU8XB.js → automations-page-DM7ZEewI.js} +1 -1
  21. package/dist/gateway/static/root/assets/automations-workspace--1TsZf3O.js +6 -0
  22. package/dist/gateway/static/root/assets/{binary-plugins-DzyZXLBX.js → binary-plugins-CxNg6InF.js} +1 -1
  23. package/dist/gateway/static/root/assets/{block-editor-kTt3gYIJ.js → block-editor-D22VcYnC.js} +3 -3
  24. package/dist/gateway/static/root/assets/{browser-automation-inputs-BKohPYR4.js → browser-automation-inputs-6NWTLEpd.js} +1 -1
  25. package/dist/gateway/static/root/assets/{browser-automations-page-ktQfFPk-.js → browser-automations-page-BrqySdbW.js} +2 -2
  26. package/dist/gateway/static/root/assets/browser-settings-page-DOHgQer_.js +8 -0
  27. package/dist/gateway/static/root/assets/capabilities-settings-panel-Bpse_5K-.js +8 -0
  28. package/dist/gateway/static/root/assets/channels-settings-yHsY174W.js +1 -0
  29. package/dist/gateway/static/root/assets/{channels-status-swr-DrqzYmDr.js → channels-status-swr-BUZimNmp.js} +1 -1
  30. package/dist/gateway/static/root/assets/{chat-terminal-dock-CIFGGLGa.js → chat-terminal-dock-CZPBNpMI.js} +2 -2
  31. package/dist/gateway/static/root/assets/clock-3-DnrAnuyZ.js +1 -0
  32. package/dist/gateway/static/root/assets/connectors-page-B_wLKGnH.js +2 -0
  33. package/dist/gateway/static/root/assets/cron-expression-C26e13YU.js +2 -0
  34. package/dist/gateway/static/root/assets/date-picker-Da_0QyLe.js +1 -0
  35. package/dist/gateway/static/root/assets/{dependency-picker-D3vNIjRI.js → dependency-picker-D_djqzy7.js} +1 -1
  36. package/dist/gateway/static/root/assets/{desktop-pet-fQwRb_3p.js → desktop-pet-Celmbw-T.js} +1 -1
  37. package/dist/gateway/static/root/assets/{desktop-pet-settings-DfOJ-GvT.js → desktop-pet-settings-CqNNgF45.js} +1 -1
  38. package/dist/gateway/static/root/assets/device-pairing-wizard-B5_w9qlm.js +1 -0
  39. package/dist/gateway/static/root/assets/{extension-debug-page-Cn53jB5-.js → extension-debug-page-ku3kCjvH.js} +1 -1
  40. package/dist/gateway/static/root/assets/{extension-page-IDpLCxpC.js → extension-page-C7FpHwL4.js} +1 -1
  41. package/dist/gateway/static/root/assets/extension-settings-page-OMj2tU2_.js +1 -0
  42. package/dist/gateway/static/root/assets/{gateway-config-swr-B7dcmP7Q.js → gateway-config-swr-6eb1vKE1.js} +1 -1
  43. package/dist/gateway/static/root/assets/gateway-settings-CH-6vkgN.js +1 -0
  44. package/dist/gateway/static/root/assets/{gateway-startup-retry-JGhGMhVZ.js → gateway-startup-retry-DUFFCU8H.js} +1 -1
  45. package/dist/gateway/static/root/assets/git-branch-Dh9uxTot.js +1 -0
  46. package/dist/gateway/static/root/assets/heartbeat-settings-CSFzOACM.js +1 -0
  47. package/dist/gateway/static/root/assets/home-page-BJebAKB-.js +1 -0
  48. package/dist/gateway/static/root/assets/{image-generation-api-BJLX7Qrh.js → image-generation-api-C1cHRBRp.js} +1 -1
  49. package/dist/gateway/static/root/assets/index-C6OWYFtQ.js +74 -0
  50. package/dist/gateway/static/root/assets/index-DKy1Qn1_.css +2 -0
  51. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CBvMTFFx.js → keyboard-shortcuts-settings-BuvD3iv8.js} +1 -1
  52. package/dist/gateway/static/root/assets/local-app-workbench-page-CaC4-THD.js +2 -0
  53. package/dist/gateway/static/root/assets/{local-apps-page-APCMNDvU.js → local-apps-page-DdJ8zwBp.js} +1 -1
  54. package/dist/gateway/static/root/assets/locale-store-BBSCIl4I.js +1 -0
  55. package/dist/gateway/static/root/assets/logs-page-BaR2he0K.js +2 -0
  56. package/dist/gateway/static/root/assets/management-settings-r-iYWZFY.js +1 -0
  57. package/dist/gateway/static/root/assets/markdown-view-c5vtnYe8.js +201 -0
  58. package/dist/gateway/static/root/assets/{media-plugins-C10byeaa.js → media-plugins-D_a6GDY6.js} +1 -1
  59. package/dist/gateway/static/root/assets/message-circle-Badhj-4D.js +1 -0
  60. package/dist/gateway/static/root/assets/message-square-fVE7Ghj1.js +1 -0
  61. package/dist/gateway/static/root/assets/{messages-D0V_bgRP.js → messages-DjuBdDCn.js} +3 -3
  62. package/dist/gateway/static/root/assets/note-detail-panel-BV6nbgac.js +5 -0
  63. package/dist/gateway/static/root/assets/notes-page-BmLKoWwi.js +8 -0
  64. package/dist/gateway/static/root/assets/{page-tabs-qQ36zncF.js → page-tabs-C7Le9bSI.js} +1 -1
  65. package/dist/gateway/static/root/assets/popover-select-Dz_Qis2R.js +1 -0
  66. package/dist/gateway/static/root/assets/{preview-open-alternatives-BiAJvvCo.js → preview-open-alternatives-B2pOxJBK.js} +1 -1
  67. package/dist/gateway/static/root/assets/{proactive-card-CcNBqHoH.js → proactive-card-BlQ1vCtV.js} +1 -1
  68. package/dist/gateway/static/root/assets/{proactive-page-C3K61jve.js → proactive-page-CghKTfYa.js} +1 -1
  69. package/dist/gateway/static/root/assets/{product-open-page-CunnDP4w.js → product-open-page-DpjiHgwu.js} +1 -1
  70. package/dist/gateway/static/root/assets/project-detail-page-CV8Lh296.js +1 -0
  71. package/dist/gateway/static/root/assets/projects-page-COweOaJP.js +1 -0
  72. package/dist/gateway/static/root/assets/{registry-api-0JSegbNl.js → registry-api-CyQ4k1Ux.js} +1 -1
  73. package/dist/gateway/static/root/assets/remote-access-hub-ChPPGVU5.js +1 -0
  74. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-bu_mwBTr.js → runtime-tools-settings-panel-Bl4ArLHf.js} +2 -2
  75. package/dist/gateway/static/root/assets/{schema-form-BE0sgZyz.js → schema-form-KQFmfWd4.js} +1 -1
  76. package/dist/gateway/static/root/assets/sessions-page-DgmHibOK.js +1 -0
  77. package/dist/gateway/static/root/assets/settings-advanced-gate-DV7kMco2.js +1 -0
  78. package/dist/gateway/static/root/assets/{settings-form-section-CBo517lV.js → settings-form-section-Dbnls9ty.js} +1 -1
  79. package/dist/gateway/static/root/assets/{settings-page-DBPimx93.js → settings-page-CDKirYRG.js} +1 -1
  80. package/dist/gateway/static/root/assets/setup-status-panel-SQmtWoOs.js +1 -0
  81. package/dist/gateway/static/root/assets/{share-preview-page-DdV75VTe.js → share-preview-page-DwgLjS1m.js} +1 -1
  82. package/dist/gateway/static/root/assets/shares-settings-Cs5bUrYw.js +1 -0
  83. package/dist/gateway/static/root/assets/skill-reload-api-DyKrjq7F.js +1 -0
  84. package/dist/gateway/static/root/assets/{skills-page-Cn_-nvRo.js → skills-page-Bd0_ED_p.js} +1 -1
  85. package/dist/gateway/static/root/assets/skills-page.utils-rA-XT-YG.js +1 -0
  86. package/dist/gateway/static/root/assets/system-settings-panel-CSkMrHLz.js +1 -0
  87. package/dist/gateway/static/root/assets/task-detail-page-CEQU-L_G.js +1 -0
  88. package/dist/gateway/static/root/assets/{theme-store-1wryLgBQ.js → theme-store-DWpIEWen.js} +1 -1
  89. package/dist/gateway/static/root/assets/tunnel-api-COJcGnEi.js +1 -0
  90. package/dist/gateway/static/root/assets/{use-autosave-N_lm4FdD.js → use-autosave-DkQAIAuB.js} +1 -1
  91. package/dist/gateway/static/root/assets/user-model-page-BQAU55lf.js +2 -0
  92. package/dist/gateway/static/root/assets/{voice-api-key-field-DMsyVfri.js → voice-api-key-field-BrqcH0P-.js} +1 -1
  93. package/dist/gateway/static/root/assets/{voice-config-api-QWVmiAp3.js → voice-config-api-BJ95Z3pT.js} +1 -1
  94. package/dist/gateway/static/root/assets/{work-discovery-overlay-BC0vAxp1.js → work-discovery-overlay-vfTWKm13.js} +1 -1
  95. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Cz9jQIlP.js → workflow-run-setup-panel-CHdr_ng9.js} +2 -2
  96. package/dist/gateway/static/root/assets/workflows-page-hwRJD7vR.js +6 -0
  97. package/dist/gateway/static/root/index.html +16 -11
  98. package/dist/package.js +1 -1
  99. package/dist/packages/gateway-contract/src/device-pairing.js +2 -1
  100. package/dist/packages/gateway-contract/src/session-identity.js +37 -0
  101. package/dist/src/agent/memory/compaction-chunks.d.ts +18 -0
  102. package/dist/src/agent/memory/compaction-chunks.js +53 -0
  103. package/dist/src/agent/memory/compaction-request.d.ts +12 -0
  104. package/dist/src/agent/memory/compaction-request.js +72 -0
  105. package/dist/src/agent/memory/compaction.d.ts +3 -0
  106. package/dist/src/agent/memory/compaction.js +166 -118
  107. package/dist/src/agent/service.js +1 -0
  108. package/dist/src/browser/native-messaging-host.js +3 -1
  109. package/dist/src/browser/providers/browser-ext-install.d.ts +6 -0
  110. package/dist/src/browser/providers/browser-ext-install.js +16 -1
  111. package/dist/src/cli/bin.js +2 -2
  112. package/dist/src/cli/commands/agent.js +2 -2
  113. package/dist/src/cli/commands/auth.js +1 -1
  114. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  115. package/dist/src/cli/commands/extension-dev.js +1 -1
  116. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  117. package/dist/src/cli/commands/extension.js +1 -1
  118. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  119. package/dist/src/cli/commands/gateway/run-foreground.js +8 -5
  120. package/dist/src/cli/commands/gateway/service.js +4 -3
  121. package/dist/src/cli/commands/gateway/token.js +28 -1
  122. package/dist/src/cli/commands/gateway-ssh-tunnel.js +1 -1
  123. package/dist/src/cli/commands/models.js +2 -2
  124. package/dist/src/cli/commands/onboard.js +1 -1
  125. package/dist/src/cli/commands/platform.js +1 -1
  126. package/dist/src/cli/commands/profile.js +1 -1
  127. package/dist/src/cli/commands/tunnel.js +6 -1
  128. package/dist/src/cli/commands/update.js +1 -1
  129. package/dist/src/cli/extension-cli-register.js +1 -1
  130. package/dist/src/config/index.js +1 -1
  131. package/dist/src/gateway/device-routes.js +4 -3
  132. package/dist/src/gateway/heartbeat/service.js +1 -1
  133. package/dist/src/gateway/hono/app.js +1 -0
  134. package/dist/src/gateway/hono/middleware/auth.d.ts +1 -2
  135. package/dist/src/gateway/hono/middleware/auth.js +49 -31
  136. package/dist/src/gateway/hono/middleware/strict-rate-limit.js +11 -15
  137. package/dist/src/gateway/hono/routes/browser-session.d.ts +3 -0
  138. package/dist/src/gateway/hono/routes/browser-session.js +43 -0
  139. package/dist/src/gateway/hono/routes/browser.js +26 -0
  140. package/dist/src/gateway/hono/routes/devices.js +61 -96
  141. package/dist/src/gateway/hono/routes/exposure.js +3 -7
  142. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  143. package/dist/src/gateway/hono/routes/models.js +60 -1
  144. package/dist/src/gateway/hono/routes/notes.js +3 -7
  145. package/dist/src/gateway/hono/routes/sessions.js +11 -0
  146. package/dist/src/gateway/hono/routes/shares.js +8 -20
  147. package/dist/src/gateway/hono/routes/site-shares.js +4 -8
  148. package/dist/src/gateway/hono/routes/tunnel.js +13 -13
  149. package/dist/src/gateway/image-generation-setup.d.ts +17 -0
  150. package/dist/src/gateway/image-generation-setup.js +30 -21
  151. package/dist/src/gateway/rate-limit/buckets.d.ts +3 -0
  152. package/dist/src/gateway/rate-limit/buckets.js +10 -0
  153. package/dist/src/gateway/run-loop.js +1 -1
  154. package/dist/src/gateway/runtime-config.js +2 -0
  155. package/dist/src/gateway/security/browser-session.d.ts +5 -0
  156. package/dist/src/gateway/security/browser-session.js +45 -0
  157. package/dist/src/gateway/security/gateway-principal.d.ts +1 -0
  158. package/dist/src/gateway/server.js +1 -1
  159. package/dist/src/gateway/service.d.ts +1 -0
  160. package/dist/src/gateway/service.js +11 -1
  161. package/dist/src/heartbeat/index.js +1 -1
  162. package/dist/src/infra/rate-limit/keyed-store.d.ts +3 -0
  163. package/dist/src/infra/rate-limit/keyed-store.js +9 -2
  164. package/dist/src/proactive/policy/service.d.ts +1 -1
  165. package/dist/src/realtime/runtime.d.ts +2 -1
  166. package/dist/src/realtime/runtime.js +9 -3
  167. package/dist/src/realtime/tickets.d.ts +1 -0
  168. package/dist/src/realtime/tickets.js +3 -0
  169. package/dist/src/session/store.d.ts +2 -0
  170. package/dist/src/session/store.js +17 -2
  171. package/dist/src/session/types.d.ts +2 -1
  172. package/dist/src/storage/sqlite/browser-session-repository.d.ts +17 -0
  173. package/dist/src/storage/sqlite/browser-session-repository.js +54 -0
  174. package/dist/src/storage/sqlite/device-pairing-approval.js +3 -4
  175. package/dist/src/storage/sqlite/device-pairing-repository.d.ts +4 -10
  176. package/dist/src/storage/sqlite/device-pairing-repository.js +10 -62
  177. package/dist/src/storage/sqlite/index.d.ts +1 -1
  178. package/dist/src/storage/sqlite/index.js +2 -2
  179. package/dist/src/storage/sqlite/migrations/164_browser_sessions.sql +8 -0
  180. package/dist/src/storage/sqlite/migrations/165_device_pairing_target.sql +40 -0
  181. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  182. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  183. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  184. package/dist/src/storage/sqlite/schema.js +1 -1
  185. package/dist/src/storage/sqlite/session-identity-sql.d.ts +2 -0
  186. package/dist/src/storage/sqlite/session-identity-sql.js +18 -0
  187. package/dist/src/storage/sqlite/session-repository.js +26 -22
  188. package/dist/src/tunnel/auth-policy.d.ts +3 -0
  189. package/dist/src/tunnel/auth-policy.js +8 -0
  190. package/dist/src/tunnel/broker-client.d.ts +5 -15
  191. package/dist/src/tunnel/broker-client.js +37 -49
  192. package/dist/src/tunnel/frpc-binary.d.ts +8 -6
  193. package/dist/src/tunnel/frpc-binary.js +76 -88
  194. package/dist/src/tunnel/frpc-config.d.ts +2 -1
  195. package/dist/src/tunnel/frpc-config.js +29 -12
  196. package/dist/src/tunnel/frpc-release.d.ts +27 -0
  197. package/dist/src/tunnel/frpc-release.js +30 -0
  198. package/dist/src/tunnel/gateway-lifecycle.js +8 -2
  199. package/dist/src/tunnel/index.js +2 -1
  200. package/dist/src/tunnel/registration-proof.d.ts +19 -0
  201. package/dist/src/tunnel/registration-proof.js +37 -0
  202. package/dist/src/tunnel/tunnel-persist.js +3 -1
  203. package/dist/src/tunnel/tunnel-service.d.ts +1 -0
  204. package/dist/src/tunnel/tunnel-service.js +35 -8
  205. package/dist/src/tunnel/tunnel-state.js +11 -5
  206. package/dist/src/tunnel/tunnel-types.d.ts +2 -0
  207. package/dist/src/tunnel/well-known.js +5 -1
  208. package/dist/src/user-context/config.js +2 -2
  209. package/dist/src/utils/logger/redact.js +4 -0
  210. package/dist/src/voice/realtime/runtime.d.ts +1 -0
  211. package/dist/src/voice/realtime/runtime.js +17 -1
  212. package/dist/src/voice/realtime/runtime.types.d.ts +1 -0
  213. package/dist/src/workflows/service/workflow-run-service.js +2 -0
  214. package/dist/src/workflows/service/workflow-session-bridge.d.ts +1 -0
  215. package/dist/src/workflows/service/workflow-session-bridge.js +1 -0
  216. package/package.json +3 -3
  217. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CE3ygr3l.js +0 -1
  218. package/dist/gateway/static/root/assets/agents-DzG2qw-c.js +0 -1
  219. package/dist/gateway/static/root/assets/apps-page-B4lX6yoT.js +0 -1
  220. package/dist/gateway/static/root/assets/automations-workspace-BiNBewg0.js +0 -6
  221. package/dist/gateway/static/root/assets/browser-settings-page-Dgdt5uVL.js +0 -8
  222. package/dist/gateway/static/root/assets/capabilities-settings-panel-BpDW-R9f.js +0 -7
  223. package/dist/gateway/static/root/assets/channels-settings-DU4EQnR0.js +0 -1
  224. package/dist/gateway/static/root/assets/connectors-page-CfJqy284.js +0 -2
  225. package/dist/gateway/static/root/assets/cron-expression-BNwbnrEb.js +0 -2
  226. package/dist/gateway/static/root/assets/date-picker-DKyirU4K.js +0 -1
  227. package/dist/gateway/static/root/assets/extension-settings-page-B1dds2bP.js +0 -1
  228. package/dist/gateway/static/root/assets/gateway-settings-pp9jN0wl.js +0 -1
  229. package/dist/gateway/static/root/assets/heartbeat-settings-B8_zTyev.js +0 -1
  230. package/dist/gateway/static/root/assets/home-page-g1KdAdLb.js +0 -1
  231. package/dist/gateway/static/root/assets/index-1zRt56Zt.css +0 -2
  232. package/dist/gateway/static/root/assets/index-OMnem2nr.js +0 -74
  233. package/dist/gateway/static/root/assets/local-app-workbench-page-bj75v2ZE.js +0 -2
  234. package/dist/gateway/static/root/assets/locale-store-BThkG0W5.js +0 -1
  235. package/dist/gateway/static/root/assets/logs-page-BX7n39zV.js +0 -2
  236. package/dist/gateway/static/root/assets/management-settings-CM62j8ZX.js +0 -1
  237. package/dist/gateway/static/root/assets/markdown-view-BwjpJVPs.js +0 -201
  238. package/dist/gateway/static/root/assets/mobile-pairing-wizard-BCWfwVx3.js +0 -1
  239. package/dist/gateway/static/root/assets/note-detail-panel-koOqb0gX.js +0 -5
  240. package/dist/gateway/static/root/assets/notes-page-BH54rY3B.js +0 -8
  241. package/dist/gateway/static/root/assets/popover-select-CKBYnT3c.js +0 -1
  242. package/dist/gateway/static/root/assets/project-detail-page-SL2g8MZY.js +0 -1
  243. package/dist/gateway/static/root/assets/projects-page-BtxazT5J.js +0 -1
  244. package/dist/gateway/static/root/assets/remote-access-hub-BSb7b67A.js +0 -1
  245. package/dist/gateway/static/root/assets/sessions-page-ljcS2KVz.js +0 -1
  246. package/dist/gateway/static/root/assets/settings-advanced-gate-CR9Y9LQm.js +0 -1
  247. package/dist/gateway/static/root/assets/setup-status-panel-J3AnooPW.js +0 -1
  248. package/dist/gateway/static/root/assets/shares-settings-AAm4Iwcp.js +0 -1
  249. package/dist/gateway/static/root/assets/skill-reload-api-pRCjP5sm.js +0 -1
  250. package/dist/gateway/static/root/assets/skills-page.utils-CfVAc_lu.js +0 -1
  251. package/dist/gateway/static/root/assets/system-settings-panel-B-pzalp-.js +0 -1
  252. package/dist/gateway/static/root/assets/task-detail-page-CmrLy3PO.js +0 -1
  253. package/dist/gateway/static/root/assets/tunnel-api-Cgpnm2fL.js +0 -1
  254. package/dist/gateway/static/root/assets/user-model-page-u3QLDX6L.js +0 -2
  255. package/dist/gateway/static/root/assets/workflows-page-DA6OOK6X.js +0 -6
package/README.md CHANGED
@@ -28,14 +28,10 @@
28
28
 
29
29
  <p align="center">
30
30
  <a href="https://xopcai.github.io/xopc/xopc-desktop.mp4">
31
- <img src="docs/public/xopc-desktop-preview.gif" alt="xopc desktop onboarding demo" width="960">
31
+ <img src="docs/public/xopc-desktop-preview.gif" alt="xopc desktop app demo" width="960">
32
32
  </a>
33
33
  </p>
34
34
 
35
- <p align="center">
36
- <a href="https://xopcai.github.io/xopc/xopc-desktop.mp4"><strong>Watch the full onboarding video (1:02) →</strong></a>
37
- </p>
38
-
39
35
  > After setup, try: **“One thing I want to move forward this week is ____. Help me find the smallest credible next step.”**
40
36
 
41
37
  <details>
package/README.zh-CN.md CHANGED
@@ -28,14 +28,10 @@
28
28
 
29
29
  <p align="center">
30
30
  <a href="https://xopcai.github.io/xopc/xopc-desktop.mp4">
31
- <img src="docs/public/xopc-desktop-preview.gif" alt="xopc 桌面端 onboarding 演示" width="960">
31
+ <img src="docs/public/xopc-desktop-preview.gif" alt="xopc 桌面应用演示" width="960">
32
32
  </a>
33
33
  </p>
34
34
 
35
- <p align="center">
36
- <a href="https://xopcai.github.io/xopc/xopc-desktop.mp4"><strong>观看完整 onboarding 视频(1:02)→</strong></a>
37
- </p>
38
-
39
35
  > 安装后可以直接告诉它:**“这周我最想推进的一件事是 ____。帮我找到最小但可信的下一步。”**
40
36
 
41
37
  <details>
@@ -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"),
@@ -5981,6 +5982,7 @@ const KEY_DATABASE = "xopc-browser-identity";
5981
5982
  const KEY_STORE = "identity";
5982
5983
  const KEY_NAME = "device-key";
5983
5984
  const NATIVE_HOST_NAME = "ai.xopc.browser";
5985
+ const GATEWAY_REQUEST_TIMEOUT_MS = 8e3;
5984
5986
  let refreshTask;
5985
5987
  async function browserPublicKeyThumbprint(jwk) {
5986
5988
  const canonical = JSON.stringify({ crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y });
@@ -6047,16 +6049,25 @@ 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
  }
6062
6073
  function openIdentityDatabase() {
@@ -6135,22 +6146,46 @@ async function verifyGateway(publicKey, payload, signature) {
6135
6146
  return false;
6136
6147
  }
6137
6148
  }
6138
- async function requestGatewayOriginPermission(origin) {
6139
- const url = new URL(origin);
6140
- const pattern = `${url.origin}/*`;
6141
- if (await chrome.permissions.contains({ origins: [pattern] })) return;
6142
- if (!await chrome.permissions.request({ origins: [pattern] })) {
6143
- throw new Error("Gateway site permission was not granted");
6149
+ function requestGatewayOriginPermissions(origins) {
6150
+ const patterns = origins.filter((origin) => {
6151
+ const url = new URL(origin);
6152
+ return !(url.protocol === "http:" && ["127.0.0.1", "localhost"].includes(url.hostname));
6153
+ }).map((origin) => `${new URL(origin).origin}/*`);
6154
+ if (!patterns.length) return Promise.resolve(true);
6155
+ return chrome.permissions.request({ origins: patterns });
6156
+ }
6157
+ class GatewayHttpError extends Error {
6158
+ constructor(message, status) {
6159
+ super(message);
6160
+ this.status = status;
6161
+ this.name = "GatewayHttpError";
6144
6162
  }
6163
+ status;
6145
6164
  }
6146
6165
  async function post(origin, path, body) {
6147
- const response = await fetch(`${origin}${path}`, {
6148
- method: "POST",
6149
- headers: { "Content-Type": "application/json" },
6150
- body: JSON.stringify(body)
6151
- });
6152
- const json = await response.json();
6153
- if (!response.ok) throw new Error(json.error?.code ?? json.error?.message ?? `Gateway returned ${response.status}`);
6166
+ const controller = new AbortController();
6167
+ const timeout = setTimeout(() => controller.abort(), GATEWAY_REQUEST_TIMEOUT_MS);
6168
+ let response;
6169
+ try {
6170
+ response = await fetch(`${origin}${path}`, {
6171
+ method: "POST",
6172
+ headers: { "Content-Type": "application/json" },
6173
+ body: JSON.stringify(body),
6174
+ signal: controller.signal
6175
+ });
6176
+ } catch (cause) {
6177
+ if (controller.signal.aborted) throw new Error(`Gateway did not respond within ${GATEWAY_REQUEST_TIMEOUT_MS / 1e3} seconds`);
6178
+ throw cause;
6179
+ } finally {
6180
+ clearTimeout(timeout);
6181
+ }
6182
+ const json = await response.json().catch(() => ({}));
6183
+ if (!response.ok) {
6184
+ throw new GatewayHttpError(
6185
+ json.error?.code ?? json.error?.message ?? `Gateway returned ${response.status}`,
6186
+ response.status
6187
+ );
6188
+ }
6154
6189
  return json;
6155
6190
  }
6156
6191
  async function signedPairingRequest(pair, payload, origin, requestId, action, completion) {
@@ -6186,7 +6221,22 @@ async function signedPairingRequest(pair, payload, origin, requestId, action, co
6186
6221
  }
6187
6222
  return decoded;
6188
6223
  }
6189
- async function refreshAccessToken(gatewayUrl, refreshToken, pair) {
6224
+ function shouldTryNextRoute(cause) {
6225
+ return !(cause instanceof GatewayHttpError) || cause.status >= 500 || [404, 408, 425, 429].includes(cause.status);
6226
+ }
6227
+ async function signedPairingRequestAcrossRoutes(pair, payload, origins, requestId, action, completion) {
6228
+ let lastRouteError;
6229
+ for (const origin of origins) {
6230
+ try {
6231
+ return { origin, result: await signedPairingRequest(pair, payload, origin, requestId, action, completion) };
6232
+ } catch (cause) {
6233
+ if (!shouldTryNextRoute(cause)) throw cause;
6234
+ lastRouteError = cause;
6235
+ }
6236
+ }
6237
+ throw lastRouteError instanceof Error ? lastRouteError : new Error("No Gateway route could be reached");
6238
+ }
6239
+ async function refreshAccessToken(gatewayUrls, refreshToken, pair, gateway) {
6190
6240
  const nextRefreshToken = createRefreshToken();
6191
6241
  const requestId = crypto.randomUUID();
6192
6242
  const timestamp = Date.now();
@@ -6199,50 +6249,94 @@ ${nonce}
6199
6249
  ${requestId}
6200
6250
  ${nextRefreshToken}`;
6201
6251
  const signature = await sign(pair, proof);
6202
- const response = await post(gatewayUrl, "/api/device-auth/refresh", {
6252
+ const body = {
6203
6253
  refreshToken,
6204
6254
  nextRefreshToken,
6205
6255
  requestId,
6206
6256
  timestamp,
6207
6257
  nonce,
6208
6258
  signature
6209
- });
6210
- if (!response.payload?.accessToken || !response.payload.accessTokenExpiresAt || response.payload.refreshToken !== nextRefreshToken) {
6259
+ };
6260
+ let gatewayUrl;
6261
+ let response;
6262
+ let lastRouteError;
6263
+ for (const origin of gatewayUrls) {
6264
+ try {
6265
+ response = await post(origin, "/api/device-auth/refresh", body);
6266
+ gatewayUrl = origin;
6267
+ break;
6268
+ } catch (cause) {
6269
+ if (!shouldTryNextRoute(cause)) throw cause;
6270
+ lastRouteError = cause;
6271
+ }
6272
+ }
6273
+ if (!response || !gatewayUrl) {
6274
+ throw lastRouteError instanceof Error ? lastRouteError : new Error("No Gateway route could be reached");
6275
+ }
6276
+ 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");
6277
+ const responseProof = decodeJson(response.signedPayload);
6278
+ 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");
6279
+ const payload = responseProof.tokens;
6280
+ if (!payload?.accessToken || !payload.accessTokenExpiresAt || payload.refreshToken !== nextRefreshToken) {
6211
6281
  throw new Error("Gateway returned invalid browser credentials");
6212
6282
  }
6213
- return response.payload;
6283
+ return { ...payload, gatewayUrl };
6214
6284
  }
6215
6285
  function wait(milliseconds) {
6216
6286
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
6217
6287
  }
6218
6288
  async function pairGateway(link, onApproval) {
6219
- const payload = parsePairingLink(link);
6220
- const origin = new URL(payload.routes[0].url).origin;
6221
- await requestGatewayOriginPermission(origin);
6289
+ const payload = parseBrowserPairingLink(link);
6290
+ const origins = [...new Set(payload.routes.map((route) => new URL(route.url).origin))];
6291
+ const permissionTask = requestGatewayOriginPermissions(origins);
6292
+ if (!await permissionTask) throw new Error("Gateway site permission was not granted");
6222
6293
  const pair = await getOrCreateKeyPair();
6223
6294
  const requestId = crypto.randomUUID();
6224
6295
  const initialRefreshToken = createRefreshToken();
6225
- let result = await signedPairingRequest(pair, payload, origin, requestId, "request");
6296
+ let { origin, result } = await signedPairingRequestAcrossRoutes(
6297
+ pair,
6298
+ payload,
6299
+ origins,
6300
+ requestId,
6301
+ "request"
6302
+ );
6226
6303
  if (result.request.status === "pending") onApproval(result.request.confirmationCode);
6227
6304
  while (result.request.status === "pending") {
6228
6305
  await wait(1500);
6229
- result = await signedPairingRequest(pair, payload, origin, requestId, "status");
6306
+ const response = await signedPairingRequestAcrossRoutes(
6307
+ pair,
6308
+ payload,
6309
+ [origin, ...origins.filter((candidate) => candidate !== origin)],
6310
+ requestId,
6311
+ "status"
6312
+ );
6313
+ ({ origin, result } = response);
6230
6314
  }
6231
6315
  if (result.request.status !== "approved" && result.request.status !== "completed") {
6232
6316
  throw new Error(`Pairing ${result.request.status}`);
6233
6317
  }
6234
6318
  if (result.request.status !== "completed") {
6235
- result = await signedPairingRequest(pair, payload, origin, requestId, "complete", {
6236
- idempotencyKey: crypto.randomUUID(),
6237
- initialRefreshToken
6238
- });
6319
+ const response = await signedPairingRequestAcrossRoutes(
6320
+ pair,
6321
+ payload,
6322
+ [origin, ...origins.filter((candidate) => candidate !== origin)],
6323
+ requestId,
6324
+ "complete",
6325
+ {
6326
+ idempotencyKey: crypto.randomUUID(),
6327
+ initialRefreshToken
6328
+ }
6329
+ );
6330
+ ({ origin, result } = response);
6239
6331
  }
6240
6332
  if (!result.request.deviceId) throw new Error("Gateway did not register the browser");
6241
- const tokens = await refreshAccessToken(origin, initialRefreshToken, pair);
6333
+ const orderedOrigins = [origin, ...origins.filter((candidate) => candidate !== origin)];
6334
+ const tokens = await refreshAccessToken(orderedOrigins, initialRefreshToken, pair, payload);
6242
6335
  const profile = {
6243
6336
  gatewayId: payload.gatewayId,
6244
6337
  gatewayName: result.gateway.name,
6245
- gatewayUrl: origin,
6338
+ gatewayUrl: tokens.gatewayUrl,
6339
+ gatewayUrls: [tokens.gatewayUrl, ...orderedOrigins.filter((candidate) => candidate !== tokens.gatewayUrl)],
6246
6340
  gatewayPublicKey: payload.gatewayPublicKey,
6247
6341
  deviceId: result.request.deviceId,
6248
6342
  refreshToken: tokens.refreshToken,
@@ -6263,8 +6357,13 @@ async function getAccessProfile() {
6263
6357
  if (profile.accessTokenExpiresAt > Date.now() + 3e4) return profile;
6264
6358
  if (refreshTask) return refreshTask;
6265
6359
  refreshTask = (async () => {
6266
- const tokens = await refreshAccessToken(profile.gatewayUrl, profile.refreshToken, await getOrCreateKeyPair());
6267
- const next = { ...profile, ...tokens };
6360
+ const gatewayUrls = profile.gatewayUrls?.length ? profile.gatewayUrls : [profile.gatewayUrl];
6361
+ const tokens = await refreshAccessToken(gatewayUrls, profile.refreshToken, await getOrCreateKeyPair(), profile);
6362
+ const next = {
6363
+ ...profile,
6364
+ ...tokens,
6365
+ gatewayUrls: [tokens.gatewayUrl, ...gatewayUrls.filter((candidate) => candidate !== tokens.gatewayUrl)]
6366
+ };
6268
6367
  await chrome.storage.local.set({ [PROFILE_KEY]: next });
6269
6368
  return next;
6270
6369
  })();
@@ -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 { 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-DkwOUI6_.js';
2
2
 
3
3
  const BROWSER_EXTENSION_PROTOCOL_VERSION = 4;
4
4
  const BROWSER_CONTROL_ENDPOINT_TOOL_NAME = "browser.control";
@@ -1253,7 +1253,7 @@ function connectWithLogging() {
1253
1253
  if (generation !== connectionGeneration && !realtime) connectWithLogging();
1254
1254
  });
1255
1255
  }
1256
- chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
1256
+ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1257
1257
  if (message.type === "browser/get-status") {
1258
1258
  sendResponse({ connected: Boolean(endpointClaim), transport: "gateway-realtime", error: lastConnectionError });
1259
1259
  } else if (message.type === "browser/get-endpoint-claim") {
@@ -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-DkwOUI6_.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, 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, p as pairGateway, s as setAutoConnectEnabled, k as readProfile, g as discoverLocalGateway, m as revokeAndForgetProfile } from './assets/auth-DkwOUI6_.js';
2
2
 
3
3
  true &&(function polyfill() {
4
4
  const relList = document.createElement("link").relList;
@@ -27544,6 +27544,22 @@ function watchSidePanelTheme(gatewayUrl) {
27544
27544
  async function reconnectBrowserBridge() {
27545
27545
  await chrome.runtime.sendMessage({ type: "browser/reconnect" }).catch(() => void 0);
27546
27546
  }
27547
+ function pairingErrorMessage(cause) {
27548
+ const message = cause instanceof Error ? cause.message : String(cause);
27549
+ if (message === "Gateway site permission was not granted") {
27550
+ return "Chrome needs access to the Gateway address. Select Connect again and allow the site permission.";
27551
+ }
27552
+ if (message === "PAIRING_EXPIRED" || message === "Pairing expired" || message === "Pairing link has expired") {
27553
+ return "This invitation expired. Create and copy a new invitation from Device access.";
27554
+ }
27555
+ if (message === "PAIRING_DEVICE_MISMATCH") {
27556
+ return "This invitation was created for a phone. Create a browser invitation instead.";
27557
+ }
27558
+ if (message === "No Gateway route could be reached") {
27559
+ return "None of the Gateway addresses responded. Check that the Gateway is online and its secure connection is active.";
27560
+ }
27561
+ return message;
27562
+ }
27547
27563
  function SidePanelApp() {
27548
27564
  const [profile, setProfile] = reactExports.useState();
27549
27565
  const [pairingLink, setPairingLink] = reactExports.useState("");
@@ -27552,6 +27568,27 @@ function SidePanelApp() {
27552
27568
  const [error, setError] = reactExports.useState("");
27553
27569
  const [localPairingLink, setLocalPairingLink] = reactExports.useState("");
27554
27570
  const initializationStarted = reactExports.useRef(false);
27571
+ const pairingStarted = reactExports.useRef(false);
27572
+ const connect = reactExports.useCallback(async (link) => {
27573
+ if (pairingStarted.current) return;
27574
+ pairingStarted.current = true;
27575
+ setState("pairing");
27576
+ setError("");
27577
+ setConfirmationCode("");
27578
+ setPairingLink(link);
27579
+ try {
27580
+ const paired = await pairGateway(link, setConfirmationCode);
27581
+ await setAutoConnectEnabled(true);
27582
+ await reconnectBrowserBridge();
27583
+ setProfile(paired);
27584
+ setState("online");
27585
+ } catch (cause) {
27586
+ setError(pairingErrorMessage(cause));
27587
+ setState("unpaired");
27588
+ } finally {
27589
+ pairingStarted.current = false;
27590
+ }
27591
+ }, []);
27555
27592
  reactExports.useEffect(() => {
27556
27593
  if (initializationStarted.current) return;
27557
27594
  initializationStarted.current = true;
@@ -27569,33 +27606,10 @@ function SidePanelApp() {
27569
27606
  return;
27570
27607
  }
27571
27608
  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
- }
27609
+ await connect(local.pairingLink);
27582
27610
  })();
27583
- }, []);
27611
+ }, [connect]);
27584
27612
  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
27613
  async function disconnect() {
27600
27614
  await revokeAndForgetProfile();
27601
27615
  setProfile(void 0);
@@ -27629,18 +27643,18 @@ function SidePanelApp() {
27629
27643
  state !== "online" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "center", children: [
27630
27644
  state === "loading" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "muted", children: "Loading…" }) : null,
27631
27645
  state === "unpaired" || state === "pairing" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "card", children: [
27632
- /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: "Connect to xopc" }),
27646
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: "Connect a Gateway" }),
27633
27647
  localPairingLink ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
27634
27648
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "muted", children: "A local xopc Gateway was found. xopc connects automatically on this computer." }),
27635
27649
  /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "primary local-connect", onClick: () => void connect(localPairingLink), disabled: state === "pairing", children: state === "pairing" ? "Connecting…" : "Retry local connection" }),
27636
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pairing-divider", children: "or use a pairing link" })
27650
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pairing-divider", children: "or paste an invitation" })
27637
27651
  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
27638
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "muted", children: "Connect to a local Gateway, or paste a pairing link for another Gateway." }),
27652
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "muted", children: "Connect locally, or paste the one-time invitation copied from Device access." }),
27639
27653
  /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "primary local-connect", onClick: () => void connectLocalGateway(), disabled: state === "pairing", children: state === "pairing" ? "Connecting…" : "Connect local Gateway" }),
27640
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pairing-divider", children: "or use a pairing link" })
27654
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pairing-divider", children: "or paste an invitation" })
27641
27655
  ] }),
27642
27656
  /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "field", children: [
27643
- "Pairing link",
27657
+ "One-time invitation",
27644
27658
  /* @__PURE__ */ jsxRuntimeExports.jsx("textarea", { rows: 4, value: pairingLink, onChange: (event) => setPairingLink(event.target.value), disabled: state === "pairing" })
27645
27659
  ] }),
27646
27660
  confirmationCode ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
@@ -27648,7 +27662,7 @@ function SidePanelApp() {
27648
27662
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "approval-code", children: confirmationCode })
27649
27663
  ] }) : null,
27650
27664
  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" }) })
27665
+ /* @__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
27666
  ] }) : null
27653
27667
  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChatPanel, {}),
27654
27668
  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.273",
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": [
@@ -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.273",
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-BBSCIl4I.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};