cli-jaw 2.2.16 → 2.2.17

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 (411) hide show
  1. package/README.md +10 -1
  2. package/dist/bin/commands/_shared/dashboard-client.js +42 -0
  3. package/dist/bin/commands/_shared/dashboard-client.js.map +1 -0
  4. package/dist/bin/commands/_shared/search-format.js +40 -0
  5. package/dist/bin/commands/_shared/search-format.js.map +1 -0
  6. package/dist/bin/commands/chat-search.js +5 -3
  7. package/dist/bin/commands/chat-search.js.map +1 -1
  8. package/dist/bin/commands/dashboard-chat.js +14 -31
  9. package/dist/bin/commands/dashboard-chat.js.map +1 -1
  10. package/dist/bin/commands/dashboard-memory.js +12 -49
  11. package/dist/bin/commands/dashboard-memory.js.map +1 -1
  12. package/dist/bin/commands/doctor.js +33 -10
  13. package/dist/bin/commands/doctor.js.map +1 -1
  14. package/dist/bin/commands/init.js +13 -1
  15. package/dist/bin/commands/init.js.map +1 -1
  16. package/dist/bin/commands/memory.js +5 -1
  17. package/dist/bin/commands/memory.js.map +1 -1
  18. package/dist/bin/commands/slack.js +57 -3
  19. package/dist/bin/commands/slack.js.map +1 -1
  20. package/dist/bin/commands/tui/input-handler.js +1 -1
  21. package/dist/bin/commands/tui/input-handler.js.map +1 -1
  22. package/dist/bin/commands/tui/slash-command-runner.js +4 -5
  23. package/dist/bin/commands/tui/slash-command-runner.js.map +1 -1
  24. package/dist/bin/postinstall.js +16 -18
  25. package/dist/bin/postinstall.js.map +1 -1
  26. package/dist/lib/media-kind.js +28 -0
  27. package/dist/lib/media-kind.js.map +1 -0
  28. package/dist/lib/upload.js +27 -10
  29. package/dist/lib/upload.js.map +1 -1
  30. package/dist/server.js +35 -51
  31. package/dist/server.js.map +1 -1
  32. package/dist/src/agent/args.js +34 -0
  33. package/dist/src/agent/args.js.map +1 -1
  34. package/dist/src/agent/codex-app-client.js +1016 -135
  35. package/dist/src/agent/codex-app-client.js.map +1 -1
  36. package/dist/src/agent/codex-app-events.js +72 -1
  37. package/dist/src/agent/codex-app-events.js.map +1 -1
  38. package/dist/src/agent/codex-host-pool.js +617 -0
  39. package/dist/src/agent/codex-host-pool.js.map +1 -0
  40. package/dist/src/agent/jwc-runtime.js +12 -4
  41. package/dist/src/agent/jwc-runtime.js.map +1 -1
  42. package/dist/src/agent/kiro-auth.js +10 -4
  43. package/dist/src/agent/kiro-auth.js.map +1 -1
  44. package/dist/src/agent/kiro-runtime.js +45 -8
  45. package/dist/src/agent/kiro-runtime.js.map +1 -1
  46. package/dist/src/agent/lifecycle-handler.js +75 -52
  47. package/dist/src/agent/lifecycle-handler.js.map +1 -1
  48. package/dist/src/agent/memory-flush-controller.js +241 -33
  49. package/dist/src/agent/memory-flush-controller.js.map +1 -1
  50. package/dist/src/agent/prompt-context.js +4 -0
  51. package/dist/src/agent/prompt-context.js.map +1 -1
  52. package/dist/src/agent/runtime-pool.js +64 -34
  53. package/dist/src/agent/runtime-pool.js.map +1 -1
  54. package/dist/src/agent/session-persistence.js +71 -15
  55. package/dist/src/agent/session-persistence.js.map +1 -1
  56. package/dist/src/agent/spawn/queue.js +319 -162
  57. package/dist/src/agent/spawn/queue.js.map +1 -1
  58. package/dist/src/agent/spawn.js +581 -268
  59. package/dist/src/agent/spawn.js.map +1 -1
  60. package/dist/src/bgtask/types.js +1 -1
  61. package/dist/src/bgtask/types.js.map +1 -1
  62. package/dist/src/browser/adaptive-fetch/safety.js +25 -0
  63. package/dist/src/browser/adaptive-fetch/safety.js.map +1 -1
  64. package/dist/src/browser/connection.js +2 -8
  65. package/dist/src/browser/connection.js.map +1 -1
  66. package/dist/src/cli/capability-probe-worker.js +172 -0
  67. package/dist/src/cli/capability-probe-worker.js.map +1 -0
  68. package/dist/src/cli/capability-probe.js +83 -0
  69. package/dist/src/cli/capability-probe.js.map +1 -0
  70. package/dist/src/cli/claude-models.js +2 -2
  71. package/dist/src/cli/claude-models.js.map +1 -1
  72. package/dist/src/cli/cli-status-worker.js +296 -0
  73. package/dist/src/cli/cli-status-worker.js.map +1 -0
  74. package/dist/src/cli/cli-status.js +81 -0
  75. package/dist/src/cli/cli-status.js.map +1 -0
  76. package/dist/src/cli/command-context.js +17 -5
  77. package/dist/src/cli/command-context.js.map +1 -1
  78. package/dist/src/cli/compact.js +56 -19
  79. package/dist/src/cli/compact.js.map +1 -1
  80. package/dist/src/cli/handlers-runtime.js +6 -4
  81. package/dist/src/cli/handlers-runtime.js.map +1 -1
  82. package/dist/src/cli/handlers.js +7 -2
  83. package/dist/src/cli/handlers.js.map +1 -1
  84. package/dist/src/cli/opencodex-models.js +5 -32
  85. package/dist/src/cli/opencodex-models.js.map +1 -1
  86. package/dist/src/cli/opencodex-runtime.js +82 -0
  87. package/dist/src/cli/opencodex-runtime.js.map +1 -0
  88. package/dist/src/cli/readiness.js +35 -18
  89. package/dist/src/cli/readiness.js.map +1 -1
  90. package/dist/src/cli/registry-live.js +8 -2
  91. package/dist/src/cli/registry-live.js.map +1 -1
  92. package/dist/src/cli/registry.js +1 -1
  93. package/dist/src/cli/registry.js.map +1 -1
  94. package/dist/src/core/browser-open-default.js +6 -4
  95. package/dist/src/core/browser-open-default.js.map +1 -1
  96. package/dist/src/core/browser-open.js +11 -15
  97. package/dist/src/core/browser-open.js.map +1 -1
  98. package/dist/src/core/bus.js +7 -1
  99. package/dist/src/core/bus.js.map +1 -1
  100. package/dist/src/core/chat-sessions.js +121 -12
  101. package/dist/src/core/chat-sessions.js.map +1 -1
  102. package/dist/src/core/cli-detect.js +148 -4
  103. package/dist/src/core/cli-detect.js.map +1 -1
  104. package/dist/src/core/codex-config.js +21 -0
  105. package/dist/src/core/codex-config.js.map +1 -1
  106. package/dist/src/core/compact.js +73 -21
  107. package/dist/src/core/compact.js.map +1 -1
  108. package/dist/src/core/config.js +449 -20
  109. package/dist/src/core/config.js.map +1 -1
  110. package/dist/src/core/db.js +225 -0
  111. package/dist/src/core/db.js.map +1 -1
  112. package/dist/src/core/event-bus.js +49 -4
  113. package/dist/src/core/event-bus.js.map +1 -1
  114. package/dist/src/core/event-scope.js +100 -0
  115. package/dist/src/core/event-scope.js.map +1 -0
  116. package/dist/src/core/main-session.js +64 -21
  117. package/dist/src/core/main-session.js.map +1 -1
  118. package/dist/src/core/message-summary.js +12 -2
  119. package/dist/src/core/message-summary.js.map +1 -1
  120. package/dist/src/core/platform-kind.js +139 -0
  121. package/dist/src/core/platform-kind.js.map +1 -0
  122. package/dist/src/core/rate-limit.js +156 -0
  123. package/dist/src/core/rate-limit.js.map +1 -0
  124. package/dist/src/core/runtime-settings.js +165 -17
  125. package/dist/src/core/runtime-settings.js.map +1 -1
  126. package/dist/src/core/session-context.js +7 -0
  127. package/dist/src/core/session-context.js.map +1 -0
  128. package/dist/src/core/session-ops.js +53 -9
  129. package/dist/src/core/session-ops.js.map +1 -1
  130. package/dist/src/core/settings-merge.js +105 -3
  131. package/dist/src/core/settings-merge.js.map +1 -1
  132. package/dist/src/core/settings-watch.js +29 -5
  133. package/dist/src/core/settings-watch.js.map +1 -1
  134. package/dist/src/core/widget-watcher.js +15 -2
  135. package/dist/src/core/widget-watcher.js.map +1 -1
  136. package/dist/src/discord/bot.js +5 -2
  137. package/dist/src/discord/bot.js.map +1 -1
  138. package/dist/src/discord/commands.js +4 -4
  139. package/dist/src/discord/commands.js.map +1 -1
  140. package/dist/src/goal/heartbeat.js +1 -1
  141. package/dist/src/goal/heartbeat.js.map +1 -1
  142. package/dist/src/goal/runtime.js +1 -1
  143. package/dist/src/goal/runtime.js.map +1 -1
  144. package/dist/src/goal-run/controller.js +2 -2
  145. package/dist/src/goal-run/controller.js.map +1 -1
  146. package/dist/src/manager/internal-fetch.js +15 -0
  147. package/dist/src/manager/internal-fetch.js.map +1 -0
  148. package/dist/src/manager/logs.js +2 -1
  149. package/dist/src/manager/logs.js.map +1 -1
  150. package/dist/src/manager/memory/chat-federation.js +104 -11
  151. package/dist/src/manager/memory/chat-federation.js.map +1 -1
  152. package/dist/src/manager/memory/federation.js +100 -0
  153. package/dist/src/manager/memory/federation.js.map +1 -1
  154. package/dist/src/manager/metadata.js +4 -1
  155. package/dist/src/manager/metadata.js.map +1 -1
  156. package/dist/src/manager/notes/assets.js +1 -1
  157. package/dist/src/manager/notes/assets.js.map +1 -1
  158. package/dist/src/manager/notes/frontmatter.js +5 -49
  159. package/dist/src/manager/notes/frontmatter.js.map +1 -1
  160. package/dist/src/manager/notes/link-resolver.js +2 -2
  161. package/dist/src/manager/notes/link-resolver.js.map +1 -1
  162. package/dist/src/manager/notes/remote-assets.js +1 -1
  163. package/dist/src/manager/notes/remote-assets.js.map +1 -1
  164. package/dist/src/manager/notes/routes.js +2 -2
  165. package/dist/src/manager/notes/routes.js.map +1 -1
  166. package/dist/src/manager/notes/store.js +2 -2
  167. package/dist/src/manager/notes/store.js.map +1 -1
  168. package/dist/src/manager/notes/trash.js +1 -1
  169. package/dist/src/manager/notes/trash.js.map +1 -1
  170. package/dist/src/manager/notes/vault-index.js +2 -2
  171. package/dist/src/manager/notes/vault-index.js.map +1 -1
  172. package/dist/src/manager/notes/wiki-links.js +1 -1
  173. package/dist/src/manager/notes/wiki-links.js.map +1 -1
  174. package/dist/src/manager/notes/wiki-routes.js +84 -0
  175. package/dist/src/manager/notes/wiki-routes.js.map +1 -0
  176. package/dist/src/manager/proxy.js +1 -0
  177. package/dist/src/manager/proxy.js.map +1 -1
  178. package/dist/src/manager/routes/dashboard-memory.js +24 -1
  179. package/dist/src/manager/routes/dashboard-memory.js.map +1 -1
  180. package/dist/src/manager/routes/runtime-monitor.js +1 -1
  181. package/dist/src/manager/routes/runtime-monitor.js.map +1 -1
  182. package/dist/src/manager/scan.js +5 -3
  183. package/dist/src/manager/scan.js.map +1 -1
  184. package/dist/src/manager/server.js +20 -6
  185. package/dist/src/manager/server.js.map +1 -1
  186. package/dist/src/manager/telegram-hub/hub-bot.js +4 -3
  187. package/dist/src/manager/telegram-hub/hub-bot.js.map +1 -1
  188. package/dist/src/manager/worker-events.js +2 -1
  189. package/dist/src/manager/worker-events.js.map +1 -1
  190. package/dist/src/memory/heartbeat.js +6 -5
  191. package/dist/src/memory/heartbeat.js.map +1 -1
  192. package/dist/src/memory/indexing.js +162 -45
  193. package/dist/src/memory/indexing.js.map +1 -1
  194. package/dist/src/messaging/channel-validate.js +14 -1
  195. package/dist/src/messaging/channel-validate.js.map +1 -1
  196. package/dist/src/messaging/redact.js +2 -1
  197. package/dist/src/messaging/redact.js.map +1 -1
  198. package/dist/src/messaging/session-key.js +21 -2
  199. package/dist/src/messaging/session-key.js.map +1 -1
  200. package/dist/src/notes/constants.js.map +1 -0
  201. package/dist/src/notes/frontmatter.js +59 -0
  202. package/dist/src/notes/frontmatter.js.map +1 -0
  203. package/dist/src/notes/path-guards.js.map +1 -0
  204. package/dist/src/notes/search.js.map +1 -0
  205. package/dist/src/orchestrator/attestation.js +1 -1
  206. package/dist/src/orchestrator/attestation.js.map +1 -1
  207. package/dist/src/orchestrator/gateway.js +135 -31
  208. package/dist/src/orchestrator/gateway.js.map +1 -1
  209. package/dist/src/orchestrator/pipeline.js +53 -21
  210. package/dist/src/orchestrator/pipeline.js.map +1 -1
  211. package/dist/src/orchestrator/scope.js +36 -2
  212. package/dist/src/orchestrator/scope.js.map +1 -1
  213. package/dist/src/orchestrator/session-lanes.js +87 -0
  214. package/dist/src/orchestrator/session-lanes.js.map +1 -0
  215. package/dist/src/orchestrator/session-work.js +25 -0
  216. package/dist/src/orchestrator/session-work.js.map +1 -0
  217. package/dist/src/orchestrator/state-machine.js +1 -5
  218. package/dist/src/orchestrator/state-machine.js.map +1 -1
  219. package/dist/src/orchestrator/worker-registry.js +20 -10
  220. package/dist/src/orchestrator/worker-registry.js.map +1 -1
  221. package/dist/src/prompt/builder.js +40 -2
  222. package/dist/src/prompt/builder.js.map +1 -1
  223. package/dist/src/prompt/templates/a1-system.md +8 -1
  224. package/dist/src/routes/agent-control.js +44 -8
  225. package/dist/src/routes/agent-control.js.map +1 -1
  226. package/dist/src/routes/chat-sessions.js +34 -6
  227. package/dist/src/routes/chat-sessions.js.map +1 -1
  228. package/dist/src/routes/command.js +63 -8
  229. package/dist/src/routes/command.js.map +1 -1
  230. package/dist/src/routes/events.js +11 -2
  231. package/dist/src/routes/events.js.map +1 -1
  232. package/dist/src/routes/link-preview.js +1 -27
  233. package/dist/src/routes/link-preview.js.map +1 -1
  234. package/dist/src/routes/messages.js +6 -5
  235. package/dist/src/routes/messages.js.map +1 -1
  236. package/dist/src/routes/messaging.js +45 -1
  237. package/dist/src/routes/messaging.js.map +1 -1
  238. package/dist/src/routes/orchestrate.js +53 -33
  239. package/dist/src/routes/orchestrate.js.map +1 -1
  240. package/dist/src/routes/search.js +84 -0
  241. package/dist/src/routes/search.js.map +1 -0
  242. package/dist/src/routes/session-request.js +29 -0
  243. package/dist/src/routes/session-request.js.map +1 -0
  244. package/dist/src/routes/settings.js +110 -3
  245. package/dist/src/routes/settings.js.map +1 -1
  246. package/dist/src/routes/static.js +30 -8
  247. package/dist/src/routes/static.js.map +1 -1
  248. package/dist/src/routes/system.js +1 -1
  249. package/dist/src/routes/system.js.map +1 -1
  250. package/dist/src/routes/wiki.js +122 -0
  251. package/dist/src/routes/wiki.js.map +1 -0
  252. package/dist/src/search/contract.js +2 -0
  253. package/dist/src/search/contract.js.map +1 -0
  254. package/dist/src/search/coordinator.js +153 -0
  255. package/dist/src/search/coordinator.js.map +1 -0
  256. package/dist/src/search/provider.js +40 -0
  257. package/dist/src/search/provider.js.map +1 -0
  258. package/dist/src/search/providers/chat.js +115 -0
  259. package/dist/src/search/providers/chat.js.map +1 -0
  260. package/dist/src/search/providers/memory.js +53 -0
  261. package/dist/src/search/providers/memory.js.map +1 -0
  262. package/dist/src/search/providers/wiki.js +80 -0
  263. package/dist/src/search/providers/wiki.js.map +1 -0
  264. package/dist/src/slack/api.js +10 -1
  265. package/dist/src/slack/api.js.map +1 -1
  266. package/dist/src/slack/attachment-recovery.js +42 -0
  267. package/dist/src/slack/attachment-recovery.js.map +1 -0
  268. package/dist/src/slack/bot.js +120 -41
  269. package/dist/src/slack/bot.js.map +1 -1
  270. package/dist/src/slack/commands.js +24 -8
  271. package/dist/src/slack/commands.js.map +1 -1
  272. package/dist/src/slack/events.js +12 -1
  273. package/dist/src/slack/events.js.map +1 -1
  274. package/dist/src/slack/history.js +108 -0
  275. package/dist/src/slack/history.js.map +1 -0
  276. package/dist/src/slack/inbound-file.js +242 -0
  277. package/dist/src/slack/inbound-file.js.map +1 -0
  278. package/dist/src/slack/inbound-url.js +39 -0
  279. package/dist/src/slack/inbound-url.js.map +1 -0
  280. package/dist/src/slack/ingress.js +140 -0
  281. package/dist/src/slack/ingress.js.map +1 -0
  282. package/dist/src/slack/manifest.js +3 -0
  283. package/dist/src/slack/manifest.js.map +1 -1
  284. package/dist/src/slack/socket.js +1 -1
  285. package/dist/src/slack/socket.js.map +1 -1
  286. package/dist/src/slack/thread-tracker.js +86 -0
  287. package/dist/src/slack/thread-tracker.js.map +1 -0
  288. package/dist/src/telegram/bot.js +21 -11
  289. package/dist/src/telegram/bot.js.map +1 -1
  290. package/dist/src/wiki/config.js +193 -0
  291. package/dist/src/wiki/config.js.map +1 -0
  292. package/dist/src/wiki/entities.js +61 -0
  293. package/dist/src/wiki/entities.js.map +1 -0
  294. package/dist/src/wiki/ontology.js +72 -0
  295. package/dist/src/wiki/ontology.js.map +1 -0
  296. package/dist/src/wiki/prompt.js +172 -0
  297. package/dist/src/wiki/prompt.js.map +1 -0
  298. package/dist/src/wiki/safe-traversal.js +198 -0
  299. package/dist/src/wiki/safe-traversal.js.map +1 -0
  300. package/dist/src/wiki/scaffold.js +77 -0
  301. package/dist/src/wiki/scaffold.js.map +1 -0
  302. package/package.json +1 -1
  303. package/public/css/session-hub.css +266 -0
  304. package/public/dist/assets/AdvancedExport-DYGcCAUq.js +1 -0
  305. package/public/dist/assets/Agent-CNNQ7KkJ.js +1 -0
  306. package/public/dist/assets/{DesignPanel-BGMPhZSx.js → DesignPanel-DcL369nB.js} +1 -1
  307. package/public/dist/assets/{DocPanel-Dz-J_l5M.js → DocPanel-K8A2pm_1.js} +1 -1
  308. package/public/dist/assets/{FolderPanel-DbPhzzvi.js → FolderPanel-CV52EzwG.js} +1 -1
  309. package/public/dist/assets/{MilkdownWysiwygEditor-Em7iC6y9.js → MilkdownWysiwygEditor-BKOCDI4Z.js} +1 -1
  310. package/public/dist/assets/api-B25zNNFJ.js +1 -0
  311. package/public/dist/assets/{app-DX4e6isX.css → app-DjgGeXhJ.css} +1 -1
  312. package/public/dist/assets/app-Dsgp4xpU.js +55 -0
  313. package/public/dist/assets/bgtask-badge-C6h5C-o4.js +1 -0
  314. package/public/dist/assets/{bgtask-badge-qMkKOZx0.js → bgtask-badge-CpavV0Jc.js} +4 -4
  315. package/public/dist/assets/{employees-BnobWM_2.js → employees-BJyEgim7.js} +4 -4
  316. package/public/dist/assets/idb-cache-B5PX63p7.js +1 -0
  317. package/public/dist/assets/{idb-cache-BzzftUET.js → idb-cache-lOntwU3S.js} +1 -1
  318. package/public/dist/assets/{iframe-renderer-C5vRbbl9.js → iframe-renderer-B8k3AvTv.js} +12 -12
  319. package/public/dist/assets/iframe-renderer-BO_GgCTR.js +1 -0
  320. package/public/dist/assets/manager-LkGs6qEJ.css +1 -0
  321. package/public/dist/assets/manager-kXYQyMhR.js +13 -0
  322. package/public/dist/assets/{memory-DF4kPwwC.js → memory-D2RbBVO-.js} +11 -11
  323. package/public/dist/assets/memory-amsvg4Ey.js +1 -0
  324. package/public/dist/assets/message-history-BGHZxvgV.js +1 -0
  325. package/public/dist/assets/message-history-Bw2E_b8L.js +1 -0
  326. package/public/dist/assets/pi-settings-5HVg1sXJ.js +1 -0
  327. package/public/dist/assets/render-BkGcpH7z.js +157 -0
  328. package/public/dist/assets/settings-B1FPORO2.js +56 -0
  329. package/public/dist/assets/settings-CMN-zN4Q.js +1 -0
  330. package/public/dist/assets/settings-core-B_OjGYVN.js +1 -0
  331. package/public/dist/assets/settings-core-CxRwqx86.js +144 -0
  332. package/public/dist/assets/sidebar-DW78DANx.js +49 -0
  333. package/public/dist/assets/skills-Dz-9Yrxr.js +1 -0
  334. package/public/dist/assets/{skills-IGquen_j.js → skills-lWi0ZFiV.js} +6 -6
  335. package/public/dist/assets/{slash-commands-ZRDOL99E.js → slash-commands-DYOI6nKj.js} +1 -1
  336. package/public/dist/assets/slash-commands-xJFCdTTM.js +1 -0
  337. package/public/dist/assets/{trace-drawer-D8To8fYt.js → trace-drawer-DBX9xzmt.js} +1 -1
  338. package/public/dist/assets/{ui-Hx_mNoDf.js → ui-Bx7eqnXt.js} +1 -1
  339. package/public/dist/assets/ui-JOcrYeG-.js +1 -0
  340. package/public/dist/assets/{wiki-link-suggestions-DZQc78gj.js → wiki-link-suggestions-Dp6kBQVu.js} +1 -1
  341. package/public/dist/index.html +4 -4
  342. package/public/dist/manager/index.html +2 -2
  343. package/public/index.html +3 -2
  344. package/public/js/event-channel.ts +25 -0
  345. package/public/js/features/channel-onboarding-flow.ts +16 -1
  346. package/public/js/features/channel-onboarding.ts +20 -2
  347. package/public/js/features/chat-messages.ts +3 -1
  348. package/public/js/features/chat-search.ts +2 -1
  349. package/public/js/features/chat.ts +56 -18
  350. package/public/js/features/elicitation.ts +15 -0
  351. package/public/js/features/idb-cache.ts +34 -0
  352. package/public/js/features/message-history.ts +2 -1
  353. package/public/js/features/session-hub.ts +334 -0
  354. package/public/js/features/settings-cli-status-render.ts +1 -1
  355. package/public/js/features/settings-cli-status.ts +25 -11
  356. package/public/js/features/settings-core.ts +72 -3
  357. package/public/js/features/settings-types.ts +32 -0
  358. package/public/js/features/ui-status.ts +2 -1
  359. package/public/js/main.ts +20 -0
  360. package/public/js/render/compose-block.ts +7 -0
  361. package/public/js/ws.ts +22 -2
  362. package/public/locales/en.json +46 -4
  363. package/public/locales/ja.json +46 -4
  364. package/public/locales/ko.json +46 -4
  365. package/public/locales/zh.json +46 -4
  366. package/public/manager/src/App.tsx +1 -1
  367. package/public/manager/src/InstancePreview.tsx +5 -1
  368. package/public/manager/src/api.ts +2 -1
  369. package/public/manager/src/components/InstanceGroups.tsx +10 -0
  370. package/public/manager/src/components/InstanceListContent.tsx +24 -1
  371. package/public/manager/src/components/InstanceRow.tsx +33 -3
  372. package/public/manager/src/components/InstanceSessionList.tsx +132 -0
  373. package/public/manager/src/hooks/useActiveSessionDisclosure.ts +45 -0
  374. package/public/manager/src/lib/resilient-fetch.ts +93 -0
  375. package/public/manager/src/lib/session-store.ts +216 -0
  376. package/public/manager/src/manager-components.css +97 -0
  377. package/public/manager/src/settings/pages/AdvancedExport.tsx +12 -2
  378. package/public/manager/src/settings/pages/Agent.tsx +113 -1
  379. package/public/manager/src/settings/pages/components/agent/agent-meta.ts +1 -1
  380. package/scripts/burst-scenario.mjs +72 -0
  381. package/scripts/check-redaction-sinks.mjs +1 -0
  382. package/scripts/check-strict-baseline.mjs +1 -1
  383. package/dist/src/manager/notes/constants.js.map +0 -1
  384. package/dist/src/manager/notes/path-guards.js.map +0 -1
  385. package/dist/src/manager/notes/search.js.map +0 -1
  386. package/public/dist/assets/AdvancedExport-DsDpqXoH.js +0 -1
  387. package/public/dist/assets/Agent-BjbZVZ9p.js +0 -1
  388. package/public/dist/assets/api-C9dOxby7.js +0 -1
  389. package/public/dist/assets/app-BzD_ZLvt.js +0 -55
  390. package/public/dist/assets/bgtask-badge-Dqbp-Y4e.js +0 -1
  391. package/public/dist/assets/idb-cache-ZH6lOebk.js +0 -1
  392. package/public/dist/assets/iframe-renderer-Df4KIVyx.js +0 -1
  393. package/public/dist/assets/manager-C4eNDNFt.css +0 -1
  394. package/public/dist/assets/manager-DaN201mN.js +0 -13
  395. package/public/dist/assets/memory-D-bULTHl.js +0 -1
  396. package/public/dist/assets/message-history-C4WOisGx.js +0 -1
  397. package/public/dist/assets/message-history-ZBoza6ew.js +0 -1
  398. package/public/dist/assets/pi-settings-CBUGDAuT.js +0 -1
  399. package/public/dist/assets/render-DYX6GRQ0.js +0 -122
  400. package/public/dist/assets/settings-DbJpGoaX.js +0 -55
  401. package/public/dist/assets/settings-SreihUje.js +0 -1
  402. package/public/dist/assets/settings-core-B1Y5Nb4Z.js +0 -1
  403. package/public/dist/assets/settings-core-DobZWIZ7.js +0 -140
  404. package/public/dist/assets/sidebar-Cp22g0Gv.js +0 -49
  405. package/public/dist/assets/skills-DwPIP08e.js +0 -1
  406. package/public/dist/assets/slash-commands-BBVfwcnW.js +0 -1
  407. package/public/dist/assets/ui-CAicpUZc.js +0 -1
  408. /package/dist/src/{manager/notes → notes}/constants.js +0 -0
  409. /package/dist/src/{manager/notes → notes}/path-guards.js +0 -0
  410. /package/dist/src/{manager/notes → notes}/search.js +0 -0
  411. /package/public/dist/assets/{pi-settings-Dh5lgb87.js → pi-settings-DEuKgvIj.js} +0 -0
