@xopcai/xopc 0.0.222 → 0.0.224

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 (213) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  3. package/dist/extensions/telegram/xopc.extension.json +1 -1
  4. package/dist/gateway/static/root/assets/{activity-store-NItGQmvR.js → activity-store--GBciH10.js} +1 -1
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DsR_2U9-.js → agent-avatar-dicebear-K7V4XXt7.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-BsxTpXyq.js +68 -0
  7. package/dist/gateway/static/root/assets/{api-53ZXsuyr.js → api-HoIz_ija.js} +1 -1
  8. package/dist/gateway/static/root/assets/{app-management-settings-panel-BCzVX09V.js → app-management-settings-panel-xQCmkAHh.js} +1 -1
  9. package/dist/gateway/static/root/assets/{appearance-settings-DgSpwqQI.js → appearance-settings-BRoeA4kU.js} +1 -1
  10. package/dist/gateway/static/root/assets/apps-page-BXgpBA8w.js +1 -0
  11. package/dist/gateway/static/root/assets/{archive-plugin-D8o8CP9Y.js → archive-plugin-CteCVsBP.js} +1 -1
  12. package/dist/gateway/static/root/assets/{attachment-load-BQHcAR6J.js → attachment-load-D7xNA2jB.js} +1 -1
  13. package/dist/gateway/static/root/assets/{automations-page-CswK3HFb.js → automations-page-BD1vK7r5.js} +1 -1
  14. package/dist/gateway/static/root/assets/automations-workspace-wrgf-z7D.js +6 -0
  15. package/dist/gateway/static/root/assets/{binary-plugins-BlpyTJ1b.js → binary-plugins-C3DaJa0W.js} +1 -1
  16. package/dist/gateway/static/root/assets/block-editor-lTkcHTve.js +184 -0
  17. package/dist/gateway/static/root/assets/browser-settings-page-zhzNkeVG.js +8 -0
  18. package/dist/gateway/static/root/assets/{browser-workflow-inputs-Bi6RSSpD.js → browser-workflow-inputs-1UZ0vnIy.js} +1 -1
  19. package/dist/gateway/static/root/assets/{browser-workflows-page-CZNOOQY4.js → browser-workflows-page-BHuJOF4M.js} +2 -2
  20. package/dist/gateway/static/root/assets/capabilities-settings-panel-DuCmg2Ej.js +7 -0
  21. package/dist/gateway/static/root/assets/{capability-presets-api-pC2fno7r.js → capability-presets-api-yNqTIuyd.js} +1 -1
  22. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DjiP3mQQ.js +3 -0
  23. package/dist/gateway/static/root/assets/{channel-recipient-api-B5Szgu_z.js → channel-recipient-api-krezGsKc.js} +1 -1
  24. package/dist/gateway/static/root/assets/channels-settings-B4AtvQHk.js +1 -0
  25. package/dist/gateway/static/root/assets/channels-status-swr-DMxB7slL.js +1 -0
  26. package/dist/gateway/static/root/assets/{chat-terminal-dock-2fpzufzt.js → chat-terminal-dock-BRrL2iHA.js} +2 -2
  27. package/dist/gateway/static/root/assets/connectors-page-fmda2NEP.js +2 -0
  28. package/dist/gateway/static/root/assets/{cron-expression-VePLfPUR.js → cron-expression-Bl-2DzBQ.js} +1 -1
  29. package/dist/gateway/static/root/assets/{date-picker-CJegmPTJ.js → date-picker-CxTl6Wlz.js} +1 -1
  30. package/dist/gateway/static/root/assets/{dependency-picker-B2o9unBk.js → dependency-picker-DSl0mOPa.js} +1 -1
  31. package/dist/gateway/static/root/assets/{desktop-pet-BH4Np-ay.js → desktop-pet-DTeCmCdb.js} +1 -1
  32. package/dist/gateway/static/root/assets/{desktop-pet-settings-Duu3ctxD.js → desktop-pet-settings-BNebxg0V.js} +1 -1
  33. package/dist/gateway/static/root/assets/{directory-picker-path-field-BBCUZOg2.js → directory-picker-path-field-Dn9XpmXY.js} +1 -1
  34. package/dist/gateway/static/root/assets/dist-DaxPZj9e.js +1 -0
  35. package/dist/gateway/static/root/assets/{dist-DY4Af0fY.js → dist-J_ySZvz0.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-debug-page-DS_o3F97.js → extension-debug-page-D-J-eOTb.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-page-BTLBZdCq.js → extension-page-CpST24nU.js} +1 -1
  38. package/dist/gateway/static/root/assets/{extension-settings-page-KTGrYbgk.js → extension-settings-page-4nQXFnFq.js} +1 -1
  39. package/dist/gateway/static/root/assets/floating-ui.dom-B7uQOZZW.js +1 -0
  40. package/dist/gateway/static/root/assets/{gateway-config-api-D3YJVfzY.js → gateway-config-api-BHWHduDi.js} +1 -1
  41. package/dist/gateway/static/root/assets/{gateway-config-swr-BzTbnu4O.js → gateway-config-swr-yUxMMVjK.js} +1 -1
  42. package/dist/gateway/static/root/assets/{gateway-settings-B8--s3yC.js → gateway-settings-BimMKmkM.js} +1 -1
  43. package/dist/gateway/static/root/assets/{gateway-startup-retry-B2zpkNvi.js → gateway-startup-retry-9mrsL84j.js} +1 -1
  44. package/dist/gateway/static/root/assets/heartbeat-settings-MUJ3mEC9.js +1 -0
  45. package/dist/gateway/static/root/assets/home-page-DSM6aPHF.js +1 -0
  46. package/dist/gateway/static/root/assets/{image-generation-api-BXRjz-iY.js → image-generation-api-CgFAGDi8.js} +1 -1
  47. package/dist/gateway/static/root/assets/index-B3zYJBhK.js +74 -0
  48. package/dist/gateway/static/root/assets/index-D3_xSYKd.css +2 -0
  49. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-D-Ib-suu.js → keyboard-shortcuts-settings-6Ar5rfX4.js} +1 -1
  50. package/dist/gateway/static/root/assets/local-app-workbench-page-tzM0wTL8.js +2 -0
  51. package/dist/gateway/static/root/assets/{local-apps-page-Bsy1lvAc.js → local-apps-page-B5n-x544.js} +1 -1
  52. package/dist/gateway/static/root/assets/{locale-store-iKjqemWG.js → locale-store-CPylQjH9.js} +1 -1
  53. package/dist/gateway/static/root/assets/logs-page-CgoQlera.js +2 -0
  54. package/dist/gateway/static/root/assets/{management-settings-D-akydG4.js → management-settings-CXBLyU-0.js} +1 -1
  55. package/dist/gateway/static/root/assets/{markdown-split-DHH4Cu2i.js → markdown-split-CtmQemJi.js} +1 -1
  56. package/dist/gateway/static/root/assets/markdown-view-CUsob4Pz.js +69 -0
  57. package/dist/gateway/static/root/assets/{media-plugins-BwHtUXkj.js → media-plugins-Dsd-IEOW.js} +1 -1
  58. package/dist/gateway/static/root/assets/messages-B82nsi9k.js +3 -0
  59. package/dist/gateway/static/root/assets/notes-api-CfKZYrBC.js +1 -0
  60. package/dist/gateway/static/root/assets/{notes-page-BxM1p6hz.js → notes-page-BKbOTE2n.js} +1 -1
  61. package/dist/gateway/static/root/assets/notes-workbench-BScELo01.js +4 -0
  62. package/dist/gateway/static/root/assets/oauth-authorization-window-Cdolr2wE.js +1 -0
  63. package/dist/gateway/static/root/assets/{popover-select-BzdnTy3h.js → popover-select-CccGri5Y.js} +1 -1
  64. package/dist/gateway/static/root/assets/{product-open-page-DrfWH1ir.js → product-open-page-DqB9bsDB.js} +1 -1
  65. package/dist/gateway/static/root/assets/project-detail-page-DUoyty8X.js +1 -0
  66. package/dist/gateway/static/root/assets/projects-page-PeXUdGdO.js +1 -0
  67. package/dist/gateway/static/root/assets/{registry-api-Cx3JxXSL.js → registry-api-B_5D8epF.js} +1 -1
  68. package/dist/gateway/static/root/assets/remote-access-hub-sHho-uXP.js +1 -0
  69. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DF7syQRd.js → runtime-tools-settings-panel-DBTH_t0O.js} +1 -1
  70. package/dist/gateway/static/root/assets/{schema-form-BQ_qRIsM.js → schema-form-CqMKAwV0.js} +1 -1
  71. package/dist/gateway/static/root/assets/sessions-page-DyvNgaP9.js +1 -0
  72. package/dist/gateway/static/root/assets/settings-advanced-gate-CnYf1R7z.js +1 -0
  73. package/dist/gateway/static/root/assets/{settings-form-section-BBHGOQHU.js → settings-form-section-dPriuuYq.js} +1 -1
  74. package/dist/gateway/static/root/assets/{settings-loading-skeleton-CiwjP2-b.js → settings-loading-skeleton-B-Mbm8Va.js} +1 -1
  75. package/dist/gateway/static/root/assets/{settings-page-Rl9waapk.js → settings-page-Dyj3w-Ml.js} +1 -1
  76. package/dist/gateway/static/root/assets/setup-status-panel-C4FxY5J3.js +1 -0
  77. package/dist/gateway/static/root/assets/share-preview-page-emEdx7YL.js +2 -0
  78. package/dist/gateway/static/root/assets/shares-settings-BQBVq-sN.js +1 -0
  79. package/dist/gateway/static/root/assets/skill-reload-api-BFoEpQ4I.js +1 -0
  80. package/dist/gateway/static/root/assets/{skills-page-YbtR_zEU.js → skills-page-BNtYnrRT.js} +1 -1
  81. package/dist/gateway/static/root/assets/{skills-page.utils-DTmx2Zza.js → skills-page.utils-DjnbNFs5.js} +1 -1
  82. package/dist/gateway/static/root/assets/{system-settings-panel-BZDJcKdS.js → system-settings-panel-DDStf-jZ.js} +1 -1
  83. package/dist/gateway/static/root/assets/task-detail-page-ZVwr8KbS.js +1 -0
  84. package/dist/gateway/static/root/assets/{theme-store-BOD2D0dJ.js → theme-store-BN-32Fz5.js} +1 -1
  85. package/dist/gateway/static/root/assets/{use-autosave-Be9aR9qA.js → use-autosave-C2mKZ-ua.js} +1 -1
  86. package/dist/gateway/static/root/assets/user-context-page-CHjIinCW.js +1 -0
  87. package/dist/gateway/static/root/assets/{voice-api-key-field-IMc3Ua6C.js → voice-api-key-field-D7OHeQby.js} +1 -1
  88. package/dist/gateway/static/root/assets/{work-discovery-overlay-TC-xQenr.js → work-discovery-overlay-CIiXie7F.js} +1 -1
  89. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-B2auxcRv.js → workflow-run-setup-panel-9_dAGW3_.js} +2 -2
  90. package/dist/gateway/static/root/assets/workflows-page-DXpYJxao.js +5 -0
  91. package/dist/gateway/static/root/index.html +15 -14
  92. package/dist/package.js +1 -1
  93. package/dist/src/agent/agent-instance-gateway.d.ts +3 -0
  94. package/dist/src/agent/agent-manager.d.ts +3 -0
  95. package/dist/src/agent/agent-manager.js +30 -24
  96. package/dist/src/agent/embedded/index.d.ts +1 -1
  97. package/dist/src/agent/embedded/index.js +2 -2
  98. package/dist/src/agent/embedded/run-for-session.js +101 -62
  99. package/dist/src/agent/embedded/run-turn.js +56 -28
  100. package/dist/src/agent/embedded/runs.d.ts +16 -29
  101. package/dist/src/agent/embedded/runs.js +44 -65
  102. package/dist/src/agent/embedded/types.d.ts +4 -0
  103. package/dist/src/agent/orchestration/agent-run-supervisor.d.ts +28 -0
  104. package/dist/src/agent/orchestration/agent-run-supervisor.js +49 -0
  105. package/dist/src/agent/orchestration/agent-turn-policy.d.ts +18 -0
  106. package/dist/src/agent/orchestration/agent-turn-policy.js +36 -0
  107. package/dist/src/agent/orchestration/llm-turn-retry.d.ts +5 -0
  108. package/dist/src/agent/orchestration/llm-turn-retry.js +34 -4
  109. package/dist/src/agent/orchestration/run-agent-turn-with-timeout.d.ts +10 -1
  110. package/dist/src/agent/orchestration/run-agent-turn-with-timeout.js +25 -4
  111. package/dist/src/agent/service/async-queue.d.ts +16 -3
  112. package/dist/src/agent/service/async-queue.js +29 -11
  113. package/dist/src/agent/service/process-direct-streaming.js +27 -4
  114. package/dist/src/agent/service.js +1 -0
  115. package/dist/src/agent/tools/exec-command.d.ts +2 -0
  116. package/dist/src/agent/tools/exec-command.js +70 -7
  117. package/dist/src/auth/oauth/index.js +3 -3
  118. package/dist/src/auth/oauth/registry.d.ts +2 -0
  119. package/dist/src/auth/oauth/registry.js +20 -12
  120. package/dist/src/auth/oauth/xopc-cloud.d.ts +1 -0
  121. package/dist/src/auth/oauth/xopc-cloud.js +32 -16
  122. package/dist/src/cli/commands/channels.js +1 -1
  123. package/dist/src/cli/commands/connectors.js +1 -1
  124. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  125. package/dist/src/cli/commands/models.js +1 -1
  126. package/dist/src/cli/commands/onboard.js +1 -1
  127. package/dist/src/cli/commands/tunnel.js +4 -5
  128. package/dist/src/config/agent-profile.js +1 -1
  129. package/dist/src/config/schema.d.ts +18 -0
  130. package/dist/src/config/schema.js +19 -1
  131. package/dist/src/extensions/sdk/index.js +1 -1
  132. package/dist/src/gateway/agents-admin.js +1 -1
  133. package/dist/src/gateway/hono/app.js +2 -1
  134. package/dist/src/gateway/hono/oauth-async.d.ts +1 -0
  135. package/dist/src/gateway/hono/oauth-async.js +11 -4
  136. package/dist/src/gateway/hono/routes/config.js +10 -0
  137. package/dist/src/gateway/hono/routes/host-fs.js +40 -1
  138. package/dist/src/gateway/hono/routes/media.js +33 -1
  139. package/dist/src/gateway/hono/routes/notes.js +162 -7
  140. package/dist/src/gateway/hono/routes/shares.js +141 -6
  141. package/dist/src/gateway/hono/routes/tunnel.js +47 -10
  142. package/dist/src/gateway/hono/routes/voice.d.ts +2 -6
  143. package/dist/src/gateway/hono/routes/voice.js +20 -4
  144. package/dist/src/gateway/hono/routes/workflows.js +2 -2
  145. package/dist/src/gateway/run-loop.js +3 -0
  146. package/dist/src/gateway/server.d.ts +3 -0
  147. package/dist/src/gateway/server.js +30 -5
  148. package/dist/src/gateway/service.js +4 -4
  149. package/dist/src/notes/service.d.ts +6 -2
  150. package/dist/src/notes/service.js +36 -4
  151. package/dist/src/providers/index.js +2 -2
  152. package/dist/src/share/note-share-service.d.ts +67 -0
  153. package/dist/src/share/note-share-service.js +283 -0
  154. package/dist/src/share/share-config.js +32 -3
  155. package/dist/src/share/share-landing.d.ts +5 -1
  156. package/dist/src/share/share-landing.js +28 -1
  157. package/dist/src/share/share-store.d.ts +34 -5
  158. package/dist/src/share/share-store.js +125 -19
  159. package/dist/src/share/share-thumbnail.js +4 -2
  160. package/dist/src/share/share-types.d.ts +52 -14
  161. package/dist/src/share/share-types.js +9 -0
  162. package/dist/src/share/share-zip.d.ts +2 -2
  163. package/dist/src/tui/backends/embedded-backend.js +1 -1
  164. package/dist/src/tunnel/env.d.ts +12 -6
  165. package/dist/src/tunnel/env.js +34 -26
  166. package/dist/src/tunnel/gateway-lifecycle.js +2 -13
  167. package/dist/src/tunnel/index.d.ts +1 -1
  168. package/dist/src/tunnel/index.js +2 -2
  169. package/dist/src/tunnel/tunnel-audit.d.ts +1 -1
  170. package/dist/src/tunnel/tunnel-config.d.ts +1 -1
  171. package/dist/src/tunnel/tunnel-config.js +9 -4
  172. package/dist/src/tunnel/tunnel-service.d.ts +1 -1
  173. package/dist/src/tunnel/tunnel-service.js +3 -0
  174. package/dist/src/tunnel/well-known.d.ts +1 -1
  175. package/dist/src/tunnel/well-known.js +1 -1
  176. package/dist/src/tunnel/xopc-cloud-registration.d.ts +9 -0
  177. package/dist/src/tunnel/xopc-cloud-registration.js +42 -0
  178. package/dist/src/voice/stt/transcribe-core.js +17 -1
  179. package/dist/src/voice/stt/types.d.ts +1 -1
  180. package/package.json +2 -2
  181. package/dist/gateway/static/root/assets/agents-DijFbC4G.js +0 -68
  182. package/dist/gateway/static/root/assets/apps-page-BFAmf9hq.js +0 -1
  183. package/dist/gateway/static/root/assets/automations-workspace-B8us5JBf.js +0 -6
  184. package/dist/gateway/static/root/assets/block-editor-C3mwGsms.js +0 -184
  185. package/dist/gateway/static/root/assets/browser-settings-page-BeBd17-3.js +0 -8
  186. package/dist/gateway/static/root/assets/capabilities-settings-panel-Bv0z3KRq.js +0 -7
  187. package/dist/gateway/static/root/assets/capability-presets-settings-panel-BczD-pWE.js +0 -3
  188. package/dist/gateway/static/root/assets/channels-settings-2KQYq6xl.js +0 -1
  189. package/dist/gateway/static/root/assets/channels-status-swr-ByRbxC6z.js +0 -1
  190. package/dist/gateway/static/root/assets/connectors-page-PB1boaNy.js +0 -2
  191. package/dist/gateway/static/root/assets/dist-C230izr8.js +0 -1
  192. package/dist/gateway/static/root/assets/heartbeat-settings-5YQ5BUwp.js +0 -1
  193. package/dist/gateway/static/root/assets/home-page-DfIVWJl3.js +0 -1
  194. package/dist/gateway/static/root/assets/index-BXGC3VFm.css +0 -2
  195. package/dist/gateway/static/root/assets/index-jqDCfet4.js +0 -74
  196. package/dist/gateway/static/root/assets/local-app-workbench-page-CAb0odzu.js +0 -2
  197. package/dist/gateway/static/root/assets/logs-page-CFxKbDZl.js +0 -2
  198. package/dist/gateway/static/root/assets/markdown-view-DYkxMtJA.js +0 -69
  199. package/dist/gateway/static/root/assets/messages-kx5W39dO.js +0 -3
  200. package/dist/gateway/static/root/assets/notes-api-DJizatxh.js +0 -1
  201. package/dist/gateway/static/root/assets/notes-workbench-BGjEC89c.js +0 -4
  202. package/dist/gateway/static/root/assets/project-detail-page-Dj9kEQwg.js +0 -1
  203. package/dist/gateway/static/root/assets/projects-page-CBRy5Ezz.js +0 -1
  204. package/dist/gateway/static/root/assets/remote-access-hub-DSwz9RBh.js +0 -1
  205. package/dist/gateway/static/root/assets/sessions-page-WtattyVX.js +0 -1
  206. package/dist/gateway/static/root/assets/settings-advanced-gate-CNAz_q1F.js +0 -1
  207. package/dist/gateway/static/root/assets/setup-status-panel-CNo4Ajhn.js +0 -1
  208. package/dist/gateway/static/root/assets/share-preview-page-B7PI3yZ6.js +0 -2
  209. package/dist/gateway/static/root/assets/shares-settings-DpOH0zWB.js +0 -1
  210. package/dist/gateway/static/root/assets/skill-reload-api-BOf4xCat.js +0 -1
  211. package/dist/gateway/static/root/assets/task-detail-page-DrMX5Yhj.js +0 -1
  212. package/dist/gateway/static/root/assets/user-context-page-ewIK2ddC.js +0 -1
  213. package/dist/gateway/static/root/assets/workflows-page-Bdn82kFQ.js +0 -5
