@xopcai/xopc 0.0.84 → 0.0.85

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 (410) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  3. package/dist/extensions/feishu/src/plugin.d.ts +2 -0
  4. package/dist/extensions/feishu/src/plugin.js +10 -0
  5. package/dist/extensions/feishu/src/plugin.js.map +1 -1
  6. package/dist/extensions/feishu/src/workflow-progress.d.ts +27 -0
  7. package/dist/extensions/feishu/src/workflow-progress.js +99 -0
  8. package/dist/extensions/feishu/src/workflow-progress.js.map +1 -0
  9. package/dist/extensions/telegram/src/plugin.d.ts +2 -0
  10. package/dist/extensions/telegram/src/plugin.js +11 -1
  11. package/dist/extensions/telegram/src/plugin.js.map +1 -1
  12. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  13. package/dist/extensions/telegram/src/workflow-progress.d.ts +24 -0
  14. package/dist/extensions/telegram/src/workflow-progress.js +73 -0
  15. package/dist/extensions/telegram/src/workflow-progress.js.map +1 -0
  16. package/dist/extensions/telegram/xopc.extension.json +1 -1
  17. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js +158 -0
  18. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js.map +1 -0
  19. package/dist/extensions/weixin/src/api/api.js +2 -2
  20. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  21. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  22. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  23. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  24. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  25. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  26. package/dist/extensions/weixin/src/plugin.d.ts +2 -0
  27. package/dist/extensions/weixin/src/plugin.js +11 -1
  28. package/dist/extensions/weixin/src/plugin.js.map +1 -1
  29. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  30. package/dist/extensions/weixin/src/workflow-progress.d.ts +26 -0
  31. package/dist/extensions/weixin/src/workflow-progress.js +99 -0
  32. package/dist/extensions/weixin/src/workflow-progress.js.map +1 -0
  33. package/dist/gateway/static/root/assets/agents-D3_-kNlZ.js +222 -0
  34. package/dist/gateway/static/root/assets/apps-page-D7v7649T.js +1 -0
  35. package/dist/gateway/static/root/assets/channels-settings-nCaMb0a7.js +1 -0
  36. package/dist/gateway/static/root/assets/channels-status-swr-C1gZBcJV.js +8 -0
  37. package/dist/gateway/static/root/assets/createLucideIcon-DPHK1VkS.js +1 -0
  38. package/dist/gateway/static/root/assets/cron-api-CoYK0hlm.js +1 -0
  39. package/dist/gateway/static/root/assets/cron-page-DeGo-Vjc.js +1 -0
  40. package/dist/gateway/static/root/assets/dist-BTWC-BTN.js +45 -0
  41. package/dist/gateway/static/root/assets/{dist-CqNMNhJM.js → dist-DaK4dsss.js} +1 -1
  42. package/dist/gateway/static/root/assets/{extension-debug-page-gf2L0kY_.js → extension-debug-page-BZngZWbO.js} +1 -1
  43. package/dist/gateway/static/root/assets/extension-page-D6JSyV27.js +1 -0
  44. package/dist/gateway/static/root/assets/extension-settings-page-8PZcmWI7.js +1 -0
  45. package/dist/gateway/static/root/assets/fetch-B2MYHbWg.js +1 -0
  46. package/dist/gateway/static/root/assets/{field-primitives-DTtlp-l8.js → field-primitives-Zzl22MvN.js} +1 -1
  47. package/dist/gateway/static/root/assets/heartbeat-config-api-BtIcpG0O.js +1 -0
  48. package/dist/gateway/static/root/assets/index-D4vM3-P7.js +4700 -0
  49. package/dist/gateway/static/root/assets/index-ew_2L2We.css +1 -0
  50. package/dist/gateway/static/root/assets/logs-page-_d4UJ-qQ.js +1 -0
  51. package/dist/gateway/static/root/assets/sessions-page-5N4aF2Wk.js +1 -0
  52. package/dist/gateway/static/root/assets/settings-form-section-D_tgb8r2.js +1 -0
  53. package/dist/gateway/static/root/assets/settings-page-C18xBt4X.js +3 -0
  54. package/dist/gateway/static/root/assets/share-preview-page-D4EG_vM1.js +2 -0
  55. package/dist/gateway/static/root/assets/skills-page-sPAXhh8w.js +2 -0
  56. package/dist/gateway/static/root/assets/theme-store-DryYl3qD.js +1 -0
  57. package/dist/gateway/static/root/assets/url-BwNL6Rgk.js +3 -0
  58. package/dist/gateway/static/root/assets/utils-CYO9eTCM.js +1 -0
  59. package/dist/gateway/static/root/assets/voice-api-key-field-Ds51havm.js +1 -0
  60. package/dist/gateway/static/root/index.html +7 -6
  61. package/dist/package.js +1 -1
  62. package/dist/src/agent/agent-manager.js +7 -7
  63. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  64. package/dist/src/agent/context/workspace-seed.js +3 -3
  65. package/dist/src/agent/embedded/map-stream-events.js +6 -0
  66. package/dist/src/agent/embedded/map-stream-events.js.map +1 -1
  67. package/dist/src/agent/embedded/subscribe-session.js +24 -0
  68. package/dist/src/agent/embedded/subscribe-session.js.map +1 -1
  69. package/dist/src/agent/embedded/types.d.ts +19 -0
  70. package/dist/src/agent/goals/goal-locale.js +2 -2
  71. package/dist/src/agent/goals/goal-run-store.js +4 -4
  72. package/dist/src/agent/goals/persistent-goal-service.js +1 -1
  73. package/dist/src/agent/goals/post-turn.js +2 -2
  74. package/dist/src/agent/image/load-image-media.js +2 -2
  75. package/dist/src/agent/ipc/bus.js +1 -1
  76. package/dist/src/agent/ipc/inbox.js +2 -2
  77. package/dist/src/agent/ipc/socket.js +1 -1
  78. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  79. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  80. package/dist/src/agent/memory/dreaming/events.js +1 -1
  81. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  82. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  83. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  84. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  85. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  86. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  87. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  88. package/dist/src/agent/models/manager.js +1 -1
  89. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  90. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  91. package/dist/src/agent/reply/startup-context.d.ts +3 -0
  92. package/dist/src/agent/reply/startup-context.js +25 -2
  93. package/dist/src/agent/reply/startup-context.js.map +1 -1
  94. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  95. package/dist/src/agent/sandbox/path-policy.js +2 -2
  96. package/dist/src/agent/service/build-direct-message-content.js +1 -1
  97. package/dist/src/agent/service.d.ts +1 -0
  98. package/dist/src/agent/service.js +10 -4
  99. package/dist/src/agent/service.js.map +1 -1
  100. package/dist/src/agent/session/session-inspector.js +1 -1
  101. package/dist/src/agent/skills/config.js +1 -1
  102. package/dist/src/agent/skills/hub-hash.js +2 -2
  103. package/dist/src/agent/skills/hub-lock.js +1 -1
  104. package/dist/src/agent/skills/hub-pull.js +3 -3
  105. package/dist/src/agent/skills/index.js +1 -1
  106. package/dist/src/agent/skills/managed-store.js +1 -1
  107. package/dist/src/agent/skills/scanner.js +1 -1
  108. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  109. package/dist/src/agent/skills/skill-manager.js +1 -1
  110. package/dist/src/agent/tools/create-share-tool.d.ts +27 -0
  111. package/dist/src/agent/tools/create-share-tool.js +237 -0
  112. package/dist/src/agent/tools/create-share-tool.js.map +1 -0
  113. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  114. package/dist/src/agent/tools/factory.js +35 -1
  115. package/dist/src/agent/tools/factory.js.map +1 -1
  116. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  117. package/dist/src/agent/tools/index.d.ts +2 -0
  118. package/dist/src/agent/tools/index.js +3 -1
  119. package/dist/src/agent/tools/send-media.js +1 -1
  120. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  121. package/dist/src/agent/tools/workflow-tool.d.ts +41 -0
  122. package/dist/src/agent/tools/workflow-tool.js +271 -0
  123. package/dist/src/agent/tools/workflow-tool.js.map +1 -0
  124. package/dist/src/agent/tools/write.js +1 -1
  125. package/dist/src/agent/workflow/builtins/audit-repo.d.ts +9 -0
  126. package/dist/src/agent/workflow/builtins/audit-repo.js +115 -0
  127. package/dist/src/agent/workflow/builtins/audit-repo.js.map +1 -0
  128. package/dist/src/agent/workflow/builtins/index.d.ts +15 -0
  129. package/dist/src/agent/workflow/builtins/index.js +28 -0
  130. package/dist/src/agent/workflow/builtins/index.js.map +1 -0
  131. package/dist/src/agent/workflow/builtins/multi-perspective-review.d.ts +9 -0
  132. package/dist/src/agent/workflow/builtins/multi-perspective-review.js +113 -0
  133. package/dist/src/agent/workflow/builtins/multi-perspective-review.js.map +1 -0
  134. package/dist/src/agent/workflow/builtins/research.d.ts +9 -0
  135. package/dist/src/agent/workflow/builtins/research.js +129 -0
  136. package/dist/src/agent/workflow/builtins/research.js.map +1 -0
  137. package/dist/src/agent/workflow/catalog.d.ts +51 -0
  138. package/dist/src/agent/workflow/catalog.js +155 -0
  139. package/dist/src/agent/workflow/catalog.js.map +1 -0
  140. package/dist/src/agent/workflow/channel-capability.d.ts +76 -0
  141. package/dist/src/agent/workflow/channel-capability.js +1 -0
  142. package/dist/src/agent/workflow/index.d.ts +11 -0
  143. package/dist/src/agent/workflow/index.js +10 -0
  144. package/dist/src/agent/workflow/last-run-memory.d.ts +42 -0
  145. package/dist/src/agent/workflow/last-run-memory.js +60 -0
  146. package/dist/src/agent/workflow/last-run-memory.js.map +1 -0
  147. package/dist/src/agent/workflow/parser.d.ts +20 -0
  148. package/dist/src/agent/workflow/parser.js +137 -0
  149. package/dist/src/agent/workflow/parser.js.map +1 -0
  150. package/dist/src/agent/workflow/progress-broker.d.ts +80 -0
  151. package/dist/src/agent/workflow/progress-broker.js +263 -0
  152. package/dist/src/agent/workflow/progress-broker.js.map +1 -0
  153. package/dist/src/agent/workflow/runtime.d.ts +31 -0
  154. package/dist/src/agent/workflow/runtime.js +301 -0
  155. package/dist/src/agent/workflow/runtime.js.map +1 -0
  156. package/dist/src/agent/workflow/snapshot.d.ts +18 -0
  157. package/dist/src/agent/workflow/snapshot.js +144 -0
  158. package/dist/src/agent/workflow/snapshot.js.map +1 -0
  159. package/dist/src/agent/workflow/structured-output-tool.d.ts +33 -0
  160. package/dist/src/agent/workflow/structured-output-tool.js +58 -0
  161. package/dist/src/agent/workflow/structured-output-tool.js.map +1 -0
  162. package/dist/src/agent/workflow/subagent-runner.d.ts +42 -0
  163. package/dist/src/agent/workflow/subagent-runner.js +104 -0
  164. package/dist/src/agent/workflow/subagent-runner.js.map +1 -0
  165. package/dist/src/agent/workflow/types.d.ts +137 -0
  166. package/dist/src/agent/workflow/types.js +1 -0
  167. package/dist/src/auth/credentials.js +3 -3
  168. package/dist/src/auth/profiles/store.js +1 -1
  169. package/dist/src/auth/sync-provider-auth.js +1 -1
  170. package/dist/src/browser/cache-dir-policy.js +1 -1
  171. package/dist/src/browser/cdp-local-launcher.js +2 -2
  172. package/dist/src/browser/providers/browser-ext-install.js +4 -4
  173. package/dist/src/browser/providers/cloakbrowser.js +4 -4
  174. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  175. package/dist/src/browser/stealth.js +1 -1
  176. package/dist/src/channels/attachments/inbound-persist.js +1 -1
  177. package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
  178. package/dist/src/channels/outbound/persist-store.js +1 -1
  179. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  180. package/dist/src/channels/pairing/pairing-store.js +2 -2
  181. package/dist/src/chat-commands/builtins/config.js +2 -2
  182. package/dist/src/chat-commands/builtins/model.js +40 -23
  183. package/dist/src/chat-commands/builtins/model.js.map +1 -1
  184. package/dist/src/chat-commands/builtins/system.js +30 -15
  185. package/dist/src/chat-commands/builtins/system.js.map +1 -1
  186. package/dist/src/chat-commands/builtins/workflow.d.ts +18 -0
  187. package/dist/src/chat-commands/builtins/workflow.js +167 -0
  188. package/dist/src/chat-commands/builtins/workflow.js.map +1 -0
  189. package/dist/src/chat-commands/context.js +1 -1
  190. package/dist/src/chat-commands/format-output.d.ts +28 -0
  191. package/dist/src/chat-commands/format-output.js +45 -0
  192. package/dist/src/chat-commands/format-output.js.map +1 -0
  193. package/dist/src/chat-commands/index.d.ts +1 -0
  194. package/dist/src/chat-commands/index.js +3 -1
  195. package/dist/src/chat-commands/index.js.map +1 -1
  196. package/dist/src/cli/commands/config.js +2 -2
  197. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  198. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  199. package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
  200. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  201. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  202. package/dist/src/cli/commands/extension-dev.js +1 -1
  203. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  204. package/dist/src/cli/commands/extension-pack.js +1 -1
  205. package/dist/src/cli/commands/gateway/lifecycle.js +10 -4
  206. package/dist/src/cli/commands/gateway/lifecycle.js.map +1 -1
  207. package/dist/src/cli/commands/gateway/shared.js +1 -1
  208. package/dist/src/cli/commands/image.js +1 -1
  209. package/dist/src/cli/commands/init.js +4 -4
  210. package/dist/src/cli/commands/onboard.js +2 -2
  211. package/dist/src/cli/commands/tunnel.js +2 -2
  212. package/dist/src/cli/utils/gateway-client.js +1 -1
  213. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  214. package/dist/src/config/agent-profile.js +1 -1
  215. package/dist/src/config/gateway-bind.js +1 -1
  216. package/dist/src/config/index.js +5 -5
  217. package/dist/src/config/loader.js +2 -2
  218. package/dist/src/config/models-json.js +2 -2
  219. package/dist/src/config/paths-state.js +1 -1
  220. package/dist/src/config/profile.js +2 -2
  221. package/dist/src/config/public-url.d.ts +28 -0
  222. package/dist/src/config/public-url.js +103 -0
  223. package/dist/src/config/public-url.js.map +1 -0
  224. package/dist/src/config/schema.d.ts +82 -0
  225. package/dist/src/config/schema.js +130 -1
  226. package/dist/src/config/schema.js.map +1 -1
  227. package/dist/src/config/workspace-path.js +1 -1
  228. package/dist/src/cron/executor.js +2 -2
  229. package/dist/src/cron/persistence.js +1 -1
  230. package/dist/src/cron/run-log-store.js +1 -1
  231. package/dist/src/daemon/constants.js +1 -1
  232. package/dist/src/daemon/install-plan.js +3 -3
  233. package/dist/src/daemon/install-plan.js.map +1 -1
  234. package/dist/src/daemon/launchd.js +2 -2
  235. package/dist/src/daemon/schtasks.js +38 -1
  236. package/dist/src/daemon/schtasks.js.map +1 -1
  237. package/dist/src/daemon/systemd.js +2 -2
  238. package/dist/src/extensions/bundle-mcp.js +1 -1
  239. package/dist/src/extensions/discover-extensions.js +1 -1
  240. package/dist/src/extensions/health.js +1 -1
  241. package/dist/src/extensions/loader.js +1 -1
  242. package/dist/src/extensions/lockfile.js +2 -2
  243. package/dist/src/gateway/agents-admin.js +2 -2
  244. package/dist/src/gateway/file-path-classifier.js +2 -2
  245. package/dist/src/gateway/hono/app.js +33 -2
  246. package/dist/src/gateway/hono/app.js.map +1 -1
  247. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  248. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  249. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  250. package/dist/src/gateway/hono/oauth.js +1 -1
  251. package/dist/src/gateway/hono/routes/agents.js +1 -1
  252. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  253. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  254. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  255. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  256. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  257. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  258. package/dist/src/gateway/hono/routes/models.js +1 -1
  259. package/dist/src/gateway/hono/routes/shares.js +631 -34
  260. package/dist/src/gateway/hono/routes/shares.js.map +1 -1
  261. package/dist/src/gateway/hono/routes/site-shares.d.ts +3 -0
  262. package/dist/src/gateway/hono/routes/site-shares.js +228 -0
  263. package/dist/src/gateway/hono/routes/site-shares.js.map +1 -0
  264. package/dist/src/gateway/hono/routes/tunnel.js +97 -8
  265. package/dist/src/gateway/hono/routes/tunnel.js.map +1 -1
  266. package/dist/src/gateway/hono/routes/workspace.js +5 -5
  267. package/dist/src/gateway/hono/sse.js +2 -2
  268. package/dist/src/gateway/host.d.ts +3 -1
  269. package/dist/src/gateway/host.js +3 -1
  270. package/dist/src/gateway/host.js.map +1 -1
  271. package/dist/src/gateway/lock.js +3 -3
  272. package/dist/src/gateway/ports.d.ts +6 -0
  273. package/dist/src/gateway/ports.js +38 -2
  274. package/dist/src/gateway/ports.js.map +1 -1
  275. package/dist/src/gateway/public-url.d.ts +8 -0
  276. package/dist/src/gateway/public-url.js +10 -0
  277. package/dist/src/gateway/public-url.js.map +1 -0
  278. package/dist/src/gateway/security/origin-check.d.ts +9 -1
  279. package/dist/src/gateway/security/origin-check.js +4 -0
  280. package/dist/src/gateway/security/origin-check.js.map +1 -1
  281. package/dist/src/gateway/server.js +15 -0
  282. package/dist/src/gateway/server.js.map +1 -1
  283. package/dist/src/gateway/service/agent-runner.js +2 -2
  284. package/dist/src/gateway/service/marketplace-service.js +2 -2
  285. package/dist/src/gateway/service/run-gateway-agent.js +2 -2
  286. package/dist/src/gateway/service.js +3 -2
  287. package/dist/src/gateway/service.js.map +1 -1
  288. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  289. package/dist/src/i18n/goals-bundle.js +1 -1
  290. package/dist/src/i18n/index.d.ts +1 -0
  291. package/dist/src/i18n/index.js +2 -1
  292. package/dist/src/i18n/locales/share-tool.en.js +15 -0
  293. package/dist/src/i18n/locales/share-tool.en.js.map +1 -0
  294. package/dist/src/i18n/locales/share-tool.zh.js +15 -0
  295. package/dist/src/i18n/locales/share-tool.zh.js.map +1 -0
  296. package/dist/src/i18n/share-tool-bundle.d.ts +20 -0
  297. package/dist/src/i18n/share-tool-bundle.js +56 -0
  298. package/dist/src/i18n/share-tool-bundle.js.map +1 -0
  299. package/dist/src/infra/gateway-processes.js +1 -0
  300. package/dist/src/infra/gateway-processes.js.map +1 -1
  301. package/dist/src/infra/restart.js +2 -2
  302. package/dist/src/infra/update-check.js +1 -1
  303. package/dist/src/infra/update-lock.js +3 -3
  304. package/dist/src/infra/update-runner.js +1 -1
  305. package/dist/src/infra/update-startup.js +2 -2
  306. package/dist/src/infra/write-file-atomic.js +2 -2
  307. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  308. package/dist/src/providers/index.js +2 -2
  309. package/dist/src/providers/model-registry.js +1 -1
  310. package/dist/src/session/config-store.js +2 -2
  311. package/dist/src/session/parity/jsonl-transcript-io.js +2 -2
  312. package/dist/src/session/parity/sessions-json-file.js +1 -1
  313. package/dist/src/session/parity/transcript-file-lock.js +2 -2
  314. package/dist/src/session/parity/transcript-paths.js +1 -1
  315. package/dist/src/session/search-index-cache.js +1 -1
  316. package/dist/src/session/search-index.js +1 -1
  317. package/dist/src/session/session-title.js +3 -2
  318. package/dist/src/session/session-title.js.map +1 -1
  319. package/dist/src/session/store.js +5 -5
  320. package/dist/src/share/share-auto.d.ts +74 -0
  321. package/dist/src/share/share-auto.js +247 -0
  322. package/dist/src/share/share-auto.js.map +1 -0
  323. package/dist/src/share/share-config.js +63 -4
  324. package/dist/src/share/share-config.js.map +1 -1
  325. package/dist/src/share/share-landing.d.ts +28 -2
  326. package/dist/src/share/share-landing.js +155 -34
  327. package/dist/src/share/share-landing.js.map +1 -1
  328. package/dist/src/share/share-store.d.ts +48 -4
  329. package/dist/src/share/share-store.js +322 -51
  330. package/dist/src/share/share-store.js.map +1 -1
  331. package/dist/src/share/share-thumbnail.d.ts +35 -0
  332. package/dist/src/share/share-thumbnail.js +277 -0
  333. package/dist/src/share/share-thumbnail.js.map +1 -0
  334. package/dist/src/share/share-types.d.ts +68 -10
  335. package/dist/src/share/share-types.js +18 -1
  336. package/dist/src/share/share-types.js.map +1 -1
  337. package/dist/src/share/share-url.js +1 -1
  338. package/dist/src/share/share-zip.d.ts +35 -0
  339. package/dist/src/share/share-zip.js +303 -0
  340. package/dist/src/share/share-zip.js.map +1 -0
  341. package/dist/src/share/site-proxy.d.ts +35 -0
  342. package/dist/src/share/site-proxy.js +234 -0
  343. package/dist/src/share/site-proxy.js.map +1 -0
  344. package/dist/src/share/site-share-config.d.ts +11 -0
  345. package/dist/src/share/site-share-config.js +103 -0
  346. package/dist/src/share/site-share-config.js.map +1 -0
  347. package/dist/src/share/site-share-router.d.ts +23 -0
  348. package/dist/src/share/site-share-router.js +147 -0
  349. package/dist/src/share/site-share-router.js.map +1 -0
  350. package/dist/src/share/site-share-store.d.ts +53 -0
  351. package/dist/src/share/site-share-store.js +400 -0
  352. package/dist/src/share/site-share-store.js.map +1 -0
  353. package/dist/src/share/site-share-types.d.ts +103 -0
  354. package/dist/src/share/site-share-types.js +41 -0
  355. package/dist/src/share/site-share-types.js.map +1 -0
  356. package/dist/src/share/site-static-serve.d.ts +10 -0
  357. package/dist/src/share/site-static-serve.js +145 -0
  358. package/dist/src/share/site-static-serve.js.map +1 -0
  359. package/dist/src/tui/clipboard-image.js +3 -3
  360. package/dist/src/tui/theme-manager.js +1 -1
  361. package/dist/src/tui/tui-commands.js +18 -0
  362. package/dist/src/tui/tui-commands.js.map +1 -1
  363. package/dist/src/tui/tui-keybindings-file.js +1 -1
  364. package/dist/src/tui/tui-scoped-models.js +2 -2
  365. package/dist/src/tui/tui-settings.js +1 -1
  366. package/dist/src/tui/tui-workflow-slash.d.ts +32 -0
  367. package/dist/src/tui/tui-workflow-slash.js +63 -0
  368. package/dist/src/tui/tui-workflow-slash.js.map +1 -0
  369. package/dist/src/tui/tui.js +2 -2
  370. package/dist/src/tunnel/enable-lan-pairing.js +1 -1
  371. package/dist/src/tunnel/frpc-binary.js +3 -3
  372. package/dist/src/tunnel/frpc-config.js +1 -1
  373. package/dist/src/tunnel/frpc-extract.js +1 -1
  374. package/dist/src/tunnel/index.js +2 -2
  375. package/dist/src/tunnel/pair-context.d.ts +7 -1
  376. package/dist/src/tunnel/pair-context.js +25 -9
  377. package/dist/src/tunnel/pair-context.js.map +1 -1
  378. package/dist/src/tunnel/pair-url.d.ts +14 -1
  379. package/dist/src/tunnel/pair-url.js +14 -1
  380. package/dist/src/tunnel/pair-url.js.map +1 -1
  381. package/dist/src/tunnel/tunnel-service.js +2 -2
  382. package/dist/src/tunnel/tunnel-state.js +1 -1
  383. package/dist/src/utils/logger/audit.js +1 -1
  384. package/dist/src/utils/logger/log-store.js +1 -1
  385. package/dist/src/utils/logger/rotation.js +1 -1
  386. package/dist/src/voice/tts/audio.js +1 -1
  387. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  388. package/package.json +3 -2
  389. package/dist/gateway/static/root/assets/agents-tR-nNP04.js +0 -222
  390. package/dist/gateway/static/root/assets/apps-page-BDw6SP-d.js +0 -1
  391. package/dist/gateway/static/root/assets/button-KafIU8dx.js +0 -1
  392. package/dist/gateway/static/root/assets/channels-settings-DEFd-jj1.js +0 -1
  393. package/dist/gateway/static/root/assets/channels-status-swr-DI5FHdGe.js +0 -8
  394. package/dist/gateway/static/root/assets/cron-api-BSqY8LwW.js +0 -1
  395. package/dist/gateway/static/root/assets/cron-page-D7lVDjcR.js +0 -1
  396. package/dist/gateway/static/root/assets/dist-C57OMHW8.js +0 -48
  397. package/dist/gateway/static/root/assets/extension-page-CQo2Xsmg.js +0 -1
  398. package/dist/gateway/static/root/assets/extension-settings-page-CZf0WoZg.js +0 -1
  399. package/dist/gateway/static/root/assets/fetch-2iRFmd3n.js +0 -3
  400. package/dist/gateway/static/root/assets/heartbeat-config-api-B0drdQEJ.js +0 -1
  401. package/dist/gateway/static/root/assets/index-0Gt3TG4j.js +0 -4693
  402. package/dist/gateway/static/root/assets/index-BuFldCsB.css +0 -1
  403. package/dist/gateway/static/root/assets/logs-page-DMuORLfC.js +0 -1
  404. package/dist/gateway/static/root/assets/sessions-page-_UO8g6NN.js +0 -1
  405. package/dist/gateway/static/root/assets/settings-form-section-DkmHkknc.js +0 -1
  406. package/dist/gateway/static/root/assets/settings-page-Cz8FoW_A.js +0 -3
  407. package/dist/gateway/static/root/assets/skills-page-HrUOxF7H.js +0 -2
  408. package/dist/gateway/static/root/assets/theme-store-D01dJt95.js +0 -1
  409. package/dist/gateway/static/root/assets/utils-BFwcR6pL.js +0 -1
  410. package/dist/gateway/static/root/assets/voice-api-key-field-JF8-aqc5.js +0 -1
