@xopcai/xopc 0.0.273 → 0.0.275

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 (171) hide show
  1. package/dist/browser-ext/_locales/en/messages.json +215 -0
  2. package/dist/browser-ext/_locales/zh_CN/messages.json +215 -0
  3. package/dist/browser-ext/dist/assets/{auth-DkwOUI6_.js → auth-ClQTK565.js} +291 -115
  4. package/dist/browser-ext/dist/assets/{sidepanel-C86O7q5Y.css → sidepanel-CeGqObOa.css} +41 -20
  5. package/dist/browser-ext/dist/background.js +36 -4
  6. package/dist/browser-ext/dist/sidepanel.html +2 -2
  7. package/dist/browser-ext/dist/sidepanel.js +457 -310
  8. package/dist/browser-ext/manifest.json +6 -4
  9. package/dist/extensions/telegram/xopc.extension.json +1 -1
  10. package/dist/gateway/static/root/assets/{activity-store-cF7IX2RP.js → activity-store-SJZ5fS17.js} +1 -1
  11. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BrgxX8nG.js → agent-avatar-dicebear-Dx6x7MXq.js} +1 -1
  12. package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-DvhuRCLA.js → agent-defaults-settings-panel-BuxTpjkf.js} +1 -1
  13. package/dist/gateway/static/root/assets/agents-_f9HEOol.js +1 -0
  14. package/dist/gateway/static/root/assets/{api-CYkdUpkx.js → api-CnJAVHBu.js} +1 -1
  15. package/dist/gateway/static/root/assets/{app-management-settings-panel-DfoNzWIa.js → app-management-settings-panel-BYKWXcVl.js} +1 -1
  16. package/dist/gateway/static/root/assets/{appearance-settings-czbLdCqj.js → appearance-settings-BmhSJc4X.js} +1 -1
  17. package/dist/gateway/static/root/assets/apps-page-DYTnK9lL.js +1 -0
  18. package/dist/gateway/static/root/assets/{archive-plugin-D14P13mX.js → archive-plugin-BY6ncIeE.js} +1 -1
  19. package/dist/gateway/static/root/assets/attachment-load-B6cw8KtO.js +1 -0
  20. package/dist/gateway/static/root/assets/{attachment-preview-renderer-BDTD8YUe.js → attachment-preview-renderer-CfEDFYPE.js} +1 -1
  21. package/dist/gateway/static/root/assets/attachment-process-heavy-C5CqLCsX.js +5 -0
  22. package/dist/gateway/static/root/assets/{automations-page-DM7ZEewI.js → automations-page-D1WwsSf3.js} +1 -1
  23. package/dist/gateway/static/root/assets/automations-workspace-CjF56MI_.js +6 -0
  24. package/dist/gateway/static/root/assets/{binary-plugins-CxNg6InF.js → binary-plugins-CC-wYm0K.js} +2 -2
  25. package/dist/gateway/static/root/assets/{block-editor-D22VcYnC.js → block-editor-D8rh9KNe.js} +3 -3
  26. package/dist/gateway/static/root/assets/{browser-automation-inputs-6NWTLEpd.js → browser-automation-inputs-DGCqIPXT.js} +1 -1
  27. package/dist/gateway/static/root/assets/{browser-automations-page-BrqySdbW.js → browser-automations-page-CMrffyct.js} +2 -2
  28. package/dist/gateway/static/root/assets/browser-settings-page-1onvP1Se.js +8 -0
  29. package/dist/gateway/static/root/assets/capabilities-settings-panel-C9ZSJxjr.js +8 -0
  30. package/dist/gateway/static/root/assets/{channels-settings-yHsY174W.js → channels-settings-CvLTnI99.js} +1 -1
  31. package/dist/gateway/static/root/assets/{channels-status-swr-BUZimNmp.js → channels-status-swr-BTT2sIGg.js} +1 -1
  32. package/dist/gateway/static/root/assets/{chat-terminal-dock-CZPBNpMI.js → chat-terminal-dock-F_dUdZ8l.js} +2 -2
  33. package/dist/gateway/static/root/assets/connectors-page-D7NHV8B2.js +2 -0
  34. package/dist/gateway/static/root/assets/{date-picker-Da_0QyLe.js → date-picker-MHuajwQ-.js} +1 -1
  35. package/dist/gateway/static/root/assets/{dependency-picker-D_djqzy7.js → dependency-picker-BcMJJI9X.js} +1 -1
  36. package/dist/gateway/static/root/assets/{desktop-pet-Celmbw-T.js → desktop-pet-DlNm_7H0.js} +1 -1
  37. package/dist/gateway/static/root/assets/{desktop-pet-settings-CqNNgF45.js → desktop-pet-settings-BI1JQMnE.js} +1 -1
  38. package/dist/gateway/static/root/assets/device-pairing-wizard-Cp5jO5B_.js +1 -0
  39. package/dist/gateway/static/root/assets/excel-worksheet-utils-DpdB-DjU.js +1 -0
  40. package/dist/gateway/static/root/assets/{extension-debug-page-ku3kCjvH.js → extension-debug-page-DZr0GkkA.js} +1 -1
  41. package/dist/gateway/static/root/assets/{extension-page-C7FpHwL4.js → extension-page-QsHoQ6VX.js} +1 -1
  42. package/dist/gateway/static/root/assets/{extension-settings-page-OMj2tU2_.js → extension-settings-page-I2YX4Tzb.js} +1 -1
  43. package/dist/gateway/static/root/assets/{gateway-config-swr-6eb1vKE1.js → gateway-config-swr-cd8owslz.js} +1 -1
  44. package/dist/gateway/static/root/assets/gateway-settings-GwfQu8rN.js +1 -0
  45. package/dist/gateway/static/root/assets/{gateway-startup-retry-DUFFCU8H.js → gateway-startup-retry-CVTa5HSS.js} +1 -1
  46. package/dist/gateway/static/root/assets/{heartbeat-settings-CSFzOACM.js → heartbeat-settings-D-hVYXzL.js} +1 -1
  47. package/dist/gateway/static/root/assets/home-page-SEW_0k8Q.js +1 -0
  48. package/dist/gateway/static/root/assets/{image-generation-api-C1cHRBRp.js → image-generation-api-DtMRG1oF.js} +1 -1
  49. package/dist/gateway/static/root/assets/{index-C6OWYFtQ.js → index-DfZZLrWp.js} +35 -35
  50. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BuvD3iv8.js → keyboard-shortcuts-settings-D_I-hiG2.js} +1 -1
  51. package/dist/gateway/static/root/assets/{local-app-workbench-page-CaC4-THD.js → local-app-workbench-page-BcY7wIHs.js} +2 -2
  52. package/dist/gateway/static/root/assets/{local-apps-page-DdJ8zwBp.js → local-apps-page-DniZuXJJ.js} +1 -1
  53. package/dist/gateway/static/root/assets/{locale-store-BBSCIl4I.js → locale-store-BkJ7g35d.js} +1 -1
  54. package/dist/gateway/static/root/assets/{logs-page-BaR2he0K.js → logs-page-DIiOMrJ_.js} +2 -2
  55. package/dist/gateway/static/root/assets/management-settings-BPw41YX6.js +1 -0
  56. package/dist/gateway/static/root/assets/{markdown-view-c5vtnYe8.js → markdown-view-B2IR4E2r.js} +1 -1
  57. package/dist/gateway/static/root/assets/{media-plugins-D_a6GDY6.js → media-plugins-BoP3LSQz.js} +1 -1
  58. package/dist/gateway/static/root/assets/{messages-DjuBdDCn.js → messages-BGc-OJWg.js} +2 -2
  59. package/dist/gateway/static/root/assets/note-detail-panel-BI2xr54R.js +5 -0
  60. package/dist/gateway/static/root/assets/notes-page-CM7Ns8i1.js +8 -0
  61. package/dist/gateway/static/root/assets/{page-tabs-C7Le9bSI.js → page-tabs-B21WfV92.js} +1 -1
  62. package/dist/gateway/static/root/assets/{preview-open-alternatives-B2pOxJBK.js → preview-open-alternatives-BZoDpPqV.js} +1 -1
  63. package/dist/gateway/static/root/assets/{proactive-card-BlQ1vCtV.js → proactive-card-Bw9CbzUX.js} +1 -1
  64. package/dist/gateway/static/root/assets/{proactive-page-CghKTfYa.js → proactive-page-Czw_CEDB.js} +1 -1
  65. package/dist/gateway/static/root/assets/{product-open-page-DpjiHgwu.js → product-open-page-DsQcgZkI.js} +1 -1
  66. package/dist/gateway/static/root/assets/project-detail-page-jOECabbf.js +1 -0
  67. package/dist/gateway/static/root/assets/projects-page-Ck9j5q0x.js +1 -0
  68. package/dist/gateway/static/root/assets/{registry-api-CyQ4k1Ux.js → registry-api-CTq8EECj.js} +1 -1
  69. package/dist/gateway/static/root/assets/remote-access-hub-2xcpaLTC.js +1 -0
  70. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-Bl4ArLHf.js → runtime-tools-settings-panel-Bz5gIRjy.js} +2 -2
  71. package/dist/gateway/static/root/assets/{schema-form-KQFmfWd4.js → schema-form-CqM0ntNm.js} +1 -1
  72. package/dist/gateway/static/root/assets/sessions-page-CE9MK60k.js +1 -0
  73. package/dist/gateway/static/root/assets/settings-advanced-gate-D0grhQan.js +1 -0
  74. package/dist/gateway/static/root/assets/{settings-form-section-Dbnls9ty.js → settings-form-section-LqcDYJ2m.js} +1 -1
  75. package/dist/gateway/static/root/assets/{settings-page-CDKirYRG.js → settings-page-BpvBmheO.js} +1 -1
  76. package/dist/gateway/static/root/assets/setup-status-panel-CYuqNzWH.js +1 -0
  77. package/dist/gateway/static/root/assets/share-preview-page-F3qhAryJ.js +2 -0
  78. package/dist/gateway/static/root/assets/shares-settings-B4wSoQM3.js +1 -0
  79. package/dist/gateway/static/root/assets/skill-reload-api-C3LD7fkR.js +1 -0
  80. package/dist/gateway/static/root/assets/{skills-page-Bd0_ED_p.js → skills-page-D9fI548d.js} +1 -1
  81. package/dist/gateway/static/root/assets/{skills-page.utils-rA-XT-YG.js → skills-page.utils-DZNmyYqU.js} +1 -1
  82. package/dist/gateway/static/root/assets/{system-settings-panel-CSkMrHLz.js → system-settings-panel-CMsmFOhV.js} +1 -1
  83. package/dist/gateway/static/root/assets/task-detail-page-DRwTJ8E0.js +1 -0
  84. package/dist/gateway/static/root/assets/{theme-store-DWpIEWen.js → theme-store-mV6Cm2vj.js} +1 -1
  85. package/dist/gateway/static/root/assets/tunnel-api-DGaqXwql.js +1 -0
  86. package/dist/gateway/static/root/assets/{use-autosave-DkQAIAuB.js → use-autosave-bXCl0Y0j.js} +1 -1
  87. package/dist/gateway/static/root/assets/user-model-page-B3RjDSri.js +2 -0
  88. package/dist/gateway/static/root/assets/{voice-api-key-field-BrqcH0P-.js → voice-api-key-field-Cx9rl7mP.js} +1 -1
  89. package/dist/gateway/static/root/assets/{voice-config-api-BJ95Z3pT.js → voice-config-api-D3DdcH4H.js} +1 -1
  90. package/dist/gateway/static/root/assets/{work-discovery-overlay-vfTWKm13.js → work-discovery-overlay-ywJpaqKp.js} +1 -1
  91. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-CHdr_ng9.js → workflow-run-setup-panel-DyGukxOL.js} +2 -2
  92. package/dist/gateway/static/root/assets/workflows-page-CifIqO2B.js +6 -0
  93. package/dist/gateway/static/root/index.html +9 -9
  94. package/dist/package.js +1 -1
  95. package/dist/packages/gateway-contract/src/device-pairing.js +41 -2
  96. package/dist/src/agent/child-agent-factory.d.ts +3 -0
  97. package/dist/src/agent/child-agent-factory.js +2 -1
  98. package/dist/src/agent/external-tools/endpoint-provider.js +1 -1
  99. package/dist/src/agent/service.js +20 -16
  100. package/dist/src/agent/tools/factory.d.ts +1 -0
  101. package/dist/src/agent/tools/factory.js +21 -4
  102. package/dist/src/agent/workflow/workflow-child-tools.js +2 -0
  103. package/dist/src/browser/native-messaging-host.d.ts +1 -1
  104. package/dist/src/browser/native-messaging-host.js +3 -2
  105. package/dist/src/browser/providers/browser-ext-install.d.ts +1 -1
  106. package/dist/src/browser/providers/browser-ext-install.js +8 -3
  107. package/dist/src/browser/providers/realtime-extension.d.ts +4 -1
  108. package/dist/src/browser/providers/realtime-extension.js +26 -10
  109. package/dist/src/browser/readiness.d.ts +4 -1
  110. package/dist/src/browser/readiness.js +11 -5
  111. package/dist/src/cli/commands/onboard.js +1 -1
  112. package/dist/src/gateway/gateway-workflow-host.types.d.ts +2 -0
  113. package/dist/src/gateway/heartbeat/service.js +1 -1
  114. package/dist/src/gateway/hono/app.js +5 -2
  115. package/dist/src/gateway/hono/routes/agent-stream.js +1 -1
  116. package/dist/src/gateway/hono/routes/browser.js +24 -11
  117. package/dist/src/gateway/hono/routes/device-pairing-approval.d.ts +9 -2
  118. package/dist/src/gateway/hono/routes/device-pairing-approval.js +50 -10
  119. package/dist/src/gateway/hono/routes/devices.d.ts +2 -1
  120. package/dist/src/gateway/hono/routes/devices.js +33 -16
  121. package/dist/src/gateway/hono/routes/endpoint-tools.js +9 -0
  122. package/dist/src/gateway/hono/routes/models.js +6 -0
  123. package/dist/src/gateway/hono/routes/session-input-handler.d.ts +1 -1
  124. package/dist/src/gateway/hono/routes/session-input-handler.js +1 -1
  125. package/dist/src/gateway/hono/routes/side-chats.js +1 -1
  126. package/dist/src/gateway/hono/routes/tunnel.js +34 -2
  127. package/dist/src/gateway/hono/routes/voice.js +1 -1
  128. package/dist/src/gateway/rate-limit/buckets.js +2 -1
  129. package/dist/src/gateway/service/run-gateway-agent.js +1 -1
  130. package/dist/src/heartbeat/index.js +1 -1
  131. package/dist/src/providers/model-catalog-persistence.js +4 -0
  132. package/dist/src/providers/model-catalog-types.d.ts +1 -0
  133. package/dist/src/providers/xopc-cloud-model-source.js +12 -1
  134. package/dist/src/storage/sqlite/device-pairing-approval.js +3 -1
  135. package/dist/src/storage/sqlite/endpoint-session-binding-repository.d.ts +1 -0
  136. package/dist/src/storage/sqlite/endpoint-session-binding-repository.js +9 -1
  137. package/dist/src/storage/sqlite/index.d.ts +1 -1
  138. package/dist/src/storage/sqlite/index.js +2 -2
  139. package/dist/src/tui/tui.js +1 -1
  140. package/dist/src/tunnel/xopc-cloud-registration.d.ts +5 -0
  141. package/dist/src/tunnel/xopc-cloud-registration.js +17 -11
  142. package/dist/src/workflows/service/workflow-run-service.js +4 -1
  143. package/package.json +2 -2
  144. package/dist/gateway/static/root/assets/agents-C0By2FIo.js +0 -1
  145. package/dist/gateway/static/root/assets/apps-page-BSJXKWcE.js +0 -1
  146. package/dist/gateway/static/root/assets/attachment-load-Dok_B1Gv.js +0 -2
  147. package/dist/gateway/static/root/assets/attachment-process-heavy-B2_kr5EA.js +0 -11
  148. package/dist/gateway/static/root/assets/automations-workspace--1TsZf3O.js +0 -6
  149. package/dist/gateway/static/root/assets/browser-settings-page-DOHgQer_.js +0 -8
  150. package/dist/gateway/static/root/assets/capabilities-settings-panel-Bpse_5K-.js +0 -8
  151. package/dist/gateway/static/root/assets/connectors-page-B_wLKGnH.js +0 -2
  152. package/dist/gateway/static/root/assets/device-pairing-wizard-B5_w9qlm.js +0 -1
  153. package/dist/gateway/static/root/assets/excel-worksheet-utils-EyvwNT4X.js +0 -1
  154. package/dist/gateway/static/root/assets/gateway-settings-CH-6vkgN.js +0 -1
  155. package/dist/gateway/static/root/assets/home-page-BJebAKB-.js +0 -1
  156. package/dist/gateway/static/root/assets/management-settings-r-iYWZFY.js +0 -1
  157. package/dist/gateway/static/root/assets/note-detail-panel-BV6nbgac.js +0 -5
  158. package/dist/gateway/static/root/assets/notes-page-BmLKoWwi.js +0 -8
  159. package/dist/gateway/static/root/assets/project-detail-page-CV8Lh296.js +0 -1
  160. package/dist/gateway/static/root/assets/projects-page-COweOaJP.js +0 -1
  161. package/dist/gateway/static/root/assets/remote-access-hub-ChPPGVU5.js +0 -1
  162. package/dist/gateway/static/root/assets/sessions-page-DgmHibOK.js +0 -1
  163. package/dist/gateway/static/root/assets/settings-advanced-gate-DV7kMco2.js +0 -1
  164. package/dist/gateway/static/root/assets/setup-status-panel-SQmtWoOs.js +0 -1
  165. package/dist/gateway/static/root/assets/share-preview-page-DwgLjS1m.js +0 -2
  166. package/dist/gateway/static/root/assets/shares-settings-Cs5bUrYw.js +0 -1
  167. package/dist/gateway/static/root/assets/skill-reload-api-DyKrjq7F.js +0 -1
  168. package/dist/gateway/static/root/assets/task-detail-page-CEQU-L_G.js +0 -1
  169. package/dist/gateway/static/root/assets/tunnel-api-COJcGnEi.js +0 -1
  170. package/dist/gateway/static/root/assets/user-model-page-BQAU55lf.js +0 -2
  171. package/dist/gateway/static/root/assets/workflows-page-hwRJD7vR.js +0 -6
