@xopcai/xopc 0.0.234 → 0.0.238

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 (320) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/feishu/src/schema/config-schema.d.ts +8 -8
  3. package/dist/extensions/telegram/src/config-schema.d.ts +8 -8
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/extensions/weixin/src/config-schema.d.ts +3 -3
  6. package/dist/gateway/static/root/assets/{activity-store-BzswYHcj.js → activity-store-DLfkwJzZ.js} +1 -1
  7. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CztNAQyE.js → agent-avatar-dicebear-BCZ6T3y8.js} +1 -1
  8. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-KPtQudPf.js +1 -0
  9. package/dist/gateway/static/root/assets/agents-DKQZKGCB.js +1 -0
  10. package/dist/gateway/static/root/assets/{api-7zOtMbaE.js → api-IUm57Zse.js} +1 -1
  11. package/dist/gateway/static/root/assets/app-management-settings-panel-B_h6HVgw.js +1 -0
  12. package/dist/gateway/static/root/assets/appearance-settings-D07Ew40N.js +1 -0
  13. package/dist/gateway/static/root/assets/apps-page-_toby2SK.js +1 -0
  14. package/dist/gateway/static/root/assets/{archive-plugin-DawToDU8.js → archive-plugin-Bha1jUhj.js} +1 -1
  15. package/dist/gateway/static/root/assets/{attachment-load-BpCKsdiO.js → attachment-load-C2Ac3q6g.js} +1 -1
  16. package/dist/gateway/static/root/assets/{automations-page-a6_hTplT.js → automations-page-Bc4Is3z0.js} +1 -1
  17. package/dist/gateway/static/root/assets/automations-workspace-DH-QeQ0O.js +6 -0
  18. package/dist/gateway/static/root/assets/{binary-plugins-OqUf-uET.js → binary-plugins-yMQJYHIQ.js} +1 -1
  19. package/dist/gateway/static/root/assets/{block-editor-9OAYqVKF.js → block-editor-DrNzI_0p.js} +56 -56
  20. package/dist/gateway/static/root/assets/browser-settings-page-Bv8GclZd.js +8 -0
  21. package/dist/gateway/static/root/assets/{browser-workflow-inputs-4ooVX-Tx.js → browser-workflow-inputs-CHHw7Ula.js} +1 -1
  22. package/dist/gateway/static/root/assets/{browser-workflows-page-CUgwXXsi.js → browser-workflows-page-D_EOs50E.js} +2 -2
  23. package/dist/gateway/static/root/assets/capabilities-settings-panel-gKLN0aaW.js +7 -0
  24. package/dist/gateway/static/root/assets/channels-settings-Bh7BqWsN.js +1 -0
  25. package/dist/gateway/static/root/assets/{channels-status-swr-BDJvMnA_.js → channels-status-swr-CwUSKmeY.js} +1 -1
  26. package/dist/gateway/static/root/assets/chat-terminal-dock-B7agEwma.js +36 -0
  27. package/dist/gateway/static/root/assets/connectors-page-DifO0WX4.js +2 -0
  28. package/dist/gateway/static/root/assets/{cron-expression-a9Jyianb.js → cron-expression-bjxQQFdv.js} +1 -1
  29. package/dist/gateway/static/root/assets/{date-picker-B_l2CHWO.js → date-picker-C7ujLHll.js} +1 -1
  30. package/dist/gateway/static/root/assets/dependency-picker-rl8E7nXp.js +1 -0
  31. package/dist/gateway/static/root/assets/{desktop-pet-ZCBsj8Je.js → desktop-pet-D4GbYBcD.js} +1 -1
  32. package/dist/gateway/static/root/assets/desktop-pet-settings-Bo34tFlD.js +1 -0
  33. package/dist/gateway/static/root/assets/{extension-debug-page-CMXbAkx-.js → extension-debug-page-DuPa1bVQ.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-page-WWePedpo.js → extension-page-CB9xF3qo.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-settings-page-DjIhNJVI.js → extension-settings-page-CovEdmGD.js} +1 -1
  36. package/dist/gateway/static/root/assets/{files-Dp8_uGTO.js → files-DQjhZjr2.js} +1 -1
  37. package/dist/gateway/static/root/assets/{gateway-config-api-BNj6srhV.js → gateway-config-api-CAaoukkR.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-config-swr-R702lNJR.js → gateway-config-swr-DfMY-MLf.js} +1 -1
  39. package/dist/gateway/static/root/assets/gateway-settings-CesXGTe3.js +1 -0
  40. package/dist/gateway/static/root/assets/{gateway-startup-retry-2rVSUvyw.js → gateway-startup-retry-S6aB0hVI.js} +1 -1
  41. package/dist/gateway/static/root/assets/heartbeat-settings-Bu5cIcNb.js +1 -0
  42. package/dist/gateway/static/root/assets/home-page-sQfx98tH.js +1 -0
  43. package/dist/gateway/static/root/assets/{image-generation-api-B28USRCK.js → image-generation-api-DOX5uq-R.js} +1 -1
  44. package/dist/gateway/static/root/assets/index-C73V7tJP.js +70 -0
  45. package/dist/gateway/static/root/assets/index-C9rUND9-.css +2 -0
  46. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-d12AAEaC.js → keyboard-shortcuts-settings-CpZxPmd0.js} +1 -1
  47. package/dist/gateway/static/root/assets/local-app-workbench-page-DjvHSI0e.js +2 -0
  48. package/dist/gateway/static/root/assets/local-apps-page-5KTZwLbX.js +1 -0
  49. package/dist/gateway/static/root/assets/{locale-store-8k4mvYGL.js → locale-store-XDFAPNNu.js} +1 -1
  50. package/dist/gateway/static/root/assets/logs-page-frYgoe2x.js +2 -0
  51. package/dist/gateway/static/root/assets/management-settings-9iZjSpHe.js +1 -0
  52. package/dist/gateway/static/root/assets/{markdown-split-7rTfQCN_.js → markdown-split-C4-0M8mu.js} +1 -1
  53. package/dist/gateway/static/root/assets/markdown-view-Y68dCxuc.css +1 -0
  54. package/dist/gateway/static/root/assets/markdown-view-v-O3cOpk.js +201 -0
  55. package/dist/gateway/static/root/assets/{media-plugins-BIfKo5Ow.js → media-plugins-CjMa9GMF.js} +1 -1
  56. package/dist/gateway/static/root/assets/messages-B1HDp_j8.js +3 -0
  57. package/dist/gateway/static/root/assets/mobile-pairing-wizard-DikJ7HCm.js +1 -0
  58. package/dist/gateway/static/root/assets/models-hub-cache-Bngs8o1m.js +1 -0
  59. package/dist/gateway/static/root/assets/{notes-api-p2Pncp2B.js → notes-api-BMhFpRmW.js} +1 -1
  60. package/dist/gateway/static/root/assets/{notes-page-dOvbZBOQ.js → notes-page-CC45W2KR.js} +1 -1
  61. package/dist/gateway/static/root/assets/notes-workbench-BFreGbmY.js +4 -0
  62. package/dist/gateway/static/root/assets/{oauth-api-DpLONwfK.js → oauth-api-B_pcOUfT.js} +1 -1
  63. package/dist/gateway/static/root/assets/popover-select-DBrVS3tZ.js +1 -0
  64. package/dist/gateway/static/root/assets/{product-delivery-tRr-7IxY.js → product-delivery-dUJgmBQZ.js} +1 -1
  65. package/dist/gateway/static/root/assets/product-open-page-B8cjLdm4.js +1 -0
  66. package/dist/gateway/static/root/assets/project-detail-page-53z9nB5L.js +1 -0
  67. package/dist/gateway/static/root/assets/projects-page-DR7OvyAl.js +1 -0
  68. package/dist/gateway/static/root/assets/{registry-api-B7b0LJgI.js → registry-api-DeVvBsl4.js} +1 -1
  69. package/dist/gateway/static/root/assets/remote-access-hub-BkSGDDbn.js +1 -0
  70. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-D3PS55Yg.js → runtime-tools-settings-panel-DLv-QsQo.js} +1 -1
  71. package/dist/gateway/static/root/assets/{schema-form-H-aeWTzM.js → schema-form-DDW7aJWa.js} +1 -1
  72. package/dist/gateway/static/root/assets/sessions-page-C-yaSuuQ.js +1 -0
  73. package/dist/gateway/static/root/assets/settings-advanced-gate-CelrRPXt.js +1 -0
  74. package/dist/gateway/static/root/assets/{settings-form-section-B9oF8Rhw.js → settings-form-section-5NTg906_.js} +1 -1
  75. package/dist/gateway/static/root/assets/settings-loading-skeleton-CAmWMaOT.js +1 -0
  76. package/dist/gateway/static/root/assets/{settings-page-C6pmQNzY.js → settings-page-DgTYtrmh.js} +1 -1
  77. package/dist/gateway/static/root/assets/setup-status-panel-Dm_gdAfm.js +1 -0
  78. package/dist/gateway/static/root/assets/share-preview-page-BX2Ev7-I.js +2 -0
  79. package/dist/gateway/static/root/assets/shares-settings-D2Zd9l04.js +1 -0
  80. package/dist/gateway/static/root/assets/skeleton-BwbyijEw.js +1 -0
  81. package/dist/gateway/static/root/assets/skill-reload-api-BvND7xsL.js +1 -0
  82. package/dist/gateway/static/root/assets/{skills-page-CfNV6kgb.js → skills-page-Cmqu9f_n.js} +1 -1
  83. package/dist/gateway/static/root/assets/{skills-page.utils-DgxGb7v7.js → skills-page.utils-KOxLvm84.js} +1 -1
  84. package/dist/gateway/static/root/assets/system-settings-panel-CS7cDwv2.js +1 -0
  85. package/dist/gateway/static/root/assets/task-detail-page-COpgFG6K.js +1 -0
  86. package/dist/gateway/static/root/assets/{theme-store-CpcBI73Q.js → theme-store-5-XHH7F0.js} +1 -1
  87. package/dist/gateway/static/root/assets/tunnel-api-D3h311_s.js +1 -0
  88. package/dist/gateway/static/root/assets/{use-autosave-DR7YWBzR.js → use-autosave-DvATIVb_.js} +1 -1
  89. package/dist/gateway/static/root/assets/user-context-page-PKrbPu4w.js +1 -0
  90. package/dist/gateway/static/root/assets/{voice-api-key-field-BZhqoxBR.js → voice-api-key-field-C3BgRKG2.js} +1 -1
  91. package/dist/gateway/static/root/assets/{voice-config-api-ynE-vY6I.js → voice-config-api-Bk_bVeGX.js} +1 -1
  92. package/dist/gateway/static/root/assets/{work-discovery-overlay-CouKiK45.js → work-discovery-overlay-DHcQSZZD.js} +1 -1
  93. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-CUqAESrr.js → workflow-run-setup-panel-Nx6xmy_N.js} +2 -2
  94. package/dist/gateway/static/root/assets/workflows-page-DBkP6B4E.js +5 -0
  95. package/dist/gateway/static/root/index.html +19 -18
  96. package/dist/package.js +1 -1
  97. package/dist/packages/gateway-contract/src/device-pairing.js +39 -0
  98. package/dist/packages/gateway-contract/src/model-selection.js +7 -0
  99. package/dist/packages/gateway-contract/src/new-session.js +9 -2
  100. package/dist/packages/gateway-contract/src/turn-outcome.js +27 -2
  101. package/dist/src/agent/agent-manager.js +4 -4
  102. package/dist/src/agent/background-review/run-background-review.js +1 -1
  103. package/dist/src/agent/embedded/model-runtime.js +1 -1
  104. package/dist/src/agent/embedded/run-for-session.js +2 -2
  105. package/dist/src/agent/embedded/run-turn.js +5 -0
  106. package/dist/src/agent/image/tool-model-config.js +1 -1
  107. package/dist/src/agent/ipc/inbox.js +1 -1
  108. package/dist/src/agent/mcp/oauth/mcp-oauth-store.js +1 -1
  109. package/dist/src/agent/models/manager.d.ts +3 -0
  110. package/dist/src/agent/models/manager.js +9 -0
  111. package/dist/src/agent/prompt/sections/tooling.js +1 -0
  112. package/dist/src/agent/service.js +2 -2
  113. package/dist/src/agent/session/session-config-service.d.ts +6 -2
  114. package/dist/src/agent/session/session-config-service.js +78 -17
  115. package/dist/src/agent/session/session-hydrator.d.ts +3 -4
  116. package/dist/src/agent/session/session-hydrator.js +19 -8
  117. package/dist/src/agent/session/session-inspector.d.ts +3 -1
  118. package/dist/src/agent/session/session-inspector.js +8 -4
  119. package/dist/src/agent/skills/hub-lock.js +1 -1
  120. package/dist/src/agent/tasks/task-judge-service.js +3 -3
  121. package/dist/src/agent/tools/create-share-tool.js +1 -1
  122. package/dist/src/agent/tools/exec-command.js +1 -0
  123. package/dist/src/agent/tools/publish-artifacts.d.ts +1 -0
  124. package/dist/src/agent/tools/publish-artifacts.js +16 -5
  125. package/dist/src/agent/tools/send-media.js +1 -1
  126. package/dist/src/agent/tools/workflow-tool.js +1 -1
  127. package/dist/src/agent/tools/write.js +1 -1
  128. package/dist/src/agent/tools/xopc-use-tool.js +2 -2
  129. package/dist/src/agent/transcript/thinking-types.d.ts +1 -1
  130. package/dist/src/agent/transcript/thinking-types.js +2 -0
  131. package/dist/src/agent-config/schema.d.ts +16 -16
  132. package/dist/src/ai-assist/text-assist.js +1 -1
  133. package/dist/src/auth/credentials.js +2 -2
  134. package/dist/src/auth/profiles/store.js +1 -1
  135. package/dist/src/auth/sync-provider-auth.js +2 -2
  136. package/dist/src/automations/domain/validation.d.ts +62 -62
  137. package/dist/src/automations/draft/automation-draft-validator.d.ts +10 -10
  138. package/dist/src/browser/providers/browser-ext-install.js +1 -1
  139. package/dist/src/chat-commands/builtins/thinking.js +1 -0
  140. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  141. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  142. package/dist/src/cli/commands/models.js +1 -1
  143. package/dist/src/config/index.js +4 -4
  144. package/dist/src/config/loader.js +1 -1
  145. package/dist/src/config/models-json.d.ts +137 -11
  146. package/dist/src/config/models-json.js +29 -2
  147. package/dist/src/config/schema.d.ts +15 -15
  148. package/dist/src/execution-environments/git.d.ts +27 -0
  149. package/dist/src/execution-environments/git.js +125 -0
  150. package/dist/src/execution-environments/index.d.ts +7 -0
  151. package/dist/src/execution-environments/index.js +8 -0
  152. package/dist/src/execution-environments/local-worktree-manager.d.ts +37 -0
  153. package/dist/src/execution-environments/local-worktree-manager.js +322 -0
  154. package/dist/src/execution-environments/paths.d.ts +2 -0
  155. package/dist/src/execution-environments/paths.js +18 -0
  156. package/dist/src/execution-environments/session-environment-service.d.ts +22 -0
  157. package/dist/src/execution-environments/session-environment-service.js +73 -0
  158. package/dist/src/execution-environments/store.d.ts +13 -0
  159. package/dist/src/execution-environments/store.js +183 -0
  160. package/dist/src/execution-environments/subject.d.ts +2 -0
  161. package/dist/src/execution-environments/subject.js +12 -0
  162. package/dist/src/execution-environments/types.d.ts +74 -0
  163. package/dist/src/execution-environments/types.js +54 -0
  164. package/dist/src/extensions/lockfile.js +1 -1
  165. package/dist/src/files/file-service.d.ts +10 -2
  166. package/dist/src/files/file-service.js +33 -12
  167. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  168. package/dist/src/gateway/agents-admin.js +1 -1
  169. package/dist/src/gateway/custom-image-providers.d.ts +1 -1
  170. package/dist/src/gateway/file-path-classifier.d.ts +30 -0
  171. package/dist/src/gateway/file-path-classifier.js +105 -0
  172. package/dist/src/gateway/file-reference-errors.d.ts +6 -0
  173. package/dist/src/gateway/file-reference-errors.js +21 -0
  174. package/dist/src/gateway/file-reference-registry.d.ts +34 -0
  175. package/dist/src/gateway/file-reference-registry.js +45 -0
  176. package/dist/src/gateway/file-space-service.d.ts +4 -0
  177. package/dist/src/gateway/file-space-service.js +19 -0
  178. package/dist/src/gateway/hono/app.js +3 -1
  179. package/dist/src/gateway/hono/lib/config-payload.d.ts +4 -4
  180. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  181. package/dist/src/gateway/hono/routes/chat-model-config.d.ts +34 -0
  182. package/dist/src/gateway/hono/routes/chat-model-config.js +42 -0
  183. package/dist/src/gateway/hono/routes/device-pairing-approval.d.ts +3 -0
  184. package/dist/src/gateway/hono/routes/device-pairing-approval.js +100 -0
  185. package/dist/src/gateway/hono/routes/devices.js +15 -8
  186. package/dist/src/gateway/hono/routes/execution-environments.d.ts +3 -0
  187. package/dist/src/gateway/hono/routes/execution-environments.js +136 -0
  188. package/dist/src/gateway/hono/routes/file-references.d.ts +4 -0
  189. package/dist/src/gateway/hono/routes/file-references.js +98 -0
  190. package/dist/src/gateway/hono/routes/files.js +39 -17
  191. package/dist/src/gateway/hono/routes/html-preview.d.ts +4 -0
  192. package/dist/src/gateway/hono/routes/html-preview.js +45 -0
  193. package/dist/src/gateway/hono/routes/index.js +4 -0
  194. package/dist/src/gateway/hono/routes/mobile-privacy.d.ts +3 -0
  195. package/dist/src/gateway/hono/routes/mobile-privacy.js +13 -0
  196. package/dist/src/gateway/hono/routes/models.js +10 -1
  197. package/dist/src/gateway/hono/routes/projects.js +43 -4
  198. package/dist/src/gateway/hono/routes/session-input-handler.d.ts +15 -1
  199. package/dist/src/gateway/hono/routes/session-input-handler.js +122 -52
  200. package/dist/src/gateway/hono/routes/sessions.js +105 -22
  201. package/dist/src/gateway/hono/routes/shares.js +18 -10
  202. package/dist/src/gateway/hono/routes/tasks.js +7 -15
  203. package/dist/src/gateway/mobile-privacy.d.ts +7 -0
  204. package/dist/src/gateway/mobile-privacy.js +102 -0
  205. package/dist/src/gateway/security/csp.d.ts +1 -1
  206. package/dist/src/gateway/security/csp.js +2 -2
  207. package/dist/src/gateway/security/gateway-scopes.js +1 -0
  208. package/dist/src/gateway/service/agent-runner.d.ts +1 -1
  209. package/dist/src/gateway/service/config-coordinator.js +1 -1
  210. package/dist/src/gateway/service/session-input-coordinator.d.ts +2 -1
  211. package/dist/src/gateway/service/session-input-coordinator.js +14 -5
  212. package/dist/src/gateway/service/sessions-api.d.ts +4 -12
  213. package/dist/src/gateway/service/sessions-api.js +13 -0
  214. package/dist/src/gateway/service.d.ts +1 -1
  215. package/dist/src/gateway/service.js +3 -3
  216. package/dist/src/gateway/session-context-summary.d.ts +5 -0
  217. package/dist/src/gateway/session-context-summary.js +151 -0
  218. package/dist/src/i18n/response-language.d.ts +1 -1
  219. package/dist/src/projects/index.js +3 -3
  220. package/dist/src/projects/project-kind.d.ts +7 -0
  221. package/dist/src/projects/project-kind.js +6 -1
  222. package/dist/src/projects/project-service.js +10 -2
  223. package/dist/src/projects/project-store.d.ts +1 -0
  224. package/dist/src/projects/project-store.js +10 -7
  225. package/dist/src/projects/types.d.ts +4 -0
  226. package/dist/src/providers/auth-runtime/resolve-auth.js +1 -1
  227. package/dist/src/providers/index.js +2 -2
  228. package/dist/src/providers/model-registry.js +3 -1
  229. package/dist/src/providers/model-thinking.d.ts +4 -0
  230. package/dist/src/providers/model-thinking.js +41 -0
  231. package/dist/src/providers/register-runtime-providers.js +1 -1
  232. package/dist/src/session/config-types.d.ts +1 -0
  233. package/dist/src/session/index.js +1 -1
  234. package/dist/src/session/model-config-lock.d.ts +2 -0
  235. package/dist/src/session/model-config-lock.js +14 -0
  236. package/dist/src/session/session-workspace.d.ts +2 -1
  237. package/dist/src/session/session-workspace.js +5 -1
  238. package/dist/src/session/store.js +1 -1
  239. package/dist/src/session/turn-outcome-projector.js +9 -9
  240. package/dist/src/share/hosted-session-share.js +1 -1
  241. package/dist/src/storage/sqlite/config-repository.d.ts +5 -0
  242. package/dist/src/storage/sqlite/config-repository.js +14 -6
  243. package/dist/src/storage/sqlite/device-access-repository.d.ts +2 -0
  244. package/dist/src/storage/sqlite/device-access-repository.js +12 -2
  245. package/dist/src/storage/sqlite/device-pairing-approval.d.ts +19 -0
  246. package/dist/src/storage/sqlite/device-pairing-approval.js +154 -0
  247. package/dist/src/storage/sqlite/device-pairing-repository.d.ts +1 -1
  248. package/dist/src/storage/sqlite/device-pairing-repository.js +11 -4
  249. package/dist/src/storage/sqlite/index.js +2 -2
  250. package/dist/src/storage/sqlite/migrations/141_device_pairing_approval.sql +17 -0
  251. package/dist/src/storage/sqlite/migrations/142_session_input_instance.sql +1 -0
  252. package/dist/src/storage/sqlite/migrations/143_fixed_session_model.sql +1 -0
  253. package/dist/src/storage/sqlite/migrations/144_execution_environments.sql +59 -0
  254. package/dist/src/storage/sqlite/migrations/145_project_execution_mode.sql +5 -0
  255. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  256. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  257. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  258. package/dist/src/storage/sqlite/row-mappers.d.ts +1 -0
  259. package/dist/src/storage/sqlite/row-mappers.js +3 -2
  260. package/dist/src/storage/sqlite/schema.js +1 -1
  261. package/dist/src/storage/sqlite/session-input-repository.d.ts +5 -0
  262. package/dist/src/storage/sqlite/session-input-repository.js +15 -4
  263. package/dist/src/storage/sqlite/session-repository.js +1 -1
  264. package/dist/src/tasks/execution-context.d.ts +3 -1
  265. package/dist/src/tasks/execution-context.js +7 -2
  266. package/dist/src/tasks/task-signal-service.js +1 -1
  267. package/dist/src/tui/backends/embedded-backend.js +1 -1
  268. package/dist/src/tui/components/thinking-selector.js +1 -0
  269. package/dist/src/tui/tui-settings.js +1 -1
  270. package/dist/src/tui/tui-startup-resources.js +1 -1
  271. package/dist/src/tui/tui.js +1 -1
  272. package/dist/src/user-context/config.d.ts +9 -9
  273. package/dist/src/work-discovery/service.d.ts +1 -1
  274. package/dist/src/workflows/service/workflow-run-service.js +1 -1
  275. package/package.json +3 -3
  276. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-BHeLVAW5.js +0 -1
  277. package/dist/gateway/static/root/assets/agents-B8c0U7Ze.js +0 -1
  278. package/dist/gateway/static/root/assets/app-management-settings-panel-BxBMAdWc.js +0 -1
  279. package/dist/gateway/static/root/assets/appearance-settings-DVAxCOPL.js +0 -1
  280. package/dist/gateway/static/root/assets/apps-page-BtzXxSYK.js +0 -1
  281. package/dist/gateway/static/root/assets/automations-workspace-C7ZwZl04.js +0 -6
  282. package/dist/gateway/static/root/assets/browser-settings-page-CEHhbDj0.js +0 -8
  283. package/dist/gateway/static/root/assets/capabilities-settings-panel-CAbI9beX.js +0 -7
  284. package/dist/gateway/static/root/assets/channels-settings-BksDnAyv.js +0 -1
  285. package/dist/gateway/static/root/assets/chat-terminal-dock-DB9zi_dy.js +0 -36
  286. package/dist/gateway/static/root/assets/connectors-page-CnY8lcGJ.js +0 -2
  287. package/dist/gateway/static/root/assets/dependency-picker-DjcEIzVJ.js +0 -1
  288. package/dist/gateway/static/root/assets/desktop-pet-settings-DJJf0EvL.js +0 -1
  289. package/dist/gateway/static/root/assets/gateway-settings-DvlFDxhZ.js +0 -1
  290. package/dist/gateway/static/root/assets/heartbeat-settings-Dlahslof.js +0 -1
  291. package/dist/gateway/static/root/assets/home-page-DJhUd30b.js +0 -1
  292. package/dist/gateway/static/root/assets/index-BTUuTnc9.css +0 -2
  293. package/dist/gateway/static/root/assets/index-CXGQihfj.js +0 -70
  294. package/dist/gateway/static/root/assets/local-app-workbench-page-DUP0UiFY.js +0 -2
  295. package/dist/gateway/static/root/assets/local-apps-page-_z2o0cD1.js +0 -1
  296. package/dist/gateway/static/root/assets/logs-page-CPUaLcGH.js +0 -2
  297. package/dist/gateway/static/root/assets/management-settings-eTBfNgXU.js +0 -1
  298. package/dist/gateway/static/root/assets/markdown-view-B1bGSQqt.css +0 -1
  299. package/dist/gateway/static/root/assets/markdown-view-D02mJdoU.js +0 -201
  300. package/dist/gateway/static/root/assets/messages-CoovNoMn.js +0 -3
  301. package/dist/gateway/static/root/assets/mobile-device-api-CvjVB_TB.js +0 -1
  302. package/dist/gateway/static/root/assets/models-hub-cache-CYr6LzvY.js +0 -1
  303. package/dist/gateway/static/root/assets/notes-workbench-DQMUpDc9.js +0 -4
  304. package/dist/gateway/static/root/assets/popover-select-3E24E65N.js +0 -1
  305. package/dist/gateway/static/root/assets/product-open-page-CgZhadZQ.js +0 -1
  306. package/dist/gateway/static/root/assets/project-detail-page-D1HidxgT.js +0 -1
  307. package/dist/gateway/static/root/assets/projects-page-CxwNbbud.js +0 -1
  308. package/dist/gateway/static/root/assets/remote-access-hub-CK59rSc_.js +0 -1
  309. package/dist/gateway/static/root/assets/sessions-page-C2tP7363.js +0 -1
  310. package/dist/gateway/static/root/assets/settings-advanced-gate-DlYBA2N-.js +0 -1
  311. package/dist/gateway/static/root/assets/settings-loading-skeleton-CazDM3n5.js +0 -1
  312. package/dist/gateway/static/root/assets/setup-status-panel-Cn2E0G2o.js +0 -1
  313. package/dist/gateway/static/root/assets/share-preview-page-XgxvE8cx.js +0 -2
  314. package/dist/gateway/static/root/assets/shares-settings-Czph0_fM.js +0 -1
  315. package/dist/gateway/static/root/assets/skill-reload-api-DDq_QEqd.js +0 -1
  316. package/dist/gateway/static/root/assets/system-settings-panel-B4W--Ukh.js +0 -1
  317. package/dist/gateway/static/root/assets/task-detail-page-UY5kNWoR.js +0 -1
  318. package/dist/gateway/static/root/assets/user-context-page-DnUL8kJU.js +0 -1
  319. package/dist/gateway/static/root/assets/workflows-page-B8dJRjMJ.js +0 -5
  320. /package/dist/gateway/static/root/assets/{dist-DqPZM2MH2.js → dist-DqPZM2MH.js} +0 -0
