cli-jaw 2.1.1 → 2.1.3

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 (477) hide show
  1. package/README.ja.md +8 -6
  2. package/README.ko.md +8 -6
  3. package/README.md +18 -11
  4. package/README.zh-CN.md +8 -6
  5. package/dist/bin/cli-jaw.js +19 -3
  6. package/dist/bin/cli-jaw.js.map +1 -1
  7. package/dist/bin/commands/browser.js +1 -1
  8. package/dist/bin/commands/browser.js.map +1 -1
  9. package/dist/bin/commands/chat-search.js +71 -0
  10. package/dist/bin/commands/chat-search.js.map +1 -0
  11. package/dist/bin/commands/chat.js +98 -58
  12. package/dist/bin/commands/chat.js.map +1 -1
  13. package/dist/bin/commands/dispatch.js +130 -5
  14. package/dist/bin/commands/dispatch.js.map +1 -1
  15. package/dist/bin/commands/goal.js +66 -9
  16. package/dist/bin/commands/goal.js.map +1 -1
  17. package/dist/bin/commands/history.js +61 -0
  18. package/dist/bin/commands/history.js.map +1 -0
  19. package/dist/bin/commands/lock.js +104 -0
  20. package/dist/bin/commands/lock.js.map +1 -0
  21. package/dist/bin/commands/memory.js +23 -2
  22. package/dist/bin/commands/memory.js.map +1 -1
  23. package/dist/bin/commands/orchestrate.js.map +1 -1
  24. package/dist/bin/commands/project.js +4 -1
  25. package/dist/bin/commands/project.js.map +1 -1
  26. package/dist/bin/commands/tui/fullscreen-mode.js +237 -0
  27. package/dist/bin/commands/tui/fullscreen-mode.js.map +1 -0
  28. package/dist/bin/commands/tui/input-handler.js +139 -52
  29. package/dist/bin/commands/tui/input-handler.js.map +1 -1
  30. package/dist/bin/commands/tui/overlays.js +177 -70
  31. package/dist/bin/commands/tui/overlays.js.map +1 -1
  32. package/dist/bin/commands/tui/renderer.js +70 -20
  33. package/dist/bin/commands/tui/renderer.js.map +1 -1
  34. package/dist/bin/commands/tui/simple-mode.js +1 -2
  35. package/dist/bin/commands/tui/simple-mode.js.map +1 -1
  36. package/dist/bin/commands/tui/tui-io.js +8 -0
  37. package/dist/bin/commands/tui/tui-io.js.map +1 -0
  38. package/dist/bin/commands/tui/types.js +9 -0
  39. package/dist/bin/commands/tui/types.js.map +1 -1
  40. package/dist/bin/commands/tui/ws-handler.js +115 -23
  41. package/dist/bin/commands/tui/ws-handler.js.map +1 -1
  42. package/dist/bin/commands/worker.js +159 -0
  43. package/dist/bin/commands/worker.js.map +1 -0
  44. package/dist/bin/postinstall.js +0 -76
  45. package/dist/bin/postinstall.js.map +1 -1
  46. package/dist/lib/mcp/format-converters.js +21 -2
  47. package/dist/lib/mcp/format-converters.js.map +1 -1
  48. package/dist/lib/mcp/mcp-registry.js +75 -0
  49. package/dist/lib/mcp/mcp-registry.js.map +1 -0
  50. package/dist/lib/stt.js +1 -1
  51. package/dist/lib/stt.js.map +1 -1
  52. package/dist/lib/upload.js +7 -0
  53. package/dist/lib/upload.js.map +1 -1
  54. package/dist/scripts/fresh-install-smoke.js +1 -1
  55. package/dist/scripts/fresh-install-smoke.js.map +1 -1
  56. package/dist/server.js +151 -22
  57. package/dist/server.js.map +1 -1
  58. package/dist/src/agent/agy-runtime.js +1 -0
  59. package/dist/src/agent/agy-runtime.js.map +1 -1
  60. package/dist/src/agent/agy-transcript-watcher.js +78 -0
  61. package/dist/src/agent/agy-transcript-watcher.js.map +1 -0
  62. package/dist/src/agent/agy-transcript.js +158 -0
  63. package/dist/src/agent/agy-transcript.js.map +1 -0
  64. package/dist/src/agent/args.js +51 -5
  65. package/dist/src/agent/args.js.map +1 -1
  66. package/dist/src/agent/claude-e-runtime.js +1 -1
  67. package/dist/src/agent/claude-e-runtime.js.map +1 -1
  68. package/dist/src/agent/codex-app-client.js +2 -2
  69. package/dist/src/agent/codex-app-client.js.map +1 -1
  70. package/dist/src/agent/cursor-runtime.js +1 -0
  71. package/dist/src/agent/cursor-runtime.js.map +1 -1
  72. package/dist/src/agent/error-classifier.js +6 -1
  73. package/dist/src/agent/error-classifier.js.map +1 -1
  74. package/dist/src/agent/events/claude.js +1 -0
  75. package/dist/src/agent/events/claude.js.map +1 -1
  76. package/dist/src/agent/events/codex.js +0 -44
  77. package/dist/src/agent/events/codex.js.map +1 -1
  78. package/dist/src/agent/events/helpers.js +52 -5
  79. package/dist/src/agent/events/helpers.js.map +1 -1
  80. package/dist/src/agent/events/opencode.js +6 -2
  81. package/dist/src/agent/events/opencode.js.map +1 -1
  82. package/dist/src/agent/events/summary.js +3 -2
  83. package/dist/src/agent/events/summary.js.map +1 -1
  84. package/dist/src/agent/events/tool-labels.js +8 -5
  85. package/dist/src/agent/events/tool-labels.js.map +1 -1
  86. package/dist/src/agent/kiro-auth.js +213 -0
  87. package/dist/src/agent/kiro-auth.js.map +1 -0
  88. package/dist/src/agent/kiro-models.js +79 -0
  89. package/dist/src/agent/kiro-models.js.map +1 -0
  90. package/dist/src/agent/kiro-runtime.js +314 -0
  91. package/dist/src/agent/kiro-runtime.js.map +1 -0
  92. package/dist/src/agent/lifecycle-handler.js +208 -23
  93. package/dist/src/agent/lifecycle-handler.js.map +1 -1
  94. package/dist/src/agent/memory-flush-controller.js +3 -4
  95. package/dist/src/agent/memory-flush-controller.js.map +1 -1
  96. package/dist/src/agent/resume-classifier.js +18 -1
  97. package/dist/src/agent/resume-classifier.js.map +1 -1
  98. package/dist/src/agent/session-persistence.js +2 -2
  99. package/dist/src/agent/session-persistence.js.map +1 -1
  100. package/dist/src/agent/smoke-detector.js +3 -0
  101. package/dist/src/agent/smoke-detector.js.map +1 -1
  102. package/dist/src/agent/spawn/queue.js +11 -5
  103. package/dist/src/agent/spawn/queue.js.map +1 -1
  104. package/dist/src/agent/spawn/resume.js +6 -1
  105. package/dist/src/agent/spawn/resume.js.map +1 -1
  106. package/dist/src/agent/spawn-env.js +1 -1
  107. package/dist/src/agent/spawn-env.js.map +1 -1
  108. package/dist/src/agent/spawn.js +231 -43
  109. package/dist/src/agent/spawn.js.map +1 -1
  110. package/dist/src/agent/watchdog.js +1 -1
  111. package/dist/src/agent/watchdog.js.map +1 -1
  112. package/dist/src/browser/actions.js +0 -8
  113. package/dist/src/browser/actions.js.map +1 -1
  114. package/dist/src/browser/adaptive-fetch/browser-escalation.js +5 -29
  115. package/dist/src/browser/adaptive-fetch/browser-escalation.js.map +1 -1
  116. package/dist/src/browser/adaptive-fetch/browser-runtime.js +5 -14
  117. package/dist/src/browser/adaptive-fetch/browser-runtime.js.map +1 -1
  118. package/dist/src/browser/adaptive-fetch/browser-session.js +14 -28
  119. package/dist/src/browser/adaptive-fetch/browser-session.js.map +1 -1
  120. package/dist/src/browser/adaptive-fetch/challenge-detector.js +4 -26
  121. package/dist/src/browser/adaptive-fetch/challenge-detector.js.map +1 -1
  122. package/dist/src/browser/adaptive-fetch/content-scorer.js +5 -29
  123. package/dist/src/browser/adaptive-fetch/content-scorer.js.map +1 -1
  124. package/dist/src/browser/adaptive-fetch/endpoint-resolvers.js +0 -64
  125. package/dist/src/browser/adaptive-fetch/endpoint-resolvers.js.map +1 -1
  126. package/dist/src/browser/adaptive-fetch/fetcher.js +4 -19
  127. package/dist/src/browser/adaptive-fetch/fetcher.js.map +1 -1
  128. package/dist/src/browser/adaptive-fetch/human-loop.js +0 -26
  129. package/dist/src/browser/adaptive-fetch/human-loop.js.map +1 -1
  130. package/dist/src/browser/adaptive-fetch/index.js +74 -145
  131. package/dist/src/browser/adaptive-fetch/index.js.map +1 -1
  132. package/dist/src/browser/adaptive-fetch/metadata.js +1 -41
  133. package/dist/src/browser/adaptive-fetch/metadata.js.map +1 -1
  134. package/dist/src/browser/adaptive-fetch/output.js +1 -18
  135. package/dist/src/browser/adaptive-fetch/output.js.map +1 -1
  136. package/dist/src/browser/adaptive-fetch/reader-adapters.js +43 -75
  137. package/dist/src/browser/adaptive-fetch/reader-adapters.js.map +1 -1
  138. package/dist/src/browser/adaptive-fetch/safety.js +5 -48
  139. package/dist/src/browser/adaptive-fetch/safety.js.map +1 -1
  140. package/dist/src/browser/adaptive-fetch/third-party-readers.js +0 -11
  141. package/dist/src/browser/adaptive-fetch/third-party-readers.js.map +1 -1
  142. package/dist/src/browser/adaptive-fetch/trace.js +3 -18
  143. package/dist/src/browser/adaptive-fetch/trace.js.map +1 -1
  144. package/dist/src/browser/adaptive-fetch/transforms.js +0 -23
  145. package/dist/src/browser/adaptive-fetch/transforms.js.map +1 -1
  146. package/dist/src/browser/adaptive-fetch/types.js +3 -0
  147. package/dist/src/browser/adaptive-fetch/types.js.map +1 -0
  148. package/dist/src/browser/adaptive-fetch/validators.js +0 -17
  149. package/dist/src/browser/adaptive-fetch/validators.js.map +1 -1
  150. package/dist/src/browser/adaptive-fetch/waf-profiles.js +0 -10
  151. package/dist/src/browser/adaptive-fetch/waf-profiles.js.map +1 -1
  152. package/dist/src/browser/connection.js +1 -1
  153. package/dist/src/browser/connection.js.map +1 -1
  154. package/dist/src/browser/web-ai/chatgpt-response.js +0 -1
  155. package/dist/src/browser/web-ai/chatgpt-response.js.map +1 -1
  156. package/dist/src/browser/web-ai/chatgpt.js +0 -33
  157. package/dist/src/browser/web-ai/chatgpt.js.map +1 -1
  158. package/dist/src/browser/web-ai/diagnostics.js +0 -16
  159. package/dist/src/browser/web-ai/diagnostics.js.map +1 -1
  160. package/dist/src/browser/web-ai/doctor.js.map +1 -1
  161. package/dist/src/browser/web-ai/errors.js +1 -1
  162. package/dist/src/browser/web-ai/errors.js.map +1 -1
  163. package/dist/src/browser/web-ai/grok-live.js +2 -0
  164. package/dist/src/browser/web-ai/grok-live.js.map +1 -1
  165. package/dist/src/cli/claude-models.js +2 -2
  166. package/dist/src/cli/claude-models.js.map +1 -1
  167. package/dist/src/cli/command-context.js.map +1 -1
  168. package/dist/src/cli/commands.js +16 -4
  169. package/dist/src/cli/commands.js.map +1 -1
  170. package/dist/src/cli/compact.js +2 -1
  171. package/dist/src/cli/compact.js.map +1 -1
  172. package/dist/src/cli/handlers/session-handlers.js +34 -0
  173. package/dist/src/cli/handlers/session-handlers.js.map +1 -0
  174. package/dist/src/cli/handlers-project.js.map +1 -1
  175. package/dist/src/cli/handlers-runtime.js +2 -0
  176. package/dist/src/cli/handlers-runtime.js.map +1 -1
  177. package/dist/src/cli/handlers-workflows.js +85 -17
  178. package/dist/src/cli/handlers-workflows.js.map +1 -1
  179. package/dist/src/cli/handlers.js +84 -43
  180. package/dist/src/cli/handlers.js.map +1 -1
  181. package/dist/src/cli/readiness.js +17 -1
  182. package/dist/src/cli/readiness.js.map +1 -1
  183. package/dist/src/cli/registry-live.js +17 -0
  184. package/dist/src/cli/registry-live.js.map +1 -0
  185. package/dist/src/cli/registry.js +51 -10
  186. package/dist/src/cli/registry.js.map +1 -1
  187. package/dist/src/cli/tui/composer.js +135 -5
  188. package/dist/src/cli/tui/composer.js.map +1 -1
  189. package/dist/src/cli/tui/diffview.js +41 -0
  190. package/dist/src/cli/tui/diffview.js.map +1 -0
  191. package/dist/src/cli/tui/editor.js +45 -0
  192. package/dist/src/cli/tui/editor.js.map +1 -0
  193. package/dist/src/cli/tui/file-mention.js +78 -0
  194. package/dist/src/cli/tui/file-mention.js.map +1 -0
  195. package/dist/src/cli/tui/highlight.js +82 -0
  196. package/dist/src/cli/tui/highlight.js.map +1 -0
  197. package/dist/src/cli/tui/keymap.js +21 -0
  198. package/dist/src/cli/tui/keymap.js.map +1 -1
  199. package/dist/src/cli/tui/markdown.js +124 -0
  200. package/dist/src/cli/tui/markdown.js.map +1 -0
  201. package/dist/src/cli/tui/mode.js +26 -0
  202. package/dist/src/cli/tui/mode.js.map +1 -0
  203. package/dist/src/cli/tui/overlay.js +121 -98
  204. package/dist/src/cli/tui/overlay.js.map +1 -1
  205. package/dist/src/cli/tui/render/frame.js +72 -0
  206. package/dist/src/cli/tui/render/frame.js.map +1 -0
  207. package/dist/src/cli/tui/render/layout.js +22 -0
  208. package/dist/src/cli/tui/render/layout.js.map +1 -0
  209. package/dist/src/cli/tui/render/mouse.js +25 -0
  210. package/dist/src/cli/tui/render/mouse.js.map +1 -0
  211. package/dist/src/cli/tui/render/scheduler.js +37 -0
  212. package/dist/src/cli/tui/render/scheduler.js.map +1 -0
  213. package/dist/src/cli/tui/render/viewport.js +82 -0
  214. package/dist/src/cli/tui/render/viewport.js.map +1 -0
  215. package/dist/src/cli/tui/renderers.js +37 -0
  216. package/dist/src/cli/tui/renderers.js.map +1 -1
  217. package/dist/src/cli/tui/stream.js +48 -0
  218. package/dist/src/cli/tui/stream.js.map +1 -0
  219. package/dist/src/cli/tui/text-buffer.js +143 -0
  220. package/dist/src/cli/tui/text-buffer.js.map +1 -0
  221. package/dist/src/cli/tui/theme.js +128 -0
  222. package/dist/src/cli/tui/theme.js.map +1 -0
  223. package/dist/src/cli/tui/transcript.js +4 -0
  224. package/dist/src/cli/tui/transcript.js.map +1 -1
  225. package/dist/src/command-contract/help-renderer.js +1 -1
  226. package/dist/src/command-contract/help-renderer.js.map +1 -1
  227. package/dist/src/core/chat-sessions.js +63 -0
  228. package/dist/src/core/chat-sessions.js.map +1 -0
  229. package/dist/src/core/cli-detection.js +14 -0
  230. package/dist/src/core/cli-detection.js.map +1 -1
  231. package/dist/src/core/compact.js +43 -11
  232. package/dist/src/core/compact.js.map +1 -1
  233. package/dist/src/core/config.js +14 -1
  234. package/dist/src/core/config.js.map +1 -1
  235. package/dist/src/core/db.js +52 -12
  236. package/dist/src/core/db.js.map +1 -1
  237. package/dist/src/core/employees.js +2 -2
  238. package/dist/src/core/employees.js.map +1 -1
  239. package/dist/src/core/main-session.js +3 -2
  240. package/dist/src/core/main-session.js.map +1 -1
  241. package/dist/src/discord/bot.js.map +1 -1
  242. package/dist/src/discord/discord-file.js +1 -1
  243. package/dist/src/discord/discord-file.js.map +1 -1
  244. package/dist/src/discord/send-only-client.js +1 -3
  245. package/dist/src/discord/send-only-client.js.map +1 -1
  246. package/dist/src/goal/heartbeat.js +113 -7
  247. package/dist/src/goal/heartbeat.js.map +1 -1
  248. package/dist/src/goal/store.js +44 -5
  249. package/dist/src/goal/store.js.map +1 -1
  250. package/dist/src/ide/diff.js +37 -0
  251. package/dist/src/ide/diff.js.map +1 -1
  252. package/dist/src/manager/launchd-service.js +1 -1
  253. package/dist/src/manager/launchd-service.js.map +1 -1
  254. package/dist/src/manager/lifecycle-helpers.js +14 -0
  255. package/dist/src/manager/lifecycle-helpers.js.map +1 -1
  256. package/dist/src/manager/lifecycle-store.js.map +1 -1
  257. package/dist/src/manager/lifecycle.js +94 -5
  258. package/dist/src/manager/lifecycle.js.map +1 -1
  259. package/dist/src/manager/notes/routes.js +0 -31
  260. package/dist/src/manager/notes/routes.js.map +1 -1
  261. package/dist/src/manager/notes/ws.js.map +1 -1
  262. package/dist/src/manager/preview-link-policy.js +11 -4
  263. package/dist/src/manager/preview-link-policy.js.map +1 -1
  264. package/dist/src/manager/registry.js.map +1 -1
  265. package/dist/src/manager/routes/dashboard-memory.js.map +1 -1
  266. package/dist/src/manager/scan.js +36 -1
  267. package/dist/src/manager/scan.js.map +1 -1
  268. package/dist/src/manager/server.js +42 -7
  269. package/dist/src/manager/server.js.map +1 -1
  270. package/dist/src/manager/shutdown.js +8 -3
  271. package/dist/src/manager/shutdown.js.map +1 -1
  272. package/dist/src/manager/systemd-service.js +1 -1
  273. package/dist/src/manager/systemd-service.js.map +1 -1
  274. package/dist/src/memory/indexing.js +49 -1
  275. package/dist/src/memory/indexing.js.map +1 -1
  276. package/dist/src/memory/keyword-expand.js +0 -187
  277. package/dist/src/memory/keyword-expand.js.map +1 -1
  278. package/dist/src/memory/runtime.js +3 -2
  279. package/dist/src/memory/runtime.js.map +1 -1
  280. package/dist/src/memory/shared.js.map +1 -1
  281. package/dist/src/messaging/send.js +66 -7
  282. package/dist/src/messaging/send.js.map +1 -1
  283. package/dist/src/orchestrator/collect.js +3 -2
  284. package/dist/src/orchestrator/collect.js.map +1 -1
  285. package/dist/src/orchestrator/distribute.js +9 -3
  286. package/dist/src/orchestrator/distribute.js.map +1 -1
  287. package/dist/src/orchestrator/friction.js +59 -0
  288. package/dist/src/orchestrator/friction.js.map +1 -0
  289. package/dist/src/orchestrator/gateway.js +4 -4
  290. package/dist/src/orchestrator/gateway.js.map +1 -1
  291. package/dist/src/orchestrator/pipeline.js +89 -45
  292. package/dist/src/orchestrator/pipeline.js.map +1 -1
  293. package/dist/src/orchestrator/sanitize.js +69 -0
  294. package/dist/src/orchestrator/sanitize.js.map +1 -0
  295. package/dist/src/orchestrator/seed.js +50 -0
  296. package/dist/src/orchestrator/seed.js.map +1 -0
  297. package/dist/src/orchestrator/state-machine.js +215 -76
  298. package/dist/src/orchestrator/state-machine.js.map +1 -1
  299. package/dist/src/orchestrator/worker-monitor.js +1 -1
  300. package/dist/src/orchestrator/worker-monitor.js.map +1 -1
  301. package/dist/src/orchestrator/worker-progress.js +29 -0
  302. package/dist/src/orchestrator/worker-progress.js.map +1 -0
  303. package/dist/src/orchestrator/worker-registry.js +63 -2
  304. package/dist/src/orchestrator/worker-registry.js.map +1 -1
  305. package/dist/src/prompt/builder.js +190 -115
  306. package/dist/src/prompt/builder.js.map +1 -1
  307. package/dist/src/prompt/templates/a1-system.md +124 -61
  308. package/dist/src/prompt/templates/control-system.md +2 -2
  309. package/dist/src/prompt/templates/employee.md +41 -56
  310. package/dist/src/prompt/templates/orchestration.md +23 -8
  311. package/dist/src/prompt/templates/skills.md +6 -0
  312. package/dist/src/routes/browser.js +3 -3
  313. package/dist/src/routes/browser.js.map +1 -1
  314. package/dist/src/routes/employees.js +4 -4
  315. package/dist/src/routes/employees.js.map +1 -1
  316. package/dist/src/routes/goal.js +48 -4
  317. package/dist/src/routes/goal.js.map +1 -1
  318. package/dist/src/routes/heartbeat.js +1 -1
  319. package/dist/src/routes/heartbeat.js.map +1 -1
  320. package/dist/src/routes/i18n.js +1 -1
  321. package/dist/src/routes/i18n.js.map +1 -1
  322. package/dist/src/routes/jaw-memory.js +1 -1
  323. package/dist/src/routes/jaw-memory.js.map +1 -1
  324. package/dist/src/routes/memory.js.map +1 -1
  325. package/dist/src/routes/messaging.js +8 -3
  326. package/dist/src/routes/messaging.js.map +1 -1
  327. package/dist/src/routes/orchestrate.js +267 -117
  328. package/dist/src/routes/orchestrate.js.map +1 -1
  329. package/dist/src/routes/quota-agy-reverse.js +6 -5
  330. package/dist/src/routes/quota-agy-reverse.js.map +1 -1
  331. package/dist/src/routes/quota-kiro-reverse.js +187 -0
  332. package/dist/src/routes/quota-kiro-reverse.js.map +1 -0
  333. package/dist/src/routes/quota.js +68 -6
  334. package/dist/src/routes/quota.js.map +1 -1
  335. package/dist/src/routes/settings.js +37 -8
  336. package/dist/src/routes/settings.js.map +1 -1
  337. package/dist/src/routes/skills.js.map +1 -1
  338. package/dist/src/security/path-guards.js +0 -3
  339. package/dist/src/security/path-guards.js.map +1 -1
  340. package/dist/src/security/security-audit-log.js.map +1 -1
  341. package/dist/src/shared/shell-command-display.js +51 -0
  342. package/dist/src/shared/shell-command-display.js.map +1 -0
  343. package/dist/src/telegram/bot.js.map +1 -1
  344. package/dist/src/trace/store.js +32 -0
  345. package/dist/src/trace/store.js.map +1 -1
  346. package/dist/src/types/cli-engine.js +1 -0
  347. package/dist/src/types/cli-engine.js.map +1 -1
  348. package/dist/src/workflows/employee-boundary.js +7 -7
  349. package/dist/src/workflows/employee-boundary.js.map +1 -1
  350. package/dist/src/workflows/handoff.js +16 -16
  351. package/dist/src/workflows/handoff.js.map +1 -1
  352. package/dist/src/workflows/scope-sandbox.js +58 -0
  353. package/dist/src/workflows/scope-sandbox.js.map +1 -0
  354. package/package.json +1 -1
  355. package/public/assets/providers/kiro-color.svg +15 -0
  356. package/public/assets/providers/kiro.svg +14 -0
  357. package/public/css/chat.css +27 -0
  358. package/public/css/modals.css +79 -0
  359. package/public/css/orc-state.css +10 -6
  360. package/public/css/sidebar.css +85 -0
  361. package/public/css/variables.css +6 -2
  362. package/public/dist/assets/{Agent-CIUGaUVn.js → Agent-DBKNQ6tp.js} +1 -1
  363. package/public/dist/assets/{DocPanel-C1pGgE-S.js → DocPanel-BU16GUlB.js} +1 -1
  364. package/public/dist/assets/DocPanel-gU-WkgyA.css +1 -0
  365. package/public/dist/assets/Employees-F0ssNuO-.js +1 -0
  366. package/public/dist/assets/{FolderPanel-DSkanaGN.js → FolderPanel-DT0fU8f2.js} +1 -1
  367. package/public/dist/assets/Heartbeat-fsuLzY9c.js +1 -0
  368. package/public/dist/assets/Mcp-_Yq4N3Sk.js +4 -0
  369. package/public/dist/assets/{Memory-BgN8djV4.js → Memory-CRR8kotI.js} +1 -1
  370. package/public/dist/assets/{ModelProvider-DHQ1Zvw0.js → ModelProvider-DQgISbKw.js} +1 -1
  371. package/public/dist/assets/agent-meta-C4mauPL5.js +1 -0
  372. package/public/dist/assets/app-0OQhPpTG.css +1 -0
  373. package/public/dist/assets/app-CSqIyg9A.js +55 -0
  374. package/public/dist/assets/constants-BHMkzpN_.js +1 -0
  375. package/public/dist/assets/{employees-DiNLzEXS.js → employees-CZdWHH-r.js} +7 -7
  376. package/public/dist/assets/idb-cache-0LNMskFB.js +1 -0
  377. package/public/dist/assets/idb-cache-5H89a4l8.js +1 -0
  378. package/public/dist/assets/manager-CGTQ5EIm.js +12 -0
  379. package/public/dist/assets/manager-UBunDqMH.css +1 -0
  380. package/public/dist/assets/{memory-B_nn0A4v.js → memory-B3QSmj_e.js} +9 -9
  381. package/public/dist/assets/memory-DOBqiuPc.js +1 -0
  382. package/public/dist/assets/{provider-icons-XEfJPGTe.js → provider-icons-Crv6yvlG.js} +35 -6
  383. package/public/dist/assets/render-J11oxfnl.js +28 -0
  384. package/public/dist/assets/settings-BV_2Bh0_.js +1 -0
  385. package/public/dist/assets/settings-m_cim0ov.js +151 -0
  386. package/public/dist/assets/sidebar-ZBXdBgF7.js +49 -0
  387. package/public/dist/assets/{skills-COa4iSwL.js → skills-CjaBmIPV.js} +6 -6
  388. package/public/dist/assets/skills-Xm3fl1zr.js +1 -0
  389. package/public/dist/assets/{slash-commands-C_ePvrPi.js → slash-commands-71jc07Wf.js} +1 -1
  390. package/public/dist/assets/slash-commands-BO6ssnAz.js +1 -0
  391. package/public/dist/assets/{trace-drawer-CY4z_Ie8.js → trace-drawer-Czvf2P2o.js} +1 -1
  392. package/public/dist/assets/ui-CverZJnd.js +1 -0
  393. package/public/dist/assets/ui-qKxy-4p9.js +142 -0
  394. package/public/dist/index.html +113 -86
  395. package/public/dist/manager/index.html +2 -2
  396. package/public/index.html +111 -84
  397. package/public/js/constants.ts +34 -11
  398. package/public/js/features/chat-messages.ts +13 -2
  399. package/public/js/features/chat-search.ts +5 -1
  400. package/public/js/features/chat.ts +86 -44
  401. package/public/js/features/employees.ts +7 -2
  402. package/public/js/features/idb-cache.ts +4 -0
  403. package/public/js/features/media-lightbox.ts +40 -0
  404. package/public/js/features/message-history.ts +55 -7
  405. package/public/js/features/pending-queue.ts +28 -4
  406. package/public/js/features/process-block.ts +32 -17
  407. package/public/js/features/process-log-adapter.ts +11 -2
  408. package/public/js/features/settings-cli-status-render.ts +161 -0
  409. package/public/js/features/settings-cli-status.ts +136 -187
  410. package/public/js/features/settings-core.ts +5 -1
  411. package/public/js/features/settings-mcp.ts +513 -7
  412. package/public/js/features/settings-types.ts +1 -0
  413. package/public/js/features/settings.ts +1 -1
  414. package/public/js/features/tool-ui.ts +18 -4
  415. package/public/js/features/transport-status-row.ts +3 -0
  416. package/public/js/features/ui-status.ts +5 -1
  417. package/public/js/main.ts +5 -0
  418. package/public/js/preview-parent-origin.ts +14 -0
  419. package/public/js/provider-icons.ts +6 -1
  420. package/public/js/render/file-links.ts +10 -2
  421. package/public/js/render/markdown.ts +16 -0
  422. package/public/js/ui.ts +8 -1
  423. package/public/js/virtual-scroll.ts +19 -0
  424. package/public/js/ws.ts +151 -15
  425. package/public/locales/en.json +9 -2
  426. package/public/locales/ja.json +9 -2
  427. package/public/locales/ko.json +9 -2
  428. package/public/locales/zh.json +9 -2
  429. package/public/manager/src/App.tsx +13 -70
  430. package/public/manager/src/InstancePreview.tsx +56 -11
  431. package/public/manager/src/SidebarRailRouter.tsx +32 -4
  432. package/public/manager/src/components/InstanceRow.tsx +0 -1
  433. package/public/manager/src/components/WorkbenchHeader.tsx +17 -7
  434. package/public/manager/src/doc-panel/DocPanel.tsx +14 -1
  435. package/public/manager/src/doc-panel/doc-panel.css +16 -0
  436. package/public/manager/src/folder-panel/FolderPanel.tsx +13 -2
  437. package/public/manager/src/hooks/useElectronDroppedPaths.ts +89 -0
  438. package/public/manager/src/hooks/useInstanceMessageEvents.ts +4 -15
  439. package/public/manager/src/manager-components.css +35 -1
  440. package/public/manager/src/manager-polish.css +11 -1
  441. package/public/manager/src/manager-shortcut-runner.ts +107 -0
  442. package/public/manager/src/manager-shortcuts.ts +15 -0
  443. package/public/manager/src/panels/desktop-bridge.ts +13 -0
  444. package/public/manager/src/settings/SettingsSidebar.tsx +1 -1
  445. package/public/manager/src/settings/components/sidebar-filter.ts +2 -0
  446. package/public/manager/src/settings/pages/Mcp.tsx +311 -43
  447. package/public/manager/src/settings/pages/components/McpServerCard.tsx +89 -55
  448. package/public/manager/src/settings/pages/components/agent/agent-meta.ts +32 -9
  449. package/public/manager/src/settings/pages/components/employees-helpers.ts +1 -0
  450. package/public/manager/src/settings/pages/components/heartbeat-helpers.ts +1 -0
  451. package/public/manager/src/settings/pages/mcp-helpers.ts +54 -12
  452. package/public/manager/src/settings/types.ts +1 -0
  453. package/public/manager/src/types.ts +2 -1
  454. package/scripts/fresh-install-smoke.ts +1 -1
  455. package/scripts/smoke/agy-transcript-tail-smoke.mjs +89 -0
  456. package/public/dist/assets/DocPanel-CL1scIfq.css +0 -1
  457. package/public/dist/assets/Employees-BL9MAzzx.js +0 -1
  458. package/public/dist/assets/Heartbeat-D64JCg4t.js +0 -1
  459. package/public/dist/assets/Mcp-wYwJA_61.js +0 -3
  460. package/public/dist/assets/agent-meta-BhEbjy4P.js +0 -1
  461. package/public/dist/assets/app-2Rz848bQ.js +0 -48
  462. package/public/dist/assets/app-BW-Xz2p6.css +0 -1
  463. package/public/dist/assets/constants-ahKI_aEG.js +0 -1
  464. package/public/dist/assets/idb-cache-BnZfG5FD.js +0 -1
  465. package/public/dist/assets/idb-cache-CZ3JdK8r.js +0 -1
  466. package/public/dist/assets/manager-CfyZloIP.js +0 -12
  467. package/public/dist/assets/manager-DyrwJLZr.css +0 -1
  468. package/public/dist/assets/memory-CCjNFWmO.js +0 -1
  469. package/public/dist/assets/render-CgDEBoCX.js +0 -28
  470. package/public/dist/assets/settings-CY_6tGuS.js +0 -1
  471. package/public/dist/assets/settings-DWW4GzNc.js +0 -66
  472. package/public/dist/assets/sidebar-DQKE5IA1.js +0 -23
  473. package/public/dist/assets/skills-DYTlqoke.js +0 -1
  474. package/public/dist/assets/slash-commands-D7CU5oso.js +0 -1
  475. package/public/dist/assets/ui-Car1OUvV.js +0 -1
  476. package/public/dist/assets/ui-DK_9ndj0.js +0 -140
  477. /package/public/dist/assets/{locale-DT1WRaeJ.js → locale-BHMJIzyw.js} +0 -0