@@ -1,4 +1,4 @@
1
- import { devicePairingTargetKindSchema } from "../../../../packages/gateway-contract/src/device-pairing.js";
1
+ import { devicePairingInvitationPayloadSchema, devicePairingTargetKindSchema, formatBrowserPairingInvitation } from "../../../../packages/gateway-contract/src/device-pairing.js";
2
2
  import { listDevices, revokeDevice, rotateDeviceRefreshToken } from "../../../storage/sqlite/device-access-repository.js";
3
3
  import { getGatewayIdentityPublicKeyRaw, getOrCreateGatewayIdentity, signGatewayPayload } from "../../../storage/sqlite/gateway-identity-repository.js";
4
4
  import { createDevicePairingSetup, isDevicePairingSetupActive } from "../../../storage/sqlite/device-pairing-repository.js";
@@ -6,7 +6,7 @@ import { resolveSecureDeviceRoutes } from "../../device-routes.js";
6
6
  import { buckets } from "../../rate-limit/buckets.js";
7
7
  import "../../rate-limit/index.js";
8
8
  import { getGatewayPrincipal } from "../../security/gateway-principal.js";
9
- import { registerPairingApprovalAdminRoutes, registerPairingApprovalPublicRoutes } from "./device-pairing-approval.js";
9
+ import { pairingClientKey, registerPairingApprovalAdminRoutes, registerPairingApprovalPublicRoutes } from "./device-pairing-approval.js";
10
10
  import os from "node:os";