@@ -2,9 +2,9 @@ import { PACKAGE_VERSION, init_package_version } from "../package-version.js";
2
2
  import { createLogger } from "../utils/logger/index.js";
3
3
  import { init_logger } from "../utils/logger.js";
4
4
  import { SERVICE_VERSION_ENV_KEY, formatGatewayServiceDescription } from "./constants.js";
5
- import { existsSync } from "node:fs";
6
- import path from "node:path";
7
5
  import { homedir } from "node:os";
6
+ import path from "node:path";
7
+ import { existsSync } from "node:fs";
8
8
  //#region src/daemon/install-plan.ts
9
9
  /**
10
10
  * Install Plan Builder - Build gateway installation configuration
@@ -34,7 +34,7 @@ function isSEABinary() {
34
34
  function resolveEntryPoint() {
35
35
  if (isSEABinary()) return process.execPath;
36
36
  const thisDir = path.dirname(new URL(import.meta.url).pathname);
37
- return path.join(thisDir, "..", "cli", "index.js");
37
+ return path.join(thisDir, "..", "cli", "bin.js");
38
38
  }
39
39
  function buildGatewayInstallPlan(params) {
40
40
  const configPath = resolveDefaultConfigPath();
@@ -1 +1 @@
1
- {"version":3,"file":"install-plan.js","names":[],"sources":["../../../src/daemon/install-plan.ts"],"sourcesContent":["/**\n * Install Plan Builder - Build gateway installation configuration\n *\n * Aligned with OpenClaw: adds XOPC_SERVICE_VERSION, StandardOut/ErrorPath,\n * supports binary runtime detection, and --foreground arg passing.\n */\n\nimport { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { homedir } from 'node:os';\nimport { createLogger } from '../utils/logger.js';\nimport { SERVICE_VERSION_ENV_KEY, formatGatewayServiceDescription } from './constants.js';\nimport { PACKAGE_VERSION } from '../package-version.js';\nimport type { GatewayServiceInstallArgs, GatewayServiceEnv } from './types.js';\n\nconst log = createLogger('InstallPlan');\n\nexport interface InstallPlan {\n programArguments: string[];\n workingDirectory: string;\n environment: Record<string, string>;\n description: string;\n}\n\n// ─── Path Resolution ───\n\nfunction resolveDefaultConfigPath(): string {\n const envConfig = process.env.XOPC_CONFIG || process.env.XOPC_CONFIG_PATH;\n if (envConfig) return envConfig;\n return path.join(homedir(), '.xopc', 'xopc.json');\n}\n\nfunction resolveDefaultWorkspace(): string {\n const envWorkspace = process.env.XOPC_WORKSPACE;\n if (envWorkspace) return envWorkspace;\n return path.join(homedir(), '.xopc', 'workspace');\n}\n\nfunction resolveLogDir(): string {\n return path.join(homedir(), '.xopc', 'logs');\n}\n\n// ─── Binary Detection ───\n\nfunction isSEABinary(): boolean {\n // Node.js SEA (Single Executable Application) detection\n return !!(process as NodeJS.Process & { pkg?: unknown }).pkg ||\n process.execPath.endsWith('xopc') ||\n process.execPath.endsWith('xopc.exe');\n}\n\nfunction resolveEntryPoint(): string {\n if (isSEABinary()) {\n return process.execPath;\n }\n // Resolve relative to this file's location → ../cli/index.js (built output)\n const thisDir = path.dirname(new URL(import.meta.url).pathname);\n return path.join(thisDir, '..', 'cli', 'index.js');\n}\n\n// ─── Plan Builder ───\n\nexport function buildGatewayInstallPlan(params: {\n port: number;\n bind?: import('../config/schema.js').GatewayBindMode;\n token?: string;\n env?: GatewayServiceEnv;\n runtime?: 'node' | 'binary';\n version?: string;\n}): InstallPlan {\n const configPath = resolveDefaultConfigPath();\n const workspace = resolveDefaultWorkspace();\n const version = params.version || PACKAGE_VERSION;\n\n // Determine program + arguments\n let programArguments: string[];\n\n if (params.runtime === 'binary' || isSEABinary()) {\n // SEA binary: direct execution\n const binaryPath = process.execPath;\n programArguments = [binaryPath, 'gateway', '--foreground', '--port', params.port.toString()];\n } else {\n // Node.js runtime\n const nodeArgs = process.execArgv.filter(\n (arg) => !arg.startsWith('--inspect') && !arg.startsWith('--debug'),\n );\n const entryPoint = resolveEntryPoint();\n programArguments = [\n process.execPath,\n ...nodeArgs,\n entryPoint,\n 'gateway',\n '--foreground',\n '--port', params.port.toString(),\n ];\n }\n\n if (params.bind && params.bind !== 'loopback') {\n programArguments.push('--bind', params.bind);\n }\n\n // Build environment\n const environment: Record<string, string> = {\n XOPC_CONFIG: configPath,\n XOPC_WORKSPACE: workspace,\n XOPC_LOG_LEVEL: process.env.XOPC_LOG_LEVEL || 'info',\n XOPC_LOG_FILE: 'true',\n XOPC_LOG_CONSOLE: 'false',\n XOPC_LOG_DIR: resolveLogDir(),\n [SERVICE_VERSION_ENV_KEY]: version,\n XOPC_SERVICE_MARKER: '1',\n };\n\n if (params.token) {\n environment.XOPC_GATEWAY_TOKEN = params.token;\n }\n\n // Copy relevant API key env vars\n const relevantEnvVars = [\n 'OPENAI_API_KEY',\n 'ANTHROPIC_API_KEY',\n 'GOOGLE_API_KEY',\n 'BRAVE_API_KEY',\n 'DASHSCOPE_API_KEY',\n 'XOPC_LOG_RETENTION_DAYS',\n ];\n\n for (const key of relevantEnvVars) {\n if (process.env[key]) {\n environment[key] = process.env[key]!;\n }\n }\n\n // Add custom env from params (non-XOPC keys only; XOPC keys already handled)\n if (params.env) {\n for (const [key, value] of Object.entries(params.env)) {\n if (value !== undefined && !key.startsWith('XOPC_')) {\n environment[key] = value;\n }\n }\n }\n\n // Service description\n const profile = params.env?.XOPC_PROFILE?.trim() || undefined;\n const description = formatGatewayServiceDescription({ profile, version });\n\n log.info({\n programArguments: programArguments.slice(0, 3),\n envKeys: Object.keys(environment),\n version,\n }, 'Built gateway install plan');\n\n return {\n programArguments,\n workingDirectory: path.dirname(configPath),\n environment,\n description,\n };\n}\n\n// ─── Install Args Builder ───\n\nexport function buildGatewayInstallArgs(params: {\n port: number;\n bind?: import('../config/schema.js').GatewayBindMode;\n token?: string;\n env?: GatewayServiceEnv;\n runtime?: 'node' | 'binary';\n version?: string;\n}): GatewayServiceInstallArgs {\n const plan = buildGatewayInstallPlan(params);\n\n return {\n env: params.env || process.env,\n programArguments: plan.programArguments,\n workingDirectory: plan.workingDirectory,\n environment: plan.environment,\n description: plan.description,\n };\n}\n\n// ─── Validation ───\n\n/** Check if the program in an install plan still exists on disk */\nexport function validateInstallPlanProgram(programArguments: string[]): boolean {\n if (programArguments.length === 0) return false;\n const program = programArguments[0];\n return existsSync(program);\n}\n"],"mappings":";;;;;;;;;;;;;;aAUkD;sBAEM;AAGxD,MAAM,MAAM,aAAa,cAAc;AAWvC,SAAS,2BAAmC;CAC1C,MAAM,YAAY,QAAQ,IAAI,eAAe,QAAQ,IAAI;AACzD,KAAI,UAAW,QAAO;AACtB,QAAO,KAAK,KAAK,SAAS,EAAE,SAAS,YAAY;;AAGnD,SAAS,0BAAkC;CACzC,MAAM,eAAe,QAAQ,IAAI;AACjC,KAAI,aAAc,QAAO;AACzB,QAAO,KAAK,KAAK,SAAS,EAAE,SAAS,YAAY;;AAGnD,SAAS,gBAAwB;AAC/B,QAAO,KAAK,KAAK,SAAS,EAAE,SAAS,OAAO;;AAK9C,SAAS,cAAuB;AAE9B,QAAO,CAAC,CAAE,QAA+C,OACvD,QAAQ,SAAS,SAAS,OAAO,IACjC,QAAQ,SAAS,SAAS,WAAW;;AAGzC,SAAS,oBAA4B;AACnC,KAAI,aAAa,CACf,QAAO,QAAQ;CAGjB,MAAM,UAAU,KAAK,QAAQ,IAAI,IAAI,OAAO,KAAK,IAAI,CAAC,SAAS;AAC/D,QAAO,KAAK,KAAK,SAAS,MAAM,OAAO,WAAW;;AAKpD,SAAgB,wBAAwB,QAOxB;CACd,MAAM,aAAa,0BAA0B;CAC7C,MAAM,YAAY,yBAAyB;CAC3C,MAAM,UAAU,OAAO,WAAW;CAGlC,IAAI;AAEJ,KAAI,OAAO,YAAY,YAAY,aAAa,CAG9C,oBAAmB;EADA,QAAQ;EACK;EAAW;EAAgB;EAAU,OAAO,KAAK,UAAU;EAAC;MACvF;EAEL,MAAM,WAAW,QAAQ,SAAS,QAC/B,QAAQ,CAAC,IAAI,WAAW,YAAY,IAAI,CAAC,IAAI,WAAW,UAAU,CACpE;EACD,MAAM,aAAa,mBAAmB;AACtC,qBAAmB;GACjB,QAAQ;GACR,GAAG;GACH;GACA;GACA;GACA;GAAU,OAAO,KAAK,UAAU;GACjC;;AAGH,KAAI,OAAO,QAAQ,OAAO,SAAS,WACjC,kBAAiB,KAAK,UAAU,OAAO,KAAK;CAI9C,MAAM,cAAsC;EAC1C,aAAa;EACb,gBAAgB;EAChB,gBAAgB,QAAQ,IAAI,kBAAkB;EAC9C,eAAe;EACf,kBAAkB;EAClB,cAAc,eAAe;GAC5B,0BAA0B;EAC3B,qBAAqB;EACtB;AAED,KAAI,OAAO,MACT,aAAY,qBAAqB,OAAO;AAa1C,MAAK,MAAM,OAAO;EARhB;EACA;EACA;EACA;EACA;EACA;EAG+B,CAC/B,KAAI,QAAQ,IAAI,KACd,aAAY,OAAO,QAAQ,IAAI;AAKnC,KAAI,OAAO;OACJ,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,IAAI,CACnD,KAAI,UAAU,KAAA,KAAa,CAAC,IAAI,WAAW,QAAQ,CACjD,aAAY,OAAO;;CAOzB,MAAM,cAAc,gCAAgC;EAAE,SADtC,OAAO,KAAK,cAAc,MAAM,IAAI,KAAA;EACW;EAAS,CAAC;AAEzE,KAAI,KAAK;EACP,kBAAkB,iBAAiB,MAAM,GAAG,EAAE;EAC9C,SAAS,OAAO,KAAK,YAAY;EACjC;EACD,EAAE,6BAA6B;AAEhC,QAAO;EACL;EACA,kBAAkB,KAAK,QAAQ,WAAW;EAC1C;EACA;EACD;;AAKH,SAAgB,wBAAwB,QAOV;CAC5B,MAAM,OAAO,wBAAwB,OAAO;AAE5C,QAAO;EACL,KAAK,OAAO,OAAO,QAAQ;EAC3B,kBAAkB,KAAK;EACvB,kBAAkB,KAAK;EACvB,aAAa,KAAK;EAClB,aAAa,KAAK;EACnB;;;AAMH,SAAgB,2BAA2B,kBAAqC;AAC9E,KAAI,iBAAiB,WAAW,EAAG,QAAO;CAC1C,MAAM,UAAU,iBAAiB;AACjC,QAAO,WAAW,QAAQ"}
1
+ {"version":3,"file":"install-plan.js","names":[],"sources":["../../../src/daemon/install-plan.ts"],"sourcesContent":["/**\n * Install Plan Builder - Build gateway installation configuration\n *\n * Aligned with OpenClaw: adds XOPC_SERVICE_VERSION, StandardOut/ErrorPath,\n * supports binary runtime detection, and --foreground arg passing.\n */\n\nimport { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { homedir } from 'node:os';\nimport { createLogger } from '../utils/logger.js';\nimport { SERVICE_VERSION_ENV_KEY, formatGatewayServiceDescription } from './constants.js';\nimport { PACKAGE_VERSION } from '../package-version.js';\nimport type { GatewayServiceInstallArgs, GatewayServiceEnv } from './types.js';\n\nconst log = createLogger('InstallPlan');\n\nexport interface InstallPlan {\n programArguments: string[];\n workingDirectory: string;\n environment: Record<string, string>;\n description: string;\n}\n\n// ─── Path Resolution ───\n\nfunction resolveDefaultConfigPath(): string {\n const envConfig = process.env.XOPC_CONFIG || process.env.XOPC_CONFIG_PATH;\n if (envConfig) return envConfig;\n return path.join(homedir(), '.xopc', 'xopc.json');\n}\n\nfunction resolveDefaultWorkspace(): string {\n const envWorkspace = process.env.XOPC_WORKSPACE;\n if (envWorkspace) return envWorkspace;\n return path.join(homedir(), '.xopc', 'workspace');\n}\n\nfunction resolveLogDir(): string {\n return path.join(homedir(), '.xopc', 'logs');\n}\n\n// ─── Binary Detection ───\n\nfunction isSEABinary(): boolean {\n // Node.js SEA (Single Executable Application) detection\n return !!(process as NodeJS.Process & { pkg?: unknown }).pkg ||\n process.execPath.endsWith('xopc') ||\n process.execPath.endsWith('xopc.exe');\n}\n\nfunction resolveEntryPoint(): string {\n if (isSEABinary()) {\n return process.execPath;\n }\n // Must match package.json \"bin\" (cli/bin.js). index.js only exports runCli and exits\n // immediately when executed directly — systemd/LaunchAgent need the real entry.\n const thisDir = path.dirname(new URL(import.meta.url).pathname);\n return path.join(thisDir, '..', 'cli', 'bin.js');\n}\n\n// ─── Plan Builder ───\n\nexport function buildGatewayInstallPlan(params: {\n port: number;\n bind?: import('../config/schema.js').GatewayBindMode;\n token?: string;\n env?: GatewayServiceEnv;\n runtime?: 'node' | 'binary';\n version?: string;\n}): InstallPlan {\n const configPath = resolveDefaultConfigPath();\n const workspace = resolveDefaultWorkspace();\n const version = params.version || PACKAGE_VERSION;\n\n // Determine program + arguments\n let programArguments: string[];\n\n if (params.runtime === 'binary' || isSEABinary()) {\n // SEA binary: direct execution\n const binaryPath = process.execPath;\n programArguments = [binaryPath, 'gateway', '--foreground', '--port', params.port.toString()];\n } else {\n // Node.js runtime\n const nodeArgs = process.execArgv.filter(\n (arg) => !arg.startsWith('--inspect') && !arg.startsWith('--debug'),\n );\n const entryPoint = resolveEntryPoint();\n programArguments = [\n process.execPath,\n ...nodeArgs,\n entryPoint,\n 'gateway',\n '--foreground',\n '--port', params.port.toString(),\n ];\n }\n\n if (params.bind && params.bind !== 'loopback') {\n programArguments.push('--bind', params.bind);\n }\n\n // Build environment\n const environment: Record<string, string> = {\n XOPC_CONFIG: configPath,\n XOPC_WORKSPACE: workspace,\n XOPC_LOG_LEVEL: process.env.XOPC_LOG_LEVEL || 'info',\n XOPC_LOG_FILE: 'true',\n XOPC_LOG_CONSOLE: 'false',\n XOPC_LOG_DIR: resolveLogDir(),\n [SERVICE_VERSION_ENV_KEY]: version,\n XOPC_SERVICE_MARKER: '1',\n };\n\n if (params.token) {\n environment.XOPC_GATEWAY_TOKEN = params.token;\n }\n\n // Copy relevant API key env vars\n const relevantEnvVars = [\n 'OPENAI_API_KEY',\n 'ANTHROPIC_API_KEY',\n 'GOOGLE_API_KEY',\n 'BRAVE_API_KEY',\n 'DASHSCOPE_API_KEY',\n 'XOPC_LOG_RETENTION_DAYS',\n ];\n\n for (const key of relevantEnvVars) {\n if (process.env[key]) {\n environment[key] = process.env[key]!;\n }\n }\n\n // Add custom env from params (non-XOPC keys only; XOPC keys already handled)\n if (params.env) {\n for (const [key, value] of Object.entries(params.env)) {\n if (value !== undefined && !key.startsWith('XOPC_')) {\n environment[key] = value;\n }\n }\n }\n\n // Service description\n const profile = params.env?.XOPC_PROFILE?.trim() || undefined;\n const description = formatGatewayServiceDescription({ profile, version });\n\n log.info({\n programArguments: programArguments.slice(0, 3),\n envKeys: Object.keys(environment),\n version,\n }, 'Built gateway install plan');\n\n return {\n programArguments,\n workingDirectory: path.dirname(configPath),\n environment,\n description,\n };\n}\n\n// ─── Install Args Builder ───\n\nexport function buildGatewayInstallArgs(params: {\n port: number;\n bind?: import('../config/schema.js').GatewayBindMode;\n token?: string;\n env?: GatewayServiceEnv;\n runtime?: 'node' | 'binary';\n version?: string;\n}): GatewayServiceInstallArgs {\n const plan = buildGatewayInstallPlan(params);\n\n return {\n env: params.env || process.env,\n programArguments: plan.programArguments,\n workingDirectory: plan.workingDirectory,\n environment: plan.environment,\n description: plan.description,\n };\n}\n\n// ─── Validation ───\n\n/** Check if the program in an install plan still exists on disk */\nexport function validateInstallPlanProgram(programArguments: string[]): boolean {\n if (programArguments.length === 0) return false;\n const program = programArguments[0];\n return existsSync(program);\n}\n"],"mappings":";;;;;;;;;;;;;;aAUkD;sBAEM;AAGxD,MAAM,MAAM,aAAa,cAAc;AAWvC,SAAS,2BAAmC;CAC1C,MAAM,YAAY,QAAQ,IAAI,eAAe,QAAQ,IAAI;AACzD,KAAI,UAAW,QAAO;AACtB,QAAO,KAAK,KAAK,SAAS,EAAE,SAAS,YAAY;;AAGnD,SAAS,0BAAkC;CACzC,MAAM,eAAe,QAAQ,IAAI;AACjC,KAAI,aAAc,QAAO;AACzB,QAAO,KAAK,KAAK,SAAS,EAAE,SAAS,YAAY;;AAGnD,SAAS,gBAAwB;AAC/B,QAAO,KAAK,KAAK,SAAS,EAAE,SAAS,OAAO;;AAK9C,SAAS,cAAuB;AAE9B,QAAO,CAAC,CAAE,QAA+C,OACvD,QAAQ,SAAS,SAAS,OAAO,IACjC,QAAQ,SAAS,SAAS,WAAW;;AAGzC,SAAS,oBAA4B;AACnC,KAAI,aAAa,CACf,QAAO,QAAQ;CAIjB,MAAM,UAAU,KAAK,QAAQ,IAAI,IAAI,OAAO,KAAK,IAAI,CAAC,SAAS;AAC/D,QAAO,KAAK,KAAK,SAAS,MAAM,OAAO,SAAS;;AAKlD,SAAgB,wBAAwB,QAOxB;CACd,MAAM,aAAa,0BAA0B;CAC7C,MAAM,YAAY,yBAAyB;CAC3C,MAAM,UAAU,OAAO,WAAW;CAGlC,IAAI;AAEJ,KAAI,OAAO,YAAY,YAAY,aAAa,CAG9C,oBAAmB;EADA,QAAQ;EACK;EAAW;EAAgB;EAAU,OAAO,KAAK,UAAU;EAAC;MACvF;EAEL,MAAM,WAAW,QAAQ,SAAS,QAC/B,QAAQ,CAAC,IAAI,WAAW,YAAY,IAAI,CAAC,IAAI,WAAW,UAAU,CACpE;EACD,MAAM,aAAa,mBAAmB;AACtC,qBAAmB;GACjB,QAAQ;GACR,GAAG;GACH;GACA;GACA;GACA;GAAU,OAAO,KAAK,UAAU;GACjC;;AAGH,KAAI,OAAO,QAAQ,OAAO,SAAS,WACjC,kBAAiB,KAAK,UAAU,OAAO,KAAK;CAI9C,MAAM,cAAsC;EAC1C,aAAa;EACb,gBAAgB;EAChB,gBAAgB,QAAQ,IAAI,kBAAkB;EAC9C,eAAe;EACf,kBAAkB;EAClB,cAAc,eAAe;GAC5B,0BAA0B;EAC3B,qBAAqB;EACtB;AAED,KAAI,OAAO,MACT,aAAY,qBAAqB,OAAO;AAa1C,MAAK,MAAM,OAAO;EARhB;EACA;EACA;EACA;EACA;EACA;EAG+B,CAC/B,KAAI,QAAQ,IAAI,KACd,aAAY,OAAO,QAAQ,IAAI;AAKnC,KAAI,OAAO;OACJ,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,IAAI,CACnD,KAAI,UAAU,KAAA,KAAa,CAAC,IAAI,WAAW,QAAQ,CACjD,aAAY,OAAO;;CAOzB,MAAM,cAAc,gCAAgC;EAAE,SADtC,OAAO,KAAK,cAAc,MAAM,IAAI,KAAA;EACW;EAAS,CAAC;AAEzE,KAAI,KAAK;EACP,kBAAkB,iBAAiB,MAAM,GAAG,EAAE;EAC9C,SAAS,OAAO,KAAK,YAAY;EACjC;EACD,EAAE,6BAA6B;AAEhC,QAAO;EACL;EACA,kBAAkB,KAAK,QAAQ,WAAW;EAC1C;EACA;EACD;;AAKH,SAAgB,wBAAwB,QAOV;CAC5B,MAAM,OAAO,wBAAwB,OAAO;AAE5C,QAAO;EACL,KAAK,OAAO,OAAO,QAAQ;EAC3B,kBAAkB,KAAK;EACvB,kBAAkB,KAAK;EACvB,aAAa,KAAK;EAClB,aAAa,KAAK;EACnB;;;AAMH,SAAgB,2BAA2B,kBAAqC;AAC9E,KAAI,iBAAiB,WAAW,EAAG,QAAO;CAC1C,MAAM,UAAU,iBAAiB;AACjC,QAAO,WAAW,QAAQ"}
@@ -1,10 +1,10 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
3
  import { resolveGatewayLaunchAgentLabel, resolveLaunchAgentPlistPath as resolveLaunchAgentPlistPath$1 } from "./constants.js";
4
+ import os from "node:os";
5
+ import path from "node:path";
4
6
  import { existsSync } from "node:fs";
5
7
  import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
6
- import path from "node:path";
7
- import os from "node:os";
8
8
  import { spawn, spawnSync } from "node:child_process";
9
9
  //#region src/daemon/launchd.ts
10
10
  /**
@@ -1,6 +1,9 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
3
  import { resolveGatewayWindowsTaskName } from "./constants.js";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
7
  import { spawn, spawnSync } from "node:child_process";
5
8
  //#region src/daemon/schtasks.ts
6
9
  /**
@@ -57,6 +60,36 @@ async function schtasksExec(args) {
57
60
  }
58
61
  return result.stdout;
59
62
  }
63
+ function resolveTaskEnvSidecarPath(taskName) {
64
+ const configDir = path.join(os.homedir(), ".xopc", "daemon");
65
+ return path.join(configDir, `${taskName}.env.json`);
66
+ }
67
+ function writeTaskEnvSidecar(taskName, environment) {
68
+ const sidecarPath = resolveTaskEnvSidecarPath(taskName);
69
+ try {
70
+ mkdirSync(path.dirname(sidecarPath), { recursive: true });
71
+ writeFileSync(sidecarPath, JSON.stringify(environment, null, 2), "utf8");
72
+ } catch (err) {
73
+ log.warn({
74
+ err,
75
+ sidecarPath
76
+ }, "Failed to write task environment sidecar");
77
+ }
78
+ }
79
+ function readTaskEnvSidecar(taskName) {
80
+ const sidecarPath = resolveTaskEnvSidecarPath(taskName);
81
+ try {
82
+ const raw = readFileSync(sidecarPath, "utf8");
83
+ const parsed = JSON.parse(raw);
84
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
85
+ } catch {}
86
+ }
87
+ function removeTaskEnvSidecar(taskName) {
88
+ const sidecarPath = resolveTaskEnvSidecarPath(taskName);
89
+ try {
90
+ rmSync(sidecarPath, { force: true });
91
+ } catch {}
92
+ }
60
93
  function isSchtasksAvailable() {
61
94
  if (process.platform !== "win32") return false;
62
95
  try {
@@ -101,6 +134,7 @@ const schtasksService = {
101
134
  "LIMITED",
102
135
  "/f"
103
136
  ]);
137
+ if (args.environment && Object.keys(args.environment).length > 0) writeTaskEnvSidecar(taskName, args.environment);
104
138
  args.stdout?.write(`Created scheduled task: ${taskName}\n`);
105
139
  args.stdout?.write(` Program: ${program}\n`);
106
140
  args.stdout?.write(` Args: ${programArgs}\n`);
@@ -126,6 +160,7 @@ const schtasksService = {
126
160
  } catch (err) {
127
161
  log.debug({ err }, "Uninstall task not found");
128
162
  }
163
+ removeTaskEnvSidecar(taskName);
129
164
  log.info({ taskName }, "Scheduled task uninstalled");
130
165
  },
131
166
  async stop(args) {
@@ -228,9 +263,11 @@ const schtasksService = {
228
263
  if (closeQuote > 0) programArguments = [taskRun.slice(1, closeQuote), ...taskRun.slice(closeQuote + 1).trim().split(/\s+/).filter(Boolean)];
229
264
  else programArguments = taskRun.split(/\s+/);
230
265
  } else programArguments = taskRun.split(/\s+/);
266
+ const environment = readTaskEnvSidecar(taskName);
231
267
  return {
232
268
  programArguments,
233
- workingDirectory: workDirMatch?.[1]?.trim() || void 0
269
+ workingDirectory: workDirMatch?.[1]?.trim() || void 0,
270
+ environment
234
271
  };
235
272
  } catch {
236
273
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"schtasks.js","names":[],"sources":["../../../src/daemon/schtasks.ts"],"sourcesContent":["/**\n * Scheduled Task Service - Windows service management via schtasks\n *\n * Aligned with OpenClaw Windows implementation:\n * - Task with ONLOGON trigger for persistence\n * - RepetitionInterval for keep-alive behavior\n * - Proper start/stop/restart lifecycle\n */\n\nimport { spawn, spawnSync } from 'node:child_process';\nimport { createLogger } from '../utils/logger.js';\nimport { resolveGatewayWindowsTaskName } from './constants.js';\nimport type {\n GatewayService,\n GatewayServiceInstallArgs,\n GatewayServiceControlArgs,\n GatewayServiceEnvArgs,\n GatewayServiceRuntime,\n GatewayServiceCommandConfig,\n GatewayServiceEnv,\n GatewayServiceRestartResult,\n} from './types.js';\n\nconst log = createLogger('SchtasksService');\n\n// ─── Resolution ───\n\nfunction resolveProfileFromEnv(env?: GatewayServiceEnv): string | undefined {\n return env?.XOPC_PROFILE?.trim() || undefined;\n}\n\nfunction resolveTaskName(env?: GatewayServiceEnv): string {\n return resolveGatewayWindowsTaskName(resolveProfileFromEnv(env));\n}\n\n// ─── Command Execution ───\n\ninterface SchtasksResult {\n stdout: string;\n stderr: string;\n exitCode: number | null;\n}\n\nasync function schtasks(args: string[]): Promise<SchtasksResult> {\n return new Promise<SchtasksResult>((resolve, reject) => {\n const child = spawn('schtasks', args, {\n stdio: ['ignore', 'pipe', 'pipe'],\n shell: true,\n });\n\n let stdout = '';\n let stderr = '';\n\n child.stdout?.on('data', (data) => { stdout += data.toString(); });\n child.stderr?.on('data', (data) => { stderr += data.toString(); });\n\n child.on('close', (code) => {\n resolve({ stdout, stderr, exitCode: code });\n });\n child.on('error', (err) => {\n reject(new Error(`schtasks spawn failed: ${err.message}`));\n });\n });\n}\n\nasync function schtasksExec(args: string[]): Promise<string> {\n const result = await schtasks(args);\n if (result.exitCode !== 0) {\n const detail = result.stderr.trim() || result.stdout.trim();\n throw new Error(`schtasks failed (exit ${result.exitCode}): ${detail}`);\n }\n return result.stdout;\n}\n\n// ─── Availability Check ───\n\nexport function isSchtasksAvailable(): boolean {\n if (process.platform !== 'win32') return false;\n try {\n const result = spawnSync('schtasks', ['/query', '/?'], {\n stdio: ['ignore', 'ignore', 'ignore'],\n shell: true,\n timeout: 3000,\n });\n return result.status === 0;\n } catch {\n return false;\n }\n}\n\n// ─── Service Implementation ───\n\nexport const schtasksService: GatewayService = {\n label: resolveGatewayWindowsTaskName(),\n loadedText: 'Scheduled Task (installed)',\n notLoadedText: 'Scheduled Task (not installed)',\n\n async install(args: GatewayServiceInstallArgs): Promise<void> {\n const taskName = resolveTaskName(args.env);\n const program = args.programArguments[0];\n const programArgs = args.programArguments.slice(1).join(' ');\n\n // Delete existing task first (ignore errors)\n try {\n await schtasks(['/delete', '/tn', taskName, '/f']);\n } catch {\n // Ignore\n }\n\n // Create task with ONLOGON trigger\n const createArgs = [\n '/create',\n '/tn', taskName,\n '/tr', `\"${program}\" ${programArgs}`,\n '/sc', 'ONLOGON',\n '/rl', 'LIMITED',\n '/f',\n ];\n\n await schtasksExec(createArgs);\n\n args.stdout?.write(`Created scheduled task: ${taskName}\\n`);\n args.stdout?.write(` Program: ${program}\\n`);\n args.stdout?.write(` Args: ${programArgs}\\n`);\n\n log.info({ taskName }, 'Scheduled task installed');\n },\n\n async uninstall(args: GatewayServiceControlArgs): Promise<void> {\n const taskName = resolveTaskName(args.env);\n\n // Stop if running\n try {\n await schtasks(['/end', '/tn', taskName]);\n } catch {\n // Ignore\n }\n\n // Delete task\n try {\n await schtasksExec(['/delete', '/tn', taskName, '/f']);\n args.stdout?.write(`Deleted scheduled task: ${taskName}\\n`);\n } catch (err) {\n log.debug({ err }, 'Uninstall task not found');\n }\n\n log.info({ taskName }, 'Scheduled task uninstalled');\n },\n\n async stop(args: GatewayServiceControlArgs): Promise<void> {\n const taskName = resolveTaskName(args.env);\n\n try {\n await schtasksExec(['/end', '/tn', taskName]);\n } catch {\n log.debug('Task not running');\n }\n\n if (args.disable) {\n try {\n await schtasksExec(['/change', '/tn', taskName, '/disable']);\n } catch {\n // Ignore\n }\n }\n\n log.info('Scheduled task stopped');\n },\n\n async restart(args: GatewayServiceControlArgs): Promise<GatewayServiceRestartResult> {\n const taskName = resolveTaskName(args.env);\n\n // End current run\n try {\n await schtasks(['/end', '/tn', taskName]);\n } catch {\n // Ignore\n }\n\n // Small delay for process cleanup\n await new Promise((resolve) => setTimeout(resolve, 500));\n\n // Start new run\n await schtasksExec(['/run', '/tn', taskName]);\n\n log.info('Scheduled task restarted');\n return { outcome: 'restarted' };\n },\n\n async isLoaded(args: GatewayServiceEnvArgs): Promise<boolean> {\n const taskName = resolveTaskName(args.env);\n const result = await schtasks(['/query', '/tn', taskName]);\n return result.exitCode === 0;\n },\n\n async readRuntime(env?: GatewayServiceEnv): Promise<GatewayServiceRuntime> {\n const taskName = resolveTaskName(env);\n\n try {\n const result = await schtasks(['/query', '/tn', taskName, '/fo', 'list', '/v']);\n if (result.exitCode !== 0) {\n return { status: 'unknown' };\n }\n\n const output = result.stdout;\n let status: 'running' | 'stopped' | 'unknown' = 'unknown';\n\n const statusMatch = output.match(/Status:\\s*(\\w+)/i);\n if (statusMatch) {\n const statusStr = statusMatch[1].toLowerCase();\n if (statusStr === 'running') {\n status = 'running';\n } else if (statusStr === 'ready' || statusStr === 'disabled') {\n status = 'stopped';\n }\n }\n\n // Parse last result code\n let lastExitStatus: number | undefined;\n const resultMatch = output.match(/Last Result:\\s*(\\d+)/i);\n if (resultMatch) {\n lastExitStatus = parseInt(resultMatch[1], 10);\n }\n\n return { status, lastExitStatus };\n } catch {\n return { status: 'unknown' };\n }\n },\n\n async readCommand(env?: GatewayServiceEnv): Promise<GatewayServiceCommandConfig | null> {\n const taskName = resolveTaskName(env);\n\n try {\n const result = await schtasks(['/query', '/tn', taskName, '/fo', 'list', '/v']);\n if (result.exitCode !== 0) return null;\n\n const output = result.stdout;\n const taskRunMatch = output.match(/Task To Run:\\s*(.+)/i);\n const workDirMatch = output.match(/Start In:\\s*(.+)/i);\n\n if (!taskRunMatch) return null;\n\n const taskRun = taskRunMatch[1].trim();\n // Handle quoted program path\n let programArguments: string[];\n if (taskRun.startsWith('\"')) {\n const closeQuote = taskRun.indexOf('\"', 1);\n if (closeQuote > 0) {\n const program = taskRun.slice(1, closeQuote);\n const rest = taskRun.slice(closeQuote + 1).trim();\n programArguments = [program, ...rest.split(/\\s+/).filter(Boolean)];\n } else {\n programArguments = taskRun.split(/\\s+/);\n }\n } else {\n programArguments = taskRun.split(/\\s+/);\n }\n\n return {\n programArguments,\n workingDirectory: workDirMatch?.[1]?.trim() || undefined,\n };\n } catch {\n return null;\n }\n },\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"schtasks.js","names":[],"sources":["../../../src/daemon/schtasks.ts"],"sourcesContent":["/**\n * Scheduled Task Service - Windows service management via schtasks\n *\n * Aligned with OpenClaw Windows implementation:\n * - Task with ONLOGON trigger for persistence\n * - RepetitionInterval for keep-alive behavior\n * - Proper start/stop/restart lifecycle\n */\n\nimport { spawn, spawnSync } from 'node:child_process';\nimport { mkdirSync, readFileSync, writeFileSync, rmSync } from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { createLogger } from '../utils/logger.js';\nimport { resolveGatewayWindowsTaskName } from './constants.js';\nimport type {\n GatewayService,\n GatewayServiceInstallArgs,\n GatewayServiceControlArgs,\n GatewayServiceEnvArgs,\n GatewayServiceRuntime,\n GatewayServiceCommandConfig,\n GatewayServiceEnv,\n GatewayServiceRestartResult,\n} from './types.js';\n\nconst log = createLogger('SchtasksService');\n\n// ─── Resolution ───\n\nfunction resolveProfileFromEnv(env?: GatewayServiceEnv): string | undefined {\n return env?.XOPC_PROFILE?.trim() || undefined;\n}\n\nfunction resolveTaskName(env?: GatewayServiceEnv): string {\n return resolveGatewayWindowsTaskName(resolveProfileFromEnv(env));\n}\n\n// ─── Command Execution ───\n\ninterface SchtasksResult {\n stdout: string;\n stderr: string;\n exitCode: number | null;\n}\n\nasync function schtasks(args: string[]): Promise<SchtasksResult> {\n return new Promise<SchtasksResult>((resolve, reject) => {\n const child = spawn('schtasks', args, {\n stdio: ['ignore', 'pipe', 'pipe'],\n shell: true,\n });\n\n let stdout = '';\n let stderr = '';\n\n child.stdout?.on('data', (data) => { stdout += data.toString(); });\n child.stderr?.on('data', (data) => { stderr += data.toString(); });\n\n child.on('close', (code) => {\n resolve({ stdout, stderr, exitCode: code });\n });\n child.on('error', (err) => {\n reject(new Error(`schtasks spawn failed: ${err.message}`));\n });\n });\n}\n\nasync function schtasksExec(args: string[]): Promise<string> {\n const result = await schtasks(args);\n if (result.exitCode !== 0) {\n const detail = result.stderr.trim() || result.stdout.trim();\n throw new Error(`schtasks failed (exit ${result.exitCode}): ${detail}`);\n }\n return result.stdout;\n}\n\n// ─── Environment Sidecar ───\n// schtasks does not natively support per-task environment variables.\n// We persist them in a JSON sidecar so readCommand can return them\n// for version-mismatch detection and other diagnostics.\n\nfunction resolveTaskEnvSidecarPath(taskName: string): string {\n const configDir = path.join(os.homedir(), '.xopc', 'daemon');\n return path.join(configDir, `${taskName}.env.json`);\n}\n\nfunction writeTaskEnvSidecar(taskName: string, environment: Record<string, string>): void {\n const sidecarPath = resolveTaskEnvSidecarPath(taskName);\n try {\n mkdirSync(path.dirname(sidecarPath), { recursive: true });\n writeFileSync(sidecarPath, JSON.stringify(environment, null, 2), 'utf8');\n } catch (err) {\n log.warn({ err, sidecarPath }, 'Failed to write task environment sidecar');\n }\n}\n\nfunction readTaskEnvSidecar(taskName: string): Record<string, string> | undefined {\n const sidecarPath = resolveTaskEnvSidecarPath(taskName);\n try {\n const raw = readFileSync(sidecarPath, 'utf8');\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return parsed as Record<string, string>;\n }\n } catch {\n // Sidecar missing or corrupt — not fatal\n }\n return undefined;\n}\n\nfunction removeTaskEnvSidecar(taskName: string): void {\n const sidecarPath = resolveTaskEnvSidecarPath(taskName);\n try {\n rmSync(sidecarPath, { force: true });\n } catch {\n // Best-effort\n }\n}\n\n// ─── Availability Check ───\n\nexport function isSchtasksAvailable(): boolean {\n if (process.platform !== 'win32') return false;\n try {\n const result = spawnSync('schtasks', ['/query', '/?'], {\n stdio: ['ignore', 'ignore', 'ignore'],\n shell: true,\n timeout: 3000,\n });\n return result.status === 0;\n } catch {\n return false;\n }\n}\n\n// ─── Service Implementation ───\n\nexport const schtasksService: GatewayService = {\n label: resolveGatewayWindowsTaskName(),\n loadedText: 'Scheduled Task (installed)',\n notLoadedText: 'Scheduled Task (not installed)',\n\n async install(args: GatewayServiceInstallArgs): Promise<void> {\n const taskName = resolveTaskName(args.env);\n const program = args.programArguments[0];\n const programArgs = args.programArguments.slice(1).join(' ');\n\n // Delete existing task first (ignore errors)\n try {\n await schtasks(['/delete', '/tn', taskName, '/f']);\n } catch {\n // Ignore\n }\n\n // Create task with ONLOGON trigger\n const createArgs = [\n '/create',\n '/tn', taskName,\n '/tr', `\"${program}\" ${programArgs}`,\n '/sc', 'ONLOGON',\n '/rl', 'LIMITED',\n '/f',\n ];\n\n await schtasksExec(createArgs);\n\n // Persist environment variables in a sidecar file\n // (schtasks does not support per-task env vars natively)\n if (args.environment && Object.keys(args.environment).length > 0) {\n writeTaskEnvSidecar(taskName, args.environment);\n }\n\n args.stdout?.write(`Created scheduled task: ${taskName}\\n`);\n args.stdout?.write(` Program: ${program}\\n`);\n args.stdout?.write(` Args: ${programArgs}\\n`);\n\n log.info({ taskName }, 'Scheduled task installed');\n },\n\n async uninstall(args: GatewayServiceControlArgs): Promise<void> {\n const taskName = resolveTaskName(args.env);\n\n // Stop if running\n try {\n await schtasks(['/end', '/tn', taskName]);\n } catch {\n // Ignore\n }\n\n // Delete task\n try {\n await schtasksExec(['/delete', '/tn', taskName, '/f']);\n args.stdout?.write(`Deleted scheduled task: ${taskName}\\n`);\n } catch (err) {\n log.debug({ err }, 'Uninstall task not found');\n }\n\n // Clean up environment sidecar\n removeTaskEnvSidecar(taskName);\n\n log.info({ taskName }, 'Scheduled task uninstalled');\n },\n\n async stop(args: GatewayServiceControlArgs): Promise<void> {\n const taskName = resolveTaskName(args.env);\n\n try {\n await schtasksExec(['/end', '/tn', taskName]);\n } catch {\n log.debug('Task not running');\n }\n\n if (args.disable) {\n try {\n await schtasksExec(['/change', '/tn', taskName, '/disable']);\n } catch {\n // Ignore\n }\n }\n\n log.info('Scheduled task stopped');\n },\n\n async restart(args: GatewayServiceControlArgs): Promise<GatewayServiceRestartResult> {\n const taskName = resolveTaskName(args.env);\n\n // End current run\n try {\n await schtasks(['/end', '/tn', taskName]);\n } catch {\n // Ignore\n }\n\n // Small delay for process cleanup\n await new Promise((resolve) => setTimeout(resolve, 500));\n\n // Start new run\n await schtasksExec(['/run', '/tn', taskName]);\n\n log.info('Scheduled task restarted');\n return { outcome: 'restarted' };\n },\n\n async isLoaded(args: GatewayServiceEnvArgs): Promise<boolean> {\n const taskName = resolveTaskName(args.env);\n const result = await schtasks(['/query', '/tn', taskName]);\n return result.exitCode === 0;\n },\n\n async readRuntime(env?: GatewayServiceEnv): Promise<GatewayServiceRuntime> {\n const taskName = resolveTaskName(env);\n\n try {\n const result = await schtasks(['/query', '/tn', taskName, '/fo', 'list', '/v']);\n if (result.exitCode !== 0) {\n return { status: 'unknown' };\n }\n\n const output = result.stdout;\n let status: 'running' | 'stopped' | 'unknown' = 'unknown';\n\n const statusMatch = output.match(/Status:\\s*(\\w+)/i);\n if (statusMatch) {\n const statusStr = statusMatch[1].toLowerCase();\n if (statusStr === 'running') {\n status = 'running';\n } else if (statusStr === 'ready' || statusStr === 'disabled') {\n status = 'stopped';\n }\n }\n\n // Parse last result code\n let lastExitStatus: number | undefined;\n const resultMatch = output.match(/Last Result:\\s*(\\d+)/i);\n if (resultMatch) {\n lastExitStatus = parseInt(resultMatch[1], 10);\n }\n\n return { status, lastExitStatus };\n } catch {\n return { status: 'unknown' };\n }\n },\n\n async readCommand(env?: GatewayServiceEnv): Promise<GatewayServiceCommandConfig | null> {\n const taskName = resolveTaskName(env);\n\n try {\n const result = await schtasks(['/query', '/tn', taskName, '/fo', 'list', '/v']);\n if (result.exitCode !== 0) return null;\n\n const output = result.stdout;\n const taskRunMatch = output.match(/Task To Run:\\s*(.+)/i);\n const workDirMatch = output.match(/Start In:\\s*(.+)/i);\n\n if (!taskRunMatch) return null;\n\n const taskRun = taskRunMatch[1].trim();\n // Handle quoted program path\n let programArguments: string[];\n if (taskRun.startsWith('\"')) {\n const closeQuote = taskRun.indexOf('\"', 1);\n if (closeQuote > 0) {\n const program = taskRun.slice(1, closeQuote);\n const rest = taskRun.slice(closeQuote + 1).trim();\n programArguments = [program, ...rest.split(/\\s+/).filter(Boolean)];\n } else {\n programArguments = taskRun.split(/\\s+/);\n }\n } else {\n programArguments = taskRun.split(/\\s+/);\n }\n\n // Read environment from sidecar file (schtasks has no native env support)\n const environment = readTaskEnvSidecar(taskName);\n\n return {\n programArguments,\n workingDirectory: workDirMatch?.[1]?.trim() || undefined,\n environment,\n };\n } catch {\n return null;\n }\n },\n};\n"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
3
  import { resolveGatewaySystemdServiceName, resolveSystemdUnitPath } from "./constants.js";
4
+ import os from "node:os";
5
+ import path from "node:path";
4
6
  import { existsSync } from "node:fs";
5
7
  import { access, constants as constants$1, mkdir, readFile, rm, writeFile } from "node:fs/promises";
6
- import path from "node:path";
7
- import os from "node:os";
8
8
  import { spawn, spawnSync } from "node:child_process";
9
9
  //#region src/daemon/systemd.ts
10
10
  /**
@@ -1,8 +1,8 @@
1
1
  import { init_paths, resolveBundledExtensionsDir, resolveExtensionsDir } from "../config/paths.js";
2
2
  import { isRecord } from "../utils/is-record.js";
3
3
  import { normalizeConfiguredMcpServers } from "../config/mcp-config-normalize.js";
4
- import { existsSync, readFileSync, readdirSync } from "node:fs";
5
4
  import { join } from "node:path";
5
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
6
6
  //#region src/extensions/bundle-mcp.ts
7
7
  init_paths();
8
8
  function extractMcpServerMap(raw) {
@@ -1,6 +1,6 @@
1
+ import { init_agent_scope, resolveDefaultAgentId } from "../agent/agent-scope.js";
1
2
  import { createLogger } from "../utils/logger/index.js";
2
3
  import { init_logger } from "../utils/logger.js";
3
- import { init_agent_scope, resolveDefaultAgentId } from "../agent/agent-scope.js";
4
4
  import { init_paths, resolveBundledExtensionsDir, resolveExtensionsDir, resolveWorkspaceExtensionsDir } from "../config/paths.js";
5
5
  import { init_loader, loadConfig } from "../config/loader.js";
6
6
  import { normalizeExtensionManifest } from "./normalize-manifest.js";
@@ -1,8 +1,8 @@
1
1
  import { init_paths, resolveExtensionsDir } from "../config/paths.js";
2
2
  import { getExtensionLockfileManager } from "./lockfile.js";
3
- import { readFile, readdir } from "fs/promises";
4
3
  import { join } from "path";
5
4
  import { existsSync } from "fs";
5
+ import { readFile, readdir } from "fs/promises";
6
6
  //#region src/extensions/health.ts
7
7
  init_paths();
8
8
  var ExtensionHealthChecker = class {
@@ -1,7 +1,7 @@
1
1
  import { PACKAGE_VERSION, init_package_version } from "../package-version.js";
2
+ import { init_agent_scope, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agent/agent-scope.js";
2
3
  import { createLogger, createServiceLogger } from "../utils/logger/index.js";
3
4
  import { init_logger } from "../utils/logger.js";
4
- import { init_agent_scope, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agent/agent-scope.js";
5
5
  import { init_paths, resolveBundledExtensionsDir, resolveExtensionSdkPath, resolveExtensionsDir, resolveWorkspaceExtensionsDir } from "../config/paths.js";
6
6
  import { init_loader, loadConfig } from "../config/loader.js";
7
7
  import { getProviderRegistry, init_plugin_registry } from "../providers/plugin-registry.js";
@@ -1,10 +1,10 @@
1
- import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
2
1
  import { createLogger } from "../utils/logger/index.js";
3
2
  import { init_logger } from "../utils/logger.js";
4
3
  import { init_paths, resolveExtensionsDir, resolveExtensionsLockPath } from "../config/paths.js";
5
- import { mkdir, readFile } from "fs/promises";
4
+ import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
6
5
  import { dirname, join } from "path";
7
6
  import { existsSync } from "fs";
7
+ import { mkdir, readFile } from "fs/promises";
8
8
  import { createHash } from "crypto";
9
9
  //#region src/extensions/lockfile.ts
10
10
  init_write_file_atomic();
@@ -1,13 +1,13 @@
1
1
  import { DEFAULT_AGENT_ID, init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentDir, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId, resolveUserPath, validateAgentIdForNewAgent } from "../agent/agent-scope.js";
2
- import { WORKSPACE_FILES, init_paths } from "../config/paths.js";
3
2
  import { resolveEffectiveAgentProfile } from "../config/agent-profile.js";
3
+ import { WORKSPACE_FILES, init_paths } from "../config/paths.js";
4
4
  import { AGENT_PROFILE_MARKDOWN_SYSTEM_FILES } from "../agent/context/workspace.js";
5
5
  import { isPathUnderWorkspace, resolveWorkspaceSafePath } from "./workspace-editor-path.js";
6
6
  import { applyAgentConfig, findAgentEntryIndex, pruneAgentConfig, removeAgentDirsFromDisk } from "../commands/agents.config.js";
7
7
  import { GATEWAY_BUILTIN_TOOL_IDS } from "./agent-builtin-tools.js";
8
8
  import { seedAgentProfileMarkdownFiles } from "../agent/context/workspace-seed.js";
9
- import { mkdir, readFile, realpath, stat, unlink, writeFile } from "node:fs/promises";
10
9
  import { join, resolve } from "node:path";
10
+ import { mkdir, readFile, realpath, stat, unlink, writeFile } from "node:fs/promises";
11
11
  //#region src/gateway/agents-admin.ts
12
12
  /**
13
13
  * Gateway REST helpers for multi-agent management.
@@ -1,11 +1,11 @@
1
1
  import { init_paths_state, resolveStateDir } from "../config/paths-state.js";
2
2
  import { init_agent_scope, resolveAgentProfileDir } from "../agent/agent-scope.js";
3
- import { init_paths, resolveConfigPath, resolveSessionsDir, resolveSkillsDir } from "../config/paths.js";
4
3
  import { extractProfileAgentId } from "../config/agent-profile.js";
4
+ import { init_paths, resolveConfigPath, resolveSessionsDir, resolveSkillsDir } from "../config/paths.js";
5
5
  import { isBareProfileMarkdownFileName, resolveProfileMarkdownPathIfBareName } from "../agent/tools/tool-paths.js";
6
6
  import { isPathUnderWorkspace, resolveWorkspaceSafePath } from "./workspace-editor-path.js";
7
- import { stat } from "node:fs/promises";
8
7
  import { basename, isAbsolute, resolve } from "node:path";
8
+ import { stat } from "node:fs/promises";
9
9
  //#region src/gateway/file-path-classifier.ts
10
10
  init_agent_scope();
11
11
  init_paths();
@@ -2,10 +2,12 @@ import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
3
  import { resolveAllowedBrowserOrigins, resolveGatewayServiceListenPort } from "../host.js";
4
4
  import { resolveGatewayEffectiveHost } from "../../config/gateway-bind.js";
5
- import { maxWebchatAgentRequestBodyBytes } from "../chat-limits.js";
6
5
  import { loadTunnelState } from "../../tunnel/tunnel-state.js";
6
+ import { maxWebchatAgentRequestBodyBytes } from "../chat-limits.js";
7
+ import { isLoopbackIpAddress, isTrustedProxyAddress } from "../client-ip.js";
7
8
  import { buildGatewayConsoleCspHeader } from "../security/csp.js";
8
9
  import { checkBrowserOrigin } from "../security/origin-check.js";
10
+ import { resolveReverseProxyPublicUrl } from "../public-url.js";
9
11
  import { auth } from "./middleware/auth.js";
10
12
  import { operatorScopes } from "./middleware/scopes.js";
11
13
  import { createStrictRateLimitMiddleware } from "./middleware/strict-rate-limit.js";
@@ -16,10 +18,12 @@ import { resetLazyRouteBundlesForTests } from "./routes/lazy-fallback.js";
16
18
  import { registerAuthenticatedRoutes } from "./routes/index.js";
17
19
  import { prewarmStaticUiCache } from "./lib/static-ui.js";
18
20
  import { registerPublicGatewayRoutes } from "./routes/public-gateway.js";
21
+ import { registerSiteShareMiddleware } from "../../share/site-share-router.js";
19
22
  import { Hono } from "hono";
20
23
  import { cors } from "hono/cors";
21
24
  import { createMiddleware } from "hono/factory";
22
25
  import { bodyLimit } from "hono/body-limit";
26
+ import { getConnInfo } from "@hono/node-server/conninfo";
23
27
  //#region src/gateway/hono/app.ts
24
28
  init_logger();
25
29
  const log = createLogger("HonoApp");
@@ -40,13 +44,39 @@ function createHonoApp(config) {
40
44
  configuredOrigins: service.currentConfig.gateway.corsOrigins,
41
45
  port: gatewayPort,
42
46
  bindHost: resolveGatewayEffectiveHost(service.currentConfig),
43
- tunnelPublicUrl: loadTunnelState()?.publicUrl
47
+ tunnelPublicUrl: loadTunnelState()?.publicUrl,
48
+ reverseProxyPublicUrl: resolveReverseProxyPublicUrl(service.currentConfig)
44
49
  });
50
+ /**
51
+ * TCP source for the in-flight request, normalized for trusted-proxy checks.
52
+ * Returns undefined when the runtime doesn't expose conninfo (tests, mocks).
53
+ */
54
+ const resolveRequestRemoteAddress = (c) => {
55
+ try {
56
+ return getConnInfo(c).remote.address;
57
+ } catch {
58
+ return;
59
+ }
60
+ };
61
+ /**
62
+ * A request's TCP source qualifies as a "trusted proxy hop" when it's
63
+ * loopback (the user's own machine, where any reverse proxy lives) or
64
+ * listed in `gateway.trustedProxies`. We use this signal to safely
65
+ * auto-allow same-host Origins through CSRF without requiring a manual
66
+ * `corsOrigins` entry for every reverse-proxy hostname.
67
+ */
68
+ const isRequestFromTrustedProxy = (c) => {
69
+ const remote = resolveRequestRemoteAddress(c);
70
+ if (!remote) return false;
71
+ if (isLoopbackIpAddress(remote)) return true;
72
+ return isTrustedProxyAddress(remote, service.currentConfig.gateway?.trustedProxies);
73
+ };
45
74
  app.use(logContextMiddleware());
46
75
  app.use(logger({
47
76
  trustedProxies: service.currentConfig.gateway?.trustedProxies,
48
77
  allowRealIpFallback: service.currentConfig.gateway?.allowRealIpFallback === true
49
78
  }));
79
+ registerSiteShareMiddleware(app, service);
50
80
  app.use(cors({
51
81
  origin: (origin) => {
52
82
  const allowed = resolveBrowserOrigins();
@@ -93,6 +123,7 @@ function createHonoApp(config) {
93
123
  origin,
94
124
  allowedOrigins: resolveBrowserOrigins(),
95
125
  allowHostHeaderOriginFallback,
126
+ autoAllowSameHostFromTrustedProxy: isRequestFromTrustedProxy(c),
96
127
  isLocalClient: false
97
128
  });
98
129
  if (!result.ok) {
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","names":[],"sources":["../../../../src/gateway/hono/app.ts"],"sourcesContent":["import { Hono } from 'hono';\nimport { cors } from 'hono/cors';\nimport { createMiddleware } from 'hono/factory';\nimport { bodyLimit } from 'hono/body-limit';\n\nimport { resolveGatewayEffectiveHost } from '../../config/gateway-bind.js';\nimport { createLogger } from '../../utils/logger.js';\nimport type { GatewayService } from '../service.js';\nimport { resolveAllowedBrowserOrigins, resolveGatewayServiceListenPort } from '../host.js';\nimport { loadTunnelState } from '../../tunnel/tunnel-state.js';\nimport { maxWebchatAgentRequestBodyBytes } from '../chat-limits.js';\nimport { buildGatewayConsoleCspHeader } from '../security/csp.js';\nimport { checkBrowserOrigin } from '../security/origin-check.js';\nimport { auth } from './middleware/auth.js';\nimport { operatorScopes } from './middleware/scopes.js';\nimport { createStrictRateLimitMiddleware } from './middleware/strict-rate-limit.js';\nimport { logContextMiddleware } from './middleware/log-context.js';\nimport { logger } from './middleware/logger.js';\nimport { registerPublicExtensionAssetRoutes } from './routes/auth-registry-extensions.js';\nimport { registerAuthenticatedRoutes } from './routes/index.js';\nimport { registerPublicGatewayRoutes } from './routes/public-gateway.js';\nimport { resetLazyRouteBundlesForTests } from './routes/lazy-fallback.js';\nimport { prewarmStaticUiCache } from './lib/static-ui.js';\nconst log = createLogger('HonoApp');\n\nexport interface HonoAppConfig {\n service: GatewayService;\n token?: string;\n}\n\n/**\n * Extension sandbox HTML under `/api/extensions/:id/assets/*` ships its own CSP\n * (`frame-ancestors 'self'`). The global gateway middleware must not overwrite it\n * with `frame-ancestors 'none'` / `X-Frame-Options: DENY`, or the console cannot embed iframes.\n */\nexport function isExtensionGatewayUiAssetPath(path: string): boolean {\n return /^\\/api\\/extensions\\/[^/]+\\/assets\\//.test(path);\n}\n\nexport function createHonoApp(config: HonoAppConfig): Hono {\n if (process.env.VITEST) {\n resetLazyRouteBundlesForTests();\n }\n const { service, token } = config;\n const app = new Hono();\n\n const gatewayPort = resolveGatewayServiceListenPort(service);\n\n const resolveBrowserOrigins = (): string[] =>\n resolveAllowedBrowserOrigins({\n configuredOrigins: service.currentConfig.gateway.corsOrigins,\n port: gatewayPort,\n bindHost: resolveGatewayEffectiveHost(service.currentConfig),\n tunnelPublicUrl: loadTunnelState()?.publicUrl,\n });\n\n app.use(logContextMiddleware());\n app.use(logger({\n trustedProxies: service.currentConfig.gateway?.trustedProxies,\n allowRealIpFallback: service.currentConfig.gateway?.allowRealIpFallback === true,\n }));\n app.use(\n cors({\n origin: (origin) => {\n const allowed = resolveBrowserOrigins();\n if (!origin) {\n return allowed[0] ?? `http://127.0.0.1:${gatewayPort}`;\n }\n const normalized = origin.toLowerCase();\n const hit = allowed.find((entry) => entry.toLowerCase() === normalized);\n if (hit) return origin;\n return allowed.includes('*') ? '*' : '';\n },\n allowMethods: ['GET', 'POST', 'PATCH', 'DELETE', 'OPTIONS'],\n allowHeaders: ['Content-Type', 'Authorization', 'Accept', 'X-Session-Id', 'Last-Event-ID'],\n credentials: true,\n maxAge: 86400,\n }),\n );\n\n // Build CSP header once at startup (no inline script hashes needed for SPA)\n const gatewayConsoleCsp = buildGatewayConsoleCspHeader();\n\n // Security headers middleware\n app.use(createMiddleware(async (c, next) => {\n await next();\n if (isExtensionGatewayUiAssetPath(c.req.path)) {\n return;\n }\n c.header('X-Frame-Options', 'DENY');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Referrer-Policy', 'strict-origin-when-cross-origin');\n c.header('X-XSS-Protection', '1; mode=block');\n // microphone=(self): allow same-origin chat voice (composer). microphone=() breaks packaged Electron loading the gateway SPA.\n c.header('Permissions-Policy', 'camera=(), microphone=(self), geolocation=()');\n c.header('Content-Security-Policy', gatewayConsoleCsp);\n }));\n\n // Browser Origin check middleware for API routes (CSRF protection).\n // Non-browser requests (no Origin header) pass through — they are\n // authenticated by the token middleware instead.\n const allowHostHeaderOriginFallback =\n service.currentConfig.gateway?.dangerouslyAllowHostHeaderOriginFallback === true;\n app.use('/api/*', createMiddleware(async (c, next) => {\n // Sandboxed extension iframes (no allow-same-origin) send `Origin: null`.\n // `checkBrowserOrigin` rejects that; these routes rely on CSP instead\n // (`registerPublicExtensionAssetRoutes`).\n if (isExtensionGatewayUiAssetPath(c.req.path)) {\n return next();\n }\n\n const origin = c.req.header('origin');\n if (!origin || origin.trim().toLowerCase() === 'null') {\n // Native apps / opaque origins — authenticated via Bearer token\n return next();\n }\n\n const result = checkBrowserOrigin({\n requestHost: c.req.header('host'),\n origin,\n allowedOrigins: resolveBrowserOrigins(),\n allowHostHeaderOriginFallback,\n isLocalClient: false,\n });\n\n if (!result.ok) {\n log.warn(\n {\n origin,\n requestHost: c.req.header('host'),\n reason: 'reason' in result ? result.reason : 'unknown',\n path: c.req.path,\n method: c.req.method,\n },\n `Browser origin check failed: ${origin} not in allowed list`,\n );\n return c.json({ error: 'Forbidden', message: 'Origin not allowed' }, 403);\n }\n\n return next();\n }));\n\n app.use('/api/skills/upload', bodyLimit({\n maxSize: 10 * 1024 * 1024,\n onError: (c) => {\n log.warn({ path: c.req.path, maxSizeMb: 10 }, 'Request body too large: skills upload exceeds 10MB limit');\n return c.json({ error: 'Skill package too large', maxSize: '10MB' }, 413);\n },\n }));\n\n const DEFAULT_API_BODY_MAX = 1 * 1024 * 1024;\n const WEBCHAT_AGENT_BODY_MAX = maxWebchatAgentRequestBodyBytes();\n\n app.use('/api/*', async (c, next) => {\n const maxSize = c.req.path === '/api/agent' ? WEBCHAT_AGENT_BODY_MAX : DEFAULT_API_BODY_MAX;\n const maxSizeMb = Math.ceil(maxSize / (1024 * 1024));\n return bodyLimit({\n maxSize,\n onError: (ctx) => {\n log.warn({ path: ctx.req.path, maxSizeMb }, `Request body too large: exceeds ${maxSizeMb}MB limit`);\n return ctx.json({ error: 'Request body too large', maxSize: `${maxSizeMb}MB` }, 413);\n },\n })(c, next);\n });\n\n registerPublicGatewayRoutes(app, service);\n\n // Extension UI assets are served without auth: sandboxed iframes (no allow-same-origin)\n // have an opaque origin of `null` and cannot forward the ?token= from the parent HTML URL.\n // Security is enforced by the strict CSP (frame-ancestors 'self') on every response.\n registerPublicExtensionAssetRoutes(app, service);\n\n const authenticated = new Hono();\n authenticated.use(\n auth({\n token,\n getGatewayAuth: () => service.currentConfig.gateway?.auth,\n getResolvedAuth: () => {\n if (typeof service.getResolvedAuth === 'function') {\n return service.getResolvedAuth();\n }\n return token ? { mode: 'token', token } : { mode: 'none' };\n },\n getTrustedProxyContext: () => ({\n trustedProxies: service.currentConfig.gateway?.trustedProxies,\n allowRealIpFallback: service.currentConfig.gateway?.allowRealIpFallback === true,\n }),\n }),\n );\n authenticated.use(operatorScopes());\n\n const strictRateLimitMiddleware = createStrictRateLimitMiddleware({\n getTrustedProxyContext: () => ({\n trustedProxies: service.currentConfig.gateway?.trustedProxies,\n allowRealIpFallback: service.currentConfig.gateway?.allowRealIpFallback === true,\n }),\n });\n\n const sseConfig = {\n service,\n maxSseConnections: service.currentConfig.gateway.maxSseConnections,\n };\n\n registerAuthenticatedRoutes(app, authenticated, {\n service,\n strictRateLimitMiddleware,\n sseConfig,\n });\n\n const prewarm = prewarmStaticUiCache();\n if (prewarm.loaded > 0) {\n log.debug({ loaded: prewarm.loaded, missing: prewarm.missing }, 'Static UI cache prewarmed');\n }\n\n app.route('/', authenticated);\n\n app.notFound((c) => {\n const isApiRoute = c.req.path.startsWith('/api/');\n const fields = { path: c.req.path, method: c.req.method };\n if (isApiRoute) {\n log.warn(fields, 'Route not found');\n } else {\n log.debug(fields, 'Route not found');\n }\n return c.json({ error: 'Not found' }, 404);\n });\n\n app.onError((err, c) => {\n log.error(\n {\n err,\n path: c.req.path,\n method: c.req.method,\n userAgent: c.req.header('user-agent'),\n },\n `Hono error on ${c.req.method} ${c.req.path}: ${err instanceof Error ? err.message : String(err)}`,\n );\n return c.json({ error: 'Internal server error' }, 500);\n });\n\n return app;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"app.js","names":[],"sources":["../../../../src/gateway/hono/app.ts"],"sourcesContent":["import { Hono } from 'hono';\nimport type { Context } from 'hono';\nimport { cors } from 'hono/cors';\nimport { createMiddleware } from 'hono/factory';\nimport { bodyLimit } from 'hono/body-limit';\nimport { getConnInfo } from '@hono/node-server/conninfo';\n\nimport { resolveGatewayEffectiveHost } from '../../config/gateway-bind.js';\nimport { createLogger } from '../../utils/logger.js';\nimport type { GatewayService } from '../service.js';\nimport { resolveAllowedBrowserOrigins, resolveGatewayServiceListenPort } from '../host.js';\nimport { loadTunnelState } from '../../tunnel/tunnel-state.js';\nimport { maxWebchatAgentRequestBodyBytes } from '../chat-limits.js';\nimport { buildGatewayConsoleCspHeader } from '../security/csp.js';\nimport { checkBrowserOrigin } from '../security/origin-check.js';\nimport { isLoopbackIpAddress, isTrustedProxyAddress } from '../client-ip.js';\nimport { resolveReverseProxyPublicUrl } from '../public-url.js';\nimport { auth } from './middleware/auth.js';\nimport { operatorScopes } from './middleware/scopes.js';\nimport { createStrictRateLimitMiddleware } from './middleware/strict-rate-limit.js';\nimport { logContextMiddleware } from './middleware/log-context.js';\nimport { logger } from './middleware/logger.js';\nimport { registerPublicExtensionAssetRoutes } from './routes/auth-registry-extensions.js';\nimport { registerAuthenticatedRoutes } from './routes/index.js';\nimport { registerPublicGatewayRoutes } from './routes/public-gateway.js';\nimport { resetLazyRouteBundlesForTests } from './routes/lazy-fallback.js';\nimport { prewarmStaticUiCache } from './lib/static-ui.js';\nimport { registerSiteShareMiddleware } from '../../share/site-share-router.js';\nconst log = createLogger('HonoApp');\n\nexport interface HonoAppConfig {\n service: GatewayService;\n token?: string;\n}\n\n/**\n * Extension sandbox HTML under `/api/extensions/:id/assets/*` ships its own CSP\n * (`frame-ancestors 'self'`). The global gateway middleware must not overwrite it\n * with `frame-ancestors 'none'` / `X-Frame-Options: DENY`, or the console cannot embed iframes.\n */\nexport function isExtensionGatewayUiAssetPath(path: string): boolean {\n return /^\\/api\\/extensions\\/[^/]+\\/assets\\//.test(path);\n}\n\nexport function createHonoApp(config: HonoAppConfig): Hono {\n if (process.env.VITEST) {\n resetLazyRouteBundlesForTests();\n }\n const { service, token } = config;\n const app = new Hono();\n\n const gatewayPort = resolveGatewayServiceListenPort(service);\n\n const resolveBrowserOrigins = (): string[] =>\n resolveAllowedBrowserOrigins({\n configuredOrigins: service.currentConfig.gateway.corsOrigins,\n port: gatewayPort,\n bindHost: resolveGatewayEffectiveHost(service.currentConfig),\n tunnelPublicUrl: loadTunnelState()?.publicUrl,\n reverseProxyPublicUrl: resolveReverseProxyPublicUrl(service.currentConfig),\n });\n\n /**\n * TCP source for the in-flight request, normalized for trusted-proxy checks.\n * Returns undefined when the runtime doesn't expose conninfo (tests, mocks).\n */\n const resolveRequestRemoteAddress = (c: Context): string | undefined => {\n try {\n return getConnInfo(c).remote.address;\n } catch {\n return undefined;\n }\n };\n\n /**\n * A request's TCP source qualifies as a \"trusted proxy hop\" when it's\n * loopback (the user's own machine, where any reverse proxy lives) or\n * listed in `gateway.trustedProxies`. We use this signal to safely\n * auto-allow same-host Origins through CSRF without requiring a manual\n * `corsOrigins` entry for every reverse-proxy hostname.\n */\n const isRequestFromTrustedProxy = (c: Context): boolean => {\n const remote = resolveRequestRemoteAddress(c);\n if (!remote) return false;\n if (isLoopbackIpAddress(remote)) return true;\n return isTrustedProxyAddress(remote, service.currentConfig.gateway?.trustedProxies);\n };\n\n app.use(logContextMiddleware());\n app.use(logger({\n trustedProxies: service.currentConfig.gateway?.trustedProxies,\n allowRealIpFallback: service.currentConfig.gateway?.allowRealIpFallback === true,\n }));\n\n // Site-share middleware runs BEFORE CORS/CSP — it owns the request when the\n // Host header matches `*.<publicHostSuffix>` (default `*.share.xopc.ai`) or\n // the path starts with `/site/:token/`. Otherwise it falls through.\n registerSiteShareMiddleware(app, service);\n app.use(\n cors({\n origin: (origin) => {\n const allowed = resolveBrowserOrigins();\n if (!origin) {\n return allowed[0] ?? `http://127.0.0.1:${gatewayPort}`;\n }\n const normalized = origin.toLowerCase();\n const hit = allowed.find((entry) => entry.toLowerCase() === normalized);\n if (hit) return origin;\n return allowed.includes('*') ? '*' : '';\n },\n allowMethods: ['GET', 'POST', 'PATCH', 'DELETE', 'OPTIONS'],\n allowHeaders: ['Content-Type', 'Authorization', 'Accept', 'X-Session-Id', 'Last-Event-ID'],\n credentials: true,\n maxAge: 86400,\n }),\n );\n\n // Build CSP header once at startup (no inline script hashes needed for SPA)\n const gatewayConsoleCsp = buildGatewayConsoleCspHeader();\n\n // Security headers middleware\n app.use(createMiddleware(async (c, next) => {\n await next();\n if (isExtensionGatewayUiAssetPath(c.req.path)) {\n return;\n }\n c.header('X-Frame-Options', 'DENY');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Referrer-Policy', 'strict-origin-when-cross-origin');\n c.header('X-XSS-Protection', '1; mode=block');\n // microphone=(self): allow same-origin chat voice (composer). microphone=() breaks packaged Electron loading the gateway SPA.\n c.header('Permissions-Policy', 'camera=(), microphone=(self), geolocation=()');\n c.header('Content-Security-Policy', gatewayConsoleCsp);\n }));\n\n // Browser Origin check middleware for API routes (CSRF protection).\n // Non-browser requests (no Origin header) pass through — they are\n // authenticated by the token middleware instead.\n const allowHostHeaderOriginFallback =\n service.currentConfig.gateway?.dangerouslyAllowHostHeaderOriginFallback === true;\n app.use('/api/*', createMiddleware(async (c, next) => {\n // Sandboxed extension iframes (no allow-same-origin) send `Origin: null`.\n // `checkBrowserOrigin` rejects that; these routes rely on CSP instead\n // (`registerPublicExtensionAssetRoutes`).\n if (isExtensionGatewayUiAssetPath(c.req.path)) {\n return next();\n }\n\n const origin = c.req.header('origin');\n if (!origin || origin.trim().toLowerCase() === 'null') {\n // Native apps / opaque origins — authenticated via Bearer token\n return next();\n }\n\n const result = checkBrowserOrigin({\n requestHost: c.req.header('host'),\n origin,\n allowedOrigins: resolveBrowserOrigins(),\n allowHostHeaderOriginFallback,\n autoAllowSameHostFromTrustedProxy: isRequestFromTrustedProxy(c),\n isLocalClient: false,\n });\n\n if (!result.ok) {\n log.warn(\n {\n origin,\n requestHost: c.req.header('host'),\n reason: 'reason' in result ? result.reason : 'unknown',\n path: c.req.path,\n method: c.req.method,\n },\n `Browser origin check failed: ${origin} not in allowed list`,\n );\n return c.json({ error: 'Forbidden', message: 'Origin not allowed' }, 403);\n }\n\n return next();\n }));\n\n app.use('/api/skills/upload', bodyLimit({\n maxSize: 10 * 1024 * 1024,\n onError: (c) => {\n log.warn({ path: c.req.path, maxSizeMb: 10 }, 'Request body too large: skills upload exceeds 10MB limit');\n return c.json({ error: 'Skill package too large', maxSize: '10MB' }, 413);\n },\n }));\n\n const DEFAULT_API_BODY_MAX = 1 * 1024 * 1024;\n const WEBCHAT_AGENT_BODY_MAX = maxWebchatAgentRequestBodyBytes();\n\n app.use('/api/*', async (c, next) => {\n const maxSize = c.req.path === '/api/agent' ? WEBCHAT_AGENT_BODY_MAX : DEFAULT_API_BODY_MAX;\n const maxSizeMb = Math.ceil(maxSize / (1024 * 1024));\n return bodyLimit({\n maxSize,\n onError: (ctx) => {\n log.warn({ path: ctx.req.path, maxSizeMb }, `Request body too large: exceeds ${maxSizeMb}MB limit`);\n return ctx.json({ error: 'Request body too large', maxSize: `${maxSizeMb}MB` }, 413);\n },\n })(c, next);\n });\n\n registerPublicGatewayRoutes(app, service);\n\n // Extension UI assets are served without auth: sandboxed iframes (no allow-same-origin)\n // have an opaque origin of `null` and cannot forward the ?token= from the parent HTML URL.\n // Security is enforced by the strict CSP (frame-ancestors 'self') on every response.\n registerPublicExtensionAssetRoutes(app, service);\n\n const authenticated = new Hono();\n authenticated.use(\n auth({\n token,\n getGatewayAuth: () => service.currentConfig.gateway?.auth,\n getResolvedAuth: () => {\n if (typeof service.getResolvedAuth === 'function') {\n return service.getResolvedAuth();\n }\n return token ? { mode: 'token', token } : { mode: 'none' };\n },\n getTrustedProxyContext: () => ({\n trustedProxies: service.currentConfig.gateway?.trustedProxies,\n allowRealIpFallback: service.currentConfig.gateway?.allowRealIpFallback === true,\n }),\n }),\n );\n authenticated.use(operatorScopes());\n\n const strictRateLimitMiddleware = createStrictRateLimitMiddleware({\n getTrustedProxyContext: () => ({\n trustedProxies: service.currentConfig.gateway?.trustedProxies,\n allowRealIpFallback: service.currentConfig.gateway?.allowRealIpFallback === true,\n }),\n });\n\n const sseConfig = {\n service,\n maxSseConnections: service.currentConfig.gateway.maxSseConnections,\n };\n\n registerAuthenticatedRoutes(app, authenticated, {\n service,\n strictRateLimitMiddleware,\n sseConfig,\n });\n\n const prewarm = prewarmStaticUiCache();\n if (prewarm.loaded > 0) {\n log.debug({ loaded: prewarm.loaded, missing: prewarm.missing }, 'Static UI cache prewarmed');\n }\n\n app.route('/', authenticated);\n\n app.notFound((c) => {\n const isApiRoute = c.req.path.startsWith('/api/');\n const fields = { path: c.req.path, method: c.req.method };\n if (isApiRoute) {\n log.warn(fields, 'Route not found');\n } else {\n log.debug(fields, 'Route not found');\n }\n return c.json({ error: 'Not found' }, 404);\n });\n\n app.onError((err, c) => {\n log.error(\n {\n err,\n path: c.req.path,\n method: c.req.method,\n userAgent: c.req.header('user-agent'),\n },\n `Hono error on ${c.req.method} ${c.req.path}: ${err instanceof Error ? err.message : String(err)}`,\n );\n return c.json({ error: 'Internal server error' }, 500);\n });\n\n return app;\n}\n"],"mappings":"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"}
@@ -1,12 +1,12 @@
1
1
  import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveDefaultAgentId } from "../../../agent/agent-scope.js";
2
2
  import { getAllProviders, init_providers, isProviderConfigured } from "../../../providers/index.js";
3
+ import { resolveShareConfig } from "../../../share/share-config.js";
3
4
  import { normalizeConfiguredMcpServers } from "../../../config/mcp-config-normalize.js";
4
5
  import { bundledChannelPlugins } from "../../../generated/bundled-channel-plugins.js";
5
6
  import { listChannelPlugins, syncChannelPluginsFromManager } from "../../../channels/plugins/registry.js";
6
7
  import { resolveCronConfigForWeb, resolveGoalsConfigForWeb, resolveSessionConfigForWeb, resolveUpdateConfigForWeb } from "../../../config/web-patch.js";
7
8
  import { safeToolsWebForGet } from "../../config-tools-web.js";
8
9
  import { maskTunnelSecretForWeb } from "../../../tunnel/env.js";
9
- import { resolveShareConfig } from "../../../share/share-config.js";
10
10
  import { agentImageGenerationModelAutoProviderFallback, agentImageGenerationModelTimeoutMs, agentModelFallbacksToArray, agentModelRefToString } from "./agent-model.js";
11
11
  import { buildSafeProvidersConfigForWeb } from "./safe-providers-config.js";
12
12
  import { maskSttConfigForWeb, maskTtsConfigForWeb } from "./safe-voice-config.js";
@@ -1,7 +1,7 @@
1
1
  import { init_write_file_atomic, writeTextAtomic } from "../../../infra/write-file-atomic.js";
2
- import { readFile } from "node:fs/promises";
3
- import { join } from "node:path";
4
2
  import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { readFile } from "node:fs/promises";
5
5
  //#region src/gateway/hono/lib/extension-store.ts
6
6
  init_write_file_atomic();
7
7
  /** Extension UI: write-through JSON KV per namespace under ~/.xopc/extensions/{namespace}/storage.json */
@@ -1,6 +1,6 @@
1
- import { createHash } from "node:crypto";
2
- import { readFileSync } from "node:fs";
3
1
  import { dirname, resolve } from "node:path";
2
+ import { readFileSync } from "node:fs";
3
+ import { createHash } from "node:crypto";
4
4
  import { fileURLToPath } from "node:url";
5
5
  //#region src/gateway/hono/lib/static-ui.ts
6
6
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -1,6 +1,6 @@
1
1
  import { CredentialResolver, init_credentials } from "../../auth/credentials.js";
2
- import { anthropicOAuthProvider } from "../../auth/oauth/anthropic.js";
3
2
  import { init_providers, isProviderConfigured } from "../../providers/index.js";
3
+ import { anthropicOAuthProvider } from "../../auth/oauth/anthropic.js";
4
4
  import { minimaxOAuthProvider } from "../../auth/oauth/minimax.js";
5
5
  import { minimaxCnOAuthProvider } from "../../auth/oauth/minimax-cn.js";
6
6
  import { kimiCodingOAuthProvider } from "../../auth/oauth/kimi-coding.js";
@@ -1,5 +1,5 @@
1
- import { init_agent_scope, normalizeAgentId } from "../../../agent/agent-scope.js";
2
1
  import { init_schema, parseModelRef } from "../../../config/schema.js";
2
+ import { init_agent_scope, normalizeAgentId } from "../../../agent/agent-scope.js";
3
3
  import { init_providers, isProviderConfigured, resolveModel } from "../../../providers/index.js";
4
4
  import { getVoiceModelsConfig } from "../../../config/voice.js";
5
5
  import { deleteAgentAvatarFile, finalizeCreateAgentDirs, listAgentProfileFiles, listGatewayAgents, prepareCreateAgent, prepareCreateAgentsBatch, prepareDeleteAgent, prepareUpdateAgent, readAgentAvatarFile, readAgentProfileFile, runAfterDeletePurge, writeAgentAvatarFromBase64, writeAgentProfileFile } from "../../agents-admin.js";
@@ -7,8 +7,8 @@ import { createOAuthHandler } from "../oauth.js";
7
7
  import { createOAuthAsyncHandler } from "../oauth-async.js";
8
8
  import { extensionAssetMimeType } from "../lib/extension-assets.js";
9
9
  import { loadExtensionStore, saveExtensionStore } from "../lib/extension-store.js";
10
- import { existsSync, readFileSync, statSync } from "node:fs";
11
10
  import { relative, resolve } from "node:path";
11
+ import { existsSync, readFileSync, statSync } from "node:fs";
12
12
  //#region src/gateway/hono/routes/auth-registry-extensions.ts
13
13
  init_providers();
14
14
  const EXTENSION_ASSET_CSP = "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'none'; frame-ancestors 'self'; frame-src 'none'; base-uri 'none'; object-src 'none'; form-action 'none'";
@@ -1,5 +1,5 @@
1
- import { CredentialResolver, init_credentials } from "../../../../auth/credentials.js";
2
1
  import { BindingsConfigSchema, McpConfigSchema, init_schema } from "../../../../config/schema.js";
2
+ import { CredentialResolver, init_credentials } from "../../../../auth/credentials.js";
3
3
  import { canonicalizeConfiguredMcpServer } from "../../../../config/mcp-config-normalize.js";
4
4
  import { mergeCronConfigPatch, mergeGatewaySkillsMarketplacePatch, mergeGoalsConfigPatch, mergeSessionConfigPatch, mergeUpdateConfigPatch } from "../../../../config/web-patch.js";
5
5
  import { assertGatewayAuthConfigured, resolveGatewayAuth } from "../../../auth.js";
@@ -5,8 +5,8 @@ import { getWorkspacePath } from "../../../config/workspace-path-helpers.js";
5
5
  import { parseDreamingLastRunFile } from "../../../agent/memory/dreaming/last-run.js";
6
6
  import { readDreamingEvents } from "../../../agent/memory/dreaming/events.js";
7
7
  import { previewDreamingDeepPromotion } from "../../../agent/memory/dreaming/preview.js";
8
- import fs from "node:fs/promises";
9
8
  import path from "node:path";
9
+ import fs from "node:fs/promises";
10
10
  //#region src/gateway/hono/routes/dreaming.ts
11
11
  function isRecord(v) {
12
12
  return v !== null && typeof v === "object" && !Array.isArray(v);
@@ -1,8 +1,8 @@
1
1
  import { createLogger } from "../../../utils/logger/index.js";
2
2
  import { init_logger } from "../../../utils/logger.js";
3
- import { readdir, realpath, stat } from "node:fs/promises";
4
- import * as path$1 from "node:path";
5
3
  import * as os$1 from "node:os";
4
+ import * as path$1 from "node:path";
5
+ import { readdir, realpath, stat } from "node:fs/promises";
6
6
  //#region src/gateway/hono/routes/host-fs.ts
7
7
  init_logger();
8
8
  const log = createLogger("HostFs");
@@ -142,6 +142,14 @@ const AUTHENTICATED_LAZY_ROUTE_BUNDLES = [
142
142
  return { register: registerShareRoutes };
143
143
  }
144
144
  },
145
+ {
146
+ id: "site-shares",
147
+ match: (path) => startsWithAny(path, ["/api/site-shares"]),
148
+ load: async () => {
149
+ const { registerSiteShareRoutes } = await import("./site-shares.js");
150
+ return { register: registerSiteShareRoutes };
151
+ }
152
+ },
145
153
  {
146
154
  id: "tunnel",
147
155
  match: (path) => startsWithAny(path, ["/api/tunnel"]),