@@ -0,0 +1,100 @@
1
+ // ─── Scoped SSE delivery rule (072 §1.3a) ────────────
2
+ // A browser tab bound to one chat session connects with `?scope=`, and the route
3
+ // filters on strict equality against `data.scope`. That filter alone is not enough,
4
+ // because `broadcast()` stamps the ambient session scope onto EVERY event published
5
+ // inside a session's async context (core/bus.ts). Instance-wide events published
6
+ // during an agent turn — a heartbeat, a settings reload — therefore carry that
7
+ // session's scope and would vanish from every other tab.
8
+ //
9
+ // So delivery asks two questions in order: is this event instance-wide (deliver to
10
+ // everyone regardless of the scope it happens to carry), and otherwise does its scope
11
+ // match the connection. The judgement is "does one session own this event", not "is it
12
+ // topology". An event wrongly marked instance-wide is just noise in a tab; an event
13
+ // wrongly marked session-owned disappears.
14
+ import { DELIVERY_KEY_GLOBAL, DELIVERY_KEY_NONE, isPublicSseTopic } from './event-bus.js';
15
+ // Instance-wide events. Every tab needs these regardless of which session's async
16
+ // context happened to publish them.
17
+ export const INSTANCE_WIDE_EVENTS = new Set([
18
+ // The session list itself — a tab must see sessions appear and disappear.
19
+ 'session_created',
20
+ 'session_list',
21
+ // Instance configuration and inventory.
22
+ 'settings_change',
23
+ 'agent_added',
24
+ 'agent_updated',
25
+ 'agent_deleted',
26
+ // Instance-wide subsystems with no session dimension.
27
+ 'memory_status',
28
+ 'heartbeat_pending',
29
+ 'bgtask_update',
30
+ 'alert_escalation',
31
+ 'schedule_wakeup',
32
+ 'schedule_wakeup_failed',
33
+ // A global switch is published outside any session context, so it carries no scope
34
+ // and a strict filter would drop it from every scoped tab — leaving each of them
35
+ // showing a stale idea of which session is active.
36
+ 'session_switched',
37
+ ]);
38
+ // `system_notice` is a mixed bag: some notices describe one session's turn and some
39
+ // describe the instance. Classifying the whole type either way is wrong, so the code
40
+ // decides. An unrecognised code is treated as instance-wide, which is the safe error:
41
+ // an extra notice is noise, a missing one is invisible.
42
+ //
43
+ // The code is not sufficient on its own. `auto_compact_refresh` is published both by a
44
+ // session's own turn AND by the instance-wide reset in session-ops, and only the first
45
+ // carries a scope. A notice with no scope has no session to belong to, so it is
46
+ // delivered everywhere rather than nowhere.
47
+ const SESSION_OWNED_NOTICE_CODES = new Set([
48
+ 'compact_suggest',
49
+ 'auto_compact_refresh',
50
+ ]);
51
+ function isSessionOwnedNotice(data) {
52
+ const code = data["code"];
53
+ return typeof code === 'string'
54
+ && SESSION_OWNED_NOTICE_CODES.has(code)
55
+ && typeof data["scope"] === 'string';
56
+ }
57
+ // Goal state is a single instance-wide file with no session field (goal/store.ts).
58
+ // A goal finished in one tab must clear the cockpit in every tab, so goal events are
59
+ // delivered everywhere even though a turn in one session produced them.
60
+ export function isInstanceWideEvent(event) {
61
+ return INSTANCE_WIDE_EVENTS.has(event) || event.startsWith('goal_');
62
+ }
63
+ export function shouldDeliverToScope(entry, scopeFilter) {
64
+ // No filter means "everything", which is what manager and worker connections rely on.
65
+ if (!scopeFilter)
66
+ return true;
67
+ if (entry.event === 'system_notice') {
68
+ return isSessionOwnedNotice(entry.data)
69
+ ? entry.data["scope"] === scopeFilter
70
+ : true;
71
+ }
72
+ if (isInstanceWideEvent(entry.event))
73
+ return true;
74
+ return entry.data["scope"] === scopeFilter;
75
+ }
76
+ /**
77
+ * The delivery class of an event, for the replay-gap watermarks in the bus.
78
+ *
79
+ * It answers the same questions as delivery, in the same order, because a gap check that
80
+ * classified events differently from the filter would report losses that never happened
81
+ * and miss ones that did. The route drops non-public topics before it looks at scope, so
82
+ * that comes first here too: an event no subscriber can see costs nobody anything when it
83
+ * ages out.
84
+ */
85
+ export function deliveryKeyForEntry(entry) {
86
+ if (!isPublicSseTopic(entry.topic))
87
+ return DELIVERY_KEY_NONE;
88
+ if (entry.event === 'system_notice') {
89
+ // A compact suggestion belongs to the session that raised it; every other notice
90
+ // is for the whole instance.
91
+ return isSessionOwnedNotice(entry.data)
92
+ ? String(entry.data["scope"])
93
+ : DELIVERY_KEY_GLOBAL;
94
+ }
95
+ if (isInstanceWideEvent(entry.event))
96
+ return DELIVERY_KEY_GLOBAL;
97
+ const scope = entry.data["scope"];
98
+ return typeof scope === 'string' && scope ? scope : DELIVERY_KEY_GLOBAL;
99
+ }
100
+ //# sourceMappingURL=event-scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-scope.js","sourceRoot":"","sources":["../../../src/core/event-scope.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,8 @@ import { broadcast } from './bus.js';
2
2
  import { DEFAULT_CLI } from '../cli/registry.js';