11
11
  import { z } from "zod";
12
12
  import { bodyLimit } from "hono/body-limit";
@@ -21,10 +21,10 @@ const refreshRequestSchema = z.strictObject({
21
21
  });
22
22
  const pairingProbeSchema = z.strictObject({ pairingId: z.string().uuid() });
23
23
  const pairingSetupSchema = z.strictObject({ targetKind: devicePairingTargetKindSchema });
24
- function pairingLinkPayload(input) {
25
- return Buffer.from(JSON.stringify(input)).toString("base64url");
24
+ function pairingPayload(input) {
25
+ return Buffer.from(JSON.stringify(devicePairingInvitationPayloadSchema.parse(input))).toString("base64url");
26
26
  }
27
- function registerDeviceAuthPublicRoutes(app) {
27
+ function registerDeviceAuthPublicRoutes(app, options) {
28
28
  app.post("/api/gateway-identity/challenge", bodyLimit({ maxSize: 512 }), async (c) => {
29
29
  const budget = buckets.identityChallenge().consume("gateway");
30
30
  if (!budget.allowed) {
@@ -46,7 +46,7 @@ function registerDeviceAuthPublicRoutes(app) {
46
46
  signature: signGatewayPayload(signedPayload)
47
47
  });
48
48
  });
49
- registerPairingApprovalPublicRoutes(app);
49
+ registerPairingApprovalPublicRoutes(app, options);
50
50
  app.post("/api/device-auth/refresh", async (c) => {
51
51
  const parsed = refreshRequestSchema.safeParse(await c.req.json().catch(() => null));
52
52
  if (!parsed.success) return c.json({
@@ -81,21 +81,37 @@ function registerDeviceAuthPublicRoutes(app) {
81
81
  }, 401);
82
82
  }
83
83
  });
84
- app.post("/api/device-pairing/probe", async (c) => {
84
+ app.post("/api/device-pairing/probe", bodyLimit({ maxSize: 512 }), async (c) => {
85
+ const clientKey = pairingClientKey(c, options);
86
+ const blocked = buckets.pairingExchange().check(clientKey);
87
+ if (blocked.blocked) {
88
+ c.header("Retry-After", String(blocked.retryAfterSec));
89
+ return c.json({
90
+ ok: false,
91
+ error: {
92
+ code: "PAIRING_RATE_LIMITED",
93
+ message: "Too many failed pairing attempts"
94
+ }
95
+ }, 429);
96
+ }
85
97
  const parsed = pairingProbeSchema.safeParse(await c.req.json().catch(() => null));
86
- if (!parsed.success || !isDevicePairingSetupActive(parsed.data.pairingId)) return c.json({
87
- ok: false,
88
- error: {
89
- code: "PAIRING_NOT_FOUND",
90
- message: "Pairing setup not found"
91
- }
92
- }, 404);
98
+ if (!parsed.success || !isDevicePairingSetupActive(parsed.data.pairingId)) {
99
+ buckets.pairingExchange().fail(clientKey);
100
+ return c.json({
101
+ ok: false,
102
+ error: {
103
+ code: "PAIRING_NOT_FOUND",
104
+ message: "Pairing setup not found"
105
+ }
106
+ }, 404);
107
+ }
93
108
  const identity = getOrCreateGatewayIdentity();
94
109
  const payload = Buffer.from(JSON.stringify({
95
110
  gatewayId: identity.id,
96
111
  pairingId: parsed.data.pairingId,
97
112
  issuedAt: Date.now()
98
113
  })).toString("base64url");
114
+ buckets.pairingExchange().succeed(clientKey);
99
115
  return c.json({
100
116
  ok: true,
101
117
  signedPayload: payload,
@@ -136,7 +152,7 @@ function registerDeviceRoutes(authenticated, deps) {
136
152
  }, 409);
137
153
  const setup = createDevicePairingSetup(routes, Date.now(), { targetKind: parsed.data.targetKind });
138
154
  const identity = getOrCreateGatewayIdentity();
139
- const encoded = pairingLinkPayload({
155
+ const encoded = pairingPayload({
140
156
  version: 3,
141
157
  pairingToken: setup.token,
142
158
  gatewayId: identity.id,
@@ -146,11 +162,12 @@ function registerDeviceRoutes(authenticated, deps) {
146
162
  targetKind: setup.targetKind,
147
163
  expiresAt: setup.expiresAt
148
164
  });
165
+ const invitation = setup.targetKind === "mobile" ? { universalLink: `https://link.xopc.ai/connect#p=${encoded}` } : { browserInvitation: formatBrowserPairingInvitation(encoded) };
149
166
  return c.json({
150
167
  ok: true,
151
168
  setup: {
152
169
  id: setup.id,
153
- universalLink: `https://link.xopc.ai/connect#p=${encoded}`,
170
+ ...invitation,
154
171
  expiresAt: setup.expiresAt,
155
172
  routes,
156
173
  protocolVersion: 3,
@@ -177,6 +177,15 @@ function registerEndpointToolRoutes(authenticated, deps) {
177
177
  message: "Invalid endpoint binding"
178
178
  }
179
179
  }, 400);
180
+ const gatewayPrincipal = getGatewayPrincipal(c);
181
+ const endpoint = deps.service.endpointTools.registry.get(parsed.data.endpointId);
182
+ if (gatewayPrincipal.kind === "device" && (!endpoint || !gatewayPrincipal.deviceId || endpoint.principalId !== gatewayPrincipal.deviceId)) return c.json({
183
+ ok: false,
184
+ error: {
185
+ code: "FORBIDDEN",
186
+ message: "Endpoint does not belong to this device"
187
+ }
188
+ }, 403);
180
189
  try {
181
190
  const binding = deps.service.endpointTools.bindings.bind(c.req.param("sessionKey"), parsed.data.endpointId);
182
191
  return c.json({
@@ -28,6 +28,10 @@ init_providers();
28
28
  init_credentials();
29
29
  init_model_catalog_store();
30
30
  init_plugin_registry();
31
+ function catalogDisplayNames(providerId, modelId) {
32
+ const model = getModelCatalogStore().getSource(providerId)?.models.find((item) => item.id === modelId);
33
+ return model?.displayNames ? { displayNames: model.displayNames } : {};
34
+ }
31
35
  function readModelsJsonProviderApiKey(providerId) {
32
36
  const { config } = loadModelsJson(resolveModelsJsonPath());
33
37
  const key = (config.providers?.[providerId.trim()])?.apiKey;
@@ -292,6 +296,7 @@ function registerModelsRoutes(authenticated, deps) {
292
296
  const models = sortModelsForPicker(await getAvailableModels()).map((m) => ({
293
297
  id: `${m.provider}/${m.id}`,
294
298
  name: m.name,
299
+ ...catalogDisplayNames(m.provider, m.id),
295
300
  provider: m.provider,
296
301
  contextWindow: m.contextWindow ?? 128e3,
297
302
  maxTokens: m.maxTokens ?? 4096,
@@ -656,6 +661,7 @@ function registerModelsRoutes(authenticated, deps) {
656
661
  const models = sortModelsForPicker(allModels).map((m) => ({
657
662
  id: `${m.provider}/${m.id}`,
658
663
  name: m.name,
664
+ ...catalogDisplayNames(m.provider, m.id),
659
665
  provider: m.provider,
660
666
  contextWindow: m.contextWindow ?? 128e3,
661
667
  maxTokens: m.maxTokens ?? 4096,
@@ -136,7 +136,7 @@ export declare function replaceLatestSessionTurn(c: Context, deps: Authenticated
136
136
  code: "TARGET_NOT_FOUND" | "NOT_LATEST" | "SESSION_BUSY" | "BAD_REQUEST" | "CONTEXT_UNAVAILABLE";
137
137
  message: string;
138
138
  };
139
- }, 400 | 404 | 409, "json">) | (Response & import("hono").TypedResponse<{
139
+ }, 404 | 400 | 409, "json">) | (Response & import("hono").TypedResponse<{
140
140
  ok: true;
141
141
  payload: {
142
142
  sessionKey: string;
@@ -1,9 +1,9 @@
1
1
  import { browserPageContextsInputSchema } from "../../../../packages/gateway-contract/src/browser-page-context.js";
2
2
  import { endpointTurnClaimSchema } from "../../../../packages/endpoint-tools-protocol/src/index.js";
3
3
  import { init_providers, resolveModel } from "../../../providers/index.js";
4
+ import { validateWebchatAttachments, validateWebchatContent } from "../../chat-limits.js";
4
5
  import { parseTurnContextRefs } from "../../../agent/source-context/types.js";
5
6
  import { getModelThinking } from "../../../providers/model-thinking.js";
6
- import { validateWebchatAttachments, validateWebchatContent } from "../../chat-limits.js";
7
7
  import { withModelConfigLock } from "../../../session/model-config-lock.js";
8
8
  import { browserPageContextToAgentContext } from "../../../agent/source-context/browser-page.js";
9
9
  //#region src/gateway/hono/routes/session-input-handler.ts
@@ -1,7 +1,7 @@
1
1
  import { chooseModelThinking } from "../../../../packages/gateway-contract/src/model-selection.js";
2
2
  import { init_providers, resolveModel } from "../../../providers/index.js";
3
- import { getModelThinking } from "../../../providers/model-thinking.js";
4
3
  import { validateWebchatAttachments, validateWebchatContent } from "../../chat-limits.js";
4
+ import { getModelThinking } from "../../../providers/model-thinking.js";
5
5
  import { validateSideChatSelections } from "../../side-chat/context-snapshot.js";
6
6
  import { SideChatError, parseThinkingLevel } from "../../side-chat/manager.js";
7
7
  import "../../side-chat/index.js";
@@ -1,3 +1,5 @@
1
+ import { createLogger } from "../../../utils/logger/index.js";
2
+ import { init_logger } from "../../../utils/logger.js";
1
3
  import { init_public_url, validatePublicUrl } from "../../../config/public-url.js";
2
4
  import { TUNNEL_REGISTRATION_SECRET_REQUIRED_CODE, TunnelRegistrationSecretError, getTunnelRegistrationSecretMeta, readTunnelRegistrationSecretFromConfigOnly, resolveTunnelBrokerUrl } from "../../../tunnel/env.js";
3
5
  import { logTunnelAudit } from "../../../tunnel/tunnel-audit.js";
@@ -9,9 +11,11 @@ import { applyTunnelConsentToConfig, mergeTunnelConfigPatch, setTunnelEnabledInC
9
11
  import { getGatewayPrincipal } from "../../security/gateway-principal.js";
10
12
  import { consumeTunnelMutationLimit } from "../../../tunnel/tunnel-rate-limit.js";
11
13
  import "../../../tunnel/index.js";
12
- import { provisionTunnelRegistrationKey } from "../../../tunnel/xopc-cloud-registration.js";
14
+ import { TunnelRegistrationProvisionError, provisionTunnelRegistrationKey } from "../../../tunnel/xopc-cloud-registration.js";
13
15
  //#region src/gateway/hono/routes/tunnel.ts
16
+ init_logger();
14
17
  init_public_url();
18
+ const log = createLogger("Gateway:Tunnel");
15
19
  async function configureTunnelFromService(deps, opts) {
16
20
  await configureTunnelFromGatewayConfig(deps.service.currentConfig, opts);
17
21
  }
@@ -161,6 +165,10 @@ function registerTunnelRoutes(authenticated, deps) {
161
165
  });
162
166
  authenticated.post("/api/tunnel/registration-key", tunnelMutationLimit, async (c) => {
163
167
  const config = deps.service.currentConfig;
168
+ if (readTunnelRegistrationSecretFromConfigOnly(config)) return c.json({
169
+ ok: true,
170
+ reused: true
171
+ });
164
172
  try {
165
173
  const merged = mergeTunnelConfigPatch(config, { registrationSecret: await provisionTunnelRegistrationKey() });
166
174
  if (merged.ok === false) return c.json({
@@ -176,9 +184,33 @@ function registerTunnelRoutes(authenticated, deps) {
176
184
  return c.json({ ok: true });
177
185
  } catch (error) {
178
186
  const message = error instanceof Error ? error.message : String(error);
187
+ if (error instanceof TunnelRegistrationProvisionError) {
188
+ const status = error.code === "tunnel_key_limit_reached" ? 409 : error.code === "tunnel_oauth_required" ? 403 : 502;
189
+ log.warn({
190
+ err: error,
191
+ code: error.code,
192
+ upstreamStatus: error.status,
193
+ phase: "registration_key"
194
+ }, `Tunnel registration key failed: ${message}`);
195
+ return c.json({
196
+ ok: false,
197
+ error: {
198
+ code: error.code,
199
+ message
200
+ }
201
+ }, status);
202
+ }
203
+ log.warn({
204
+ err: error,
205
+ errorMessage: message,
206
+ phase: "registration_key"
207
+ }, `Tunnel registration key failed: ${message}`);
179
208
  return c.json({
180
209
  ok: false,
181
- error: message
210
+ error: {
211
+ code: "tunnel_registration_failed",
212
+ message
213
+ }
182
214
  }, 502);
183
215
  }
184
216
  });
@@ -19,8 +19,8 @@ import { resolveOmniRoute } from "../../../voice/realtime/omniRoute.js";
19
19
  import { VoiceSessionCreationError, resolveStreamingStt, resolveStreamingTts } from "../../../voice/realtime/runtime.js";
20
20
  import { getGatewayPrincipal } from "../../security/gateway-principal.js";
21
21
  import { createGatewayRouteLogger } from "../lib/route-logger.js";
22
- import { listLocalVoiceModelStatuses, removeLocalVoiceModel, startLocalVoiceModelInstall } from "../../../voice/local/model-manager.js";
23
22
  import { listTtsProvidersForApi } from "../../../voice/tts/list-providers.js";
23
+ import { listLocalVoiceModelStatuses, removeLocalVoiceModel, startLocalVoiceModelInstall } from "../../../voice/local/model-manager.js";
24
24
  import { z } from "zod";
25
25
  //#region src/gateway/hono/routes/voice.ts
26
26
  init_providers();
@@ -144,7 +144,8 @@ var BucketRegistry = class {
144
144
  if (!this.pairingExchangeLimiter) this.pairingExchangeLimiter = new FailureLimiter({
145
145
  maxFailures: 30,
146
146
  windowMs: 5 * 6e4,
147
- blockDurationMs: 5 * 6e4
147
+ blockDurationMs: 5 * 6e4,
148
+ burstCoalesceMs: 0
148
149
  });
149
150
  return this.pairingExchangeLimiter;
150
151
  }
@@ -9,8 +9,8 @@ import { init_session_key, parseSessionKey } from "../../routing/session-key.js"
9
9
  import { resolveExecutionContext } from "../../tasks/execution-context.js";
10
10
  import { TaskRunCoordinator } from "../../tasks/task-run-coordinator.js";
11
11
  import { formatAgentRunErrorForClient } from "../../agent/client-error-format.js";
12
- import { prependEnvelopeTimestamp } from "../../channels/envelope-timestamp.js";
13
12
  import "../chat-limits.js";
13
+ import { prependEnvelopeTimestamp } from "../../channels/envelope-timestamp.js";
14
14
  import { ChatStreamMapper } from "../chat-stream/mapper.js";
15
15
  import { resolveWebchatSessionKey } from "../resolve-webchat-session-key.js";
16
16
  import { recordExplicitRelationshipFollowUp } from "../../user-context/relationship-continuity.js";
@@ -1,6 +1,6 @@
1
1
  import { DEFAULT_ACK_MAX_CHARS, HEARTBEAT_OK, NO_REPLY, shouldSilence, stripHeartbeatToken } from "./tokens.js";
2
- import { appendCronEventLines } from "./event-prompt.js";
3
2
  import { isWithinActiveHours } from "./active-hours.js";
4
3
  import { isHeartbeatContentEmpty } from "./content-check.js";
4
+ import { appendCronEventLines } from "./event-prompt.js";
5
5
  import { createHeartbeatWake } from "./wake.js";
6
6
  export { DEFAULT_ACK_MAX_CHARS, HEARTBEAT_OK, NO_REPLY, appendCronEventLines, createHeartbeatWake, isHeartbeatContentEmpty, isWithinActiveHours, shouldSilence, stripHeartbeatToken };
@@ -62,6 +62,10 @@ var init_model_catalog_persistence = __esmMin((() => {
62
62
  catalogModelSchema = z.object({
63
63
  id: z.string().min(1),
64
64
  name: z.string().min(1),
65
+ displayNames: z.object({
66
+ "zh-CN": z.string().min(1).optional(),
67
+ en: z.string().min(1).optional()
68
+ }).strict().optional(),
65
69
  availability: z.enum(["available", "unavailable"]),
66
70
  kind: z.enum([
67
71
  "language",
@@ -1,6 +1,7 @@
1
1
  export interface CatalogModel {
2
2
  id: string;
3
3
  name: string;
4
+ displayNames?: Partial<Record<'zh-CN' | 'en', string>>;
4
5
  availability: 'available' | 'unavailable';
5
6
  kind: 'language' | 'image' | 'stt' | 'tts';
6
7
  input: Array<'text' | 'image' | 'audio'>;
@@ -52,7 +52,8 @@ var XopcCloudModelSource = class {
52
52
  const tts = kind === "tts" ? parseTtsCapabilities(model.xopc?.capabilities, model.xopc?.defaultVoice) : void 0;
53
53
  const catalogModel = {
54
54
  id: model.id,
55
- name: model.id,
55
+ name: typeof model.xopc?.displayName === "string" && model.xopc.displayName.trim() ? model.xopc.displayName.trim() : model.id,
56
+ ...parseDisplayNames(model.xopc?.displayNames),
56
57
  kind,
57
58
  input,
58
59
  output,
@@ -180,5 +181,15 @@ function parseImageGenerationCapabilities(value) {
180
181
  maxInputImages: Number.isSafeInteger(raw.maxInputImages) && Number(raw.maxInputImages) > 0 ? Number(raw.maxInputImages) : 0
181
182
  };
182
183
  }
184
+ function parseDisplayNames(value) {
185
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
186
+ const raw = value;
187
+ const displayNames = {};
188
+ for (const locale of ["zh-CN", "en"]) {
189
+ const name = raw[locale];
190
+ if (typeof name === "string" && name.trim()) displayNames[locale] = name.trim();
191
+ }
192
+ return Object.keys(displayNames).length ? { displayNames } : {};
193
+ }
183
194
  //#endregion
184
195
  export { XopcCloudModelError, XopcCloudModelSource };
@@ -48,6 +48,7 @@ function requestRow(id, now) {
48
48
  }
49
49
  function statusFromRow(row, now) {
50
50
  const device = devicePairingDeviceSchema.parse(JSON.parse(row.device_json));
51
+ const connectedAt = row.device_id ? getDevice(row.device_id)?.lastSeenAt : void 0;
51
52
  return {
52
53
  requestId: row.request_id,
53
54
  setupId: row.pairing_id,
@@ -58,7 +59,8 @@ function statusFromRow(row, now) {
58
59
  confirmationCode: row.confirmation_code,
59
60
  expiresAt: row.expires_at,
60
61
  serverTime: now,
61
- ...row.device_id ? { deviceId: row.device_id } : {}
62
+ ...row.device_id ? { deviceId: row.device_id } : {},
63
+ ...connectedAt ? { connectedAt } : {}
62
64
  };
63
65
  }
64
66
  function verifiedSetup(token, now) {
@@ -6,3 +6,4 @@ export interface StoredEndpointSessionBinding {
6
6
  export declare function getEndpointSessionBinding(sessionKey: string): StoredEndpointSessionBinding | undefined;
7
7
  export declare function setEndpointSessionBinding(binding: StoredEndpointSessionBinding): StoredEndpointSessionBinding;
8
8
  export declare function deleteEndpointSessionBinding(sessionKey: string): boolean;
9
+ export declare function deleteEndpointSessionBindingsByPrincipal(principalId: string): number;
@@ -28,5 +28,13 @@ function setEndpointSessionBinding(binding) {
28
28
  function deleteEndpointSessionBinding(sessionKey) {
29
29
  return getSqliteDatabase().prepare("DELETE FROM endpoint_session_bindings WHERE session_key = ?").run(sessionKey).changes > 0;
30
30
  }
31
+ function deleteEndpointSessionBindingsByPrincipal(principalId) {
32
+ return Number(getSqliteDatabase().prepare(`
33
+ DELETE FROM endpoint_session_bindings
34
+ WHERE endpoint_id IN (
35
+ SELECT endpoint_id FROM endpoint_instance_bindings WHERE principal_id = ?
36
+ )
37
+ `).run(principalId).changes);
38
+ }
31
39
  //#endregion
32
- export { deleteEndpointSessionBinding, getEndpointSessionBinding, setEndpointSessionBinding };
40
+ export { deleteEndpointSessionBinding, deleteEndpointSessionBindingsByPrincipal, getEndpointSessionBinding, setEndpointSessionBinding };
@@ -5,7 +5,7 @@ export { DatabaseSchemaMigrationGapError, DatabaseSchemaTooNewError, } from './m
5
5
  export { discoverSqlMigrations, listRegisteredMigrationTargets } from './migrations/discover.js';
6
6
  export { closeXopcDatabase, getXopcDatabase, isXopcDatabaseOpen, openXopcDatabase, requireXopcDatabase, resetXopcDatabaseSingletonForTest, type OpenXopcDatabaseOptions, type XopcDatabase, } from './connection.js';
7
7
  export { getSqliteDatabase, runSqliteWriteTransaction } from './transaction.js';
8
- export { deleteEndpointSessionBinding, getEndpointSessionBinding, setEndpointSessionBinding, type StoredEndpointSessionBinding, } from './endpoint-session-binding-repository.js';
8
+ export { deleteEndpointSessionBinding, deleteEndpointSessionBindingsByPrincipal, getEndpointSessionBinding, setEndpointSessionBinding, type StoredEndpointSessionBinding, } from './endpoint-session-binding-repository.js';
9
9
  export { deleteBrowserTabBinding, deleteBrowserTabBindingsByEndpoint, deleteBrowserTabBindingsByPrincipal, getBrowserTabBinding, getBrowserTabBindingById, setBrowserTabBinding, } from './browser-tab-binding-repository.js';
10
10
  export { authenticateDeviceAccessToken, buildRefreshProofMessage, createDevice, getDevice, issueDeviceTokenPair, listDevices, revokeDevice, rotateDeviceRefreshToken, type DeviceAccessIdentity, type DevicePlatform, type DevicePublicKeyJwk, type DeviceRecord, type DeviceTokenPair, } from './device-access-repository.js';
11
11
  export { clearGatewayIdentityForTest, getOrCreateGatewayIdentity, signGatewayPayload, type GatewayIdentity, } from './gateway-identity-repository.js';
@@ -6,7 +6,7 @@ import { XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_SCHEMA_VERSION, applyPendingMi
6
6
  import { ensureXopcDatabaseSchema } from "./schema.js";
7
7
  import { closeXopcDatabase, getXopcDatabase, isXopcDatabaseOpen, openXopcDatabase, requireXopcDatabase, resetXopcDatabaseSingletonForTest } from "./connection.js";
8
8
  import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
9
- import { deleteEndpointSessionBinding, getEndpointSessionBinding, setEndpointSessionBinding } from "./endpoint-session-binding-repository.js";
9
+ import { deleteEndpointSessionBinding, deleteEndpointSessionBindingsByPrincipal, getEndpointSessionBinding, setEndpointSessionBinding } from "./endpoint-session-binding-repository.js";
10
10
  import { deleteBrowserTabBinding, deleteBrowserTabBindingsByEndpoint, deleteBrowserTabBindingsByPrincipal, getBrowserTabBinding, getBrowserTabBindingById, setBrowserTabBinding } from "./browser-tab-binding-repository.js";
11
11
  import { authenticateDeviceAccessToken, buildRefreshProofMessage, createDevice, getDevice, issueDeviceTokenPair, listDevices, revokeDevice, rotateDeviceRefreshToken } from "./device-access-repository.js";
12
12
  import { clearGatewayIdentityForTest, getOrCreateGatewayIdentity, signGatewayPayload } from "./gateway-identity-repository.js";
@@ -40,4 +40,4 @@ import { appendConnectorExecutionAudit, claimConnectorWebhookDelivery, completeC
40
40
  import { getConnectorAccount, listConnectorAccounts, reconcileConnectorAccount, refreshConnectorAccountCurrent } from "./connector-account-repository.js";
41
41
  import { getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, listConnectorSyncPolicies, upsertConnectorSyncPolicy } from "./connector-sync-policy-repository.js";
42
42
  import { getUserTrustPolicy, setUserTrustPolicy } from "./user-trust-repository.js";
43
- export { COMPOSER_INPUT_HISTORY_LIMIT, DatabaseSchemaMigrationGapError, DatabaseSchemaTooNewError, SCHEMA_META_SCHEMA_VERSION_KEY, XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_FILENAME, XOPC_DB_SCHEMA_VERSION, acknowledgeHomeAttention, appendCompactionBoundaryIfUnchanged, appendComposerInputHistory, appendConnectorExecutionAudit, appendTranscriptEntry, applyPendingMigrations, authenticateDeviceAccessToken, bindEndpointPrincipal, buildDefaultSessionMetadata, buildGlobalSessionStats, buildRefreshProofMessage, buildRelationshipPrompt, cancelQueuedSessionInput, claimConnectorWebhookDelivery, claimContextExtractionRun, claimKnowledgeSourceItems, claimNextConnectorLearningJob, claimNextSessionInput, classifyStoredRow, clearComposerInputHistory, clearGatewayIdentityForTest, closeTemporalAssertions, closeXopcDatabase, completeConnectorWebhookDelivery, completeKnowledgeSourceItemSynthesis, consumeClarificationApproval, consumeClarificationResume, consumeConnectorApproval, countKnowledgeSourceItems, createClarificationWait, createCollaborationRule, createConnectorApproval, createContextEvidence, createDevice, createDevicePairingSetup, createEndpointPrincipal, createObjectLinkRecord, createTemporalAssertion, decideConnectorApproval, deleteBrowserTabBinding, deleteBrowserTabBindingsByEndpoint, deleteBrowserTabBindingsByPrincipal, deleteConnectorConnection, deleteConnectorInstallation, deleteEndpointSessionBinding, deleteKnowledgeSourceItems, deleteNoteAgentContextRecord, deleteNoteRecord, deleteObjectLinkRecord, deleteSessionConfig, deleteSessionRecord, discoverSqlMigrations, enqueueConnectorLearningJob, ensureSessionRecord, ensureXopcDatabaseSchema, estimateTokensFromMessages, extractFtsContent, findSessionInput, findSessionKeyBySessionId, finishContextExtractionRun, finishEndpointToolInvocationAudit, finishKnowledgeSyncRun, finishSessionInputRun, getActiveClarification, getActivityEventRecord, getBrowserTabBinding, getBrowserTabBindingById, getCachedConnectorCatalogEntry, getClarification, getClarificationResumeInput, getClarificationSnapshot, getCollaborationRule, getConnectorAccount, getConnectorApproval, getConnectorConnection, getConnectorInstallation, getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, getContextExtractionRun, getCurrentSessionId, getDevice, getEndpointPrincipal, getEndpointSessionBinding, getGlobalSessionStats, getInteractionState, getKnowledgeConsumerWatermark, getKnowledgeSourceCursor, getKnowledgeSourceItem, getNoteAgentContextRecord, getNoteRecord, getOrCreateGatewayIdentity, getRelationshipSettings, getSessionConfig, getSessionInputById, getSessionInputState, getSessionMetadata, getSessionPersistedLevels, getSessionTaskPlan, getSqliteDatabase, getUserPeopleIndexState, getUserPerson, getUserTrustPolicy, getXopcDatabase, hasIndependentExtractionOutput, hasSessionConfig, incrementSessionStatsOnAppend, insertSessionInput, inspectSchemaMigrationStatus, isClarificationSuspended, isDevicePairingSetupActive, isHomeAttentionAcknowledged, isProactiveSupportAllowed, isXopcDatabaseOpen, issueDeviceTokenPair, linkContextObjects, listActiveSessionInputRuns, listActivityRecords, listCachedConnectorCatalogEntries, listCollaborationRules, listCompactionBoundaries, listComposerInputHistory, listConnectorAccounts, listConnectorActionMetadata, listConnectorApprovals, listConnectorConnections, listConnectorExecutionAudit, listConnectorInstallations, listConnectorLearningJobs, listConnectorSyncPolicies, listContextExtractionOutputs, listContextExtractionRuns, listContextObjectRelations, listDevices, listEndpointPrincipals, listEndpointToolInvocationAudits, listKnowledgeSourceChanges, listKnowledgeSourceItems, listKnowledgeSyncRuns, listNoteRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, listRegisteredMigrationTargets, listSessionMetadata, listSessionsByAgent, listTemporalAssertions, listUserPeople, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, mergeUserPeople, metadataToSessionInsert, mutateQueuedSessionInput, openXopcDatabase, paginateTranscriptMessages, patchSessionMetadata, pruneBoundedKnowledgeSourceItems, readSchemaVersion, readSchemaVersionForTest, reconcileConnectorAccount, recordActivityEvent, recoverSessionInputState, recoverStaleConnectorLearningJobs, refreshConnectorAccountCurrent, releaseConnectorWebhookDelivery, replaceConnectorCatalogEntries, replaceLatestSessionTurnAndQueueInput, replaceTranscriptRows, replaceUserPeopleIndex, requireXopcDatabase, resetSessionRecord, resetXopcDatabaseSingletonForTest, resolveClarification, resolveMigrationsDir, resolveSessionAgentId, resolveXopcDatabasePath, restoreBeforeCompactionBoundary, revokeDevice, revokeEndpointPrincipal, rotateDeviceRefreshToken, runSqliteWriteTransaction, searchSessionTranscript, sessionConfigRowToConfig, sessionRowToMetadata, setBrowserTabBinding, setCollaborationRuleStatus, setConnectorLearningPaused, setEndpointSessionBinding, setInteractionState, setKnowledgeConsumerWatermark, setKnowledgeSourceCursor, setKnowledgeSourceItemSynthesisStatus, setSessionConfig, setSessionInputStatus, setSessionTaskPlan, setUserTrustPolicy, signGatewayPayload, startEndpointToolInvocationAudit, startKnowledgeSyncRun, summarizeUserPeople, supersedeActiveClarification, touchEndpointPrincipal, transcriptEntryRowToStoredRow, updateConnectorLearningJob, updateInteractionStateFromMessage, updateRelationshipSettings, updateSessionConfig, updateSessionStats, updateUserPerson, upsertConnectorActionMetadata, upsertConnectorCatalogEntry, upsertConnectorConnection, upsertConnectorInstallation, upsertConnectorSyncPolicy, upsertKnowledgeSourceItems, upsertNoteAgentContextRecord, upsertNoteRecord, validateLatestSessionTurnTarget };
43
+ export { COMPOSER_INPUT_HISTORY_LIMIT, DatabaseSchemaMigrationGapError, DatabaseSchemaTooNewError, SCHEMA_META_SCHEMA_VERSION_KEY, XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_FILENAME, XOPC_DB_SCHEMA_VERSION, acknowledgeHomeAttention, appendCompactionBoundaryIfUnchanged, appendComposerInputHistory, appendConnectorExecutionAudit, appendTranscriptEntry, applyPendingMigrations, authenticateDeviceAccessToken, bindEndpointPrincipal, buildDefaultSessionMetadata, buildGlobalSessionStats, buildRefreshProofMessage, buildRelationshipPrompt, cancelQueuedSessionInput, claimConnectorWebhookDelivery, claimContextExtractionRun, claimKnowledgeSourceItems, claimNextConnectorLearningJob, claimNextSessionInput, classifyStoredRow, clearComposerInputHistory, clearGatewayIdentityForTest, closeTemporalAssertions, closeXopcDatabase, completeConnectorWebhookDelivery, completeKnowledgeSourceItemSynthesis, consumeClarificationApproval, consumeClarificationResume, consumeConnectorApproval, countKnowledgeSourceItems, createClarificationWait, createCollaborationRule, createConnectorApproval, createContextEvidence, createDevice, createDevicePairingSetup, createEndpointPrincipal, createObjectLinkRecord, createTemporalAssertion, decideConnectorApproval, deleteBrowserTabBinding, deleteBrowserTabBindingsByEndpoint, deleteBrowserTabBindingsByPrincipal, deleteConnectorConnection, deleteConnectorInstallation, deleteEndpointSessionBinding, deleteEndpointSessionBindingsByPrincipal, deleteKnowledgeSourceItems, deleteNoteAgentContextRecord, deleteNoteRecord, deleteObjectLinkRecord, deleteSessionConfig, deleteSessionRecord, discoverSqlMigrations, enqueueConnectorLearningJob, ensureSessionRecord, ensureXopcDatabaseSchema, estimateTokensFromMessages, extractFtsContent, findSessionInput, findSessionKeyBySessionId, finishContextExtractionRun, finishEndpointToolInvocationAudit, finishKnowledgeSyncRun, finishSessionInputRun, getActiveClarification, getActivityEventRecord, getBrowserTabBinding, getBrowserTabBindingById, getCachedConnectorCatalogEntry, getClarification, getClarificationResumeInput, getClarificationSnapshot, getCollaborationRule, getConnectorAccount, getConnectorApproval, getConnectorConnection, getConnectorInstallation, getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, getContextExtractionRun, getCurrentSessionId, getDevice, getEndpointPrincipal, getEndpointSessionBinding, getGlobalSessionStats, getInteractionState, getKnowledgeConsumerWatermark, getKnowledgeSourceCursor, getKnowledgeSourceItem, getNoteAgentContextRecord, getNoteRecord, getOrCreateGatewayIdentity, getRelationshipSettings, getSessionConfig, getSessionInputById, getSessionInputState, getSessionMetadata, getSessionPersistedLevels, getSessionTaskPlan, getSqliteDatabase, getUserPeopleIndexState, getUserPerson, getUserTrustPolicy, getXopcDatabase, hasIndependentExtractionOutput, hasSessionConfig, incrementSessionStatsOnAppend, insertSessionInput, inspectSchemaMigrationStatus, isClarificationSuspended, isDevicePairingSetupActive, isHomeAttentionAcknowledged, isProactiveSupportAllowed, isXopcDatabaseOpen, issueDeviceTokenPair, linkContextObjects, listActiveSessionInputRuns, listActivityRecords, listCachedConnectorCatalogEntries, listCollaborationRules, listCompactionBoundaries, listComposerInputHistory, listConnectorAccounts, listConnectorActionMetadata, listConnectorApprovals, listConnectorConnections, listConnectorExecutionAudit, listConnectorInstallations, listConnectorLearningJobs, listConnectorSyncPolicies, listContextExtractionOutputs, listContextExtractionRuns, listContextObjectRelations, listDevices, listEndpointPrincipals, listEndpointToolInvocationAudits, listKnowledgeSourceChanges, listKnowledgeSourceItems, listKnowledgeSyncRuns, listNoteRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, listRegisteredMigrationTargets, listSessionMetadata, listSessionsByAgent, listTemporalAssertions, listUserPeople, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, mergeUserPeople, metadataToSessionInsert, mutateQueuedSessionInput, openXopcDatabase, paginateTranscriptMessages, patchSessionMetadata, pruneBoundedKnowledgeSourceItems, readSchemaVersion, readSchemaVersionForTest, reconcileConnectorAccount, recordActivityEvent, recoverSessionInputState, recoverStaleConnectorLearningJobs, refreshConnectorAccountCurrent, releaseConnectorWebhookDelivery, replaceConnectorCatalogEntries, replaceLatestSessionTurnAndQueueInput, replaceTranscriptRows, replaceUserPeopleIndex, requireXopcDatabase, resetSessionRecord, resetXopcDatabaseSingletonForTest, resolveClarification, resolveMigrationsDir, resolveSessionAgentId, resolveXopcDatabasePath, restoreBeforeCompactionBoundary, revokeDevice, revokeEndpointPrincipal, rotateDeviceRefreshToken, runSqliteWriteTransaction, searchSessionTranscript, sessionConfigRowToConfig, sessionRowToMetadata, setBrowserTabBinding, setCollaborationRuleStatus, setConnectorLearningPaused, setEndpointSessionBinding, setInteractionState, setKnowledgeConsumerWatermark, setKnowledgeSourceCursor, setKnowledgeSourceItemSynthesisStatus, setSessionConfig, setSessionInputStatus, setSessionTaskPlan, setUserTrustPolicy, signGatewayPayload, startEndpointToolInvocationAudit, startKnowledgeSyncRun, summarizeUserPeople, supersedeActiveClarification, touchEndpointPrincipal, transcriptEntryRowToStoredRow, updateConnectorLearningJob, updateInteractionStateFromMessage, updateRelationshipSettings, updateSessionConfig, updateSessionStats, updateUserPerson, upsertConnectorActionMetadata, upsertConnectorCatalogEntry, upsertConnectorConnection, upsertConnectorInstallation, upsertConnectorSyncPolicy, upsertKnowledgeSourceItems, upsertNoteAgentContextRecord, upsertNoteRecord, validateLatestSessionTurnTarget };
@@ -7,10 +7,10 @@ import { init_paths } from "../config/paths.js";
7
7
  import { loadConfig } from "../config/loader.js";
8
8
  import { getAllModels, getAllProviders, getApiKey, init_providers, isProviderConfiguredSync } from "../providers/index.js";
9
9
  import { ProjectTrustStore, hasTrustRequiringProjectResources } from "../project-trust/trust-store.js";
10
+ import { MAX_WEBCHAT_ATTACHMENT_FILE_BYTES } from "../gateway/chat-limits.js";
10
11
  import { renderWorkflowFinalSummary, renderWorkflowPanel } from "../agent/workflow/snapshot.js";
11
12
  import { ensureStarterAgentsInitialized } from "../agent/starter-agents.js";
12
13
  import "../config/index.js";
13
- import { MAX_WEBCHAT_ATTACHMENT_FILE_BYTES } from "../gateway/chat-limits.js";
14
14
  import { isTerminalWorkflowRunStatus } from "../workflows/domain/run.js";
15
15
  import "../workflows/domain/index.js";
16
16
  import { runViewToSnapshot } from "../workflows/service/run-view-to-snapshot.js";
@@ -4,6 +4,11 @@ type ProvisionOptions = {
4
4
  resolveAccessToken?: () => Promise<string | null>;
5
5
  deviceName?: string;
6
6
  };
7
+ export declare class TunnelRegistrationProvisionError extends Error {
8
+ readonly code: string;
9
+ readonly status: number;
10
+ constructor(message: string, code: string, status: number);
11
+ }
7
12
  /** Exchange a narrowly scoped XOPC OAuth grant for a tunnel registration key. */
8
13
  export declare function provisionTunnelRegistrationKey(options?: ProvisionOptions): Promise<string>;
9
14
  export {};
@@ -6,20 +6,26 @@ import { z } from "zod";
6
6
  init_credentials();
7
7
  init_xopc_cloud_config();
8
8
  const registrationResponseSchema = z.object({ key: z.string().min(1) });
9
- function responseError(body, status) {
10
- if (body && typeof body === "object") {
11
- const error = body.error;
12
- if (error && typeof error === "object") {
13
- const message = error.message;
14
- if (typeof message === "string" && message.trim()) return message;
15
- }
9
+ const registrationErrorSchema = z.object({ error: z.object({
10
+ code: z.string().min(1).optional(),
11
+ message: z.string().min(1).optional()
12
+ }) });
13
+ var TunnelRegistrationProvisionError = class extends Error {
14
+ constructor(message, code, status) {
15
+ super(message);
16
+ this.code = code;
17
+ this.status = status;
18
+ this.name = "TunnelRegistrationProvisionError";
16
19
  }
17
- return `Tunnel registration failed (${status})`;
20
+ };
21
+ function responseError(body, status) {
22
+ const parsed = registrationErrorSchema.safeParse(body);
23
+ return new TunnelRegistrationProvisionError(parsed.success ? parsed.data.error.message ?? `Tunnel registration failed (${status})` : `Tunnel registration failed (${status})`, parsed.success ? parsed.data.error.code ?? "tunnel_registration_failed" : "tunnel_registration_failed", status);
18
24
  }
19
25
  /** Exchange a narrowly scoped XOPC OAuth grant for a tunnel registration key. */
20
26
  async function provisionTunnelRegistrationKey(options = {}) {
21
27
  const accessToken = await (options.resolveAccessToken ?? (() => new CredentialResolver().resolveApiKey("xopc-tunnel")))();
22
- if (!accessToken) throw new Error("Authorize XOPC Public Tunnel before creating a registration key");
28
+ if (!accessToken) throw new TunnelRegistrationProvisionError("Authorize XOPC Public Tunnel before creating a registration key", "tunnel_oauth_required", 401);
23
29
  const routerUrl = resolveXopcModelRouterUrl(options.routerUrl);
24
30
  const deviceName = options.deviceName?.trim() || hostname() || "XOPC gateway";
25
31
  const response = await (options.fetchImpl ?? fetch)(`${routerUrl}/tunnel/registration-key`, {
@@ -33,10 +39,10 @@ async function provisionTunnelRegistrationKey(options = {}) {
33
39
  signal: AbortSignal.timeout(3e4)
34
40
  });
35
41
  const body = await response.json().catch(() => null);
36
- if (!response.ok) throw new Error(responseError(body, response.status));
42
+ if (!response.ok) throw responseError(body, response.status);
37
43
  const parsed = registrationResponseSchema.safeParse(body);
38
44
  if (!parsed.success) throw new Error("Tunnel registration returned an invalid response");
39
45
  return parsed.data.key;
40
46
  }
41
47
  //#endregion
42
- export { provisionTunnelRegistrationKey };
48
+ export { TunnelRegistrationProvisionError, provisionTunnelRegistrationKey };
@@ -567,7 +567,10 @@ var WorkflowRunService = class {
567
567
  getDefaultModel: () => resolveModel(gatewayService.agentService.getModelForSession(params.sessionKey)),
568
568
  getConfig: () => gatewayService.currentConfig,
569
569
  sessionStore: gatewayService.sessionIndexInstance.getStore(),
570
- buildChildTools: (childOptions) => this.options.buildChildTools(childOptions)
570
+ buildChildTools: (childOptions) => this.options.buildChildTools({
571
+ ...childOptions,
572
+ endpointTools: gatewayService.endpointTools
573
+ })
571
574
  });
572
575
  return new WorkflowEngine({
573
576
  cwd: workspace,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xopcai/xopc",
3
- "version": "0.0.273",
3
+ "version": "0.0.275",
4
4
  "description": "Local-first personal AI assistant with reviewable user understanding, durable tasks, workflows, automations, and local or cloud models.",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -166,8 +166,8 @@
166
166
  "vitest": "4.1.5",
167
167
  "vue": "^3.5.35",
168
168
  "@xopcai/browser-control-contract": "0.1.0",
169
- "@xopcai/gateway-contract": "0.0.0",
170
169
  "@xopcai/endpoint-tools-protocol": "0.0.0",
170
+ "@xopcai/gateway-contract": "0.0.0",
171
171
  "@xopcai/realtime-client": "0.0.0",
172
172
  "@xopcai/realtime-protocol": "0.0.0"
173
173
  },