@@ -9,11 +9,12 @@ import { init_kimi_coding, kimiCodingOAuthProvider } from "./kimi-coding.js";
9
9
  import { init_minimax_cn, minimaxCnOAuthProvider } from "./minimax-cn.js";
10
10
  import { init_minimax, minimaxOAuthProvider } from "./minimax.js";
11
11
  import { init_openai_codex, openaiCodexOAuthProvider } from "./openai-codex.js";
12
- import { init_xopc_cloud, xopcCloudOAuthProvider } from "./xopc-cloud.js";
12
+ import { init_xopc_cloud, xopcCloudOAuthProvider, xopcTunnelOAuthProvider } from "./xopc-cloud.js";
13
13
  //#region src/auth/oauth/registry.ts
14
- function definition(provider, displayName = provider.name) {
14
+ function definition(provider, purpose, displayName = provider.name) {
15
15
  return {
16
16
  displayName,
17
+ purpose,
17
18
  provider,
18
19
  profileId: `${provider.id}:default`,
19
20
  urlPrompt: "🌐 Please open this URL in your browser:\n"
@@ -28,6 +29,9 @@ function getOAuthProviderInterfaces() {
28
29
  function getOAuthProviderIds() {
29
30
  return Object.keys(OAUTH_PROVIDER_DEFINITIONS);
30
31
  }
32
+ function getModelOAuthProviderIds() {
33
+ return Object.entries(OAUTH_PROVIDER_DEFINITIONS).filter(([, definition]) => definition.purpose === "models").map(([id]) => id);
34
+ }
31
35
  function isOAuthOnlyProvider(provider) {
32
36
  return OAUTH_PROVIDER_DEFINITIONS[provider]?.oauthOnly === true;
33
37
  }
@@ -44,22 +48,26 @@ var init_registry = __esmMin((() => {
44
48
  init_xopc_cloud();
45
49
  OAUTH_PROVIDER_DEFINITIONS = {
46
50
  "xopc-cloud": {
47
- ...definition(xopcCloudOAuthProvider),
51
+ ...definition(xopcCloudOAuthProvider, "models"),
52
+ oauthOnly: true
53
+ },
54
+ "xopc-tunnel": {
55
+ ...definition(xopcTunnelOAuthProvider, "tunnel"),
48
56
  oauthOnly: true
49
57
  },
50
- anthropic: definition(anthropicOAuthProvider, "Anthropic (Claude)"),
51
- minimax: definition(minimaxOAuthProvider, "MiniMax (幂维智能)"),
58
+ anthropic: definition(anthropicOAuthProvider, "models", "Anthropic (Claude)"),
59
+ minimax: definition(minimaxOAuthProvider, "models", "MiniMax (幂维智能)"),
52
60
  "minimax-cn": {
53
- ...definition(minimaxCnOAuthProvider, "MiniMax CN"),
61
+ ...definition(minimaxCnOAuthProvider, "models", "MiniMax CN"),
54
62
  urlPrompt: "🌐 请在浏览器中打开以下 URL:\n"
55
63
  },
56
- "kimi-coding": definition(kimiCodingOAuthProvider, "Kimi For Coding (月之暗面)"),
57
- "github-copilot": definition(githubCopilotOAuthProvider),
58
- "google-gemini-cli": definition(geminiCliOAuthProvider),
59
- "google-antigravity": definition(antigravityOAuthProvider),
60
- "openai-codex": definition(openaiCodexOAuthProvider)
64
+ "kimi-coding": definition(kimiCodingOAuthProvider, "models", "Kimi For Coding (月之暗面)"),
65
+ "github-copilot": definition(githubCopilotOAuthProvider, "models"),
66
+ "google-gemini-cli": definition(geminiCliOAuthProvider, "models"),
67
+ "google-antigravity": definition(antigravityOAuthProvider, "models"),
68
+ "openai-codex": definition(openaiCodexOAuthProvider, "models")
61
69
  };
62
70
  }));
63
71
  //#endregion
64
72
  init_registry();
65
- export { OAUTH_PROVIDER_DEFINITIONS, getOAuthProviderDefinition, getOAuthProviderIds, getOAuthProviderInterfaces, init_registry, isOAuthOnlyProvider };
73
+ export { OAUTH_PROVIDER_DEFINITIONS, getModelOAuthProviderIds, getOAuthProviderDefinition, getOAuthProviderIds, getOAuthProviderInterfaces, init_registry, isOAuthOnlyProvider };
@@ -1,2 +1,3 @@
1
1
  import type { OAuthProviderInterface } from './types.js';
2
2
  export declare const xopcCloudOAuthProvider: OAuthProviderInterface;
3
+ export declare const xopcTunnelOAuthProvider: OAuthProviderInterface;
@@ -213,7 +213,7 @@ function callbackHtml(title, message, tone, returnToAppUrl) {
213
213
  </body>
214
214
  </html>`;
215
215
  }
216
- async function loginWithBrowser(callbacks) {
216
+ async function loginWithBrowser(callbacks, scope) {
217
217
  if (callbacks.signal?.aborted) throw callbacks.signal.reason instanceof Error ? callbacks.signal.reason : /* @__PURE__ */ new Error("XOPC OAuth login cancelled");
218
218
  const { verifier, challenge } = await generatePKCE();
219
219
  const state = randomBytes(24).toString("base64url");
@@ -274,7 +274,7 @@ async function loginWithBrowser(callbacks) {
274
274
  response_type: "code",
275
275
  client_id: CLIENT_ID,
276
276
  redirect_uri: redirectUri,
277
- scope: DEFAULT_SCOPE,
277
+ scope,
278
278
  code_challenge: challenge,
279
279
  code_challenge_method: "S256",
280
280
  state,
@@ -309,7 +309,7 @@ async function loginWithBrowser(callbacks) {
309
309
  server.close();
310
310
  }
311
311
  }
312
- async function loginWithDeviceCode(callbacks) {
312
+ async function loginWithDeviceCode(callbacks, scope) {
313
313
  const response = await fetch(`${consoleUrl()}/oauth/device_authorization`, {
314
314
  method: "POST",
315
315
  headers: {
@@ -318,7 +318,7 @@ async function loginWithDeviceCode(callbacks) {
318
318
  },
319
319
  body: new URLSearchParams({
320
320
  client_id: CLIENT_ID,
321
- scope: DEFAULT_SCOPE,
321
+ scope,
322
322
  device_name: hostname() || "XOPC client",
323
323
  client_type: "cli"
324
324
  }),
@@ -353,9 +353,9 @@ async function loginWithDeviceCode(callbacks) {
353
353
  }
354
354
  throw new Error("XOPC OAuth authorization expired");
355
355
  }
356
- async function login(callbacks) {
356
+ async function login(callbacks, options) {
357
357
  return await callbacks.onSelect({
358
- message: "Choose how to authorize XOPC Model Service",
358
+ message: `Choose how to authorize ${options.serviceName}`,
359
359
  options: [{
360
360
  id: "browser",
361
361
  label: "Browser (recommended for this device)"
@@ -363,7 +363,7 @@ async function login(callbacks) {
363
363
  id: "device_code",
364
364
  label: "Device code (remote or headless)"
365
365
  }]
366
- }) === "device_code" ? loginWithDeviceCode(callbacks) : loginWithBrowser(callbacks);
366
+ }) === "device_code" ? loginWithDeviceCode(callbacks, options.scope) : loginWithBrowser(callbacks, options.scope);
367
367
  }
368
368
  async function refreshToken(current, signal) {
369
369
  const response = await tokenRequest(new URLSearchParams({
@@ -375,23 +375,39 @@ async function refreshToken(current, signal) {
375
375
  if (!response.ok) throw new Error(body.error_description ?? body.error ?? "XOPC OAuth refresh failed");
376
376
  return credentials(body);
377
377
  }
378
- var CLIENT_ID, DEFAULT_CONSOLE_URL, DEFAULT_SCOPE, CALLBACK_PATH, AUTHORIZATION_TIMEOUT_MS, xopcCloudOAuthProvider;
378
+ function createXopcOAuthProvider(options) {
379
+ return {
380
+ id: options.id,
381
+ name: options.name,
382
+ loginMethods: ["browser", "device_code"],
383
+ login: (callbacks) => login(callbacks, {
384
+ scope: options.scope,
385
+ serviceName: options.name
386
+ }),
387
+ refreshToken,
388
+ getApiKey: (value) => value.access
389
+ };
390
+ }
391
+ var CLIENT_ID, DEFAULT_CONSOLE_URL, MODEL_SERVICE_SCOPE, TUNNEL_REGISTRATION_SCOPE, CALLBACK_PATH, AUTHORIZATION_TIMEOUT_MS, xopcCloudOAuthProvider, xopcTunnelOAuthProvider;
379
392
  var init_xopc_cloud = __esmMin((() => {
380
393
  init_pkce();
381
394
  CLIENT_ID = "xopc-native";
382
395
  DEFAULT_CONSOLE_URL = "https://console.xopc.ai";
383
- DEFAULT_SCOPE = "models:read models:invoke account:usage connectors:read connectors:manage connectors:execute offline_access";
396
+ MODEL_SERVICE_SCOPE = "models:read models:invoke account:usage connectors:read connectors:manage connectors:execute offline_access";
397
+ TUNNEL_REGISTRATION_SCOPE = "tunnel:register";
384
398
  CALLBACK_PATH = "/oauth/callback";
385
399
  AUTHORIZATION_TIMEOUT_MS = 5 * 6e4;
386
- xopcCloudOAuthProvider = {
400
+ xopcCloudOAuthProvider = createXopcOAuthProvider({
387
401
  id: "xopc-cloud",
388
402
  name: "XOPC Model Service",
389
- loginMethods: ["browser", "device_code"],
390
- login,
391
- refreshToken,
392
- getApiKey: (value) => value.access
393
- };
403
+ scope: MODEL_SERVICE_SCOPE
404
+ });
405
+ xopcTunnelOAuthProvider = createXopcOAuthProvider({
406
+ id: "xopc-tunnel",
407
+ name: "XOPC Public Tunnel",
408
+ scope: TUNNEL_REGISTRATION_SCOPE
409
+ });
394
410
  }));
395
411
  //#endregion
396
412
  init_xopc_cloud();
397
- export { init_xopc_cloud, xopcCloudOAuthProvider };
413
+ export { init_xopc_cloud, xopcCloudOAuthProvider, xopcTunnelOAuthProvider };
@@ -1,8 +1,8 @@
1
1
  import { buildChannelCatalogForConfig, init_channel_catalog_service } from "../../channels/catalog/channel-catalog-service.js";
2
2
  import { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
3
+ import { formatExamples, register } from "../registry.js";
3
4
  import { listChannelPairingState } from "../../channels/pairing/pairing-service.js";
4
5
  import { approveChannelPairingFromCli } from "../../channels/pairing/approve-cli.js";
5
- import { formatExamples, register } from "../registry.js";
6
6
  import { colors } from "../utils/colors.js";
7
7
  import { Command } from "commander";
8
8
  //#region src/cli/commands/channels.ts
@@ -1,8 +1,8 @@
1
1
  import { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
2
2
  import { getStoreConnectorInstallPlan, installStoreConnector, listStoreConnectors } from "../../capabilities/store-connector.js";
3
3
  import { register } from "../registry.js";
4
- import { confirm } from "@inquirer/prompts";
5
4
  import { Command } from "commander";
5
+ import { confirm } from "@inquirer/prompts";
6
6
  //#region src/cli/commands/connectors.ts
7
7
  init_loader();
8
8
  function parsePairs(values, option) {
@@ -13,8 +13,8 @@ import { existsSync, readFileSync, rmSync, statSync } from "node:fs";
13
13
  import { execSync } from "node:child_process";
14
14
  import { createHash } from "node:crypto";
15
15
  import semver from "semver";
16
- import { confirm } from "@inquirer/prompts";
17
16
  import { Command } from "commander";
17
+ import { confirm } from "@inquirer/prompts";
18
18
  //#region src/cli/commands/extension-marketplace.ts
19
19
  init_loader();
20
20
  init_paths();
@@ -9,8 +9,8 @@ import { prepareUpdateGlobalDefaults } from "../../gateway/global-defaults-admin
9
9
  import { disconnectProvider } from "../../providers/provider-disconnect.js";
10
10
  import { colors } from "../utils/colors.js";
11
11
  import { runCliOAuthLogin } from "../utils/oauth-login.js";
12
- import { input } from "@inquirer/prompts";
13
12
  import { Command } from "commander";
13
+ import { input } from "@inquirer/prompts";
14
14
  //#region src/cli/commands/models.ts
15
15
  init_credentials();
16
16
  init_schema();
@@ -10,8 +10,8 @@ import { initWorkspace } from "../utils/init-workspace.js";
10
10
  import { setupModel } from "./onboard/model.js";
11
11
  import { getChannelConfigurators } from "./onboard/channels/registry.js";
12
12
  import { setupChannels } from "./onboard/channels/index.js";
13
- import { select } from "@inquirer/prompts";
14
13
  import { Command } from "commander";
14
+ import { select } from "@inquirer/prompts";
15
15
  //#region src/cli/commands/onboard.ts
16
16
  init_schema();
17
17
  init_paths_state();
@@ -38,7 +38,7 @@ function configureTunnel(ctx) {
38
38
  const brokerUrl = resolveTunnelBrokerUrl(config.tunnel?.brokerUrl);
39
39
  getTunnelService().configure({
40
40
  brokerUrl,
41
- registrationSecret: resolveTunnelRegistrationSecret(process.env, brokerUrl, config.tunnel?.registrationSecret),
41
+ registrationSecret: resolveTunnelRegistrationSecret(brokerUrl, config.tunnel?.registrationSecret),
42
42
  autoStart: config.tunnel?.autoStart ?? false,
43
43
  gatewayHost: host,
44
44
  frpSubdomainHost: resolveFrpSubdomainHost(resolveTunnelBrokerUrl(config.tunnel?.brokerUrl))
@@ -131,13 +131,12 @@ function createTunnelCommand(ctx) {
131
131
  });
132
132
  console.log("Tunnel security consent recorded.");
133
133
  });
134
- cmd.command("secret").description("Manage tunnel broker registration secret in config").command("set").description("Save tunnel.registrationSecret to xopc.json (env XOPC_TUNNEL_REGISTRATION_SECRET overrides at runtime)").argument("[secret]", "Registration secret (prompts securely when omitted in a TTY)").option("--stdin", "Read secret from stdin (single line, trimmed)").action(async (secretArg, opts) => {
134
+ cmd.command("secret").description("Manage tunnel broker registration secret in config").command("set").description("Save tunnel.registrationSecret to xopc.json").argument("[secret]", "Registration secret (prompts securely when omitted in a TTY)").option("--stdin", "Read secret from stdin (single line, trimmed)").action(async (secretArg, opts) => {
135
135
  try {
136
136
  await saveTunnelRegistrationSecret(ctx, await readTunnelRegistrationSecretFromCli({
137
137
  secretArg,
138
138
  stdin: opts.stdin
139
139
  }));
140
- if (process.env.XOPC_TUNNEL_REGISTRATION_SECRET?.trim()) console.log("Note: XOPC_TUNNEL_REGISTRATION_SECRET is set in the environment and overrides the saved config at runtime.");
141
140
  console.log(`Saved tunnel registration secret to ${ctx.configPath}.`);
142
141
  } catch (err) {
143
142
  const em = err instanceof Error ? err.message : String(err);
@@ -227,7 +226,7 @@ function createTunnelCommand(ctx) {
227
226
  console.log(`# Self-hosted FRP broker sketch for ${domain}`);
228
227
  console.log("# 1. Run frps with vhost HTTP/HTTPS and a registration token");
229
228
  console.log(`# 2. Point tunnel.brokerUrl to https://${domain}/api`);
230
- console.log(`# 3. Set XOPC_TUNNEL_REGISTRATION_SECRET in the gateway environment`);
229
+ console.log("# 3. Save the broker registration key as tunnel.registrationSecret");
231
230
  console.log("");
232
231
  console.log(JSON.stringify({
233
232
  frps: {
@@ -237,7 +236,7 @@ function createTunnelCommand(ctx) {
237
236
  },
238
237
  broker: {
239
238
  apiUrl: `https://${domain}/api`,
240
- registrationSecretEnv: "XOPC_TUNNEL_REGISTRATION_SECRET"
239
+ registrationSecretConfig: "tunnel.registrationSecret"
241
240
  }
242
241
  }, null, 2));
243
242
  }));
@@ -1,6 +1,6 @@
1
- import { init_agent_scope, normalizeAgentId, resolveAgentWorkspaceDir } from "../agent/agent-scope.js";
2
1
  import { resolveEffectiveAgentManifest } from "../agent-manifest/resolver.js";
3
2
  import "../agent-manifest/index.js";
3
+ import { init_agent_scope, normalizeAgentId, resolveAgentWorkspaceDir } from "../agent/agent-scope.js";
4
4
  import { init_session_key, parseSessionKey } from "../routing/session-key.js";
5
5
  import { agentExists, getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
6
6
  //#region src/config/agent-profile.ts
@@ -991,6 +991,15 @@ export declare const GatewayConfigSchema: z.ZodDefault<z.ZodObject<{
991
991
  listingCacheMs: z.ZodDefault<z.ZodNumber>;
992
992
  zipConcurrency: z.ZodDefault<z.ZodNumber>;
993
993
  }, z.core.$strip>>;
994
+ note: z.ZodDefault<z.ZodObject<{
995
+ enabled: z.ZodDefault<z.ZodBoolean>;
996
+ maxMarkdownBytes: z.ZodDefault<z.ZodNumber>;
997
+ maxAttachmentCount: z.ZodDefault<z.ZodNumber>;
998
+ maxAttachmentSize: z.ZodDefault<z.ZodNumber>;
999
+ maxTotalSize: z.ZodDefault<z.ZodNumber>;
1000
+ assetTicketTtlMs: z.ZodDefault<z.ZodNumber>;
1001
+ revokeOnSourceDelete: z.ZodDefault<z.ZodBoolean>;
1002
+ }, z.core.$strip>>;
994
1003
  }, z.core.$strip>>;
995
1004
  siteShare: z.ZodOptional<z.ZodObject<{
996
1005
  enabled: z.ZodDefault<z.ZodBoolean>;
@@ -2067,6 +2076,15 @@ export declare const ConfigSchema: z.ZodDefault<z.ZodObject<{
2067
2076
  listingCacheMs: z.ZodDefault<z.ZodNumber>;
2068
2077
  zipConcurrency: z.ZodDefault<z.ZodNumber>;
2069
2078
  }, z.core.$strip>>;
2079
+ note: z.ZodDefault<z.ZodObject<{
2080
+ enabled: z.ZodDefault<z.ZodBoolean>;
2081
+ maxMarkdownBytes: z.ZodDefault<z.ZodNumber>;
2082
+ maxAttachmentCount: z.ZodDefault<z.ZodNumber>;
2083
+ maxAttachmentSize: z.ZodDefault<z.ZodNumber>;
2084
+ maxTotalSize: z.ZodDefault<z.ZodNumber>;
2085
+ assetTicketTtlMs: z.ZodDefault<z.ZodNumber>;
2086
+ revokeOnSourceDelete: z.ZodDefault<z.ZodBoolean>;
2087
+ }, z.core.$strip>>;
2070
2088
  }, z.core.$strip>>;
2071
2089
  siteShare: z.ZodOptional<z.ZodObject<{
2072
2090
  enabled: z.ZodDefault<z.ZodBoolean>;
@@ -490,7 +490,7 @@ strict: z.boolean().optional() }).optional();
490
490
  TunnelConfigSchema = z.object({
491
491
  enabled: z.boolean().default(false),
492
492
  brokerUrl: z.string().url().default("https://frp.xopc.ai/api"),
493
- /** Broker register API secret (env `XOPC_TUNNEL_REGISTRATION_SECRET` overrides when set). */
493
+ /** Broker register API secret. */
494
494
  registrationSecret: z.string().min(1).optional(),
495
495
  autoStart: z.boolean().default(false),
496
496
  subdomain: z.string().optional(),
@@ -620,6 +620,24 @@ activityDetailDefault: z.enum([
620
620
  maxDepth: 20,
621
621
  listingCacheMs: 6e4,
622
622
  zipConcurrency: 1
623
+ }),
624
+ /** Note snapshot-sharing controls. */
625
+ note: z.object({
626
+ enabled: z.boolean().default(true),
627
+ maxMarkdownBytes: z.number().int().min(1024).max(10485760).default(2097152),
628
+ maxAttachmentCount: z.number().int().min(0).max(500).default(50),
629
+ maxAttachmentSize: z.number().int().min(1024).max(1073741824).default(104857600),
630
+ maxTotalSize: z.number().int().min(1024).max(2147483648).default(262144e3),
631
+ assetTicketTtlMs: z.number().int().min(6e4).max(36e5).default(6e5),
632
+ revokeOnSourceDelete: z.boolean().default(true)
633
+ }).default({
634
+ enabled: true,
635
+ maxMarkdownBytes: 2097152,
636
+ maxAttachmentCount: 50,
637
+ maxAttachmentSize: 104857600,
638
+ maxTotalSize: 262144e3,
639
+ assetTicketTtlMs: 6e5,
640
+ revokeOnSourceDelete: true
623
641
  })
624
642
  }).optional(),
625
643
  /** Site-share configuration (static directory or reverse-proxy a local dev server). */
@@ -7,8 +7,8 @@ import { SlotRegistry, getSlotRegistry, registerSlotType } from "../slots.js";
7
7
  import { ExtensionDiagnostics, ExtensionLoaderCacheImpl, getExtensionCache, getExtensionDiagnostics } from "../diagnostics.js";
8
8
  import "../loader.js";
9
9
  import { ExtensionHookRunner, createHookContext, isHookEvent } from "../hooks.js";
10
- import { defineChannelPluginEntry } from "./channel-entry.js";
11
10
  import { registerExtensionCliProgram } from "./channel-helpers.js";
11
+ import { defineChannelPluginEntry } from "./channel-entry.js";
12
12
  import { lazyFunction, lazyModule } from "./lazy.js";
13
13
  import { createMockExtensionApi, createTestGateway } from "./testing.js";
14
14
  //#region src/extensions/sdk/index.ts
@@ -1,5 +1,5 @@
1
- import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentDir, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId, resolveUserPath, validateAgentIdForNewAgent } from "../agent/agent-scope.js";
2
1
  import { resolveCapabilityPresetLayer, resolveEffectiveAgentManifest } from "../agent-manifest/resolver.js";
2
+ import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentDir, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId, resolveUserPath, validateAgentIdForNewAgent } from "../agent/agent-scope.js";
3
3
  import { resolveEffectiveAgentProfile } from "../config/agent-profile.js";
