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
@@ -1,17 +1,10 @@
1
- // Phase 8 — single MCP server card. The MCP page composes a list of these
2
- // over the `servers` map returned by `/api/mcp`. Pure presentation; the
3
- // parent owns the canonical server map and the dirty entry.
4
- //
5
- // The shape is defensive: `args` may be missing on legacy entries (treated
6
- // as `[]`), `env` may be missing or null. We only persist back a clean
7
- // `McpServer` so loadUnifiedMcp/saveUnifiedMcp round-trip stays stable.
8
-
9
1
  import type { McpServer } from '../mcp-helpers';
10
2
  import {
11
3
  formatArgsText,
12
4
  formatEnvText,
13
5
  parseArgsText,
14
6
  parseEnvText,
7
+ getServerTag,
15
8
  } from '../mcp-helpers';
16
9
 
17
10
  type Props = {
@@ -34,6 +27,9 @@ export function McpServerCard({
34
27
  const id = `mcp-${name || 'unnamed'}`;
35
28
  const argsText = formatArgsText(server.args);
36
29
  const envText = formatEnvText(server.env);
30
+ const headersText = formatEnvText(server.headers);
31
+ const tag = getServerTag(server);
32
+ const isRemote = tag === 'remote';
37
33
 
38
34
  return (
39
35
  <article className="mcp-server-card" aria-label={`MCP server ${name || '(unnamed)'}`}>
@@ -55,57 +51,95 @@ export function McpServerCard({
55
51
  </span>
56
52
  ) : null}
57
53
  </label>
58
- <button
59
- type="button"
60
- className="settings-action settings-action-discard"
61
- onClick={onRemove}
62
- aria-label={`Remove ${name || 'server'}`}
63
- >
64
- Remove
65
- </button>
54
+ <div className="mcp-server-card-actions">
55
+ {tag ? (
56
+ <span className="mcp-server-tag" data-tag={tag}>[{tag}]</span>
57
+ ) : null}
58
+ <button
59
+ type="button"
60
+ className="settings-action settings-action-discard"
61
+ onClick={onRemove}
62
+ aria-label={`Remove ${name || 'server'}`}
63
+ >
64
+ Remove
65
+ </button>
66
+ </div>
66
67
  </header>
67
68
 
68
- <label className="settings-field settings-field-text" htmlFor={`${id}-command`}>
69
- <span className="settings-field-label">Command</span>
70
- <input
71
- id={`${id}-command`}
72
- type="text"
73
- value={server.command || ''}
74
- placeholder="npx"
75
- spellCheck={false}
76
- onChange={(event) =>
77
- onChange({ ...server, command: event.target.value })
78
- }
79
- />
80
- </label>
69
+ {isRemote ? (
70
+ <>
71
+ <label className="settings-field settings-field-text" htmlFor={`${id}-url`}>
72
+ <span className="settings-field-label">URL</span>
73
+ <input
74
+ id={`${id}-url`}
75
+ type="text"
76
+ value={server.url || ''}
77
+ placeholder="https://mcp.example.com/sse"
78
+ spellCheck={false}
79
+ onChange={(event) =>
80
+ onChange({ ...server, url: event.target.value })
81
+ }
82
+ />
83
+ </label>
81
84
 
82
- <label className="settings-field settings-field-text" htmlFor={`${id}-args`}>
83
- <span className="settings-field-label">
84
- Args (one per line, or comma-separated)
85
- </span>
86
- <textarea
87
- id={`${id}-args`}
88
- value={argsText}
89
- rows={3}
90
- spellCheck={false}
91
- onChange={(event) =>
92
- onChange({ ...server, args: parseArgsText(event.target.value) })
93
- }
94
- />
95
- </label>
85
+ <label className="settings-field settings-field-text" htmlFor={`${id}-headers`}>
86
+ <span className="settings-field-label">Headers (KEY=value per line)</span>
87
+ <textarea
88
+ id={`${id}-headers`}
89
+ value={headersText}
90
+ rows={3}
91
+ spellCheck={false}
92
+ onChange={(event) =>
93
+ onChange({ ...server, headers: parseEnvText(event.target.value) })
94
+ }
95
+ />
96
+ </label>
97
+ </>
98
+ ) : (
99
+ <>
100
+ <label className="settings-field settings-field-text" htmlFor={`${id}-command`}>
101
+ <span className="settings-field-label">Command</span>
102
+ <input
103
+ id={`${id}-command`}
104
+ type="text"
105
+ value={server.command || ''}
106
+ placeholder="npx"
107
+ spellCheck={false}
108
+ onChange={(event) =>
109
+ onChange({ ...server, command: event.target.value })
110
+ }
111
+ />
112
+ </label>
96
113
 
97
- <label className="settings-field settings-field-text" htmlFor={`${id}-env`}>
98
- <span className="settings-field-label">Env (KEY=value per line)</span>
99
- <textarea
100
- id={`${id}-env`}
101
- value={envText}
102
- rows={3}
103
- spellCheck={false}
104
- onChange={(event) =>
105
- onChange({ ...server, env: parseEnvText(event.target.value) })
106
- }
107
- />
108
- </label>
114
+ <label className="settings-field settings-field-text" htmlFor={`${id}-args`}>
115
+ <span className="settings-field-label">
116
+ Args (one per line, or comma-separated)
117
+ </span>
118
+ <textarea
119
+ id={`${id}-args`}
120
+ value={argsText}
121
+ rows={3}
122
+ spellCheck={false}
123
+ onChange={(event) =>
124
+ onChange({ ...server, args: parseArgsText(event.target.value) })
125
+ }
126
+ />
127
+ </label>
128
+
129
+ <label className="settings-field settings-field-text" htmlFor={`${id}-env`}>
130
+ <span className="settings-field-label">Env (KEY=value per line)</span>
131
+ <textarea
132
+ id={`${id}-env`}
133
+ value={envText}
134
+ rows={3}
135
+ spellCheck={false}
136
+ onChange={(event) =>
137
+ onChange({ ...server, env: parseEnvText(event.target.value) })
138
+ }
139
+ />
140
+ </label>
141
+ </>
142
+ )}
109
143
 
110
144
  <label className="settings-field settings-field-toggle" htmlFor={`${id}-autostart`}>
111
145
  <input
@@ -25,7 +25,7 @@ export type ActiveOverride = {
25
25
  effort?: string;
26
26
  };
27
27
 
28
- export const PRIMARY_CLIS: ReadonlyArray<string> = ['claude', 'claude-e', 'agy', 'codex', 'cursor', 'gemini'];
28
+ export const PRIMARY_CLIS: ReadonlyArray<string> = ['claude', 'claude-e', 'agy', 'codex', 'cursor', 'kiro-code', 'gemini'];
29
29
 
30
30
  export const CLI_META: Record<string, CliMeta> = {
31
31
  agy: {
@@ -37,15 +37,16 @@ export const CLI_META: Record<string, CliMeta> = {
37
37
  'ai-e': {
38
38
  label: 'AI-E',
39
39
  defaultProvider: 'claude',
40
- providers: ['claude', 'codex', 'gemini', 'grok', 'copilot'],
41
- models: ['opus', 'sonnet', 'haiku', 'gpt-5.4', 'gpt-5.4-mini', 'gemini-3-flash-preview', 'grok-build', 'gpt-5-mini'],
40
+ providers: ['claude', 'codex', 'gemini', 'grok', 'copilot', 'kiro'],
41
+ models: ['opus', 'sonnet', 'haiku', 'gpt-5.5', 'gpt-5.4', 'gpt-5.4-mini', 'gemini-3-flash-preview', 'grok-build', 'grok-composer-2.5-fast', 'gpt-5-mini'],
42
42
  efforts: ['low', 'medium', 'high', 'xhigh', 'max'],
43
43
  modelsByProvider: {
44
- claude: ['opus', 'sonnet', 'haiku'],
45
- codex: ['gpt-5.4', 'gpt-5.4-mini'],
44
+ claude: ['claude-opus-4-8', 'opus', 'sonnet', 'haiku'],
45
+ codex: ['gpt-5.5', 'gpt-5.4', 'gpt-5.4-mini'],
46
46
  gemini: ['gemini-3-flash-preview'],
47
- grok: ['grok-build'],
47
+ grok: ['grok-build', 'grok-composer-2.5-fast'],
48
48
  copilot: ['gpt-5-mini'],
49
+ kiro: ['auto', 'claude-sonnet-4.6', 'deepseek-3.2', 'minimax-m2.5', 'glm-5', 'qwen3-coder-next'],
49
50
  },
50
51
  effortsByProvider: {
51
52
  claude: ['low', 'medium', 'high', 'xhigh', 'max'],
@@ -53,6 +54,7 @@ export const CLI_META: Record<string, CliMeta> = {
53
54
  gemini: [],
54
55
  grok: [],
55
56
  copilot: ['low', 'medium', 'high'],
57
+ kiro: [],
56
58
  },
57
59
  },
58
60
  claude: {
@@ -62,7 +64,7 @@ export const CLI_META: Record<string, CliMeta> = {
62
64
  // firstPartyNameToCanonical resolution; pinned IDs reach the API
63
65
  // verbatim for stable prompt-cache prefixes. The `[1m]` suffix is
64
66
  // parsed by Claude Code (stripped before send, enables 1M context
65
- // on Opus 4.7/4.6 + Sonnet 4.6). Mirrors getDefaultClaudeChoices()
67
+ // on Opus 4.8/4.7/4.6 + Sonnet 4.6). Mirrors getDefaultClaudeChoices()
66
68
  // in src/cli/claude-models.ts. Verified via Grok web research
67
69
  // 2026-05-01 (devlog/_plan/260501_claude_model_passthrough/).
68
70
  models: [
@@ -117,6 +119,27 @@ export const CLI_META: Record<string, CliMeta> = {
117
119
  efforts: ['none', 'none-fast', 'low', 'low-fast', 'medium', 'medium-fast', 'high', 'high-fast', 'xhigh', 'xhigh-fast', 'max', 'max-fast'],
118
120
  effortNote: 'Cursor effort resolves to model IDs; no separate --effort flag',
119
121
  },
122
+ 'kiro-code': {
123
+ label: 'Kiro',
124
+ models: [
125
+ 'auto',
126
+ 'claude-opus-4.8',
127
+ 'claude-opus-4.7',
128
+ 'claude-opus-4.6',
129
+ 'claude-sonnet-4.6',
130
+ 'claude-opus-4.5',
131
+ 'claude-sonnet-4.5',
132
+ 'claude-sonnet-4',
133
+ 'claude-haiku-4.5',
134
+ 'deepseek-3.2',
135
+ 'minimax-m2.5',
136
+ 'minimax-m2.1',
137
+ 'glm-5',
138
+ 'qwen3-coder-next',
139
+ ],
140
+ efforts: [],
141
+ effortNote: 'Kiro CLI has no separate effort flag',
142
+ },
120
143
  gemini: {
121
144
  label: 'Gemini',
122
145
  models: ['gemini-3-pro-preview', 'gemini-2.5-pro', 'gemini-3-flash-preview'],
@@ -124,9 +147,9 @@ export const CLI_META: Record<string, CliMeta> = {
124
147
  },
125
148
  grok: {
126
149
  label: 'Grok',
127
- models: ['grok-build'],
150
+ models: ['grok-build', 'grok-composer-2.5-fast'],
128
151
  efforts: [],
129
- effortNote: 'unsupported by grok-build; do not pass --effort',
152
+ effortNote: 'unsupported by grok-build/composer; do not pass --effort',
130
153
  },
131
154
  opencode: {
132
155
  label: 'OpenCode',
@@ -19,6 +19,7 @@ export const DEFAULT_CLI_OPTIONS = [
19
19
  'codex-app',
20
20
  'copilot',
21
21
  'cursor',
22
+ 'kiro-code',
22
23
  'gemini',
23
24
  'grok',
24
25
  'opencode',
@@ -21,6 +21,7 @@ export const TARGET_FALLBACK = [
21
21
  'codex-app',
22
22
  'copilot',
23
23
  'cursor',
24
+ 'kiro-code',
24
25
  'gemini',
25
26
  'grok',
26
27
  'opencode',
@@ -7,9 +7,11 @@
7
7
  // silently drop fields the runtime added later (e.g. `disabledServers`).
8
8
 
9
9
  export type McpServer = {
10
- command: string;
10
+ command?: string;
11
11
  args?: string[];
12
12
  env?: Record<string, string>;
13
+ url?: string;
14
+ headers?: Record<string, string>;
13
15
  autostart?: boolean;
14
16
  [key: string]: unknown;
15
17
  };
@@ -44,9 +46,10 @@ export function normalizeMcpConfig(raw: unknown): McpConfig {
44
46
  }
45
47
 
46
48
  export function normalizeServer(raw: unknown): McpServer {
47
- if (!raw || typeof raw !== 'object') return { command: '' };
49
+ if (!raw || typeof raw !== 'object') return {};
48
50
  const r = raw as Record<string, unknown>;
49
- const command = typeof r['command'] === 'string' ? r['command'] : '';
51
+ const command = typeof r['command'] === 'string' && r['command'] ? r['command'] : undefined;
52
+ const url = typeof r['url'] === 'string' && r['url'] ? r['url'] : undefined;
50
53
  const args = Array.isArray(r['args'])
51
54
  ? r['args'].filter((v): v is string => typeof v === 'string')
52
55
  : undefined;
@@ -59,21 +62,32 @@ export function normalizeServer(raw: unknown): McpServer {
59
62
  ),
60
63
  )
61
64
  : undefined;
65
+ const headers =
66
+ r['headers'] && typeof r['headers'] === 'object' && !Array.isArray(r['headers'])
67
+ ? Object.fromEntries(
68
+ Object.entries(r['headers'] as Record<string, unknown>).filter(
69
+ (entry): entry is [string, string] =>
70
+ typeof entry[1] === 'string',
71
+ ),
72
+ )
73
+ : undefined;
62
74
  const autostart = typeof r['autostart'] === 'boolean' ? r['autostart'] : undefined;
63
- const out: McpServer = { command };
75
+ const out: McpServer = {};
76
+ if (command) out.command = command;
77
+ if (url) out.url = url;
64
78
  if (args && args.length > 0) out.args = args;
65
79
  if (env && Object.keys(env).length > 0) out.env = env;
80
+ if (headers && Object.keys(headers).length > 0) out.headers = headers;
66
81
  if (autostart !== undefined) out.autostart = autostart;
67
- // Preserve any unknown extras so the runtime can keep evolving the schema.
68
82
  for (const [k, v] of Object.entries(r)) {
69
- if (k === 'command' || k === 'args' || k === 'env' || k === 'autostart') continue;
83
+ if (['command', 'url', 'args', 'env', 'headers', 'autostart'].includes(k)) continue;
70
84
  out[k] = v;
71
85
  }
72
86
  return out;
73
87
  }
74
88
 
75
- export function makeEmptyServer(): McpServer {
76
- return { command: '' };
89
+ export function makeEmptyServer(type: 'local' | 'remote' = 'local'): McpServer {
90
+ return type === 'remote' ? { url: '' } : { command: '' };
77
91
  }
78
92
 
79
93
  // Args round-tripping: prefer one-arg-per-line. We accept comma-separated
@@ -136,12 +150,35 @@ export function validateServer(name: string, server: McpServer): ServerValidatio
136
150
  reason: 'Server name must match [a-zA-Z0-9._-] (1–64 chars).',
137
151
  };
138
152
  }
139
- if (!server.command || server.command.trim() === '') {
140
- return { kind: 'invalid', reason: 'Command is required.' };
153
+ const hasCommand = server.command && server.command.trim() !== '';
154
+ const hasUrl = server.url && String(server.url).trim() !== '';
155
+ if (!hasCommand && !hasUrl) {
156
+ return { kind: 'invalid', reason: 'Command or URL is required.' };
141
157
  }
142
158
  return { kind: 'ok' };
143
159
  }
144
160
 
161
+ export type ServerTag = 'npx' | 'uvx' | 'docker' | 'remote' | null;
162
+
163
+ export function getServerTag(server: McpServer): ServerTag {
164
+ if (server.url) return 'remote';
165
+ if (!server.command) return null;
166
+ const cmd = server.command;
167
+ if (cmd === 'npx' || cmd.endsWith('/npx')) return 'npx';
168
+ if (cmd === 'uvx' || cmd === 'uv' || cmd.endsWith('/uvx')) return 'uvx';
169
+ if (cmd === 'docker' || cmd.endsWith('/docker')) return 'docker';
170
+ return null;
171
+ }
172
+
173
+ export function countInstallBundleCandidates(
174
+ servers: Record<string, McpServer>,
175
+ ): number {
176
+ return Object.values(servers).filter(s => {
177
+ if (!s.command) return false;
178
+ return s.command === 'npx' || s.command === 'uv' || s.command === 'uvx';
179
+ }).length;
180
+ }
181
+
145
182
  export function findDuplicateNames(
146
183
  names: ReadonlyArray<string>,
147
184
  ): Set<string> {
@@ -163,14 +200,19 @@ export function findDuplicateNames(
163
200
  export function toPersistShape(config: McpConfig): McpConfig {
164
201
  const servers: Record<string, McpServer> = {};
165
202
  for (const [name, srv] of Object.entries(config.servers)) {
166
- const out: McpServer = { command: srv.command };
203
+ const out: McpServer = {};
204
+ if (srv.command) out.command = srv.command;
205
+ if (srv.url) out.url = srv.url;
167
206
  if (srv.args && srv.args.length > 0) out.args = [...srv.args];
168
207
  if (srv.env && Object.keys(srv.env).length > 0) {
169
208
  out.env = { ...srv.env };
170
209
  }
210
+ if (srv.headers && Object.keys(srv.headers).length > 0) {
211
+ out.headers = { ...srv.headers };
212
+ }
171
213
  if (srv.autostart !== undefined) out.autostart = srv.autostart;
172
214
  for (const [k, v] of Object.entries(srv)) {
173
- if (k === 'command' || k === 'args' || k === 'env' || k === 'autostart') continue;
215
+ if (['command', 'url', 'args', 'env', 'headers', 'autostart'].includes(k)) continue;
174
216
  out[k] = v;
175
217
  }
176
218
  servers[name] = out;
@@ -22,6 +22,7 @@ export type SettingsCategoryId =
22
22
  export type SettingsCategoryGroup =
23
23
  | 'runtime'
24
24
  | 'identity'
25
+ | 'mcp'
25
26
  | 'channels'
26
27
  | 'automation'
27
28
  | 'integrations'
@@ -7,7 +7,7 @@ export type DashboardInstanceStatus =
7
7
 
8
8
  export type DashboardServiceMode = 'unknown' | 'ad-hoc' | 'service' | 'manager';
9
9
  export type DashboardLifecycleAction = 'start' | 'stop' | 'restart' | 'perm' | 'unperm';
10
- export type DashboardLifecycleOwner = 'none' | 'external' | 'manager' | 'service';
10
+ export type DashboardLifecycleOwner = 'none' | 'external' | 'manager' | 'service' | 'peer';
11
11
  export type DashboardDetailTab = 'overview' | 'preview' | 'logs' | 'settings';
12
12
  export type DashboardUiTheme = 'auto' | 'dark' | 'light';
13
13
  export type DashboardLocale = 'ko' | 'en' | 'zh' | 'ja';
@@ -230,6 +230,7 @@ export type InstanceLatestMessageSummary = {
230
230
  title: string;
231
231
  updatedAt: string;
232
232
  } | null;
233
+ processBusy?: boolean;
233
234
  };
234
235
 
235
236
  export type HealthEvent = {
@@ -176,7 +176,7 @@ async function main(): Promise<void> {
176
176
  if (!cliRes.ok) throw new Error(`/api/cli-status HTTP ${cliRes.status}`);
177
177
  const cliJson = (await cliRes.json()) as Record<string, unknown> | null;
178
178
  const keys = Object.keys(cliJson ?? {});
179
- const required: string[] = ['ai-e', 'claude', 'claude-e', 'codex', 'codex-app', 'copilot', 'cursor', 'gemini', 'grok', 'opencode'];
179
+ const required: string[] = ['ai-e', 'claude', 'claude-e', 'codex', 'codex-app', 'copilot', 'cursor', 'kiro-code', 'gemini', 'grok', 'opencode'];
180
180
  for (const k of required) {
181
181
  if (!keys.includes(k)) throw new Error(`missing cli key in status: ${k}`);
182
182
  }
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Smoke: resolve AGY brain transcript path + tail-parse new JSONL lines.
4
+ * Does not invoke agy (live tool steps require cascade; -p smokes often skip RUN_COMMAND).
5
+ */
6
+ import fs from 'node:fs';
7
+ import os from 'node:os';
8
+ import path from 'node:path';
9
+
10
+ const HOME = os.homedir();
11
+ const CACHE = path.join(HOME, '.gemini', 'antigravity-cli', 'cache', 'last_conversations.json');
12
+ const BRAIN = path.join(HOME, '.gemini', 'antigravity-cli', 'brain');
13
+
14
+ function resolveTranscriptPath(cwd) {
15
+ const map = JSON.parse(fs.readFileSync(CACHE, 'utf8'));
16
+ const uuid = map[cwd];
17
+ if (!uuid) return { ok: false, reason: 'no uuid in last_conversations.json for cwd' };
18
+ const transcript = path.join(BRAIN, uuid, '.system_generated', 'logs', 'transcript.jsonl');
19
+ if (!fs.existsSync(transcript)) return { ok: false, uuid, reason: 'transcript.jsonl missing' };
20
+ return { ok: true, uuid, transcript };
21
+ }
22
+
23
+ function parseStepLine(line) {
24
+ const d = JSON.parse(line);
25
+ const type = d.type;
26
+ const toolTypes = new Set(['RUN_COMMAND', 'VIEW_FILE', 'LIST_DIRECTORY', 'GREP_SEARCH', 'READ_FILE', 'WRITE_FILE']);
27
+ if (!toolTypes.has(type) && type !== 'PLANNER_RESPONSE') return null;
28
+ const label = type === 'PLANNER_RESPONSE' ? 'planner' : type.replace(/_/g, ' ').toLowerCase();
29
+ return { step_index: d.step_index, type, status: d.status, label };
30
+ }
31
+
32
+ function tailOnce(transcript, offset) {
33
+ const stat = fs.statSync(transcript);
34
+ if (stat.size <= offset) return { offset, events: [] };
35
+ const buf = Buffer.alloc(stat.size - offset);
36
+ const fd = fs.openSync(transcript, 'r');
37
+ fs.readSync(fd, buf, 0, buf.length, offset);
38
+ fs.closeSync(fd);
39
+ const text = buf.toString('utf8');
40
+ const events = [];
41
+ for (const line of text.split('\n')) {
42
+ if (!line.trim()) continue;
43
+ try {
44
+ const ev = parseStepLine(line);
45
+ if (ev) events.push(ev);
46
+ } catch {
47
+ /* skip malformed */
48
+ }
49
+ }
50
+ return { offset: stat.size, events };
51
+ }
52
+
53
+ function histogram(transcript) {
54
+ const counts = {};
55
+ for (const line of fs.readFileSync(transcript, 'utf8').split('\n')) {
56
+ if (!line.trim()) continue;
57
+ try {
58
+ const t = JSON.parse(line).type;
59
+ counts[t] = (counts[t] || 0) + 1;
60
+ } catch { /* */ }
61
+ }
62
+ return counts;
63
+ }
64
+
65
+ const cwd = process.argv[2] || process.cwd();
66
+ const resolved = resolveTranscriptPath(cwd);
67
+ console.log(JSON.stringify({ phase: 'resolve', cwd, ...resolved }, null, 2));
68
+ if (!resolved.ok) process.exit(1);
69
+
70
+ const hist = histogram(resolved.transcript);
71
+ console.log(JSON.stringify({ phase: 'histogram', types: hist }, null, 2));
72
+
73
+ let offset = 0;
74
+ const first = tailOnce(resolved.transcript, offset);
75
+ offset = first.offset;
76
+ console.log(JSON.stringify({ phase: 'tail_baseline', offset, parsed_events: first.events.length }, null, 2));
77
+
78
+ const hasRun = (hist.RUN_COMMAND || 0) > 0;
79
+ console.log(JSON.stringify({
80
+ phase: 'verdict',
81
+ path_resolves: true,
82
+ tail_parser_runs: true,
83
+ corpus_has_RUN_COMMAND: hasRun,
84
+ note: hasRun
85
+ ? 'Transcript tail is viable for jaw Stage 1 when conversation uuid is known.'
86
+ : 'This conversation has no RUN_COMMAND yet; use a cwd with tool-heavy history or resume cascade session.',
87
+ }, null, 2));
88
+
89
+ process.exit(hasRun ? 0 : 2);
@@ -1 +0,0 @@
1
- .doc-panel{flex-direction:column;min-width:0;height:100%;min-height:0;font-size:12px;display:flex;overflow:hidden}.doc-unavailable,.doc-empty,.doc-error,.doc-binary{color:var(--text-dim);justify-content:center;align-items:center;padding:12px;font-size:11px;display:flex}.doc-error{color:var(--status-error)}.doc-toolbar{border-bottom:1px solid var(--border-subtle);flex-shrink:0;align-items:center;padding:6px 10px;display:flex}.doc-file-name{color:var(--text-base);text-overflow:ellipsis;white-space:nowrap;font-size:11px;font-weight:500;overflow:hidden}.doc-content{flex:1;min-height:0;overflow:auto}.doc-pre{white-space:pre-wrap;word-break:break-all;margin:0;padding:8px 10px;font-family:SF Mono,Menlo,monospace;font-size:12px;line-height:1.5}.doc-markdown{padding:12px 16px}.doc-content .notes-code-block{border-radius:0;margin:0}.doc-content .notes-code-block pre{max-height:none}
@@ -1 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-XQCOJYun.js";import{n as t,t as n}from"./jsx-runtime-BZmCptaP.js";import{i as r}from"./page-shell-k5-hYhKb.js";var i=e(t(),1),a=n(),o=[`employees`],s=[`ai-e`,`claude`,`claude-e`,`codex`,`codex-app`,`copilot`,`cursor`,`gemini`,`grok`,`opencode`],c=0;function l(){return c+=1,`emp_${Date.now().toString(36)}_${c}`}function u(){let e=globalThis.crypto;if(e&&typeof e.randomUUID==`function`)try{return e.randomUUID()}catch{}return l()}function d(e=u()){return{id:e,name:``,cli:`claude`,role:``,prompt:``,active:!0}}function f(e){if(!Array.isArray(e))return[];let t=[],n=0;for(let r of e){if(typeof r==`string`){n+=1,t.push({...d(`emp_legacy_${n}`),name:r});continue}if(!r||typeof r!=`object`)continue;let e=r,i=typeof e.name==`string`?e.name:``;if(!i&&!e.id)continue;n+=1;let a=typeof e.id==`string`&&e.id.trim()?e.id.trim():`emp_unknown_${n}`,o=typeof e.cli==`string`&&e.cli.trim()?e.cli.trim():`claude`,s=typeof e.role==`string`?e.role:``,c=typeof e.prompt==`string`?e.prompt:``,l=e.active!==!1;t.push({id:a,name:i,cli:o,role:s,prompt:c,active:l})}return t}function p(e){return e.name.trim()?e.cli.trim()?null:`CLI is required`:`Name is required`}function m(e){return e.some(e=>p(e)!==null)}function h(e){let t=new Map;for(let n of e){let e=n.name.trim().toLowerCase();e&&t.set(e,(t.get(e)??0)+1)}let n=new Set;for(let[e,r]of t)r>1&&n.add(e);return n}function g(e){return e.map(e=>{let t={id:e.id,name:e.name.trim(),cli:e.cli.trim()||`claude`,role:e.role.trim(),active:e.active};return e.prompt.trim()&&(t.prompt=e.prompt),t})}function _({registerSave:e}){return(0,i.useEffect)(()=>{if(e)return e(null),()=>e(null)},[e]),(0,a.jsx)(`form`,{className:`settings-page-form`,onSubmit:e=>e.preventDefault(),children:(0,a.jsx)(r,{title:`Employees`,hint:`Runtime employees are now managed from the Agent page.`,children:(0,a.jsx)(`p`,{className:`settings-section-hint`,children:`Open Runtime / Agent to edit dispatchable employees, static employee model overrides, and database-backed employees in one place.`})})})}export{s as DEFAULT_CLI_OPTIONS,o as EMPLOYEE_KEYS,_ as default,h as duplicateNameSet,p as employeeRowError,m as employeesHaveErrors,d as makeDefaultEmployee,u as newEmployeeId,f as normalizeEmployees,g as toPersistShape};
@@ -1 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-XQCOJYun.js";import{n as t,t as n}from"./jsx-runtime-BZmCptaP.js";import{a as r,i,n as a,r as o,t as s}from"./page-shell-k5-hYhKb.js";import{a as c,i as l,s as u}from"./fields-C-y_8RgA.js";import{n as d}from"./agent-meta-BhEbjy4P.js";import{t as f}from"./path-utils-ztBHV7MX.js";var p=e(t(),1),m=n(),h=[{value:`every`,label:`every (interval)`},{value:`cron`,label:`cron expression`}];function g({job:e,index:t,bodyError:n,timeZoneError:r,onChange:i,onRemove:a}){let o=(0,p.useId)(),s=e.schedule.kind,d=e.schedule.timeZone??``;return(0,m.jsxs)(`fieldset`,{className:`settings-heartbeat-job`,"aria-label":`Heartbeat job ${t+1}${e.name?` (${e.name})`:``}`,children:[(0,m.jsx)(`legend`,{className:`settings-heartbeat-job-legend`,children:e.name||`Job ${t+1}`}),(0,m.jsx)(c,{id:`${o}-enabled`,label:`Enabled`,value:e.enabled,onChange:e=>i({enabled:e})}),(0,m.jsx)(u,{id:`${o}-name`,label:`Name`,value:e.name,placeholder:`Morning summary`,onChange:e=>i({name:e})}),(0,m.jsx)(l,{id:`${o}-kind`,label:`Schedule kind`,value:s,options:h,onChange:e=>{e===`every`&&s!==`every`?i({schedule:{kind:`every`,minutes:30,...d?{timeZone:d}:{}}}):e===`cron`&&s!==`cron`&&i({schedule:{kind:`cron`,cron:`0 9 * * *`,...d?{timeZone:d}:{}}})}}),s===`every`?(0,m.jsx)(u,{id:`${o}-minutes`,label:`Every (minutes)`,value:String(e.schedule.minutes??``),placeholder:`30`,error:n??null,onChange:e=>{let t=e.trim(),n=Number(t);i({schedule:{kind:`every`,minutes:Number.isFinite(n)?n:NaN,...d?{timeZone:d}:{}}})}}):(0,m.jsx)(u,{id:`${o}-cron`,label:`Cron expression`,value:e.schedule.cron??``,placeholder:`0 9 * * *`,error:n??null,onChange:e=>i({schedule:{kind:`cron`,cron:e,...d?{timeZone:d}:{}}})}),(0,m.jsx)(u,{id:`${o}-tz`,label:`Time zone (optional)`,value:d,placeholder:`Asia/Seoul`,error:r??null,onChange:t=>{let n=t.trim();i(s===`every`?{schedule:{kind:`every`,minutes:e.schedule.minutes,...n?{timeZone:n}:{}}}:{schedule:{kind:`cron`,cron:e.schedule.cron,...n?{timeZone:n}:{}}})}}),(0,m.jsxs)(`label`,{className:`settings-field settings-field-textarea`,htmlFor:`${o}-prompt`,children:[(0,m.jsx)(`span`,{className:`settings-field-label`,children:`Prompt`}),(0,m.jsx)(`textarea`,{id:`${o}-prompt`,rows:3,value:e.prompt,placeholder:`What should this heartbeat do?`,onChange:e=>i({prompt:e.target.value})})]}),(0,m.jsx)(`div`,{className:`settings-heartbeat-job-footer`,children:(0,m.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,onClick:a,children:`Remove job`})})]})}var _=/^\d+[smh]$/,v=/^([01]\d|2[0-3]):[0-5]\d$/,y=[`ai-e`,`claude`,`claude-e`,`codex`,`codex-app`,`copilot`,`cursor`,`gemini`,`grok`,`opencode`],b=[`heartbeat.enabled`,`heartbeat.every`,`heartbeat.activeHours.start`,`heartbeat.activeHours.end`,`heartbeat.target`],x=[`heartbeat.jobs`,`heartbeat.md`];function S(e){return _.test(e.trim())}function C(e){return v.test(e.trim())}function w(e=Date.now()){return{id:`hb_${e}`,name:``,enabled:!0,schedule:{kind:`every`,minutes:30},prompt:``}}function T(e){return e.startsWith(`heartbeat.`)&&e!==`heartbeat.jobs`&&e!==`heartbeat.md`}function E(e,t){if(!e||typeof e!=`object`)return null;let n=e,r=typeof n.id==`string`&&n.id.trim()?n.id.trim():`hb_unknown_${t}`,i=typeof n.name==`string`?n.name:``,a=n.enabled!==!1,o=typeof n.prompt==`string`?n.prompt:``,s=n.schedule,c;if(s&&typeof s==`object`){let e=s;c=e.kind===`cron`&&typeof e.cron==`string`?{kind:`cron`,cron:e.cron,...typeof e.timeZone==`string`&&e.timeZone?{timeZone:e.timeZone}:{}}:{kind:`every`,minutes:typeof e.minutes==`number`?e.minutes:30,...typeof e.timeZone==`string`&&e.timeZone?{timeZone:e.timeZone}:{}}}else c={kind:`every`,minutes:30};return{id:r,name:i,enabled:a,schedule:c,prompt:o}}function D(e){if(!e||typeof e!=`object`)return[];let t=e.jobs;return Array.isArray(t)?t.map((e,t)=>E(e,t)).filter(e=>e!==null):[]}function O(e){if(e.kind===`every`){let t=e.minutes;return!Number.isFinite(t)||t<=0||!Number.isInteger(t)?`Minutes must be a positive integer`:null}let t=e.cron?.trim()??``;return t?t.split(/\s+/).length<5?`Cron must have at least 5 fields`:null:`Cron expression required`}function k(e){return e.some(e=>O(e.schedule)!==null)}function A({port:e,client:t,dirty:n,snapshot:r}){let[i,a]=(0,p.useState)([]),[c,l]=(0,p.useState)([]),[u,d]=(0,p.useState)(!1),[f,h]=(0,p.useState)(null);(0,p.useEffect)(()=>{if(r.kind!==`ready`)return;let e=D(r.data);a(e),l(e)},[r]),(0,p.useEffect)(()=>{n.set(`heartbeat.jobs`,{value:i,original:c,valid:!k(i)})},[i,c,n]),(0,p.useEffect)(()=>()=>{n.remove(`heartbeat.jobs`)},[n]);let _=(0,p.useCallback)(async()=>{if(k(i)){h(`Fix invalid schedules before saving.`);return}d(!0),h(null);try{let e=D(await t.put(`/api/heartbeat`,{jobs:i}));a(e),l(e),n.remove(`heartbeat.jobs`)}catch(e){h(e instanceof Error?e.message:String(e))}finally{d(!1)}},[t,n,i]);if(r.kind===`loading`)return(0,m.jsx)(`p`,{className:`settings-section-hint`,children:`Loading jobs…`});if(r.kind===`offline`)return(0,m.jsx)(o,{port:e});if(r.kind===`error`)return(0,m.jsx)(s,{message:r.message});let v=n.pending.has(`heartbeat.jobs`),y=k(i);function b(e,t){a(n=>n.map((n,r)=>r===e?{...n,...t}:n))}function x(){a(e=>[...e,w()])}function S(e){a(t=>t.filter((t,n)=>n!==e))}return(0,m.jsxs)(m.Fragment,{children:[i.length===0?(0,m.jsx)(`p`,{className:`settings-section-hint`,children:`No jobs configured. Add one below.`}):(0,m.jsx)(`div`,{className:`settings-heartbeat-jobs-list`,children:i.map((e,t)=>(0,m.jsx)(g,{job:e,index:t,bodyError:O(e.schedule),onChange:e=>b(t,e),onRemove:()=>S(t)},e.id))}),(0,m.jsxs)(`div`,{className:`settings-heartbeat-jobs-footer`,children:[(0,m.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,onClick:x,children:`+ Add job`}),(0,m.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,onClick:()=>void _(),disabled:u||!v||y,children:u?`Saving…`:`Apply jobs`})]}),f?(0,m.jsx)(`p`,{className:`settings-field-error`,role:`alert`,children:f}):null]})}function j({port:e,client:t,dirty:n,snapshot:r}){let[i,a]=(0,p.useState)(``),[c,l]=(0,p.useState)(``),[u,d]=(0,p.useState)(!1),[f,h]=(0,p.useState)(null);(0,p.useEffect)(()=>{if(r.kind!==`ready`)return;let e=r.data.content??``;a(e),l(e)},[r]),(0,p.useEffect)(()=>{n.set(`heartbeat.md`,{value:i,original:c,valid:!0})},[i,c,n]),(0,p.useEffect)(()=>()=>{n.remove(`heartbeat.md`)},[n]);let g=(0,p.useCallback)(async()=>{d(!0),h(null);try{await t.put(`/api/heartbeat-md`,{content:i}),l(i),n.remove(`heartbeat.md`)}catch(e){h(e instanceof Error?e.message:String(e))}finally{d(!1)}},[t,n,i]);if(r.kind===`loading`)return(0,m.jsx)(`p`,{className:`settings-section-hint`,children:`Loading template…`});if(r.kind===`offline`)return(0,m.jsx)(o,{port:e});if(r.kind===`error`)return(0,m.jsx)(s,{message:r.message});let _=n.pending.has(`heartbeat.md`);return(0,m.jsxs)(m.Fragment,{children:[(0,m.jsxs)(`label`,{className:`settings-field settings-field-textarea`,htmlFor:`hb-md`,children:[(0,m.jsx)(`span`,{className:`settings-field-label`,children:`Template`}),(0,m.jsx)(`textarea`,{id:`hb-md`,rows:10,spellCheck:!1,value:i,onChange:e=>a(e.target.value),style:{fontFamily:`ui-monospace, monospace`}})]}),(0,m.jsx)(`div`,{className:`settings-heartbeat-md-footer`,children:(0,m.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,onClick:()=>void g(),disabled:u||!_,children:u?`Saving…`:`Save template`})}),f?(0,m.jsx)(`p`,{className:`settings-field-error`,role:`alert`,children:f}):null]})}function M({port:e,client:t,dirty:n,registerSave:h}){let g=r(t,`/api/settings`),_=r(t,`/api/heartbeat`),v=r(t,`/api/heartbeat-md`),[x,w]=(0,p.useState)(!1),[E,D]=(0,p.useState)(`30m`),[O,k]=(0,p.useState)(`08:00`),[M,N]=(0,p.useState)(`22:00`),[P,F]=(0,p.useState)(`all`);(0,p.useEffect)(()=>{if(g.state.kind!==`ready`)return;let e=g.state.data.heartbeat||{};w(!!e.enabled),D(typeof e.every==`string`?e.every:`30m`),k(e.activeHours?.start??`08:00`),N(e.activeHours?.end??`22:00`),F(typeof e.target==`string`?e.target:`all`)},[g.state]),(0,p.useEffect)(()=>()=>{for(let e of b)n.remove(e)},[n]);let I=(0,p.useMemo)(()=>g.state.kind===`ready`&&g.state.data.heartbeat||{},[g.state]),L=(0,p.useCallback)((e,t)=>n.set(e,t),[n]),R=(0,p.useRef)(0),z=(0,p.useCallback)(async()=>{let e=n.saveBundle(),r={};for(let[t,n]of Object.entries(e))T(t)&&(r[t]=n);if(Object.keys(r).length===0)return;let i=++R.current,a=f(r),o=await t.put(`/api/settings`,a);if(i!==R.current)return;let s=o&&typeof o==`object`&&`data`in o?o.data:o;for(let e of b)n.remove(e);g.setData(s);let c=s.heartbeat||{};w(!!c.enabled),D(typeof c.every==`string`?c.every:`30m`),k(c.activeHours?.start??`08:00`),N(c.activeHours?.end??`22:00`),F(typeof c.target==`string`?c.target:`all`),await g.refresh()},[t,n,g]);if((0,p.useEffect)(()=>{if(h)return h(z),()=>h(null)},[h,z]),g.state.kind===`loading`)return(0,m.jsx)(a,{});if(g.state.kind===`offline`)return(0,m.jsx)(o,{port:e});if(g.state.kind===`error`)return(0,m.jsx)(s,{message:g.state.message});let B=S(E)?null:"Use the form `<n>s|m|h`, e.g. `30m`",V=C(O)?null:`Use HH:MM (24h)`,H=C(M)?null:`Use HH:MM (24h)`,U=g.state.data.perCli||{},W=Object.keys(U),G=[{value:`all`,label:`all (broadcast)`},...(W.length>0?W:[...y]).map(e=>({value:e,label:d(e).label||e}))];return G.some(e=>e.value===P)||G.push({value:P,label:`${d(P).label||P} (legacy)`}),(0,m.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault(),z()},children:[(0,m.jsxs)(i,{title:`Heartbeat`,hint:`Background prompts the agent runs on a schedule.`,children:[(0,m.jsx)(c,{id:`hb-enabled`,label:`Heartbeat enabled`,value:x,onChange:e=>{w(e),L(`heartbeat.enabled`,{value:e,original:!!I.enabled,valid:!0})}}),(0,m.jsx)(u,{id:`hb-every`,label:`Default interval`,value:E,placeholder:`30m`,error:B,onChange:e=>{D(e),L(`heartbeat.every`,{value:e,original:I.every??`30m`,valid:S(e)})}}),(0,m.jsx)(u,{id:`hb-start`,label:`Active hours start`,value:O,placeholder:`08:00`,error:V,onChange:e=>{k(e),L(`heartbeat.activeHours.start`,{value:e,original:I.activeHours?.start??`08:00`,valid:C(e)})}}),(0,m.jsx)(u,{id:`hb-end`,label:`Active hours end`,value:M,placeholder:`22:00`,error:H,onChange:e=>{N(e),L(`heartbeat.activeHours.end`,{value:e,original:I.activeHours?.end??`22:00`,valid:C(e)})}}),(0,m.jsx)(l,{id:`hb-target`,label:`Target`,value:P,options:G,onChange:e=>{F(e),L(`heartbeat.target`,{value:e,original:I.target??`all`,valid:!0})}})]}),(0,m.jsx)(i,{title:`Jobs`,hint:`Each job replaces the entire heartbeat.json on save. Concurrent edits from multiple browsers will overwrite — last write wins.`,children:(0,m.jsx)(A,{port:e,client:t,dirty:n,snapshot:_.state})}),(0,m.jsx)(i,{title:`Default heartbeat prompt template`,hint:`Markdown shown to the agent when a heartbeat fires without a job-specific prompt.`,children:(0,m.jsx)(j,{port:e,client:t,dirty:n,snapshot:v.state})})]})}export{x as PAGE_LOCAL_KEYS,b as SECTION_A_KEYS,y as TARGET_FALLBACK,M as default,T as isHeartbeatSettingsKey,O as jobScheduleBodyError,k as jobsHaveErrors,w as makeDefaultJob,D as normalizeJobsResponse,C as validateHHMM,S as validateInterval};
@@ -1,3 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-XQCOJYun.js";import{n as t,t as n}from"./jsx-runtime-BZmCptaP.js";import{a as r,i,n as a,r as o,t as s}from"./page-shell-k5-hYhKb.js";import{t as c}from"./fields-C-y_8RgA.js";import{t as l}from"./InlineWarn-CY6dBBMq.js";var u=e(t(),1),d=/^[a-zA-Z0-9._-]+$/;function f(e){return typeof e!=`string`||e.length===0||e.length>64?!1:d.test(e)}function p(e){if(!e||typeof e!=`object`)return{servers:{}};let t=e,n=t.servers,r={};if(n&&typeof n==`object`&&!Array.isArray(n))for(let[e,t]of Object.entries(n))r[e]=m(t);return{...t,servers:r}}function m(e){if(!e||typeof e!=`object`)return{command:``};let t=e,n=typeof t.command==`string`?t.command:``,r=Array.isArray(t.args)?t.args.filter(e=>typeof e==`string`):void 0,i=t.env&&typeof t.env==`object`&&!Array.isArray(t.env)?Object.fromEntries(Object.entries(t.env).filter(e=>typeof e[1]==`string`)):void 0,a=typeof t.autostart==`boolean`?t.autostart:void 0,o={command:n};r&&r.length>0&&(o.args=r),i&&Object.keys(i).length>0&&(o.env=i),a!==void 0&&(o.autostart=a);for(let[e,n]of Object.entries(t))e===`command`||e===`args`||e===`env`||e===`autostart`||(o[e]=n);return o}function h(){return{command:``}}function g(e){return!e||e.length===0?``:e.join(`
2
- `)}function _(e){if(!e)return[];let t=e.split(/\r?\n|,/),n=[];for(let e of t){let t=e.trim();t.length>0&&n.push(t)}return n}var v=/^[A-Za-z_][A-Za-z0-9_]*$/;function y(e){let t={};if(!e)return t;for(let n of e.split(/\r?\n/)){let e=n.trim();if(e===``||e.startsWith(`#`))continue;let r=e.indexOf(`=`);if(r===-1)continue;let i=e.slice(0,r).trim(),a=e.slice(r+1);v.test(i)&&(t[i]=a)}return t}function b(e){return e?Object.entries(e).map(([e,t])=>`${e}=${t}`).join(`
3
- `):``}function x(e,t){return f(e)?!t.command||t.command.trim()===``?{kind:`invalid`,reason:`Command is required.`}:{kind:`ok`}:{kind:`invalid`,reason:`Server name must match [a-zA-Z0-9._-] (1–64 chars).`}}function S(e){let t=new Set,n=new Set;for(let r of e){let e=r.toLowerCase();t.has(e)?n.add(e):t.add(e)}return n}function C(e){let t={};for(let[n,r]of Object.entries(e.servers)){let e={command:r.command};r.args&&r.args.length>0&&(e.args=[...r.args]),r.env&&Object.keys(r.env).length>0&&(e.env={...r.env}),r.autostart!==void 0&&(e.autostart=r.autostart);for(let[t,n]of Object.entries(r))t===`command`||t===`args`||t===`env`||t===`autostart`||(e[t]=n);t[n]=e}return{...e,servers:t}}function w(e){let t=1;for(;e.includes(`server-${t}`);)t+=1;return`server-${t}`}var T=n();function E({name:e,server:t,onRename:n,onChange:r,onRemove:i,nameError:a}){let o=`mcp-${e||`unnamed`}`,s=g(t.args),c=b(t.env);return(0,T.jsxs)(`article`,{className:`mcp-server-card`,"aria-label":`MCP server ${e||`(unnamed)`}`,children:[(0,T.jsxs)(`header`,{className:`mcp-server-card-header`,children:[(0,T.jsxs)(`label`,{className:`settings-field settings-field-text`,htmlFor:`${o}-name`,children:[(0,T.jsx)(`span`,{className:`settings-field-label`,children:`Server name`}),(0,T.jsx)(`input`,{id:`${o}-name`,type:`text`,value:e,spellCheck:!1,placeholder:`my-server`,"aria-invalid":!!a,onChange:e=>n(e.target.value)}),a?(0,T.jsx)(`span`,{className:`settings-field-error`,role:`alert`,children:a}):null]}),(0,T.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,onClick:i,"aria-label":`Remove ${e||`server`}`,children:`Remove`})]}),(0,T.jsxs)(`label`,{className:`settings-field settings-field-text`,htmlFor:`${o}-command`,children:[(0,T.jsx)(`span`,{className:`settings-field-label`,children:`Command`}),(0,T.jsx)(`input`,{id:`${o}-command`,type:`text`,value:t.command||``,placeholder:`npx`,spellCheck:!1,onChange:e=>r({...t,command:e.target.value})})]}),(0,T.jsxs)(`label`,{className:`settings-field settings-field-text`,htmlFor:`${o}-args`,children:[(0,T.jsx)(`span`,{className:`settings-field-label`,children:`Args (one per line, or comma-separated)`}),(0,T.jsx)(`textarea`,{id:`${o}-args`,value:s,rows:3,spellCheck:!1,onChange:e=>r({...t,args:_(e.target.value)})})]}),(0,T.jsxs)(`label`,{className:`settings-field settings-field-text`,htmlFor:`${o}-env`,children:[(0,T.jsx)(`span`,{className:`settings-field-label`,children:`Env (KEY=value per line)`}),(0,T.jsx)(`textarea`,{id:`${o}-env`,value:c,rows:3,spellCheck:!1,onChange:e=>r({...t,env:y(e.target.value)})})]}),(0,T.jsxs)(`label`,{className:`settings-field settings-field-toggle`,htmlFor:`${o}-autostart`,children:[(0,T.jsx)(`input`,{id:`${o}-autostart`,type:`checkbox`,checked:!!t.autostart,onChange:e=>r({...t,autostart:e.target.checked})}),(0,T.jsx)(`span`,{className:`settings-field-label`,children:`Autostart`})]})]})}var D=`mcp.config`;function O({port:e,client:t,dirty:n,registerSave:d}){let{state:f,refresh:m,setData:g}=r(t,`/api/mcp`),[_,v]=(0,u.useState)({servers:{}}),[y,b]=(0,u.useState)([]),[O,k]=(0,u.useState)(!1),[A,j]=(0,u.useState)(!0),[M,N]=(0,u.useState)({kind:`idle`}),P=(0,u.useRef)(0),F=(0,u.useMemo)(()=>f.kind===`ready`?p(f.data):{servers:{}},[f]);(0,u.useEffect)(()=>{if(f.kind===`ready`){let e=p(f.data);v(e),b(Object.keys(e.servers))}},[f]),(0,u.useEffect)(()=>()=>{n.remove(D)},[n]);let I=(0,u.useMemo)(()=>Object.keys(_.servers),[_]),L=(0,u.useMemo)(()=>S(I),[I]),R=(0,u.useMemo)(()=>I.map(e=>({name:e,result:x(e,_.servers[e]??h())})),[_,I]).some(e=>e.result.kind===`invalid`),z=L.size>0,B=!R&&!z&&A,V=(0,u.useCallback)((e,t)=>{n.set(D,{value:C(e),original:C(F),valid:t})},[n,F]),H=(0,u.useCallback)((e,t)=>{v(e),t&&b(t);let n=t??Object.keys(e.servers),r=S(n);V(e,n.every(t=>x(t,e.servers[t]??h()).kind===`ok`)&&r.size===0&&A)},[A,V]),U=(0,u.useCallback)((e,t)=>{if(e===t)return;let n=y.map(n=>n===e?t:n),r={};for(let i of n)i===t?r[i]=_.servers[e]??h():r[i]=_.servers[i]??h();H({..._,servers:r},n)},[_,y,H]),W=(0,u.useCallback)((e,t)=>{H({..._,servers:{..._.servers,[e]:t}},y)},[_,y,H]),G=(0,u.useCallback)(e=>{let t={..._.servers};delete t[e];let n=y.filter(t=>t!==e);H({..._,servers:t},n)},[_,y,H]),K=(0,u.useCallback)(()=>{let e=w(y);H({..._,servers:{..._.servers,[e]:h()}},[...y,e])},[_,y,H]),q=(0,u.useCallback)((e,t)=>{if(j(t),!t){V(_,!1);return}if(e&&typeof e==`object`&&!Array.isArray(e)){let t=p(e);v(t),b(Object.keys(t.servers));let n=S(Object.keys(t.servers));V(t,Object.entries(t.servers).every(([e,t])=>x(e,t).kind===`ok`)&&n.size===0)}},[_,V]),J=(0,u.useCallback)(async()=>{let e=n.saveBundle();if(!(D in e))return;let r=e[D],i=await t.put(`/api/mcp`,r);n.clear();let a=await t.get(`/api/mcp`).catch(()=>i),o=p(a);v(o),b(Object.keys(o.servers)),g(a),await m()},[t,n,m,g]);(0,u.useEffect)(()=>{if(d)return d(J),()=>d(null)},[d,J]);let Y=(0,u.useCallback)(async(e,r)=>{if(n.isDirty()&&typeof window<`u`&&!window.confirm(`You have unsaved MCP edits. ${e} will use the on-disk config, not your unsaved changes. Continue?`))return;let i=P.current+1;P.current=i,N({kind:`pending`,label:e});try{let n=await t.post(r,{});if(P.current!==i)return;N({kind:`success`,message:`${e} succeeded${n?.servers?`: ${JSON.stringify(n.servers)}`:``}`})}catch(e){if(P.current!==i)return;N({kind:`error`,message:e instanceof Error?e.message:String(e)})}},[t,n]);if(f.kind===`loading`)return(0,T.jsx)(a,{});if(f.kind===`offline`)return(0,T.jsx)(o,{port:e});if(f.kind===`error`)return(0,T.jsx)(s,{message:f.message});let X=Array.from(L).sort();return(0,T.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>e.preventDefault(),children:[(0,T.jsxs)(i,{title:`MCP servers`,hint:`Edit each server's command/args/env. Save writes back to mcp.json; Sync pushes the saved config to all CLIs.`,children:[(0,T.jsxs)(`div`,{className:`mcp-servers-list`,children:[y.length===0&&(0,T.jsxs)(`p`,{className:`settings-section-hint`,children:[`No servers configured. Add one or run `,(0,T.jsx)(`code`,{children:`Reset to defaults`}),`.`]}),y.map(e=>{let t=_.servers[e]??h(),n=e.toLowerCase(),r=L.has(n),i=x(e,t);return(0,T.jsx)(E,{name:e,server:t,onRename:t=>U(e,t),onChange:t=>W(e,t),onRemove:()=>G(e),nameError:r?`Duplicate server name (case-insensitive).`:i.kind===`invalid`?i.reason:null},e)})]}),(0,T.jsx)(`div`,{className:`mcp-servers-actions`,children:(0,T.jsx)(`button`,{type:`button`,className:`settings-action`,onClick:K,children:`Add server`})}),z&&(0,T.jsxs)(l,{role:`alert`,children:[`Duplicate server name`,X.length===1?``:`s`,`: `,X.join(`, `),`. Saving is blocked until names are unique.`]}),R&&!z&&(0,T.jsx)(l,{role:`alert`,children:`Some servers have errors (missing command or invalid name). Saving is blocked until they are fixed.`})]}),(0,T.jsxs)(i,{title:`Actions`,hint:`These act on the saved config. Save edits first if you want them included.`,children:[(0,T.jsxs)(`div`,{className:`mcp-action-buttons`,children:[(0,T.jsx)(`button`,{type:`button`,className:`settings-action`,disabled:M.kind===`pending`,onClick:()=>void Y(`Sync to all CLIs`,`/api/mcp/sync`),children:`Sync to all CLIs`}),(0,T.jsx)(`button`,{type:`button`,className:`settings-action`,disabled:M.kind===`pending`,onClick:()=>void Y(`Install bundle`,`/api/mcp/install`),children:`Install bundle`}),(0,T.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,disabled:M.kind===`pending`,onClick:()=>{typeof window<`u`&&!window.confirm(`Reset MCP config to defaults? Your custom servers will be removed.`)||Y(`Reset to defaults`,`/api/mcp/reset`)},children:`Reset to defaults`})]}),M.kind===`pending`&&(0,T.jsxs)(`p`,{className:`settings-section-hint`,role:`status`,children:[M.label,`…`]}),M.kind===`success`&&(0,T.jsxs)(`p`,{className:`settings-section-hint`,role:`status`,children:[`✅ `,M.message]}),M.kind===`error`&&(0,T.jsx)(l,{role:`alert`,children:M.message})]}),(0,T.jsxs)(i,{title:`Advanced (raw JSON)`,hint:`Edit the entire config object. Useful for fields not surfaced in the structured editor.`,children:[(0,T.jsx)(`button`,{type:`button`,className:`settings-action`,onClick:()=>k(e=>!e),"aria-expanded":O,children:O?`Hide raw JSON`:`Show raw JSON`}),O&&(0,T.jsx)(c,{id:`mcp-raw`,label:`mcp.json`,value:C(_),rows:16,onChange:q}),!B&&(0,T.jsx)(`p`,{className:`settings-section-hint`,children:`Save is disabled while validation errors are present.`})]})]})}export{O as default};
@@ -1 +0,0 @@
1
- var e=[`claude`,`claude-e`,`agy`,`codex`,`cursor`,`gemini`],t={agy:{label:`Antigravity`,models:[`gemini-3.5-flash`],efforts:[],effortNote:`AGY print mode uses the current AGY-selected model; switch models in native AGY UI, no --model/--effort flags in agy 1.0.0`},"ai-e":{label:`AI-E`,defaultProvider:`claude`,providers:[`claude`,`codex`,`gemini`,`grok`,`copilot`],models:[`opus`,`sonnet`,`haiku`,`gpt-5.4`,`gpt-5.4-mini`,`gemini-3-flash-preview`,`grok-build`,`gpt-5-mini`],efforts:[`low`,`medium`,`high`,`xhigh`,`max`],modelsByProvider:{claude:[`opus`,`sonnet`,`haiku`],codex:[`gpt-5.4`,`gpt-5.4-mini`],gemini:[`gemini-3-flash-preview`],grok:[`grok-build`],copilot:[`gpt-5-mini`]},effortsByProvider:{claude:[`low`,`medium`,`high`,`xhigh`,`max`],codex:[`low`,`medium`,`high`,`xhigh`],gemini:[],grok:[],copilot:[`low`,`medium`,`high`]}},claude:{label:`Claude`,models:[`opus`,`sonnet`,`sonnet[1m]`,`haiku`,`claude-opus-4-8`,`claude-opus-4-8[1m]`,`claude-opus-4-7`,`claude-opus-4-7[1m]`,`claude-opus-4-6`,`claude-opus-4-6[1m]`,`claude-sonnet-4-6`,`claude-sonnet-4-6[1m]`,`claude-haiku-4-5`],efforts:[`low`,`medium`,`high`,`xhigh`,`max`]},"claude-e":{label:`Claude E`,models:[`opus`,`sonnet`,`haiku`,`claude-opus-4-8`,`claude-opus-4-7`,`claude-sonnet-4-6`,`claude-haiku-4-5`],efforts:[`low`,`medium`,`high`,`xhigh`,`max`]},codex:{label:`Codex`,models:[`gpt-5.5`,`gpt-5.4`,`gpt-5.4-mini`,`gpt-5.3-codex`],efforts:[`low`,`medium`,`high`,`xhigh`]},"codex-app":{label:`Codex App`,models:[`gpt-5.5`,`gpt-5.4`,`gpt-5.4-mini`,`gpt-5.3-codex`],efforts:[`low`,`medium`,`high`,`xhigh`]},cursor:{label:`Cursor`,models:`auto,composer-2.5,composer-2,gpt-5.5,gpt-5.4,gpt-5.4-mini,gpt-5.4-nano,gpt-5.3-codex,gpt-5.2,gpt-5.2-codex,gpt-5.1-codex-max,gpt-5.1-codex-mini,gpt-5.1,claude-opus-4-8,claude-opus-4-8-thinking,claude-opus-4-7,claude-opus-4-7-thinking,claude-4.6-opus,claude-4.6-sonnet,claude-4.5-opus-high,claude-4.5-sonnet,claude-4-sonnet,gemini-3.1-pro,gemini-3-flash,gemini-3.5-flash,grok-4.3,grok-build-0.1,gpt-5-mini,kimi-k2.5`.split(`,`),efforts:[`none`,`none-fast`,`low`,`low-fast`,`medium`,`medium-fast`,`high`,`high-fast`,`xhigh`,`xhigh-fast`,`max`,`max-fast`],effortNote:`Cursor effort resolves to model IDs; no separate --effort flag`},gemini:{label:`Gemini`,models:[`gemini-3-pro-preview`,`gemini-2.5-pro`,`gemini-3-flash-preview`],efforts:[]},grok:{label:`Grok`,models:[`grok-build`],efforts:[],effortNote:`unsupported by grok-build; do not pass --effort`},opencode:{label:`OpenCode`,models:[`opencode-go/kimi-k2.6`,`opencode-go/glm-5.1`],efforts:[`minimal`,`low`,`high`,`max`]},copilot:{label:`Copilot`,models:[`gpt-5.5`,`claude-opus-4.8`,`claude-opus-4.7`,`claude-sonnet-4.6`,`gpt-5.4`],efforts:[`low`,`medium`,`high`]}};function n(e){return t[e]||{label:e,models:[],efforts:[]}}function r(e,t={},n={}){return n[e]?.model||t[e]?.model||``}function i(e,t={},n={}){return n[e]?.effort||t[e]?.effort||``}function a(e,t=``){let n=new Set;t&&n.add(t);for(let t of e)n.add(t);return Array.from(n).map(e=>({value:e,label:e}))}export{r as a,i,n,a as r,e as t};