@@ -36,7 +36,7 @@ import { useJawCeoDashboardBridge } from './jaw-ceo/useJawCeoDashboardBridge';
36
36
  import { actionForShortcutEvent, isManagerShortcutEditableTarget } from './manager-shortcuts';
37
37
  import { reconcileActiveProfileFilter } from './profile-filter';
38
38
  import type { DashboardDetailTab, DashboardInstance, DashboardInstanceStatus, DashboardLifecycleAction, DashboardNotesAuthoringMode, DashboardNotesGraphSettings, DashboardNotesViewMode, DashboardProfile, DashboardScanResult, DashboardShortcutAction, DashboardSidebarMode } from './types';
39
- import { panelShortcutBus } from './panels/panel-shortcut-bus';
39
+ import { runManagerShortcut as runManagerShortcutAction } from './manager-shortcut-runner';
40
40
  import { getDesktop } from './panels/desktop-bridge';
41
41
  import type { PanelLayoutState } from './panels/PanelLayoutProvider';
42
42
  import { panelLayoutInitialStateFromUi, panelLayoutUiFromState } from './panels/panel-layout-registry-state';
@@ -355,75 +355,18 @@ export function App() {
355
355
  }
356
356
 
357
357
  function runManagerShortcut(action: DashboardShortcutAction): void {
358
- if (panelShortcutBus.dispatch(action)) return;
359
- if (action === 'focusInstances') {
360
- handleSidebarModeChange('instances');
361
- view.setDrawerOpen(false);
362
- return;
363
- }
364
- if (action === 'focusActiveSession') {
365
- const target = selectedInstance?.ok
366
- ? selectedInstance
367
- : filtered.find(instance => instance.ok) || null;
368
- if (target) handlePreview(target);
369
- else handleSidebarModeChange('instances');
370
- return;
371
- }
372
- if (action === 'focusNotes') {
373
- handleSidebarModeChange('notes');
374
- view.setDrawerOpen(false);
375
- return;
376
- }
377
- if (action === 'previousInstance') {
378
- selectRelativeInstance(-1);
379
- return;
380
- }
381
- if (action === 'nextInstance') {
382
- selectRelativeInstance(1);
383
- return;
384
- }
385
- if (action === 'closeFocusedTab') {
386
- const active = document.activeElement;
387
- if (active?.closest('.browser-webview-stack, .browser-tab-strip')) {
388
- document.dispatchEvent(new CustomEvent('jaw:shortcut-action', { detail: 'closeBrowserTab' }));
389
- } else if (active?.closest('.terminal-panel, .xterm')) {
390
- document.dispatchEvent(new CustomEvent('jaw:shortcut-action', { detail: 'closeTerminalTab' }));
391
- } else if (active?.closest('.bottom-panel')) {
392
- panelShortcutBus.dispatch('closeActiveBottomTab');
393
- } else if (active?.closest('.right-panel')) {
394
- panelShortcutBus.dispatch('toggleRightPanel');
395
- }
396
- return;
397
- }
398
- if (action === 'switchTab1') { handleTabChange('overview'); return; }
399
- if (action === 'switchTab2') { handleTabChange('preview'); return; }
400
- if (action === 'switchTab3') { handleTabChange('logs'); return; }
401
- if (action === 'switchTab4') { handleTabChange('settings'); return; }
402
- if (action === 'previousTab' || action === 'nextTab') {
403
- const tabs: DashboardDetailTab[] = ['overview', 'preview', 'logs', 'settings'];
404
- const idx = tabs.indexOf(view.activeDetailTab);
405
- const dir = action === 'nextTab' ? 1 : -1;
406
- handleTabChange(tabs[(idx + dir + tabs.length) % tabs.length]);
407
- return;
408
- }
409
- if (action === 'browserReload' || action === 'browserHardReload' || action === 'browserFocusUrl' || action === 'browserBack' || action === 'browserForward') {
410
- const el = document.activeElement;
411
- if (el?.closest('.browser-webview-stack, .browser-tab-strip, .browser-panel')) {
412
- document.dispatchEvent(new CustomEvent('jaw:shortcut-action', { detail: action }));
413
- }
414
- return;
415
- }
416
- if (action === 'terminalClear' || action === 'terminalNewTab') {
417
- const el = document.activeElement;
418
- if (el?.closest('.terminal-panel, .xterm')) {
419
- document.dispatchEvent(new CustomEvent('jaw:shortcut-action', { detail: action }));
420
- }
421
- return;
422
- }
423
- if (action === 'toggleLeftSidebar') {
424
- handleSidebarToggle();
425
- return;
426
- }
358
+ runManagerShortcutAction(action, {
359
+ selectedInstance,
360
+ filtered,
361
+ activeDetailTab: view.activeDetailTab,
362
+ setDrawerOpen: view.setDrawerOpen,
363
+ handleSidebarModeChange,
364
+ handlePreview,
365
+ selectRelativeInstance,
366
+ handleTabChange,
367
+ setPreviewRefreshKey,
368
+ handleSidebarToggle,
369
+ });
427
370
  }
