@wjarka/cezarion 0.10.0-pr30.54

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 (478) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +838 -0
  3. package/dist/agent-config/account-identity.d.ts +44 -0
  4. package/dist/agent-config/account-identity.js +128 -0
  5. package/dist/agent-config/account-identity.js.map +1 -0
  6. package/dist/agent-config/catalog.d.ts +72 -0
  7. package/dist/agent-config/catalog.js +223 -0
  8. package/dist/agent-config/catalog.js.map +1 -0
  9. package/dist/agent-config/files.d.ts +46 -0
  10. package/dist/agent-config/files.js +119 -0
  11. package/dist/agent-config/files.js.map +1 -0
  12. package/dist/agent-config/model-settings/claude.d.ts +2 -0
  13. package/dist/agent-config/model-settings/claude.js +11 -0
  14. package/dist/agent-config/model-settings/claude.js.map +1 -0
  15. package/dist/agent-config/model-settings/codex.d.ts +2 -0
  16. package/dist/agent-config/model-settings/codex.js +16 -0
  17. package/dist/agent-config/model-settings/codex.js.map +1 -0
  18. package/dist/agent-config/model-settings/opencode.d.ts +2 -0
  19. package/dist/agent-config/model-settings/opencode.js +8 -0
  20. package/dist/agent-config/model-settings/opencode.js.map +1 -0
  21. package/dist/agent-config/model-settings/pi.d.ts +12 -0
  22. package/dist/agent-config/model-settings/pi.js +18 -0
  23. package/dist/agent-config/model-settings/pi.js.map +1 -0
  24. package/dist/agent-config/model-settings/shared.d.ts +9 -0
  25. package/dist/agent-config/model-settings/shared.js +93 -0
  26. package/dist/agent-config/model-settings/shared.js.map +1 -0
  27. package/dist/agent-config/model-settings/types.d.ts +9 -0
  28. package/dist/agent-config/model-settings/types.js +2 -0
  29. package/dist/agent-config/model-settings/types.js.map +1 -0
  30. package/dist/agent-config/models.d.ts +9 -0
  31. package/dist/agent-config/models.js +32 -0
  32. package/dist/agent-config/models.js.map +1 -0
  33. package/dist/agent-config/seed.d.ts +7 -0
  34. package/dist/agent-config/seed.js +90 -0
  35. package/dist/agent-config/seed.js.map +1 -0
  36. package/dist/agent-config/service.d.ts +44 -0
  37. package/dist/agent-config/service.js +71 -0
  38. package/dist/agent-config/service.js.map +1 -0
  39. package/dist/agent-config/validate.d.ts +21 -0
  40. package/dist/agent-config/validate.js +76 -0
  41. package/dist/agent-config/validate.js.map +1 -0
  42. package/dist/automations/coordinator.d.ts +26 -0
  43. package/dist/automations/coordinator.js +66 -0
  44. package/dist/automations/coordinator.js.map +1 -0
  45. package/dist/automations/github-poller.d.ts +74 -0
  46. package/dist/automations/github-poller.js +234 -0
  47. package/dist/automations/github-poller.js.map +1 -0
  48. package/dist/automations/scheduler.d.ts +42 -0
  49. package/dist/automations/scheduler.js +192 -0
  50. package/dist/automations/scheduler.js.map +1 -0
  51. package/dist/automations/store.d.ts +65 -0
  52. package/dist/automations/store.js +298 -0
  53. package/dist/automations/store.js.map +1 -0
  54. package/dist/automations/task-template.d.ts +18 -0
  55. package/dist/automations/task-template.js +95 -0
  56. package/dist/automations/task-template.js.map +1 -0
  57. package/dist/automations/types.d.ts +255 -0
  58. package/dist/automations/types.js +159 -0
  59. package/dist/automations/types.js.map +1 -0
  60. package/dist/config.d.ts +77 -0
  61. package/dist/config.js +242 -0
  62. package/dist/config.js.map +1 -0
  63. package/dist/contract/agent-config.d.ts +153 -0
  64. package/dist/contract/agent-profiles.d.ts +347 -0
  65. package/dist/contract/automations.d.ts +935 -0
  66. package/dist/contract/events.d.ts +104 -0
  67. package/dist/contract/github.d.ts +556 -0
  68. package/dist/contract/health.d.ts +102 -0
  69. package/dist/contract/index.d.ts +16 -0
  70. package/dist/contract/index.js +1895 -0
  71. package/dist/contract/projects.d.ts +210 -0
  72. package/dist/contract/repo.d.ts +234 -0
  73. package/dist/contract/runs.d.ts +1473 -0
  74. package/dist/contract/skills.d.ts +232 -0
  75. package/dist/contract/workflows.d.ts +218 -0
  76. package/dist/contract/workspace.d.ts +579 -0
  77. package/dist/core/agent-env.d.ts +31 -0
  78. package/dist/core/agent-env.js +371 -0
  79. package/dist/core/agent-env.js.map +1 -0
  80. package/dist/core/agent-model-policy.d.ts +10 -0
  81. package/dist/core/agent-model-policy.js +36 -0
  82. package/dist/core/agent-model-policy.js.map +1 -0
  83. package/dist/core/agent-profiles.d.ts +62 -0
  84. package/dist/core/agent-profiles.js +90 -0
  85. package/dist/core/agent-profiles.js.map +1 -0
  86. package/dist/core/agent-runner.d.ts +211 -0
  87. package/dist/core/agent-runner.js +68 -0
  88. package/dist/core/agent-runner.js.map +1 -0
  89. package/dist/core/ask.d.ts +105 -0
  90. package/dist/core/ask.js +187 -0
  91. package/dist/core/ask.js.map +1 -0
  92. package/dist/core/backend-detect.d.ts +16 -0
  93. package/dist/core/backend-detect.js +155 -0
  94. package/dist/core/backend-detect.js.map +1 -0
  95. package/dist/core/claude-cli-runner.d.ts +59 -0
  96. package/dist/core/claude-cli-runner.js +483 -0
  97. package/dist/core/claude-cli-runner.js.map +1 -0
  98. package/dist/core/claude-ui-mapper.d.ts +80 -0
  99. package/dist/core/claude-ui-mapper.js +598 -0
  100. package/dist/core/claude-ui-mapper.js.map +1 -0
  101. package/dist/core/codex-app-server-runner.d.ts +41 -0
  102. package/dist/core/codex-app-server-runner.js +584 -0
  103. package/dist/core/codex-app-server-runner.js.map +1 -0
  104. package/dist/core/codex-app-server-transport.d.ts +35 -0
  105. package/dist/core/codex-app-server-transport.js +150 -0
  106. package/dist/core/codex-app-server-transport.js.map +1 -0
  107. package/dist/core/codex-model-catalog.d.ts +10 -0
  108. package/dist/core/codex-model-catalog.js +110 -0
  109. package/dist/core/codex-model-catalog.js.map +1 -0
  110. package/dist/core/codex-ui-mapper.d.ts +112 -0
  111. package/dist/core/codex-ui-mapper.js +766 -0
  112. package/dist/core/codex-ui-mapper.js.map +1 -0
  113. package/dist/core/model-identity.d.ts +125 -0
  114. package/dist/core/model-identity.js +132 -0
  115. package/dist/core/model-identity.js.map +1 -0
  116. package/dist/core/model-presets.d.ts +21 -0
  117. package/dist/core/model-presets.js +81 -0
  118. package/dist/core/model-presets.js.map +1 -0
  119. package/dist/core/ndjson.d.ts +6 -0
  120. package/dist/core/ndjson.js +23 -0
  121. package/dist/core/ndjson.js.map +1 -0
  122. package/dist/core/opencode-model-catalog.d.ts +32 -0
  123. package/dist/core/opencode-model-catalog.js +153 -0
  124. package/dist/core/opencode-model-catalog.js.map +1 -0
  125. package/dist/core/opencode-server-runner.d.ts +32 -0
  126. package/dist/core/opencode-server-runner.js +882 -0
  127. package/dist/core/opencode-server-runner.js.map +1 -0
  128. package/dist/core/opencode-ui-mapper.d.ts +137 -0
  129. package/dist/core/opencode-ui-mapper.js +800 -0
  130. package/dist/core/opencode-ui-mapper.js.map +1 -0
  131. package/dist/core/pi-model-catalog.d.ts +31 -0
  132. package/dist/core/pi-model-catalog.js +152 -0
  133. package/dist/core/pi-model-catalog.js.map +1 -0
  134. package/dist/core/pi-runner.d.ts +24 -0
  135. package/dist/core/pi-runner.js +403 -0
  136. package/dist/core/pi-runner.js.map +1 -0
  137. package/dist/core/pi-ui-mapper.d.ts +36 -0
  138. package/dist/core/pi-ui-mapper.js +304 -0
  139. package/dist/core/pi-ui-mapper.js.map +1 -0
  140. package/dist/core/process-usage.d.ts +66 -0
  141. package/dist/core/process-usage.js +193 -0
  142. package/dist/core/process-usage.js.map +1 -0
  143. package/dist/core/provider-auth.d.ts +154 -0
  144. package/dist/core/provider-auth.js +509 -0
  145. package/dist/core/provider-auth.js.map +1 -0
  146. package/dist/core/provider-availability.d.ts +3 -0
  147. package/dist/core/provider-availability.js +14 -0
  148. package/dist/core/provider-availability.js.map +1 -0
  149. package/dist/core/runner-factory.d.ts +8 -0
  150. package/dist/core/runner-factory.js +25 -0
  151. package/dist/core/runner-factory.js.map +1 -0
  152. package/dist/core/runner-model-catalog.d.ts +29 -0
  153. package/dist/core/runner-model-catalog.js +78 -0
  154. package/dist/core/runner-model-catalog.js.map +1 -0
  155. package/dist/core/secret-redaction.d.ts +37 -0
  156. package/dist/core/secret-redaction.js +115 -0
  157. package/dist/core/secret-redaction.js.map +1 -0
  158. package/dist/core/shell-env.d.ts +28 -0
  159. package/dist/core/shell-env.js +56 -0
  160. package/dist/core/shell-env.js.map +1 -0
  161. package/dist/core/tool-display.d.ts +31 -0
  162. package/dist/core/tool-display.js +179 -0
  163. package/dist/core/tool-display.js.map +1 -0
  164. package/dist/core/ui-events.d.ts +335 -0
  165. package/dist/core/ui-events.js +25 -0
  166. package/dist/core/ui-events.js.map +1 -0
  167. package/dist/core/usage-limit.d.ts +42 -0
  168. package/dist/core/usage-limit.js +209 -0
  169. package/dist/core/usage-limit.js.map +1 -0
  170. package/dist/core/usage.d.ts +11 -0
  171. package/dist/core/usage.js +15 -0
  172. package/dist/core/usage.js.map +1 -0
  173. package/dist/core/v1-text-coalescer.d.ts +36 -0
  174. package/dist/core/v1-text-coalescer.js +72 -0
  175. package/dist/core/v1-text-coalescer.js.map +1 -0
  176. package/dist/git-diff-base.d.ts +85 -0
  177. package/dist/git-diff-base.js +180 -0
  178. package/dist/git-diff-base.js.map +1 -0
  179. package/dist/git-refs.d.ts +11 -0
  180. package/dist/git-refs.js +14 -0
  181. package/dist/git-refs.js.map +1 -0
  182. package/dist/git-worktree.d.ts +161 -0
  183. package/dist/git-worktree.js +508 -0
  184. package/dist/git-worktree.js.map +1 -0
  185. package/dist/handoff.d.ts +62 -0
  186. package/dist/handoff.js +154 -0
  187. package/dist/handoff.js.map +1 -0
  188. package/dist/index.d.ts +2 -0
  189. package/dist/index.js +680 -0
  190. package/dist/index.js.map +1 -0
  191. package/dist/install-as-command.d.ts +40 -0
  192. package/dist/install-as-command.js +52 -0
  193. package/dist/install-as-command.js.map +1 -0
  194. package/dist/pack-check.d.ts +17 -0
  195. package/dist/pack-check.js +27 -0
  196. package/dist/pack-check.js.map +1 -0
  197. package/dist/paths.d.ts +140 -0
  198. package/dist/paths.js +192 -0
  199. package/dist/paths.js.map +1 -0
  200. package/dist/planner.d.ts +27 -0
  201. package/dist/planner.js +268 -0
  202. package/dist/planner.js.map +1 -0
  203. package/dist/release/manifests.d.ts +81 -0
  204. package/dist/release/manifests.js +74 -0
  205. package/dist/release/manifests.js.map +1 -0
  206. package/dist/release/snapshot.d.ts +67 -0
  207. package/dist/release/snapshot.js +97 -0
  208. package/dist/release/snapshot.js.map +1 -0
  209. package/dist/release/stable.d.ts +38 -0
  210. package/dist/release/stable.js +55 -0
  211. package/dist/release/stable.js.map +1 -0
  212. package/dist/runs/agent-tmpdir.d.ts +41 -0
  213. package/dist/runs/agent-tmpdir.js +183 -0
  214. package/dist/runs/agent-tmpdir.js.map +1 -0
  215. package/dist/runs/auto-name.d.ts +75 -0
  216. package/dist/runs/auto-name.js +179 -0
  217. package/dist/runs/auto-name.js.map +1 -0
  218. package/dist/runs/event-history.d.ts +50 -0
  219. package/dist/runs/event-history.js +613 -0
  220. package/dist/runs/event-history.js.map +1 -0
  221. package/dist/runs/retention.d.ts +60 -0
  222. package/dist/runs/retention.js +86 -0
  223. package/dist/runs/retention.js.map +1 -0
  224. package/dist/runs/review-gate.d.ts +18 -0
  225. package/dist/runs/review-gate.js +21 -0
  226. package/dist/runs/review-gate.js.map +1 -0
  227. package/dist/runs/run-index.d.ts +19 -0
  228. package/dist/runs/run-index.js +43 -0
  229. package/dist/runs/run-index.js.map +1 -0
  230. package/dist/runs/store.d.ts +446 -0
  231. package/dist/runs/store.js +1118 -0
  232. package/dist/runs/store.js.map +1 -0
  233. package/dist/runs/task-markers.d.ts +28 -0
  234. package/dist/runs/task-markers.js +74 -0
  235. package/dist/runs/task-markers.js.map +1 -0
  236. package/dist/runs/task-refs.d.ts +25 -0
  237. package/dist/runs/task-refs.js +74 -0
  238. package/dist/runs/task-refs.js.map +1 -0
  239. package/dist/runs/ui-event-sink.d.ts +81 -0
  240. package/dist/runs/ui-event-sink.js +210 -0
  241. package/dist/runs/ui-event-sink.js.map +1 -0
  242. package/dist/server/app-type.d.ts +21 -0
  243. package/dist/server/app-type.js +2 -0
  244. package/dist/server/app-type.js.map +1 -0
  245. package/dist/server/capabilities.d.ts +70 -0
  246. package/dist/server/capabilities.js +152 -0
  247. package/dist/server/capabilities.js.map +1 -0
  248. package/dist/server/checkout.d.ts +128 -0
  249. package/dist/server/checkout.js +296 -0
  250. package/dist/server/checkout.js.map +1 -0
  251. package/dist/server/forge/github.d.ts +513 -0
  252. package/dist/server/forge/github.js +2364 -0
  253. package/dist/server/forge/github.js.map +1 -0
  254. package/dist/server/forge/index.d.ts +40 -0
  255. package/dist/server/forge/index.js +72 -0
  256. package/dist/server/forge/index.js.map +1 -0
  257. package/dist/server/forge/types.d.ts +242 -0
  258. package/dist/server/forge/types.js +2 -0
  259. package/dist/server/forge/types.js.map +1 -0
  260. package/dist/server/fs-browse.d.ts +105 -0
  261. package/dist/server/fs-browse.js +182 -0
  262. package/dist/server/fs-browse.js.map +1 -0
  263. package/dist/server/git-changes.d.ts +213 -0
  264. package/dist/server/git-changes.js +555 -0
  265. package/dist/server/git-changes.js.map +1 -0
  266. package/dist/server/git.d.ts +28 -0
  267. package/dist/server/git.js +112 -0
  268. package/dist/server/git.js.map +1 -0
  269. package/dist/server/github.d.ts +9 -0
  270. package/dist/server/github.js +8 -0
  271. package/dist/server/github.js.map +1 -0
  272. package/dist/server/launch-key.d.ts +7 -0
  273. package/dist/server/launch-key.js +33 -0
  274. package/dist/server/launch-key.js.map +1 -0
  275. package/dist/server/open-in-app.d.ts +66 -0
  276. package/dist/server/open-in-app.js +211 -0
  277. package/dist/server/open-in-app.js.map +1 -0
  278. package/dist/server/open-in-terminal.d.ts +70 -0
  279. package/dist/server/open-in-terminal.js +179 -0
  280. package/dist/server/open-in-terminal.js.map +1 -0
  281. package/dist/server/pr.d.ts +7 -0
  282. package/dist/server/pr.js +7 -0
  283. package/dist/server/pr.js.map +1 -0
  284. package/dist/server/project-context.d.ts +120 -0
  285. package/dist/server/project-context.js +182 -0
  286. package/dist/server/project-context.js.map +1 -0
  287. package/dist/server/provider-action-gate.d.ts +8 -0
  288. package/dist/server/provider-action-gate.js +56 -0
  289. package/dist/server/provider-action-gate.js.map +1 -0
  290. package/dist/server/provider-auth-runtime.d.ts +21 -0
  291. package/dist/server/provider-auth-runtime.js +66 -0
  292. package/dist/server/provider-auth-runtime.js.map +1 -0
  293. package/dist/server/server.d.ts +13138 -0
  294. package/dist/server/server.js +5263 -0
  295. package/dist/server/server.js.map +1 -0
  296. package/dist/server/static-ui.d.ts +49 -0
  297. package/dist/server/static-ui.js +92 -0
  298. package/dist/server/static-ui.js.map +1 -0
  299. package/dist/server/validators.d.ts +97 -0
  300. package/dist/server/validators.js +86 -0
  301. package/dist/server/validators.js.map +1 -0
  302. package/dist/server/ws.d.ts +85 -0
  303. package/dist/server/ws.js +218 -0
  304. package/dist/server/ws.js.map +1 -0
  305. package/dist/server/wsl.d.ts +25 -0
  306. package/dist/server/wsl.js +92 -0
  307. package/dist/server/wsl.js.map +1 -0
  308. package/dist/server-install/engine.d.ts +50 -0
  309. package/dist/server-install/engine.js +324 -0
  310. package/dist/server-install/engine.js.map +1 -0
  311. package/dist/server-install/platforms/macosx-ngrok.d.ts +6 -0
  312. package/dist/server-install/platforms/macosx-ngrok.js +345 -0
  313. package/dist/server-install/platforms/macosx-ngrok.js.map +1 -0
  314. package/dist/server-install/platforms/ubuntu-vps.d.ts +78 -0
  315. package/dist/server-install/platforms/ubuntu-vps.js +1016 -0
  316. package/dist/server-install/platforms/ubuntu-vps.js.map +1 -0
  317. package/dist/server-install/state.d.ts +52 -0
  318. package/dist/server-install/state.js +182 -0
  319. package/dist/server-install/state.js.map +1 -0
  320. package/dist/server-install/steps.d.ts +109 -0
  321. package/dist/server-install/steps.js +334 -0
  322. package/dist/server-install/steps.js.map +1 -0
  323. package/dist/server-install/strategies.d.ts +4 -0
  324. package/dist/server-install/strategies.js +20 -0
  325. package/dist/server-install/strategies.js.map +1 -0
  326. package/dist/server-install/types.d.ts +287 -0
  327. package/dist/server-install/types.js +121 -0
  328. package/dist/server-install/types.js.map +1 -0
  329. package/dist/server-install/ui.d.ts +42 -0
  330. package/dist/server-install/ui.js +130 -0
  331. package/dist/server-install/ui.js.map +1 -0
  332. package/dist/skills-banner.d.ts +22 -0
  333. package/dist/skills-banner.js +41 -0
  334. package/dist/skills-banner.js.map +1 -0
  335. package/dist/skills-remote.d.ts +84 -0
  336. package/dist/skills-remote.js +468 -0
  337. package/dist/skills-remote.js.map +1 -0
  338. package/dist/skills-update.d.ts +88 -0
  339. package/dist/skills-update.js +392 -0
  340. package/dist/skills-update.js.map +1 -0
  341. package/dist/skills.d.ts +82 -0
  342. package/dist/skills.js +251 -0
  343. package/dist/skills.js.map +1 -0
  344. package/dist/todos.d.ts +48 -0
  345. package/dist/todos.js +201 -0
  346. package/dist/todos.js.map +1 -0
  347. package/dist/ui-state.d.ts +26 -0
  348. package/dist/ui-state.js +38 -0
  349. package/dist/ui-state.js.map +1 -0
  350. package/dist/update-check.d.ts +12 -0
  351. package/dist/update-check.js +41 -0
  352. package/dist/update-check.js.map +1 -0
  353. package/dist/workflows/load.d.ts +15 -0
  354. package/dist/workflows/load.js +56 -0
  355. package/dist/workflows/load.js.map +1 -0
  356. package/dist/workflows/run.d.ts +758 -0
  357. package/dist/workflows/run.js +3389 -0
  358. package/dist/workflows/run.js.map +1 -0
  359. package/dist/workflows/types.d.ts +153 -0
  360. package/dist/workflows/types.js +212 -0
  361. package/dist/workflows/types.js.map +1 -0
  362. package/dist/workspace/agent-accounts.d.ts +153 -0
  363. package/dist/workspace/agent-accounts.js +304 -0
  364. package/dist/workspace/agent-accounts.js.map +1 -0
  365. package/dist/workspace/agent-profiles.d.ts +78 -0
  366. package/dist/workspace/agent-profiles.js +115 -0
  367. package/dist/workspace/agent-profiles.js.map +1 -0
  368. package/dist/workspace/config.d.ts +169 -0
  369. package/dist/workspace/config.js +379 -0
  370. package/dist/workspace/config.js.map +1 -0
  371. package/dist/workspace/migrations.d.ts +45 -0
  372. package/dist/workspace/migrations.js +147 -0
  373. package/dist/workspace/migrations.js.map +1 -0
  374. package/dist/workspace/projects-cli.d.ts +25 -0
  375. package/dist/workspace/projects-cli.js +172 -0
  376. package/dist/workspace/projects-cli.js.map +1 -0
  377. package/dist/workspace/projects.d.ts +109 -0
  378. package/dist/workspace/projects.js +250 -0
  379. package/dist/workspace/projects.js.map +1 -0
  380. package/dist/workspace/semaphore.d.ts +179 -0
  381. package/dist/workspace/semaphore.js +195 -0
  382. package/dist/workspace/semaphore.js.map +1 -0
  383. package/dist/workspace/ui-state.d.ts +34 -0
  384. package/dist/workspace/ui-state.js +53 -0
  385. package/dist/workspace/ui-state.js.map +1 -0
  386. package/package.json +70 -0
  387. package/scripts/check-pack.mjs +46 -0
  388. package/scripts/inline-contract.mjs +112 -0
  389. package/scripts/install-as-command.mjs +120 -0
  390. package/scripts/mock-claude.mjs +520 -0
  391. package/scripts/mock-pi-rpc.mjs +83 -0
  392. package/scripts/sync-readme.mjs +20 -0
  393. package/scripts/test-process-usage.mjs +47 -0
  394. package/web/dist/assets/alert-dialog-B4Ofsgv7.js +1 -0
  395. package/web/dist/assets/arrow-down-Dy8dup7j.js +1 -0
  396. package/web/dist/assets/arrow-left-BJaucbhn.js +1 -0
  397. package/web/dist/assets/bundle-mjs-BT31bpU6.js +1 -0
  398. package/web/dist/assets/centered-state-duPW0phQ.js +43 -0
  399. package/web/dist/assets/chevron-right-Be4A5TCS.js +1 -0
  400. package/web/dist/assets/chunk-BO2N2NFS-DE6qKn3r.js +131 -0
  401. package/web/dist/assets/collapsible-DdcNBdSk.js +1 -0
  402. package/web/dist/assets/commit-list-CgvN9vec.js +1 -0
  403. package/web/dist/assets/compare-variants-CQA2nd65.js +1 -0
  404. package/web/dist/assets/core-BCsw8oQw.js +12 -0
  405. package/web/dist/assets/css-BsVw1vtW.js +1 -0
  406. package/web/dist/assets/diff-B6Agp5Hl.js +3 -0
  407. package/web/dist/assets/diff-stat-BoXuGkgq.js +1 -0
  408. package/web/dist/assets/diff-view-CD8XI-fj.js +6 -0
  409. package/web/dist/assets/diff-woXpYk--.js +1 -0
  410. package/web/dist/assets/dropdown-menu-B3SYw-k5.js +1 -0
  411. package/web/dist/assets/editable-title-B-hjp5wl.js +1 -0
  412. package/web/dist/assets/ellipsis-vertical-BYwzw0xl.js +1 -0
  413. package/web/dist/assets/engine-javascript-FQvzRocB.js +141 -0
  414. package/web/dist/assets/file-BRj5eISx.js +1 -0
  415. package/web/dist/assets/folder-z4oT5981.js +1 -0
  416. package/web/dist/assets/git-toolbar-owSEkYld.js +1 -0
  417. package/web/dist/assets/github-Bz2VgRX3.js +1 -0
  418. package/web/dist/assets/go-rLFTqkRN.js +1 -0
  419. package/web/dist/assets/highlighted-body-OFNGDK62-BL-MfFgl.js +1 -0
  420. package/web/dist/assets/highlighter-CdHqIwFr.js +3 -0
  421. package/web/dist/assets/html-BY76lXLH.js +1 -0
  422. package/web/dist/assets/image-preview-h3WFluuy.js +1 -0
  423. package/web/dist/assets/index-BbcQNT92.css +2 -0
  424. package/web/dist/assets/index-EtQQQ6Kj.js +7 -0
  425. package/web/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  426. package/web/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  427. package/web/dist/assets/javascript-BgS3c2Ky.js +1 -0
  428. package/web/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  429. package/web/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  430. package/web/dist/assets/json-qhed-kSA.js +1 -0
  431. package/web/dist/assets/jsonc-CYpm1nAK.js +1 -0
  432. package/web/dist/assets/jsx-Bz0zcwM4.js +1 -0
  433. package/web/dist/assets/lib-BQXq3kEf.js +1 -0
  434. package/web/dist/assets/lib-BxQXEXDF.js +1 -0
  435. package/web/dist/assets/markdown-BYOwaDjH.js +1 -0
  436. package/web/dist/assets/markdown-DqBKYPiB.js +2 -0
  437. package/web/dist/assets/mermaid-GHXKKRXX-C4jxqUUb.js +1 -0
  438. package/web/dist/assets/new-task-form-BdJKRBJX.js +1 -0
  439. package/web/dist/assets/pill-BQfmfpYp.js +1 -0
  440. package/web/dist/assets/project-router-DxgFZY1l.js +1 -0
  441. package/web/dist/assets/prompt-templates-B6m16gq-.js +15 -0
  442. package/web/dist/assets/python-gzcpVVnB.js +1 -0
  443. package/web/dist/assets/react-runtime-CCIEwYL0.js +9 -0
  444. package/web/dist/assets/refresh-cw-mhSpxf2a.js +1 -0
  445. package/web/dist/assets/repo-git-CUNRxR3_.js +1 -0
  446. package/web/dist/assets/rolldown-runtime-QTnfLwEv.js +1 -0
  447. package/web/dist/assets/run-diff-DsmmDVfx.js +3 -0
  448. package/web/dist/assets/run-header-BkhrseLJ.js +1 -0
  449. package/web/dist/assets/rust-Cfkwpbl8.js +1 -0
  450. package/web/dist/assets/search-x-BqDMB2g8.js +1 -0
  451. package/web/dist/assets/shellscript-CLZ0U2zV.js +1 -0
  452. package/web/dist/assets/skill-empty-hint-BWEvTggc.js +1 -0
  453. package/web/dist/assets/skills-9oR_oHse.js +1 -0
  454. package/web/dist/assets/skills-DwIxnnWO.js +1 -0
  455. package/web/dist/assets/sparkles-DIoTQpyx.js +1 -0
  456. package/web/dist/assets/sql-BsFa4tDR.js +1 -0
  457. package/web/dist/assets/square-terminal-Cc7CuQxc.js +1 -0
  458. package/web/dist/assets/tab-link-D1fQgpmO.js +1 -0
  459. package/web/dist/assets/task-changes-BKeLlDpK.js +1 -0
  460. package/web/dist/assets/task-commits-gcEFZIa5.js +1 -0
  461. package/web/dist/assets/task-files-BGAqoXTW.js +2 -0
  462. package/web/dist/assets/task-thread-DT8aUYTS.js +9 -0
  463. package/web/dist/assets/textarea-BOVbfy5C.js +1 -0
  464. package/web/dist/assets/thread-loading-CypW73KD.js +1 -0
  465. package/web/dist/assets/toml-CcmNWLt0.js +1 -0
  466. package/web/dist/assets/trash-2-CJq6LHWn.js +1 -0
  467. package/web/dist/assets/triangle-alert-CjDFvU27.js +1 -0
  468. package/web/dist/assets/tsx-udAQXfEw.js +1 -0
  469. package/web/dist/assets/typescript-bsJCZSQ-.js +1 -0
  470. package/web/dist/assets/upload-CPDZlJeK.js +1 -0
  471. package/web/dist/assets/use-desktop-5JsLmi0a.js +1 -0
  472. package/web/dist/assets/use-submit-shortcut-CHVFevty.js +1 -0
  473. package/web/dist/assets/utils-DiO6zyJd.js +64 -0
  474. package/web/dist/assets/workflows-rQDFzWRt.js +11 -0
  475. package/web/dist/assets/yaml-rwi0_p6S.js +1 -0
  476. package/web/dist/assets/zoomable-image-COWqb11v.js +1 -0
  477. package/web/dist/index.html +80 -0
  478. package/web/dist/open-mercato.svg +11 -0
