@xopcai/xopc 0.0.83 → 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 (457) hide show
  1. package/README.md +2 -0
  2. package/README.zh-CN.md +3 -1
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  5. package/dist/extensions/feishu/src/plugin.d.ts +2 -0
  6. package/dist/extensions/feishu/src/plugin.js +10 -0
  7. package/dist/extensions/feishu/src/plugin.js.map +1 -1
  8. package/dist/extensions/feishu/src/workflow-progress.d.ts +27 -0
  9. package/dist/extensions/feishu/src/workflow-progress.js +99 -0
  10. package/dist/extensions/feishu/src/workflow-progress.js.map +1 -0
  11. package/dist/extensions/telegram/src/plugin.d.ts +2 -0
  12. package/dist/extensions/telegram/src/plugin.js +11 -1
  13. package/dist/extensions/telegram/src/plugin.js.map +1 -1
  14. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  15. package/dist/extensions/telegram/src/workflow-progress.d.ts +24 -0
  16. package/dist/extensions/telegram/src/workflow-progress.js +73 -0
  17. package/dist/extensions/telegram/src/workflow-progress.js.map +1 -0
  18. package/dist/extensions/telegram/xopc.extension.json +1 -1
  19. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js +158 -0
  20. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js.map +1 -0
  21. package/dist/extensions/weixin/src/api/api.js +2 -2
  22. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  23. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  24. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  25. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  26. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  27. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  28. package/dist/extensions/weixin/src/plugin.d.ts +2 -0
  29. package/dist/extensions/weixin/src/plugin.js +11 -1
  30. package/dist/extensions/weixin/src/plugin.js.map +1 -1
  31. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  32. package/dist/extensions/weixin/src/workflow-progress.d.ts +26 -0
  33. package/dist/extensions/weixin/src/workflow-progress.js +99 -0
  34. package/dist/extensions/weixin/src/workflow-progress.js.map +1 -0
  35. package/dist/gateway/static/root/assets/agents-D3_-kNlZ.js +222 -0
  36. package/dist/gateway/static/root/assets/apps-page-D7v7649T.js +1 -0
  37. package/dist/gateway/static/root/assets/channels-settings-nCaMb0a7.js +1 -0
  38. package/dist/gateway/static/root/assets/channels-status-swr-C1gZBcJV.js +8 -0
  39. package/dist/gateway/static/root/assets/createLucideIcon-DPHK1VkS.js +1 -0
  40. package/dist/gateway/static/root/assets/cron-api-CoYK0hlm.js +1 -0
  41. package/dist/gateway/static/root/assets/cron-page-DeGo-Vjc.js +1 -0
  42. package/dist/gateway/static/root/assets/dist-BTWC-BTN.js +45 -0
  43. package/dist/gateway/static/root/assets/{dist-BpQxde0t.js → dist-DaK4dsss.js} +1 -1
  44. package/dist/gateway/static/root/assets/{extension-debug-page-CY27wj_p.js → extension-debug-page-BZngZWbO.js} +1 -1
  45. package/dist/gateway/static/root/assets/extension-page-D6JSyV27.js +1 -0
  46. package/dist/gateway/static/root/assets/extension-settings-page-8PZcmWI7.js +1 -0
  47. package/dist/gateway/static/root/assets/fetch-B2MYHbWg.js +1 -0
  48. package/dist/gateway/static/root/assets/{field-primitives-fa_hiQcX.js → field-primitives-Zzl22MvN.js} +1 -1
  49. package/dist/gateway/static/root/assets/heartbeat-config-api-BtIcpG0O.js +1 -0
  50. package/dist/gateway/static/root/assets/index-D4vM3-P7.js +4700 -0
  51. package/dist/gateway/static/root/assets/index-ew_2L2We.css +1 -0
  52. package/dist/gateway/static/root/assets/logs-page-_d4UJ-qQ.js +1 -0
  53. package/dist/gateway/static/root/assets/sessions-page-5N4aF2Wk.js +1 -0
  54. package/dist/gateway/static/root/assets/settings-form-section-D_tgb8r2.js +1 -0
  55. package/dist/gateway/static/root/assets/settings-page-C18xBt4X.js +3 -0
  56. package/dist/gateway/static/root/assets/share-preview-page-D4EG_vM1.js +2 -0
  57. package/dist/gateway/static/root/assets/skills-page-sPAXhh8w.js +2 -0
  58. package/dist/gateway/static/root/assets/theme-store-DryYl3qD.js +1 -0
  59. package/dist/gateway/static/root/assets/url-BwNL6Rgk.js +3 -0
  60. package/dist/gateway/static/root/assets/utils-CYO9eTCM.js +1 -0
  61. package/dist/gateway/static/root/assets/voice-api-key-field-Ds51havm.js +1 -0
  62. package/dist/gateway/static/root/index.html +7 -6
  63. package/dist/package.js +1 -1
  64. package/dist/src/agent/agent-manager.js +7 -7
  65. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  66. package/dist/src/agent/context/workspace-seed.js +3 -3
  67. package/dist/src/agent/embedded/map-stream-events.js +6 -0
  68. package/dist/src/agent/embedded/map-stream-events.js.map +1 -1
  69. package/dist/src/agent/embedded/subscribe-session.js +24 -0
  70. package/dist/src/agent/embedded/subscribe-session.js.map +1 -1
  71. package/dist/src/agent/embedded/types.d.ts +19 -0
  72. package/dist/src/agent/goals/goal-locale.js +2 -2
  73. package/dist/src/agent/goals/goal-run-store.js +4 -4
  74. package/dist/src/agent/goals/persistent-goal-service.js +1 -1
  75. package/dist/src/agent/goals/post-turn.js +2 -2
  76. package/dist/src/agent/image/load-image-media.js +2 -2
  77. package/dist/src/agent/ipc/bus.js +1 -1
  78. package/dist/src/agent/ipc/inbox.js +2 -2
  79. package/dist/src/agent/ipc/socket.js +1 -1
  80. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  81. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  82. package/dist/src/agent/memory/dreaming/events.js +1 -1
  83. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  84. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  85. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  86. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  87. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  88. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  89. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  90. package/dist/src/agent/models/manager.js +1 -1
  91. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  92. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  93. package/dist/src/agent/reply/startup-context.d.ts +3 -0
  94. package/dist/src/agent/reply/startup-context.js +25 -2
  95. package/dist/src/agent/reply/startup-context.js.map +1 -1
  96. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  97. package/dist/src/agent/sandbox/path-policy.js +2 -2
  98. package/dist/src/agent/service/build-direct-message-content.js +1 -1
  99. package/dist/src/agent/service.d.ts +1 -0
  100. package/dist/src/agent/service.js +10 -4
  101. package/dist/src/agent/service.js.map +1 -1
  102. package/dist/src/agent/session/session-inspector.js +1 -1
  103. package/dist/src/agent/skills/config.js +1 -1
  104. package/dist/src/agent/skills/hub-hash.js +2 -2
  105. package/dist/src/agent/skills/hub-lock.js +1 -1
  106. package/dist/src/agent/skills/hub-pull.js +3 -3
  107. package/dist/src/agent/skills/index.js +1 -1
  108. package/dist/src/agent/skills/managed-store.js +1 -1
  109. package/dist/src/agent/skills/scanner.js +1 -1
  110. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  111. package/dist/src/agent/skills/skill-manager.js +1 -1
  112. package/dist/src/agent/tools/create-share-tool.d.ts +27 -0
  113. package/dist/src/agent/tools/create-share-tool.js +237 -0
  114. package/dist/src/agent/tools/create-share-tool.js.map +1 -0
  115. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  116. package/dist/src/agent/tools/factory.js +35 -1
  117. package/dist/src/agent/tools/factory.js.map +1 -1
  118. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  119. package/dist/src/agent/tools/index.d.ts +2 -0
  120. package/dist/src/agent/tools/index.js +3 -1
  121. package/dist/src/agent/tools/send-media.js +1 -1
  122. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  123. package/dist/src/agent/tools/workflow-tool.d.ts +41 -0
  124. package/dist/src/agent/tools/workflow-tool.js +271 -0
  125. package/dist/src/agent/tools/workflow-tool.js.map +1 -0
  126. package/dist/src/agent/tools/write.js +1 -1
  127. package/dist/src/agent/workflow/builtins/audit-repo.d.ts +9 -0
  128. package/dist/src/agent/workflow/builtins/audit-repo.js +115 -0
  129. package/dist/src/agent/workflow/builtins/audit-repo.js.map +1 -0
  130. package/dist/src/agent/workflow/builtins/index.d.ts +15 -0
  131. package/dist/src/agent/workflow/builtins/index.js +28 -0
  132. package/dist/src/agent/workflow/builtins/index.js.map +1 -0
  133. package/dist/src/agent/workflow/builtins/multi-perspective-review.d.ts +9 -0
  134. package/dist/src/agent/workflow/builtins/multi-perspective-review.js +113 -0
  135. package/dist/src/agent/workflow/builtins/multi-perspective-review.js.map +1 -0
  136. package/dist/src/agent/workflow/builtins/research.d.ts +9 -0
  137. package/dist/src/agent/workflow/builtins/research.js +129 -0
  138. package/dist/src/agent/workflow/builtins/research.js.map +1 -0
  139. package/dist/src/agent/workflow/catalog.d.ts +51 -0
  140. package/dist/src/agent/workflow/catalog.js +155 -0
  141. package/dist/src/agent/workflow/catalog.js.map +1 -0
  142. package/dist/src/agent/workflow/channel-capability.d.ts +76 -0
  143. package/dist/src/agent/workflow/channel-capability.js +1 -0
  144. package/dist/src/agent/workflow/index.d.ts +11 -0
  145. package/dist/src/agent/workflow/index.js +10 -0
  146. package/dist/src/agent/workflow/last-run-memory.d.ts +42 -0
  147. package/dist/src/agent/workflow/last-run-memory.js +60 -0
  148. package/dist/src/agent/workflow/last-run-memory.js.map +1 -0
  149. package/dist/src/agent/workflow/parser.d.ts +20 -0
  150. package/dist/src/agent/workflow/parser.js +137 -0
  151. package/dist/src/agent/workflow/parser.js.map +1 -0
  152. package/dist/src/agent/workflow/progress-broker.d.ts +80 -0
  153. package/dist/src/agent/workflow/progress-broker.js +263 -0
  154. package/dist/src/agent/workflow/progress-broker.js.map +1 -0
  155. package/dist/src/agent/workflow/runtime.d.ts +31 -0
  156. package/dist/src/agent/workflow/runtime.js +301 -0
  157. package/dist/src/agent/workflow/runtime.js.map +1 -0
  158. package/dist/src/agent/workflow/snapshot.d.ts +18 -0
  159. package/dist/src/agent/workflow/snapshot.js +144 -0
  160. package/dist/src/agent/workflow/snapshot.js.map +1 -0
  161. package/dist/src/agent/workflow/structured-output-tool.d.ts +33 -0
  162. package/dist/src/agent/workflow/structured-output-tool.js +58 -0
  163. package/dist/src/agent/workflow/structured-output-tool.js.map +1 -0
  164. package/dist/src/agent/workflow/subagent-runner.d.ts +42 -0
  165. package/dist/src/agent/workflow/subagent-runner.js +104 -0
  166. package/dist/src/agent/workflow/subagent-runner.js.map +1 -0
  167. package/dist/src/agent/workflow/types.d.ts +137 -0
  168. package/dist/src/agent/workflow/types.js +1 -0
  169. package/dist/src/auth/credentials.js +3 -3
  170. package/dist/src/auth/profiles/store.js +1 -1
  171. package/dist/src/auth/sync-provider-auth.js +1 -1
  172. package/dist/src/browser/cache-dir-policy.js +1 -1
  173. package/dist/src/browser/cdp-local-launcher.js +2 -2
  174. package/dist/src/browser/providers/browser-ext-install.js +4 -4
  175. package/dist/src/browser/providers/cloakbrowser.js +4 -4
  176. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  177. package/dist/src/browser/stealth.js +1 -1
  178. package/dist/src/channels/attachments/inbound-persist.js +1 -1
  179. package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
  180. package/dist/src/channels/outbound/persist-store.js +1 -1
  181. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  182. package/dist/src/channels/pairing/pairing-store.js +2 -2
  183. package/dist/src/chat-commands/builtins/config.js +2 -2
  184. package/dist/src/chat-commands/builtins/model.js +40 -23
  185. package/dist/src/chat-commands/builtins/model.js.map +1 -1
  186. package/dist/src/chat-commands/builtins/system.js +30 -15
  187. package/dist/src/chat-commands/builtins/system.js.map +1 -1
  188. package/dist/src/chat-commands/builtins/workflow.d.ts +18 -0
  189. package/dist/src/chat-commands/builtins/workflow.js +167 -0
  190. package/dist/src/chat-commands/builtins/workflow.js.map +1 -0
  191. package/dist/src/chat-commands/context.js +1 -1
  192. package/dist/src/chat-commands/format-output.d.ts +28 -0
  193. package/dist/src/chat-commands/format-output.js +45 -0
  194. package/dist/src/chat-commands/format-output.js.map +1 -0
  195. package/dist/src/chat-commands/index.d.ts +1 -0
  196. package/dist/src/chat-commands/index.js +3 -1
  197. package/dist/src/chat-commands/index.js.map +1 -1
  198. package/dist/src/cli/command-catalog.js +110 -8
  199. package/dist/src/cli/command-catalog.js.map +1 -1
  200. package/dist/src/cli/command-loaders.js +2 -0
  201. package/dist/src/cli/command-loaders.js.map +1 -1
  202. package/dist/src/cli/command-manifest.js +9 -1
  203. package/dist/src/cli/command-manifest.js.map +1 -1
  204. package/dist/src/cli/commands/config.js +71 -20
  205. package/dist/src/cli/commands/config.js.map +1 -1
  206. package/dist/src/cli/commands/cron-cli.d.ts +2 -0
  207. package/dist/src/cli/commands/cron-cli.js +15 -0
  208. package/dist/src/cli/commands/cron-cli.js.map +1 -0
  209. package/dist/src/cli/commands/cron.d.ts +4 -1
  210. package/dist/src/cli/commands/cron.js +76 -41
  211. package/dist/src/cli/commands/cron.js.map +1 -1
  212. package/dist/src/cli/commands/doctor/checks/channel-config.js +1 -1
  213. package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -1
  214. package/dist/src/cli/commands/doctor/checks/config-health.js +2 -2
  215. package/dist/src/cli/commands/doctor/checks/config-health.js.map +1 -1
  216. package/dist/src/cli/commands/doctor/checks/cron-health.js +1 -1
  217. package/dist/src/cli/commands/doctor/checks/cron-health.js.map +1 -1
  218. package/dist/src/cli/commands/doctor/checks/gateway-health.js +2 -2
  219. package/dist/src/cli/commands/doctor/checks/gateway-health.js.map +1 -1
  220. package/dist/src/cli/commands/doctor/checks/gateway-service.js +2 -2
  221. package/dist/src/cli/commands/doctor/checks/gateway-service.js.map +1 -1
  222. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  223. package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
  224. package/dist/src/cli/commands/doctor/checks/state-integrity.js +2 -2
  225. package/dist/src/cli/commands/doctor/checks/state-integrity.js.map +1 -1
  226. package/dist/src/cli/commands/doctor/checks/workspace-status.js +4 -4
  227. package/dist/src/cli/commands/doctor/checks/workspace-status.js.map +1 -1
  228. package/dist/src/cli/commands/extension-dev.js +1 -1
  229. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  230. package/dist/src/cli/commands/extension-pack.js +1 -1
  231. package/dist/src/cli/commands/gateway/index.d.ts +1 -1
  232. package/dist/src/cli/commands/gateway/index.js +2 -2
  233. package/dist/src/cli/commands/gateway/lifecycle.js +10 -4
  234. package/dist/src/cli/commands/gateway/lifecycle.js.map +1 -1
  235. package/dist/src/cli/commands/gateway/service.d.ts +4 -0
  236. package/dist/src/cli/commands/gateway/service.js +17 -2
  237. package/dist/src/cli/commands/gateway/service.js.map +1 -1
  238. package/dist/src/cli/commands/gateway/shared.js +1 -1
  239. package/dist/src/cli/commands/gateway/subcommands.js +1 -4
  240. package/dist/src/cli/commands/gateway/subcommands.js.map +1 -1
  241. package/dist/src/cli/commands/image.js +1 -1
  242. package/dist/src/cli/commands/init.js +31 -4
  243. package/dist/src/cli/commands/init.js.map +1 -1
  244. package/dist/src/cli/commands/models.d.ts +4 -1
  245. package/dist/src/cli/commands/models.js +86 -74
  246. package/dist/src/cli/commands/models.js.map +1 -1
  247. package/dist/src/cli/commands/onboard.js +4 -2
  248. package/dist/src/cli/commands/onboard.js.map +1 -1
  249. package/dist/src/cli/commands/profile.d.ts +3 -5
  250. package/dist/src/cli/commands/profile.js +31 -31
  251. package/dist/src/cli/commands/profile.js.map +1 -1
  252. package/dist/src/cli/commands/setup.js +6 -1
  253. package/dist/src/cli/commands/setup.js.map +1 -1
  254. package/dist/src/cli/commands/tunnel.js +2 -2
  255. package/dist/src/cli/gateway-run-argv.js +15 -5
  256. package/dist/src/cli/gateway-run-argv.js.map +1 -1
  257. package/dist/src/cli/utils/gateway-client.js +1 -1
  258. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  259. package/dist/src/config/agent-profile.js +1 -1
  260. package/dist/src/config/gateway-bind.js +1 -1
  261. package/dist/src/config/index.js +5 -5
  262. package/dist/src/config/loader.js +2 -2
  263. package/dist/src/config/models-json.js +2 -2
  264. package/dist/src/config/paths-state.js +1 -1
  265. package/dist/src/config/profile.js +2 -2
  266. package/dist/src/config/public-url.d.ts +28 -0
  267. package/dist/src/config/public-url.js +103 -0
  268. package/dist/src/config/public-url.js.map +1 -0
  269. package/dist/src/config/schema.d.ts +82 -0
  270. package/dist/src/config/schema.js +130 -1
  271. package/dist/src/config/schema.js.map +1 -1
  272. package/dist/src/config/workspace-path.js +1 -1
  273. package/dist/src/cron/executor.js +2 -2
  274. package/dist/src/cron/persistence.js +1 -1
  275. package/dist/src/cron/run-log-store.js +1 -1
  276. package/dist/src/daemon/constants.js +1 -1
  277. package/dist/src/daemon/install-plan.js +3 -3
  278. package/dist/src/daemon/install-plan.js.map +1 -1
  279. package/dist/src/daemon/launchd.js +2 -2
  280. package/dist/src/daemon/schtasks.js +38 -1
  281. package/dist/src/daemon/schtasks.js.map +1 -1
  282. package/dist/src/daemon/systemd.js +2 -2
  283. package/dist/src/extensions/bundle-mcp.js +1 -1
  284. package/dist/src/extensions/discover-extensions.js +1 -1
  285. package/dist/src/extensions/health.js +1 -1
  286. package/dist/src/extensions/loader.js +1 -1
  287. package/dist/src/extensions/lockfile.js +2 -2
  288. package/dist/src/gateway/agents-admin.js +2 -2
  289. package/dist/src/gateway/file-path-classifier.js +2 -2
  290. package/dist/src/gateway/heartbeat/service.js +1 -1
  291. package/dist/src/gateway/hono/app.js +33 -2
  292. package/dist/src/gateway/hono/app.js.map +1 -1
  293. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  294. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  295. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  296. package/dist/src/gateway/hono/oauth.js +1 -1
  297. package/dist/src/gateway/hono/routes/agents.js +1 -1
  298. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  299. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  300. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  301. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  302. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  303. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  304. package/dist/src/gateway/hono/routes/models.js +1 -1
  305. package/dist/src/gateway/hono/routes/shares.js +631 -34
  306. package/dist/src/gateway/hono/routes/shares.js.map +1 -1
  307. package/dist/src/gateway/hono/routes/site-shares.d.ts +3 -0
  308. package/dist/src/gateway/hono/routes/site-shares.js +228 -0
  309. package/dist/src/gateway/hono/routes/site-shares.js.map +1 -0
  310. package/dist/src/gateway/hono/routes/tunnel.js +97 -8
  311. package/dist/src/gateway/hono/routes/tunnel.js.map +1 -1
  312. package/dist/src/gateway/hono/routes/workspace.js +5 -5
  313. package/dist/src/gateway/hono/sse.js +2 -2
  314. package/dist/src/gateway/host.d.ts +3 -1
  315. package/dist/src/gateway/host.js +3 -1
  316. package/dist/src/gateway/host.js.map +1 -1
  317. package/dist/src/gateway/lock.js +3 -3
  318. package/dist/src/gateway/ports.d.ts +6 -0
  319. package/dist/src/gateway/ports.js +38 -2
  320. package/dist/src/gateway/ports.js.map +1 -1
  321. package/dist/src/gateway/public-url.d.ts +8 -0
  322. package/dist/src/gateway/public-url.js +10 -0
  323. package/dist/src/gateway/public-url.js.map +1 -0
  324. package/dist/src/gateway/security/origin-check.d.ts +9 -1
  325. package/dist/src/gateway/security/origin-check.js +4 -0
  326. package/dist/src/gateway/security/origin-check.js.map +1 -1
  327. package/dist/src/gateway/server.js +15 -0
  328. package/dist/src/gateway/server.js.map +1 -1
  329. package/dist/src/gateway/service/agent-runner.js +2 -2
  330. package/dist/src/gateway/service/marketplace-service.js +2 -2
  331. package/dist/src/gateway/service/run-gateway-agent.js +2 -2
  332. package/dist/src/gateway/service.js +3 -2
  333. package/dist/src/gateway/service.js.map +1 -1
  334. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  335. package/dist/src/heartbeat/index.js +1 -1
  336. package/dist/src/i18n/goals-bundle.js +1 -1
  337. package/dist/src/i18n/index.d.ts +1 -0
  338. package/dist/src/i18n/index.js +2 -1
  339. package/dist/src/i18n/locales/share-tool.en.js +15 -0
  340. package/dist/src/i18n/locales/share-tool.en.js.map +1 -0
  341. package/dist/src/i18n/locales/share-tool.zh.js +15 -0
  342. package/dist/src/i18n/locales/share-tool.zh.js.map +1 -0
  343. package/dist/src/i18n/share-tool-bundle.d.ts +20 -0
  344. package/dist/src/i18n/share-tool-bundle.js +56 -0
  345. package/dist/src/i18n/share-tool-bundle.js.map +1 -0
  346. package/dist/src/infra/gateway-processes.js +1 -0
  347. package/dist/src/infra/gateway-processes.js.map +1 -1
  348. package/dist/src/infra/restart.js +2 -2
  349. package/dist/src/infra/update-check.js +1 -1
  350. package/dist/src/infra/update-lock.js +3 -3
  351. package/dist/src/infra/update-runner.js +1 -1
  352. package/dist/src/infra/update-startup.js +2 -2
  353. package/dist/src/infra/write-file-atomic.js +2 -2
  354. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  355. package/dist/src/providers/index.js +2 -2
  356. package/dist/src/providers/model-registry.js +1 -1
  357. package/dist/src/session/config-store.js +2 -2
  358. package/dist/src/session/parity/jsonl-transcript-io.js +2 -2
  359. package/dist/src/session/parity/sessions-json-file.js +1 -1
  360. package/dist/src/session/parity/transcript-file-lock.js +2 -2
  361. package/dist/src/session/parity/transcript-paths.js +1 -1
  362. package/dist/src/session/search-index-cache.js +1 -1
  363. package/dist/src/session/search-index.js +1 -1
  364. package/dist/src/session/session-title.js +3 -2
  365. package/dist/src/session/session-title.js.map +1 -1
  366. package/dist/src/session/store.js +5 -5
  367. package/dist/src/share/share-auto.d.ts +74 -0
  368. package/dist/src/share/share-auto.js +247 -0
  369. package/dist/src/share/share-auto.js.map +1 -0
  370. package/dist/src/share/share-config.js +63 -4
  371. package/dist/src/share/share-config.js.map +1 -1
  372. package/dist/src/share/share-landing.d.ts +28 -2
  373. package/dist/src/share/share-landing.js +155 -34
  374. package/dist/src/share/share-landing.js.map +1 -1
  375. package/dist/src/share/share-store.d.ts +48 -4
  376. package/dist/src/share/share-store.js +322 -51
  377. package/dist/src/share/share-store.js.map +1 -1
  378. package/dist/src/share/share-thumbnail.d.ts +35 -0
  379. package/dist/src/share/share-thumbnail.js +277 -0
  380. package/dist/src/share/share-thumbnail.js.map +1 -0
  381. package/dist/src/share/share-types.d.ts +68 -10
  382. package/dist/src/share/share-types.js +18 -1
  383. package/dist/src/share/share-types.js.map +1 -1
  384. package/dist/src/share/share-url.js +1 -1
  385. package/dist/src/share/share-zip.d.ts +35 -0
  386. package/dist/src/share/share-zip.js +303 -0
  387. package/dist/src/share/share-zip.js.map +1 -0
  388. package/dist/src/share/site-proxy.d.ts +35 -0
  389. package/dist/src/share/site-proxy.js +234 -0
  390. package/dist/src/share/site-proxy.js.map +1 -0
  391. package/dist/src/share/site-share-config.d.ts +11 -0
  392. package/dist/src/share/site-share-config.js +103 -0
  393. package/dist/src/share/site-share-config.js.map +1 -0
  394. package/dist/src/share/site-share-router.d.ts +23 -0
  395. package/dist/src/share/site-share-router.js +147 -0
  396. package/dist/src/share/site-share-router.js.map +1 -0
  397. package/dist/src/share/site-share-store.d.ts +53 -0
  398. package/dist/src/share/site-share-store.js +400 -0
  399. package/dist/src/share/site-share-store.js.map +1 -0
  400. package/dist/src/share/site-share-types.d.ts +103 -0
  401. package/dist/src/share/site-share-types.js +41 -0
  402. package/dist/src/share/site-share-types.js.map +1 -0
  403. package/dist/src/share/site-static-serve.d.ts +10 -0
  404. package/dist/src/share/site-static-serve.js +145 -0
  405. package/dist/src/share/site-static-serve.js.map +1 -0
  406. package/dist/src/tui/clipboard-image.js +3 -3
  407. package/dist/src/tui/theme-manager.js +1 -1
  408. package/dist/src/tui/tui-commands.js +18 -0
  409. package/dist/src/tui/tui-commands.js.map +1 -1
  410. package/dist/src/tui/tui-keybindings-file.js +1 -1
  411. package/dist/src/tui/tui-scoped-models.js +2 -2
  412. package/dist/src/tui/tui-settings.js +1 -1
  413. package/dist/src/tui/tui-workflow-slash.d.ts +32 -0
  414. package/dist/src/tui/tui-workflow-slash.js +63 -0
  415. package/dist/src/tui/tui-workflow-slash.js.map +1 -0
  416. package/dist/src/tui/tui.js +2 -2
  417. package/dist/src/tunnel/enable-lan-pairing.js +1 -1
  418. package/dist/src/tunnel/frpc-binary.js +3 -3
  419. package/dist/src/tunnel/frpc-config.js +1 -1
  420. package/dist/src/tunnel/frpc-extract.js +1 -1
  421. package/dist/src/tunnel/index.js +2 -2
  422. package/dist/src/tunnel/pair-context.d.ts +7 -1
  423. package/dist/src/tunnel/pair-context.js +25 -9
  424. package/dist/src/tunnel/pair-context.js.map +1 -1
  425. package/dist/src/tunnel/pair-url.d.ts +14 -1
  426. package/dist/src/tunnel/pair-url.js +14 -1
  427. package/dist/src/tunnel/pair-url.js.map +1 -1
  428. package/dist/src/tunnel/tunnel-service.js +2 -2
  429. package/dist/src/tunnel/tunnel-state.js +1 -1
  430. package/dist/src/utils/logger/audit.js +1 -1
  431. package/dist/src/utils/logger/log-store.js +1 -1
  432. package/dist/src/utils/logger/rotation.js +1 -1
  433. package/dist/src/voice/tts/audio.js +1 -1
  434. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  435. package/package.json +3 -2
  436. package/dist/gateway/static/root/assets/agents-CrpYTHJS.js +0 -222
  437. package/dist/gateway/static/root/assets/apps-page-1mcKh5Rh.js +0 -1
  438. package/dist/gateway/static/root/assets/button-KafIU8dx.js +0 -1
  439. package/dist/gateway/static/root/assets/channels-settings-zd6QNKPx.js +0 -1
  440. package/dist/gateway/static/root/assets/channels-status-swr-uRAuhiUo.js +0 -8
  441. package/dist/gateway/static/root/assets/cron-api-O2Q_ruV6.js +0 -1
  442. package/dist/gateway/static/root/assets/cron-page-By09AQD-.js +0 -1
  443. package/dist/gateway/static/root/assets/dist-C57OMHW8.js +0 -48
  444. package/dist/gateway/static/root/assets/extension-page-C-Ed5ZmP.js +0 -1
  445. package/dist/gateway/static/root/assets/extension-settings-page-raLux7E7.js +0 -1
  446. package/dist/gateway/static/root/assets/fetch-2iRFmd3n.js +0 -3
  447. package/dist/gateway/static/root/assets/heartbeat-config-api-BVl5VHvL.js +0 -1
  448. package/dist/gateway/static/root/assets/index-BuFldCsB.css +0 -1
  449. package/dist/gateway/static/root/assets/index-Y-iqo-gL.js +0 -4693
  450. package/dist/gateway/static/root/assets/logs-page-BdH2n7ZW.js +0 -1
  451. package/dist/gateway/static/root/assets/sessions-page-Vpchzdp-.js +0 -1
  452. package/dist/gateway/static/root/assets/settings-form-section-Kk1yAGBl.js +0 -1
  453. package/dist/gateway/static/root/assets/settings-page-KBm0u6Dz.js +0 -3
  454. package/dist/gateway/static/root/assets/skills-page-BjeXXaOn.js +0 -2
  455. package/dist/gateway/static/root/assets/theme-store-D01dJt95.js +0 -1
  456. package/dist/gateway/static/root/assets/utils-DpTxN4AF.js +0 -1
  457. package/dist/gateway/static/root/assets/voice-api-key-field-CwO8Cf01.js +0 -1
