@xopcai/xopc 0.0.230 → 0.0.232

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 (384) hide show
  1. package/README.md +1 -0
  2. package/README.zh-CN.md +1 -0
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/feishu/src/schema/config-schema.d.ts +3 -3
  5. package/dist/extensions/telegram/src/config-schema.d.ts +4 -4
  6. package/dist/extensions/telegram/xopc.extension.json +1 -1
  7. package/dist/extensions/weixin/src/config-schema.d.ts +3 -3
  8. package/dist/gateway/static/root/assets/{activity-store-M0nAY5XB.js → activity-store-VXCWz43N.js} +1 -1
  9. package/dist/gateway/static/root/assets/agent-avatar-dicebear-BXRaZYW8.js +1 -0
  10. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-dR7HMaRX.js +1 -0
  11. package/dist/gateway/static/root/assets/agents-Bileycwe.js +1 -0
  12. package/dist/gateway/static/root/assets/api-wGPgL8xY.js +1 -0
  13. package/dist/gateway/static/root/assets/{app-management-settings-panel-CwAPK4Jm.js → app-management-settings-panel-BJfClfPx.js} +1 -1
  14. package/dist/gateway/static/root/assets/{appearance-settings-DsGLvqTb.js → appearance-settings-C_R0vUAu.js} +1 -1
  15. package/dist/gateway/static/root/assets/{apps-page-Ee9qOQEx.js → apps-page-CBow8pBI.js} +1 -1
  16. package/dist/gateway/static/root/assets/{archive-plugin-7_DXaMTP.js → archive-plugin-DnFHkSHE.js} +1 -1
  17. package/dist/gateway/static/root/assets/{attachment-load-B4qqigAQ.js → attachment-load-DZrEwytM.js} +1 -1
  18. package/dist/gateway/static/root/assets/{automations-page-B8ImehSW.js → automations-page-DpkKajui.js} +1 -1
  19. package/dist/gateway/static/root/assets/automations-workspace-BBntVWgv.js +6 -0
  20. package/dist/gateway/static/root/assets/{binary-plugins-DaJbyYc2.js → binary-plugins-Ckc_Csue.js} +1 -1
  21. package/dist/gateway/static/root/assets/{block-editor-Kl25XWJc.js → block-editor-DAC6w-iV.js} +4 -4
  22. package/dist/gateway/static/root/assets/browser-settings-page-DrsMd-Po.js +8 -0
  23. package/dist/gateway/static/root/assets/browser-workflow-inputs-BGd7R8GO.js +1 -0
  24. package/dist/gateway/static/root/assets/{browser-workflows-page-DjMxs33B.js → browser-workflows-page-DUfj7ntM.js} +2 -2
  25. package/dist/gateway/static/root/assets/capabilities-settings-panel-97gkGeSV.js +7 -0
  26. package/dist/gateway/static/root/assets/channels-settings-CuBsz8UI.js +1 -0
  27. package/dist/gateway/static/root/assets/{channel-recipient-api-C5ABr73b.js → channels-status-swr-CfboECLt.js} +1 -1
  28. package/dist/gateway/static/root/assets/{chat-terminal-dock-BiU_4Rq6.js → chat-terminal-dock-CA9fndbZ.js} +2 -2
  29. package/dist/gateway/static/root/assets/cloud-C4-yfnnk.js +1 -0
  30. package/dist/gateway/static/root/assets/{code-editor-dFzqyDXS.js → code-editor-D4_k-6QN.js} +1 -1
  31. package/dist/gateway/static/root/assets/connectors-page-SuL7td7Z.js +2 -0
  32. package/dist/gateway/static/root/assets/cron-expression-CqPu7HYJ.js +2 -0
  33. package/dist/gateway/static/root/assets/date-picker-C8dJsCgk.js +1 -0
  34. package/dist/gateway/static/root/assets/dependency-picker-Iz2wYimy.js +1 -0
  35. package/dist/gateway/static/root/assets/{desktop-pet-ux9DxchT.js → desktop-pet-C3h40FmG.js} +1 -1
  36. package/dist/gateway/static/root/assets/{desktop-pet-settings-BVVCBgYK.js → desktop-pet-settings-YfeVVzLe.js} +1 -1
  37. package/dist/gateway/static/root/assets/dist-DqPZM2MH2.js +1 -0
  38. package/dist/gateway/static/root/assets/{extension-debug-page-Dh6DDuvQ.js → extension-debug-page-CChgztz_.js} +1 -1
  39. package/dist/gateway/static/root/assets/{extension-page-8OKQDEat.js → extension-page-DF6ct6_y.js} +1 -1
  40. package/dist/gateway/static/root/assets/extension-settings-page-jgBsjn0F.js +1 -0
  41. package/dist/gateway/static/root/assets/files-Dp8_uGTO.js +1 -0
  42. package/dist/gateway/static/root/assets/{gateway-config-api-Dlc6eaTG.js → gateway-config-api-CVajuIGL.js} +1 -1
  43. package/dist/gateway/static/root/assets/gateway-config-swr-BGQn8duh.js +1 -0
  44. package/dist/gateway/static/root/assets/{gateway-settings-DqQgiAUv.js → gateway-settings-BbssNGid.js} +1 -1
  45. package/dist/gateway/static/root/assets/{gateway-startup-retry-B_zrtccP.js → gateway-startup-retry-D2Rnh9fX.js} +1 -1
  46. package/dist/gateway/static/root/assets/heartbeat-settings-CJtXu8iD.js +1 -0
  47. package/dist/gateway/static/root/assets/home-page-Be1o1AXQ.js +1 -0
  48. package/dist/gateway/static/root/assets/html-workspace-editor-C3DKAkMc.js +1 -0
  49. package/dist/gateway/static/root/assets/{image-generation-api-YKP2me5Z.js → image-generation-api-D7W2p5_8.js} +1 -1
  50. package/dist/gateway/static/root/assets/index-B2OJSXX9.js +70 -0
  51. package/dist/gateway/static/root/assets/index-rHjAElxG.css +2 -0
  52. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BSFNqxzY.js → keyboard-shortcuts-settings-BvHYyNus.js} +1 -1
  53. package/dist/gateway/static/root/assets/local-app-workbench-page-COfelgk7.js +2 -0
  54. package/dist/gateway/static/root/assets/{local-apps-page-DzU6yZ9-.js → local-apps-page-Cb8t2wWM.js} +1 -1
  55. package/dist/gateway/static/root/assets/locale-store-DLwVxS3V.js +1 -0
  56. package/dist/gateway/static/root/assets/logs-page-DA8oDjeB.js +2 -0
  57. package/dist/gateway/static/root/assets/management-settings-B8Jie4-J.js +1 -0
  58. package/dist/gateway/static/root/assets/markdown-editor-nDLmA_LF.js +2 -0
  59. package/dist/gateway/static/root/assets/markdown-split-BD1r4o2i.js +1 -0
  60. package/dist/gateway/static/root/assets/{markdown-view-DvM5PWEH.js → markdown-view-B-BHEcNd.js} +1 -1
  61. package/dist/gateway/static/root/assets/markdown-view-B1bGSQqt.css +1 -0
  62. package/dist/gateway/static/root/assets/{media-plugins-B8vMe5VX.js → media-plugins-BCev8fkW.js} +1 -1
  63. package/dist/gateway/static/root/assets/messages-Dp1OxSKt.js +3 -0
  64. package/dist/gateway/static/root/assets/mobile-device-api-DACoHhhk.js +1 -0
  65. package/dist/gateway/static/root/assets/models-hub-cache-C8zjqmIv.js +1 -0
  66. package/dist/gateway/static/root/assets/{notes-api-BFsOGYkd.js → notes-api-DEdNKw0I.js} +1 -1
  67. package/dist/gateway/static/root/assets/{notes-page-B-YZ7iuK.js → notes-page-BBTLjJwa.js} +1 -1
  68. package/dist/gateway/static/root/assets/notes-workbench-DICgUGPv.js +4 -0
  69. package/dist/gateway/static/root/assets/oauth-api-BNCO2YK5.js +1 -0
  70. package/dist/gateway/static/root/assets/popover-select-3E24E65N.js +1 -0
  71. package/dist/gateway/static/root/assets/{product-open-page-DkWcyki5.js → product-open-page-fEBbRekH.js} +1 -1
  72. package/dist/gateway/static/root/assets/project-detail-page-CqdkznYJ.js +1 -0
  73. package/dist/gateway/static/root/assets/projects-page-dHDXpMCg.js +1 -0
  74. package/dist/gateway/static/root/assets/{registry-api-BFZrVYfy.js → registry-api-Cvr4Qm7N.js} +1 -1
  75. package/dist/gateway/static/root/assets/remote-access-hub-2feZudJw.js +1 -0
  76. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-Bq_ETeal.js → runtime-tools-settings-panel-BT5B74IH.js} +2 -2
  77. package/dist/gateway/static/root/assets/{schema-form-BogTlrsP.js → schema-form-C4tB34S5.js} +1 -1
  78. package/dist/gateway/static/root/assets/sessions-page-CO2JCFdy.js +1 -0
  79. package/dist/gateway/static/root/assets/settings-advanced-gate-DxMVaqdn.js +1 -0
  80. package/dist/gateway/static/root/assets/{settings-form-section-Coy1Cbp6.js → settings-form-section-D1oXhkgI.js} +1 -1
  81. package/dist/gateway/static/root/assets/settings-loading-skeleton-CldfX6FJ.js +1 -0
  82. package/dist/gateway/static/root/assets/settings-page-c3LJnbvE.js +1 -0
  83. package/dist/gateway/static/root/assets/settings-shell-layer-context-DCp6ykjQ.js +1 -0
  84. package/dist/gateway/static/root/assets/setup-status-panel-DZNHb6A5.js +1 -0
  85. package/dist/gateway/static/root/assets/share-preview-page-DptCK_mk.js +2 -0
  86. package/dist/gateway/static/root/assets/shares-settings-DakZ2AGN.js +1 -0
  87. package/dist/gateway/static/root/assets/skill-reload-api-BOiNkWJC.js +1 -0
  88. package/dist/gateway/static/root/assets/{skills-page-Brxb6QnW.js → skills-page-OHBeBtSg.js} +1 -1
  89. package/dist/gateway/static/root/assets/{skills-page.utils-FB5LtEGm.js → skills-page.utils-B9WZbOLC.js} +1 -1
  90. package/dist/gateway/static/root/assets/{system-settings-panel-ChosWt8n.js → system-settings-panel-Dj_DpOGw.js} +1 -1
  91. package/dist/gateway/static/root/assets/task-detail-page-D5Nbe3C8.js +1 -0
  92. package/dist/gateway/static/root/assets/theme-store-Cpd3Gd5R.js +1 -0
  93. package/dist/gateway/static/root/assets/{use-autosave-2SqnmSKD.js → use-autosave-DCl5Yq7N.js} +1 -1
  94. package/dist/gateway/static/root/assets/user-context-page-CAPSUK8B.js +1 -0
  95. package/dist/gateway/static/root/assets/{vendor-codemirror-DRr7hFaD.js → vendor-codemirror--gTq3YAI.js} +16 -16
  96. package/dist/gateway/static/root/assets/voice-api-key-field-BB_ZQV8F.js +1 -0
  97. package/dist/gateway/static/root/assets/voice-config-api-BNiYmpl5.js +1 -0
  98. package/dist/gateway/static/root/assets/{work-discovery-overlay-CK3aZDdE.js → work-discovery-overlay-BrIdtdum.js} +1 -1
  99. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BjOuddkX.js → workflow-run-setup-panel-hKh-uCLo.js} +2 -2
  100. package/dist/gateway/static/root/assets/workflows-page-ahDvypGO.js +5 -0
  101. package/dist/gateway/static/root/index.html +19 -15
  102. package/dist/package.js +1 -1
  103. package/dist/src/agent/agent-manager.d.ts +1 -2
  104. package/dist/src/agent/agent-manager.js +29 -44
  105. package/dist/src/agent/background-review/run-background-review.js +10 -15
  106. package/dist/src/agent/embedded/run-for-session.js +1 -1
  107. package/dist/src/agent/external-tools/mcp-provider.js +3 -13
  108. package/dist/src/agent/image/generation/runtime.js +1 -1
  109. package/dist/src/agent/image/tool-model-config.js +13 -14
  110. package/dist/src/agent/mcp/bundle-mcp-policy.d.ts +0 -9
  111. package/dist/src/agent/mcp/bundle-mcp-policy.js +1 -13
  112. package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
  113. package/dist/src/agent/mcp/index.js +2 -2
  114. package/dist/src/agent/media-generation/runtime-shared.d.ts +1 -1
  115. package/dist/src/agent/media-generation/runtime-shared.js +1 -1
  116. package/dist/src/agent/memory/create-memory-manager.js +1 -1
  117. package/dist/src/agent/memory/manager.d.ts +1 -1
  118. package/dist/src/{agent-runtime/memory-runtime.d.ts → agent/memory/runtime.d.ts} +1 -1
  119. package/dist/src/{agent-runtime/memory-runtime.js → agent/memory/runtime.js} +2 -3
  120. package/dist/src/agent/orchestration/agent-orchestrator.d.ts +0 -3
  121. package/dist/src/agent/orchestration/agent-orchestrator.js +1 -3
  122. package/dist/src/agent/orchestration/run-agent-turn-with-timeout.js +2 -2
  123. package/dist/src/agent/service.d.ts +1 -0
  124. package/dist/src/agent/service.js +5 -3
  125. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  126. package/dist/src/agent/starter-agents.js +1 -8
  127. package/dist/src/agent/tools/executor.d.ts +1 -1
  128. package/dist/src/agent/tools/workflow-tool.js +1 -5
  129. package/dist/src/agent/tools/write.js +9 -12
  130. package/dist/src/agent/tools/xopc-use-tool.js +2 -2
  131. package/dist/src/agent-config/index.d.ts +2 -0
  132. package/dist/src/agent-config/index.js +11 -0
  133. package/dist/src/agent-config/resolver.d.ts +11 -0
  134. package/dist/src/agent-config/resolver.js +113 -0
  135. package/dist/src/agent-config/schema.d.ts +491 -0
  136. package/dist/src/agent-config/schema.js +172 -0
  137. package/dist/src/auth/oauth/index.js +2 -2
  138. package/dist/src/auth/oauth/registry.d.ts +1 -1
  139. package/dist/src/auth/oauth/registry.js +5 -1
  140. package/dist/src/auth/oauth/xopc-cloud.d.ts +1 -0
  141. package/dist/src/auth/oauth/xopc-cloud.js +8 -2
  142. package/dist/src/chat-commands/builtins/config.js +2 -2
  143. package/dist/src/chat-commands/builtins/review.js +1 -1
  144. package/dist/src/chat-commands/config-paths.js +1 -1
  145. package/dist/src/cli/commands/agents.js +2 -1
  146. package/dist/src/cli/commands/config.js +1 -1
  147. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  148. package/dist/src/cli/commands/doctor/checks/provider-auth.js +12 -4
  149. package/dist/src/cli/commands/image.js +3 -4
  150. package/dist/src/cli/commands/models.js +9 -3
  151. package/dist/src/cli/commands/onboard/model.js +12 -11
  152. package/dist/src/cli/commands/onboard.js +1 -1
  153. package/dist/src/cli/commands/tunnel.js +3 -18
  154. package/dist/src/cli/utils/init-workspace-core.d.ts +1 -1
  155. package/dist/src/cli/utils/init-workspace-core.js +1 -1
  156. package/dist/src/commands/agents.config.d.ts +1 -3
  157. package/dist/src/commands/agents.config.js +9 -26
  158. package/dist/src/config/agent-model-intents.d.ts +10 -0
  159. package/dist/src/config/agent-model-intents.js +39 -0
  160. package/dist/src/config/agent-profile.d.ts +7 -9
  161. package/dist/src/config/agent-profile.js +30 -28
  162. package/dist/src/config/default-model.d.ts +1 -11
  163. package/dist/src/config/default-model.js +3 -11
  164. package/dist/src/config/index.js +3 -3
  165. package/dist/src/config/integration.d.ts +1 -1
  166. package/dist/src/config/reload.js +1 -1
  167. package/dist/src/config/rules.js +3 -3
  168. package/dist/src/config/schema.d.ts +187 -452
  169. package/dist/src/config/schema.js +53 -131
  170. package/dist/src/extensions/activation-context.js +7 -11
  171. package/dist/src/files/file-service.d.ts +36 -0
  172. package/dist/src/files/file-service.js +282 -0
  173. package/dist/src/gateway/agent-builtin-tools.d.ts +250 -6
  174. package/dist/src/gateway/agent-builtin-tools.js +284 -46
  175. package/dist/src/gateway/agents-admin.d.ts +20 -62
  176. package/dist/src/gateway/agents-admin.js +36 -228
  177. package/dist/src/gateway/device-routes.d.ts +3 -0
  178. package/dist/src/gateway/device-routes.js +47 -0
  179. package/dist/src/gateway/global-defaults-admin.d.ts +6 -20
  180. package/dist/src/gateway/global-defaults-admin.js +20 -120
  181. package/dist/src/gateway/heartbeat/service.js +1 -1
  182. package/dist/src/gateway/hono/app.js +6 -4
  183. package/dist/src/gateway/hono/lib/config-payload.d.ts +54 -137
  184. package/dist/src/gateway/hono/lib/config-payload.js +2 -4
  185. package/dist/src/gateway/hono/middleware/auth.js +33 -1
  186. package/dist/src/gateway/hono/middleware/scopes.d.ts +2 -12
  187. package/dist/src/gateway/hono/middleware/scopes.js +9 -18
  188. package/dist/src/gateway/hono/routes/agents.js +64 -100
  189. package/dist/src/gateway/hono/routes/connectors.js +1 -1
  190. package/dist/src/gateway/hono/routes/device-push.d.ts +2 -0
  191. package/dist/src/gateway/hono/routes/{mobile.js → device-push.js} +40 -18
  192. package/dist/src/gateway/hono/routes/devices.d.ts +4 -0
  193. package/dist/src/gateway/hono/routes/devices.js +214 -0
  194. package/dist/src/gateway/hono/routes/files.d.ts +3 -0
  195. package/dist/src/gateway/hono/routes/files.js +176 -0
  196. package/dist/src/gateway/hono/routes/global-defaults.js +5 -9
  197. package/dist/src/gateway/hono/routes/index.js +4 -2
  198. package/dist/src/gateway/hono/routes/lazy-bundles.js +12 -20
  199. package/dist/src/gateway/hono/routes/models.js +2 -2
  200. package/dist/src/gateway/hono/routes/projects.js +0 -508
  201. package/dist/src/gateway/hono/routes/realtime.js +8 -1
  202. package/dist/src/gateway/hono/routes/shares.js +410 -21
  203. package/dist/src/gateway/hono/routes/status.js +9 -16
  204. package/dist/src/gateway/hono/routes/tunnel.d.ts +0 -2
  205. package/dist/src/gateway/hono/routes/tunnel.js +10 -199
  206. package/dist/src/gateway/hono/routes/voice.js +1 -1
  207. package/dist/src/gateway/hono/routes/workspace.js +15 -974
  208. package/dist/src/gateway/image-generation-setup.d.ts +2 -2
  209. package/dist/src/gateway/image-generation-setup.js +8 -7
  210. package/dist/src/gateway/public-url.d.ts +1 -1
  211. package/dist/src/gateway/security/gateway-principal.d.ts +11 -0
  212. package/dist/src/gateway/security/gateway-principal.js +12 -0
  213. package/dist/src/gateway/security/gateway-scopes.d.ts +7 -0
  214. package/dist/src/gateway/security/gateway-scopes.js +66 -0
  215. package/dist/src/gateway/security/index.d.ts +2 -1
  216. package/dist/src/gateway/security/index.js +3 -2
  217. package/dist/src/gateway/service.js +4 -4
  218. package/dist/src/gateway/xopc-cloud-capability-setup.js +19 -21
  219. package/dist/src/heartbeat/index.js +1 -1
  220. package/dist/src/migrations/index.d.ts +0 -1
  221. package/dist/src/migrations/index.js +1 -2
  222. package/dist/src/migrations/runner.js +1 -2
  223. package/dist/src/notifications/device-store.d.ts +1 -1
  224. package/dist/src/notifications/device-store.js +11 -11
  225. package/dist/src/notifications/store.js +3 -3
  226. package/dist/src/providers/index.js +1 -1
  227. package/dist/src/providers/model-reference-auditor.js +14 -9
  228. package/dist/src/realtime/runtime.d.ts +2 -0
  229. package/dist/src/realtime/runtime.js +27 -3
  230. package/dist/src/realtime/tickets.d.ts +6 -1
  231. package/dist/src/realtime/tickets.js +2 -1
  232. package/dist/src/remote-access/exposure-manager.js +3 -3
  233. package/dist/src/share/hosted-session-share.d.ts +104 -0
  234. package/dist/src/share/hosted-session-share.js +276 -0
  235. package/dist/src/share/note-share-service.js +4 -24
  236. package/dist/src/share/session-share-projector.d.ts +31 -0
  237. package/dist/src/share/session-share-projector.js +79 -0
  238. package/dist/src/share/session-share-service.d.ts +89 -0
  239. package/dist/src/share/session-share-service.js +325 -0
  240. package/dist/src/share/share-asset-ticket.d.ts +7 -0
  241. package/dist/src/share/share-asset-ticket.js +30 -0
  242. package/dist/src/share/share-landing.d.ts +4 -3
  243. package/dist/src/share/share-landing.js +5 -5
  244. package/dist/src/share/share-store.d.ts +27 -2
  245. package/dist/src/share/share-store.js +71 -8
  246. package/dist/src/share/share-types.d.ts +17 -2
  247. package/dist/src/share/share-url.js +2 -2
  248. package/dist/src/storage/sqlite/device-access-repository.d.ts +54 -0
  249. package/dist/src/storage/sqlite/device-access-repository.js +194 -0
  250. package/dist/src/storage/sqlite/device-pairing-repository.d.ts +22 -0
  251. package/dist/src/storage/sqlite/device-pairing-repository.js +86 -0
  252. package/dist/src/storage/sqlite/gateway-identity-repository.d.ts +10 -0
  253. package/dist/src/storage/sqlite/gateway-identity-repository.js +50 -0
  254. package/dist/src/storage/sqlite/index.d.ts +3 -0
  255. package/dist/src/storage/sqlite/index.js +4 -1
  256. package/dist/src/storage/sqlite/migrations/138_device_access.sql +96 -0
  257. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  258. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  259. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  260. package/dist/src/storage/sqlite/schema.js +1 -1
  261. package/dist/src/tui/backends/embedded-backend.js +1 -1
  262. package/dist/src/tui/backends/gateway-realtime-backend.js +11 -3
  263. package/dist/src/tunnel/consent.d.ts +1 -1
  264. package/dist/src/tunnel/consent.js +1 -1
  265. package/dist/src/tunnel/gateway-lifecycle.js +1 -1
  266. package/dist/src/tunnel/index.d.ts +1 -4
  267. package/dist/src/tunnel/index.js +3 -5
  268. package/dist/src/tunnel/tunnel-audit.d.ts +1 -1
  269. package/dist/src/tunnel/tunnel-config.js +1 -1
  270. package/dist/src/tunnel/tunnel-service.d.ts +2 -3
  271. package/dist/src/tunnel/tunnel-service.js +1 -20
  272. package/dist/src/tunnel/tunnel-types.d.ts +0 -6
  273. package/dist/src/workflows/draft/workflow-draft-service.js +2 -2
  274. package/dist/src/workflows/service/workflow-run-service.js +3 -3
  275. package/package.json +3 -3
  276. package/dist/gateway/static/root/assets/agent-avatar-dicebear-Bp_wmuGW.js +0 -1
  277. package/dist/gateway/static/root/assets/agents-CKG93dlc.js +0 -68
  278. package/dist/gateway/static/root/assets/api-BywYxpaS.js +0 -1
  279. package/dist/gateway/static/root/assets/automations-workspace-BNFAfNwC.js +0 -6
  280. package/dist/gateway/static/root/assets/browser-settings-page-Cg6NgwE_.js +0 -8
  281. package/dist/gateway/static/root/assets/browser-workflow-inputs-8NC2qDRF.js +0 -1
  282. package/dist/gateway/static/root/assets/capabilities-settings-panel-NvJKgF1u.js +0 -7
  283. package/dist/gateway/static/root/assets/capability-presets-api-o0y9WgAI.js +0 -1
  284. package/dist/gateway/static/root/assets/capability-presets-settings-panel-C2uBdALe.js +0 -3
  285. package/dist/gateway/static/root/assets/channels-settings-CIcYKMEs.js +0 -1
  286. package/dist/gateway/static/root/assets/channels-status-swr-38FsOnR0.js +0 -1
  287. package/dist/gateway/static/root/assets/connectors-page-CEEcmUiP.js +0 -2
  288. package/dist/gateway/static/root/assets/cron-expression-Cs_5pUPT.js +0 -2
  289. package/dist/gateway/static/root/assets/date-picker-y1kWrFVU.js +0 -1
  290. package/dist/gateway/static/root/assets/dependency-picker-skc62zrn.js +0 -1
  291. package/dist/gateway/static/root/assets/directory-picker-path-field-V8vZP0Dy.js +0 -1
  292. package/dist/gateway/static/root/assets/dist-J_ySZvz0.js +0 -1
  293. package/dist/gateway/static/root/assets/extension-settings-page-BgSV0Nny.js +0 -1
  294. package/dist/gateway/static/root/assets/file-code-corner-byQA1VfD.js +0 -1
  295. package/dist/gateway/static/root/assets/gateway-config-swr-BWGjnmDl.js +0 -1
  296. package/dist/gateway/static/root/assets/heartbeat-settings-Pxqk5GFH.js +0 -1
  297. package/dist/gateway/static/root/assets/home-page-1xjo6wE4.js +0 -1
  298. package/dist/gateway/static/root/assets/html-workspace-editor-bXK5tq64.js +0 -1
  299. package/dist/gateway/static/root/assets/index-Bbd_dXui.js +0 -70
  300. package/dist/gateway/static/root/assets/index-D_hrEKXM.css +0 -2
  301. package/dist/gateway/static/root/assets/local-app-workbench-page-heQ4-PJ7.js +0 -2
  302. package/dist/gateway/static/root/assets/locale-store-CXhjfe4q.js +0 -1
  303. package/dist/gateway/static/root/assets/logs-page-BblnS6Jy.js +0 -2
  304. package/dist/gateway/static/root/assets/management-settings-B8hM56HS.js +0 -1
  305. package/dist/gateway/static/root/assets/markdown-editor-TWGaF7Xa.js +0 -2
  306. package/dist/gateway/static/root/assets/markdown-split-DRbZjxMK.js +0 -1
  307. package/dist/gateway/static/root/assets/markdown-view-CLzTdVLW.css +0 -1
  308. package/dist/gateway/static/root/assets/messages-BMdD0LWk.js +0 -3
  309. package/dist/gateway/static/root/assets/notes-workbench-CAM09C8b.js +0 -4
  310. package/dist/gateway/static/root/assets/popover-select-CccGri5Y.js +0 -1
  311. package/dist/gateway/static/root/assets/project-detail-page-BIPIwgU2.js +0 -1
  312. package/dist/gateway/static/root/assets/projects-page-B_kzTn1K.js +0 -1
  313. package/dist/gateway/static/root/assets/remote-access-hub-CtD8DsD-.js +0 -1
  314. package/dist/gateway/static/root/assets/sessions-page-B8n9HI1y.js +0 -1
  315. package/dist/gateway/static/root/assets/settings-advanced-gate-xlhdRTME.js +0 -1
  316. package/dist/gateway/static/root/assets/settings-loading-skeleton-B5GU7iCG.js +0 -1
  317. package/dist/gateway/static/root/assets/settings-page-Dd-BRu12.js +0 -1
  318. package/dist/gateway/static/root/assets/setup-status-panel-CwEFAVWx.js +0 -1
  319. package/dist/gateway/static/root/assets/share-preview-page-DzXw9UQJ.js +0 -2
  320. package/dist/gateway/static/root/assets/shares-settings-Bk6UQOwS.js +0 -1
  321. package/dist/gateway/static/root/assets/skill-reload-api-DrmQZ3Au.js +0 -1
  322. package/dist/gateway/static/root/assets/task-detail-page-CW2sJbdc.js +0 -1
  323. package/dist/gateway/static/root/assets/theme-store-DOdCjyuw.js +0 -1
  324. package/dist/gateway/static/root/assets/typed-models-lib-q5-Vfqd8.js +0 -1
  325. package/dist/gateway/static/root/assets/user-context-page-Bq9KB-Oj.js +0 -1
  326. package/dist/gateway/static/root/assets/voice-api-key-field-DtTIF6M8.js +0 -1
  327. package/dist/gateway/static/root/assets/workflows-page-CcbGEQol.js +0 -5
  328. package/dist/src/agent-manifest/index.d.ts +0 -5
  329. package/dist/src/agent-manifest/index.js +0 -10
  330. package/dist/src/agent-manifest/preset-chain.d.ts +0 -10
  331. package/dist/src/agent-manifest/preset-chain.js +0 -30
  332. package/dist/src/agent-manifest/prompt.d.ts +0 -2
  333. package/dist/src/agent-manifest/prompt.js +0 -49
  334. package/dist/src/agent-manifest/resolver.d.ts +0 -32
  335. package/dist/src/agent-manifest/resolver.js +0 -114
  336. package/dist/src/agent-manifest/schema.d.ts +0 -695
  337. package/dist/src/agent-manifest/schema.js +0 -226
  338. package/dist/src/agent-manifest/validator.d.ts +0 -25
  339. package/dist/src/agent-manifest/validator.js +0 -74
  340. package/dist/src/agent-runtime/boundary-guard.d.ts +0 -12
  341. package/dist/src/agent-runtime/boundary-guard.js +0 -21
  342. package/dist/src/agent-runtime/index.d.ts +0 -7
  343. package/dist/src/agent-runtime/index.js +0 -8
  344. package/dist/src/agent-runtime/model-router.d.ts +0 -11
  345. package/dist/src/agent-runtime/model-router.js +0 -14
  346. package/dist/src/agent-runtime/run-trace.d.ts +0 -27
  347. package/dist/src/agent-runtime/run-trace.js +0 -51
  348. package/dist/src/agent-runtime/runtime-profile.d.ts +0 -26
  349. package/dist/src/agent-runtime/runtime-profile.js +0 -42
  350. package/dist/src/agent-runtime/tool-registry.d.ts +0 -28
  351. package/dist/src/agent-runtime/tool-registry.js +0 -50
  352. package/dist/src/agent-runtime/workflow-runtime.d.ts +0 -31
  353. package/dist/src/agent-runtime/workflow-runtime.js +0 -32
  354. package/dist/src/config/agent-typed-models.d.ts +0 -13
  355. package/dist/src/config/agent-typed-models.js +0 -48
  356. package/dist/src/gateway/capability-presets-admin.d.ts +0 -88
  357. package/dist/src/gateway/capability-presets-admin.js +0 -303
  358. package/dist/src/gateway/file-path-classifier.d.ts +0 -30
  359. package/dist/src/gateway/file-path-classifier.js +0 -105
  360. package/dist/src/gateway/file-reference-errors.d.ts +0 -6
  361. package/dist/src/gateway/file-reference-errors.js +0 -21
  362. package/dist/src/gateway/file-reference-registry.d.ts +0 -34
  363. package/dist/src/gateway/file-reference-registry.js +0 -45
  364. package/dist/src/gateway/hono/lib/agent-model.d.ts +0 -35
  365. package/dist/src/gateway/hono/lib/agent-model.js +0 -97
  366. package/dist/src/gateway/hono/routes/capability-presets.d.ts +0 -3
  367. package/dist/src/gateway/hono/routes/capability-presets.js +0 -187
  368. package/dist/src/gateway/hono/routes/mobile.d.ts +0 -3
  369. package/dist/src/gateway/security/operator-scopes.d.ts +0 -37
  370. package/dist/src/gateway/security/operator-scopes.js +0 -147
  371. package/dist/src/migrations/config/default-capability-preset.d.ts +0 -10
  372. package/dist/src/migrations/config/default-capability-preset.js +0 -133
  373. package/dist/src/tunnel/enable-lan-pairing.d.ts +0 -8
  374. package/dist/src/tunnel/enable-lan-pairing.js +0 -41
  375. package/dist/src/tunnel/pair-context.d.ts +0 -36
  376. package/dist/src/tunnel/pair-context.js +0 -77
  377. package/dist/src/tunnel/pair-url.d.ts +0 -43
  378. package/dist/src/tunnel/pair-url.js +0 -117
  379. package/dist/src/tunnel/pairing-rate-limit.d.ts +0 -12
  380. package/dist/src/tunnel/pairing-rate-limit.js +0 -28
  381. package/dist/src/tunnel/pairing.d.ts +0 -21
  382. package/dist/src/tunnel/pairing.js +0 -103
  383. package/dist/src/tunnel/tunnel-qr.d.ts +0 -9
  384. package/dist/src/tunnel/tunnel-qr.js +0 -29