@@ -35,7 +35,7 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
35
35
  primary: string;
36
36
  fallbacks: string[];
37
37
  };
38
- intents?: Partial<Record<"understanding" | "fast" | "reasoning" | "coding" | "review" | "vision", {
38
+ intents?: Partial<Record<"review" | "coding" | "understanding" | "fast" | "reasoning" | "vision", {
39
39
  primary: string;
40
40
  fallbacks: string[];
41
41
  }>>;
@@ -74,7 +74,7 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
74
74
  primary: string;
75
75
  fallbacks: string[];
76
76
  };
77
- intents: Partial<Record<"understanding" | "fast" | "reasoning" | "coding" | "review" | "vision", {
77
+ intents: Partial<Record<"review" | "coding" | "understanding" | "fast" | "reasoning" | "vision", {
78
78
  primary: string;
79
79
  fallbacks: string[];
80
80
  }>>;
@@ -209,7 +209,7 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
209
209
  };
210
210
  userContext: {
211
211
  preferences: {
212
- responseLanguage: "auto" | "zh-CN" | "en";
212
+ responseLanguage: "en" | "auto" | "zh-CN";
213
213
  };
214
214
  dreaming: {
215
215
  mode: "off" | "review";
@@ -221,7 +221,7 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
221
221
  timezone?: string;
222
222
  };
223
223
  privacy: {
224
- sensitiveWritePolicy: "allow" | "deny" | "confirm";
224
+ sensitiveWritePolicy: "allow" | "confirm" | "deny";
225
225
  };
226
226
  memory: {
227
227
  retention: {
@@ -1,9 +1,9 @@
1
1
  import { ContextCompactionPolicySchema, UserContextDreamingSchema, UserContextPrivacySchema, init_config } from "../../../user-context/config.js";
2
2
  import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveDefaultAgentId } from "../../../agent/agent-scope.js";
3
3
  import { resolveModelsJsonPath } from "../../../config/paths.js";
4
+ import { buildChannelCatalogForConfig, buildChannelCatalogFromSnapshot, getChannelSetupStatus, init_channel_catalog_service } from "../../../channels/catalog/channel-catalog-service.js";
4
5
  import { init_models_json, loadModelsJson } from "../../../config/models-json.js";
5
6
  import { CredentialResolver, init_credentials } from "../../../auth/credentials.js";
6
- import { buildChannelCatalogForConfig, buildChannelCatalogFromSnapshot, getChannelSetupStatus, init_channel_catalog_service } from "../../../channels/catalog/channel-catalog-service.js";
7
7
  import { getProviderRegistry, init_plugin_registry } from "../../../providers/plugin-registry.js";
8
8
  import { getAllProviders, init_providers, isProviderConfigured } from "../../../providers/index.js";
9
9
  import { normalizeConfiguredMcpServers } from "../../../config/mcp-config-normalize.js";
@@ -0,0 +1,34 @@
1
+ import type { Context } from 'hono';
2
+ import type { AuthenticatedRouteDeps } from './deps.js';
3
+ export declare function patchChatModelConfig(c: Context, service: AuthenticatedRouteDeps['service'], sessionKey: string, body: Record<string, unknown>): Promise<(Response & import("hono").TypedResponse<{
4
+ ok: false;
5
+ error: string;
6
+ code: string;
7
+ }, 409, "json">) | (Response & import("hono").TypedResponse<{
8
+ ok: false;
9
+ error: string;
10
+ }, 400, "json">) | (Response & import("hono").TypedResponse<{
11
+ ok: false;
12
+ error: string;
13
+ code: "CONFIG_CHANGED" | "INVALID_MODEL" | "INVALID_THINKING";
14
+ }, 400 | 409, "json">) | (Response & import("hono").TypedResponse<{
15
+ ok: true;
16
+ payload: {
17
+ thinkingLevel: import("@earendil-works/pi-agent-core").ThinkingLevel;
18
+ model: string;
19
+ configVersion: number;
20
+ fixedModel: boolean;
21
+ reasoningLevel: import("../../../config/index.js").ReasoningLevel;
22
+ activityDetail: {
23
+ default: import("../../../config/index.js").ReasoningLevel;
24
+ override: import("../../../config/index.js").ReasoningLevel | null;
25
+ effective: import("../../../config/index.js").ReasoningLevel;
26
+ source: "session" | "default";
27
+ };
28
+ verboseLevel: import("../../../config/index.js").VerboseLevel;
29
+ effectiveWorkspacePath: string;
30
+ workingDirectoryLocked: boolean;
31
+ workspaceSource: "execution_environment" | "project" | "session_override" | "agent_default_root" | "agent_workspace";
32
+ userContextMode: "enabled" | "off" | "temporary";
33
+ };
34
+ }, import("hono/dist/types/utils/http-status.js").ContentfulStatusCode, "json">)>;
@@ -0,0 +1,42 @@
1
+ import { withModelConfigLock } from "../../../session/model-config-lock.js";
2
+ //#region src/gateway/hono/routes/chat-model-config.ts
3
+ async function patchChatModelConfig(c, service, sessionKey, body) {
4
+ return withModelConfigLock(sessionKey, async () => {
5
+ const changesModel = body.model !== void 0 || body.thinkingLevel !== void 0;
6
+ if (changesModel) {
7
+ const state = service.getSessionInputState(sessionKey);
8
+ if (service.sessions.getActiveRun(sessionKey).active || state.activeRunId || state.inputs.length > 0) return c.json({
9
+ ok: false,
10
+ error: "Wait for the current reply and pending inputs to finish",
11
+ code: "SESSION_BUSY"
12
+ }, 409);
13
+ if (body.thinkingLevel !== void 0 && typeof body.thinkingLevel !== "string") return c.json({
14
+ ok: false,
15
+ error: "Invalid thinking level"
16
+ }, 400);
17
+ if (body.configVersion !== void 0 && (!Number.isSafeInteger(body.configVersion) || Number(body.configVersion) < 0)) return c.json({
18
+ ok: false,
19
+ error: "Invalid configuration version"
20
+ }, 400);
21
+ if (body.model !== void 0 && (typeof body.model !== "string" || !body.model.trim())) return c.json({
22
+ ok: false,
23
+ error: "Select a specific model"
24
+ }, 400);
25
+ }
26
+ const result = await service.sessions.patchAgentConfig(sessionKey, {
27
+ ...body,
28
+ ...changesModel ? { fixedModel: true } : {}
29
+ });
30
+ if (!result.ok) return c.json({
31
+ ok: false,
32
+ error: result.error,
33
+ code: result.code
34
+ }, result.code === "CONFIG_CHANGED" ? 409 : 400);
35
+ return c.json({
36
+ ok: true,
37
+ payload: await service.sessions.getAgentConfig(sessionKey)
38
+ });
39
+ });
40
+ }
41
+ //#endregion
42
+ export { patchChatModelConfig };
@@ -0,0 +1,3 @@
1
+ import type { Hono } from 'hono';
2
+ export declare function registerPairingApprovalPublicRoutes(app: Hono): void;
3
+ export declare function registerPairingApprovalAdminRoutes(app: Hono): void;
@@ -0,0 +1,100 @@
1
+ import { devicePairingCompleteSchema, devicePairingProofSchema, devicePairingRequestSchema } from "../../../../packages/gateway-contract/src/device-pairing.js";
2
+ import { getOrCreateGatewayIdentity, signGatewayPayload } from "../../../storage/sqlite/gateway-identity-repository.js";
3
+ import { DevicePairingError, cancelDevicePairingSetup, decideDevicePairingRequest, operateDevicePairingRequest, readDevicePairingSetup, submitDevicePairingRequest } from "../../../storage/sqlite/device-pairing-approval.js";
4
+ import os from "node:os";
5
+ import { z } from "zod";
6
+ //#region src/gateway/hono/routes/device-pairing-approval.ts
7
+ function pairingError(c, error) {
8
+ if (error instanceof DevicePairingError) return c.json({
9
+ ok: false,
10
+ error: {
11
+ code: error.code,
12
+ message: error.code
13
+ }
14
+ }, error.status);
15
+ return c.json({
16
+ ok: false,
17
+ error: {
18
+ code: "PAIRING_FAILED",
19
+ message: "Pairing could not be completed"
20
+ }
21
+ }, 500);
22
+ }
23
+ function registerPairingApprovalPublicRoutes(app) {
24
+ for (const action of [
25
+ "request",
26
+ "status",
27
+ "complete",
28
+ "cancel"
29
+ ]) {
30
+ const path = action === "request" ? "/api/device-pairing/requests" : `/api/device-pairing/requests/:id/${action}`;
31
+ app.post(path, async (c) => {
32
+ const parsed = (action === "request" ? devicePairingRequestSchema : action === "complete" ? devicePairingCompleteSchema : devicePairingProofSchema).safeParse(await c.req.json().catch(() => null));
33
+ if (!parsed.success || action !== "request" && parsed.data.requestId !== c.req.param("id")) return c.json({
34
+ ok: false,
35
+ error: {
36
+ code: "BAD_REQUEST",
37
+ message: "Invalid pairing request"
38
+ }
39
+ }, 400);
40
+ try {
41
+ const result = action === "request" ? { request: submitDevicePairingRequest(parsed.data) } : operateDevicePairingRequest(action, parsed.data);
42
+ const signedPayload = Buffer.from(JSON.stringify({
43
+ ...result,
44
+ gateway: {
45
+ id: getOrCreateGatewayIdentity().id,
46
+ name: os.hostname()
47
+ },
48
+ nonce: parsed.data.nonce,
49
+ issuedAt: Date.now()
50
+ })).toString("base64url");
51
+ return c.json({
52
+ ok: true,
53
+ signedPayload,
54
+ signature: signGatewayPayload(signedPayload)
55
+ });
56
+ } catch (error) {
57
+ return pairingError(c, error);
58
+ }
59
+ });
60
+ }
61
+ }
62
+ function registerPairingApprovalAdminRoutes(app) {
63
+ app.get("/api/device-pairing/setups/:id", (c) => {
64
+ try {
65
+ return c.json({
66
+ ok: true,
67
+ ...readDevicePairingSetup(c.req.param("id"))
68
+ });
69
+ } catch (error) {
70
+ return pairingError(c, error);
71
+ }
72
+ });
73
+ app.delete("/api/device-pairing/setups/:id", (c) => {
74
+ cancelDevicePairingSetup(c.req.param("id"));
75
+ return c.json({ ok: true });
76
+ });
77
+ app.post("/api/device-pairing/requests/:id/decision", async (c) => {
78
+ const parsed = z.strictObject({
79
+ decision: z.enum(["approve", "reject"]),
80
+ expectedRevision: z.number().int().positive()
81
+ }).safeParse(await c.req.json().catch(() => null));
82
+ if (!parsed.success) return c.json({
83
+ ok: false,
84
+ error: {
85
+ code: "BAD_REQUEST",
86
+ message: "Invalid decision"
87
+ }
88
+ }, 400);
89
+ try {
90
+ return c.json({
91
+ ok: true,
92
+ request: decideDevicePairingRequest(c.req.param("id"), parsed.data.decision, parsed.data.expectedRevision)
93
+ });
94
+ } catch (error) {
95
+ return pairingError(c, error);
96
+ }
97
+ });
98
+ }
99
+ //#endregion
100
+ export { registerPairingApprovalAdminRoutes, registerPairingApprovalPublicRoutes };
@@ -5,6 +5,7 @@ import { getGatewayIdentityPublicKeyRaw, getOrCreateGatewayIdentity, signGateway
5
5
  import { consumeDevicePairingToken, createDevicePairingSetup, isDevicePairingSetupActive } from "../../../storage/sqlite/device-pairing-repository.js";
6
6
  import { resolveSecureDeviceRoutes } from "../../device-routes.js";
7
7
  import { getGatewayPrincipal } from "../../security/gateway-principal.js";
8
+ import { registerPairingApprovalAdminRoutes, registerPairingApprovalPublicRoutes } from "./device-pairing-approval.js";
8
9
  import os from "node:os";
9
10
  import { z } from "zod";
10
11
  //#region src/gateway/hono/routes/devices.ts
@@ -31,12 +32,10 @@ const pairingExchangeSchema = z.strictObject({
31
32
  });
32
33
  const pairingProbeSchema = z.strictObject({ pairingId: z.string().uuid() });
33
34
  function pairingLinkPayload(input) {
34
- return Buffer.from(JSON.stringify({
35
- version: 2,
36
- ...input
37
- })).toString("base64url");
35
+ return Buffer.from(JSON.stringify(input)).toString("base64url");
38
36
  }
39
37
  function registerDeviceAuthPublicRoutes(app) {
38
+ registerPairingApprovalPublicRoutes(app);
40
39
  app.post("/api/device-auth/refresh", async (c) => {
41
40
  const parsed = refreshRequestSchema.safeParse(await c.req.json().catch(() => null));
42
41
  if (!parsed.success) return c.json({
@@ -138,15 +137,21 @@ function registerDeviceAuthPublicRoutes(app) {
138
137
  });
139
138
  }
140
139
  function registerDeviceRoutes(authenticated, deps) {
140
+ registerPairingApprovalAdminRoutes(authenticated);
141
141
  authenticated.get("/api/device-pairing/readiness", (c) => {
142
142
  const routes = resolveSecureDeviceRoutes(deps.service.currentConfig);
143
143
  return c.json({
144
144
  ok: true,
145
145
  ready: routes.length > 0,
146
- routes
146
+ routes,
147
+ protocolVersions: [2, 3],
148
+ routeState: routes.length > 0 ? "configured" : "missing",
149
+ nextAction: routes.length > 0 ? "scan" : "configure-route",
150
+ serverTime: Date.now()
147
151
  });
148
152
  });
149
- authenticated.post("/api/device-pairing/setups", (c) => {
153
+ authenticated.post("/api/device-pairing/setups", async (c) => {
154
+ const version = (await c.req.json().catch(() => ({}))).protocolVersion === 3 ? 3 : 2;
150
155
  const routes = resolveSecureDeviceRoutes(deps.service.currentConfig);
151
156
  if (routes.length === 0) return c.json({
152
157
  ok: false,
@@ -155,9 +160,10 @@ function registerDeviceRoutes(authenticated, deps) {
155
160
  message: "Configure XOPC Secure Link, Tailscale Serve, or an HTTPS public URL first"
156
161
  }
157
162
  }, 409);
158
- const setup = createDevicePairingSetup(routes);
163
+ const setup = createDevicePairingSetup(routes, Date.now(), version);
159
164
  const identity = getOrCreateGatewayIdentity();
160
165
  const encoded = pairingLinkPayload({
166
+ version,
161
167
  pairingToken: setup.token,
162
168
  gatewayId: identity.id,
163
169
  gatewayName: os.hostname(),
@@ -171,7 +177,8 @@ function registerDeviceRoutes(authenticated, deps) {
171
177
  id: setup.id,
172
178
  universalLink: `https://link.xopc.ai/connect#p=${encoded}`,
173
179
  expiresAt: setup.expiresAt,
174
- routes
180
+ routes,
181
+ protocolVersion: version
175
182
  }
176
183
  }, 201);
177
184
  });
@@ -0,0 +1,3 @@
1
+ import type { Hono } from 'hono';
2
+ import type { AuthenticatedRouteDeps } from './deps.js';
3
+ export declare function registerExecutionEnvironmentRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void;
@@ -0,0 +1,136 @@
1
+ import { ExecutionEnvironmentStore } from "../../../execution-environments/store.js";
2
+ import { LocalWorktreeManager } from "../../../execution-environments/local-worktree-manager.js";
3
+ import { SessionEnvironmentService } from "../../../execution-environments/session-environment-service.js";
4
+ //#region src/gateway/hono/routes/execution-environments.ts
5
+ function executionMode(value) {
6
+ return value === "local_checkout" || value === "managed_worktree" ? value : void 0;
7
+ }
8
+ function errorResponse(error) {
9
+ return {
10
+ ok: false,
11
+ error: error instanceof Error ? error.message : String(error)
12
+ };
13
+ }
14
+ function registerExecutionEnvironmentRoutes(authenticated, deps) {
15
+ const store = new ExecutionEnvironmentStore();
16
+ const worktrees = new LocalWorktreeManager({ store });
17
+ const sessions = new SessionEnvironmentService({
18
+ store,
19
+ worktrees
20
+ });
21
+ authenticated.get("/api/projects/:projectId/environments", (c) => {
22
+ const projectId = c.req.param("projectId");
23
+ if (!deps.service.projects.get(projectId)) return c.json({
24
+ ok: false,
25
+ error: "Project not found"
26
+ }, 404);
27
+ return c.json({
28
+ ok: true,
29
+ environments: store.list({
30
+ projectId,
31
+ includeDeleted: c.req.query("includeDeleted") === "true"
32
+ })
33
+ });
34
+ });
35
+ authenticated.get("/api/sessions/:sessionKey/environment", (c) => {
36
+ const environment = sessions.get(c.req.param("sessionKey"));
37
+ return environment ? c.json({
38
+ ok: true,
39
+ environment
40
+ }) : c.json({
41
+ ok: false,
42
+ error: "Execution environment not found"
43
+ }, 404);
44
+ });
45
+ authenticated.post("/api/sessions/:sessionKey/environment", async (c) => {
46
+ const sessionKey = c.req.param("sessionKey");
47
+ if (deps.service.getActiveWebchatRunId(sessionKey)) return c.json({
48
+ ok: false,
49
+ error: "Stop the active session run before changing its environment"
50
+ }, 409);
51
+ const session = await deps.service.sessions.getSession(sessionKey);
52
+ if (!session) return c.json({
53
+ ok: false,
54
+ error: "Session not found"
55
+ }, 404);
56
+ const projectId = session.projectId?.trim();
57
+ const project = projectId ? deps.service.projects.get(projectId) : null;
58
+ if (!project) return c.json({
59
+ ok: false,
60
+ error: "Session is not attached to a project"
61
+ }, 409);
62
+ const body = await c.req.json().catch(() => ({}));
63
+ const mode = body.mode === void 0 ? void 0 : executionMode(body.mode);
64
+ if (body.mode !== void 0 && !mode) return c.json({
65
+ ok: false,
66
+ error: "Invalid execution mode"
67
+ }, 400);
68
+ try {
69
+ const environment = await sessions.attach({
70
+ sessionKey,
71
+ project,
72
+ mode,
73
+ baseRef: typeof body.baseRef === "string" ? body.baseRef : void 0
74
+ });
75
+ return c.json({
76
+ ok: true,
77
+ environment
78
+ }, 201);
79
+ } catch (error) {
80
+ return c.json(errorResponse(error), 409);
81
+ }
82
+ });
83
+ authenticated.delete("/api/sessions/:sessionKey/environment", async (c) => {
84
+ const sessionKey = c.req.param("sessionKey");
85
+ if (deps.service.getActiveWebchatRunId(sessionKey)) return c.json({
86
+ ok: false,
87
+ error: "Stop the active session run before releasing its environment"
88
+ }, 409);
89
+ try {
90
+ const environment = await sessions.release(sessionKey, c.req.query("keepManaged") !== "true");
91
+ return c.json({
92
+ ok: true,
93
+ environment
94
+ });
95
+ } catch (error) {
96
+ return c.json(errorResponse(error), 409);
97
+ }
98
+ });
99
+ authenticated.get("/api/execution-environments/:environmentId", async (c) => {
100
+ const environment = store.get(c.req.param("environmentId"));
101
+ if (!environment) return c.json({
102
+ ok: false,
103
+ error: "Execution environment not found"
104
+ }, 404);
105
+ const inspection = environment.kind === "managed_worktree" ? await worktrees.inspect(environment.id).catch(() => void 0) : void 0;
106
+ return c.json({
107
+ ok: true,
108
+ environment,
109
+ ...inspection ? { inspection } : {}
110
+ });
111
+ });
112
+ authenticated.post("/api/execution-environments/:environmentId/reconcile", async (c) => {
113
+ try {
114
+ const environment = await worktrees.reconcile(c.req.param("environmentId"));
115
+ return c.json({
116
+ ok: true,
117
+ environment
118
+ });
119
+ } catch (error) {
120
+ return c.json(errorResponse(error), 409);
121
+ }
122
+ });
123
+ authenticated.delete("/api/execution-environments/:environmentId", async (c) => {
124
+ try {
125
+ const environment = await worktrees.remove(c.req.param("environmentId"));
126
+ return c.json({
127
+ ok: true,
128
+ environment
129
+ });
130
+ } catch (error) {
131
+ return c.json(errorResponse(error), 409);
132
+ }
133
+ });
134
+ }
135
+ //#endregion
136
+ export { registerExecutionEnvironmentRoutes };
@@ -0,0 +1,4 @@
1
+ import type { Hono } from 'hono';
2
+ import type { AuthenticatedRouteDeps } from './deps.js';
3
+ /** Metadata and explicit desktop actions for links outside a managed workspace. */
4
+ export declare function registerFileReferenceRoutes(app: Hono, deps: AuthenticatedRouteDeps): void;
@@ -0,0 +1,98 @@
1
+ import { FileServiceError } from "../../../files/file-service.js";
2
+ import { buildFilePathClassifierContext, classifyFileLocation, displayNameForPath, fileRefSessionKeysMatch, resolveFileReferenceCandidate } from "../../file-path-classifier.js";
3
+ import { classifyFileReferenceFsError } from "../../file-reference-errors.js";
4
+ import { FileReferenceRegistry } from "../../file-reference-registry.js";
5
+ import { getGatewayFileSpaceService } from "../../file-space-service.js";
6
+ import { realpath, stat } from "node:fs/promises";
7
+ //#region src/gateway/hono/routes/file-references.ts
8
+ /** Metadata and explicit desktop actions for links outside a managed workspace. */
9
+ function registerFileReferenceRoutes(app, deps) {
10
+ const files = getGatewayFileSpaceService(deps.service);
11
+ const refs = new FileReferenceRegistry();
12
+ app.post("/api/files/resolve-reference", async (c) => {
13
+ const body = await c.req.json();
14
+ if (!body.spaceId || !body.path?.trim()) return c.json({ error: { message: "spaceId and path are required" } }, 400);
15
+ try {
16
+ const space = await files.get(body.spaceId);
17
+ const sessionKey = body.sessionKey?.trim();
18
+ const agentId = space.bindings.find((binding) => binding.kind === "agent")?.id;
19
+ const ctx = {
20
+ ...buildFilePathClassifierContext(deps.service.currentConfig, sessionKey || (agentId ? `agent:${agentId}:main` : void 0)),
21
+ workspaceRoot: space.root
22
+ };
23
+ const inputPath = body.path.trim();
24
+ const base = {
25
+ inputPath,
26
+ displayName: displayNameForPath(inputPath)
27
+ };
28
+ const { candidate, invalid } = await resolveFileReferenceCandidate(inputPath, space.root, ctx);
29
+ if (!candidate || invalid) return c.json({ reference: {
30
+ ...base,
31
+ scope: "invalid",
32
+ exists: false,
33
+ capabilities: []
34
+ } });
35
+ let absolutePath;
36
+ let info;
37
+ try {
38
+ absolutePath = await realpath(candidate);
39
+ info = await stat(absolutePath);
40
+ } catch (error) {
41
+ const failure = classifyFileReferenceFsError(error);
42
+ if (failure.code !== "FILE_NOT_FOUND") return c.json({ error: { message: failure.message } }, failure.status === 403 ? 403 : 500);
43
+ return c.json({ reference: {
44
+ ...base,
45
+ scope: "missing",
46
+ absolutePath: candidate,
47
+ exists: false,
48
+ capabilities: ["copyPath"]
49
+ } });
50
+ }
51
+ const classified = classifyFileLocation(absolutePath, ctx);
52
+ const capabilities = info.isFile() || info.isDirectory() ? [
53
+ "openExternal",
54
+ "revealInFolder",
55
+ "copyPath"
56
+ ] : ["copyPath"];
57
+ const ref = refs.register({
58
+ absolutePath,
59
+ sessionKey,
60
+ ...classified,
61
+ capabilities
62
+ });
63
+ return c.json({ reference: {
64
+ ...base,
65
+ ...classified,
66
+ fileRefId: ref.id,
67
+ absolutePath,
68
+ exists: true,
69
+ isDirectory: info.isDirectory(),
70
+ capabilities,
71
+ mtimeMs: info.mtimeMs
72
+ } });
73
+ } catch (error) {
74
+ if (error instanceof FileServiceError) return c.json({ error: { message: error.message } }, error.status);
75
+ throw error;
76
+ }
77
+ });
78
+ app.post("/api/files/references/:id/action", async (c) => {
79
+ const ref = refs.resolve(c.req.param("id"));
80
+ if (!ref) return c.json({ error: { message: "File reference expired" } }, 404);
81
+ const body = await c.req.json();
82
+ if (!fileRefSessionKeysMatch(ref.sessionKey, body.sessionKey)) return c.json({ error: { message: "File reference forbidden" } }, 403);
83
+ if (body.action !== "openExternal" && body.action !== "revealInFolder" || !ref.capabilities.includes(body.action)) return c.json({ error: { message: "Action not allowed" } }, 403);
84
+ try {
85
+ if (await realpath(ref.absolutePath) !== ref.absolutePath) return c.json({ error: { message: "File reference changed" } }, 409);
86
+ const info = await stat(ref.absolutePath);
87
+ if (!info.isFile() && !info.isDirectory()) return c.json({ error: { message: "Not a file or directory" } }, 400);
88
+ return c.json({
89
+ absolutePath: ref.absolutePath,
90
+ isDirectory: info.isDirectory()
91
+ });
92
+ } catch {
93
+ return c.json({ error: { message: "File not found" } }, 404);
94
+ }
95
+ });
96
+ }
97
+ //#endregion
98
+ export { registerFileReferenceRoutes };
@@ -1,8 +1,10 @@
1
- import { FileServiceError, FileSpaceService, fileResourceFromPath, resolveFilePath } from "../../../files/file-service.js";
1
+ import { FileServiceError, fileResourceFromPath, resolveFilePath } from "../../../files/file-service.js";
2
+ import { getGatewayFileSpaceService } from "../../file-space-service.js";
3
+ import { fuzzySearchWorkspaceFiles, fuzzySubsequenceScore } from "../../workspace-file-search.js";
4
+ import { registerFileReferenceRoutes } from "./file-references.js";
2
5
  import { basename, join } from "node:path";
3
6
  import { readFile, writeFile } from "node:fs/promises";
4
7
  //#region src/gateway/hono/routes/files.ts
5
- const services = /* @__PURE__ */ new WeakMap();
6
8
  const mutationLocks = /* @__PURE__ */ new Map();
7
9
  async function withMutationLock(key, action) {
8
10
  const previous = mutationLocks.get(key) ?? Promise.resolve();
@@ -20,13 +22,6 @@ async function withMutationLock(key, action) {
20
22
  if (mutationLocks.get(key) === tail) mutationLocks.delete(key);
21
23
  }
22
24
  }
23
- function getFiles(deps) {
24
- const existing = services.get(deps.service);
25
- if (existing) return existing;
26
- const created = new FileSpaceService(() => deps.service.currentConfig, deps.service.projects, (sessionKey) => deps.service.agentService.getResolvedWorkspaceForSession(sessionKey));
27
- services.set(deps.service, created);
28
- return created;
29
- }
30
25
  function publicSpace(space) {
31
26
  const { root: _root, ...value } = space;
32
27
  return value;
@@ -39,22 +34,28 @@ function contentDisposition(disposition, fileName) {
39
34
  const sanitized = fileName.replace(/[\u0000-\u001f\u007f]/g, "_");
40
35
  return `${disposition}; filename="${sanitized.replace(/[^\x20-\x7e]/g, "_").replace(/["\\]/g, "_")}"; filename*=UTF-8''${encodeURIComponent(sanitized).replace(/['()*]/g, (character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`)}`;
41
36
  }
42
- async function collectFiles(files, spaceId, query, max) {
37
+ async function collectFiles(files, spaceId, max) {
43
38
  const output = [];
44
39
  const directories = [""];
40
+ const visited = /* @__PURE__ */ new Set();
41
+ const space = await files.get(spaceId);
45
42
  while (directories.length && output.length < max) {
46
43
  const directory = directories.shift();
44
+ const canonical = await resolveFilePath(space.root, directory).catch(() => null);
45
+ if (!canonical || visited.has(canonical)) continue;
46
+ visited.add(canonical);
47
47
  const children = await files.children(spaceId, directory);
48
48
  for (const child of children) {
49
49
  if (child.kind === "directory") directories.push(child.relativePath);
50
- else if (!query || child.name.toLocaleLowerCase().includes(query)) output.push(child);
50
+ else output.push(child);
51
51
  if (output.length >= max) break;
52
52
  }
53
53
  }
54
54
  return output;
55
55
  }
56
56
  function registerFilesRoutes(authenticated, deps) {
57
- const files = getFiles(deps);
57
+ const files = getGatewayFileSpaceService(deps.service);
58
+ registerFileReferenceRoutes(authenticated, deps);
58
59
  authenticated.get("/api/files/spaces", async (c) => {
59
60
  try {
60
61
  return c.json({ spaces: (await files.list()).map(publicSpace) });
@@ -62,6 +63,13 @@ function registerFilesRoutes(authenticated, deps) {
62
63
  return errorResponse(c, error);
63
64
  }
64
65
  });
66
+ authenticated.get("/api/files/default-space", async (c) => {
67
+ try {
68
+ return c.json({ space: publicSpace(await files.defaultSpace()) });
69
+ } catch (error) {
70
+ return errorResponse(c, error);
71
+ }
72
+ });
65
73
  authenticated.get("/api/files/contexts/:kind/:id", async (c) => {
66
74
  try {
67
75
  const kind = c.req.param("kind");
@@ -82,7 +90,7 @@ function registerFilesRoutes(authenticated, deps) {
82
90
  try {
83
91
  const limit = Math.min(100, Math.max(1, Number(c.req.query("limit")) || 50));
84
92
  const spaces = await files.list();
85
- const items = (await Promise.all(spaces.map((space) => collectFiles(files, space.id, "", 5e3)))).flat().sort((a, b) => b.modifiedAt - a.modifiedAt).slice(0, limit);
93
+ const items = (await Promise.all(spaces.map((space) => collectFiles(files, space.id, 5e3)))).flat().sort((a, b) => b.modifiedAt - a.modifiedAt).slice(0, limit);
86
94
  return c.json({ items });
87
95
  } catch (error) {
88
96
  return errorResponse(c, error);
@@ -91,11 +99,23 @@ function registerFilesRoutes(authenticated, deps) {
91
99
  authenticated.get("/api/files/search", async (c) => {
92
100
  try {
93
101
  const query = (c.req.query("q") ?? "").trim().toLocaleLowerCase();
94
- if (!query) return c.json({ items: [] });
95
102
  const limit = Math.min(100, Math.max(1, Number(c.req.query("limit")) || 50));
96
103
  const requestedSpaceId = c.req.query("spaceId");
97
104
  const spaces = requestedSpaceId ? [await files.get(requestedSpaceId)] : await files.list();
98
- const items = (await Promise.all(spaces.map((space) => collectFiles(files, space.id, query, 5e3)))).flat().sort((a, b) => b.modifiedAt - a.modifiedAt).slice(0, limit);
105
+ const items = (await Promise.all(spaces.map(async (space) => {
106
+ const candidates = await fuzzySearchWorkspaceFiles(space.root, query, limit);
107
+ return Promise.all(candidates.map(async (candidate) => {
108
+ try {
109
+ return await fileResourceFromPath(space, await resolveFilePath(space.root, candidate.path));
110
+ } catch (error) {
111
+ if (error instanceof FileServiceError) return null;
112
+ throw error;
113
+ }
114
+ }));
115
+ }))).flat().filter((file) => file !== null).map((file) => ({
116
+ file,
117
+ score: Math.max(fuzzySubsequenceScore(query, file.relativePath) ?? -Infinity, fuzzySubsequenceScore(query, file.name) ?? -Infinity)
118
+ })).sort((a, b) => b.score - a.score || a.file.relativePath.localeCompare(b.file.relativePath)).slice(0, limit).map((row) => row.file);
99
119
  return c.json({ items });
100
120
  } catch (error) {
101
121
  return errorResponse(c, error);
@@ -144,12 +164,14 @@ function registerFilesRoutes(authenticated, deps) {
144
164
  const body = await c.req.json();
145
165
  if (typeof body.content !== "string" || !body.revision) throw new FileServiceError(400, "content and revision are required");
146
166
  const id = c.req.param("id");
147
- const resource = await withMutationLock(id, async () => {
167
+ const initial = await files.resource(id);
168
+ const resource = await withMutationLock(initial.absolutePath, async () => {
148
169
  const current = await files.resource(id);
170
+ if (current.absolutePath !== initial.absolutePath) throw new FileServiceError(409, "File has changed");
149
171
  if (!current.resource.capabilities.includes("edit")) throw new FileServiceError(403, "File is not editable");
150
172
  if (body.revision !== current.resource.revision) throw new FileServiceError(409, "File has changed");
151
173
  await writeFile(current.absolutePath, body.content, "utf8");
152
- return fileResourceFromPath(current.space, current.absolutePath);
174
+ return (await files.resource(id)).resource;
153
175
  });
154
176
  return c.json({ resource });
155
177
  } catch (error) {