@@ -1,14 +1,14 @@
1
+ import { resolveStateDir } from "../config/paths-state.js";
1
2
  import { createLogger } from "../utils/logger/index.js";
2
3
  import { init_logger } from "../utils/logger.js";
3
- import { resolveStateDir } from "../config/paths-state.js";
4
4
  import { init_paths } from "../config/paths.js";
5
+ import { SHARE_CONFIG_DEFAULTS } from "./share-types.js";
5
6
  import { isPathUnderWorkspace } from "../gateway/workspace-editor-path.js";
6
7
  import { logShareAudit } from "./share-audit.js";
7
- import { SHARE_CONFIG_DEFAULTS } from "./share-types.js";
8
- import { randomBytes, randomUUID } from "node:crypto";
8
+ import { join, relative, resolve } from "node:path";
9
9
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
10
- import { lstat, realpath, stat } from "node:fs/promises";
11
- import { join } from "node:path";
10
+ import { randomBytes, randomUUID } from "node:crypto";
11
+ import { lstat, readdir, realpath, stat } from "node:fs/promises";
12
12
  //#region src/share/share-store.ts
13
13
  init_paths();
14
14
  init_logger();
@@ -18,17 +18,20 @@ const CLEANUP_INTERVAL_MS = 10 * 6e4;
18
18
  const EXPIRED_RETENTION_MS = 1440 * 6e4;