4
4
  import { WORKSPACE_FILES, init_paths } from "../config/paths.js";
5
5
  import { AGENT_PROFILE_MARKDOWN_SYSTEM_FILES, REQUIRED_AGENT_PROFILE_MARKDOWN_FILE_SET } from "../agent/context/workspace.js";
@@ -147,6 +147,7 @@ function createHonoApp(config) {
147
147
  const DEFAULT_API_BODY_MAX = 1 * 1024 * 1024;
148
148
  const SKILL_UPLOAD_BODY_MAX = 10 * 1024 * 1024;
149
149
  const NOTE_MEDIA_BODY_MAX = 25 * 1024 * 1024;
150
+ const MEDIA_UPLOAD_BODY_MAX = 33 * 1024 * 1024;
150
151
  const VOICE_TRANSCRIBE_BODY_MAX = 26 * 1024 * 1024;
151
152
  const SESSION_INPUT_BODY_MAX = maxSessionInputRequestBodyBytes();
152
153
  const isNoteMediaUploadRequest = (path, method, contentType) => {
@@ -175,7 +176,7 @@ function createHonoApp(config) {
175
176
  }));
176
177
  app.use("/api/*", async (c, next) => {
177
178
  const contentType = c.req.header("content-type");
178
- const maxSize = c.req.method === "POST" && c.req.path === "/api/tasks" || c.req.method === "POST" && /^\/api\/sessions\/[^/]+\/inputs$/.test(c.req.path) || c.req.method === "POST" && /^\/api\/tasks\/[^/]+\/inputs$/.test(c.req.path) || c.req.method === "PATCH" && /^\/api\/sessions\/[^/]+\/inputs\/[^/]+$/.test(c.req.path) ? SESSION_INPUT_BODY_MAX : c.req.path === "/api/skills/upload" ? SKILL_UPLOAD_BODY_MAX : c.req.path === "/api/voice/transcriptions" ? VOICE_TRANSCRIBE_BODY_MAX : isNoteMediaUploadRequest(c.req.path, c.req.method, contentType) ? NOTE_MEDIA_BODY_MAX : isProjectFileUploadRequest(c.req.path, c.req.method, contentType) ? NOTE_MEDIA_BODY_MAX : discussionUploadBodyMax(c.req.path, c.req.method, contentType) ?? DEFAULT_API_BODY_MAX;
179
+ const maxSize = c.req.method === "POST" && c.req.path === "/api/tasks" || c.req.method === "POST" && /^\/api\/sessions\/[^/]+\/inputs$/.test(c.req.path) || c.req.method === "POST" && /^\/api\/tasks\/[^/]+\/inputs$/.test(c.req.path) || c.req.method === "PATCH" && /^\/api\/sessions\/[^/]+\/inputs\/[^/]+$/.test(c.req.path) ? SESSION_INPUT_BODY_MAX : c.req.path === "/api/skills/upload" ? SKILL_UPLOAD_BODY_MAX : c.req.path === "/api/voice/transcriptions" ? VOICE_TRANSCRIBE_BODY_MAX : c.req.path === "/api/media" && c.req.method === "POST" ? MEDIA_UPLOAD_BODY_MAX : isNoteMediaUploadRequest(c.req.path, c.req.method, contentType) ? NOTE_MEDIA_BODY_MAX : isProjectFileUploadRequest(c.req.path, c.req.method, contentType) ? NOTE_MEDIA_BODY_MAX : discussionUploadBodyMax(c.req.path, c.req.method, contentType) ?? DEFAULT_API_BODY_MAX;
179
180
  const maxSizeMb = Math.ceil(maxSize / (1024 * 1024));
180
181
  return bodyLimit({
181
182
  maxSize,
@@ -23,6 +23,7 @@ export interface OAuthCompletionReadiness {
23
23
  export declare function buildOAuthCompletionReadiness(config: Config, catalog: CatalogReadiness): OAuthCompletionReadiness;
24
24
  export declare function refreshModelCatalogAfterOAuth(provider: string, service: Pick<GatewayService, 'getModelCatalogSync'>): Promise<CatalogReadiness | undefined>;
25
25
  export declare function normalizeDesktopOAuthReturnPath(value: unknown): string | undefined;
26
+ export declare function buildDesktopOAuthReturnUrl(provider: string, sessionId: string, returnPath: unknown): string | undefined;
26
27
  export declare function resolveOAuthLoginMethodPreference(params: {
27
28
  requestedMethod?: unknown;
28
29
  supportedMethods?: readonly string[];
@@ -82,11 +82,17 @@ function normalizeDesktopOAuthReturnPath(value) {
82
82
  if (path.length === 0 || path.length > 2048 || !path.startsWith("/") || path.startsWith("//") || path.includes("\\") || /[\u0000-\u001f\u007f]/.test(path)) return;
83
83
  return path;
84
84
  }
85
- function desktopOAuthReturnUrl(sessionId, returnPath) {
85
+ const DESKTOP_OAUTH_CALLBACK_PATHS = {
86
+ "xopc-cloud": "model-connected",
87
+ "xopc-tunnel": "tunnel-connected"
88
+ };
89
+ function buildDesktopOAuthReturnUrl(provider, sessionId, returnPath) {
90
+ const callbackPath = DESKTOP_OAUTH_CALLBACK_PATHS[provider];
91
+ if (!callbackPath) return void 0;
86
92
  const params = new URLSearchParams({ request_id: sessionId });
87
93
  const normalizedReturnPath = normalizeDesktopOAuthReturnPath(returnPath);
88
94
  if (normalizedReturnPath) params.set("return_path", normalizedReturnPath);
89
- return `xopc://cloud/model-connected?${params.toString()}`;
95
+ return `xopc://cloud/${callbackPath}?${params.toString()}`;
90
96
  }
91
97
  function cancelOAuthSession(session, message = "OAuth flow cancelled") {
92
98
  if (session.abortController) session.abortController.abort();
@@ -142,10 +148,11 @@ function createOAuthAsyncHandler(service) {
142
148
  const oauthProvider = OAUTH_PROVIDERS[provider];
143
149
  if (!oauthProvider) return c.json({ error: `Unknown OAuth provider: ${provider}` }, 400);
144
150
  const sessionId = generateSessionId();
151
+ const returnToAppUrl = body.client === "desktop" ? buildDesktopOAuthReturnUrl(provider, sessionId, body.returnPath) : void 0;
145
152
  const session = {
146
153
  id: sessionId,
147
154
  provider,
148
- ...body.client === "desktop" && provider === "xopc-cloud" ? { returnToAppUrl: desktopOAuthReturnUrl(sessionId, body.returnPath) } : {},
155
+ ...returnToAppUrl ? { returnToAppUrl } : {},
149
156
  preferredLoginMethod: preferredOAuthLoginMethod({
150
157
  provider,
151
158
  requestedMethod: body.loginMethod,
@@ -378,4 +385,4 @@ async function runOAuthFlow(session, oauthProvider, service) {
378
385
  }
379
386
  }
380
387
  //#endregion
381
- export { buildOAuthCompletionReadiness, createOAuthAsyncHandler, normalizeDesktopOAuthReturnPath, refreshModelCatalogAfterOAuth, resolveOAuthLoginMethodPreference };
388
+ export { buildDesktopOAuthReturnUrl, buildOAuthCompletionReadiness, createOAuthAsyncHandler, normalizeDesktopOAuthReturnPath, refreshModelCatalogAfterOAuth, resolveOAuthLoginMethodPreference };
@@ -1,4 +1,5 @@
1
1
  import { enumerateLanGatewayCandidates } from "../../host.js";
2
+ import { getTunnelService } from "../../../tunnel/tunnel-service.js";
2
3
  import { prepareLocalVoiceModelAfterProviderSwitch } from "../../../voice/local/provider-switch.js";
3
4
  import { buildSafeWebConfigPayload } from "../lib/config-payload.js";
4
5
  import { applyAgentsPatch } from "./config-patch/agents.js";
@@ -70,6 +71,15 @@ function registerConfigRoutes(authenticated, deps) {
70
71
  ok: false,
71
72
  error: finalGwCheck.error
72
73
  }, finalGwCheck.status);
74
+ if (body?.tunnel && typeof body.tunnel === "object" && !Array.isArray(body.tunnel) && body.tunnel.registrationSecret === null) try {
75
+ await getTunnelService().stop();
76
+ } catch (err) {
77
+ const message = err instanceof Error ? err.message : String(err);
78
+ return c.json({
79
+ ok: false,
80
+ error: `Failed to stop tunnel before clearing key: ${message}`
81
+ }, 500);
82
+ }
73
83
  const result = await service.saveConfig(config);
74
84
  if (!result.saved) return c.json({
75
85
  ok: false,
@@ -1,7 +1,7 @@
1
1
  import { createGatewayRouteLogger } from "../lib/route-logger.js";
2
2
  import * as os$1 from "node:os";
3
3
  import * as path$1 from "node:path";
4
- import { readdir, realpath, stat } from "node:fs/promises";
4
+ import { mkdir, readdir, realpath, stat } from "node:fs/promises";
5
5
  //#region src/gateway/hono/routes/host-fs.ts
6
6
  const log = createGatewayRouteLogger("HostFs");
7
7
  function jsonError(status, message) {
@@ -172,6 +172,45 @@ function registerHostFsRoutes(authenticated, _deps) {
172
172
  return jsonError(500, msg || "Failed to read directory");
173
173
  }
174
174
  });
175
+ /** Create one directory below an existing absolute directory on the gateway host. */
176
+ authenticated.post("/api/host/fs/directory", async (c) => {
177
+ const body = await c.req.json().catch(() => null);
178
+ const parentPath = body && typeof body === "object" && typeof body.parentPath === "string" ? body.parentPath.trim() : "";
179
+ const name = body && typeof body === "object" && typeof body.name === "string" ? body.name.trim() : "";
180
+ if (!parentPath || !path$1.isAbsolute(parentPath)) return jsonError(400, "An absolute parent path is required");
181
+ if (!name || name === "." || name === ".." || name.includes("/") || name.includes("\\") || name.includes("\0") || name.length > 255) return jsonError(400, "Invalid folder name");
182
+ let resolvedParent;
183
+ try {
184
+ resolvedParent = await realpath(path$1.normalize(parentPath));
185
+ if (!(await stat(resolvedParent)).isDirectory()) return jsonError(400, "Parent path is not a directory");
186
+ } catch (err) {
187
+ log.warn({
188
+ err,
189
+ path: parentPath
190
+ }, "Host fs create parent lookup failed");
191
+ return jsonError(404, "Parent path not found");
192
+ }
193
+ const directoryPath = path$1.join(resolvedParent, name);
194
+ try {
195
+ await mkdir(directoryPath);
196
+ const createdPath = await realpath(directoryPath);
197
+ log.info({ path: createdPath }, "Host fs directory created");
198
+ return c.json({
199
+ ok: true,
200
+ payload: { absolutePath: createdPath }
201
+ }, 201);
202
+ } catch (err) {
203
+ const code = err?.code;
204
+ if (code === "EEXIST") return jsonError(409, "A file or folder with this name already exists");
205
+ log.warn({
206
+ err,
207
+ path: directoryPath
208
+ }, "Host fs directory create failed");
209
+ if (code === "EACCES" || code === "EPERM" || code === "EROFS") return jsonError(403, "Permission denied");
210
+ if (code === "ENOENT") return jsonError(404, "Parent path not found");
211
+ return jsonError(500, "Failed to create folder");
212
+ }
213
+ });
175
214
  }
176
215
  //#endregion
177
216
  export { registerHostFsRoutes };
@@ -1,15 +1,47 @@
1
1
  import { TaskRepository } from "../../../tasks/task-repository.js";
2
2
  import { parseMediaUri } from "../../../media/uri.js";
3
- import { mimeTypeFromMediaPath } from "../../../media/store.js";
3
+ import { mimeTypeFromMediaPath, saveMediaBuffer } from "../../../media/store.js";
4
4
  import { readMediaReference } from "../../../media/media-reference.js";
5
5
  import { TaskContextRepository } from "../../../tasks/task-context-repository.js";
6
6
  import { pendingTranscriptReferencesMediaUri } from "../../../agent/inbound/attachment-pipeline.js";
7
+ import { MAX_WEBCHAT_ATTACHMENT_FILE_BYTES } from "../../chat-limits.js";
7
8
  import { messagesReferenceMediaUri } from "../../../media/session-references.js";
8
9
  import { createGatewayRouteLogger } from "../lib/route-logger.js";
9
10
  //#region src/gateway/hono/routes/media.ts
10
11
  const log = createGatewayRouteLogger("Media");
11
12
  function registerMediaRoutes(authenticated, deps) {
12
13
  const tasks = new TaskRepository();
14
+ authenticated.post("/api/media", deps.strictRateLimitMiddleware, async (c) => {
15
+ const file = (await c.req.formData().catch(() => null))?.get("file");
16
+ if (!(file instanceof Blob)) return c.json({
17
+ ok: false,
18
+ error: { message: "Missing required file field: file" }
19
+ }, 400);
20
+ if (file.size === 0) return c.json({
21
+ ok: false,
22
+ error: { message: "Uploaded file is empty" }
23
+ }, 400);
24
+ if (file.size > 33554432) return c.json({
25
+ ok: false,
26
+ error: { message: "Uploaded file exceeds 32 MB limit" }
27
+ }, 413);
28
+ const name = "name" in file && typeof file.name === "string" && file.name.trim() ? file.name.trim() : `upload-${Date.now()}`;
29
+ const saved = await saveMediaBuffer(Buffer.from(await file.arrayBuffer()), {
30
+ bucket: "inbound",
31
+ contentType: file.type || "application/octet-stream",
32
+ maxBytes: MAX_WEBCHAT_ATTACHMENT_FILE_BYTES,
33
+ originalFilename: name
34
+ });
35
+ return c.json({
36
+ ok: true,
37
+ payload: {
38
+ uri: saved.uri,
39
+ mimeType: saved.contentType,
40
+ name,
41
+ size: saved.size
42
+ }
43
+ }, 201);
44
+ });
13
45
  authenticated.get("/api/media/read", async (c) => {
14
46
  const uriRaw = c.req.query("uri");
15
47
  if (!uriRaw || typeof uriRaw !== "string") return c.json({