428
371
  useEffect(() => {
429
372
  if (!view.dashboardShortcutsEnabled) return undefined;
@@ -12,6 +12,8 @@ type InstancePreviewProps = {
12
12
  refreshKey: number;
13
13
  theme: PreviewTheme;
14
14
  onOpenNotesFromPreview?: (path: string) => void;
15
+ onOpenDocFromPreview?: (absolutePath: string) => void;
16
+ onPreviewDroppedFiles?: (files: File[]) => void;
15
17
  };
16
18
 
17
19
  type PreviewOpenNotesMessage = {
@@ -25,6 +27,11 @@ type PreviewSendMessage = {
25
27
  prompt?: unknown;
26
28
  };
27
29
 
30
+ type PreviewDroppedFilesMessage = {
31
+ type?: unknown;
32
+ files?: unknown;
33
+ };
34
+
28
35
  function normalizeLoopbackHostname(hostname: string): string {
29
36
  return hostname.replace(/^\[|\]$/g, '').toLowerCase();
30
37
  }
@@ -114,6 +121,21 @@ function postPreviewSttToggle(frame: HTMLIFrameElement | null, src: string): voi
114
121
  }
115
122
  }
116
123
 
124
+ function postPreviewVisible(frame: HTMLIFrameElement | null, src: string): void {
125
+ const targetWindow = frame?.contentWindow;
126
+ if (!targetWindow) return;
127
+ const targetOrigin = previewTargetOrigin(src, frame);
128
+ if (!targetOrigin || targetOrigin === 'null') return;
129
+ try {
130
+ targetWindow.postMessage(
131
+ { type: 'jaw-preview-visibility', visible: true },
132
+ targetOrigin,
133
+ );
134
+ } catch (error) {
135
+ console.warn('[manager-preview] visibility sync skipped', error);
136
+ }
137
+ }
138
+
117
139
  function isEditableShortcutTarget(target: EventTarget | null): boolean {
118
140
  if (!(target instanceof HTMLElement)) return false;
119
141
  if (target.isContentEditable) return true;
@@ -128,6 +150,11 @@ function isPreviewSttShortcut(event: KeyboardEvent): boolean {
128
150
  return primarySpace || fallbackMic;
129
151
  }
130
152
 
153
+ function extractDroppedFiles(data: PreviewDroppedFilesMessage | null): File[] {
154
+ if (!data || data.type !== 'jaw-preview-dropped-files' || !Array.isArray(data.files)) return [];
155
+ return data.files.filter((item): item is File => item instanceof File);
156
+ }
157
+
131
158
  export function InstancePreview(props: InstancePreviewProps) {
132
159
  const iframeRef = useRef<HTMLIFrameElement | null>(null);
133
160
  const loadedSrcRef = useRef<string | null>(null);
@@ -198,11 +225,31 @@ export function InstancePreview(props: InstancePreviewProps) {
198
225
  props.onOpenNotesFromPreview?.(path);
199
226
  }
200
227
  window.addEventListener('message', onPreviewOpenNotes);
228
+ function onPreviewOpenDoc(event: MessageEvent): void {
229
+ if (event.source !== iframeRef.current?.contentWindow) return;
230
+ if (!state.src || !previewFrameOriginMatches(event.origin, state.src, iframeRef.current)) return;
231
+ const data = event.data as { type?: unknown; path?: unknown } | null;
232
+ if (!data || data.type !== 'jaw-preview-open-doc') return;
233
+ const path = typeof data.path === 'string' ? data.path.trim() : '';
234
+ if (!path) return;
235
+ props.onOpenDocFromPreview?.(path);
236
+ }
237
+ window.addEventListener('message', onPreviewOpenDoc);
238
+ function onPreviewDroppedFiles(event: MessageEvent): void {
239
+ if (event.source !== iframeRef.current?.contentWindow) return;
240
+ if (!state.src || !previewFrameOriginMatches(event.origin, state.src, iframeRef.current)) return;
241
+ const files = extractDroppedFiles(event.data as PreviewDroppedFilesMessage | null);
242
+ if (files.length === 0) return;
243
+ props.onPreviewDroppedFiles?.(files);
244
+ }
245
+ window.addEventListener('message', onPreviewDroppedFiles);
201
246
  return () => {
202
247
  window.removeEventListener('message', onPreviewSend);
203
248
  window.removeEventListener('message', onPreviewOpenNotes);
249
+ window.removeEventListener('message', onPreviewOpenDoc);
250
+ window.removeEventListener('message', onPreviewDroppedFiles);
204
251
  };
205
- }, [props.enabled, props.instance, props.onOpenNotesFromPreview, state.canPreview, state.src]);
252
+ }, [props.enabled, props.instance, props.onOpenNotesFromPreview, props.onOpenDocFromPreview, props.onPreviewDroppedFiles, state.canPreview, state.src]);
206
253
 