19
19
  const MAX_STORED_RECORDS = 500;
20
20
  const TRUNCATE_TO = 200;
21
- const VIEW_COUNT_DEBOUNCE_MS = 2e3;
21
+ const COUNTER_DEBOUNCE_MS = 2e3;
22
22
  function resolveSharesPath() {
23
23
  return join(resolveStateDir(), SHARES_FILE);
24
24
  }
25
25
  var ShareStore = class {
26
26
  shares = /* @__PURE__ */ new Map();
27
27
  tokenIndex = /* @__PURE__ */ new Map();
28
- viewCountDirty = false;
29
- viewCountTimer = null;
28
+ dirty = false;
29
+ debounceTimer = null;
30
30
  cleanupTimer = null;
31
31
  config;
32
+ listingCache = /* @__PURE__ */ new Map();
33
+ /** Optional cleanup hook invoked when a share record is dropped (e.g. delete thumbnail). */
34
+ onCleanup = null;
32
35
  constructor(config) {
33
36
  this.config = {
34
37
  ...SHARE_CONFIG_DEFAULTS,
@@ -43,6 +46,10 @@ var ShareStore = class {
43
46
  ...config
44
47
  };
45
48
  }
49
+ /** Register a cleanup hook (idempotent — last wins). */
50
+ setCleanupHook(hook) {
51
+ this.onCleanup = hook;
52
+ }
46
53
  getConfig() {
47
54
  return { ...this.config };
48
55
  }
@@ -57,6 +64,30 @@ var ShareStore = class {
57
64
  }
58
65
  const absolutePath = await this.resolveAndValidatePath(relPath, workspaceRoot);
59
66
  const fileStat = await stat(absolutePath);
67
+ const detectedKind = fileStat.isDirectory() ? "directory" : "file";
68
+ const requestedKind = params.kind ?? detectedKind;
69
+ if (requestedKind !== detectedKind) throw new Error(`Requested share kind '${requestedKind}' does not match filesystem (got '${detectedKind}')`);
70
+ if (requestedKind === "file") return this.createFileShare({
71
+ params,
72
+ absolutePath,
73
+ fileStat,
74
+ relPath,
75
+ workspaceRoot,
76
+ ttlMs,
77
+ gatewayTokenHash
78
+ });
79
+ return this.createDirectoryShare({
80
+ params,
81
+ absolutePath,
82
+ fileStat,
83
+ relPath,
84
+ workspaceRoot,
85
+ ttlMs,
86
+ gatewayTokenHash
87
+ });
88
+ }
89
+ async createFileShare(args) {
90
+ const { params, absolutePath, fileStat, relPath, workspaceRoot, ttlMs, gatewayTokenHash } = args;
60
91
  if (!fileStat.isFile()) throw new Error("Path is not a regular file");
61
92
  if (fileStat.size > this.config.maxFileSize) {
62
93
  const maxMb = (this.config.maxFileSize / 1048576).toFixed(0);
@@ -65,42 +96,108 @@ var ShareStore = class {
65
96
  if ((await lstat(absolutePath)).isSymbolicLink()) {
66
97
  if (!isPathUnderWorkspace(workspaceRoot, await realpath(absolutePath))) throw new Error("Symlink target is outside workspace");
67
98
  }
68
- const id = randomUUID();
69
- const token = randomBytes(32).toString("base64url");
70
- const fileName = relPath.split("/").pop() ?? relPath;
99
+ const fileName = relPath.split("/").pop() || relPath;
71
100
  const mimeType = resolveMimeType(fileName);
72
- const now = /* @__PURE__ */ new Date();
73
- const record = {
74
- id,
75
- token,
101
+ const record = this.buildRecord({
102
+ kind: "file",
76
103
  absolutePath,
77
- workspaceRelativePath: relPath,
78
104
  workspaceRoot,
105
+ workspaceRelativePath: relPath,
79
106
  inode: fileStat.ino,
80
- isDirectory: false,
81
107
  fileName,
82
108
  fileSize: fileStat.size,
83
109
  mimeType,
110
+ ttlMs,
111
+ maxViews: params.maxViews,
112
+ description: params.description,
113
+ gatewayTokenHash
114
+ });
115
+ this.persistAndAudit(record, "share.create", `Share created: ${record.fileName}`, {
116
+ fileName: record.fileName,
117
+ fileSize: record.fileSize,
118
+ ttlMs
119
+ });
120
+ return record;
121
+ }
122
+ async createDirectoryShare(args) {
123
+ const { params, absolutePath, fileStat, relPath, workspaceRoot, ttlMs, gatewayTokenHash } = args;
124
+ const dirCfg = this.config.directory;
125
+ if (!dirCfg.enabled) throw new Error("Directory sharing is disabled");
126
+ const followSymlinks = params.followSymlinks ?? false;
127
+ const maxDepth = params.maxDepth ?? dirCfg.maxDepth;
128
+ const summary = await scanDirectory(absolutePath, {
129
+ workspaceRoot,
130
+ followSymlinks,
131
+ maxDepth,
132
+ maxFileCount: Math.min(params.maxFileCount ?? dirCfg.maxFileCount, dirCfg.maxFileCount),
133
+ maxFolderSize: Math.min(params.maxFolderSize ?? dirCfg.maxFolderSize, dirCfg.maxFolderSize)
134
+ });
135
+ const fileName = relPath.split("/").pop() || relPath || "shared";
136
+ const record = this.buildRecord({
137
+ kind: "directory",
138
+ absolutePath,
139
+ workspaceRoot,
140
+ workspaceRelativePath: relPath,
141
+ inode: fileStat.ino,
142
+ fileName,
143
+ fileSize: summary.totalSize,
144
+ mimeType: "application/x-directory",
145
+ ttlMs,
146
+ maxViews: params.maxViews,
147
+ description: params.description,
148
+ gatewayTokenHash,
149
+ directory: {
150
+ mode: params.directoryMode ?? "browse",
151
+ entryCount: summary.entryCount,
152
+ followSymlinks,
153
+ maxDepth
154
+ }
155
+ });
156
+ this.persistAndAudit(record, "share.create", `Folder share created: ${record.fileName}`, {
157
+ fileName: record.fileName,
158
+ entryCount: summary.entryCount,
159
+ totalSize: summary.totalSize,
160
+ ttlMs,
161
+ mode: record.directory?.mode
162
+ });
163
+ return record;
164
+ }
165
+ buildRecord(input) {
166
+ const id = randomUUID();
167
+ const token = randomBytes(32).toString("base64url");
168
+ const now = /* @__PURE__ */ new Date();
169
+ const record = {
170
+ id,
171
+ token,
172
+ absolutePath: input.absolutePath,
173
+ workspaceRelativePath: input.workspaceRelativePath,
174
+ workspaceRoot: input.workspaceRoot,
175
+ inode: input.inode,
176
+ kind: input.kind,
177
+ fileName: input.fileName,
178
+ fileSize: input.fileSize,
179
+ mimeType: input.mimeType,
84
180
  createdAt: now.toISOString(),
85
- expiresAt: new Date(now.getTime() + ttlMs).toISOString(),
86
- maxViews: params.maxViews ?? null,
87
- viewCount: 0,
181
+ expiresAt: new Date(now.getTime() + input.ttlMs).toISOString(),
182
+ maxViews: input.maxViews ?? null,
183
+ downloadCount: 0,
88
184
  revoked: false,
89
- createdByTokenHash: gatewayTokenHash,
90
- description: params.description
185
+ createdByTokenHash: input.gatewayTokenHash,
186
+ description: input.description,
187
+ directory: input.directory
91
188
  };
92
189
  this.shares.set(id, record);
93
190
  this.tokenIndex.set(token, id);
94
- this.persistSync();
95
- logShareAudit("share.create", {
96
- shareId: id,
97
- tokenPrefix: token.slice(0, 8),
98
- fileName,
99
- fileSize: fileStat.size,
100
- ttlMs
101
- }, `Share created: ${fileName}`);
102
191
  return record;
103
192
  }
193
+ persistAndAudit(record, event, message, extra) {
194
+ this.persistSync();
195
+ logShareAudit(event, {
196
+ shareId: record.id,
197
+ tokenPrefix: record.token.slice(0, 8),
198
+ ...extra
199
+ }, message);
200
+ }
104
201
  getById(id) {
105
202
  return this.shares.get(id) ?? null;
106
203
  }
@@ -119,17 +216,17 @@ var ShareStore = class {
119
216
  valid: false,
120
217
  reason: "expired"
121
218
  };
122
- if (record.maxViews !== null && record.viewCount >= record.maxViews) return {
219
+ if (record.maxViews !== null && record.downloadCount >= record.maxViews) return {
123
220
  valid: false,
124
221
  reason: "max_views"
125
222
  };
126
223
  return { valid: true };
127
224
  }
128
- /** Increment view count (debounced persist). */
129
- incrementViewCount(id) {
225
+ /** Increment download counter (used by directory & file downloads). Debounced persist. */
226
+ incrementDownloadCount(id) {
130
227
  const record = this.shares.get(id);
131
228
  if (!record) return;
132
- record.viewCount++;
229
+ record.downloadCount++;
133
230
  this.scheduleDebouncedPersist();
134
231
  }
135
232
  /** Check if the file still exists and inode matches. */
@@ -147,7 +244,7 @@ var ShareStore = class {
147
244
  tokenPrefix: record.token.slice(0, 8),
148
245
  oldInode: record.inode,
149
246
  newInode: fileStat.ino
150
- }, `Share file replaced (inode changed): ${record.fileName}`);
247
+ }, `Share path replaced (inode changed): ${record.fileName}`);
151
248
  return {
152
249
  valid: false,
153
250
  reason: "file_deleted"
@@ -161,10 +258,125 @@ var ShareStore = class {
161
258
  };
162
259
  }
163
260
  }
261
+ /**
262
+ * Resolve a child path inside a directory share. Returns the absolute path
263
+ * if it stays within both the share root and the workspace.
264
+ */
265
+ async resolveDirectoryChild(record, relativePath) {
266
+ if (record.kind !== "directory") return {
267
+ ok: false,
268
+ reason: "not_directory"
269
+ };
270
+ const trimmed = (relativePath ?? "").replace(/^\/+/, "").replace(/\\/g, "/");
271
+ if (trimmed.includes("..") || trimmed.includes("\0")) return {
272
+ ok: false,
273
+ reason: "path_traversal"
274
+ };
275
+ const abs = resolve(record.absolutePath, trimmed);
276
+ const relToShare = relative(record.absolutePath, abs);
277
+ if (relToShare.startsWith("..") || relToShare.split(/[/\\]/).includes("..")) return {
278
+ ok: false,
279
+ reason: "path_outside_share"
280
+ };
281
+ try {
282
+ const real = await realpath(abs);
283
+ if (!isPathUnderWorkspace(record.workspaceRoot, real)) return {
284
+ ok: false,
285
+ reason: "path_outside_workspace"
286
+ };
287
+ const relToShareReal = relative(record.absolutePath, real);
288
+ if (relToShareReal.startsWith("..") || relToShareReal.split(/[/\\]/).includes("..")) return {
289
+ ok: false,
290
+ reason: "path_outside_share"
291
+ };
292
+ return {
293
+ ok: true,
294
+ absolutePath: real
295
+ };
296
+ } catch {
297
+ return {
298
+ ok: false,
299
+ reason: "not_found"
300
+ };
301
+ }
302
+ }
303
+ /** List a single directory level (cached, share-root-relative). */
304
+ async listDirectory(record, relativePath) {
305
+ if (record.kind !== "directory") throw new Error("Not a directory share");
306
+ const trimmed = (relativePath ?? "").replace(/^\/+/, "");
307
+ const cacheKey = `${record.id}::${trimmed}`;
308
+ const cacheTtl = this.config.directory.listingCacheMs;
309
+ const now = Date.now();
310
+ const cached = this.listingCache.get(cacheKey);
311
+ if (cached && cached.expiresAt > now) return cached.listing;
312
+ const resolved = await this.resolveDirectoryChild(record, trimmed);
313
+ if (resolved.ok !== true) throw new Error(resolved.reason);
314
+ const absDir = resolved.absolutePath;
315
+ if (!(await stat(absDir)).isDirectory()) throw new Error("not_directory");
316
+ const followSymlinks = record.directory?.followSymlinks ?? false;
317
+ const dirents = await readdir(absDir, { withFileTypes: true });
318
+ const entries = [];
319
+ let truncated = false;
320
+ const limit = 2e3;
321
+ for (const dirent of dirents) {
322
+ if (entries.length >= limit) {
323
+ truncated = true;
324
+ break;
325
+ }
326
+ const childAbs = resolve(absDir, dirent.name);
327
+ try {
328
+ const childLstat = await lstat(childAbs);
329
+ if (childLstat.isSymbolicLink()) {
330
+ if (!followSymlinks) continue;
331
+ const real = await realpath(childAbs);
332
+ if (!isPathUnderWorkspace(record.workspaceRoot, real)) continue;
333
+ if (relative(record.absolutePath, real).startsWith("..")) continue;
334
+ }
335
+ const childStat = childLstat.isSymbolicLink() ? await stat(childAbs) : childLstat;
336
+ const childRel = trimmed ? `${trimmed}/${dirent.name}` : dirent.name;
337
+ entries.push({
338
+ name: dirent.name,
339
+ path: childRel,
340
+ isDirectory: childStat.isDirectory(),
341
+ size: childStat.isFile() ? childStat.size : 0,
342
+ mtime: childStat.mtime.toISOString(),
343
+ mimeType: childStat.isDirectory() ? "application/x-directory" : resolveMimeType(dirent.name)
344
+ });
345
+ } catch {}
346
+ }
347
+ entries.sort((a, b) => {
348
+ if (a.isDirectory !== b.isDirectory) return a.isDirectory ? -1 : 1;
349
+ return a.name.localeCompare(b.name);
350
+ });
351
+ const listing = {
352
+ path: trimmed,
353
+ entries,
354
+ truncated
355
+ };
356
+ if (cacheTtl > 0) this.listingCache.set(cacheKey, {
357
+ listing,
358
+ expiresAt: now + cacheTtl
359
+ });
360
+ return listing;
361
+ }
362
+ /** Update thumbnail status. Persists immediately so generator restart is safe. */
363
+ setThumbnailStatus(id, status) {
364
+ const record = this.shares.get(id);
365
+ if (!record) return;
366
+ record.thumbnailStatus = status;
367
+ if (status === "ready") record.thumbnailGeneratedAt = (/* @__PURE__ */ new Date()).toISOString();
368
+ if (status === "failed") record.thumbnailFailedAt = (/* @__PURE__ */ new Date()).toISOString();
369
+ this.persistSync();
370
+ }
371
+ /** Drop the listing cache for a share (used on revoke/update). */
372
+ invalidateListingCache(shareId) {
373
+ for (const key of this.listingCache.keys()) if (key.startsWith(`${shareId}::`)) this.listingCache.delete(key);
374
+ }
164
375
  revoke(id) {
165
376
  const record = this.shares.get(id);
166
377
  if (!record) return false;
167
378
  record.revoked = true;
379
+ this.invalidateListingCache(id);
168
380
  this.persistSync();
169
381
  logShareAudit("share.revoke", {
170
382
  shareId: id,
@@ -179,6 +391,7 @@ var ShareStore = class {
179
391
  const record = this.shares.get(id);
180
392
  if (record && !record.revoked) {
181
393
  record.revoked = true;
394
+ this.invalidateListingCache(id);
182
395
  count++;
183
396
  logShareAudit("share.revoke", {
184
397
  shareId: id,
@@ -195,6 +408,7 @@ var ShareStore = class {
195
408
  let count = 0;
196
409
  for (const record of this.shares.values()) if (!record.revoked && now >= new Date(record.expiresAt).getTime()) {
197
410
  record.revoked = true;
411
+ this.invalidateListingCache(record.id);
198
412
  count++;
199
413
  }
200
414
  if (count > 0) this.persistSync();
@@ -265,16 +479,16 @@ var ShareStore = class {
265
479
  }, null, 2)}\n`, "utf8");
266
480
  }
267
481
  scheduleDebouncedPersist() {
268
- this.viewCountDirty = true;
269
- if (this.viewCountTimer) return;
270
- this.viewCountTimer = setTimeout(() => {
271
- this.viewCountTimer = null;
272
- if (this.viewCountDirty) {
273
- this.viewCountDirty = false;
482
+ this.dirty = true;
483
+ if (this.debounceTimer) return;
484
+ this.debounceTimer = setTimeout(() => {
485
+ this.debounceTimer = null;
486
+ if (this.dirty) {
487
+ this.dirty = false;
274
488
  this.persistSync();
275
489
  }
276
- }, VIEW_COUNT_DEBOUNCE_MS);
277
- this.viewCountTimer.unref?.();
490
+ }, COUNTER_DEBOUNCE_MS);
491
+ this.debounceTimer.unref?.();
278
492
  }
279
493
  startCleanupTimer() {
280
494
  this.cleanupTimer = setInterval(() => {
@@ -288,6 +502,15 @@ var ShareStore = class {
288
502
  for (const [id, record] of this.shares) if (now - new Date(record.expiresAt).getTime() > EXPIRED_RETENTION_MS) {
289
503
  this.shares.delete(id);
290
504
  this.tokenIndex.delete(record.token);
505
+ this.invalidateListingCache(id);
506
+ if (this.onCleanup) try {
507
+ this.onCleanup(record);
508
+ } catch (err) {
509
+ log.warn({
510
+ err,
511
+ shareId: id
512
+ }, "Share cleanup hook threw");
513
+ }
291
514
  removed++;
292
515
  }
293
516
  if (removed > 0) {
@@ -300,28 +523,63 @@ var ShareStore = class {
300
523
  clearInterval(this.cleanupTimer);
301
524
  this.cleanupTimer = null;
302
525
  }
303
- if (this.viewCountTimer) {
304
- clearTimeout(this.viewCountTimer);
305
- this.viewCountTimer = null;
526
+ if (this.debounceTimer) {
527
+ clearTimeout(this.debounceTimer);
528
+ this.debounceTimer = null;
306
529
  }
307
- if (this.viewCountDirty) {
308
- this.viewCountDirty = false;
530
+ if (this.dirty) {
531
+ this.dirty = false;
309
532
  this.persistSync();
310
533
  }
534
+ this.listingCache.clear();
311
535
  }
312
536
  async resolveAndValidatePath(relPath, workspaceRoot) {
313
537
  const trimmed = relPath.trim().replace(/\\/g, "/").replace(/^\/+/, "");
314
538
  if (!trimmed) throw new Error("Empty path");
315
539
  if (trimmed.includes("..")) throw new Error("Path traversal not allowed");
316
540
  if (trimmed.includes("\0")) throw new Error("Invalid path");
317
- const { resolve } = await import("node:path");
318
- const { relative } = await import("node:path");
319
541
  const abs = resolve(workspaceRoot, trimmed);
320
542
  const relToRoot = relative(resolve(workspaceRoot), abs);
321
543
  if (relToRoot.startsWith("..") || relToRoot.split(/[/\\]/).includes("..")) throw new Error("Path is outside workspace");
322
544
  return abs;
323
545
  }
324
546
  };
547
+ async function scanDirectory(root, opts) {
548
+ let entryCount = 0;
549
+ let totalSize = 0;
550
+ async function walk(dir, depth) {
551
+ if (depth > opts.maxDepth) return;
552
+ const dirents = await readdir(dir, { withFileTypes: true });
553
+ for (const dirent of dirents) {
554
+ if (entryCount >= opts.maxFileCount) throw new Error(`Folder exceeds maxFileCount (${opts.maxFileCount})`);
555
+ const childAbs = resolve(dir, dirent.name);
556
+ const childLstat = await lstat(childAbs);
557
+ let effectiveStat = childLstat;
558
+ if (childLstat.isSymbolicLink()) {
559
+ if (!opts.followSymlinks) continue;
560
+ const real = await realpath(childAbs);
561
+ if (!isPathUnderWorkspace(opts.workspaceRoot, real)) throw new Error("Symlink target escapes workspace");
562
+ effectiveStat = await stat(childAbs);
563
+ }
564
+ if (effectiveStat.isFile()) {
565
+ entryCount++;
566
+ totalSize += effectiveStat.size;
567
+ if (totalSize > opts.maxFolderSize) {
568
+ const maxMb = (opts.maxFolderSize / 1048576).toFixed(0);
569
+ throw new Error(`Folder exceeds maxFolderSize (${maxMb} MB)`);
570
+ }
571
+ } else if (effectiveStat.isDirectory()) {
572
+ entryCount++;
573
+ await walk(childAbs, depth + 1);
574
+ }
575
+ }
576
+ }
577
+ await walk(root, 0);
578
+ return {
579
+ entryCount,
580
+ totalSize
581
+ };
582
+ }
325
583
  const MIME_BY_EXT = {
326
584
  png: "image/png",
327
585
  jpg: "image/jpeg",
@@ -337,6 +595,7 @@ const MIME_BY_EXT = {
337
595
  html: "text/html",
338
596
  css: "text/css",
339
597
  js: "text/javascript",
598
+ mjs: "text/javascript",
340
599
  ts: "text/typescript",
341
600
  xml: "application/xml",
342
601
  csv: "text/csv",
@@ -349,6 +608,12 @@ const MIME_BY_EXT = {
349
608
  mp4: "video/mp4",
350
609
  webm: "video/webm",
351
610
  mov: "video/quicktime",
611
+ wasm: "application/wasm",
612
+ woff: "font/woff",
613
+ woff2: "font/woff2",
614
+ ttf: "font/ttf",
615
+ otf: "font/otf",
616
+ ico: "image/x-icon",
352
617
  docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
353
618
  xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
354
619
  pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
@@ -356,6 +621,12 @@ const MIME_BY_EXT = {
356
621
  function resolveMimeType(fileName) {
357
622
  return MIME_BY_EXT[fileName.split(".").pop()?.toLowerCase() ?? ""] || "application/octet-stream";
358
623
  }
624
+ /** HTTP Content-Type with charset for text-like bodies (browser inline preview). */
625
+ function shareResponseContentType(mime) {
626
+ if (/;\s*charset=/i.test(mime)) return mime;
627
+ if (mime.startsWith("text/") || mime === "application/json" || mime === "application/javascript" || mime === "application/xml" || mime === "image/svg+xml") return `${mime}; charset=utf-8`;
628
+ return mime;
629
+ }
359
630
  let singleton = null;
360
631
  function getShareStore(config) {
361
632
  if (!singleton) singleton = new ShareStore(config);
@@ -366,6 +637,6 @@ function resetShareStoreForTests() {
366
637
  singleton = null;
367
638
  }
368
639
  //#endregion
369
- export { ShareStore, getShareStore, resetShareStoreForTests };
640
+ export { ShareStore, getShareStore, resetShareStoreForTests, resolveMimeType, shareResponseContentType };
370
641
 
371
642
  //# sourceMappingURL=share-store.js.map