@mobrienv/autoloop 0.3.0 → 0.7.0

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 (415) hide show
  1. package/README.md +140 -43
  2. package/bin/autoloop +1 -1
  3. package/dist/index.d.ts +6 -0
  4. package/dist/index.js +19 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/testing/mock-backend.js +3 -5
  7. package/dist/testing/mock-backend.js.map +1 -1
  8. package/package.json +32 -10
  9. package/plugins/autoloop/.claude-plugin/plugin.json +1 -1
  10. package/dist/agent-map.d.ts +0 -10
  11. package/dist/agent-map.js +0 -58
  12. package/dist/agent-map.js.map +0 -1
  13. package/dist/backend/acp-client.d.ts +0 -38
  14. package/dist/backend/acp-client.js +0 -288
  15. package/dist/backend/acp-client.js.map +0 -1
  16. package/dist/backend/index.d.ts +0 -10
  17. package/dist/backend/index.js +0 -71
  18. package/dist/backend/index.js.map +0 -1
  19. package/dist/backend/kiro-bridge.d.ts +0 -17
  20. package/dist/backend/kiro-bridge.js +0 -84
  21. package/dist/backend/kiro-bridge.js.map +0 -1
  22. package/dist/backend/kiro-worker.d.ts +0 -1
  23. package/dist/backend/kiro-worker.js +0 -92
  24. package/dist/backend/kiro-worker.js.map +0 -1
  25. package/dist/backend/run-command.d.ts +0 -7
  26. package/dist/backend/run-command.js +0 -50
  27. package/dist/backend/run-command.js.map +0 -1
  28. package/dist/backend/run-kiro.d.ts +0 -3
  29. package/dist/backend/run-kiro.js +0 -16
  30. package/dist/backend/run-kiro.js.map +0 -1
  31. package/dist/backend/run-mock.d.ts +0 -1
  32. package/dist/backend/run-mock.js +0 -6
  33. package/dist/backend/run-mock.js.map +0 -1
  34. package/dist/backend/run-pi.d.ts +0 -5
  35. package/dist/backend/run-pi.js +0 -5
  36. package/dist/backend/run-pi.js.map +0 -1
  37. package/dist/backend/types.d.ts +0 -21
  38. package/dist/backend/types.js +0 -2
  39. package/dist/backend/types.js.map +0 -1
  40. package/dist/chains/budget.d.ts +0 -7
  41. package/dist/chains/budget.js +0 -54
  42. package/dist/chains/budget.js.map +0 -1
  43. package/dist/chains/load.d.ts +0 -18
  44. package/dist/chains/load.js +0 -129
  45. package/dist/chains/load.js.map +0 -1
  46. package/dist/chains/render.d.ts +0 -2
  47. package/dist/chains/render.js +0 -74
  48. package/dist/chains/render.js.map +0 -1
  49. package/dist/chains/run.d.ts +0 -17
  50. package/dist/chains/run.js +0 -260
  51. package/dist/chains/run.js.map +0 -1
  52. package/dist/chains/types.d.ts +0 -38
  53. package/dist/chains/types.js +0 -2
  54. package/dist/chains/types.js.map +0 -1
  55. package/dist/chains.d.ts +0 -6
  56. package/dist/chains.js +0 -5
  57. package/dist/chains.js.map +0 -1
  58. package/dist/commands/chain.d.ts +0 -1
  59. package/dist/commands/chain.js +0 -53
  60. package/dist/commands/chain.js.map +0 -1
  61. package/dist/commands/config.d.ts +0 -1
  62. package/dist/commands/config.js +0 -74
  63. package/dist/commands/config.js.map +0 -1
  64. package/dist/commands/dashboard.d.ts +0 -1
  65. package/dist/commands/dashboard.js +0 -68
  66. package/dist/commands/dashboard.js.map +0 -1
  67. package/dist/commands/guide.d.ts +0 -1
  68. package/dist/commands/guide.js +0 -33
  69. package/dist/commands/guide.js.map +0 -1
  70. package/dist/commands/inspect.d.ts +0 -1
  71. package/dist/commands/inspect.js +0 -203
  72. package/dist/commands/inspect.js.map +0 -1
  73. package/dist/commands/list.d.ts +0 -1
  74. package/dist/commands/list.js +0 -15
  75. package/dist/commands/list.js.map +0 -1
  76. package/dist/commands/loops.d.ts +0 -1
  77. package/dist/commands/loops.js +0 -72
  78. package/dist/commands/loops.js.map +0 -1
  79. package/dist/commands/memory.d.ts +0 -1
  80. package/dist/commands/memory.js +0 -65
  81. package/dist/commands/memory.js.map +0 -1
  82. package/dist/commands/pi-adapter.d.ts +0 -1
  83. package/dist/commands/pi-adapter.js +0 -6
  84. package/dist/commands/pi-adapter.js.map +0 -1
  85. package/dist/commands/run.d.ts +0 -1
  86. package/dist/commands/run.js +0 -292
  87. package/dist/commands/run.js.map +0 -1
  88. package/dist/commands/runs.d.ts +0 -1
  89. package/dist/commands/runs.js +0 -50
  90. package/dist/commands/runs.js.map +0 -1
  91. package/dist/commands/task.d.ts +0 -1
  92. package/dist/commands/task.js +0 -74
  93. package/dist/commands/task.js.map +0 -1
  94. package/dist/commands/worktree.d.ts +0 -1
  95. package/dist/commands/worktree.js +0 -162
  96. package/dist/commands/worktree.js.map +0 -1
  97. package/dist/config.d.ts +0 -31
  98. package/dist/config.js +0 -261
  99. package/dist/config.js.map +0 -1
  100. package/dist/dashboard/app.d.ts +0 -12
  101. package/dist/dashboard/app.js +0 -23
  102. package/dist/dashboard/app.js.map +0 -1
  103. package/dist/dashboard/routes/api.d.ts +0 -3
  104. package/dist/dashboard/routes/api.js +0 -130
  105. package/dist/dashboard/routes/api.js.map +0 -1
  106. package/dist/dashboard/routes/pages.d.ts +0 -2
  107. package/dist/dashboard/routes/pages.js +0 -14
  108. package/dist/dashboard/routes/pages.js.map +0 -1
  109. package/dist/dashboard/views/alpine-vendor.d.ts +0 -1
  110. package/dist/dashboard/views/alpine-vendor.js +0 -10
  111. package/dist/dashboard/views/alpine-vendor.js.map +0 -1
  112. package/dist/dashboard/views/shell.d.ts +0 -1
  113. package/dist/dashboard/views/shell.js +0 -746
  114. package/dist/dashboard/views/shell.js.map +0 -1
  115. package/dist/events/decode.d.ts +0 -2
  116. package/dist/events/decode.js +0 -45
  117. package/dist/events/decode.js.map +0 -1
  118. package/dist/events/encode.d.ts +0 -2
  119. package/dist/events/encode.js +0 -33
  120. package/dist/events/encode.js.map +0 -1
  121. package/dist/events/guards.d.ts +0 -5
  122. package/dist/events/guards.js +0 -42
  123. package/dist/events/guards.js.map +0 -1
  124. package/dist/events/types.d.ts +0 -26
  125. package/dist/events/types.js +0 -2
  126. package/dist/events/types.js.map +0 -1
  127. package/dist/harness/config-helpers.d.ts +0 -35
  128. package/dist/harness/config-helpers.js +0 -411
  129. package/dist/harness/config-helpers.js.map +0 -1
  130. package/dist/harness/coordination.d.ts +0 -1
  131. package/dist/harness/coordination.js +0 -127
  132. package/dist/harness/coordination.js.map +0 -1
  133. package/dist/harness/display.d.ts +0 -21
  134. package/dist/harness/display.js +0 -176
  135. package/dist/harness/display.js.map +0 -1
  136. package/dist/harness/emit.d.ts +0 -15
  137. package/dist/harness/emit.js +0 -240
  138. package/dist/harness/emit.js.map +0 -1
  139. package/dist/harness/index.d.ts +0 -13
  140. package/dist/harness/index.js +0 -240
  141. package/dist/harness/index.js.map +0 -1
  142. package/dist/harness/iteration.d.ts +0 -16
  143. package/dist/harness/iteration.js +0 -131
  144. package/dist/harness/iteration.js.map +0 -1
  145. package/dist/harness/journal.d.ts +0 -31
  146. package/dist/harness/journal.js +0 -178
  147. package/dist/harness/journal.js.map +0 -1
  148. package/dist/harness/metareview.d.ts +0 -4
  149. package/dist/harness/metareview.js +0 -48
  150. package/dist/harness/metareview.js.map +0 -1
  151. package/dist/harness/metrics.d.ts +0 -12
  152. package/dist/harness/metrics.js +0 -180
  153. package/dist/harness/metrics.js.map +0 -1
  154. package/dist/harness/parallel.d.ts +0 -37
  155. package/dist/harness/parallel.js +0 -237
  156. package/dist/harness/parallel.js.map +0 -1
  157. package/dist/harness/prompt.d.ts +0 -46
  158. package/dist/harness/prompt.js +0 -403
  159. package/dist/harness/prompt.js.map +0 -1
  160. package/dist/harness/scratchpad.d.ts +0 -2
  161. package/dist/harness/scratchpad.js +0 -67
  162. package/dist/harness/scratchpad.js.map +0 -1
  163. package/dist/harness/stop.d.ts +0 -5
  164. package/dist/harness/stop.js +0 -70
  165. package/dist/harness/stop.js.map +0 -1
  166. package/dist/harness/tools.d.ts +0 -3
  167. package/dist/harness/tools.js +0 -65
  168. package/dist/harness/tools.js.map +0 -1
  169. package/dist/harness/types.d.ts +0 -110
  170. package/dist/harness/types.js +0 -2
  171. package/dist/harness/types.js.map +0 -1
  172. package/dist/harness/wave/finalize-wave.d.ts +0 -9
  173. package/dist/harness/wave/finalize-wave.js +0 -87
  174. package/dist/harness/wave/finalize-wave.js.map +0 -1
  175. package/dist/harness/wave/launch-branches.d.ts +0 -6
  176. package/dist/harness/wave/launch-branches.js +0 -314
  177. package/dist/harness/wave/launch-branches.js.map +0 -1
  178. package/dist/harness/wave/parse-objectives.d.ts +0 -3
  179. package/dist/harness/wave/parse-objectives.js +0 -32
  180. package/dist/harness/wave/parse-objectives.js.map +0 -1
  181. package/dist/harness/wave/types.d.ts +0 -43
  182. package/dist/harness/wave/types.js +0 -2
  183. package/dist/harness/wave/types.js.map +0 -1
  184. package/dist/harness/wave.d.ts +0 -6
  185. package/dist/harness/wave.js +0 -159
  186. package/dist/harness/wave.js.map +0 -1
  187. package/dist/isolation/index.d.ts +0 -4
  188. package/dist/isolation/index.js +0 -3
  189. package/dist/isolation/index.js.map +0 -1
  190. package/dist/isolation/resolve.d.ts +0 -39
  191. package/dist/isolation/resolve.js +0 -118
  192. package/dist/isolation/resolve.js.map +0 -1
  193. package/dist/isolation/run-scope.d.ts +0 -21
  194. package/dist/isolation/run-scope.js +0 -50
  195. package/dist/isolation/run-scope.js.map +0 -1
  196. package/dist/json.d.ts +0 -8
  197. package/dist/json.js +0 -82
  198. package/dist/json.js.map +0 -1
  199. package/dist/loops/health.d.ts +0 -16
  200. package/dist/loops/health.js +0 -152
  201. package/dist/loops/health.js.map +0 -1
  202. package/dist/loops/list.d.ts +0 -6
  203. package/dist/loops/list.js +0 -21
  204. package/dist/loops/list.js.map +0 -1
  205. package/dist/loops/policy.d.ts +0 -6
  206. package/dist/loops/policy.js +0 -41
  207. package/dist/loops/policy.js.map +0 -1
  208. package/dist/loops/render.d.ts +0 -19
  209. package/dist/loops/render.js +0 -100
  210. package/dist/loops/render.js.map +0 -1
  211. package/dist/loops/show.d.ts +0 -8
  212. package/dist/loops/show.js +0 -31
  213. package/dist/loops/show.js.map +0 -1
  214. package/dist/loops/watch.d.ts +0 -14
  215. package/dist/loops/watch.js +0 -143
  216. package/dist/loops/watch.js.map +0 -1
  217. package/dist/main.d.ts +0 -1
  218. package/dist/main.js +0 -148
  219. package/dist/main.js.map +0 -1
  220. package/dist/markdown.d.ts +0 -10
  221. package/dist/markdown.js +0 -66
  222. package/dist/markdown.js.map +0 -1
  223. package/dist/memory-render.d.ts +0 -6
  224. package/dist/memory-render.js +0 -81
  225. package/dist/memory-render.js.map +0 -1
  226. package/dist/memory.d.ts +0 -22
  227. package/dist/memory.js +0 -318
  228. package/dist/memory.js.map +0 -1
  229. package/dist/pi-adapter.d.ts +0 -1
  230. package/dist/pi-adapter.js +0 -220
  231. package/dist/pi-adapter.js.map +0 -1
  232. package/dist/profiles.d.ts +0 -12
  233. package/dist/profiles.js +0 -71
  234. package/dist/profiles.js.map +0 -1
  235. package/dist/registry/derive.d.ts +0 -8
  236. package/dist/registry/derive.js +0 -88
  237. package/dist/registry/derive.js.map +0 -1
  238. package/dist/registry/discover.d.ts +0 -20
  239. package/dist/registry/discover.js +0 -98
  240. package/dist/registry/discover.js.map +0 -1
  241. package/dist/registry/harness.d.ts +0 -7
  242. package/dist/registry/harness.js +0 -63
  243. package/dist/registry/harness.js.map +0 -1
  244. package/dist/registry/index.d.ts +0 -6
  245. package/dist/registry/index.js +0 -6
  246. package/dist/registry/index.js.map +0 -1
  247. package/dist/registry/read.d.ts +0 -11
  248. package/dist/registry/read.js +0 -50
  249. package/dist/registry/read.js.map +0 -1
  250. package/dist/registry/rebuild.d.ts +0 -5
  251. package/dist/registry/rebuild.js +0 -22
  252. package/dist/registry/rebuild.js.map +0 -1
  253. package/dist/registry/types.d.ts +0 -28
  254. package/dist/registry/types.js +0 -2
  255. package/dist/registry/types.js.map +0 -1
  256. package/dist/registry/update.d.ts +0 -2
  257. package/dist/registry/update.js +0 -7
  258. package/dist/registry/update.js.map +0 -1
  259. package/dist/tasks-render.d.ts +0 -2
  260. package/dist/tasks-render.js +0 -44
  261. package/dist/tasks-render.js.map +0 -1
  262. package/dist/tasks.d.ts +0 -24
  263. package/dist/tasks.js +0 -184
  264. package/dist/tasks.js.map +0 -1
  265. package/dist/topology.d.ts +0 -31
  266. package/dist/topology.js +0 -309
  267. package/dist/topology.js.map +0 -1
  268. package/dist/usage.d.ts +0 -9
  269. package/dist/usage.js +0 -159
  270. package/dist/usage.js.map +0 -1
  271. package/dist/utils.d.ts +0 -21
  272. package/dist/utils.js +0 -349
  273. package/dist/utils.js.map +0 -1
  274. package/dist/worktree/clean.d.ts +0 -12
  275. package/dist/worktree/clean.js +0 -98
  276. package/dist/worktree/clean.js.map +0 -1
  277. package/dist/worktree/create.d.ts +0 -14
  278. package/dist/worktree/create.js +0 -71
  279. package/dist/worktree/create.js.map +0 -1
  280. package/dist/worktree/index.d.ts +0 -10
  281. package/dist/worktree/index.js +0 -6
  282. package/dist/worktree/index.js.map +0 -1
  283. package/dist/worktree/list.d.ts +0 -9
  284. package/dist/worktree/list.js +0 -24
  285. package/dist/worktree/list.js.map +0 -1
  286. package/dist/worktree/merge.d.ts +0 -11
  287. package/dist/worktree/merge.js +0 -129
  288. package/dist/worktree/merge.js.map +0 -1
  289. package/dist/worktree/meta.d.ts +0 -17
  290. package/dist/worktree/meta.js +0 -34
  291. package/dist/worktree/meta.js.map +0 -1
  292. package/presets/autocode/README.md +0 -81
  293. package/presets/autocode/autoloops.toml +0 -30
  294. package/presets/autocode/harness.md +0 -26
  295. package/presets/autocode/miniloops.toml +0 -22
  296. package/presets/autocode/roles/build.md +0 -34
  297. package/presets/autocode/roles/critic.md +0 -40
  298. package/presets/autocode/roles/finalizer.md +0 -43
  299. package/presets/autocode/roles/planner.md +0 -40
  300. package/presets/autocode/topology.toml +0 -32
  301. package/presets/autodoc/README.md +0 -42
  302. package/presets/autodoc/autoloops.toml +0 -21
  303. package/presets/autodoc/harness.md +0 -19
  304. package/presets/autodoc/miniloops.toml +0 -21
  305. package/presets/autodoc/roles/auditor.md +0 -39
  306. package/presets/autodoc/roles/checker.md +0 -43
  307. package/presets/autodoc/roles/publisher.md +0 -51
  308. package/presets/autodoc/roles/writer.md +0 -37
  309. package/presets/autodoc/topology.toml +0 -31
  310. package/presets/autofix/README.md +0 -56
  311. package/presets/autofix/autoloops.toml +0 -24
  312. package/presets/autofix/harness.md +0 -25
  313. package/presets/autofix/miniloops.toml +0 -21
  314. package/presets/autofix/roles/closer.md +0 -48
  315. package/presets/autofix/roles/diagnoser.md +0 -43
  316. package/presets/autofix/roles/fixer.md +0 -28
  317. package/presets/autofix/roles/verifier.md +0 -31
  318. package/presets/autofix/topology.toml +0 -33
  319. package/presets/autoideas/README.md +0 -73
  320. package/presets/autoideas/autoloops.toml +0 -18
  321. package/presets/autoideas/harness.md +0 -31
  322. package/presets/autoideas/miniloops.toml +0 -18
  323. package/presets/autoideas/roles/analyst.md +0 -32
  324. package/presets/autoideas/roles/reviewer.md +0 -36
  325. package/presets/autoideas/roles/scanner.md +0 -26
  326. package/presets/autoideas/roles/synthesizer.md +0 -61
  327. package/presets/autoideas/topology.toml +0 -32
  328. package/presets/automerge/README.md +0 -3
  329. package/presets/automerge/autoloops.toml +0 -12
  330. package/presets/automerge/harness.md +0 -10
  331. package/presets/automerge/miniloops.toml +0 -12
  332. package/presets/automerge/roles/merge.md +0 -10
  333. package/presets/automerge/topology.toml +0 -10
  334. package/presets/autoperf/README.md +0 -56
  335. package/presets/autoperf/autoloops.toml +0 -21
  336. package/presets/autoperf/harness.md +0 -21
  337. package/presets/autoperf/miniloops.toml +0 -21
  338. package/presets/autoperf/roles/judge.md +0 -38
  339. package/presets/autoperf/roles/measurer.md +0 -36
  340. package/presets/autoperf/roles/optimizer.md +0 -35
  341. package/presets/autoperf/roles/profiler.md +0 -38
  342. package/presets/autoperf/topology.toml +0 -32
  343. package/presets/autopr/README.md +0 -99
  344. package/presets/autopr/autoloops.toml +0 -22
  345. package/presets/autopr/harness.md +0 -27
  346. package/presets/autopr/miniloops.toml +0 -22
  347. package/presets/autopr/roles/collector.md +0 -55
  348. package/presets/autopr/roles/drafter.md +0 -38
  349. package/presets/autopr/roles/publisher.md +0 -28
  350. package/presets/autopr/roles/validator.md +0 -31
  351. package/presets/autopr/topology.toml +0 -32
  352. package/presets/autoqa/README.md +0 -76
  353. package/presets/autoqa/autoloops.toml +0 -21
  354. package/presets/autoqa/harness.md +0 -30
  355. package/presets/autoqa/miniloops.toml +0 -21
  356. package/presets/autoqa/roles/executor.md +0 -43
  357. package/presets/autoqa/roles/inspector.md +0 -45
  358. package/presets/autoqa/roles/planner.md +0 -55
  359. package/presets/autoqa/roles/reporter.md +0 -74
  360. package/presets/autoqa/topology.toml +0 -31
  361. package/presets/autoresearch/README.md +0 -63
  362. package/presets/autoresearch/autoloops.toml +0 -18
  363. package/presets/autoresearch/harness.md +0 -28
  364. package/presets/autoresearch/miniloops.toml +0 -18
  365. package/presets/autoresearch/roles/benchmarker.md +0 -34
  366. package/presets/autoresearch/roles/evaluator.md +0 -33
  367. package/presets/autoresearch/roles/implementer.md +0 -26
  368. package/presets/autoresearch/roles/strategist.md +0 -43
  369. package/presets/autoresearch/topology.toml +0 -31
  370. package/presets/autoreview/README.md +0 -51
  371. package/presets/autoreview/autoloops.toml +0 -21
  372. package/presets/autoreview/harness.md +0 -20
  373. package/presets/autoreview/miniloops.toml +0 -21
  374. package/presets/autoreview/roles/checker.md +0 -36
  375. package/presets/autoreview/roles/reader.md +0 -33
  376. package/presets/autoreview/roles/suggester.md +0 -26
  377. package/presets/autoreview/roles/summarizer.md +0 -57
  378. package/presets/autoreview/topology.toml +0 -31
  379. package/presets/autosec/README.md +0 -51
  380. package/presets/autosec/autoloops.toml +0 -21
  381. package/presets/autosec/harness.md +0 -20
  382. package/presets/autosec/miniloops.toml +0 -21
  383. package/presets/autosec/roles/analyst.md +0 -38
  384. package/presets/autosec/roles/hardener.md +0 -36
  385. package/presets/autosec/roles/reporter.md +0 -63
  386. package/presets/autosec/roles/scanner.md +0 -38
  387. package/presets/autosec/topology.toml +0 -31
  388. package/presets/autosimplify/README.md +0 -83
  389. package/presets/autosimplify/autoloops.toml +0 -26
  390. package/presets/autosimplify/harness.md +0 -25
  391. package/presets/autosimplify/miniloops.toml +0 -22
  392. package/presets/autosimplify/roles/reviewer.md +0 -38
  393. package/presets/autosimplify/roles/scoper.md +0 -42
  394. package/presets/autosimplify/roles/simplifier.md +0 -51
  395. package/presets/autosimplify/roles/verifier.md +0 -40
  396. package/presets/autosimplify/topology.toml +0 -32
  397. package/presets/autospec/README.md +0 -84
  398. package/presets/autospec/autoloops.toml +0 -21
  399. package/presets/autospec/harness.md +0 -23
  400. package/presets/autospec/miniloops.toml +0 -21
  401. package/presets/autospec/roles/clarifier.md +0 -39
  402. package/presets/autospec/roles/critic.md +0 -41
  403. package/presets/autospec/roles/designer.md +0 -37
  404. package/presets/autospec/roles/planner.md +0 -38
  405. package/presets/autospec/roles/researcher.md +0 -33
  406. package/presets/autospec/topology.toml +0 -38
  407. package/presets/autotest/README.md +0 -55
  408. package/presets/autotest/autoloops.toml +0 -21
  409. package/presets/autotest/harness.md +0 -21
  410. package/presets/autotest/miniloops.toml +0 -21
  411. package/presets/autotest/roles/assessor.md +0 -57
  412. package/presets/autotest/roles/runner.md +0 -31
  413. package/presets/autotest/roles/surveyor.md +0 -39
  414. package/presets/autotest/roles/writer.md +0 -37
  415. package/presets/autotest/topology.toml +0 -32
