@xopcai/xopc 0.0.264 → 0.0.266

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 (209) hide show
  1. package/dist/browser-ext/dist/assets/auth-CknJ00ae.js +5844 -0
  2. package/dist/browser-ext/dist/assets/sidepanel-C69P3v9u.css +113 -0
  3. package/dist/browser-ext/dist/background.js +200 -68
  4. package/dist/browser-ext/dist/sidepanel.html +14 -0
  5. package/dist/browser-ext/dist/sidepanel.js +18832 -0
  6. package/dist/browser-ext/manifest.json +20 -20
  7. package/dist/extensions/telegram/xopc.extension.json +1 -1
  8. package/dist/gateway/static/root/assets/{activity-store-BYBCpt7_.js → activity-store-Bhyy6ENz.js} +1 -1
  9. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-D20aBHPJ.js → agent-avatar-dicebear-Qrp5ALCF.js} +1 -1
  10. package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-BZvMqNrU.js → agent-defaults-settings-panel-DwinST48.js} +1 -1
  11. package/dist/gateway/static/root/assets/{agents-6foBELwt.js → agents-Dlr0YyNt.js} +1 -1
  12. package/dist/gateway/static/root/assets/{api-YbtjDbuG.js → api-B2y7ZjZk.js} +1 -1
  13. package/dist/gateway/static/root/assets/{app-management-settings-panel-4ps1RrDU.js → app-management-settings-panel-bLNvz93c.js} +1 -1
  14. package/dist/gateway/static/root/assets/{appearance-settings-C7nBHnkG.js → appearance-settings-D5qgIepF.js} +1 -1
  15. package/dist/gateway/static/root/assets/{apps-page-B_g-rL5b.js → apps-page-BQVlXhIb.js} +1 -1
  16. package/dist/gateway/static/root/assets/{archive-plugin-DfKK1iJO.js → archive-plugin-BEA7VAA4.js} +1 -1
  17. package/dist/gateway/static/root/assets/{attachment-load-BOU1pdnQ.js → attachment-load-B1RyF3uu.js} +1 -1
  18. package/dist/gateway/static/root/assets/{automations-page-BePzexAH.js → automations-page-BfH0FdKa.js} +1 -1
  19. package/dist/gateway/static/root/assets/{automations-workspace-7-m5pBEZ.js → automations-workspace-C37AlD3E.js} +1 -1
  20. package/dist/gateway/static/root/assets/{binary-plugins-Cly8XDyt.js → binary-plugins-EU884ZXi.js} +1 -1
  21. package/dist/gateway/static/root/assets/{block-editor-DzSu62js.js → block-editor-Bjr3naHb.js} +1 -1
  22. package/dist/gateway/static/root/assets/{browser-automation-inputs-8bHj7Fv2.js → browser-automation-inputs-s5I78Iko.js} +1 -1
  23. package/dist/gateway/static/root/assets/{browser-automations-page-CzL7Aj2k.js → browser-automations-page-CDrYrNGy.js} +1 -1
  24. package/dist/gateway/static/root/assets/{browser-settings-page-Dum3mTiz.js → browser-settings-page-DOmUkj2k.js} +1 -1
  25. package/dist/gateway/static/root/assets/{capabilities-settings-panel-Ci6qVS-O.js → capabilities-settings-panel-slt1o04n.js} +2 -2
  26. package/dist/gateway/static/root/assets/{channels-settings-BOGEZnSv.js → channels-settings-oHTTX6Jy.js} +1 -1
  27. package/dist/gateway/static/root/assets/{channels-status-swr-BR8oQ_eP.js → channels-status-swr-_OsWr_vS.js} +1 -1
  28. package/dist/gateway/static/root/assets/{chat-terminal-dock-BF9ZXa5Z.js → chat-terminal-dock-DEYQdv6n.js} +1 -1
  29. package/dist/gateway/static/root/assets/{connectors-page-DBvEvupa.js → connectors-page-olrbxHIT.js} +1 -1
  30. package/dist/gateway/static/root/assets/{cron-expression-BszT_gjK.js → cron-expression-DFrbDWpP.js} +1 -1
  31. package/dist/gateway/static/root/assets/{date-picker-D2MKBJ0G.js → date-picker-CYriYKpH.js} +1 -1
  32. package/dist/gateway/static/root/assets/{dependency-picker-DqigBx-G.js → dependency-picker-XY3qUErs.js} +1 -1
  33. package/dist/gateway/static/root/assets/{desktop-pet-CapspBGG.js → desktop-pet-Dsc__ynA.js} +1 -1
  34. package/dist/gateway/static/root/assets/{desktop-pet-settings-DMPk4CaK.js → desktop-pet-settings-EpuX3C08.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-debug-page-CXLsDtrW.js → extension-debug-page-B_NeLV4K.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-page-B2j87ROw.js → extension-page-D3JC6mLB.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-settings-page-t1BApw-u.js → extension-settings-page-CXTQt1lp.js} +1 -1
  38. package/dist/gateway/static/root/assets/{files-BArWTfr7.js → files-Be5viEFY.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-config-swr-BFSesvAC.js → gateway-config-swr-OObCK8jM.js} +1 -1
  40. package/dist/gateway/static/root/assets/{gateway-settings-BFAecoGy.js → gateway-settings-yeYm_UPE.js} +1 -1
  41. package/dist/gateway/static/root/assets/{gateway-startup-retry-D1giYgI-.js → gateway-startup-retry-D_TxKN_A.js} +1 -1
  42. package/dist/gateway/static/root/assets/{heartbeat-settings-CyD9zDcU.js → heartbeat-settings-coh1LFsg.js} +1 -1
  43. package/dist/gateway/static/root/assets/{home-page-uItZMiBE.js → home-page-CAgoBZqp.js} +1 -1
  44. package/dist/gateway/static/root/assets/{image-generation-api-BeB-OPqO.js → image-generation-api-fPU9yGsw.js} +1 -1
  45. package/dist/gateway/static/root/assets/index-Cn__9Un2.js +74 -0
  46. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-Q_CM-ZCs.js → keyboard-shortcuts-settings-Cu1bI3Bg.js} +1 -1
  47. package/dist/gateway/static/root/assets/{local-app-workbench-page-DaiBWfOt.js → local-app-workbench-page-C9s2lFaI.js} +1 -1
  48. package/dist/gateway/static/root/assets/{local-apps-page-BALMNCSp.js → local-apps-page-CJ03Umjr.js} +1 -1
  49. package/dist/gateway/static/root/assets/{locale-store-RJHYFoq9.js → locale-store-DFQX9kTl.js} +1 -1
  50. package/dist/gateway/static/root/assets/{logs-page-C-TS7oFg.js → logs-page-CY_DQKJ2.js} +1 -1
  51. package/dist/gateway/static/root/assets/{management-settings-BajkJeYl.js → management-settings-YPEemeMo.js} +1 -1
  52. package/dist/gateway/static/root/assets/{markdown-view-BxoQJqHx.js → markdown-view-D-5jHRWg.js} +1 -1
  53. package/dist/gateway/static/root/assets/{media-plugins-C_8Hl6KG.js → media-plugins-BjT6jlrA.js} +1 -1
  54. package/dist/gateway/static/root/assets/{messages-Cf1h5WXB.js → messages-Dj8QuS6e.js} +2 -2
  55. package/dist/gateway/static/root/assets/{mobile-pairing-wizard-CsWIZrZW.js → mobile-pairing-wizard-A8eLtV6v.js} +1 -1
  56. package/dist/gateway/static/root/assets/{note-detail-panel-CCbPg_GP.js → note-detail-panel-DHT2QksJ.js} +3 -3
  57. package/dist/gateway/static/root/assets/{notes-page-BdxxcUKa.js → notes-page-BRFQiivM.js} +1 -1
  58. package/dist/gateway/static/root/assets/{page-tabs-BMYQef5D.js → page-tabs-DNUwulnl.js} +1 -1
  59. package/dist/gateway/static/root/assets/{preview-open-alternatives-CKZ-H5hJ.js → preview-open-alternatives-B33KsKkJ.js} +1 -1
  60. package/dist/gateway/static/root/assets/{product-delivery-CV4pDOtG.js → product-delivery-CCC4FJ3Y.js} +1 -1
  61. package/dist/gateway/static/root/assets/{product-open-page-zXJIptXs.js → product-open-page-CIGLPFm7.js} +1 -1
  62. package/dist/gateway/static/root/assets/{project-detail-page-DRhhxhZB.js → project-detail-page-CItEFVt9.js} +1 -1
  63. package/dist/gateway/static/root/assets/{projects-page-Wt7gF3Sx.js → projects-page-Bmy-c_lL.js} +1 -1
  64. package/dist/gateway/static/root/assets/{registry-api-BSfFaxVN.js → registry-api-CsZLatKo.js} +1 -1
  65. package/dist/gateway/static/root/assets/{remote-access-hub-B6de5Zrb.js → remote-access-hub-H6B1cA2V.js} +1 -1
  66. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DcUB5h1f.js → runtime-tools-settings-panel-BsCovC39.js} +1 -1
  67. package/dist/gateway/static/root/assets/{schema-form-CquWhe7r.js → schema-form-NsPb_Vam.js} +1 -1
  68. package/dist/gateway/static/root/assets/{schemas-BHS7bo06.js → schemas-BaskVM5g.js} +2 -2
  69. package/dist/gateway/static/root/assets/{sessions-page-BNWO2EVF.js → sessions-page-CyYLSXk_.js} +1 -1
  70. package/dist/gateway/static/root/assets/settings-advanced-gate-3T4rPk4A.js +1 -0
  71. package/dist/gateway/static/root/assets/{settings-form-section-DwswAefc.js → settings-form-section-BzPIPe1-.js} +1 -1
  72. package/dist/gateway/static/root/assets/{settings-page-CoAVmjjs.js → settings-page-4idpMhsw.js} +1 -1
  73. package/dist/gateway/static/root/assets/{setup-status-panel-C9EIcWtH.js → setup-status-panel-D2ds_TTD.js} +1 -1
  74. package/dist/gateway/static/root/assets/{share-preview-page-DWwy_4zh.js → share-preview-page-Djo3VTaC.js} +1 -1
  75. package/dist/gateway/static/root/assets/{shares-settings-CIUvq27-.js → shares-settings-fhRzNfRp.js} +1 -1
  76. package/dist/gateway/static/root/assets/skill-reload-api-Ct8tUju_.js +1 -0
  77. package/dist/gateway/static/root/assets/{skills-page-CqsgVtVh.js → skills-page-riM7FytZ.js} +1 -1
  78. package/dist/gateway/static/root/assets/{skills-page.utils-B-N73248.js → skills-page.utils-B3G8LBb-.js} +1 -1
  79. package/dist/gateway/static/root/assets/{system-settings-panel-BndjXuBZ.js → system-settings-panel-CW91jjnB.js} +1 -1
  80. package/dist/gateway/static/root/assets/{task-detail-page-CG6Ha9t7.js → task-detail-page-BBXKvl0k.js} +1 -1
  81. package/dist/gateway/static/root/assets/{theme-store-C5ssn64t.js → theme-store-zRT6vaZc.js} +1 -1
  82. package/dist/gateway/static/root/assets/{tunnel-api-BxZdcp3h.js → tunnel-api-DILER0Yb.js} +1 -1
  83. package/dist/gateway/static/root/assets/{use-autosave-mj9CUuz1.js → use-autosave-GxnP8vLO.js} +1 -1
  84. package/dist/gateway/static/root/assets/{user-model-page-DKeHMXI4.js → user-model-page-I1H4XRfA.js} +1 -1
  85. package/dist/gateway/static/root/assets/{voice-api-key-field-CzxVMYlr.js → voice-api-key-field-CI3sXyl4.js} +1 -1
  86. package/dist/gateway/static/root/assets/{voice-config-api-COA0V1cK.js → voice-config-api-DpJEu2RQ.js} +1 -1
  87. package/dist/gateway/static/root/assets/{work-discovery-overlay-DMiPK8dp.js → work-discovery-overlay-DZC9Exn3.js} +1 -1
  88. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-C82OXCJK.js → workflow-run-setup-panel-CaBaQER2.js} +1 -1
  89. package/dist/gateway/static/root/assets/{workflows-page-HLCUV3rQ.js → workflows-page-C-_Dxihw.js} +1 -1
  90. package/dist/gateway/static/root/index.html +12 -12
  91. package/dist/package.js +1 -1
  92. package/dist/packages/browser-control-contract/src/index.js +14 -0
  93. package/dist/packages/endpoint-tools-protocol/src/index.js +2 -1
  94. package/dist/packages/gateway-contract/src/browser-page-context.js +43 -0
  95. package/dist/packages/gateway-contract/src/browser-tab-binding.js +29 -0
  96. package/dist/packages/gateway-contract/src/device-pairing.js +18 -2
  97. package/dist/packages/realtime-protocol/src/index.js +1 -0
  98. package/dist/packages/realtime-protocol/src/voice-audio.js +70 -9
  99. package/dist/packages/realtime-protocol/src/voice.js +65 -17
  100. package/dist/src/agent/agent-manager.js +4 -4
  101. package/dist/src/agent/background-review/run-background-review.js +1 -1
  102. package/dist/src/agent/embedded/model-runtime.js +1 -1
  103. package/dist/src/agent/embedded/run-for-session.js +1 -1
  104. package/dist/src/agent/image/tool-model-config.js +1 -1
  105. package/dist/src/agent/mcp/oauth/mcp-oauth-store.js +1 -1
  106. package/dist/src/agent/service.js +2 -2
  107. package/dist/src/agent/session/session-inspector.js +1 -1
  108. package/dist/src/agent/skills/hub-lock.js +1 -1
  109. package/dist/src/agent/source-context/browser-page.d.ts +3 -0
  110. package/dist/src/agent/source-context/browser-page.js +39 -0
  111. package/dist/src/agent/source-context/injector.js +9 -2
  112. package/dist/src/agent/source-context/types.d.ts +7 -1
  113. package/dist/src/agent/source-context/types.js +4 -1
  114. package/dist/src/agent/tasks/task-judge-service.js +3 -3
  115. package/dist/src/agent/tools/factory.js +9 -1
  116. package/dist/src/ai-assist/text-assist.js +1 -1
  117. package/dist/src/auth/credentials.js +2 -2
  118. package/dist/src/auth/oauth/xopc-cloud.js +1 -1
  119. package/dist/src/auth/profiles/store.js +1 -1
  120. package/dist/src/auth/sync-provider-auth.js +2 -2
  121. package/dist/src/browser/automations/schema.d.ts +1 -1
  122. package/dist/src/browser/automations/service.d.ts +1 -1
  123. package/dist/src/browser/native-messaging-host.d.ts +15 -0
  124. package/dist/src/browser/native-messaging-host.js +105 -0
  125. package/dist/src/browser/providers/browser-ext-install.d.ts +17 -1
  126. package/dist/src/browser/providers/browser-ext-install.js +82 -16
  127. package/dist/src/browser/providers/extension.d.ts +4 -0
  128. package/dist/src/browser/providers/extension.js +104 -38
  129. package/dist/src/browser/runtime/browser-runtime.d.ts +2 -1
  130. package/dist/src/browser/runtime/browser-runtime.js +6 -2
  131. package/dist/src/cli/commands/browser.js +13 -3
  132. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  133. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  134. package/dist/src/cli/commands/models.js +1 -1
  135. package/dist/src/config/index.js +4 -4
  136. package/dist/src/config/loader.js +2 -2
  137. package/dist/src/config/models-json.js +1 -1
  138. package/dist/src/endpoint-tools/runtime.js +2 -0
  139. package/dist/src/extensions/lockfile.js +1 -1
  140. package/dist/src/gateway/agents-admin.js +1 -1
  141. package/dist/src/gateway/chat-stream/mapper.js +3 -2
  142. package/dist/src/gateway/file-path-classifier.js +1 -1
  143. package/dist/src/gateway/hono/app.js +19 -3
  144. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  145. package/dist/src/gateway/hono/middleware/auth.d.ts +4 -1
  146. package/dist/src/gateway/hono/middleware/auth.js +12 -1
  147. package/dist/src/gateway/hono/routes/browser-install.js +1 -1
  148. package/dist/src/gateway/hono/routes/browser.js +106 -7
  149. package/dist/src/gateway/hono/routes/devices.js +36 -3
  150. package/dist/src/gateway/hono/routes/endpoint-tools.js +15 -0
  151. package/dist/src/gateway/hono/routes/models.js +1 -1
  152. package/dist/src/gateway/hono/routes/session-input-handler.d.ts +20 -2
  153. package/dist/src/gateway/hono/routes/session-input-handler.js +18 -0
  154. package/dist/src/gateway/hono/routes/sessions.js +12 -6
  155. package/dist/src/gateway/hono/routes/voice.js +5 -4
  156. package/dist/src/gateway/security/gateway-scopes.d.ts +1 -0
  157. package/dist/src/gateway/security/gateway-scopes.js +10 -1
  158. package/dist/src/gateway/security/origin-check.d.ts +1 -0
  159. package/dist/src/gateway/security/origin-check.js +5 -1
  160. package/dist/src/gateway/service/agent-runner.js +2 -1
  161. package/dist/src/gateway/service/config-coordinator.js +1 -1
  162. package/dist/src/gateway/service/session-input-coordinator.d.ts +1 -0
  163. package/dist/src/gateway/service/session-input-coordinator.js +5 -4
  164. package/dist/src/gateway/service.js +22 -21
  165. package/dist/src/providers/auth-runtime/resolve-auth.js +1 -1
  166. package/dist/src/providers/index.js +2 -2
  167. package/dist/src/providers/model-registry.js +1 -1
  168. package/dist/src/providers/register-runtime-providers.js +1 -1
  169. package/dist/src/realtime/runtime.js +2 -1
  170. package/dist/src/session/client-history.d.ts +4 -1
  171. package/dist/src/session/client-history.js +6 -3
  172. package/dist/src/storage/sqlite/browser-tab-binding-repository.d.ts +7 -0
  173. package/dist/src/storage/sqlite/browser-tab-binding-repository.js +60 -0
  174. package/dist/src/storage/sqlite/device-access-repository.d.ts +3 -1
  175. package/dist/src/storage/sqlite/device-access-repository.js +4 -3
  176. package/dist/src/storage/sqlite/device-pairing-approval.js +6 -4
  177. package/dist/src/storage/sqlite/device-pairing-repository.d.ts +1 -1
  178. package/dist/src/storage/sqlite/index.d.ts +1 -0
  179. package/dist/src/storage/sqlite/index.js +2 -1
  180. package/dist/src/storage/sqlite/migrations/155_browser_extension.sql +120 -0
  181. package/dist/src/storage/sqlite/migrations/156_browser_tab_bindings.sql +14 -0
  182. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  183. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  184. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  185. package/dist/src/storage/sqlite/schema.js +1 -1
  186. package/dist/src/tui/tui-startup-resources.js +1 -1
  187. package/dist/src/tui/tui.js +1 -1
  188. package/dist/src/voice/realtime/agentBroker.d.ts +54 -0
  189. package/dist/src/voice/realtime/agentBroker.js +116 -0
  190. package/dist/src/voice/realtime/agentEngine.js +62 -15
  191. package/dist/src/voice/realtime/engine.d.ts +2 -1
  192. package/dist/src/voice/realtime/omniEngine.js +36 -7
  193. package/dist/src/voice/realtime/pcmFrameBuffer.d.ts +6 -0
  194. package/dist/src/voice/realtime/pcmFrameBuffer.js +29 -0
  195. package/dist/src/voice/realtime/runtime.js +97 -21
  196. package/dist/src/voice/realtime/runtime.types.d.ts +5 -21
  197. package/dist/src/voice/realtime/turnPolicy.d.ts +36 -0
  198. package/dist/src/voice/realtime/turnPolicy.js +134 -0
  199. package/dist/src/work-discovery/service.js +1 -1
  200. package/dist/src/workflows/service/workflow-run-service.js +1 -1
  201. package/package.json +2 -2
  202. package/dist/browser-ext/dist/content.js +0 -191
  203. package/dist/browser-ext/dist/popup.js +0 -32
  204. package/dist/browser-ext/popup.html +0 -37
  205. package/dist/gateway/static/root/assets/index-DQtjs2x3.js +0 -74
  206. package/dist/gateway/static/root/assets/settings-advanced-gate-DK1yTYE4.js +0 -1
  207. package/dist/gateway/static/root/assets/skill-reload-api-DfE3zFVw.js +0 -1
  208. package/dist/src/voice/realtime/conversationTurn.d.ts +0 -20
  209. package/dist/src/voice/realtime/conversationTurn.js +0 -83