@@ -0,0 +1,325 @@
1
+ import { resolveStateDir } from "../config/paths-state.js";
2
+ import { createLogger } from "../utils/logger/index.js";
3
+ import { init_logger } from "../utils/logger.js";
4
+ import { init_paths } from "../config/paths.js";
5
+ import { resolveMediaReference } from "../media/media-reference.js";
6
+ import { projectSessionShare } from "./session-share-projector.js";
7
+ import { issueShareAssetTicket, verifyShareAssetTicket } from "./share-asset-ticket.js";
8
+ import { basename, join } from "node:path";
9
+ import { createReadStream } from "node:fs";
10
+ import { createHash, randomUUID } from "node:crypto";
11
+ import { copyFile, mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
12
+ //#region src/share/session-share-service.ts
13
+ init_paths();
14
+ init_logger();
15
+ const log = createLogger("SessionShareService");
16
+ const MANIFEST_SCHEMA_VERSION = 1;
17
+ const MAX_SHARE_MESSAGES = 1e4;
18
+ const MAX_MANIFEST_BYTES = 10 * 1024 * 1024;
19
+ const MAX_ATTACHMENT_COUNT = 20;
20
+ const MAX_ATTACHMENT_BYTES = 32 * 1024 * 1024;
21
+ const MAX_TOTAL_ATTACHMENT_BYTES = 100 * 1024 * 1024;
22
+ const ASSET_TICKET_TTL_MS = 10 * 6e4;
23
+ var SessionShareSnapshotConflictError = class extends Error {
24
+ constructor() {
25
+ super("Session changed after the share preview was reviewed");
26
+ this.name = "SessionShareSnapshotConflictError";
27
+ }
28
+ };
29
+ var SessionShareService = class {
30
+ constructor(store, source) {
31
+ this.store = store;
32
+ this.source = source;
33
+ }
34
+ async preview(sessionKey) {
35
+ const source = await this.loadSource(sessionKey);
36
+ const projection = projectSessionShare(source.snapshot.entries);
37
+ this.validateMessages(projection.messages);
38
+ return {
39
+ sessionId: source.snapshot.sessionId,
40
+ cutoffSeq: source.snapshot.lastSeq,
41
+ metadataUpdatedAt: source.metadata.updatedAt,
42
+ title: source.metadata.name?.trim() || "Shared conversation",
43
+ snapshotAt: (/* @__PURE__ */ new Date()).toISOString(),
44
+ messageCount: projection.messages.length,
45
+ messages: projection.messages,
46
+ toolActivities: projection.toolActivities,
47
+ attachmentCandidates: projection.attachmentCandidates
48
+ };
49
+ }
50
+ async create(sessionKey, input) {
51
+ const source = await this.loadExpectedSource(sessionKey, input);
52
+ const id = randomUUID();
53
+ const projection = projectSessionShare(source.snapshot.entries);
54
+ const includeToolActivities = input.includeToolActivities === true;
55
+ const manifestBase = this.buildManifestBase(id, source, projection, {
56
+ includeToolActivities,
57
+ selectedAttachmentIds: input.attachmentIds ?? []
58
+ });
59
+ const built = await this.createArtifact(id, manifestBase, projection, input.attachmentIds ?? []);
60
+ try {
61
+ return this.store.createSessionShare({
62
+ id,
63
+ sourceSessionId: built.manifest.source.sessionId,
64
+ cutoffSeq: built.manifest.source.cutoffSeq,
65
+ artifactRelativePath: this.artifactRelativePath(id),
66
+ artifactSize: built.totalSize,
67
+ messageCount: built.manifest.messages.length,
68
+ attachmentCount: built.manifest.attachments.length,
69
+ includeToolActivities,
70
+ fileName: built.manifest.title,
71
+ ttlMs: input.ttlMs,
72
+ maxViews: input.maxViews,
73
+ description: input.description,
74
+ gatewayTokenHash: input.gatewayTokenHash
75
+ });
76
+ } catch (error) {
77
+ await this.removeArtifact(id);
78
+ throw error;
79
+ }
80
+ }
81
+ async refresh(sessionKey, shareId, input) {
82
+ const record = this.store.getById(shareId);
83
+ if (!record || record.kind !== "session") throw new Error("Session share not found");
84
+ const source = await this.loadExpectedSource(sessionKey, input);
85
+ if (source.snapshot.sessionId !== record.sourceSessionId) throw new Error("Session share belongs to a previous session");
86
+ const previous = await this.readManifest(record);
87
+ const includeToolActivities = input.includeToolActivities ?? record.includeToolActivities;
88
+ const attachmentIds = input.attachmentIds ?? previous.attachments.map((attachment) => attachment.id);
89
+ const projection = projectSessionShare(source.snapshot.entries);
90
+ const manifestBase = this.buildManifestBase(shareId, source, projection, {
91
+ includeToolActivities,
92
+ selectedAttachmentIds: attachmentIds
93
+ });
94
+ const finalDir = this.artifactDir(shareId);
95
+ const stagedDir = `${finalDir}.refresh-${randomUUID()}`;
96
+ const backupDir = `${finalDir}.backup-${randomUUID()}`;
97
+ const built = await this.writeArtifact(stagedDir, manifestBase, projection, attachmentIds);
98
+ let movedOld = false;
99
+ try {
100
+ await rename(finalDir, backupDir);
101
+ movedOld = true;
102
+ await rename(stagedDir, finalDir);
103
+ const updated = this.store.updateSessionSnapshot(shareId, {
104
+ cutoffSeq: built.manifest.source.cutoffSeq,
105
+ artifactSize: built.totalSize,
106
+ messageCount: built.manifest.messages.length,
107
+ attachmentCount: built.manifest.attachments.length,
108
+ includeToolActivities,
109
+ fileName: built.manifest.title
110
+ });
111
+ if (!updated) throw new Error("Session share not found");
112
+ await rm(backupDir, {
113
+ recursive: true,
114
+ force: true
115
+ }).catch((err) => {
116
+ log.warn({
117
+ err,
118
+ shareId
119
+ }, "Failed to remove previous Session share artifact");
120
+ });
121
+ return updated;
122
+ } catch (error) {
123
+ await rm(stagedDir, {
124
+ recursive: true,
125
+ force: true
126
+ });
127
+ if (movedOld) {
128
+ await rm(finalDir, {
129
+ recursive: true,
130
+ force: true
131
+ });
132
+ await rename(backupDir, finalDir).catch(() => void 0);
133
+ }
134
+ throw error;
135
+ }
136
+ }
137
+ list(sessionId) {
138
+ return this.store.getSessionShares(sessionId);
139
+ }
140
+ async readManifest(record) {
141
+ const path = join(resolveStateDir(), record.artifactRelativePath, "manifest.json");
142
+ const file = await stat(path);
143
+ if (!file.isFile() || file.size > MAX_MANIFEST_BYTES) throw new Error("Invalid Session share artifact");
144
+ const manifest = JSON.parse(await readFile(path, "utf8"));
145
+ if (manifest.schemaVersion !== MANIFEST_SCHEMA_VERSION || manifest.shareId !== record.id || typeof manifest.title !== "string" || typeof manifest.snapshotAt !== "string" || !manifest.source || manifest.source.sessionId !== record.sourceSessionId || manifest.source.cutoffSeq !== record.cutoffSeq || !Array.isArray(manifest.messages) || !manifest.messages.every(isSessionShareMessage) || !Array.isArray(manifest.toolActivities) || !manifest.toolActivities.every(isSessionShareToolActivity) || !Array.isArray(manifest.attachments) || !manifest.attachments.every(isSessionShareAttachment)) throw new Error("Invalid Session share artifact");
146
+ this.validateMessages(manifest.messages);
147
+ this.validateManifestRelations(record, manifest);
148
+ return manifest;
149
+ }
150
+ issueAssetTicket(record) {
151
+ return issueShareAssetTicket(record, ASSET_TICKET_TTL_MS);
152
+ }
153
+ verifyAssetTicket(record, ticket) {
154
+ return verifyShareAssetTicket(record, ticket);
155
+ }
156
+ async resolveAsset(record, attachmentId) {
157
+ const attachment = (await this.readManifest(record)).attachments.find((item) => item.id === attachmentId);
158
+ if (!attachment || attachment.artifactFileName !== attachment.id) return null;
159
+ const path = join(resolveStateDir(), record.artifactRelativePath, "assets", attachment.id);
160
+ if (await checksumFile(path).catch(() => "") !== attachment.checksum) return null;
161
+ return {
162
+ path,
163
+ attachment
164
+ };
165
+ }
166
+ async removeArtifact(shareId) {
167
+ await rm(this.artifactDir(shareId), {
168
+ recursive: true,
169
+ force: true
170
+ }).catch((err) => {
171
+ log.warn({
172
+ err,
173
+ shareId
174
+ }, "Failed to remove Session share artifact");
175
+ });
176
+ }
177
+ async loadExpectedSource(sessionKey, expected) {
178
+ const source = await this.loadSource(sessionKey);
179
+ if (source.snapshot.sessionId !== expected.expectedSessionId || source.snapshot.lastSeq !== expected.expectedCutoffSeq || source.metadata.updatedAt !== expected.expectedMetadataUpdatedAt) throw new SessionShareSnapshotConflictError();
180
+ return source;
181
+ }
182
+ async loadSource(sessionKey) {
183
+ const [metadata, snapshot] = await Promise.all([this.source.getMetadata(sessionKey), this.source.getSnapshot(sessionKey)]);
184
+ if (!metadata || !snapshot || !metadata.sessionId || metadata.sessionId !== snapshot.sessionId) throw new Error("Session not found");
185
+ return {
186
+ metadata,
187
+ snapshot
188
+ };
189
+ }
190
+ buildManifestBase(shareId, source, projection, options) {
191
+ this.validateMessages(projection.messages);
192
+ const selected = new Set(options.selectedAttachmentIds);
193
+ return {
194
+ schemaVersion: MANIFEST_SCHEMA_VERSION,
195
+ shareId,
196
+ source: {
197
+ sessionId: source.snapshot.sessionId,
198
+ cutoffSeq: source.snapshot.lastSeq
199
+ },
200
+ title: source.metadata.name?.trim() || "Shared conversation",
201
+ snapshotAt: (/* @__PURE__ */ new Date()).toISOString(),
202
+ messages: projection.messages.map((message) => ({
203
+ ...message,
204
+ attachmentIds: message.attachmentIds.filter((id) => selected.has(id))
205
+ })),
206
+ toolActivities: options.includeToolActivities ? projection.toolActivities : []
207
+ };
208
+ }
209
+ async createArtifact(shareId, manifestBase, projection, attachmentIds) {
210
+ const finalDir = this.artifactDir(shareId);
211
+ const stagedDir = `${finalDir}.staged-${randomUUID()}`;
212
+ const built = await this.writeArtifact(stagedDir, manifestBase, projection, attachmentIds);
213
+ try {
214
+ await rename(stagedDir, finalDir);
215
+ return built;
216
+ } catch (error) {
217
+ await rm(stagedDir, {
218
+ recursive: true,
219
+ force: true
220
+ });
221
+ throw error;
222
+ }
223
+ }
224
+ async writeArtifact(targetDir, manifestBase, projection, attachmentIds) {
225
+ const selected = [...new Set(attachmentIds)];
226
+ if (selected.length > MAX_ATTACHMENT_COUNT) throw new Error(`Select at most ${MAX_ATTACHMENT_COUNT} attachments`);
227
+ const candidates = new Map(projection.attachmentCandidates.map((candidate) => [candidate.id, candidate]));
228
+ for (const id of selected) if (!candidates.has(id) || !projection.attachmentUris.has(id)) throw new Error(`Attachment is not part of this session snapshot: ${id}`);
229
+ await mkdir(join(targetDir, "assets"), { recursive: true });
230
+ const attachments = [];
231
+ let totalAttachmentSize = 0;
232
+ try {
233
+ for (const id of selected) {
234
+ const candidate = candidates.get(id);
235
+ const source = await resolveMediaReference(projection.attachmentUris.get(id));
236
+ const sourceStat = await stat(source.path);
237
+ if (!sourceStat.isFile()) throw new Error(`Attachment is not a file: ${candidate.fileName}`);
238
+ if (sourceStat.size > MAX_ATTACHMENT_BYTES) throw new Error(`Attachment is too large: ${candidate.fileName}`);
239
+ totalAttachmentSize += sourceStat.size;
240
+ if (totalAttachmentSize > MAX_TOTAL_ATTACHMENT_BYTES) throw new Error("Selected attachments are too large");
241
+ const target = join(targetDir, "assets", id);
242
+ await copyFile(source.path, target);
243
+ const copied = await stat(target);
244
+ if (!copied.isFile() || copied.size !== sourceStat.size) throw new Error(`Attachment changed while copying: ${candidate.fileName}`);
245
+ attachments.push({
246
+ id,
247
+ messageId: candidate.messageId,
248
+ mimeType: publicMimeType(candidate.mimeType),
249
+ fileName: publicFileName(candidate.fileName),
250
+ size: copied.size,
251
+ artifactFileName: id,
252
+ checksum: await checksumFile(target)
253
+ });
254
+ }
255
+ const manifest = {
256
+ ...manifestBase,
257
+ attachments
258
+ };
259
+ const bytes = Buffer.from(`${JSON.stringify(manifest, null, 2)}\n`, "utf8");
260
+ if (bytes.length > MAX_MANIFEST_BYTES) throw new Error("Session share is too large");
261
+ await writeFile(join(targetDir, "manifest.json"), bytes, { mode: 384 });
262
+ return {
263
+ manifest,
264
+ totalSize: bytes.length + totalAttachmentSize
265
+ };
266
+ } catch (error) {
267
+ await rm(targetDir, {
268
+ recursive: true,
269
+ force: true
270
+ });
271
+ throw error;
272
+ }
273
+ }
274
+ artifactRelativePath(shareId) {
275
+ return join("share-artifacts", shareId);
276
+ }
277
+ artifactDir(shareId) {
278
+ return join(resolveStateDir(), this.artifactRelativePath(shareId));
279
+ }
280
+ validateMessages(messages) {
281
+ if (messages.length === 0) throw new Error("Session has no shareable messages");
282
+ if (messages.length > MAX_SHARE_MESSAGES) throw new Error(`Session has more than ${MAX_SHARE_MESSAGES} shareable messages`);
283
+ }
284
+ validateManifestRelations(record, manifest) {
285
+ if (manifest.messages.length !== record.messageCount || manifest.attachments.length !== record.attachmentCount) throw new Error("Invalid Session share artifact");
286
+ if (!record.includeToolActivities && manifest.toolActivities.length > 0) throw new Error("Invalid Session share artifact");
287
+ const attachments = new Map(manifest.attachments.map((attachment) => [attachment.id, attachment]));
288
+ if (attachments.size !== manifest.attachments.length) throw new Error("Invalid Session share artifact");
289
+ const messages = new Set(manifest.messages.map((message) => message.id));
290
+ for (const message of manifest.messages) for (const attachmentId of message.attachmentIds) {
291
+ const attachment = attachments.get(attachmentId);
292
+ if (!attachment || attachment.messageId !== message.id) throw new Error("Invalid Session share artifact");
293
+ }
294
+ if (manifest.attachments.some((attachment) => !messages.has(attachment.messageId))) throw new Error("Invalid Session share artifact");
295
+ }
296
+ };
297
+ function publicFileName(value) {
298
+ return basename(value.replaceAll("\\", "/")).replace(/[\u0000-\u001f\u007f]/g, "_").trim().slice(0, 200) || "attachment";
299
+ }
300
+ function publicMimeType(value) {
301
+ const normalized = value.split(";")[0]?.trim().toLowerCase() ?? "";
302
+ return /^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/.test(normalized) ? normalized : "application/octet-stream";
303
+ }
304
+ async function checksumFile(path) {
305
+ const hash = createHash("sha256");
306
+ for await (const chunk of createReadStream(path)) hash.update(chunk);
307
+ return hash.digest("hex");
308
+ }
309
+ function isSessionShareMessage(value) {
310
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
311
+ const message = value;
312
+ return typeof message.id === "string" && (message.role === "user" || message.role === "assistant") && typeof message.markdown === "string" && typeof message.createdAt === "string" && Array.isArray(message.attachmentIds) && message.attachmentIds.every((id) => typeof id === "string");
313
+ }
314
+ function isSessionShareToolActivity(value) {
315
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
316
+ const activity = value;
317
+ return typeof activity.id === "string" && (activity.messageId === void 0 || typeof activity.messageId === "string") && typeof activity.toolName === "string" && (activity.status === "completed" || activity.status === "failed") && typeof activity.createdAt === "string";
318
+ }
319
+ function isSessionShareAttachment(value) {
320
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
321
+ const attachment = value;
322
+ return typeof attachment.id === "string" && /^attachment-[a-f0-9]{24}$/.test(attachment.id) && typeof attachment.messageId === "string" && typeof attachment.mimeType === "string" && typeof attachment.fileName === "string" && typeof attachment.size === "number" && attachment.artifactFileName === attachment.id && typeof attachment.checksum === "string" && /^[a-f0-9]{64}$/.test(attachment.checksum);
323
+ }
324
+ //#endregion
325
+ export { SessionShareService, SessionShareSnapshotConflictError };
@@ -0,0 +1,7 @@
1
+ export interface TicketedShareRecord {
2
+ id: string;
3
+ snapshotRevision: number;
4
+ assetTicketSecret: string;
5
+ }
6
+ export declare function issueShareAssetTicket(record: TicketedShareRecord, ttlMs: number): string;
7
+ export declare function verifyShareAssetTicket(record: TicketedShareRecord, ticket: string): boolean;
@@ -0,0 +1,30 @@
1
+ import { createHmac, timingSafeEqual } from "node:crypto";
2
+ //#region src/share/share-asset-ticket.ts
3
+ function issueShareAssetTicket(record, ttlMs) {
4
+ const payload = Buffer.from(JSON.stringify({
5
+ shareId: record.id,
6
+ revision: record.snapshotRevision,
7
+ expiresAt: Date.now() + ttlMs
8
+ })).toString("base64url");
9
+ return `${payload}.${createHmac("sha256", record.assetTicketSecret).update(payload).digest("base64url")}`;
10
+ }
11
+ function verifyShareAssetTicket(record, ticket) {
12
+ const [payload, signature] = ticket.split(".");
13
+ if (!payload || !signature) return false;
14
+ const expected = createHmac("sha256", record.assetTicketSecret).update(payload).digest();
15
+ let actual;
16
+ try {
17
+ actual = Buffer.from(signature, "base64url");
18
+ } catch {
19
+ return false;
20
+ }
21
+ if (actual.length !== expected.length || !timingSafeEqual(actual, expected)) return false;
22
+ try {
23
+ const value = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
24
+ return value.shareId === record.id && value.revision === record.snapshotRevision && typeof value.expiresAt === "number" && Date.now() < value.expiresAt;
25
+ } catch {
26
+ return false;
27
+ }
28
+ }
29
+ //#endregion
30
+ export { issueShareAssetTicket, verifyShareAssetTicket };
@@ -1,5 +1,5 @@
1
1
  import type { DirectoryListing } from './share-store.js';
2
- import type { NoteShareRecord, ShareRecord } from './share-types.js';
2
+ import type { NoteShareRecord, SessionShareRecord, ShareRecord } from './share-types.js';
3
3
  export interface ShareLandingOgOptions {
4
4
  /** Absolute https/http URL of this landing page (for og:url). Omit if non-public. */
5
5
  absoluteShareUrl?: string | null;
@@ -10,8 +10,9 @@ export interface ShareLandingOgOptions {
10
10
  /** Description override (default: type + size). */
11
11
  description?: string;
12
12
  }
13
- /** Lightweight public shell for Note shares. Crawlers get metadata; browsers continue to the SPA preview. */
14
- export declare function renderNoteShareLandingPage(record: NoteShareRecord, previewUrl: string, options?: {
13
+ /** Lightweight public shell for state-owned snapshots. Crawlers get metadata; browsers continue to the SPA preview. */
14
+ export declare function renderSnapshotShareLandingPage(record: NoteShareRecord | SessionShareRecord, previewUrl: string, options: {
15
+ label: 'Note' | 'conversation';
15
16
  og?: ShareLandingOgOptions;
16
17
  }): string;
17
18
  /** Render the file download confirmation landing page (does not consume downloadCount). */
@@ -35,10 +35,10 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;b
35
35
  .empty{text-align:center;color:#94a3b8;padding:2rem}
36
36
  `;
37
37
  }
38
- /** Lightweight public shell for Note shares. Crawlers get metadata; browsers continue to the SPA preview. */
39
- function renderNoteShareLandingPage(record, previewUrl, options) {
38
+ /** Lightweight public shell for state-owned snapshots. Crawlers get metadata; browsers continue to the SPA preview. */
39
+ function renderSnapshotShareLandingPage(record, previewUrl, options) {
40
40
  const title = escapeHtml(record.fileName);
41
- const description = escapeHtml(record.description ?? "A Note shared via xopc");
41
+ const description = escapeHtml(record.description ?? `A ${options.label} shared via xopc`);
42
42
  const target = escapeHtml(previewUrl);
43
43
  return `<!DOCTYPE html>
44
44
  <html lang="zh">
@@ -57,7 +57,7 @@ ${renderOgTags({
57
57
  <meta http-equiv="refresh" content="0;url=${target}">
58
58
  </head>
59
59
  <body>
60
- <p><a href="${target}">Open shared Note</a></p>
60
+ <p><a href="${target}">Open shared ${options.label}</a></p>
61
61
  <script>location.replace(${JSON.stringify(previewUrl)})<\/script>
62
62
  </body>
63
63
  </html>`;
@@ -239,4 +239,4 @@ function renderShareExpiredPage(reason) {
239
239
  </html>`;
240
240
  }
241
241
  //#endregion
242
- export { renderFolderLandingPage, renderNoteShareLandingPage, renderShareExpiredPage, renderShareLandingPage };
242
+ export { renderFolderLandingPage, renderShareExpiredPage, renderShareLandingPage, renderSnapshotShareLandingPage };
@@ -1,4 +1,4 @@
1
- import type { ShareRecord, ShareConfig, CreateShareParams, WorkspaceShareRecord, NoteShareRecord, DirectoryShareRecord } from './share-types.js';
1
+ import type { ShareRecord, ShareConfig, CreateShareParams, WorkspaceShareRecord, NoteShareRecord, SessionShareRecord, DirectoryShareRecord } from './share-types.js';
2
2
  export interface DirectoryListingEntry {
3
3
  name: string;
4
4
  /** Workspace/share-relative POSIX path. */
@@ -57,6 +57,31 @@ export declare class ShareStore {
57
57
  fileName: string;
58
58
  }): NoteShareRecord | null;
59
59
  getNoteShares(noteId: string): NoteShareRecord[];
60
+ createSessionShare(input: {
61
+ id: string;
62
+ sourceSessionId: string;
63
+ cutoffSeq: number;
64
+ artifactRelativePath: string;
65
+ artifactSize: number;
66
+ messageCount: number;
67
+ attachmentCount?: number;
68
+ includeToolActivities?: boolean;
69
+ snapshotRevision?: number;
70
+ fileName: string;
71
+ ttlMs?: number;
72
+ maxViews?: number | null;
73
+ description?: string;
74
+ gatewayTokenHash: string;
75
+ }): SessionShareRecord;
76
+ getSessionShares(sessionId: string): SessionShareRecord[];
77
+ updateSessionSnapshot(id: string, patch: {
78
+ cutoffSeq: number;
79
+ artifactSize: number;
80
+ messageCount: number;
81
+ attachmentCount: number;
82
+ includeToolActivities: boolean;
83
+ fileName: string;
84
+ }): SessionShareRecord | null;
60
85
  private persistAndAudit;
61
86
  getById(id: string): ShareRecord | null;
62
87
  getByToken(token: string): ShareRecord | null;
@@ -112,7 +137,7 @@ export declare class ShareStore {
112
137
  private cleanupExpired;
113
138
  shutdown(): void;
114
139
  private resolveAndValidatePath;
115
- private cleanupNoteArtifact;
140
+ private cleanupStateArtifact;
116
141
  }
117
142
  export declare function resolveMimeType(fileName: string): string;
118
143
  /** HTTP Content-Type with charset for text-like bodies (browser inline preview). */
@@ -254,6 +254,69 @@ var ShareStore = class {
254
254
  getNoteShares(noteId) {
255
255
  return this.getAllShares().filter((record) => record.kind === "note" && record.sourceNoteId === noteId);
256
256
  }
257
+ createSessionShare(input) {
258
+ if (!this.config.enabled) throw new Error("Session sharing is disabled");
259
+ if (this.getActiveShares().length >= this.config.maxActiveShares) throw new Error(`Maximum active shares reached (${this.config.maxActiveShares})`);
260
+ const ttlMs = input.ttlMs ?? this.config.defaultTtlMs;
261
+ if (ttlMs < 6e4 || ttlMs > this.config.maxTtlMs) throw new Error(`TTL must be between 60s and ${this.config.maxTtlMs / 1e3}s`);
262
+ if (input.maxViews !== void 0 && input.maxViews !== null && (input.maxViews < 1 || input.maxViews > 1e3)) throw new Error("maxViews must be between 1 and 1000");
263
+ const now = /* @__PURE__ */ new Date();
264
+ const record = {
265
+ id: input.id,
266
+ token: randomBytes(32).toString("base64url"),
267
+ kind: "session",
268
+ fileName: input.fileName,
269
+ fileSize: input.artifactSize,
270
+ mimeType: "application/x-xopc-session",
271
+ workspaceRelativePath: "",
272
+ sourceSessionId: input.sourceSessionId,
273
+ cutoffSeq: input.cutoffSeq,
274
+ artifactRelativePath: input.artifactRelativePath,
275
+ messageCount: input.messageCount,
276
+ attachmentCount: input.attachmentCount ?? 0,
277
+ includeToolActivities: input.includeToolActivities ?? false,
278
+ snapshotRevision: input.snapshotRevision ?? 1,
279
+ assetTicketSecret: randomBytes(32).toString("base64url"),
280
+ createdAt: now.toISOString(),
281
+ expiresAt: new Date(now.getTime() + ttlMs).toISOString(),
282
+ maxViews: input.maxViews ?? null,
283
+ downloadCount: 0,
284
+ revoked: false,
285
+ createdByTokenHash: input.gatewayTokenHash,
286
+ description: input.description
287
+ };
288
+ this.shares.set(record.id, record);
289
+ this.tokenIndex.set(record.token, record.id);
290
+ this.persistAndAudit(record, "share.create", `Session share created: ${record.fileName}`, {
291
+ sourceSessionId: record.sourceSessionId,
292
+ cutoffSeq: record.cutoffSeq,
293
+ messageCount: record.messageCount,
294
+ ttlMs
295
+ });
296
+ return record;
297
+ }
298
+ getSessionShares(sessionId) {
299
+ return this.getAllShares().filter((record) => record.kind === "session" && record.sourceSessionId === sessionId);
300
+ }
301
+ updateSessionSnapshot(id, patch) {
302
+ const record = this.shares.get(id);
303
+ if (!record || record.kind !== "session") return null;
304
+ record.cutoffSeq = patch.cutoffSeq;
305
+ record.fileSize = patch.artifactSize;
306
+ record.messageCount = patch.messageCount;
307
+ record.attachmentCount = patch.attachmentCount;
308
+ record.includeToolActivities = patch.includeToolActivities;
309
+ record.fileName = patch.fileName;
310
+ record.snapshotRevision += 1;
311
+ this.persistSync();
312
+ logShareAudit("share.update", {
313
+ shareId: id,
314
+ sourceSessionId: record.sourceSessionId,
315
+ cutoffSeq: record.cutoffSeq,
316
+ snapshotRevision: record.snapshotRevision
317
+ }, `Session share snapshot updated: ${record.fileName}`);
318
+ return record;
319
+ }
257
320
  persistAndAudit(record, event, message, extra) {
258
321
  this.persistSync();
259
322
  logShareAudit(event, {
@@ -455,7 +518,7 @@ var ShareStore = class {
455
518
  const record = this.shares.get(id);
456
519
  if (!record) return false;
457
520
  record.revoked = true;
458
- this.cleanupNoteArtifact(record);
521
+ this.cleanupStateArtifact(record);
459
522
  this.invalidateListingCache(id);
460
523
  this.persistSync();
461
524
  logShareAudit("share.revoke", {
@@ -471,7 +534,7 @@ var ShareStore = class {
471
534
  const record = this.shares.get(id);
472
535
  if (record && !record.revoked) {
473
536
  record.revoked = true;
474
- this.cleanupNoteArtifact(record);
537
+ this.cleanupStateArtifact(record);
475
538
  this.invalidateListingCache(id);
476
539
  count++;
477
540
  logShareAudit("share.revoke", {
@@ -489,7 +552,7 @@ var ShareStore = class {
489
552
  let count = 0;
490
553
  for (const record of this.shares.values()) if (!record.revoked && now >= new Date(record.expiresAt).getTime()) {
491
554
  record.revoked = true;
492
- this.cleanupNoteArtifact(record);
555
+ this.cleanupStateArtifact(record);
493
556
  this.invalidateListingCache(record.id);
494
557
  count++;
495
558
  }
@@ -583,7 +646,7 @@ var ShareStore = class {
583
646
  let removed = 0;
584
647
  for (const [id, record] of this.shares) {
585
648
  const expiredMs = now - new Date(record.expiresAt).getTime();
586
- if (expiredMs >= 0) this.cleanupNoteArtifact(record);
649
+ if (expiredMs >= 0) this.cleanupStateArtifact(record);
587
650
  if (expiredMs > EXPIRED_RETENTION_MS) {
588
651
  this.shares.delete(id);
589
652
  this.tokenIndex.delete(record.token);
@@ -629,14 +692,14 @@ var ShareStore = class {
629
692
  if (relToRoot.startsWith("..") || relToRoot.split(/[/\\]/).includes("..")) throw new Error("Path is outside workspace");
630
693
  return abs;
631
694
  }
632
- cleanupNoteArtifact(record) {
633
- if (record.kind !== "note") return;
695
+ cleanupStateArtifact(record) {
696
+ if (record.kind !== "note" && record.kind !== "session") return;
634
697
  const expected = join("share-artifacts", record.id);
635
698
  if (record.artifactRelativePath !== expected) {
636
699
  log.warn({
637
700
  shareId: record.id,
638
701
  artifactRelativePath: record.artifactRelativePath
639
- }, "Skipped unsafe Note share artifact cleanup path");
702
+ }, "Skipped unsafe share artifact cleanup path");
640
703
  return;
641
704
  }
642
705
  rm(join(resolveStateDir(), expected), {
@@ -646,7 +709,7 @@ var ShareStore = class {
646
709
  log.warn({
647
710
  err,
648
711
  shareId: record.id
649
- }, "Failed to clean Note share artifact");
712
+ }, "Failed to clean share artifact");
650
713
  });
651
714
  }
652
715
  };
@@ -1,5 +1,5 @@
1
1
  export type WorkspaceShareKind = 'file' | 'directory';
2
- export type ShareKind = WorkspaceShareKind | 'note';
2
+ export type ShareKind = WorkspaceShareKind | 'note' | 'session';
3
3
  export interface ShareDirectoryMeta {
4
4
  /** 'browse' shows a file tree; 'zip-only' hides structure and only offers ZIP. */
5
5
  mode: 'browse' | 'zip-only';
@@ -81,8 +81,23 @@ export interface NoteShareRecord extends ShareRecordBase {
81
81
  assetTicketSecret: string;
82
82
  directory?: undefined;
83
83
  }
84
+ export interface SessionShareRecord extends ShareRecordBase {
85
+ kind: 'session';
86
+ /** Sessions are state-owned objects, not workspace paths. */
87
+ workspaceRelativePath: '';
88
+ sourceSessionId: string;
89
+ cutoffSeq: number;
90
+ artifactRelativePath: string;
91
+ messageCount: number;
92
+ attachmentCount: number;
93
+ includeToolActivities: boolean;
94
+ snapshotRevision: number;
95
+ /** Private HMAC key for short-lived public asset tickets. */
96
+ assetTicketSecret: string;
97
+ directory?: undefined;
98
+ }
84
99
  export type WorkspaceShareRecord = FileShareRecord | DirectoryShareRecord;
85
- export type ShareRecord = WorkspaceShareRecord | NoteShareRecord;
100
+ export type ShareRecord = WorkspaceShareRecord | NoteShareRecord | SessionShareRecord;
86
101
  export interface CreateShareParams {
87
102
  /** Workspace-relative file path. */
88
103
  path: string;
@@ -1,5 +1,5 @@
1
+ import { enumerateLanGatewayCandidates } from "../gateway/host.js";
1
2
  import { loadTunnelState } from "../tunnel/tunnel-state.js";
2
- import { resolveLanGatewayUrl } from "../tunnel/tunnel-qr.js";
3
3
  //#region src/share/share-url.ts
4
4
  function resolveShareUrl(token, ctx) {
5
5
  const tunnelState = loadTunnelState();
@@ -32,7 +32,7 @@ function resolveShareUrl(token, ctx) {
32
32
  };
33
33
  }
34
34
  function buildLanUrl(host, port, path) {
35
- const lanBase = resolveLanGatewayUrl(host, port);
35
+ const lanBase = isLoopbackHost(host) ? null : enumerateLanGatewayCandidates(port).find((candidate) => candidate.address === host)?.url ?? `http://${host.includes(":") ? `[${host}]` : host}:${port}`;
36
36
  if (!lanBase) return null;
37
37
  return `${lanBase.replace(/\/+$/, "")}${path}`;
38
38
  }