207
254
  useEffect(() => {
208
255
  if (!props.active || !props.enabled || !state.canPreview || !state.src) return undefined;
@@ -221,16 +268,8 @@ export function InstancePreview(props: InstancePreviewProps) {
221
268
  useEffect(() => {
222
269
  const wasActive = prevActiveRef.current;
223
270
  prevActiveRef.current = props.active;
224
- if (!wasActive && props.active && iframeRef.current?.contentWindow && state.src) {
225
- const origin = previewTargetOrigin(state.src, iframeRef.current);
226
- if (origin && origin !== 'null') {
227
- try {
228
- iframeRef.current.contentWindow.postMessage(
229
- { type: 'jaw-preview-visibility', visible: true },
230
- origin,
231
- );
232
- } catch { /* cross-origin guard */ }
233
- }
271
+ if (!wasActive && props.active && state.src) {
272
+ postPreviewVisible(iframeRef.current, state.src);
234
273
  }
235
274
  }, [props.active, state.src]);
236
275
 
@@ -250,6 +289,12 @@ export function InstancePreview(props: InstancePreviewProps) {
250
289
  onLoad={() => {
251
290
  loadedSrcRef.current = state.src;
252
291
  syncTheme();
292
+ // Every (re)mount is a fresh document. The active-tab
293
+ // effect only pings on a !wasActive→active transition, so
294
+ // an instance switch (port/key changes, active stays true)
295
+ // remounts without re-settling. Ping here so the embedded
296
+ // chat runs its jaw-preview-visibility re-settle path.
297
+ if (state.src) postPreviewVisible(iframeRef.current, state.src);
253
298
  }}
254
299
  />
255
300
  )}
@@ -1,4 +1,4 @@
1
- import { useState, type ReactNode, Suspense } from 'react';
1
+ import { useCallback, useState, type ReactNode, Suspense } from 'react';
2
2
  import { ActivityDock } from './components/ActivityDock';
3
3
  import { InstanceDrawer } from './components/InstanceDrawer';
4
4
  import { InstanceNavigator } from './components/InstanceNavigator';
@@ -31,6 +31,12 @@ import { DashboardScheduleWorkspace } from './dashboard-schedule/DashboardSchedu
31
31
  import { DashboardRemindersSidebar, type RemindersView } from './dashboard-reminders/DashboardRemindersSidebar';
32
32
  import { DashboardRemindersWorkspace } from './dashboard-reminders/DashboardRemindersWorkspace';
33
33
  import { useRemindersFeed } from './dashboard-reminders/useRemindersFeed';
34
+ import {
35
+ firstDirectory,
36
+ firstFile,
37
+ useElectronDroppedPaths,
38
+ type ElectronDroppedPathsEvent,
39
+ } from './hooks/useElectronDroppedPaths';
34
40
  import type { HelpTopicId } from './help/helpContent';
35
41
  import { NotesCommandPalette } from './notes/NotesCommandPalette';
36
42
  import { NotesCommandProvider } from './notes/notes-command-registry';
@@ -140,6 +146,7 @@ type Props = {
140
146
  function renderRightPanelContent(
141
147
  mode: RightPanelMode,
142
148
  previewFilePath: string | null,
149
+ folderRootPath: string | null,
143
150
  onPreviewFile: (path: string) => void,
144
151
  selectedInstance: DashboardInstance | null,
145
152
  dashboardSettingsUi: DashboardRegistryUi,
@@ -149,7 +156,7 @@ function renderRightPanelContent(
149
156
  const fallback = <div style={{ padding: '12px', color: 'var(--text-dim)', fontSize: '12px' }}>Loading...</div>;
150
157
  switch (mode) {
151
158
  case 'diff': return <Suspense fallback={fallback}><DiffPanel selectedInstance={selectedInstance} settings={dashboardSettingsUi} onSettingsPatch={onDashboardSettingsPatch} /></Suspense>;
152
- case 'folder': return <Suspense fallback={fallback}><FolderPanel selectedFilePath={previewFilePath} notesTree={notesModel.tree} notesRoot={notesModel.notesRoot} onPreviewFile={onPreviewFile} /></Suspense>;
159
+ case 'folder': return <Suspense fallback={fallback}><FolderPanel selectedFilePath={previewFilePath} externalRootPath={folderRootPath} notesTree={notesModel.tree} notesRoot={notesModel.notesRoot} onPreviewFile={onPreviewFile} /></Suspense>;
153
160
  case 'doc': return <Suspense fallback={fallback}><DocPanel filePath={previewFilePath ?? undefined} /></Suspense>;
154
161
  case 'browser': return <Suspense fallback={fallback}><BrowserPanel /></Suspense>;
155
162
  default: return null;
@@ -168,6 +175,8 @@ function renderBottomTabContent(tab: BottomPanelTab, controls: BottomPanelRender
168
175
  export function SidebarRailRouter(props: Props) {
169
176
  const panelLayout = usePanelLayout();
170
177
  const [rightPreviewFilePath, setRightPreviewFilePath] = useState<string | null>(null);
178
+ const [rightFolderRootPath, setRightFolderRootPath] = useState<string | null>(null);
179
+ const [, setRecentDroppedPaths] = useState<ElectronDroppedPathsEvent | null>(null);
171
180
  const [remindersView, setRemindersView] = useState<RemindersView>('matrix');
172
181
  const remindersFeed = useRemindersFeed({ active: props.sidebarMode === 'reminders' });
173
182
  const desktopPanelsAvailable = currentManagerSurface() === 'electron';
@@ -184,6 +193,25 @@ export function SidebarRailRouter(props: Props) {
184
193
  panelLayout.dispatch({ type: 'OPEN_RIGHT_PANEL', mode: 'doc', slot: 'bottom' });
185
194
  }
186
195
 
196
+ const handleDroppedPaths = useCallback((event: ElectronDroppedPathsEvent): void => {
197
+ setRecentDroppedPaths(event);
198
+ if (event.source === 'preview') return;
199
+ const directory = firstDirectory(event.entries);
200
+ if (directory) {
201
+ setRightFolderRootPath(directory.path);
202
+ panelLayout.dispatch({ type: 'OPEN_RIGHT_PANEL', mode: 'folder', slot: 'top' });
203
+ return;
204
+ }
205
+ const file = firstFile(event.entries);
206
+ if (file) handleRightPreviewFile(file.path);
207
+ }, [panelLayout]);
208
+
209
+ const electronDrop = useElectronDroppedPaths({ onDroppedPaths: handleDroppedPaths });
210
+
211
+ const handlePreviewDroppedFiles = useCallback((files: File[]): void => {
212
+ void electronDrop.resolveDroppedFiles(files, 'preview');
213
+ }, [electronDrop]);
214
+
187
215
  return (
188
216
  <NotesCommandProvider>
189
217
  {props.jawCeoVoiceOverlay}
@@ -195,7 +223,7 @@ export function SidebarRailRouter(props: Props) {
195
223
  onCloseDrawer={props.onCloseDrawer}
196
224
  rightPanelOpen={rightPanelOpen}
197
225
  rightPanelWidth={panelLayout.state.rightPanel.width}
198
- rightPanelContent={rightPanelOpen ? <RightSidebar renderPanel={mode => renderRightPanelContent(mode, rightPreviewFilePath, handleRightPreviewFile, props.selectedInstance, props.dashboardSettingsUi, props.onDashboardSettingsPatch, props.notesModel)} /> : undefined}
226
+ rightPanelContent={rightPanelOpen ? <RightSidebar renderPanel={mode => renderRightPanelContent(mode, rightPreviewFilePath, rightFolderRootPath, handleRightPreviewFile, props.selectedInstance, props.dashboardSettingsUi, props.onDashboardSettingsPatch, props.notesModel)} /> : undefined}
199
227
  bottomPanelOpen={bottomPanelOpen}
200
228
  bottomPanelHeight={panelLayout.state.bottomPanel.height}
201
229
  bottomPanelContent={bottomPanelOpen && panelLayout.state.bottomPanel.tabs.length > 0 ? <BottomPanel renderTab={renderBottomTabContent} /> : undefined}
@@ -243,7 +271,7 @@ export function SidebarRailRouter(props: Props) {
243
271
  <div className="workspace-surface-layer">
244
272
  <WorkspaceSurface active={props.sidebarMode === 'instances'}>
245
273
  <Workbench mode={props.activeDetailTab} onModeChange={props.onDetailTabChange} header={props.workbenchHeader} modeActions={props.jawCeoWorkbenchButton} overview={props.detailContent('overview')} preview={(
246
- <InstancePreview instance={props.selectedInstance} data={props.data} enabled={props.previewEnabled} active={props.sidebarMode === 'instances' && props.activeDetailTab === 'preview'} refreshKey={props.previewRefreshKey} theme={props.previewTheme} {...(props.onOpenNotesFromPreview ? { onOpenNotesFromPreview: props.onOpenNotesFromPreview } : {})} />
274
+ <InstancePreview instance={props.selectedInstance} data={props.data} enabled={props.previewEnabled} active={props.sidebarMode === 'instances' && props.activeDetailTab === 'preview'} refreshKey={props.previewRefreshKey} theme={props.previewTheme} {...(props.onOpenNotesFromPreview ? { onOpenNotesFromPreview: props.onOpenNotesFromPreview } : {})} onOpenDocFromPreview={handleRightPreviewFile} onPreviewDroppedFiles={handlePreviewDroppedFiles} />
247
275
  )} logs={props.detailContent('logs')} settings={props.detailContent('settings')} />
248
276
  </WorkspaceSurface>
249
277
  <WorkspaceSurface active={props.sidebarMode === 'notes'}>
@@ -67,7 +67,6 @@ export function InstanceRow(props: InstanceRowProps) {
67
67
  const transitionLabel = props.transitioning ? TRANSITION_LABELS[props.transitioning] : null;
68
68
  const dotClass = `${statusClass(props.instance.status)}${transitionLabel ? ' is-transitioning' : ''}${props.agentBusy ? ' is-busy' : ''}`;
69
69
  const primaryLabel = props.instance.label || props.profile?.label || props.label;
70
-
71
70
  async function submitLabel(event: FormEvent<HTMLFormElement>): Promise<void> {
72
71
  event.preventDefault();
73
72
  event.stopPropagation();
@@ -11,27 +11,37 @@ type WorkbenchHeaderProps = {
11
11
  onOpenHelpTopic?: (topic: HelpTopicId) => void;
12
12
  };
13
13
 
14
+ function compactPath(path: string): string {
15
+ const parts = path.split(/[/\\]/).filter(Boolean);
16
+ if (parts.length <= 2) return path;
17
+ return `…/${parts.slice(-2).join('/')}`;
18
+ }
19
+
14
20
  export function WorkbenchHeader(props: WorkbenchHeaderProps) {
15
21
  const instance = props.instance;
16
22
  const canPreview = Boolean(instance?.ok);
17
23
  const previewLabel = props.previewEnabled ? 'Preview on' : 'Preview off';
18
24
  const hasActions = Boolean(instance || props.onOpenHelpTopic);
25
+ const projectDirs = instance?.projectDirs?.filter(Boolean) ?? [];
19
26
 
20
27
  return (
21
28
  <div className="detail-header">
22
29
  <div>
23
30
  <p className="eyebrow">Selected instance</p>
24
31
  <h2>{instance ? instanceLabel(instance) : 'No instance selected'}</h2>
25
- <span>{instance?.workingDir || instance?.url || 'Select an online instance to inspect it.'}</span>
26
- {instance?.projectDirs && instance.projectDirs.length > 0 && (
27
- <div className="project-dirs">
28
- <span className="label">Projects:</span>
29
- {instance.projectDirs.map((dir, i) => (
32
+ {instance ? (
33
+ <div className={`project-dirs${projectDirs.length ? '' : ' is-empty'}`}>
34
+ <span className="label">Project</span>
35
+ {projectDirs.length ? projectDirs.map((dir, i) => (
30
36
  <span key={i} className="project-dir" title={dir}>
31
- {dir.split(/[/\\]/).slice(-2).join('/')}
37
+ {compactPath(dir)}
32
38
  </span>
33
- ))}
39
+ )) : (
40
+ <span className="project-dir">Not set</span>
41
+ )}
34
42
  </div>
43
+ ) : (
44
+ <span>Select an online instance to inspect it.</span>
35
45
  )}
36
46
  </div>
37
47
  {hasActions && (
@@ -103,7 +103,20 @@ export function DocPanel(props: { filePath?: string | undefined }) {
103
103
  return (
104
104
  <div className="doc-panel">
105
105
  <div className="doc-toolbar">
106
- <span className="doc-file-name">{props.filePath.split('/').pop()}</span>
106
+ <span className="doc-file-name" title={props.filePath}>{props.filePath.split('/').pop()}</span>
107
+ <button
108
+ type="button"
109
+ className="doc-copy-path"
110
+ title="Copy full path"
111
+ onClick={() => {
112
+ void navigator.clipboard.writeText(props.filePath!).then(() => {
113
+ const btn = document.querySelector('.doc-copy-path');
114
+ if (btn) { btn.textContent = 'Copied'; setTimeout(() => { btn.textContent = 'Path'; }, 1200); }
115
+ });
116
+ }}
117
+ >
118
+ Path
119
+ </button>
107
120
  </div>
108
121
  <div className="doc-content">
109
122
  <DocContent filePath={props.filePath} content={content} />
@@ -30,6 +30,22 @@
30
30
  overflow: hidden;
31
31
  text-overflow: ellipsis;
32
32
  white-space: nowrap;
33
+ flex: 1;
34
+ }
35
+ .doc-copy-path {
36
+ font-size: 10px;
37
+ padding: 1px 6px;
38
+ border: 1px solid var(--border-subtle);
39
+ border-radius: 3px;
40
+ background: transparent;
41
+ color: var(--text-dim);
42
+ cursor: pointer;
43
+ flex-shrink: 0;
44
+ margin-left: 6px;
45
+ }
46
+ .doc-copy-path:hover {
47
+ background: var(--border-subtle);
48
+ color: var(--text-base);
33
49
  }
34
50
  .doc-content {
35
51
  flex: 1;
@@ -10,6 +10,7 @@ function getFolderBridge(): FolderBridgeApi | null {
10
10
 
11
11
  type FolderPanelProps = {
12
12
  selectedFilePath?: string | null | undefined;
13
+ externalRootPath?: string | null | undefined;
13
14
  notesTree?: NotesTreeEntry[] | undefined;
14
15
  notesRoot?: string | null | undefined;
15
16
  onPreviewFile?: ((path: string) => void) | undefined;
@@ -73,7 +74,7 @@ export function FolderPanel(props: FolderPanelProps) {
73
74
  }, [loadDir, rootPath, source]);
74
75
 
75
76
  useEffect(() => {
76
- if (rootPath !== null) return;
77
+ if (rootPath !== null || props.externalRootPath) return;
77
78
  let cancelled = false;
78
79
  void (async () => {
79
80
  const nextRoot = await source.getDefaultRoot();
@@ -82,7 +83,17 @@ export function FolderPanel(props: FolderPanelProps) {
82
83
  await loadDir(nextRoot);
83
84
  })();
84
85
  return () => { cancelled = true; };
85
- }, [loadDir, rootPath, source]);
86
+ }, [loadDir, props.externalRootPath, rootPath, source]);
87
+
88
+ useEffect(() => {
89
+ const externalRoot = props.externalRootPath;
90
+ if (!externalRoot || externalRoot === rootPath) return;
91
+ if (rootPath && source.unwatchDir) void source.unwatchDir(rootPath);
92
+ setRootPath(externalRoot);
93
+ setExpanded(new Set());
94
+ setChildrenCache(new Map());
95
+ void loadDir(externalRoot);
96
+ }, [loadDir, props.externalRootPath, rootPath, source]);
86
97
 
87
98
  useEffect(() => {
88
99
  if (!source.watchDir || !source.onDirChange || rootPath === null) return;
@@ -0,0 +1,89 @@
1
+ import { useCallback, useEffect } from 'react';
2
+ import { getDesktop, isElectron, type DroppedPathEntry } from '../panels/desktop-bridge';
3
+
4
+ export type ElectronDroppedPathsSource = 'manager' | 'preview';
5
+
6
+ export type ElectronDroppedPathsEvent = {
7
+ source: ElectronDroppedPathsSource;
8
+ entries: DroppedPathEntry[];
9
+ };
10
+
11
+ type UseElectronDroppedPathsOptions = {
12
+ onDroppedPaths: (event: ElectronDroppedPathsEvent) => void;
13
+ };
14
+
15
+ type ClosestTarget = {
16
+ closest: (selector: string) => Element | null;
17
+ };
18
+
19
+ export function isPreviewDropTarget(target: EventTarget | null): boolean {
20
+ const maybeElement = target as Partial<ClosestTarget> | null;
21
+ if (typeof maybeElement?.closest !== 'function') return false;
22
+ return Boolean(maybeElement.closest('.preview-panel, .preview-frame'));
23
+ }
24
+
25
+ export function shouldConsumeManagerDrop(target: EventTarget | null): boolean {
26
+ return !isPreviewDropTarget(target);
27
+ }
28
+
29
+ export function firstDirectory(entries: DroppedPathEntry[]): DroppedPathEntry | null {
30
+ return entries.find(entry => entry.kind === 'directory') ?? null;
31
+ }
32
+
33
+ export function firstFile(entries: DroppedPathEntry[]): DroppedPathEntry | null {
34
+ return entries.find(entry => entry.kind === 'file') ?? null;
35
+ }
36
+
37
+ function hasFileTransfer(dataTransfer: DataTransfer | null): boolean {
38
+ if (!dataTransfer) return false;
39
+ if (dataTransfer.files.length > 0) return true;
40
+ return Array.from(dataTransfer.types).includes('Files');
41
+ }
42
+
43
+ export function useElectronDroppedPaths(options: UseElectronDroppedPathsOptions): {
44
+ resolveDroppedFiles: (files: File[], source: ElectronDroppedPathsSource) => Promise<DroppedPathEntry[]>;
45
+ } {
46
+ const resolveDroppedFiles = useCallback(async (files: File[], source: ElectronDroppedPathsSource): Promise<DroppedPathEntry[]> => {
47
+ const bridge = getDesktop()?.dragDrop;
48
+ if (!bridge || files.length === 0) return [];
49
+ try {
50
+ const result = await bridge.resolveDroppedItems(files);
51
+ const entries = result.ok && result.entries ? result.entries : [];
52
+ if (entries.length > 0) options.onDroppedPaths({ source, entries });
53
+ return entries;
54
+ } catch (error) {
55
+ console.warn('[electron-drop] failed to resolve dropped files', error);
56
+ return [];
57
+ }
58
+ }, [options]);
59
+
60
+ useEffect(() => {
61
+ if (!isElectron() || !getDesktop()?.dragDrop) return undefined;
62
+
63
+ function onDragOver(event: DragEvent): void {
64
+ const dataTransfer = event.dataTransfer;
65
+ if (!dataTransfer || !hasFileTransfer(dataTransfer)) return;
66
+ if (!shouldConsumeManagerDrop(event.target)) return;
67
+ event.preventDefault();
68
+ dataTransfer.dropEffect = 'copy';
69
+ }
70
+
71
+ function onDrop(event: DragEvent): void {
72
+ const files = event.dataTransfer?.files ? Array.from(event.dataTransfer.files) : [];
73
+ if (files.length === 0) return;
74
+ if (!shouldConsumeManagerDrop(event.target)) return;
75
+ event.preventDefault();
76
+ event.stopPropagation();
77
+ void resolveDroppedFiles(files, 'manager');
78
+ }
79
+
80
+ document.addEventListener('dragover', onDragOver, true);
81
+ document.addEventListener('drop', onDrop, true);
82
+ return () => {
83
+ document.removeEventListener('dragover', onDragOver, true);
84
+ document.removeEventListener('drop', onDrop, true);
85
+ };
86
+ }, [resolveDroppedFiles]);
87
+
88
+ return { resolveDroppedFiles };
89
+ }
@@ -57,20 +57,9 @@ function titleSupportFromEnvelope(data: MessageEnvelope['data']): DashboardActiv
57
57
  return 'activity' in data || 'latestAssistant' in data ? 'ready' : 'legacy';
58
58
  }
59
59
 
60
- const BUSY_STALE_MS = 2 * 60 * 60_000;
61
-
62
- function parseUtcTimestamp(raw: string): number {
63
- const iso = raw.includes('T') ? raw : raw.replace(' ', 'T');
64
- return Date.parse(iso.endsWith('Z') ? iso : iso + 'Z');
65
- }
66
-
67
- function isActivityBusy(data: MessageEnvelope['data']): boolean {
68
- if (!data || !('activity' in data)) return false;
69
- const activity = data.activity;
70
- if (!activity || activity.role !== 'user') return false;
71
- const updatedAt = parseUtcTimestamp(activity.updatedAt);
72
- if (Number.isNaN(updatedAt)) return false;
73
- return Date.now() - updatedAt < BUSY_STALE_MS;
60
+ function isProcessBusy(data: MessageEnvelope['data']): boolean {
61
+ if (!data || typeof data !== 'object') return false;
62
+ return 'processBusy' in data && data.processBusy === true;
74
63
  }
75
64
 
76
65
  async function fetchLatestAssistantMessage(port: number): Promise<{
@@ -86,7 +75,7 @@ async function fetchLatestAssistantMessage(port: number): Promise<{
86
75
  latest: notifiableAssistantFromEnvelope(body.data),
87
76
  title: activityTitleFromEnvelope(body.data),
88
77
  support: titleSupportFromEnvelope(body.data),
89
- busy: isActivityBusy(body.data),
78
+ busy: isProcessBusy(body.data),
90
79
  };
91
80
  }
92
81
 
@@ -87,7 +87,7 @@ h2 { font-size: 13px; }
87
87
  .command-actions { justify-self: end; }
88
88
  .is-electron-titlebar {
89
89
  -webkit-app-region: drag;
90
- padding-left: 80px;
90
+ padding-left: 96px;
91
91
  }
92
92
  .is-electron-titlebar button,
93
93
  .is-electron-titlebar input,
@@ -499,6 +499,40 @@ h2 { font-size: 13px; }
499
499
  text-overflow: ellipsis;
500
500
  white-space: nowrap;
501
501
  }
502
+ .project-dirs {
503
+ display: flex;
504
+ flex-wrap: wrap;
505
+ min-width: 0;
506
+ max-width: min(100%, 520px);
507
+ align-items: center;
508
+ gap: 5px;
509
+ margin-top: 2px;
510
+ overflow: hidden;
511
+ }
512
+ .project-dirs .label {
513
+ flex: 0 0 auto;
514
+ color: var(--text-muted);
515
+ font-size: 11px;
516
+ font-weight: 650;
517
+ }
518
+ .project-dir {
519
+ min-width: 0;
520
+ flex: 0 1 220px;
521
+ max-width: 220px;
522
+ border: 1px solid var(--border-subtle);
523
+ border-radius: 6px;
524
+ background: var(--canvas-mid);
525
+ padding: 2px 6px;
526
+ color: var(--text-secondary);
527
+ font-family: "Geist Mono", "JetBrains Mono", monospace;
528
+ font-size: 11px;
529
+ }
530
+ .project-dirs.is-empty .project-dir {
531
+ border-style: dashed;
532
+ background: transparent;
533
+ color: var(--text-muted);
534
+ font-family: inherit;
535
+ }
502
536
  .detail-tabs {
503
537
  display: flex;
504
538
  gap: 3px;
@@ -55,7 +55,7 @@
55
55
  padding: 6px 10px;
56
56
  }
57
57
  .command-bar.is-electron-titlebar {
58
- padding-left: 80px;
58
+ padding-left: 96px;
59
59
  }
60
60
 
61
61
  .command-primary {
@@ -133,6 +133,16 @@
133
133
  font-size: 12px;
134
134
  }
135
135
 
136
+ .workbench-preview .project-dirs {
137
+ margin-top: 1px;
138
+ gap: 4px;
139
+ }
140
+
141
+ .workbench-preview .project-dir {
142
+ max-width: 180px;
143
+ padding: 1px 5px;
144
+ }
145
+
136
146
  .workbench-preview .workbench-mode-tabs button {
137
147
  min-height: 24px;
138
148
  padding: 3px 8px;