@@ -18,6 +18,12 @@ export declare function submitSessionInput(c: Context, deps: AuthenticatedRouteD
18
18
  code: string;
19
19
  message: string;
20
20
  };
21
+ }, 403, "json">) | (Response & import("hono").TypedResponse<{
22
+ ok: false;
23
+ error: {
24
+ code: string;
25
+ message: string;
26
+ };
21
27
  }, 409, "json">) | (Response & import("hono").TypedResponse<{
22
28
  ok: false;
23
29
  error: {
@@ -63,9 +69,12 @@ export declare function submitSessionInput(c: Context, deps: AuthenticatedRouteD
63
69
  title: string;
64
70
  tokenEstimate?: number;
65
71
  truncated?: boolean;
72
+ url?: string;
73
+ capturedAt?: number;
74
+ documentId?: string;
66
75
  }[];
67
76
  contextSnapshots?: {
68
- kind: import("../../../agent/source-context/types.js").SessionSourceBinding["kind"];
77
+ kind: import("../../../agent/source-context/types.js").SessionSourceBinding["kind"] | "browser_page";
69
78
  sourceId: string;
70
79
  version: string;
71
80
  title: string;
@@ -77,6 +86,9 @@ export declare function submitSessionInput(c: Context, deps: AuthenticatedRouteD
77
86
  }[];
78
87
  tokenEstimate?: number;
79
88
  truncated?: boolean;
89
+ url?: string;
90
+ capturedAt?: number;
91
+ documentId?: string;
80
92
  }[];
81
93
  thinking?: string;
82
94
  origin: {
@@ -163,9 +175,12 @@ export declare function replaceLatestSessionTurn(c: Context, deps: Authenticated
163
175
  title: string;
164
176
  tokenEstimate?: number;
165
177
  truncated?: boolean;
178
+ url?: string;
179
+ capturedAt?: number;
180
+ documentId?: string;
166
181
  }[];
167
182
  contextSnapshots?: {
168
- kind: import("../../../agent/source-context/types.js").SessionSourceBinding["kind"];
183
+ kind: import("../../../agent/source-context/types.js").SessionSourceBinding["kind"] | "browser_page";
169
184
  sourceId: string;
170
185
  version: string;
171
186
  title: string;
@@ -177,6 +192,9 @@ export declare function replaceLatestSessionTurn(c: Context, deps: Authenticated
177
192
  }[];
178
193
  tokenEstimate?: number;
179
194
  truncated?: boolean;
195
+ url?: string;
196
+ capturedAt?: number;
197
+ documentId?: string;
180
198
  }[];
181
199
  thinking?: string;
182
200
  origin: {
@@ -1,9 +1,11 @@
1
+ import { browserPageContextsInputSchema } from "../../../../packages/gateway-contract/src/browser-page-context.js";
1
2
  import { endpointTurnClaimSchema } from "../../../../packages/endpoint-tools-protocol/src/index.js";
2
3
  import { init_providers, resolveModel } from "../../../providers/index.js";
3
4
  import { parseTurnContextRefs } from "../../../agent/source-context/types.js";
4
5
  import { getModelThinking } from "../../../providers/model-thinking.js";
5
6
  import { validateWebchatAttachments, validateWebchatContent } from "../../chat-limits.js";
6
7
  import { withModelConfigLock } from "../../../session/model-config-lock.js";
8
+ import { browserPageContextToAgentContext } from "../../../agent/source-context/browser-page.js";
7
9
  //#region src/gateway/hono/routes/session-input-handler.ts
8
10
  init_providers();
9
11
  const MAX_TURN_CONTEXTS = 5;
@@ -25,6 +27,14 @@ async function submitSessionInput(c, deps, sessionKey) {
25
27
  message: `contextRefs must contain at most ${MAX_TURN_CONTEXTS} valid notes`
26
28
  }
27
29
  }, 400);
30
+ const browserContexts = browserPageContextsInputSchema.safeParse(body.browserContexts ?? []);
31
+ if (!browserContexts.success) return c.json({
32
+ ok: false,
33
+ error: {
34
+ code: "BAD_REQUEST",
35
+ message: "Invalid browser page context"
36
+ }
37
+ }, 400);
28
38
  const content = typeof body.content === "string" ? body.content : "";
29
39
  const contentError = validateWebchatContent(content);
30
40
  if (contentError) return c.json({
@@ -65,6 +75,13 @@ async function submitSessionInput(c, deps, sessionKey) {
65
75
  message: "Endpoint connection is not active"
66
76
  }
67
77
  }, 401);
78
+ if (browserContexts.data.length && deps.service.endpointTools.registry.get(origin.data.endpointId)?.kind !== "browser") return c.json({
79
+ ok: false,
80
+ error: {
81
+ code: "FORBIDDEN",
82
+ message: "Browser context requires a browser endpoint"
83
+ }
84
+ }, 403);
68
85
  if (body.expectedSessionId !== void 0 && (typeof body.expectedSessionId !== "string" || !body.expectedSessionId || body.expectedSessionId.length > 128)) return c.json({
69
86
  ok: false,
70
87
  error: {
@@ -115,6 +132,7 @@ async function submitSessionInput(c, deps, sessionKey) {
115
132
  content,
116
133
  attachments,
117
134
  contextRefs,
135
+ sourceContexts: browserContexts.data.map(browserPageContextToAgentContext),
118
136
  thinking: selection?.thinkingLevel ?? (typeof body.thinking === "string" ? body.thinking : void 0),
119
137
  origin: {
120
138
  type: "endpoint",
@@ -1,3 +1,4 @@
1
+ import { deleteBrowserTabBinding } from "../../../storage/sqlite/browser-tab-binding-repository.js";
1
2
  import { buildSessionKey, init_session_key } from "../../../routing/session-key.js";
2
3
  import { resolveProjectAgentId } from "../../../projects/project-agent.js";
3
4
  import "../../../projects/index.js";
@@ -245,6 +246,7 @@ function registerSessionsRoutes(authenticated, deps) {
245
246
  }, 400);
246
247
  }
247
248
  }
249
+ if (body.createdSurface === "browser_extension") await service.sessions.patch(sessionKey, { customData: { createdSurface: "browser_extension" } });
248
250
  const session = await service.sessions.getSession(sessionKey);
249
251
  const agentConfig = channel === "webchat" ? await service.sessions.getFixedAgentConfig(sessionKey) : void 0;
250
252
  return c.json({
@@ -657,6 +659,7 @@ function registerSessionsRoutes(authenticated, deps) {
657
659
  ok: false,
658
660
  error: result.error
659
661
  }, 404);
662
+ deleteBrowserTabBinding(key);
660
663
  if (requestedProjectId !== void 0) try {
661
664
  if (requestedProjectId) service.projects.attachSession(key, requestedProjectId);
662
665
  else service.projects.detachSession(key);
@@ -832,12 +835,15 @@ function registerSessionsRoutes(authenticated, deps) {
832
835
  error: "Stop the active session run before deleting its environment"
833
836
  }, 409);
834
837
  const result = await service.sessions.delete(key);
835
- if (result.deleted) await environments.release(key).catch((error) => {
836
- log.warn({
837
- err: error,
838
- sessionKey: key
839
- }, "Session deleted but execution environment cleanup failed");
840
- });
838
+ if (result.deleted) {
839
+ deleteBrowserTabBinding(key);
840
+ await environments.release(key).catch((error) => {
841
+ log.warn({
842
+ err: error,
843
+ sessionKey: key
844
+ }, "Session deleted but execution environment cleanup failed");
845
+ });
846
+ }
841
847
  return c.json(result);
842
848
  });
843
849
  authenticated.post("/api/sessions/:key/archive", async (c) => {
@@ -133,12 +133,13 @@ function registerVoiceRoutes(authenticated, deps) {
133
133
  enabled,
134
134
  capabilities: {
135
135
  dictation: availability(Boolean(stt)),
136
- agent: availability(Boolean(stt && tts)),
137
- omni: availability(Boolean(omni)),
136
+ assistant: availability(Boolean(stt && tts)),
137
+ natural: availability(Boolean(omni)),
138
138
  languages: ["zh", "en"],
139
- bargeIn: config.voice?.realtime?.bargeIn ?? true
139
+ bargeIn: config.voice?.realtime?.bargeIn ?? true,
140
+ mediaTransports: ["websocket-pcm"]
140
141
  },
141
- defaultEngine: config.voice?.realtime?.defaultEngine ?? "agent",
142
+ defaultMode: config.voice?.realtime?.defaultEngine === "omni" ? "natural" : "assistant",
142
143
  omni: omni?.route ?? null,
143
144
  stt: stt?.route ?? null,
144
145
  tts: tts ? {
@@ -1,6 +1,7 @@
1
1
  export declare const GATEWAY_SCOPES: readonly ["gateway.status", "agents.read", "agents.run", "sessions.read", "sessions.write", "workspace.read", "workspace.write", "tasks.read", "tasks.write", "automations.read", "automations.write", "notifications.self", "device.self", "gateway.admin"];
2
2
  export type GatewayScope = typeof GATEWAY_SCOPES[number];
3
3
  export declare const DEFAULT_MOBILE_SCOPES: readonly GatewayScope[];
4
+ export declare const DEFAULT_BROWSER_EXTENSION_SCOPES: readonly GatewayScope[];
4
5
  export declare function isGatewayScope(value: unknown): value is GatewayScope;
5
6
  export declare function parseGatewayScopes(value: string): GatewayScope[];
6
7
  export declare function requiredGatewayScope(method: string, path: string): GatewayScope;
@@ -31,6 +31,14 @@ const DEFAULT_MOBILE_SCOPES = [
31
31
  "notifications.self",
32
32
  "device.self"
33
33
  ];
34
+ const DEFAULT_BROWSER_EXTENSION_SCOPES = [
35
+ "gateway.status",
36
+ "agents.read",
37
+ "agents.run",
38
+ "sessions.read",
39
+ "sessions.write",
40
+ "device.self"
41
+ ];
34
42
  function isGatewayScope(value) {
35
43
  return typeof value === "string" && KNOWN_GATEWAY_SCOPES.has(value);
36
44
  }
@@ -48,6 +56,7 @@ function requiredGatewayScope(method, path) {
48
56
  if (path === "/api/device-auth/refresh" || path === "/api/devices/me") return "device.self";
49
57
  if (path.startsWith("/api/devices/me/push")) return "notifications.self";
50
58
  if (path.startsWith("/api/endpoint-tools")) return "device.self";
59
+ if (path.startsWith("/api/browser/tab-bindings") || path.startsWith("/api/browser/approvals")) return methodScope(method, "sessions.read", "sessions.write");
51
60
  if (method === "GET" && path === "/api/connectors/approvals") return "sessions.read";
52
61
  if (method === "POST" && path === "/api/connectors/approvals/respond") return "sessions.write";
53
62
  if (path === "/api/agent" || path.startsWith("/api/agent/")) return "agents.run";
@@ -66,4 +75,4 @@ function hasGatewayScope(granted, required) {
66
75
  return granted.includes("gateway.admin") || granted.includes(required);
67
76
  }
68
77
  //#endregion
69
- export { DEFAULT_MOBILE_SCOPES, GATEWAY_SCOPES, hasGatewayScope, isGatewayScope, parseGatewayScopes, requiredGatewayScope };
78
+ export { DEFAULT_BROWSER_EXTENSION_SCOPES, DEFAULT_MOBILE_SCOPES, GATEWAY_SCOPES, hasGatewayScope, isGatewayScope, parseGatewayScopes, requiredGatewayScope };
@@ -11,6 +11,7 @@ type OriginCheckResult = {
11
11
  ok: false;
12
12
  reason: string;
13
13
  };
14
+ export declare function isChromeExtensionOrigin(origin: string | undefined): boolean;
14
15
  export declare function checkBrowserOrigin(params: {
15
16
  requestHost?: string;
16
17
  origin?: string;
@@ -5,6 +5,10 @@ const LOOPBACK_HOSTNAMES = new Set([
5
5
  "::1",
6
6
  "[::1]"
7
7
  ]);
8
+ const CHROME_EXTENSION_ORIGIN = /^chrome-extension:\/\/[a-p]{32}$/;
9
+ function isChromeExtensionOrigin(origin) {
10
+ return CHROME_EXTENSION_ORIGIN.test((origin ?? "").trim().toLowerCase());
11
+ }
8
12
  function isLoopbackHost(hostname) {
9
13
  return LOOPBACK_HOSTNAMES.has(hostname.toLowerCase());
10
14
  }
@@ -55,4 +59,4 @@ function checkBrowserOrigin(params) {
55
59
  };
56
60
  }
57
61
  //#endregion
58
- export { checkBrowserOrigin };
62
+ export { checkBrowserOrigin, isChromeExtensionOrigin };
@@ -50,7 +50,8 @@ var GatewayAgentRunner = class {
50
50
  const generator = this.runAgent(input.content, "webchat", input.sessionKey, input.origin, input.attachments, input.thinking, {
51
51
  runId: input.runId,
52
52
  taskRunId: input.taskRunId,
53
- sourceContexts: input.sourceContexts
53
+ sourceContexts: input.sourceContexts,
54
+ ...input.origin.type === "channel" && input.origin.channel === "voice" ? { presentation: "voice" } : {}
54
55
  });
55
56
  let result;
56
57
  while (true) {
@@ -1,7 +1,7 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
- import { loadConfig, saveConfig } from "../../config/loader.js";
4
3
  import { getModelRegistry } from "../../providers/model-registry.js";
4
+ import { loadConfig, saveConfig } from "../../config/loader.js";
5
5
  import { init_providers } from "../../providers/index.js";
6
6
  import { disposeAllSessionMcpRuntimes } from "../../agent/mcp/bundle-mcp-runtime.js";
7
7
  import { reloadImageGenerationProviders } from "../../agent/image/generation/provider-registry.js";
@@ -11,6 +11,7 @@ export type SubmitSessionInput = {
11
11
  content: string;
12
12
  attachments?: UserTurnAttachment[];
13
13
  contextRefs?: TurnContextRef[];
14
+ sourceContexts?: AgentSourceContext[];
14
15
  thinking?: string;
15
16
  origin: TurnOrigin;
16
17
  };
@@ -7,6 +7,7 @@ import { cancelConnectionObjective, consumeConnectionResume, invalidateConnectio
7
7
  import "../../storage/sqlite/index.js";
8
8
  import { summarizeSourceContext } from "../../agent/source-context/types.js";
9
9
  import { deleteMediaUrisNoLongerReferenced } from "../../media/session-references.js";
10
+ import { fitSourceContextsToBudget } from "../../agent/source-context/budget.js";
10
11
  import crypto from "node:crypto";
11
12
  //#region src/gateway/service/session-input-coordinator.ts
12
13
  init_logger();
@@ -70,7 +71,7 @@ var SessionInputCoordinator = class {
70
71
  const clientMessageId = input.clientMessageId.trim();
71
72
  const content = input.content.trim();
72
73
  const targetTurnId = input.targetTurnId.trim();
73
- if (!sessionKey || !clientMessageId || !targetTurnId || !content && !input.attachments?.length) return {
74
+ if (!sessionKey || !clientMessageId || !targetTurnId || !content && !input.attachments?.length && !input.sourceContexts?.length) return {
74
75
  ok: false,
75
76
  code: "BAD_REQUEST"
76
77
  };
@@ -89,7 +90,7 @@ var SessionInputCoordinator = class {
89
90
  const attachments = await this.deps.prepareAttachments(sessionKey, input.attachments);
90
91
  let sourceContexts;
91
92
  try {
92
- sourceContexts = await this.deps.prepareContexts(input.contextRefs);
93
+ sourceContexts = fitSourceContextsToBudget([...await this.deps.prepareContexts(input.contextRefs) ?? [], ...input.sourceContexts ?? []]);
93
94
  } catch (err) {
94
95
  log.warn({
95
96
  err,
@@ -137,7 +138,7 @@ var SessionInputCoordinator = class {
137
138
  const sessionKey = input.sessionKey;
138
139
  const clientMessageId = input.clientMessageId.trim();
139
140
  const content = input.content.trim();
140
- if (!sessionKey || !clientMessageId || !content && !input.attachments?.length) return {
141
+ if (!sessionKey || !clientMessageId || !content && !input.attachments?.length && !input.sourceContexts?.length) return {
141
142
  ok: false,
142
143
  code: "BAD_REQUEST"
143
144
  };
@@ -158,7 +159,7 @@ var SessionInputCoordinator = class {
158
159
  const attachments = await this.deps.prepareAttachments(sessionKey, input.attachments);
159
160
  let sourceContexts;
160
161
  try {
161
- sourceContexts = await this.deps.prepareContexts(input.contextRefs);
162
+ sourceContexts = fitSourceContextsToBudget([...await this.deps.prepareContexts(input.contextRefs) ?? [], ...input.sourceContexts ?? []]);
162
163
  } catch (err) {
163
164
  log.warn({
164
165
  err,
@@ -6,22 +6,22 @@ import { getRuntimeLogStats } from "../utils/logger/stats.js";
6
6
  import { createLogger } from "../utils/logger/index.js";
7
7
  import { init_logger } from "../utils/logger.js";
8
8
  import { closeXopcDatabase, openXopcDatabase } from "../storage/sqlite/connection.js";
9
- import { insertSessionInput } from "../storage/sqlite/session-input-repository.js";
9
+ import { findSessionInput, insertSessionInput } from "../storage/sqlite/session-input-repository.js";
10
10
  import { notifyUserContextChange } from "../user-context/changes.js";
11
11
  import { getSessionConfig } from "../storage/sqlite/config-repository.js";
12
12
  import "../storage/sqlite/index.js";
13
13
  import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
14
14
  import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agent/agent-scope.js";
15
- import { buildSessionKey, init_session_key, sanitizeSegment } from "../routing/session-key.js";
16
- import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
17
- import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
18
15
  import { init_paths, resolveConfigPath, resolveExtensionsDir } from "../config/paths.js";
16
+ import { prewarmModelRegistry } from "../providers/model-registry.js";
19
17
  import { areExtensionsGloballyDisabled } from "../extensions/discover-extensions.js";
20
18
  import { buildExtensionMetadataSnapshot } from "../extensions/extension-metadata-snapshot.js";
21
19
  import { buildChannelCatalogForConfig, buildChannelCatalogFromSnapshot, init_channel_catalog_service } from "../channels/catalog/channel-catalog-service.js";
22
20
  import { loadConfig, saveConfig } from "../config/loader.js";
23
- import { prewarmModelRegistry } from "../providers/model-registry.js";
21
+ import { buildSessionKey, init_session_key, sanitizeSegment } from "../routing/session-key.js";
22
+ import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
24
23
  import { init_providers, providers_exports } from "../providers/index.js";
24
+ import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
25
25
  import { TaskRepository } from "../tasks/task-repository.js";
26
26
  import { TaskConversationRepository } from "../tasks/task-conversation-repository.js";
27
27
  import { getEmbeddedExecutionSession } from "../agent/embedded/execution-context.js";
@@ -54,6 +54,12 @@ import { registerClarificationChannelRuntime } from "./clarify-runtime.js";
54
54
  import { ChannelManager } from "../channels/manager.js";
55
55
  import { getWorkspacePath } from "../config/workspace-path-helpers.js";
56
56
  import "../config/index.js";
57
+ import { DiscussionService } from "../discussions/service.js";
58
+ import { DiscussionOrganizer } from "../discussions/organizer.js";
59
+ import { DiscussionLiveWorker } from "../discussions/live-worker.js";
60
+ import { DiscussionOrganizerWorker } from "../discussions/organizer-worker.js";
61
+ import { DiscussionSealer } from "../discussions/sealer.js";
62
+ import "../discussions/index.js";
57
63
  import { ManagedComposioEventPoller } from "../connectors/composio-managed-events.js";
58
64
  import { startConnectedKnowledgeCoordinator } from "../knowledge/coordinator.js";
59
65
  import "../knowledge/index.js";
@@ -61,12 +67,6 @@ import { ConnectionRecoveryService } from "../connectors/connection-recovery-ser
61
67
  import { startConnectorLearningCoordinator } from "../connectors/learning-coordinator.js";
62
68
  import { ConnectedSourceChangePublisher } from "../connectors/source-change-publisher.js";
63
69
  import { startConnectorSupervisor } from "../connectors/supervisor.js";
64
- import { DiscussionService } from "../discussions/service.js";
65
- import { DiscussionOrganizer } from "../discussions/organizer.js";
66
- import { DiscussionLiveWorker } from "../discussions/live-worker.js";
67
- import { DiscussionOrganizerWorker } from "../discussions/organizer-worker.js";
68
- import { DiscussionSealer } from "../discussions/sealer.js";
69
- import "../discussions/index.js";
70
70
  import { EndpointToolRuntime } from "../endpoint-tools/runtime.js";
71
71
  import "../endpoint-tools/index.js";
72
72
  import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
@@ -123,6 +123,7 @@ import { GatewayConfigCoordinator } from "./service/config-coordinator.js";
123
123
  import { GatewayAgentRunner } from "./service/agent-runner.js";
124
124
  import { RealtimeRuntime } from "../realtime/runtime.js";
125
125
  import { VoiceRealtimeRuntime } from "../voice/realtime/runtime.js";
126
+ import { DurableVoiceAgentBroker } from "../voice/realtime/agentBroker.js";
126
127
  import { reconcileMemoryMaintenanceAutomations } from "./memory-maintenance-automation-reconciler.js";
127
128
  import { GatewayReadiness } from "./startup-readiness.js";
128
129
  import { createGatewayStartupTrace } from "./startup-trace.js";
@@ -228,16 +229,16 @@ var GatewayService = class {
228
229
  interruptedDuring: entry.interruptedDuring
229
230
  }
230
231
  }),
231
- runAgent: (text, sessionKey, signal) => {
232
- if (this.agentRunner.hasActiveRun(sessionKey)) throw new Error("Conversation session already has an active response");
233
- return this.agentRunner.runAgent(text, "webchat", sessionKey, {
234
- type: "channel",
235
- channel: "webchat"
236
- }, void 0, void 0, {
237
- signal,
238
- presentation: "voice"
239
- });
240
- }
232
+ agentBroker: new DurableVoiceAgentBroker({
233
+ submit: (input) => this.agentRunner.submitSessionInput(input),
234
+ find: findSessionInput,
235
+ snapshot: (sessionKey) => this.agentRunner.inputs.snapshot(sessionKey),
236
+ currentSequence: (topic) => this.realtime.broker.currentSequence(topic),
237
+ subscribe: (topic, afterSeq, listener) => this.realtime.broker.subscribe(topic, afterSeq, listener),
238
+ cancelRun: async (runId) => {
239
+ await this.agentRunner.abortAgentRun(runId);
240
+ }
241
+ })
241
242
  });
242
243
  getConfig() {
243
244
  return this.config;
@@ -1,5 +1,5 @@
1
- import { init_sync_provider_auth, resolveProviderApiKeyForAgentSync } from "../../auth/sync-provider-auth.js";
2
1
  import { getApiKeyFromEnv, init_env_keys } from "../env-keys.js";
2
+ import { init_sync_provider_auth, resolveProviderApiKeyForAgentSync } from "../../auth/sync-provider-auth.js";
3
3
  import { getDefaultAuthProfileStore } from "./auth-profile-store.js";
4
4
  //#region src/providers/auth-runtime/resolve-auth.ts
5
5
  init_env_keys();
@@ -1,11 +1,11 @@
1
1
  import { __esmMin, __exportAll } from "../../_virtual/_rolldown/runtime.js";
2
2
  import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
3
- import { getModelOAuthProviderIds, init_registry } from "../auth/oauth/registry.js";
4
- import { hasProviderAuthOnDiskSync, init_sync_provider_auth } from "../auth/sync-provider-auth.js";
5
3
  import { PROVIDER_ENV_MAP, getApiKeyFromEnv, init_env_keys } from "./env-keys.js";
6
4
  import { init_model_ref, splitProviderModelRef } from "./model-ref.js";
7
5
  import { ModelRegistry, getModelRegistry, init_model_registry, prewarmModelRegistry, resetModelRegistry } from "./model-registry.js";
6
+ import { getModelOAuthProviderIds, init_registry } from "../auth/oauth/registry.js";
8
7
  import { CredentialResolver, hasCredentials, init_credentials } from "../auth/credentials.js";
8
+ import { hasProviderAuthOnDiskSync, init_sync_provider_auth } from "../auth/sync-provider-auth.js";
9
9
  import { EXTENSION_PROVIDER_BASE_URL, init_constants } from "./constants.js";
10
10
  import { applyOfficialModelMetadataCorrections, getSupplementalModels, init_model_supplements } from "./model-supplements.js";
11
11
  import { getProviderRegistry, init_plugin_registry } from "./plugin-registry.js";
@@ -1,8 +1,8 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
2
  import { createLogger } from "../utils/logger/index.js";
3
3
  import { init_logger } from "../utils/logger.js";
4
- import { resolveModelsJsonPath } from "../config/paths.js";
5
4
  import { init_resolve_config_value, resolveConfigValue, resolveHeaders } from "../config/resolve-config-value.js";
5
+ import { resolveModelsJsonPath } from "../config/paths.js";
6
6
  import { getDefaultModelValues, init_models_json, validateModelsConfig } from "../config/models-json.js";
7
7
  import { getApiKeyFromEnv, init_env_keys } from "./env-keys.js";
8
8
  import { getModelCatalogStore, init_model_catalog_store } from "./model-catalog-store.js";
@@ -1,6 +1,6 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
- import { getOAuthProviderDefinition, init_registry } from "../auth/oauth/registry.js";
3
2
  import { getModelCatalogStore, init_model_catalog_store } from "./model-catalog-store.js";
3
+ import { getOAuthProviderDefinition, init_registry } from "../auth/oauth/registry.js";
4
4
  import { XOPC_CLOUD_PROVIDER_ID, init_xopc_cloud_config, resolveXopcModelRouterUrl } from "./xopc-cloud-config.js";
5
5
  //#region src/providers/register-runtime-providers.ts
6
6
  function registerRuntimeProvider(modelRuntime, source) {
@@ -194,7 +194,8 @@ var RealtimeRuntime = class {
194
194
  connectionId = crypto.randomUUID();
195
195
  let endpointReady;
196
196
  if (message.payload.endpoint) {
197
- if (!this.endpointTools || message.payload.endpoint.kind !== message.payload.clientKind) {
197
+ const endpointKindMatches = message.payload.endpoint.kind === message.payload.clientKind || message.payload.clientKind === "browser_extension" && message.payload.endpoint.kind === "browser";
198
+ if (!this.endpointTools || !endpointKindMatches) {
198
199
  socket.close(4401, "Realtime endpoint identity is invalid");
199
200
  return;
200
201
  }
@@ -15,12 +15,15 @@ export interface ClientHistoryMessage {
15
15
  /** Whitelisted display metadata; never includes source snapshot text. */
16
16
  metadata?: {
17
17
  sourceContexts?: Array<{
18
- kind: 'note';
18
+ kind: 'note' | 'browser_page';
19
19
  sourceId: string;
20
20
  version: string;
21
21
  title: string;
22
22
  tokenEstimate?: number;
23
23
  truncated?: boolean;
24
+ url?: string;
25
+ capturedAt?: number;
26
+ documentId?: string;
24
27
  }>;
25
28
  turnOutcome?: TurnOutcome;
26
29
  };
@@ -9,14 +9,17 @@ function sourceContextDisplayMetadata(metadata) {
9
9
  const sourceContexts = rows.flatMap((value) => {
10
10
  if (!value || typeof value !== "object" || Array.isArray(value)) return [];
11
11
  const row = value;
12
- if (row.kind !== "note" || typeof row.sourceId !== "string" || typeof row.version !== "string" || typeof row.title !== "string") return [];
12
+ if (row.kind !== "note" && row.kind !== "browser_page" || typeof row.sourceId !== "string" || typeof row.version !== "string" || typeof row.title !== "string") return [];
13
13
  return [{
14
- kind: "note",
14
+ kind: row.kind,
15
15
  sourceId: row.sourceId,
16
16
  version: row.version,
17
17
  title: row.title,
18
18
  ...typeof row.tokenEstimate === "number" ? { tokenEstimate: row.tokenEstimate } : {},
19
- ...row.truncated === true ? { truncated: true } : {}
19
+ ...row.truncated === true ? { truncated: true } : {},
20
+ ...typeof row.url === "string" ? { url: row.url } : {},
21
+ ...typeof row.capturedAt === "number" ? { capturedAt: row.capturedAt } : {},
22
+ ...typeof row.documentId === "string" ? { documentId: row.documentId } : {}
20
23
  }];
21
24
  });
22
25
  return sourceContexts.length ? { sourceContexts } : void 0;
@@ -0,0 +1,7 @@
1
+ import type { BrowserTabBinding } from '@xopcai/gateway-contract';
2
+ export declare function getBrowserTabBinding(sessionKey: string, now?: number): BrowserTabBinding | undefined;
3
+ export declare function getBrowserTabBindingById(bindingId: string, now?: number): BrowserTabBinding | undefined;
4
+ export declare function setBrowserTabBinding(input: Omit<BrowserTabBinding, 'id' | 'createdAt' | 'expiresAt'>, now?: number): BrowserTabBinding;
5
+ export declare function deleteBrowserTabBinding(sessionKey: string): boolean;
6
+ export declare function deleteBrowserTabBindingsByEndpoint(endpointId: string): number;
7
+ export declare function deleteBrowserTabBindingsByPrincipal(principalId: string): number;
@@ -0,0 +1,60 @@
1
+ import { getSqliteDatabase } from "./transaction.js";
2
+ import { randomUUID } from "node:crypto";
3
+ //#region src/storage/sqlite/browser-tab-binding-repository.ts
4
+ function bindingFromRow(row) {
5
+ return {
6
+ id: row.binding_id,
7
+ sessionKey: row.session_key,
8
+ principalId: row.principal_id,
9
+ endpointId: row.endpoint_id,
10
+ tabId: row.tab_id,
11
+ windowId: row.window_id,
12
+ documentId: row.document_id,
13
+ urlOrigin: row.url_origin,
14
+ mode: row.mode,
15
+ createdAt: row.created_at,
16
+ expiresAt: row.expires_at
17
+ };
18
+ }
19
+ function getBrowserTabBinding(sessionKey, now = Date.now()) {
20
+ const db = getSqliteDatabase();
21
+ db.prepare("DELETE FROM browser_tab_bindings WHERE expires_at <= ?").run(now);
22
+ const row = db.prepare(`SELECT * FROM browser_tab_bindings WHERE session_key = ?`).get(sessionKey);
23
+ return row ? bindingFromRow(row) : void 0;
24
+ }
25
+ function getBrowserTabBindingById(bindingId, now = Date.now()) {
26
+ const db = getSqliteDatabase();
27
+ db.prepare("DELETE FROM browser_tab_bindings WHERE expires_at <= ?").run(now);
28
+ const row = db.prepare(`SELECT * FROM browser_tab_bindings WHERE binding_id = ?`).get(bindingId);
29
+ return row ? bindingFromRow(row) : void 0;
30
+ }
31
+ function setBrowserTabBinding(input, now = Date.now()) {
32
+ const binding = {
33
+ ...input,
34
+ id: randomUUID(),
35
+ createdAt: now,
36
+ expiresAt: now + 480 * 60 * 1e3
37
+ };
38
+ getSqliteDatabase().prepare(`INSERT INTO browser_tab_bindings (
39
+ binding_id, session_key, principal_id, endpoint_id, tab_id, window_id,
40
+ document_id, url_origin, mode, created_at, expires_at
41
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
42
+ ON CONFLICT(session_key) DO UPDATE SET
43
+ binding_id = excluded.binding_id, principal_id = excluded.principal_id,
44
+ endpoint_id = excluded.endpoint_id, tab_id = excluded.tab_id,
45
+ window_id = excluded.window_id, document_id = excluded.document_id,
46
+ url_origin = excluded.url_origin, mode = excluded.mode,
47
+ created_at = excluded.created_at, expires_at = excluded.expires_at`).run(binding.id, binding.sessionKey, binding.principalId, binding.endpointId, binding.tabId, binding.windowId, binding.documentId, binding.urlOrigin, binding.mode, binding.createdAt, binding.expiresAt);
48
+ return binding;
49
+ }
50
+ function deleteBrowserTabBinding(sessionKey) {
51
+ return getSqliteDatabase().prepare("DELETE FROM browser_tab_bindings WHERE session_key = ?").run(sessionKey).changes > 0;
52
+ }
53
+ function deleteBrowserTabBindingsByEndpoint(endpointId) {
54
+ return Number(getSqliteDatabase().prepare("DELETE FROM browser_tab_bindings WHERE endpoint_id = ?").run(endpointId).changes);
55
+ }
56
+ function deleteBrowserTabBindingsByPrincipal(principalId) {
57
+ return Number(getSqliteDatabase().prepare("DELETE FROM browser_tab_bindings WHERE principal_id = ?").run(principalId).changes);
58
+ }
59
+ //#endregion
60
+ export { deleteBrowserTabBinding, deleteBrowserTabBindingsByEndpoint, deleteBrowserTabBindingsByPrincipal, getBrowserTabBinding, getBrowserTabBindingById, setBrowserTabBinding };
@@ -1,11 +1,12 @@
1
1
  import crypto from 'node:crypto';
2
2
  import type { GatewayScope } from '../../gateway/security/gateway-scopes.js';
3
- export type DevicePlatform = 'ios' | 'android';
3
+ export type DevicePlatform = 'ios' | 'android' | 'chrome';
4
4
  export type DevicePublicKeyJwk = crypto.webcrypto.JsonWebKey;
5
5
  export type DeviceRecord = {
6
6
  id: string;
7
7
  displayName: string;
8
8
  platform: DevicePlatform;
9
+ extensionId?: string;
9
10
  publicKeyJwk: DevicePublicKeyJwk;
10
11
  scopes: GatewayScope[];
11
12
  createdAt: number;
@@ -28,6 +29,7 @@ export declare function createDevice(input: {
28
29
  displayName: string;
29
30
  platform: DevicePlatform;
30
31
  publicKeyJwk: DevicePublicKeyJwk;
32
+ extensionId?: string;
31
33
  scopes: readonly GatewayScope[];
32
34
  now?: number;
33
35
  }): DeviceRecord;
@@ -26,6 +26,7 @@ function deviceFromRow(row) {
26
26
  displayName: row.display_name,
27
27
  platform: row.platform,
28
28
  publicKeyJwk: JSON.parse(row.public_key_jwk),
29
+ ...row.extension_id ? { extensionId: row.extension_id } : {},
29
30
  scopes: parseGatewayScopes(row.scopes_json),
30
31
  createdAt: row.created_at,
31
32
  ...row.last_seen_at === null ? {} : { lastSeenAt: row.last_seen_at },
@@ -37,9 +38,9 @@ function createDevice(input) {
37
38
  const createdAt = input.now ?? Date.now();
38
39
  getSqliteDatabase().prepare(`
39
40
  INSERT INTO devices (
40
- device_id, display_name, platform, public_key_jwk, scopes_json, created_at
41
- ) VALUES (?, ?, ?, ?, ?, ?)
42
- `).run(id, input.displayName, input.platform, JSON.stringify(input.publicKeyJwk), JSON.stringify([...new Set(input.scopes)]), createdAt);
41
+ device_id, display_name, platform, extension_id, public_key_jwk, scopes_json, created_at
42
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)
43
+ `).run(id, input.displayName, input.platform, input.extensionId ?? null, JSON.stringify(input.publicKeyJwk), JSON.stringify([...new Set(input.scopes)]), createdAt);
43
44
  return getDevice(id);
44
45
  }
45
46
  function getDevice(deviceId) {