package/dist/skills.js ADDED
@@ -0,0 +1,251 @@
1
+ import { readdir, readFile, realpath, stat } from 'node:fs/promises';
2
+ import { homedir } from 'node:os';
3
+ import { join, resolve, basename, dirname, extname } from 'node:path';
4
+ import { gatedSkillsRepos } from './config.js';
5
+ import { getTeamSkillsCached } from './skills-remote.js';
6
+ import { readWorkspaceUiState } from './workspace/ui-state.js';
7
+ /* Precedence order — earlier dirs win name collisions. `npx skills` writes
8
+ the canonical copy to `.agents/skills/<name>/SKILL.md` and mirrors it into
9
+ each agent's dir (often as symlinks) — scanning them all and deduping by
10
+ name yields exactly the union of unique skills.
11
+
12
+ Exported for the drift guard in `test/unit/skill-dirs.test.ts` (#374): the
13
+ cockpit's empty-state hint hand-copies this list into the bundle
14
+ (`packages/web/src/components/skill-empty-hint.tsx`) because it runs in another
15
+ process, so adding a dir here without updating the hint makes the hint lie.
16
+ That test pins this list and says where to go. */
17
+ export const SKILL_DIRS = [
18
+ { dir: '.ai/cezar/skills', source: 'cezar' },
19
+ { dir: '.ai/skills', source: 'ai' },
20
+ { dir: '.agents/skills', source: 'agents' },
21
+ { dir: '.claude/skills', source: 'agents' },
22
+ { dir: '.codex/skills', source: 'agents' },
23
+ { dir: '.cursor/skills', source: 'agents' },
24
+ { dir: '.opencode/skills', source: 'agents' },
25
+ ];
26
+ /* Deliberately `homedir()` and not `agentHomePaths().claude`: these do NOT follow an
27
+ agent profile (`src/core/agent-profiles.ts`). A skill is CONTENT — a playbook — not
28
+ identity, and a second Claude login is not a second skill library. `npx skills`, which
29
+ writes the `~/.claude/skills` mirror, is profile-unaware for the same reason. */
30
+ const GLOBAL_SKILL_DIRS = [
31
+ { dir: join(homedir(), '.agents/skills'), source: 'global' },
32
+ { dir: join(homedir(), '.claude/skills'), source: 'global' },
33
+ ];
34
+ /**
35
+ * Discover the merged skill catalog for a repo. Name collisions resolve
36
+ * local-first: `.ai/cezar/skills` → `.ai/skills` → `.agents/skills` + agent
37
+ * mirrors → global (`~/.agents/skills`, `~/.claude/skills`) → team repo
38
+ * ("the user's repo is the source of truth"). Missing directories are fine —
39
+ * an empty catalog is fully supported (steps fall back to their plain
40
+ * prompt). Team skills come from the in-process cache; the first call starts
41
+ * a background load so nothing here ever waits on the network.
42
+ *
43
+ * Opt-out gate: skills from a *default* (vendor) skills repo — `open-mercato/skills`
44
+ * for the zero-config majority, see `gatedSkillsRepos` — appear unless the user has
45
+ * curated them away. `importedSkills` in the GLOBAL `~/.cezar/ui-state.json` (not the
46
+ * per-repo file — the selection describes the person and must not depend on the launch
47
+ * directory, multi-project workspace) is a tri-state: ABSENT means "not curated" and
48
+ * every default skill shows (the historical behavior — no upgrade break for existing
49
+ * installs); a PRESENT array (even `[]`) means the user has taken control and only those
50
+ * names show. A repo that sets its own `skillsRepos` gates nothing regardless. This is the
51
+ * single chokepoint, so the decision is identical for every consumer — catalog, composer
52
+ * picker, planner, runner.
53
+ */
54
+ export async function discoverSkills(repoRoot) {
55
+ const [lists, gatedRepos, uiState] = await Promise.all([
56
+ Promise.all([
57
+ ...SKILL_DIRS.map(({ dir, source }) => readMarkdownSkills(resolve(repoRoot, dir), source)),
58
+ ...GLOBAL_SKILL_DIRS.map(({ dir, source }) => readMarkdownSkills(dir, source)),
59
+ ]),
60
+ gatedSkillsRepos(repoRoot),
61
+ readWorkspaceUiState(),
62
+ ]);
63
+ const teamSkills = filterImportedTeamSkills(getTeamSkillsCached(repoRoot), gatedRepos, readImportedSkills(uiState));
64
+ const merged = [];
65
+ const seen = new Set();
66
+ for (const skills of [...lists, teamSkills]) {
67
+ for (const skill of skills) {
68
+ if (seen.has(skill.name))
69
+ continue;
70
+ seen.add(skill.name);
71
+ merged.push(skill);
72
+ }
73
+ }
74
+ merged.sort((a, b) => a.name.localeCompare(b.name));
75
+ return merged;
76
+ }
77
+ /**
78
+ * The imported team-skill names from a raw `ui-state.json` object, as a tri-state:
79
+ * `undefined` means the key is absent — "not curated", so every default skill shows
80
+ * (the opt-out default that keeps existing installs whole); an array (even empty) is
81
+ * the user's explicit selection. Defensive because the file is user-editable: a value
82
+ * that is not an array degrades to `undefined` (keep all — the safe, backward-compatible
83
+ * reading), and non-string / empty entries inside an array are dropped rather than thrown on.
84
+ */
85
+ export function readImportedSkills(uiState) {
86
+ const value = uiState.importedSkills;
87
+ if (!Array.isArray(value))
88
+ return undefined;
89
+ return value.filter((name) => typeof name === 'string' && name.length > 0);
90
+ }
91
+ /**
92
+ * The opt-out gate: keep every team skill whose repo is NOT gated (a repo with its own
93
+ * configured `skillsRepos` — auto-loads everything). For skills from a gated default
94
+ * (vendor) repo, `importedSkills === undefined` keeps them ALL (not curated — the
95
+ * historical behavior), while a present array keeps only the named ones. Local skills
96
+ * carry no `team` and are always kept. Pure so the gate is unit-testable without a
97
+ * network clone (the gated set is a const default otherwise).
98
+ */
99
+ export function filterImportedTeamSkills(teamSkills, gatedRepos, importedSkills) {
100
+ // Not curated → the full default catalog still appears (no upgrade break).
101
+ if (importedSkills === undefined)
102
+ return [...teamSkills];
103
+ const imported = new Set(importedSkills);
104
+ return teamSkills.filter((skill) => !skill.team || !gatedRepos.has(skill.team.repo) || imported.has(skill.name));
105
+ }
106
+ /**
107
+ * Walk a skills dir for entrypoints, following directory symlinks. Once a
108
+ * directory contains `SKILL.md`, it is one directory-based skill and its
109
+ * supporting Markdown (for example `references/*.md`) is not scanned. Other
110
+ * directories retain the legacy recursive `*.md` discovery behavior.
111
+ */
112
+ async function skillEntryPaths(dir, depth, visited) {
113
+ if (depth < 0)
114
+ return [];
115
+ let real;
116
+ try {
117
+ real = await realpath(dir);
118
+ }
119
+ catch {
120
+ return []; // missing dir or dangling symlink
121
+ }
122
+ if (visited.has(real))
123
+ return [];
124
+ visited.add(real);
125
+ let entries;
126
+ try {
127
+ entries = await readdir(dir, { withFileTypes: true });
128
+ }
129
+ catch {
130
+ return [];
131
+ }
132
+ const skillEntry = entries.find((entry) => entry.name === 'SKILL.md');
133
+ if (skillEntry) {
134
+ const skillPath = join(dir, skillEntry.name);
135
+ try {
136
+ if ((await stat(skillPath)).isFile())
137
+ return [skillPath];
138
+ }
139
+ catch {
140
+ // A dangling or unreadable SKILL.md does not hide other valid entries.
141
+ }
142
+ }
143
+ const paths = [];
144
+ for (const entry of entries) {
145
+ const path = join(dir, entry.name);
146
+ let isDir = entry.isDirectory();
147
+ if (entry.isSymbolicLink()) {
148
+ try {
149
+ isDir = (await stat(path)).isDirectory(); // stat follows the link
150
+ }
151
+ catch {
152
+ continue; // dangling symlink
153
+ }
154
+ }
155
+ if (isDir) {
156
+ paths.push(...(await skillEntryPaths(path, depth - 1, visited)));
157
+ }
158
+ else if (extname(entry.name).toLowerCase() === '.md') {
159
+ paths.push(path);
160
+ }
161
+ }
162
+ return paths;
163
+ }
164
+ async function readMarkdownSkills(dir, source) {
165
+ const paths = await skillEntryPaths(dir, 4, new Set());
166
+ const skills = [];
167
+ for (const absPath of paths) {
168
+ let raw;
169
+ try {
170
+ raw = await readFile(absPath, 'utf8');
171
+ }
172
+ catch {
173
+ continue;
174
+ }
175
+ const { frontmatter, body } = parseFrontmatter(raw);
176
+ const base = basename(absPath, extname(absPath));
177
+ // The `SKILL.md` convention names the skill after its directory.
178
+ const fallback = base.toLowerCase() === 'skill' ? basename(dirname(absPath)) : base;
179
+ const name = typeof frontmatter.name === 'string' && frontmatter.name.trim()
180
+ ? frontmatter.name.trim()
181
+ : fallback;
182
+ const description = typeof frontmatter.description === 'string' && frontmatter.description.trim()
183
+ ? frontmatter.description.trim()
184
+ : undefined;
185
+ const interactive = frontmatter.interactive === 'true' ? true : undefined;
186
+ skills.push({ name, description, interactive, body, path: absPath, source });
187
+ }
188
+ return skills;
189
+ }
190
+ /**
191
+ * Tiny purpose-built frontmatter parser — a leading `---\n … \n---\n` block
192
+ * with `key: value` lines, `key: [a, b]` inline arrays and `key:` + ` - a`
193
+ * block arrays. Deliberately not full YAML so we avoid a parser dependency
194
+ * for skill files.
195
+ */
196
+ export function parseFrontmatter(raw) {
197
+ // Normalize CRLF and lone CR — otherwise frontmatter is silently dropped.
198
+ const text = raw.replace(/\r\n?/g, '\n');
199
+ if (!text.startsWith('---\n'))
200
+ return { frontmatter: {}, body: raw };
201
+ // Match the closing delimiter only on its own line so a `---` thematic
202
+ // break inside the body doesn't terminate the block early.
203
+ const end = text.indexOf('\n---\n', 4);
204
+ const endAtEof = text.endsWith('\n---') ? text.length - 4 : -1;
205
+ const closeAt = end === -1 ? endAtEof : end;
206
+ if (closeAt === -1)
207
+ return { frontmatter: {}, body: raw };
208
+ const block = text.slice(4, closeAt);
209
+ const afterDelimiter = end === -1 ? -1 : text.indexOf('\n', closeAt + 1);
210
+ const body = afterDelimiter === -1 ? '' : text.slice(afterDelimiter + 1);
211
+ const frontmatter = {};
212
+ const lines = block.split('\n');
213
+ for (let i = 0; i < lines.length; i++) {
214
+ const line = lines[i] ?? '';
215
+ if (!line.trim() || line.trim().startsWith('#'))
216
+ continue;
217
+ const m = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(line);
218
+ if (!m)
219
+ continue;
220
+ const key = m[1];
221
+ const rest = (m[2] ?? '').trim();
222
+ if (rest === '') {
223
+ const items = [];
224
+ while (i + 1 < lines.length && /^\s*-\s+/.test(lines[i + 1] ?? '')) {
225
+ items.push(stripQuotes((lines[i + 1] ?? '').replace(/^\s*-\s+/, '').trim()));
226
+ i++;
227
+ }
228
+ frontmatter[key] = items;
229
+ continue;
230
+ }
231
+ if (rest.startsWith('[') && rest.endsWith(']')) {
232
+ const inner = rest.slice(1, -1).trim();
233
+ frontmatter[key] = inner
234
+ ? inner
235
+ .split(',')
236
+ .map((s) => stripQuotes(s.trim()))
237
+ .filter((s) => s.length > 0)
238
+ : [];
239
+ continue;
240
+ }
241
+ frontmatter[key] = stripQuotes(rest);
242
+ }
243
+ return { frontmatter, body };
244
+ }
245
+ function stripQuotes(s) {
246
+ if ((s.startsWith('"') && s.endsWith('"')) || (s.startsWith("'") && s.endsWith("'"))) {
247
+ return s.slice(1, -1);
248
+ }
249
+ return s;
250
+ }
251
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * The global follow-up inbox (spec 007): `.ai/cezar/todos.json`, a flat JSON
4
+ * array agents append to (via CEZ_TODOS_FILE). Agent entries are external
5
+ * data — each one is zod-validated on read and malformed ones are skipped
6
+ * with a warning, never fatal. Server writes are serialized with an
7
+ * in-process lock (the janitor `withLock` pattern) and land atomically
8
+ * (tmp + rename, the runs.json pattern).
9
+ */
10
+ export declare const todoSchema: z.ZodObject<{
11
+ id: z.ZodOptional<z.ZodString>;
12
+ ts: z.ZodOptional<z.ZodString>;
13
+ taskId: z.ZodOptional<z.ZodString>;
14
+ summary: z.ZodString;
15
+ action: z.ZodOptional<z.ZodString>;
16
+ prUrl: z.ZodOptional<z.ZodString>;
17
+ suggestedSkill: z.ZodOptional<z.ZodString>;
18
+ suggestedArgs: z.ZodOptional<z.ZodString>;
19
+ suggestedPrompt: z.ZodOptional<z.ZodString>;
20
+ runnable: z.ZodOptional<z.ZodBoolean>;
21
+ startedTaskId: z.ZodOptional<z.ZodString>;
22
+ }, z.core.$strip>;
23
+ export type TodoItem = z.infer<typeof todoSchema> & {
24
+ id: string;
25
+ };
26
+ export declare function todosPath(dataDir: string): string;
27
+ export declare function readTodos(dataDir: string): Promise<TodoItem[]>;
28
+ /** Check off (delete) an entry. False when the id isn't there. */
29
+ export declare function removeTodo(dataDir: string, id: string): Promise<boolean>;
30
+ /** The task text "▶ Run" turns an entry into: the suggested prompt (or the summary when the
31
+ * entry carries none), plus the suggested args as a trailing line. The single server-side
32
+ * source for `POST /api/todos/:id/start`; the cockpit's prefill copy
33
+ * (`packages/web/src/routes/inbox.tsx`, #374) lives in another process and cannot import this, so
34
+ * the two are pinned to the shared cases in `test/fixtures/todo-task-text.json`. */
35
+ export declare function todoTaskText(todo: Pick<TodoItem, 'summary' | 'suggestedPrompt' | 'suggestedArgs'>): string;
36
+ /** Record that "▶ Run" turned the entry into task `taskId`. The entry stays
37
+ * in the file as an audit trail; the GUI hides started entries. First start wins: an entry
38
+ * that already carries a `startedTaskId` is left untouched and answers false, so the
39
+ * best-effort `todoId` bookkeeping on `POST /api/runs` (#374) can never overwrite the audit
40
+ * trail — the check shares this lock, so two concurrent launches cannot both claim the entry. */
41
+ export declare function markStarted(dataDir: string, id: string, taskId: string): Promise<boolean>;
42
+ /** Subscribe to `dataDir`'s inbox changes; the watch is created on the first
43
+ * subscription and torn down when the last subscriber leaves. Returns the
44
+ * unsubscribe function (idempotent — a stale double call can never tear down
45
+ * a watch that later subscribers re-created). */
46
+ export declare function onTodosChanged(dataDir: string, cb: () => void): () => void;
47
+ /** Test hook: is a live watch registered for `dataDir`? */
48
+ export declare function todosWatchActive(dataDir: string): boolean;
package/dist/todos.js ADDED
@@ -0,0 +1,201 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { promises as fs } from 'node:fs';
4
+ import { mkdirSync, watch } from 'node:fs';
5
+ import { join } from 'node:path';
6
+ import { z } from 'zod';
7
+ /**
8
+ * The global follow-up inbox (spec 007): `.ai/cezar/todos.json`, a flat JSON
9
+ * array agents append to (via CEZ_TODOS_FILE). Agent entries are external
10
+ * data — each one is zod-validated on read and malformed ones are skipped
11
+ * with a warning, never fatal. Server writes are serialized with an
12
+ * in-process lock (the janitor `withLock` pattern) and land atomically
13
+ * (tmp + rename, the runs.json pattern).
14
+ */
15
+ export const todoSchema = z.object({
16
+ id: z.string().min(1).optional(),
17
+ ts: z.string().optional(),
18
+ taskId: z.string().optional(),
19
+ summary: z.string().min(1),
20
+ action: z.string().optional(),
21
+ prUrl: z.string().optional(),
22
+ suggestedSkill: z.string().optional(),
23
+ suggestedArgs: z.string().optional(),
24
+ suggestedPrompt: z.string().optional(),
25
+ /** Explicit intent; legacy entries infer it from an executable suggestion. */
26
+ runnable: z.boolean().optional(),
27
+ /** Set by the server when "▶ Run" turned this entry into a task. */
28
+ startedTaskId: z.string().optional(),
29
+ });
30
+ export function todosPath(dataDir) {
31
+ return join(dataDir, 'todos.json');
32
+ }
33
+ // ---- in-process lock (15-line port of janitor's storage.withLock) ----------
34
+ const locks = new Map();
35
+ async function withLock(key, fn) {
36
+ const prev = locks.get(key) ?? Promise.resolve();
37
+ let release = () => undefined;
38
+ const next = new Promise((r) => {
39
+ release = r;
40
+ });
41
+ locks.set(key, prev.then(() => next));
42
+ try {
43
+ await prev;
44
+ return await fn();
45
+ }
46
+ finally {
47
+ release();
48
+ }
49
+ }
50
+ // ---- read / write -----------------------------------------------------------
51
+ /** Parse + validate the file. Broken JSON / non-array → []; bad entries are
52
+ * skipped with a warning; entries without an id get one assigned. */
53
+ async function readRaw(dataDir) {
54
+ let raw;
55
+ try {
56
+ raw = await fs.readFile(todosPath(dataDir), 'utf8');
57
+ }
58
+ catch {
59
+ return { items: [], needsRewrite: false }; // no file yet — empty inbox
60
+ }
61
+ let parsed;
62
+ try {
63
+ parsed = JSON.parse(raw);
64
+ }
65
+ catch (err) {
66
+ const message = err instanceof Error ? err.message : String(err);
67
+ console.warn(`[cez] todos.json is not valid JSON — showing an empty inbox (${message})`);
68
+ return { items: [], needsRewrite: false };
69
+ }
70
+ if (!Array.isArray(parsed)) {
71
+ console.warn('[cez] todos.json is not a JSON array — showing an empty inbox');
72
+ return { items: [], needsRewrite: false };
73
+ }
74
+ const items = [];
75
+ let needsRewrite = false;
76
+ for (const entry of parsed) {
77
+ const result = todoSchema.safeParse(entry);
78
+ if (!result.success) {
79
+ console.warn(`[cez] skipped a malformed todos.json entry: ${result.error.issues.map((i) => i.message).join('; ')}`);
80
+ continue;
81
+ }
82
+ if (!result.data.id) {
83
+ // Agent entries arrive without ids — assign one so the GUI can address
84
+ // the entry; the file is rewritten (under the lock) on this read.
85
+ needsRewrite = true;
86
+ items.push({ ...result.data, id: randomUUID() });
87
+ }
88
+ else {
89
+ items.push({ ...result.data, id: result.data.id });
90
+ }
91
+ }
92
+ return { items, needsRewrite };
93
+ }
94
+ async function writeAtomic(dataDir, items) {
95
+ const file = todosPath(dataDir);
96
+ const tmp = `${file}.tmp`;
97
+ await fs.mkdir(dataDir, { recursive: true });
98
+ await fs.writeFile(tmp, JSON.stringify(items, null, 2), 'utf8');
99
+ await fs.rename(tmp, file);
100
+ }
101
+ export async function readTodos(dataDir) {
102
+ return withLock(dataDir, async () => {
103
+ const { items, needsRewrite } = await readRaw(dataDir);
104
+ if (needsRewrite) {
105
+ await writeAtomic(dataDir, items).catch(() => undefined); // best effort
106
+ }
107
+ return items;
108
+ });
109
+ }
110
+ /** Check off (delete) an entry. False when the id isn't there. */
111
+ export async function removeTodo(dataDir, id) {
112
+ return withLock(dataDir, async () => {
113
+ const { items } = await readRaw(dataDir);
114
+ const next = items.filter((t) => t.id !== id);
115
+ if (next.length === items.length)
116
+ return false;
117
+ await writeAtomic(dataDir, next);
118
+ return true;
119
+ });
120
+ }
121
+ /** The task text "▶ Run" turns an entry into: the suggested prompt (or the summary when the
122
+ * entry carries none), plus the suggested args as a trailing line. The single server-side
123
+ * source for `POST /api/todos/:id/start`; the cockpit's prefill copy
124
+ * (`packages/web/src/routes/inbox.tsx`, #374) lives in another process and cannot import this, so
125
+ * the two are pinned to the shared cases in `test/fixtures/todo-task-text.json`. */
126
+ export function todoTaskText(todo) {
127
+ let task = (todo.suggestedPrompt ?? todo.summary).trim() || todo.summary;
128
+ if (todo.suggestedArgs)
129
+ task += `\n\nArguments: ${todo.suggestedArgs}`;
130
+ return task;
131
+ }
132
+ /** Record that "▶ Run" turned the entry into task `taskId`. The entry stays
133
+ * in the file as an audit trail; the GUI hides started entries. First start wins: an entry
134
+ * that already carries a `startedTaskId` is left untouched and answers false, so the
135
+ * best-effort `todoId` bookkeeping on `POST /api/runs` (#374) can never overwrite the audit
136
+ * trail — the check shares this lock, so two concurrent launches cannot both claim the entry. */
137
+ export async function markStarted(dataDir, id, taskId) {
138
+ return withLock(dataDir, async () => {
139
+ const { items } = await readRaw(dataDir);
140
+ const item = items.find((t) => t.id === id);
141
+ if (!item || item.startedTaskId)
142
+ return false;
143
+ item.startedTaskId = taskId;
144
+ await writeAtomic(dataDir, items);
145
+ return true;
146
+ });
147
+ }
148
+ const watches = new Map();
149
+ /** Start watching `dataDir` for todos.json changes (agents write it from
150
+ * another process). Degrades to a watcher-less entry on error. */
151
+ function startWatch(dataDir) {
152
+ const emitter = new EventEmitter();
153
+ emitter.setMaxListeners(100);
154
+ const entry = { emitter, watcher: undefined, timer: undefined };
155
+ try {
156
+ mkdirSync(dataDir, { recursive: true });
157
+ const watcher = watch(dataDir, (_event, filename) => {
158
+ if (filename && filename !== 'todos.json')
159
+ return;
160
+ if (entry.timer)
161
+ clearTimeout(entry.timer);
162
+ entry.timer = setTimeout(() => emitter.emit('changed'), 300);
163
+ entry.timer.unref?.();
164
+ });
165
+ watcher.on('error', () => undefined); // a dying watcher must not kill the server
166
+ watcher.unref?.();
167
+ entry.watcher = watcher;
168
+ }
169
+ catch (err) {
170
+ const message = err instanceof Error ? err.message : String(err);
171
+ console.warn(`[cez] todos watch unavailable — the Inbox updates on refresh only (${message})`);
172
+ }
173
+ watches.set(dataDir, entry);
174
+ return entry;
175
+ }
176
+ /** Subscribe to `dataDir`'s inbox changes; the watch is created on the first
177
+ * subscription and torn down when the last subscriber leaves. Returns the
178
+ * unsubscribe function (idempotent — a stale double call can never tear down
179
+ * a watch that later subscribers re-created). */
180
+ export function onTodosChanged(dataDir, cb) {
181
+ const entry = watches.get(dataDir) ?? startWatch(dataDir);
182
+ entry.emitter.on('changed', cb);
183
+ let unsubscribed = false;
184
+ return () => {
185
+ if (unsubscribed)
186
+ return;
187
+ unsubscribed = true;
188
+ entry.emitter.off('changed', cb);
189
+ if (entry.emitter.listenerCount('changed') > 0)
190
+ return;
191
+ if (entry.timer)
192
+ clearTimeout(entry.timer);
193
+ entry.watcher?.close();
194
+ watches.delete(dataDir);
195
+ };
196
+ }
197
+ /** Test hook: is a live watch registered for `dataDir`? */
198
+ export function todosWatchActive(dataDir) {
199
+ return watches.has(dataDir);
200
+ }
201
+ //# sourceMappingURL=todos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"todos.js","sourceRoot":"","sources":["../src/todos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAkB,MAAM,SAAS,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;GAOG;AAEH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAChC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACzB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACtC,8EAA8E;IAC9E,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAChC,oEAAoE;IACpE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAC;AAIH,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,OAAO,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;AACrC,CAAC;AAED,+EAA+E;AAE/E,MAAM,KAAK,GAAG,IAAI,GAAG,EAA4B,CAAC;AAElD,KAAK,UAAU,QAAQ,CAAI,GAAW,EAAE,EAAoB;IAC1D,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IACjD,IAAI,OAAO,GAAe,GAAG,EAAE,CAAC,SAAS,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE;QACnC,OAAO,GAAG,CAAC,CAAC;IACd,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IACtC,IAAI,CAAC;QACH,MAAM,IAAI,CAAC;QACX,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,gFAAgF;AAEhF;sEACsE;AACtE,KAAK,UAAU,OAAO,CAAC,OAAe;IACpC,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,4BAA4B;IACzE,CAAC;IACD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC,gEAAgE,OAAO,GAAG,CAAC,CAAC;QACzF,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IAC5C,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;QAC9E,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IAC5C,CAAC;IACD,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,+CAA+C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpH,SAAS;QACX,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACpB,uEAAuE;YACvE,kEAAkE;YAClE,YAAY,GAAG,IAAI,CAAC;YACpB,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QACnD,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;AACjC,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,OAAe,EAAE,KAAiB;IAC3D,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAChC,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,CAAC;IAC1B,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAChE,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe;IAC7C,OAAO,QAAQ,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;QAClC,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;QACvD,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc;QAC1E,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;AACL,CAAC;AAED,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,EAAU;IAC1D,OAAO,QAAQ,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;QAClC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9C,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAC/C,MAAM,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;qFAIqF;AACrF,MAAM,UAAU,YAAY,CAC1B,IAAqE;IAErE,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC;IACzE,IAAI,IAAI,CAAC,aAAa;QAAE,IAAI,IAAI,kBAAkB,IAAI,CAAC,aAAa,EAAE,CAAC;IACvE,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;kGAIkG;AAClG,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAe,EAAE,EAAU,EAAE,MAAc;IAC3E,OAAO,QAAQ,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;QAClC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa;YAAE,OAAO,KAAK,CAAC;QAC9C,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC;QAC5B,MAAM,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAqBD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsB,CAAC;AAE9C;mEACmE;AACnE,SAAS,UAAU,CAAC,OAAe;IACjC,MAAM,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;IACnC,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAe,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC5E,IAAI,CAAC;QACH,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;YAClD,IAAI,QAAQ,IAAI,QAAQ,KAAK,YAAY;gBAAE,OAAO;YAClD,IAAI,KAAK,CAAC,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC3C,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC;YAC7D,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,2CAA2C;QACjF,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;QAClB,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC,sEAAsE,OAAO,GAAG,CAAC,CAAC;IACjG,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC5B,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;kDAGkD;AAClD,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,EAAc;IAC5D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;IAC1D,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAChC,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,OAAO,GAAG,EAAE;QACV,IAAI,YAAY;YAAE,OAAO;QACzB,YAAY,GAAG,IAAI,CAAC;QACpB,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACjC,IAAI,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,CAAC;YAAE,OAAO;QACvD,IAAI,KAAK,CAAC,KAAK;YAAE,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC3C,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;QACvB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC,CAAC;AACJ,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { UiState } from './contract/index.js';
2
+ /**
3
+ * `.ai/cezar/ui-state.json` — small GUI preferences the cockpit persists (files, not a DB).
4
+ * The server owns the schema and the writes (`PUT /api/ui-state` in `src/server/server.ts`);
5
+ * this is the shared read path, so the CLI can honour a preference the cockpit set (#391's
6
+ * `dismissedSkillsBanner`) without a second notion of where the file lives.
7
+ *
8
+ * Same zero-config rule as `src/config.ts`: missing, unreadable or malformed all degrade to
9
+ * `{}` — an absent preference, never a throw, never a blocked startup.
10
+ */
11
+ export declare function uiStatePath(repoRoot: string): string;
12
+ /**
13
+ * Read `ui-state.json` on demand — never cached, never throws.
14
+ *
15
+ * Typed by the CONTRACT (`UiState`), not by a loose record: `GET /api/v1/ui-state` answers this
16
+ * value verbatim, so a `Record<string, unknown>` here made the route name no key at all and the
17
+ * per-route parity guard vacuous — the same defect `healthSnapshot` had. `UiState` is a
18
+ * `z.looseObject`, so the index signature (and with it the round-trip promise of
19
+ * BACKWARD_COMPATIBILITY.md §3) survives; what it adds is the NAMES of the keys the server knows.
20
+ *
21
+ * The cast is unchanged in kind — the file is user-editable JSON and is deliberately NOT parsed
22
+ * through the schema, because a single malformed pref must not discard the whole bag (§3). What
23
+ * the type asserts is the wire shape the route promises; the write side (`PUT /ui-state`, validated
24
+ * by `uiStateBody`) is what actually enforces it.
25
+ */
26
+ export declare function readUiState(repoRoot: string): Promise<UiState>;
@@ -0,0 +1,38 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ /**
4
+ * `.ai/cezar/ui-state.json` — small GUI preferences the cockpit persists (files, not a DB).
5
+ * The server owns the schema and the writes (`PUT /api/ui-state` in `src/server/server.ts`);
6
+ * this is the shared read path, so the CLI can honour a preference the cockpit set (#391's
7
+ * `dismissedSkillsBanner`) without a second notion of where the file lives.
8
+ *
9
+ * Same zero-config rule as `src/config.ts`: missing, unreadable or malformed all degrade to
10
+ * `{}` — an absent preference, never a throw, never a blocked startup.
11
+ */
12
+ export function uiStatePath(repoRoot) {
13
+ return join(repoRoot, '.ai/cezar', 'ui-state.json');
14
+ }
15
+ /**
16
+ * Read `ui-state.json` on demand — never cached, never throws.
17
+ *
18
+ * Typed by the CONTRACT (`UiState`), not by a loose record: `GET /api/v1/ui-state` answers this
19
+ * value verbatim, so a `Record<string, unknown>` here made the route name no key at all and the
20
+ * per-route parity guard vacuous — the same defect `healthSnapshot` had. `UiState` is a
21
+ * `z.looseObject`, so the index signature (and with it the round-trip promise of
22
+ * BACKWARD_COMPATIBILITY.md §3) survives; what it adds is the NAMES of the keys the server knows.
23
+ *
24
+ * The cast is unchanged in kind — the file is user-editable JSON and is deliberately NOT parsed
25
+ * through the schema, because a single malformed pref must not discard the whole bag (§3). What
26
+ * the type asserts is the wire shape the route promises; the write side (`PUT /ui-state`, validated
27
+ * by `uiStateBody`) is what actually enforces it.
28
+ */
29
+ export async function readUiState(repoRoot) {
30
+ try {
31
+ const parsed = JSON.parse(await readFile(uiStatePath(repoRoot), 'utf8'));
32
+ return parsed && typeof parsed === 'object' ? parsed : {};
33
+ }
34
+ catch {
35
+ return {};
36
+ }
37
+ }
38
+ //# sourceMappingURL=ui-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-state.js","sourceRoot":"","sources":["../src/ui-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,OAAO,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;AACtD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB;IAChD,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QAClF,OAAO,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAE,MAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;IACzE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Update discovery (#368): a best-effort, fire-and-forget check against the
3
+ * npm registry so the cockpit can tell the user a newer cezar exists — the
4
+ * root cause behind most "bug already fixed" reports is `npx` happily reusing
5
+ * a stale cached version forever. Silent on any failure: offline, slow
6
+ * registry or a weird payload must never affect startup.
7
+ */
8
+ /** Newest published version when it's newer than `current`, else null. */
9
+ export declare function checkForUpdate(pkgName: string, current: string): Promise<string | null>;
10
+ /** Plain numeric semver compare (`1.2.10` > `1.2.9`); pre-release tags and
11
+ * anything unparseable compare as 0 — good enough for release-only publishes. */
12
+ export declare function isNewerVersion(candidate: string, current: string): boolean;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Update discovery (#368): a best-effort, fire-and-forget check against the
3
+ * npm registry so the cockpit can tell the user a newer cezar exists — the
4
+ * root cause behind most "bug already fixed" reports is `npx` happily reusing
5
+ * a stale cached version forever. Silent on any failure: offline, slow
6
+ * registry or a weird payload must never affect startup.
7
+ */
8
+ const REGISTRY_TIMEOUT_MS = 3_000;
9
+ /** Newest published version when it's newer than `current`, else null. */
10
+ export async function checkForUpdate(pkgName, current) {
11
+ try {
12
+ const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(pkgName)}/latest`, {
13
+ signal: AbortSignal.timeout(REGISTRY_TIMEOUT_MS),
14
+ });
15
+ if (!res.ok)
16
+ return null;
17
+ const data = (await res.json());
18
+ const latest = typeof data.version === 'string' ? data.version : null;
19
+ return latest && isNewerVersion(latest, current) ? latest : null;
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ }
25
+ /** Plain numeric semver compare (`1.2.10` > `1.2.9`); pre-release tags and
26
+ * anything unparseable compare as 0 — good enough for release-only publishes. */
27
+ export function isNewerVersion(candidate, current) {
28
+ const parse = (v) => v
29
+ .split('.')
30
+ .slice(0, 3)
31
+ .map((part) => Number.parseInt(part, 10) || 0);
32
+ const a = parse(candidate);
33
+ const b = parse(current);
34
+ for (let i = 0; i < 3; i++) {
35
+ const diff = (a[i] ?? 0) - (b[i] ?? 0);
36
+ if (diff !== 0)
37
+ return diff > 0;
38
+ }
39
+ return false;
40
+ }
41
+ //# sourceMappingURL=update-check.js.map