@@ -1,746 +0,0 @@
1
- export function htmlShell() {
2
- return `<!DOCTYPE html>
3
- <html lang="en">
4
- <head>
5
- <meta charset="utf-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1">
7
- <title>autoloop dashboard</title>
8
- <style>
9
- :root {
10
- --bg: #fff; --fg: #1a1a1a; --muted: #666; --border: #e0e0e0;
11
- --card-bg: #fafafa; --badge-bg: #eee;
12
- --active: #2563eb; --watching: #d97706; --stuck: #dc2626;
13
- --failed: #dc2626; --completed: #16a34a;
14
- }
15
- @media (prefers-color-scheme: dark) {
16
- :root {
17
- --bg: #111; --fg: #e0e0e0; --muted: #999; --border: #333;
18
- --card-bg: #1a1a1a; --badge-bg: #2a2a2a;
19
- }
20
- }
21
- * { box-sizing: border-box; margin: 0; padding: 0; }
22
- body { font-family: system-ui, -apple-system, sans-serif; background: var(--bg); color: var(--fg); max-width: 900px; margin: 0 auto; padding: 1rem; }
23
- h1 { font-size: 1.25rem; font-weight: 600; }
24
- header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 1rem; border-bottom: 1px solid var(--border); padding-bottom: 0.5rem; }
25
- header .updated { font-size: 0.75rem; color: var(--muted); font-family: monospace; }
26
-
27
- .chatbox { background: var(--card-bg); border: 1px solid var(--border); border-radius: 6px; padding: 0.75rem; margin-bottom: 1rem; display: flex; gap: 0.5rem; align-items: flex-end; }
28
- .chatbox select { padding: 0.4rem; border: 1px solid var(--border); border-radius: 4px; background: var(--bg); color: var(--fg); font-size: 0.8rem; }
29
- .chatbox textarea { flex: 1; resize: vertical; min-height: 2.5rem; max-height: 8rem; padding: 0.4rem; border: 1px solid var(--border); border-radius: 4px; font-family: inherit; font-size: 0.85rem; background: var(--bg); color: var(--fg); }
30
- .chatbox button { padding: 0.4rem 1rem; border: none; border-radius: 4px; background: var(--active); color: #fff; cursor: pointer; font-size: 0.85rem; white-space: nowrap; }
31
- .chatbox button:hover { opacity: 0.9; }
32
-
33
- .section summary { cursor: pointer; font-weight: 600; font-size: 0.9rem; padding: 0.4rem 0; list-style: none; }
34
- .section summary::-webkit-details-marker { display: none; }
35
- .section summary::before { content: "\\25b6 "; font-size: 0.7rem; }
36
- .section[open] summary::before { content: "\\25bc "; }
37
- .badge { display: inline-block; font-size: 0.7rem; padding: 0.1rem 0.4rem; border-radius: 8px; background: var(--badge-bg); margin-left: 0.3rem; font-weight: normal; }
38
- .badge[data-status="active"] { background: var(--active); color: #fff; }
39
- .badge[data-status="watching"] { background: var(--watching); color: #fff; }
40
- .badge[data-status="stuck"] { background: var(--stuck); color: #fff; }
41
- .badge[data-status="failed"] { background: var(--failed); color: #fff; }
42
- .badge[data-status="completed"] { background: var(--completed); color: #fff; }
43
- .wt-badge { background: var(--badge-bg); color: var(--muted); font-weight: 600; letter-spacing: 0.03em; }
44
-
45
- .run-list { list-style: none; padding: 0; }
46
- .run-item { display: grid; grid-template-columns: 1fr auto; gap: 0.5rem; padding: 0.4rem 0.5rem; border-bottom: 1px solid var(--border); cursor: pointer; font-size: 0.8rem; font-family: monospace; }
47
- .run-item:hover { background: var(--card-bg); }
48
- .run-item .meta { color: var(--muted); text-align: right; white-space: nowrap; }
49
-
50
- .detail-pane { background: var(--card-bg); border: 1px solid var(--border); border-radius: 6px; padding: 1rem; margin-top: 1rem; }
51
- .detail-pane h3 { font-size: 0.95rem; margin-bottom: 0.5rem; }
52
- .detail-pane .field { font-size: 0.8rem; font-family: monospace; margin-bottom: 0.25rem; }
53
- .detail-pane .field label { color: var(--muted); }
54
- .events-list { margin-top: 0.75rem; max-height: 400px; overflow-y: auto; }
55
- .event-item { font-size: 0.75rem; font-family: monospace; padding: 0.2rem 0; border-bottom: 1px solid var(--border); word-break: break-all; }
56
- .event-item summary { cursor: pointer; }
57
- .event-item.ev-system { border-left: 3px solid var(--muted); padding-left: 0.4rem; }
58
- .event-item.ev-backend { border-left: 3px solid var(--muted); padding-left: 0.4rem; }
59
- .event-item.ev-review { border-left: 3px solid var(--watching); padding-left: 0.4rem; background: rgba(217,119,6,0.03); }
60
- .event-item.ev-error { border-left: 3px solid var(--failed); padding-left: 0.4rem; background: rgba(220,38,38,0.05); }
61
- .event-item.ev-coordination { border-left: 3px solid var(--active); padding-left: 0.4rem; }
62
- .event-item.ev-completion { border-left: 3px solid var(--completed); padding-left: 0.4rem; }
63
- .event-item.ev-highlight { border-left-color: var(--active); }
64
- .event-item.ev-backend summary { opacity: 0.6; }
65
- .event-item.ev-highlight summary { opacity: 1; }
66
- .event-item.ev-backend:hover summary { opacity: 1; }
67
- .event-field { margin: 0.15rem 0; font-size: 0.7rem; }
68
- .event-field strong { color: var(--muted); margin-right: 0.3rem; }
69
- .event-field pre { display: inline; white-space: pre-wrap; }
70
- .event-field details summary { cursor: pointer; color: var(--muted); font-style: italic; }
71
-
72
- .md-content { font-family: system-ui, -apple-system, sans-serif; font-size: 0.75rem; line-height: 1.5; white-space: normal; }
73
- .md-content h1, .md-content h2, .md-content h3, .md-content h4, .md-content h5, .md-content h6 { margin: 0.5em 0 0.25em; font-weight: 600; }
74
- .md-content h1 { font-size: 1.1em; } .md-content h2 { font-size: 1em; } .md-content h3 { font-size: 0.95em; }
75
- .md-content p { margin: 0.3em 0; }
76
- .md-content code { background: var(--badge-bg); padding: 0.1em 0.3em; border-radius: 3px; font-size: 0.9em; }
77
- .md-content pre { background: var(--badge-bg); padding: 0.5em; border-radius: 4px; overflow-x: auto; margin: 0.4em 0; }
78
- .md-content pre code { background: none; padding: 0; }
79
- .md-content ul, .md-content ol { margin: 0.3em 0; padding-left: 1.5em; }
80
- .md-content li { margin: 0.15em 0; }
81
- .md-content strong { font-weight: 600; }
82
- .md-content em { font-style: italic; }
83
-
84
- .empty { color: var(--muted); font-size: 0.8rem; padding: 0.5rem 0; }
85
-
86
- /* Structured prompt styles */
87
- .prompt-structured { font-size: 0.75rem; line-height: 1.5; }
88
- .prompt-section { border-bottom: 1px solid var(--border); padding: 0.5rem 0; }
89
- .prompt-section:last-child { border-bottom: none; }
90
- .prompt-objective { background: color-mix(in srgb, var(--active) 10%, transparent); border: 1px solid color-mix(in srgb, var(--active) 30%, transparent); border-radius: 6px; padding: 0.6rem 0.8rem; margin-bottom: 0.5rem; }
91
- .prompt-objective h4 { font-size: 0.8rem; color: var(--active); margin-bottom: 0.25rem; }
92
- .prompt-topology { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; padding: 0.4rem 0; font-size: 0.7rem; font-family: monospace; }
93
- .prompt-topology .topo-label { color: var(--muted); margin-right: 0.15rem; }
94
- .prompt-topology .topo-badge { display: inline-block; padding: 0.1rem 0.4rem; border-radius: 8px; background: var(--badge-bg); font-size: 0.7rem; }
95
- .prompt-scratchpad-entries { margin-top: 0.3rem; }
96
- .prompt-show-more { background: none; border: 1px solid var(--border); border-radius: 4px; padding: 0.2rem 0.5rem; font-size: 0.7rem; color: var(--muted); cursor: pointer; margin-bottom: 0.3rem; }
97
- .prompt-show-more:hover { background: var(--card-bg); color: var(--fg); }
98
- .prompt-raw-toggle { margin-top: 0.5rem; }
99
- .prompt-raw-toggle button { background: none; border: 1px solid var(--border); border-radius: 4px; padding: 0.2rem 0.6rem; font-size: 0.7rem; color: var(--muted); cursor: pointer; }
100
- .prompt-raw-toggle button:hover { background: var(--card-bg); color: var(--fg); }
101
- .prompt-raw-toggle pre { white-space: pre-wrap; font-size: 0.65rem; margin-top: 0.3rem; max-height: 400px; overflow-y: auto; background: var(--badge-bg); padding: 0.5rem; border-radius: 4px; }
102
-
103
- /* Routing badges and backpressure */
104
- .routing-badge { display: inline-block; font-size: 0.65rem; padding: 0.1rem 0.35rem; border-radius: 6px; background: var(--badge-bg); margin: 0.1rem 0.15rem; font-family: monospace; }
105
- .bp-none { color: var(--muted); font-style: italic; font-size: 0.7rem; }
106
- .bp-warning { display: inline-block; font-size: 0.7rem; padding: 0.15rem 0.4rem; border-radius: 6px; background: color-mix(in srgb, var(--watching) 15%, transparent); border: 1px solid color-mix(in srgb, var(--watching) 40%, transparent); color: var(--watching); font-family: monospace; }
107
-
108
- /* Merged indicator */
109
- .merged-badge { color: var(--completed); font-weight: 600; }
110
- .merge-detail { margin-top: 0.5rem; padding: 0.5rem; background: color-mix(in srgb, var(--completed) 8%, transparent); border: 1px solid color-mix(in srgb, var(--completed) 25%, transparent); border-radius: 4px; }
111
- .merge-detail .field label { color: var(--completed); }
112
- </style>
113
- </head>
114
- <body x-data="dashboard()" x-init="startPolling()">
115
-
116
- <header>
117
- <h1>autoloop dashboard</h1>
118
- <span class="updated" x-text="lastUpdated ? 'updated ' + lastUpdated : 'loading...'"></span>
119
- </header>
120
-
121
- <div class="chatbox">
122
- <select x-model="selectedPreset">
123
- <template x-for="p in presets" :key="p.name">
124
- <option :value="p.name" x-text="p.name"></option>
125
- </template>
126
- </select>
127
- <textarea x-model="newPrompt" placeholder="Describe what you want to do..." @keydown.meta.enter="startLoop()" @keydown.ctrl.enter="startLoop()"></textarea>
128
- <button @click="startLoop()">Start</button>
129
- </div>
130
-
131
- <template x-for="cat in categories" :key="cat.key">
132
- <details class="section" :open="sectionOpen[cat.key]" @toggle="sectionUserToggled[cat.key] = true; sectionOpen[cat.key] = $el.open">
133
- <summary>
134
- <span x-text="cat.label"></span>
135
- <span class="badge" :data-status="cat.key" x-text="cat.items.length"></span>
136
- </summary>
137
- <ul class="run-list">
138
- <template x-for="run in cat.items" :key="run.run_id">
139
- <li class="run-item" @click="selectRun(run.run_id)">
140
- <span>
141
- <span x-text="run.run_id.slice(0, 16)"></span>
142
- <span style="color:var(--muted)"> &middot; </span>
143
- <span x-text="run.preset"></span>
144
- <span style="color:var(--muted)"> &middot; iter </span>
145
- <span x-text="run.iteration + '/' + (run.max_iterations || '?')"></span>
146
- <template x-if="run.isolation_mode === 'worktree'">
147
- <span>
148
- <span class="badge wt-badge" :title="run.worktree_name || ''">WT</span>
149
- <template x-if="run.worktree_merged">
150
- <span class="merged-badge" title="merged"> &#x2713;</span>
151
- </template>
152
- </span>
153
- </template>
154
- </span>
155
- <span class="meta">
156
- <span x-text="run.latest_event || '-'"></span>
157
- <span style="color:var(--muted)"> &middot; </span>
158
- <span x-text="timeAgo(run.created_at)"></span>
159
- </span>
160
- </li>
161
- </template>
162
- <li class="empty" x-show="cat.items.length === 0">None</li>
163
- </ul>
164
- </details>
165
- </template>
166
-
167
- <div class="detail-pane" x-show="selectedRun" x-cloak>
168
- <h3 x-text="'Run: ' + (selectedRun || '')"></h3>
169
- <template x-if="selectedRunDetail">
170
- <div>
171
- <div class="field"><label>Status: </label><span x-text="selectedRunDetail.status"></span></div>
172
- <div class="field"><label>Preset: </label><span x-text="selectedRunDetail.preset"></span></div>
173
- <div class="field"><label>Objective: </label><span x-text="selectedRunDetail.objective"></span></div>
174
- <div class="field"><label>Iteration: </label><span x-text="selectedRunDetail.iteration + '/' + (selectedRunDetail.max_iterations || '?')"></span></div>
175
- <div class="field"><label>Workspace: </label><span :title="workspacePath(selectedRunDetail)" x-text="workspaceLabel(selectedRunDetail)"></span></div>
176
- <div class="field"><label>Created: </label><span :title="selectedRunDetail.created_at" x-text="timeAgo(selectedRunDetail.created_at) + ' ago'"></span></div>
177
- <div class="field"><label>Updated: </label><span :title="selectedRunDetail.updated_at" x-text="timeAgo(selectedRunDetail.updated_at) + ' ago'"></span></div>
178
- <div class="field"><label>Duration: </label><span x-text="runDuration()"></span></div>
179
- <div class="field"><label>Latest event: </label><span x-text="'[iter ' + selectedRunDetail.iteration + '] ' + selectedRunDetail.latest_event"></span></div>
180
- <div class="field"><label>Events: </label><span x-text="selectedRunEvents.length"></span></div>
181
- <template x-if="selectedRunDetail.worktree_merged">
182
- <div class="merge-detail">
183
- <div class="field"><label>Merge status: </label><span>merged</span></div>
184
- <div class="field" x-show="selectedRunDetail.worktree_merged_at"><label>Merged at: </label><span x-text="selectedRunDetail.worktree_merged_at"></span></div>
185
- <div class="field" x-show="selectedRunDetail.worktree_merge_strategy"><label>Merge strategy: </label><span x-text="selectedRunDetail.worktree_merge_strategy"></span></div>
186
- </div>
187
- </template>
188
- </div>
189
- </template>
190
- <div class="events-list">
191
- <div style="display:flex;justify-content:space-between;align-items:center">
192
- <h3>Events</h3>
193
- <label style="font-size:0.75rem;cursor:pointer"><input type="checkbox" x-model="showVerbose" style="margin-right:0.3rem">Show backend events</label>
194
- </div>
195
- <template x-for="(ev, idx) in visibleRunEvents()" :key="idx">
196
- <details :class="eventClasses(ev)">
197
- <summary x-text="eventSummary(ev)"></summary>
198
- <div style="padding:0.3rem">
199
- <template x-for="[k,v] in eventDisplayEntries(ev)" :key="k">
200
- <div class="event-field">
201
- <strong x-text="k + ':'"></strong>
202
- <template x-if="isPromptField(ev.topic, k)">
203
- <div x-data="{ showRaw: false, showAllScratchpad: false }" class="prompt-structured">
204
- <template x-if="parsePromptSections(String(v))">
205
- <div>
206
- <template x-if="parsePromptSections(String(v)).objective">
207
- <div class="prompt-section prompt-objective">
208
- <h4>Objective</h4>
209
- <div class="md-content" x-html="renderMarkdown(parsePromptSections(String(v)).objective)"></div>
210
- </div>
211
- </template>
212
- <template x-if="parsePromptSections(String(v)).topology">
213
- <div class="prompt-section">
214
- <strong style="font-size:0.75rem">Topology</strong>
215
- <div class="prompt-topology" x-html="renderTopologyBlock(parsePromptSections(String(v)).topology)"></div>
216
- </div>
217
- </template>
218
- <template x-if="parsePromptSections(String(v)).scratchpad">
219
- <div class="prompt-section">
220
- <strong style="font-size:0.75rem">Scratchpad</strong>
221
- <div class="prompt-scratchpad-entries">
222
- <template x-if="getScratchpadEntries(parsePromptSections(String(v)).scratchpad).length > 3">
223
- <div>
224
- <button class="prompt-show-more" x-show="!showAllScratchpad" @click="showAllScratchpad = true"
225
- x-text="'Show ' + (getScratchpadEntries(parsePromptSections(String(v)).scratchpad).length - 3) + ' older entries'"></button>
226
- <template x-if="showAllScratchpad">
227
- <div class="md-content" x-html="renderMarkdown(getScratchpadEntries(parsePromptSections(String(v)).scratchpad).slice(0, -3).join('\\n\\n'))"></div>
228
- </template>
229
- </div>
230
- </template>
231
- <div class="md-content" x-html="renderMarkdown(getScratchpadEntries(parsePromptSections(String(v)).scratchpad).slice(-3).join('\\n\\n'))"></div>
232
- </div>
233
- </div>
234
- </template>
235
- <template x-if="parsePromptSections(String(v)).memory">
236
- <details class="prompt-section">
237
- <summary style="cursor:pointer;font-size:0.75rem;font-weight:600">Loop Memory</summary>
238
- <div class="md-content" style="margin-top:0.3rem" x-html="renderMarkdown(parsePromptSections(String(v)).memory)"></div>
239
- </details>
240
- </template>
241
- <template x-if="parsePromptSections(String(v)).rules">
242
- <details class="prompt-section">
243
- <summary style="cursor:pointer;font-size:0.75rem;font-weight:600">Rules &amp; Event Tool</summary>
244
- <div class="md-content" style="margin-top:0.3rem" x-html="renderMarkdown(parsePromptSections(String(v)).rules)"></div>
245
- </details>
246
- </template>
247
- <template x-if="parsePromptSections(String(v)).config">
248
- <details class="prompt-section">
249
- <summary style="cursor:pointer;font-size:0.75rem;font-weight:600">Config</summary>
250
- <div class="md-content" style="margin-top:0.3rem" x-html="renderMarkdown(parsePromptSections(String(v)).config)"></div>
251
- </details>
252
- </template>
253
- <template x-if="parsePromptSections(String(v)).harness">
254
- <details class="prompt-section">
255
- <summary style="cursor:pointer;font-size:0.75rem;font-weight:600">Harness Instructions</summary>
256
- <div class="md-content" style="margin-top:0.3rem" x-html="renderMarkdown(parsePromptSections(String(v)).harness)"></div>
257
- </details>
258
- </template>
259
- <div class="prompt-raw-toggle">
260
- <button @click="showRaw = !showRaw" x-text="showRaw ? 'Hide raw prompt' : 'Show raw prompt'"></button>
261
- <template x-if="showRaw">
262
- <pre x-text="String(v)"></pre>
263
- </template>
264
- </div>
265
- </div>
266
- </template>
267
- </div>
268
- </template>
269
- <template x-if="!isPromptField(ev.topic, k) && isRoutingBadgeField(k)">
270
- <span x-html="renderRoutingValue(k, v)"></span>
271
- </template>
272
- <template x-if="!isPromptField(ev.topic, k) && !isRoutingBadgeField(k) && isMarkdownField(ev.topic, k)">
273
- <template x-if="String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length <= 200">
274
- <div class="md-content" x-html="renderMarkdown(typeof v === 'object' ? JSON.stringify(v,null,2) : String(v))"></div>
275
- </template>
276
- </template>
277
- <template x-if="!isPromptField(ev.topic, k) && !isRoutingBadgeField(k) && isMarkdownField(ev.topic, k)">
278
- <template x-if="String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length > 200">
279
- <details>
280
- <summary x-text="k + ' (' + String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length + ' chars)'"></summary>
281
- <div class="md-content" style="font-size:0.7rem;margin-top:0.2rem" x-html="renderMarkdown(typeof v === 'object' ? JSON.stringify(v,null,2) : String(v))"></div>
282
- </details>
283
- </template>
284
- </template>
285
- <template x-if="!isPromptField(ev.topic, k) && !isRoutingBadgeField(k) && !isMarkdownField(ev.topic, k)">
286
- <template x-if="String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length <= 200">
287
- <pre x-text="typeof v === 'object' ? JSON.stringify(v,null,2) : String(v)"></pre>
288
- </template>
289
- </template>
290
- <template x-if="!isPromptField(ev.topic, k) && !isRoutingBadgeField(k) && !isMarkdownField(ev.topic, k)">
291
- <template x-if="String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length > 200">
292
- <details>
293
- <summary x-text="k + ' (' + String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length + ' chars)'"></summary>
294
- <pre style="white-space:pre-wrap;font-size:0.7rem;margin-top:0.2rem" x-text="typeof v === 'object' ? JSON.stringify(v,null,2) : String(v)"></pre>
295
- </details>
296
- </template>
297
- </template>
298
- </div>
299
- </template>
300
- </div>
301
- </details>
302
- </template>
303
- <p class="empty" x-show="visibleRunEvents().length === 0">No events</p>
304
- </div>
305
- <div x-show="selectedRunDetail && selectedRunDetail.status === 'active'" style="display:flex;gap:0.4rem;align-items:center;margin-top:0.75rem;padding-top:0.75rem;border-top:1px solid var(--border)">
306
- <input type="text" x-model="guideMessage" placeholder="Send guidance..." @keydown.enter="sendGuide()"
307
- style="flex:1;padding:0.4rem 0.6rem;border:1px solid var(--border);border-radius:4px;font-size:0.8rem;font-family:inherit;background:var(--bg);color:var(--fg)">
308
- <button @click="sendGuide()" style="padding:0.4rem 0.8rem;border:none;border-radius:4px;background:var(--active);color:#fff;cursor:pointer;font-size:0.8rem;white-space:nowrap">Send</button>
309
- <span x-show="guideFlash" x-text="guideFlash" x-transition.opacity style="font-size:0.75rem;color:var(--completed)"></span>
310
- </div>
311
- </div>
312
-
313
- <script defer src="/static/alpine.min.js"></script>
314
- <script>
315
- function dashboard() {
316
- return {
317
- runs: { active: [], watching: [], stuck: [], recentFailed: [], recentCompleted: [] },
318
- presets: [],
319
- selectedRun: null,
320
- selectedRunDetail: null,
321
- selectedRunEvents: [],
322
- newPrompt: "",
323
- selectedPreset: "",
324
- pollInterval: null,
325
- lastUpdated: null,
326
- sectionOpen: { active: false, watching: false, stuck: false, failed: false, completed: false },
327
- sectionUserToggled: {},
328
- showVerbose: false,
329
- guideMessage: "",
330
- guideFlash: "",
331
-
332
- get categories() {
333
- return [
334
- { key: "active", label: "Active", items: this.runs.active },
335
- { key: "watching", label: "Watching", items: this.runs.watching },
336
- { key: "stuck", label: "Stuck", items: this.runs.stuck },
337
- { key: "failed", label: "Failed", items: this.runs.recentFailed },
338
- { key: "completed", label: "Completed", items: this.runs.recentCompleted },
339
- ];
340
- },
341
-
342
- async startPolling() {
343
- await this.fetchPresets();
344
- await this.fetchRuns();
345
- this.pollInterval = setInterval(() => this.fetchRuns(), 3000);
346
- },
347
-
348
- async fetchRuns() {
349
- try {
350
- const res = await fetch("/api/runs");
351
- this.runs = await res.json();
352
- this.lastUpdated = new Date().toLocaleTimeString();
353
- const defaultOpen = ['active', 'watching', 'stuck'];
354
- for (const cat of this.categories) {
355
- if (!this.sectionUserToggled[cat.key]) {
356
- this.sectionOpen[cat.key] = cat.items.length > 0 && defaultOpen.includes(cat.key);
357
- }
358
- }
359
- if (this.selectedRun) this.fetchEvents(this.selectedRun);
360
- } catch (e) { /* retry on next poll */ }
361
- },
362
-
363
- async fetchPresets() {
364
- try {
365
- const res = await fetch("/api/presets");
366
- const data = await res.json();
367
- this.presets = data.presets;
368
- if (this.presets.length && !this.selectedPreset) {
369
- this.selectedPreset = this.presets[0].name;
370
- }
371
- } catch (e) { /* ignore */ }
372
- },
373
-
374
- async selectRun(runId) {
375
- this.selectedRun = runId;
376
- try {
377
- const detailRes = await fetch("/api/runs/" + runId);
378
- if (detailRes.ok) this.selectedRunDetail = await detailRes.json();
379
- } catch (e) { /* ignore */ }
380
- await this.fetchEvents(runId);
381
- },
382
-
383
- async fetchEvents(runId) {
384
- try {
385
- const res = await fetch("/api/runs/" + runId + "/events");
386
- const data = await res.json();
387
- this.selectedRunEvents = data.events;
388
- } catch (e) { /* ignore */ }
389
- },
390
-
391
- async sendGuide() {
392
- if (!this.guideMessage.trim() || !this.selectedRun) return;
393
- try {
394
- const res = await fetch("/api/runs/" + this.selectedRun + "/guide", {
395
- method: "POST",
396
- headers: { "Content-Type": "application/json" },
397
- body: JSON.stringify({ message: this.guideMessage }),
398
- });
399
- if (res.ok) {
400
- this.guideMessage = "";
401
- this.guideFlash = "Sent";
402
- setTimeout(() => { this.guideFlash = ""; }, 2000);
403
- await this.fetchEvents(this.selectedRun);
404
- } else {
405
- const data = await res.json().catch(() => ({}));
406
- this.guideFlash = data.error || "Failed";
407
- setTimeout(() => { this.guideFlash = ""; }, 3000);
408
- }
409
- } catch (e) {
410
- this.guideFlash = "Error";
411
- setTimeout(() => { this.guideFlash = ""; }, 3000);
412
- }
413
- },
414
-
415
- async startLoop() {
416
- if (!this.newPrompt.trim()) return;
417
- await fetch("/api/runs", {
418
- method: "POST",
419
- headers: { "Content-Type": "application/json" },
420
- body: JSON.stringify({ prompt: this.newPrompt, preset: this.selectedPreset }),
421
- });
422
- this.newPrompt = "";
423
- setTimeout(() => this.fetchRuns(), 1000);
424
- },
425
-
426
- timeAgo(iso) {
427
- if (!iso) return "-";
428
- const s = Math.floor((Date.now() - new Date(iso)) / 1000);
429
- if (s < 0) return "0s";
430
- if (s < 60) return s + "s";
431
- if (s < 3600) return Math.floor(s / 60) + "m";
432
- return Math.floor(s / 3600) + "h";
433
- },
434
-
435
- runDuration() {
436
- const d = this.selectedRunDetail;
437
- if (!d || !d.created_at || !d.updated_at) return "-";
438
- const ms = new Date(d.updated_at) - new Date(d.created_at);
439
- if (ms < 0) return "-";
440
- const s = Math.floor(ms / 1000);
441
- if (s < 60) return s + "s";
442
- if (s < 3600) return Math.floor(s / 60) + "m " + (s % 60) + "s";
443
- return Math.floor(s / 3600) + "h " + Math.floor((s % 3600) / 60) + "m";
444
- },
445
-
446
- workspaceLabel(run) {
447
- if (!run) return "-";
448
- if (run.isolation_mode === "worktree") {
449
- return run.worktree_name || "worktree";
450
- }
451
- return "shared checkout";
452
- },
453
-
454
- workspacePath(run) {
455
- if (!run) return "";
456
- if (run.isolation_mode === "worktree") {
457
- return run.worktree_path || run.work_dir || "";
458
- }
459
- return run.work_dir || run.project_dir || "";
460
- },
461
-
462
- isMarkdownField(topic, key) {
463
- if (!topic || !key) return false;
464
- const t = String(topic);
465
- const k = String(key);
466
- if ((t === 'backend.finish' || t === 'iteration.finish') && k === 'output') return true;
467
- if (t === 'iteration.start' && k === 'prompt') return true;
468
- return false;
469
- },
470
-
471
- renderMarkdown(text) {
472
- if (!text) return '';
473
- let html = String(text);
474
- // Escape HTML
475
- html = html.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
476
- // Fenced code blocks
477
- html = html.replace(/^\\\`\\\`\\\`(\\w*)\\n([\\s\\S]*?)^\\\`\\\`\\\`/gm, function(_, lang, code) {
478
- return '<pre><code>' + code.trim() + '</code></pre>';
479
- });
480
- // Split into lines for block-level processing
481
- const lines = html.split('\\n');
482
- const out = [];
483
- let inList = false;
484
- let listType = '';
485
- for (let i = 0; i < lines.length; i++) {
486
- const line = lines[i];
487
- // Headings
488
- const hMatch = line.match(/^(#{1,6})\\s+(.+)$/);
489
- if (hMatch) {
490
- if (inList) { out.push('</' + listType + '>'); inList = false; }
491
- const lvl = hMatch[1].length;
492
- out.push('<h' + lvl + '>' + this._inlineMd(hMatch[2]) + '</h' + lvl + '>');
493
- continue;
494
- }
495
- // Unordered list
496
- const ulMatch = line.match(/^[\\-\\*]\\s+(.+)$/);
497
- if (ulMatch) {
498
- if (!inList || listType !== 'ul') {
499
- if (inList) out.push('</' + listType + '>');
500
- out.push('<ul>'); inList = true; listType = 'ul';
501
- }
502
- out.push('<li>' + this._inlineMd(ulMatch[1]) + '</li>');
503
- continue;
504
- }
505
- // Ordered list
506
- const olMatch = line.match(/^\\d+\\.\\s+(.+)$/);
507
- if (olMatch) {
508
- if (!inList || listType !== 'ol') {
509
- if (inList) out.push('</' + listType + '>');
510
- out.push('<ol>'); inList = true; listType = 'ol';
511
- }
512
- out.push('<li>' + this._inlineMd(olMatch[1]) + '</li>');
513
- continue;
514
- }
515
- // Close list if we hit non-list line
516
- if (inList) { out.push('</' + listType + '>'); inList = false; }
517
- // Empty line = paragraph break
518
- if (line.trim() === '') {
519
- out.push('');
520
- continue;
521
- }
522
- // Normal paragraph line
523
- out.push('<p>' + this._inlineMd(line) + '</p>');
524
- }
525
- if (inList) out.push('</' + listType + '>');
526
- return out.join('\\n');
527
- },
528
-
529
- _inlineMd(text) {
530
- // Inline code
531
- text = text.replace(/\\\`([^\\\`]+)\\\`/g, '<code>$1</code>');
532
- // Bold
533
- text = text.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');
534
- text = text.replace(/__(.+?)__/g, '<strong>$1</strong>');
535
- // Italic
536
- text = text.replace(/\\*(.+?)\\*/g, '<em>$1</em>');
537
- text = text.replace(/_(.+?)_/g, '<em>$1</em>');
538
- return text;
539
- },
540
-
541
- eventDisplayEntries(ev) {
542
- if (ev.topic === 'iteration.start' && ev.fields && typeof ev.fields === 'object') {
543
- const entries = [];
544
- for (const [k, v] of Object.entries(ev)) {
545
- if (k === 'fields') continue;
546
- entries.push([k, v]);
547
- }
548
- const fieldKeys = ['recent_event', 'suggested_roles', 'allowed_events', 'backpressure', 'prompt'];
549
- for (const fk of fieldKeys) {
550
- if (ev.fields[fk] !== undefined) {
551
- entries.push([fk, ev.fields[fk]]);
552
- }
553
- }
554
- return entries;
555
- }
556
- return Object.entries(ev);
557
- },
558
-
559
- isRoutingBadgeField(key) {
560
- return ['suggested_roles', 'allowed_events', 'backpressure', 'recent_event'].includes(String(key));
561
- },
562
-
563
- renderRoutingValue(key, value) {
564
- const k = String(key);
565
- const v = String(value || '');
566
- if (k === 'backpressure') {
567
- if (!v || v === 'none' || v === '') {
568
- return '<span class="bp-none">none</span>';
569
- }
570
- return '<span class="bp-warning">' + this._escHtml(v) + '</span>';
571
- }
572
- if (k === 'suggested_roles' || k === 'allowed_events') {
573
- const items = v.split(',').map(s => s.trim()).filter(Boolean);
574
- if (items.length === 0) return '<span class="bp-none">-</span>';
575
- return items.map(i => '<span class="routing-badge">' + this._escHtml(i) + '</span>').join(' ');
576
- }
577
- return '<span class="routing-badge">' + this._escHtml(v) + '</span>';
578
- },
579
-
580
- isPromptField(topic, key) {
581
- return String(topic) === 'iteration.start' && String(key) === 'prompt';
582
- },
583
-
584
- parsePromptSections(text) {
585
- if (!text) return null;
586
- const s = String(text);
587
- const sections = {};
588
-
589
- // Objective
590
- const objMatch = s.match(/Objective:\\n([\\s\\S]*?)(?=\\n(?:Loop memory:|Topology \\(advisory\\):|Current scratchpad:|Use the event tool|Iteration:|$))/);
591
- if (objMatch) sections.objective = objMatch[1].trim();
592
-
593
- // Topology
594
- const topoMatch = s.match(/Topology \\(advisory\\):\\n([\\s\\S]*?)(?=\\n(?:Iteration:|Current scratchpad:|Use the event tool|Loop memory:|Objective:|$))/);
595
- if (topoMatch) sections.topology = topoMatch[1].trim();
596
-
597
- // Scratchpad
598
- const scratchMatch = s.match(/Current scratchpad:\\n([\\s\\S]*?)(?=\\n(?:Use the event tool|Backpressure rule:|Plain text alone|$))/);
599
- if (scratchMatch) sections.scratchpad = scratchMatch[1].trim();
600
-
601
- // Rules (event tool usage + examples + backpressure)
602
- const rulesMatch = s.match(/(Use the event tool[\\s\\S]*?)$/);
603
- if (rulesMatch) sections.rules = rulesMatch[1].trim();
604
-
605
- // Loop memory
606
- const memMatch = s.match(/Loop memory:\\n([\\s\\S]*?)(?=\\n(?:Topology \\(advisory\\):|Current scratchpad:|Objective:|Iteration:|$))/);
607
- if (memMatch) sections.memory = memMatch[1].trim();
608
-
609
- // Config (Iteration, Log level, Completion event, etc.)
610
- const cfgMatch = s.match(/(Iteration:[\\s\\S]*?)(?=\\n(?:Current scratchpad:|Use the event tool|$))/);
611
- if (cfgMatch) sections.config = cfgMatch[1].trim();
612
-
613
- // Harness instructions
614
- const harnessMatch = s.match(/Live harness instructions:\\n([\\s\\S]*?)(?=\\n(?:Context pressure:|Objective:|Loop memory:|Topology|$))/);
615
- if (harnessMatch) sections.harness = harnessMatch[1].trim();
616
-
617
- return Object.keys(sections).length > 0 ? sections : null;
618
- },
619
-
620
- renderTopologyBlock(text) {
621
- if (!text) return '';
622
- let html = '';
623
- const lines = String(text).split('\\n');
624
- for (const line of lines) {
625
- const kv = line.match(/^([^:]+):\\s*(.+)$/);
626
- if (kv) {
627
- const label = kv[1].trim();
628
- const val = kv[2].trim();
629
- if (label === 'Suggested next roles' || label === 'Allowed next events' || label === 'Recent routing event') {
630
- html += '<span class="topo-label">' + this._escHtml(label) + ':</span> ';
631
- const items = val.split(',').map(s => s.trim()).filter(Boolean);
632
- for (const item of items) {
633
- html += '<span class="topo-badge">' + this._escHtml(item) + '</span> ';
634
- }
635
- } else {
636
- html += '<span class="topo-label">' + this._escHtml(label) + ':</span> <span>' + this._escHtml(val) + '</span> ';
637
- }
638
- }
639
- }
640
- // Role deck
641
- const deckMatch = text.match(/Role deck:\\n([\\s\\S]*?)$/);
642
- if (deckMatch) {
643
- const roles = deckMatch[1].match(/- role \`([^\`]+)\`/g);
644
- if (roles) {
645
- html += '<span class="topo-label">Roles:</span> ';
646
- for (const r of roles) {
647
- const name = r.match(/\`([^\`]+)\`/);
648
- if (name) html += '<span class="topo-badge">' + this._escHtml(name[1]) + '</span> ';
649
- }
650
- }
651
- }
652
- return html;
653
- },
654
-
655
- getScratchpadEntries(text) {
656
- if (!text) return [];
657
- // Split by "## Iteration N" headers
658
- const parts = String(text).split(/(?=## Iteration \\d+)/);
659
- return parts.filter(p => p.trim().length > 0);
660
- },
661
-
662
- _escHtml(s) {
663
- return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
664
- },
665
-
666
- visibleRunEvents() {
667
- return this.selectedRunEvents.filter(ev => this.showVerbose || !this.isBackendEvent(ev));
668
- },
669
-
670
- isBackendEvent(ev) {
671
- const t = String(ev?.topic || '');
672
- return t.startsWith('backend.');
673
- },
674
-
675
- eventCategory(ev) {
676
- const t = ev.topic || '';
677
- if (['event.invalid','wave.timeout','wave.failed','loop.stop'].includes(t)) return 'ev-error';
678
- if (t === 'task.complete' || t === 'loop.complete') return 'ev-completion';
679
- if (t.startsWith('review.')) return 'ev-review';
680
- if (t.startsWith('backend.')) return 'ev-backend';
681
- if (t.startsWith('iteration.')) return 'ev-system';
682
- return 'ev-coordination';
683
- },
684
-
685
- eventClasses(ev) {
686
- const classes = ['event-item', this.eventCategory(ev)];
687
- if ((ev.topic || '') === 'iteration.start') classes.push('ev-highlight');
688
- return classes.join(' ');
689
- },
690
-
691
- eventSummary(ev) {
692
- const parts = [];
693
- if (ev.iteration) parts.push('[iter ' + ev.iteration + ']');
694
- if (ev.ts) parts.push(this.timeAgo(ev.ts));
695
- parts.push(ev.topic || JSON.stringify(ev).slice(0, 80));
696
- const f = ev.fields || {};
697
- const t = ev.topic || '';
698
- if (t === 'iteration.start') {
699
- const hints = [];
700
- if (f.recent_event) hints.push(f.recent_event);
701
- if (f.suggested_roles) hints.push('\\u2192 ' + f.suggested_roles);
702
- if (f.allowed_events) hints.push('\\u00b7 emits ' + f.allowed_events);
703
- if (f.backpressure && String(f.backpressure) !== 'none' && String(f.backpressure).trim() !== '') {
704
- hints.push('[BP: ' + f.backpressure + ']');
705
- }
706
- if (hints.length) {
707
- parts.push('\\u2014 ' + hints.join(' '));
708
- } else if (f.prompt) {
709
- const objMatch = String(f.prompt).match(/Objective:\\s*\\n?([^\\n]+)/);
710
- if (objMatch) {
711
- const preview = objMatch[1].trim().slice(0, 100);
712
- parts.push('\\u2014 ' + preview + (objMatch[1].trim().length > 100 ? '...' : ''));
713
- }
714
- }
715
- } else if (t === 'review.start') {
716
- const f = ev.fields || {};
717
- parts.push('Review Started');
718
- const hint = [];
719
- if (f.reason) hint.push(String(f.reason).slice(0, 60));
720
- if (hint.length) parts.push('\\u2014 ' + hint.join(' '));
721
- } else if (t === 'review.finish') {
722
- const f = ev.fields || {};
723
- parts.push('Review Finished');
724
- const hint = [];
725
- if (f.decision) hint.push('decision=' + f.decision);
726
- if (f.output) hint.push(String(f.output).replace(/\\s+/g, ' ').trim().slice(0, 80));
727
- if (hint.length) parts.push('\\u2014 ' + hint.join(' '));
728
- } else if (t === 'iteration.finish' || t === 'backend.finish') {
729
- const hint = [];
730
- if (f.exit_code !== undefined) hint.push('exit=' + f.exit_code);
731
- if (f.timed_out === 'true' || f.timed_out === true) hint.push('TIMEOUT');
732
- if (f.elapsed_s !== undefined) hint.push(f.elapsed_s + 's');
733
- if (f.output) hint.push(String(f.output).replace(/\\s+/g, ' ').trim().slice(0, 80));
734
- if (hint.length) parts.push('\\u2014 ' + hint.join(' '));
735
- } else if (ev.payload) {
736
- parts.push('\\u2014 ' + String(ev.payload).slice(0, 60));
737
- }
738
- return parts.join(' ');
739
- },
740
- };
741
- }
742
- </script>
743
- </body>
744
- </html>`;
745
- }
746
- //# sourceMappingURL=shell.js.map