3
3
  import { settings } from './config.js';
4
4
  import { db, clearMessages, clearMessagesScoped, getSession, updateSession } from './db.js';
5
- import { getActiveChatSession } from './chat-sessions.js';
5
+ import { getActiveChatSession, getChatSessionRemoteKey } from './chat-sessions.js';
6
+ import { scopeForChatSession } from '../orchestrator/scope.js';
6
7
  export function getCliModelAndEffort(cli, currentSettings = settings) {
7
8
  const ao = currentSettings["activeOverrides"]?.[cli] || {};
8
9
  const pc = currentSettings["perCli"]?.[cli] || {};
@@ -42,9 +43,26 @@ export function buildClearedSessionRow(currentSettings = settings, session = nul
42
43
  effort,
43
44
  };
44
45
  }
45
- export function writeMainSessionRow(row) {
46
+ /**
47
+ * The `session` row is a single row for the whole instance, and the instance web owns
48
+ * what it holds (074). Callers that speak for the instance — a settings change, a CLI
49
+ * switch — write it unconditionally. Callers acting for one session pass false when
50
+ * that session is not the default one, so clearing a Slack thread cannot rewrite the
51
+ * CLI and model every other session reads.
52
+ *
53
+ * The decision is the caller's rather than this function's: it is also on the path of
54
+ * instance-wide writes, and refusing there would stop a second browser tab from
55
+ * updating the mirror after a legitimate change.
56
+ */
57
+ export function writeMainSessionRow(row, ownsSingletonRow = true) {
58
+ if (!ownsSingletonRow)
59
+ return;
46
60
  updateSession.run(row.cli, row.sessionId, row.model, row.permissions, row.workingDir, row.effort);
47
61
  }
62
+ /** True when the caller's session is the one that owns the shared row. */
63
+ function currentSessionOwnsSingletonRow() {
64
+ return getActiveChatSession() === 'default';
65
+ }
48
66
  export function syncMainSessionToSettings(prevCli = null) {
49
67
  const session = getSession();
50
68
  const row = buildSelectedSessionRow(settings, session, prevCli);
@@ -55,20 +73,29 @@ export function syncMainSessionToSettings(prevCli = null) {
55
73
  return row;
56
74
  }
57
75
  // Atomic: delete messages + update session in one transaction
58
- const clearMainTx = db.transaction((row) => {
76
+ const clearMainTx = db.transaction((row, ownsSingletonRow) => {
59
77
  if (row.workingDir && row.workingDir !== '~') {
60
78
  clearMessagesScoped.run(row.workingDir, getActiveChatSession());
61
79
  }
62
80
  else {
63
81
  clearMessages.run(getActiveChatSession());
64
82
  }
65
- writeMainSessionRow(row);
83
+ writeMainSessionRow(row, ownsSingletonRow);
66
84
  });
67
85
  export function clearMainSessionState() {
68
86
  const session = getSession();
69
87
  const row = buildClearedSessionRow(settings, session);
70
- clearMainTx(row);
71
- broadcast('clear', {});
88
+ // History is this session's to delete; the shared runtime selection is not.
89
+ const ownsSingletonRow = currentSessionOwnsSingletonRow();
90
+ // Capture the session BEFORE the transaction so the notice names exactly the history
91
+ // that was deleted. Without a scope on it, a scoped tab drops the event and keeps
92
+ // showing messages that no longer exist — including the tab whose history this was.
93
+ const clearedSessionId = getActiveChatSession();
94
+ clearMainTx(row, ownsSingletonRow);
95
+ broadcast('clear', {
96
+ scope: scopeForChatSession(clearedSessionId, getChatSessionRemoteKey(clearedSessionId) ?? undefined),
97
+ sessionId: clearedSessionId,
98
+ });
72
99
  return row;
73
100
  }
74
101
  /** Reset boss session ID (prevents stale --resume) but preserves message history. */
@@ -82,8 +109,14 @@ export function clearBossSessionOnly() {
82
109
  export function resetSessionPreservingHistory() {
83
110
  const session = getSession();
84
111
  const row = buildClearedSessionRow(settings, session);
85
- writeMainSessionRow(row);
86
- broadcast('session_reset', { cli: row.cli, model: row.model });
112
+ writeMainSessionRow(row, currentSessionOwnsSingletonRow());
113
+ const resetSessionId = getActiveChatSession();
114
+ broadcast('session_reset', {
115
+ cli: row.cli,
116
+ model: row.model,
117
+ scope: scopeForChatSession(resetSessionId, getChatSessionRemoteKey(resetSessionId) ?? undefined),
118
+ sessionId: resetSessionId,
119
+ });
87
120
  return row;
88
121
  }
89
122
  // ─── Pending bootstrap prompt (1-shot consumption, DB-backed) ───
@@ -96,10 +129,18 @@ import { getMemory, upsertMemory, deleteMemory } from './db.js';
96
129
  import { log } from './logger.js';
97
130
  const BOOTSTRAP_KEY = '__bootstrap_prompt';
98
131
  const BOOTSTRAP_SOURCE = '__system_bootstrap';
99
- function readBootstrapRow() {
132
+ // A compact summary belongs to the conversation that produced it. While one main
133
+ // run existed at a time a single row was enough; with several scopes in flight the
134
+ // first spawn to look would take someone else's handoff. Scoped rows get their own
135
+ // key and the bare key stays the default scope's, which is what existing rows are.
136
+ function bootstrapKeyFor(scopeKey) {
137
+ return !scopeKey || scopeKey === 'default' ? BOOTSTRAP_KEY : `${BOOTSTRAP_KEY}:${scopeKey}`;
138
+ }
139
+ function readBootstrapRow(scopeKey) {
100
140
  try {
141
+ const key = bootstrapKeyFor(scopeKey);
101
142
  const rows = getMemory.all();
102
- const row = rows.find(r => r.key === BOOTSTRAP_KEY && r.source === BOOTSTRAP_SOURCE);
143
+ const row = rows.find(r => r.key === key && r.source === BOOTSTRAP_SOURCE);
103
144
  return row?.value && row.value.trim() ? row.value : null;
104
145
  }
105
146
  catch (e) {
@@ -107,13 +148,14 @@ function readBootstrapRow() {
107
148
  return null;
108
149
  }
109
150
  }
110
- export function setPendingBootstrapPrompt(text) {
151
+ export function setPendingBootstrapPrompt(text, scopeKey) {
111
152
  try {
153
+ const key = bootstrapKeyFor(scopeKey);
112
154
  if (text && text.trim()) {
113
- upsertMemory.run(BOOTSTRAP_KEY, text, BOOTSTRAP_SOURCE);
155
+ upsertMemory.run(key, text, BOOTSTRAP_SOURCE);
114
156
  }
115
157
  else {
116
- deleteMemory.run(BOOTSTRAP_KEY);
158
+ deleteMemory.run(key);
117
159
  }
118
160
  }
119
161
  catch (e) {
@@ -122,19 +164,20 @@ export function setPendingBootstrapPrompt(text) {
122
164
  }
123
165
  // Strict variant: throws on DB failure. Use inside transactions where the caller
124
166
  // must know about persistence loss so the surrounding tx can roll back.
125
- export function setPendingBootstrapPromptStrict(text) {
167
+ export function setPendingBootstrapPromptStrict(text, scopeKey) {
168
+ const key = bootstrapKeyFor(scopeKey);
126
169
  if (text && text.trim()) {
127
- upsertMemory.run(BOOTSTRAP_KEY, text, BOOTSTRAP_SOURCE);
170
+ upsertMemory.run(key, text, BOOTSTRAP_SOURCE);
128
171
  }
129
172
  else {
130
- deleteMemory.run(BOOTSTRAP_KEY);
173
+ deleteMemory.run(key);
131
174
  }
132
175
  }
133
- export function consumePendingBootstrapPrompt() {
134
- const out = readBootstrapRow();
176
+ export function consumePendingBootstrapPrompt(scopeKey) {
177
+ const out = readBootstrapRow(scopeKey);
135
178
  if (out) {
136
179
  try {
137
- deleteMemory.run(BOOTSTRAP_KEY);
180
+ deleteMemory.run(bootstrapKeyFor(scopeKey));
138
181
  }
139
182
  catch (e) {
140
183
  console.warn('[jaw:bootstrap] consume delete failed:', e.message);
@@ -142,7 +185,7 @@ export function consumePendingBootstrapPrompt() {
142
185
  }
143
186
  return out;
144
187
  }
145
- export function peekPendingBootstrapPrompt() {
146
- return readBootstrapRow();
188
+ export function peekPendingBootstrapPrompt(scopeKey) {
189
+ return readBootstrapRow(scopeKey);
147
190
  }
148
191
  //# sourceMappingURL=main-session.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"main-session.js","sourceRoot":"","sources":["../../../src/core/main-session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"main-session.js","sourceRoot":"","sources":["../../../src/core/main-session.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,16 @@
1
1
  const TITLE_MAX_CHARS = 64;
2
+ /**
3
+ * 첨부 프롬프트의 머리 블록. 파일/이미지/동영상 세 변형과 다중 헤더를 모두
4
+ * 덮는다. 한 가지만 알면 나머지 변형에서 업로드 절대경로가 활동 제목으로
5
+ * 새어나간다 (devlog 260806_slack_multifile_ingest/010 D-5).
6
+ */
7
+ // 조사가 다르다: 파일"을" / 이미지"를" / 동영상"을".
8
+ const SENT_PREFIX = /^\[(?:사용자가 (?:파일을|이미지를|동영상을) 보냈습니다:[^\]]+|사용자가 파일 \d+개를 보냈습니다)\]\s*/u;
9
+ /** 다중 목록의 번호 줄(`1. [이미지] /path`)도 제목이 되면 안 된다. */
10
+ const NUMBERED_ENTRY = /^\d+\.\s+\[(?:이미지|동영상|파일)\]\s/u;
2
11
  function stripKnownPrefixes(line) {
3
12
  return line
4
- .replace(/^\[사용자가 파일을 보냈습니다:[^\]]+\]\s*/u, '')
13
+ .replace(SENT_PREFIX, '')
5
14
  .replace(/^사용자 메시지:\s*/u, '')
6
15
  .replace(/^user message:\s*/iu, '')
7
16
  .replace(/^assistant:\s*/iu, '')
@@ -30,7 +39,8 @@ export function cleanDashboardActivityTitle(input) {
30
39
  .split('\n')
31
40
  .map(line => stripMarkdown(stripKnownPrefixes(line)).replace(/\s+/g, ' ').trim())
32
41
  .filter(Boolean)
33
- .filter(line => !line.startsWith('[사용자가 파일을 보냈습니다:'))
42
+ .filter(line => !SENT_PREFIX.test(line))
43
+ .filter(line => !NUMBERED_ENTRY.test(line))
34
44
  .filter(line => !/^```/.test(line));
35
45
  return lines[0] ? clipTitle(lines[0]) : '';
36
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"message-summary.js","sourceRoot":"","sources":["../../../src/core/message-summary.ts"],"names":[],"mappings":"AAAA,MAAM,eAAe,GAAG,EAAE,CAAC;AAE3B,SAAS,kBAAkB,CAAC,IAAY;IACpC,OAAO,IAAI;SACN,OAAO,CAAC,gCAAgC,EAAE,EAAE,CAAC;SAC7C,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;SAC5B,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC;SAClC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;SAC1B,IAAI,EAAE,CAAC;AAChB,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IAC/B,OAAO,IAAI;SACN,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;SACzB,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;SACxB,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;SACpB,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;SACtB,OAAO,CAAC,kBAAkB,EAAE,IAAI,CAAC;SACjC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC;SAC7B,OAAO,CAAC,wBAAwB,EAAE,IAAI,CAAC;SACvC,IAAI,EAAE,CAAC;AAChB,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC5B,IAAI,KAAK,CAAC,MAAM,IAAI,eAAe;QAAE,OAAO,KAAK,CAAC;IAClD,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,KAAa;IACrD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;SAC5B,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;SAClB,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;SAChF,MAAM,CAAC,OAAO,CAAC;SACf,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;SACpD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACxC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,iCAAiC,CAAC,KAAoB;IAClE,MAAM,KAAK,GAAG,2BAA2B,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IACvD,OAAO,KAAK,IAAI,IAAI,CAAC;AACzB,CAAC"}
1
+ {"version":3,"file":"message-summary.js","sourceRoot":"","sources":["../../../src/core/message-summary.ts"],"names":[],"mappings":"AAAA,MAAM,eAAe,GAAG,EAAE,CAAC;AAE3B;;;;GAIG;AACH,oCAAoC;AACpC,MAAM,WAAW,GAAG,sEAAsE,CAAC;AAC3F,kDAAkD;AAClD,MAAM,cAAc,GAAG,gCAAgC,CAAC;AAExD,SAAS,kBAAkB,CAAC,IAAY;IACpC,OAAO,IAAI;SACN,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;SACxB,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;SAC5B,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC;SAClC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;SAC1B,IAAI,EAAE,CAAC;AAChB,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IAC/B,OAAO,IAAI;SACN,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;SACzB,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;SACxB,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;SACpB,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;SACtB,OAAO,CAAC,kBAAkB,EAAE,IAAI,CAAC;SACjC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC;SAC7B,OAAO,CAAC,wBAAwB,EAAE,IAAI,CAAC;SACvC,IAAI,EAAE,CAAC;AAChB,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC5B,IAAI,KAAK,CAAC,MAAM,IAAI,eAAe;QAAE,OAAO,KAAK,CAAC;IAClD,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,KAAa;IACrD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;SAC5B,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;SAClB,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;SAChF,MAAM,CAAC,OAAO,CAAC;SACf,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SACvC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SAC1C,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACxC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,iCAAiC,CAAC,KAAoB;IAClE,MAAM,KAAK,GAAG,2BAA2B,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IACvD,OAAO,KAAK,IAAI,IAAI,CAAC;AACzB,CAAC"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Canonical platform classification for cli-jaw.
3
+ *
4
+ * Single source of truth for "am I on native Windows / in WSL / on plain
5
+ * Linux". Every rule takes its inputs as parameters so the whole matrix is
6
+ * testable on one CI OS.
7
+ *
8
+ * Design rationale and primary sources:
9
+ * devlog/_plan/260805_windows_native_detection/001_platform_signal_research.md
10
+ */
11
+ import fs from 'node:fs';
12
+ import os from 'node:os';
13
+ export const defaultPlatformProbes = {
14
+ readText(path) {
15
+ try {
16
+ return fs.readFileSync(path, 'utf8');
17
+ }
18
+ catch {
19
+ return null;
20
+ }
21
+ },
22
+ exists(path) {
23
+ try {
24
+ return fs.existsSync(path);
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
+ },
30
+ release() {
31
+ try {
32
+ return os.release();
33
+ }
34
+ catch {
35
+ return '';
36
+ }
37
+ },
38
+ };
39
+ /**
40
+ * WSL markers that only ever exist inside a WSL *Linux* process.
41
+ *
42
+ * WSLENV is deliberately absent: Microsoft documents it as shared with the
43
+ * Windows host (it is what configures env-var translation across the
44
+ * boundary), so testing it misclassifies native Windows as WSL.
45
+ */
46
+ const WSL_ENV_KEYS = ['WSL_DISTRO_NAME', 'WSL_INTEROP'];
47
+ const WSL_PATH_MARKERS = ['/run/WSL', '/proc/sys/fs/binfmt_misc/WSLInterop'];
48
+ function hasWslEnvMarker(env) {
49
+ return WSL_ENV_KEYS.some((key) => !!env[key]);
50
+ }
51
+ function hasWslPathMarker(probes) {
52
+ return WSL_PATH_MARKERS.some((markerPath) => probes.exists(markerPath));
53
+ }
54
+ function hasWslKernelMarker(probes) {
55
+ // `||` not `??`: an unreadable probe returns null, but a mounted-but-empty
56
+ // /proc under a restricted container returns '', and both must fall
57
+ // through to os.release().
58
+ const osrelease = probes.readText('/proc/sys/kernel/osrelease')?.trim() || probes.release();
59
+ if (osrelease.toLowerCase().includes('microsoft'))
60
+ return true;
61
+ const version = probes.readText('/proc/version');
62
+ return !!version && version.toLowerCase().includes('microsoft');
63
+ }
64
+ export function resolvePlatformKind(platform = process.platform, env = process.env, probes = defaultPlatformProbes) {
65
+ // STRICT: a win32 process is a Win32 binary. WSL env vars leaking in from
66
+ // the host (WSLENV, or anything a user exported) can never change this.
67
+ if (platform === 'win32')
68
+ return 'windows-native';
69
+ if (platform === 'darwin')
70
+ return 'darwin';
71
+ if (platform !== 'linux')
72
+ return 'other';
73
+ if (hasWslEnvMarker(env) || hasWslPathMarker(probes) || hasWslKernelMarker(probes)) {
74
+ return 'wsl';
75
+ }
76
+ return 'linux';
77
+ }
78
+ /**
79
+ * Takes only `platform` on purpose: adding env inputs would reintroduce the
80
+ * exact class of bug this module exists to prevent.
81
+ */
82
+ export function isWindowsNative(platform = process.platform) {
83
+ return platform === 'win32';
84
+ }
85
+ export function isWsl(platform = process.platform, env = process.env, probes = defaultPlatformProbes) {
86
+ return resolvePlatformKind(platform, env, probes) === 'wsl';
87
+ }
88
+ /**
89
+ * True when a Win32 process appears to have been launched from a WSL shell,
90
+ * i.e. Windows Node running against a WSL working directory. Global npm
91
+ * installs then land on the Windows side rather than in the distro.
92
+ *
93
+ * Keyed on the working directory, not the environment. A Win32 process started
94
+ * from inside a distro has its cwd on the WSL filesystem, which Windows spells
95
+ * as the UNC prefix `\\wsl$\<distro>` or `\\wsl.localhost\<distro>`. Every
96
+ * environment variable is ambiguous here: native Windows with interop
97
+ * configured and Windows-Node-from-WSL both carry WSLENV.
98
+ *
99
+ * Both parameters are required. There is no useful default: inside an npm
100
+ * lifecycle script `process.cwd()` is the installed package root, not where
101
+ * the user ran npm. Use `resolveInvocationCwd()` to obtain the right value.
102
+ *
103
+ * This is a HEURISTIC, and weaker than resolvePlatformKind's taxonomy. Two
104
+ * known holes, both inherent to a cwd-based signal:
105
+ * - false negative: the user cd's to a Windows path (e.g. /mnt/c/src) inside
106
+ * a WSL shell before invoking npm, so the cwd is an ordinary drive path;
107
+ * - false positive: a native PowerShell session whose cwd is a \\wsl$ share.
108
+ *
109
+ * Do not describe this function as strict. The strictness guarantee belongs to
110
+ * resolvePlatformKind, which can never confuse windows-native with wsl; this
111
+ * only decides whether to print an advisory warning.
112
+ */
113
+ export function isWindowsNodeLaunchedFromWsl(platform, cwd) {
114
+ if (platform !== 'win32')
115
+ return false;
116
+ if (!cwd)
117
+ return false;
118
+ const normalized = cwd.replace(/\//g, '\\').toLowerCase();
119
+ return normalized.startsWith('\\\\wsl$\\') || normalized.startsWith('\\\\wsl.localhost\\');
120
+ }
121
+ /**
122
+ * The directory the user actually invoked the command from.
123
+ *
124
+ * npm sets INIT_CWD to the directory where `npm` was originally run, while the
125
+ * lifecycle script itself executes from the package root. Outside an npm
126
+ * lifecycle INIT_CWD is absent and process.cwd() is already correct.
127
+ */
128
+ export function resolveInvocationCwd(env = process.env) {
129
+ const initCwd = env['INIT_CWD'];
130
+ if (initCwd && initCwd.trim())
131
+ return initCwd;
132
+ try {
133
+ return process.cwd();
134
+ }
135
+ catch {
136
+ return '';
137
+ }
138
+ }
139
+ //# sourceMappingURL=platform-kind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-kind.js","sourceRoot":"","sources":["../../../src/core/platform-kind.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,156 @@
1
+ const DEFAULT_CONFIG = {
2
+ windowMs: 60_000,
3
+ budgets: {
4
+ cli: { poll: 600, mutate: 240, general: 600 },
5
+ manager: { poll: 600, mutate: 240, general: 600 },
6
+ browser: { poll: 300, mutate: 120, general: 300 },
7
+ lan: { poll: 120, mutate: 120, general: 120 },
8
+ remote: { poll: 60, mutate: 30, general: 120 },
9
+ },
10
+ nonLoopbackTotalLimit: 120,
11
+ };
12
+ const EXEMPT_PATH_PREFIXES = [
13
+ '/api/orchestrate/worker-runs',
14
+ '/api/orchestrate/worker/',
15
+ '/api/orchestrate/worker-progress',
16
+ ];
17
+ function isLoopback(ip) {
18
+ return ip === '127.0.0.1' || ip === '::1' || ip === '::ffff:127.0.0.1';
19
+ }
20
+ export function classifyClient(opts) {
21
+ // Network position is authoritative: remote headers cannot buy a loopback budget.
22
+ if (!isLoopback(opts.ip)) {
23
+ if (opts.lanAllowed && opts.isPrivateIp(opts.ip))
24
+ return 'lan';
25
+ return 'remote';
26
+ }
27
+ if (opts.authHeader === `Bearer ${opts.authToken}`)
28
+ return 'cli';
29
+ if (opts.internalHeader !== undefined)
30
+ return 'manager';
31
+ return 'browser';
32
+ }
33
+ export function classifyPath(method, path) {
34
+ const normalizedMethod = method.toUpperCase();
35
+ if (normalizedMethod !== 'GET' && normalizedMethod !== 'HEAD')
36
+ return 'mutate';
37
+ if (path === '/api/status'
38
+ || path === '/api/health'
39
+ || path === '/api/messages/latest'
40
+ || path === '/api/goal')
41
+ return 'poll';
42
+ return 'general';
43
+ }
44
+ function viewBucket(bucket, now, windowMs) {
45
+ let { windowStart, count, prevCount } = bucket;
46
+ const age = Math.max(0, now - windowStart);
47
+ if (age >= 2 * windowMs) {
48
+ windowStart += windowMs * Math.floor(age / windowMs);
49
+ count = 0;
50
+ prevCount = 0;
51
+ }
52
+ else if (age >= windowMs) {
53
+ windowStart += windowMs * Math.floor(age / windowMs);
54
+ prevCount = count;
55
+ count = 0;
56
+ }
57
+ const elapsed = Math.max(0, now - windowStart);
58
+ const previousWeight = Math.max(0, Math.min(1, 1 - elapsed / windowMs));
59
+ return { windowStart, count, prevCount, effective: count + prevCount * previousWeight };
60
+ }
61
+ function retryAfterSec(bucket, limit, now, windowMs) {
62
+ const maxSeconds = Math.ceil(2 * windowMs / 1_000) + 1;
63
+ for (let seconds = 1; seconds <= maxSeconds; seconds++) {
64
+ if (viewBucket(bucket, now + seconds * 1_000, windowMs).effective < limit)
65
+ return seconds;
66
+ }
67
+ return maxSeconds;
68
+ }
69
+ export function createRateLimiter(config = {}) {
70
+ const resolved = { ...DEFAULT_CONFIG, ...config };
71
+ const buckets = new Map();
72
+ const loggedWindows = new Map();
73
+ function check(key, cls, pathClass, now = Date.now()) {
74
+ const pathKey = `${cls}:${key}:${pathClass}`;
75
+ const specs = [{ key: pathKey, limit: resolved.budgets[cls][pathClass] }];
76
+ if (cls === 'lan' || cls === 'remote') {
77
+ specs.push({ key: `${cls}:${key}:total`, limit: resolved.nonLoopbackTotalLimit });
78
+ }
79
+ // Peek every participating bucket before committing so a rejection consumes no quota.
80
+ const views = specs.map(spec => {
81
+ const bucket = buckets.get(spec.key) ?? { windowStart: now, count: 0, prevCount: 0 };
82
+ return { ...spec, bucket, view: viewBucket(bucket, now, resolved.windowMs) };
83
+ });
84
+ const violated = views.filter(item => item.view.effective >= item.limit);
85
+ if (violated.length > 0) {
86
+ let retry = 0;
87
+ let limit = violated[0].limit;
88
+ let shouldLog = false;
89
+ for (const item of violated) {
90
+ const needed = retryAfterSec(item.bucket, item.limit, now, resolved.windowMs);
91
+ if (needed > retry) {
92
+ retry = needed;
93
+ limit = item.limit;
94
+ }
95
+ if (loggedWindows.get(item.key) !== item.view.windowStart) {
96
+ shouldLog = true;
97
+ loggedWindows.set(item.key, item.view.windowStart);
98
+ }
99
+ }
100
+ return { allowed: false, retryAfterSec: retry, limit, remaining: 0, shouldLog };
101
+ }
102
+ for (const item of views) {
103
+ buckets.set(item.key, {
104
+ windowStart: item.view.windowStart,
105
+ count: item.view.count + 1,
106
+ prevCount: item.view.prevCount,
107
+ });
108
+ }
109
+ return { allowed: true };
110
+ }
111
+ function sweep(now = Date.now()) {
112
+ for (const [key, bucket] of buckets) {
113
+ if (now - bucket.windowStart >= 2 * resolved.windowMs) {
114
+ buckets.delete(key);
115
+ loggedWindows.delete(key);
116
+ }
117
+ }
118
+ }
119
+ return { check, sweep };
120
+ }
121
+ export function createRateLimitMiddleware(opts) {
122
+ const limiter = opts.limiter ?? createRateLimiter();
123
+ return (req, res, next) => {
124
+ if (!req.path.startsWith('/api/'))
125
+ return next();
126
+ if (req.path === '/api/events')
127
+ return next();
128
+ if (EXEMPT_PATH_PREFIXES.some(prefix => req.path.startsWith(prefix)))
129
+ return next();
130
+ const ip = req.ip || req.socket?.remoteAddress || '';
131
+ const internalHeader = req.headers['x-jaw-internal'];
132
+ const cls = classifyClient({
133
+ ip,
134
+ ...(req.headers.authorization === undefined
135
+ ? {}
136
+ : { authHeader: req.headers.authorization }),
137
+ ...(internalHeader === undefined
138
+ ? {}
139
+ : { internalHeader: Array.isArray(internalHeader) ? internalHeader.join(', ') : internalHeader }),
140
+ authToken: opts.authToken,
141
+ lanAllowed: opts.lanAllowed(),
142
+ isPrivateIp: opts.isPrivateIp,
143
+ });
144
+ const decision = limiter.check(ip, cls, classifyPath(req.method, req.path));
145
+ if (decision.allowed)
146
+ return next();
147
+ res.setHeader('Retry-After', String(decision.retryAfterSec));
148
+ res.setHeader('RateLimit', `limit=${decision.limit}, remaining=${decision.remaining}, reset=${decision.retryAfterSec}`);
149
+ res.setHeader('Cache-Control', 'no-store');
150
+ if (decision.shouldLog) {
151
+ console.warn(`[rate-limit] ${ip} (${cls}) exceeded (first blocked: ${req.method} ${req.path})`);
152
+ }
153
+ return res.status(429).json({ error: 'rate_limit', retryAfterSec: decision.retryAfterSec });
154
+ };
155
+ }
156
+ //# sourceMappingURL=rate-limit.js.map