@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
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Provider usage-limit detection (spec 2026-08-03-auto-resume-after-usage-limit).
3
+ *
4
+ * A subscription that runs out of its window does not fail like an agent bug does: the work is
5
+ * fine, the account is simply closed until a KNOWN instant. That instant is the whole feature —
6
+ * without it there is nothing to schedule, so this module answers exactly one question about a
7
+ * terminal error string: "is this a usage limit, and when does it lift?".
8
+ *
9
+ * The evidence differs per backend, so the shapes are recognized in order of how exact they are:
10
+ *
11
+ * 1. Claude Code's machine-readable envelope, `Claude AI usage limit reached|<epoch>` — the CLI
12
+ * puts it in an `is_error` result frame, which reaches cezar verbatim as the run's `error`.
13
+ * Exact, no locale, no parsing of prose. This is the one that matters in practice.
14
+ * 2. An explicit reset instant in the prose (`try again at 2026-08-03T18:00:00Z`) — how Codex and
15
+ * OpenCode phrase the same thing when they carry a timestamp at all.
16
+ * 3. A clock-only reset in prose (`resets 8:10pm (Europe/Warsaw)`) — how Claude Code phrases
17
+ * session windows in some interactive output.
18
+ * 4. A relative delay (`try again in 42 minutes`, `retry-after: 3600`).
19
+ *
20
+ * Nothing else counts. A limit message with no recoverable reset instant returns `null` on
21
+ * purpose: guessing a window would turn one interruption into a retry loop against a provider
22
+ * that is still refusing, and "we don't know when" is an honest answer the caller can surface.
23
+ */
24
+ /**
25
+ * The furthest ahead a reset may sit and still be believed. Claude's weekly window is the real
26
+ * ceiling; anything beyond a week is a corrupt or unit-confused number, and parking a task on it
27
+ * would be indistinguishable from losing the task.
28
+ */
29
+ export const MAX_USAGE_LIMIT_WAIT_MS = 7 * 24 * 60 * 60_000;
30
+ /** Claude Code's own envelope. The suffix is Unix EPOCH SECONDS (ms tolerated — see below). */
31
+ const CLAUDE_MARKER_RE = /claude(?:\s+ai)?\s+usage\s+limit\s+reached\s*\|\s*(\d{9,16})/i;
32
+ /**
33
+ * "This is a limit, not a crash." Deliberately narrow: it gates the two prose shapes below, and a
34
+ * false positive there would schedule a resume on a timestamp that means something else entirely.
35
+ */
36
+ const LIMIT_PHRASE_RE = /\b(?:usage|rate|session|weekly|hourly)[\s-]?limit\b|\brate[_-]?limit(?:_error|ed)?\b|\bquota\s+(?:exceeded|reached)\b|\bout\s+of\s+(?:credits|quota)\b/i;
37
+ /** `…try again at 2026-08-03T18:00:00Z`, `…resets at 2026-08-03 18:00`. */
38
+ const RESET_AT_RE = /(?:resets?|reset[s]?\s+at|try\s+again|retry|available\s+again|unlocks?)\b[^\n]{0,24}?\b(\d{4}-\d{2}-\d{2}(?:[T ]\d{2}:\d{2}(?::\d{2})?(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?)?)/i;
39
+ /** `...resets 8:10pm (Europe/Warsaw)`, `...try again at 20:10`. */
40
+ const RESET_CLOCK_RE = /(?:resets?|reset[s]?\s+at|try\s+again|retry|available\s+again|unlocks?)\b[^\n]{0,24}?\b(?:at\s*)?(\d{1,2})(?:(?::(\d{2}))\s*([ap]\.?m\.?)?|\s*([ap]\.?m\.?))(?:\s*\(([^)]+)\))?/i;
41
+ /** `…try again in 42 minutes`, `…retry after 3600 seconds`, `retry-after: 3600`. */
42
+ const RESET_IN_RE = /(?:try\s+again|retry|resets?|available\s+again)\b[^\n]{0,16}?\b(?:in|after)\s+(\d{1,7})\s*(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h)\b/i;
43
+ const RETRY_AFTER_HEADER_RE = /\bretry[-_\s]?after\b\s*[:=]?\s*(\d{1,7})\b/i;
44
+ const UNIT_MS = {
45
+ s: 1_000, sec: 1_000, secs: 1_000, second: 1_000, seconds: 1_000,
46
+ m: 60_000, min: 60_000, mins: 60_000, minute: 60_000, minutes: 60_000,
47
+ h: 3_600_000, hr: 3_600_000, hrs: 3_600_000, hour: 3_600_000, hours: 3_600_000,
48
+ };
49
+ /**
50
+ * Read a usage limit out of a terminal error message, or `null` when it is not one (or carries no
51
+ * usable reset instant). `now` is injected so callers and tests share one clock.
52
+ *
53
+ * Never throws: this runs on the failure path of every run, where a second failure helps nobody.
54
+ */
55
+ export function parseUsageLimit(message, now = Date.now()) {
56
+ if (!message)
57
+ return null;
58
+ const marker = CLAUDE_MARKER_RE.exec(message);
59
+ if (marker) {
60
+ const raw = Number(marker[1]);
61
+ // Epoch seconds is the documented unit; a value large enough to only make sense as
62
+ // milliseconds is accepted rather than parked ~50,000 years out.
63
+ const epochMs = raw >= 1e12 ? raw : raw * 1_000;
64
+ return settle(epochMs, now, 'claude-marker');
65
+ }
66
+ if (!LIMIT_PHRASE_RE.test(message))
67
+ return null;
68
+ const at = RESET_AT_RE.exec(message);
69
+ if (at) {
70
+ // A bare date, or `YYYY-MM-DD HH:MM` without a zone, is read in the host's local time — the
71
+ // provider is talking to the person at this machine, and `Date.parse` would otherwise read the
72
+ // space-separated form as UTC on some runtimes and local on others. A date with no time at all
73
+ // needs the midnight spelled out for the same reason: the ECMAScript date-ONLY form is defined
74
+ // as UTC, so `2026-08-03` alone would land up to a day away from the day the provider named.
75
+ const stamp = at[1].includes('T') ? at[1] : at[1].replace(' ', 'T');
76
+ const parsed = Date.parse(stamp.includes('T') ? stamp : `${stamp}T00:00`);
77
+ if (Number.isFinite(parsed))
78
+ return settle(parsed, now, 'timestamp');
79
+ }
80
+ const clock = RESET_CLOCK_RE.exec(message);
81
+ if (clock) {
82
+ const parsed = parseClockReset(clock, now);
83
+ if (parsed !== null)
84
+ return settle(parsed, now, 'clock');
85
+ }
86
+ const relative = RESET_IN_RE.exec(message);
87
+ if (relative) {
88
+ const unit = UNIT_MS[relative[2].toLowerCase()];
89
+ if (unit !== undefined)
90
+ return settle(now + Number(relative[1]) * unit, now, 'delay');
91
+ }
92
+ const header = RETRY_AFTER_HEADER_RE.exec(message);
93
+ if (header)
94
+ return settle(now + Number(header[1]) * 1_000, now, 'delay');
95
+ return null;
96
+ }
97
+ function parseClockReset(match, now) {
98
+ const hourRaw = Number(match[1]);
99
+ const minute = match[2] === undefined ? 0 : Number(match[2]);
100
+ const meridiem = (match[3] ?? match[4])?.toLowerCase().replaceAll('.', '');
101
+ if (!Number.isInteger(hourRaw) || !Number.isInteger(minute) || minute < 0 || minute > 59) {
102
+ return null;
103
+ }
104
+ let hour = hourRaw;
105
+ if (meridiem) {
106
+ if (hour < 1 || hour > 12)
107
+ return null;
108
+ if (meridiem === 'am')
109
+ hour = hour === 12 ? 0 : hour;
110
+ else if (meridiem === 'pm')
111
+ hour = hour === 12 ? 12 : hour + 12;
112
+ else
113
+ return null;
114
+ }
115
+ else if (hour < 0 || hour > 23) {
116
+ return null;
117
+ }
118
+ const timeZone = validTimeZone(match[5]?.trim());
119
+ if (timeZone)
120
+ return nextClockInTimeZone(hour, minute, timeZone, now);
121
+ return nextLocalClock(hour, minute, now);
122
+ }
123
+ function nextLocalClock(hour, minute, now) {
124
+ const candidate = new Date(now);
125
+ candidate.setHours(hour, minute, 0, 0);
126
+ if (candidate.getTime() < now)
127
+ candidate.setDate(candidate.getDate() + 1);
128
+ return candidate.getTime();
129
+ }
130
+ function nextClockInTimeZone(hour, minute, timeZone, now) {
131
+ const today = zonedParts(now, timeZone);
132
+ if (!today)
133
+ return null;
134
+ let candidate = zonedWallTimeToUtc(today.year, today.month, today.day, hour, minute, timeZone);
135
+ if (candidate === null)
136
+ return null;
137
+ if (candidate < now) {
138
+ const tomorrow = new Date(Date.UTC(today.year, today.month - 1, today.day + 1));
139
+ candidate = zonedWallTimeToUtc(tomorrow.getUTCFullYear(), tomorrow.getUTCMonth() + 1, tomorrow.getUTCDate(), hour, minute, timeZone);
140
+ }
141
+ return candidate;
142
+ }
143
+ function validTimeZone(candidate) {
144
+ if (!candidate)
145
+ return null;
146
+ try {
147
+ new Intl.DateTimeFormat('en-US', { timeZone: candidate }).format(new Date(0));
148
+ return candidate;
149
+ }
150
+ catch {
151
+ return null;
152
+ }
153
+ }
154
+ function zonedWallTimeToUtc(year, month, day, hour, minute, timeZone) {
155
+ const wallAsUtc = Date.UTC(year, month - 1, day, hour, minute, 0, 0);
156
+ let candidate = wallAsUtc;
157
+ for (let i = 0; i < 3; i += 1) {
158
+ const offset = timeZoneOffsetMs(timeZone, candidate);
159
+ if (offset === null)
160
+ return null;
161
+ const next = wallAsUtc - offset;
162
+ if (Math.abs(next - candidate) < 1_000)
163
+ return next;
164
+ candidate = next;
165
+ }
166
+ return candidate;
167
+ }
168
+ function timeZoneOffsetMs(timeZone, utcMs) {
169
+ const parts = zonedParts(utcMs, timeZone);
170
+ if (!parts)
171
+ return null;
172
+ const asUtc = Date.UTC(parts.year, parts.month - 1, parts.day, parts.hour, parts.minute, parts.second);
173
+ return asUtc - utcMs;
174
+ }
175
+ function zonedParts(utcMs, timeZone) {
176
+ try {
177
+ const parts = new Intl.DateTimeFormat('en-CA', {
178
+ timeZone,
179
+ year: 'numeric',
180
+ month: '2-digit',
181
+ day: '2-digit',
182
+ hour: '2-digit',
183
+ minute: '2-digit',
184
+ second: '2-digit',
185
+ hourCycle: 'h23',
186
+ }).formatToParts(new Date(utcMs));
187
+ const value = (type) => Number(parts.find((part) => part.type === type)?.value);
188
+ return {
189
+ year: value('year'),
190
+ month: value('month'),
191
+ day: value('day'),
192
+ hour: value('hour'),
193
+ minute: value('minute'),
194
+ second: value('second'),
195
+ };
196
+ }
197
+ catch {
198
+ return null;
199
+ }
200
+ }
201
+ /** Bound a candidate instant: past → now (the limit already lifted), absurd → not believed. */
202
+ function settle(epochMs, now, evidence) {
203
+ if (!Number.isFinite(epochMs))
204
+ return null;
205
+ if (epochMs - now > MAX_USAGE_LIMIT_WAIT_MS)
206
+ return null;
207
+ return { resetAt: new Date(Math.max(epochMs, now)), evidence };
208
+ }
209
+ //# sourceMappingURL=usage-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage-limit.js","sourceRoot":"","sources":["../../src/core/usage-limit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export declare const CACHE_READ_WEIGHT = 0.1;
2
+ export declare const CACHE_CREATION_WEIGHT = 1.25;
3
+ /** A loosely-typed usage record as emitted by the claude CLI stream. */
4
+ export interface RawUsage {
5
+ input_tokens?: number;
6
+ output_tokens?: number;
7
+ cache_creation_input_tokens?: number;
8
+ cache_read_input_tokens?: number;
9
+ }
10
+ /** Collapse a raw usage record into a single cost-weighted token count. */
11
+ export declare function costWeightedTokens(usage: RawUsage | undefined | null): number;
@@ -0,0 +1,15 @@
1
+ // Anthropic bills cache-read input at ~10% of standard input cost and cache
2
+ // creation at ~125%. Weighting raw counts by these keeps the token number
3
+ // shown in the cockpit roughly proportional to dollar cost.
4
+ export const CACHE_READ_WEIGHT = 0.1;
5
+ export const CACHE_CREATION_WEIGHT = 1.25;
6
+ /** Collapse a raw usage record into a single cost-weighted token count. */
7
+ export function costWeightedTokens(usage) {
8
+ if (!usage)
9
+ return 0;
10
+ return Math.round((usage.input_tokens ?? 0) +
11
+ (usage.output_tokens ?? 0) +
12
+ (usage.cache_creation_input_tokens ?? 0) * CACHE_CREATION_WEIGHT +
13
+ (usage.cache_read_input_tokens ?? 0) * CACHE_READ_WEIGHT);
14
+ }
15
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/core/usage.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,0EAA0E;AAC1E,4DAA4D;AAC5D,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AACrC,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAU1C,2EAA2E;AAC3E,MAAM,UAAU,kBAAkB,CAAC,KAAkC;IACnE,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,CAAC;IACrB,OAAO,IAAI,CAAC,KAAK,CACf,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC;QACvB,CAAC,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;QAC1B,CAAC,KAAK,CAAC,2BAA2B,IAAI,CAAC,CAAC,GAAG,qBAAqB;QAChE,CAAC,KAAK,CAAC,uBAAuB,IAAI,CAAC,CAAC,GAAG,iBAAiB,CAC3D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Per-item coalescing of streamed assistant text into whole v1 `text` events.
3
+ *
4
+ * The v1 `AgentEvent` contract treats `text` as a complete assistant block —
5
+ * that is what claude emits, what the RunManager persists one NDJSON line per
6
+ * event, and what every consumer renders as one paragraph (cockpit thread,
7
+ * headless CLI). Codex and opencode stream deltas, so emitting each delta as
8
+ * its own `text` event persisted one line per token: transcripts rendered one
9
+ * paragraph per token, and turn-end markers split across deltas (`CE`+`Z`+
10
+ * `:D`+`ONE`) slipped past the server's per-event marker stripping.
11
+ *
12
+ * Streaming display does not go through v1 at all — protocol v2's
13
+ * `item.delta` (coalesced by `UiEventSink`) carries it — so v1 can afford
14
+ * whole-block granularity.
15
+ */
16
+ export declare class V1TextCoalescer {
17
+ private readonly emitText;
18
+ /** Accumulated deltas per open item. Deltas with no item id share the ''
19
+ * bucket (at most one anonymous item streams at a time). */
20
+ private readonly pending;
21
+ /** Items already emitted — a late snapshot/delta must not double-emit. */
22
+ private readonly done;
23
+ constructor(emitText: (text: string) => void);
24
+ /** Buffer one streamed delta of an item. */
25
+ append(itemId: string | undefined, delta: string): void;
26
+ /**
27
+ * The item is final: emit its text exactly once — the wire snapshot when the
28
+ * backend sent one (authoritative full text), else the accumulated deltas.
29
+ */
30
+ complete(itemId: string | undefined, snapshotText?: string): void;
31
+ /** Turn/session boundary: emit whatever never saw its item complete, in
32
+ * arrival order, so interrupted turns still surface their partial prose.
33
+ * The `done` latch survives on purpose — item/part ids are unique per
34
+ * session, and a re-sent snapshot after the boundary must not re-emit. */
35
+ flush(): void;
36
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Per-item coalescing of streamed assistant text into whole v1 `text` events.
3
+ *
4
+ * The v1 `AgentEvent` contract treats `text` as a complete assistant block —
5
+ * that is what claude emits, what the RunManager persists one NDJSON line per
6
+ * event, and what every consumer renders as one paragraph (cockpit thread,
7
+ * headless CLI). Codex and opencode stream deltas, so emitting each delta as
8
+ * its own `text` event persisted one line per token: transcripts rendered one
9
+ * paragraph per token, and turn-end markers split across deltas (`CE`+`Z`+
10
+ * `:D`+`ONE`) slipped past the server's per-event marker stripping.
11
+ *
12
+ * Streaming display does not go through v1 at all — protocol v2's
13
+ * `item.delta` (coalesced by `UiEventSink`) carries it — so v1 can afford
14
+ * whole-block granularity.
15
+ */
16
+ export class V1TextCoalescer {
17
+ emitText;
18
+ /** Accumulated deltas per open item. Deltas with no item id share the ''
19
+ * bucket (at most one anonymous item streams at a time). */
20
+ pending = new Map();
21
+ /** Items already emitted — a late snapshot/delta must not double-emit. */
22
+ done = new Set();
23
+ constructor(emitText) {
24
+ this.emitText = emitText;
25
+ }
26
+ /** Buffer one streamed delta of an item. */
27
+ append(itemId, delta) {
28
+ if (delta === '')
29
+ return;
30
+ const key = itemId ?? '';
31
+ if (this.done.has(key))
32
+ return;
33
+ this.pending.set(key, (this.pending.get(key) ?? '') + delta);
34
+ }
35
+ /**
36
+ * The item is final: emit its text exactly once — the wire snapshot when the
37
+ * backend sent one (authoritative full text), else the accumulated deltas.
38
+ */
39
+ complete(itemId, snapshotText) {
40
+ const key = itemId ?? '';
41
+ if (this.done.has(key))
42
+ return;
43
+ // The anonymous bucket is never latched: without an identity, "already
44
+ // emitted" can't be told apart from "the next id-less item".
45
+ if (key !== '')
46
+ this.done.add(key);
47
+ let buffered = this.pending.get(key);
48
+ this.pending.delete(key);
49
+ if (buffered === undefined && key !== '') {
50
+ // Deltas that arrived without an item id belong to the only in-flight item.
51
+ buffered = this.pending.get('');
52
+ this.pending.delete('');
53
+ }
54
+ const text = snapshotText !== undefined && snapshotText !== '' ? snapshotText : (buffered ?? '');
55
+ if (text !== '')
56
+ this.emitText(text);
57
+ }
58
+ /** Turn/session boundary: emit whatever never saw its item complete, in
59
+ * arrival order, so interrupted turns still surface their partial prose.
60
+ * The `done` latch survives on purpose — item/part ids are unique per
61
+ * session, and a re-sent snapshot after the boundary must not re-emit. */
62
+ flush() {
63
+ for (const [key, text] of this.pending) {
64
+ if (text !== '')
65
+ this.emitText(text);
66
+ if (key !== '')
67
+ this.done.add(key);
68
+ }
69
+ this.pending.clear();
70
+ }
71
+ }
72
+ //# sourceMappingURL=v1-text-coalescer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v1-text-coalescer.js","sourceRoot":"","sources":["../../src/core/v1-text-coalescer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,eAAe;IAOG,QAAQ;IANrC;iEAC6D;IAC5C,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IACrD,0EAA0E;IACzD,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE1C,YAA6B,QAAgC;wBAAhC,QAAQ;IAA2B,CAAC;IAEjE,4CAA4C;IAC5C,MAAM,CAAC,MAA0B,EAAE,KAAa;QAC9C,IAAI,KAAK,KAAK,EAAE;YAAE,OAAO;QACzB,MAAM,GAAG,GAAG,MAAM,IAAI,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO;QAC/B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC;IAC/D,CAAC;IAED;;;OAGG;IACH,QAAQ,CAAC,MAA0B,EAAE,YAAqB;QACxD,MAAM,GAAG,GAAG,MAAM,IAAI,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO;QAC/B,uEAAuE;QACvE,6DAA6D;QAC7D,IAAI,GAAG,KAAK,EAAE;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,QAAQ,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;YACzC,4EAA4E;YAC5E,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC;QACD,MAAM,IAAI,GAAG,YAAY,KAAK,SAAS,IAAI,YAAY,KAAK,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;QACjG,IAAI,IAAI,KAAK,EAAE;YAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IAED;;;+EAG2E;IAC3E,KAAK;QACH,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,IAAI,IAAI,KAAK,EAAE;gBAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACrC,IAAI,GAAG,KAAK,EAAE;gBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;CACF"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * "Which ref anchors *this task's* diff" — the single rule every task-diff
3
+ * surface resolves through (#751).
4
+ *
5
+ * The normal answer is `merge-base(baseBranch, HEAD)`: it keeps a task's diff
6
+ * to the task's own commits even after the base branch moves on, and even
7
+ * after the task merges the base back in.
8
+ *
9
+ * Two things break that answer, and both are fixed here:
10
+ *
11
+ * **A stale local base ref.** `RunRecord.baseBranch` is a NAME (`main`),
12
+ * resolved to a ref once, when the worktree was created. Nothing ever
13
+ * fast-forwards the user's local `main` — cezar's agents only ever `git fetch`,
14
+ * which moves `origin/main` — so on a repo the user does not pull, the local
15
+ * ref drifts arbitrarily far behind. The merge-base then collapses onto that
16
+ * stale tip and every upstream commit the task forked from or merged in counts
17
+ * as the task's own work: an eight-line fix measured `+59514 −12160` against a
18
+ * `main` that was 98 commits and one monorepo restructure behind origin. So the
19
+ * base is re-resolved to the freshest ref it names at every call
20
+ * (`freshestBaseRef`) — the read-time twin of `resolveBaseRef`, which does the
21
+ * same thing at worktree-creation time and cannot know what happens later.
22
+ *
23
+ * **A repointed HEAD.** cezar hands the agent a worktree on the task's own
24
+ * branch, but nothing stops the agent from checking out another branch in it —
25
+ * every `review/pr-NNN` and QA run does exactly that, and so does every skill
26
+ * that opens its work on a named `feat/…` branch. The merge-base then silently
27
+ * redefines "this task's diff" as *the whole checked-out branch*, which is how
28
+ * a task that committed nothing came to report `+22505 −2628`. #591 and #751
29
+ * answered that with `HEAD` — uncommitted work only — which is right for a
30
+ * pure review and badly wrong for the far more common case of an agent that
31
+ * committed real work on a branch it created itself: those runs reported
32
+ * `+0 −0` for changes that were genuinely theirs.
33
+ *
34
+ * The honest anchor for a repointed HEAD is the branch as it stood **when this
35
+ * run first saw it** — its `<branch>@{<run start>}` reflog state. Diffing
36
+ * against that attributes exactly what the run did to the tree and nothing
37
+ * that was already there: a review run gets its `+0`, and a run that branched
38
+ * off the base and committed gets its real numbers. Where that baseline is
39
+ * itself stale — the run merged the base branch in afterwards, dragging the
40
+ * whole upstream delta behind it — the ordinary merge-base is the tighter
41
+ * answer, so the two candidates compete and the one that attributes FEWER
42
+ * CHANGED LINES to the task wins. The reported number is then never more than
43
+ * the least either measure can defend.
44
+ *
45
+ * It lives here so a third surface cannot get it wrong again — callers hand in
46
+ * their own `git` runner (`git-worktree.ts` and `server/git-changes.ts` each
47
+ * own a private one, and `git-changes` needs its scratch-`GIT_INDEX_FILE`
48
+ * variant), so this module stays a pure decision with no process-spawning of
49
+ * its own.
50
+ */
51
+ /** What a caller's `git` runner must answer with. Both existing runners are wider than this. */
52
+ export interface GitRunResult {
53
+ ok: boolean;
54
+ stdout: string;
55
+ }
56
+ /** A caller-supplied `git` invocation, already bound to a working directory (and env). */
57
+ export type GitRunner = (args: string[]) => Promise<GitRunResult>;
58
+ /** The task branch cezar created vs. the branch HEAD actually sits on. */
59
+ export interface RepointedHead {
60
+ headBranch: string;
61
+ taskBranch: string;
62
+ }
63
+ export interface TaskDiffBase {
64
+ /** The ref to diff against. */
65
+ base: string;
66
+ /** Present only when HEAD left the task's branch — the reason `base` is what it is. */
67
+ repointedHead?: RepointedHead;
68
+ }
69
+ /**
70
+ * Resolve the diff anchor for a task worktree. Never throws: a failing git call
71
+ * degrades to the base branch name, which is what the un-guarded callers did
72
+ * before this helper existed.
73
+ *
74
+ * `taskBranch` is optional because not every caller has one (the main working
75
+ * tree has no task branch at all). Without it there is nothing to compare HEAD
76
+ * against, so the merge-base anchor is used unchanged.
77
+ *
78
+ * `runStartedAt` is what makes the repointed-HEAD answer a measurement instead
79
+ * of a guess; without it the anchor stays `HEAD` (uncommitted work only), the
80
+ * conservative #751 answer that can never claim someone else's commits.
81
+ */
82
+ export declare function resolveTaskDiffBase(runGit: GitRunner, baseBranch: string, opts?: {
83
+ taskBranch?: string;
84
+ runStartedAt?: string;
85
+ }): Promise<TaskDiffBase>;
@@ -0,0 +1,180 @@
1
+ /**
2
+ * "Which ref anchors *this task's* diff" — the single rule every task-diff
3
+ * surface resolves through (#751).
4
+ *
5
+ * The normal answer is `merge-base(baseBranch, HEAD)`: it keeps a task's diff
6
+ * to the task's own commits even after the base branch moves on, and even
7
+ * after the task merges the base back in.
8
+ *
9
+ * Two things break that answer, and both are fixed here:
10
+ *
11
+ * **A stale local base ref.** `RunRecord.baseBranch` is a NAME (`main`),
12
+ * resolved to a ref once, when the worktree was created. Nothing ever
13
+ * fast-forwards the user's local `main` — cezar's agents only ever `git fetch`,
14
+ * which moves `origin/main` — so on a repo the user does not pull, the local
15
+ * ref drifts arbitrarily far behind. The merge-base then collapses onto that
16
+ * stale tip and every upstream commit the task forked from or merged in counts
17
+ * as the task's own work: an eight-line fix measured `+59514 −12160` against a
18
+ * `main` that was 98 commits and one monorepo restructure behind origin. So the
19
+ * base is re-resolved to the freshest ref it names at every call
20
+ * (`freshestBaseRef`) — the read-time twin of `resolveBaseRef`, which does the
21
+ * same thing at worktree-creation time and cannot know what happens later.
22
+ *
23
+ * **A repointed HEAD.** cezar hands the agent a worktree on the task's own
24
+ * branch, but nothing stops the agent from checking out another branch in it —
25
+ * every `review/pr-NNN` and QA run does exactly that, and so does every skill
26
+ * that opens its work on a named `feat/…` branch. The merge-base then silently
27
+ * redefines "this task's diff" as *the whole checked-out branch*, which is how
28
+ * a task that committed nothing came to report `+22505 −2628`. #591 and #751
29
+ * answered that with `HEAD` — uncommitted work only — which is right for a
30
+ * pure review and badly wrong for the far more common case of an agent that
31
+ * committed real work on a branch it created itself: those runs reported
32
+ * `+0 −0` for changes that were genuinely theirs.
33
+ *
34
+ * The honest anchor for a repointed HEAD is the branch as it stood **when this
35
+ * run first saw it** — its `<branch>@{<run start>}` reflog state. Diffing
36
+ * against that attributes exactly what the run did to the tree and nothing
37
+ * that was already there: a review run gets its `+0`, and a run that branched
38
+ * off the base and committed gets its real numbers. Where that baseline is
39
+ * itself stale — the run merged the base branch in afterwards, dragging the
40
+ * whole upstream delta behind it — the ordinary merge-base is the tighter
41
+ * answer, so the two candidates compete and the one that attributes FEWER
42
+ * CHANGED LINES to the task wins. The reported number is then never more than
43
+ * the least either measure can defend.
44
+ *
45
+ * It lives here so a third surface cannot get it wrong again — callers hand in
46
+ * their own `git` runner (`git-worktree.ts` and `server/git-changes.ts` each
47
+ * own a private one, and `git-changes` needs its scratch-`GIT_INDEX_FILE`
48
+ * variant), so this module stays a pure decision with no process-spawning of
49
+ * its own.
50
+ */
51
+ import { isSafeGitRef } from './git-refs.js';
52
+ /**
53
+ * ISO-8601 instants only, for the `<branch>@{<date>}` revision below. The
54
+ * timestamp comes from a stored run record, and a git revision expression is
55
+ * the one place a stray value would be interpreted rather than compared —
56
+ * `@{-1}` is "the previously checked-out branch", not a date. Anything that is
57
+ * not plainly a timestamp simply disables the baseline anchor.
58
+ */
59
+ const ISO_INSTANT = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/;
60
+ /**
61
+ * The freshest ref the configured base branch names: `origin/<base>` when the
62
+ * local branch is behind it (or missing entirely), the local branch otherwise.
63
+ *
64
+ * Same rule as `resolveBaseRef` (`git-worktree.ts`), which picks the fork point
65
+ * when the worktree is created; this one re-applies it every time a diff is
66
+ * measured, because that is when the local ref's staleness actually shows up.
67
+ * A base that is already remote-tracking, a commit sha pinned from a detached
68
+ * HEAD, or a repo with no `origin` all fall through unchanged.
69
+ */
70
+ async function freshestBaseRef(runGit, base) {
71
+ if (!isSafeGitRef(base) || base === 'HEAD' || base.startsWith('origin/'))
72
+ return base;
73
+ const remote = `origin/${base}`;
74
+ const hasRemote = await runGit(['rev-parse', '--verify', '--quiet', `${remote}^{commit}`]);
75
+ if (!hasRemote.ok)
76
+ return base;
77
+ // Exits 0 iff local is equal to or ahead of origin — the case where the local
78
+ // ref carries unpushed base commits and is the better answer.
79
+ const localCurrent = await runGit(['merge-base', '--is-ancestor', remote, base]);
80
+ return localCurrent.ok ? base : remote;
81
+ }
82
+ /**
83
+ * Where the repointed branch stood when this run started — `git rev-parse
84
+ * <branch>@{<runStartedAt>}`, i.e. its own reflog, read at a point in time.
85
+ *
86
+ * Git answers this generously by design: a timestamp older than the whole
87
+ * reflog resolves to the branch's OLDEST recorded state, which for a branch the
88
+ * agent created during the run is its creation commit — exactly the fork point
89
+ * we want. A branch that already existed resolves to the tip it had before the
90
+ * run touched it, so the previous author's commits stay theirs.
91
+ *
92
+ * Null (→ the caller keeps the conservative `HEAD` anchor) when there is no run
93
+ * start to read at, when HEAD is detached (no branch reflog to consult), or
94
+ * when reflogs are unavailable — a guess is worse than the narrow answer.
95
+ */
96
+ async function checkoutBaseline(runGit, headBranch, runStartedAt) {
97
+ if (!runStartedAt || !ISO_INSTANT.test(runStartedAt))
98
+ return null;
99
+ if (headBranch === 'HEAD' || !isSafeGitRef(headBranch))
100
+ return null;
101
+ const at = await runGit([
102
+ 'rev-parse',
103
+ '--verify',
104
+ '--quiet',
105
+ `${headBranch}@{${runStartedAt}}^{commit}`,
106
+ ]);
107
+ const sha = at.ok ? at.stdout.trim() : '';
108
+ return sha || null;
109
+ }
110
+ /**
111
+ * How many changed lines an anchor attributes to the task — the comparison that
112
+ * picks between two candidates, never a number anyone sees (the callers do their
113
+ * own parsing for that, `parseShortstat`). Both candidates cover the same
114
+ * uncommitted work, so the comparison is fair whatever the index holds.
115
+ *
116
+ * This is the one part of the decision that reads the index rather than just
117
+ * refs, and `git diff` rewrites the index it reads (a stat refresh). Callers
118
+ * that keep their diffs off an index they do not own — `collectChanges` and its
119
+ * scratch `GIT_INDEX_FILE` — must therefore hand this module a runner carrying
120
+ * that same environment, and the two probes below run one after the other so
121
+ * they never refresh one index file concurrently.
122
+ */
123
+ async function changedLines(runGit, ref) {
124
+ const res = await runGit(['diff', '--shortstat', ref]);
125
+ if (!res.ok)
126
+ return null;
127
+ let total = 0;
128
+ for (const m of res.stdout.matchAll(/(\d+) (?:insertions?\(\+\)|deletions?\(-\))/g)) {
129
+ total += Number(m[1]);
130
+ }
131
+ return total;
132
+ }
133
+ /**
134
+ * Resolve the diff anchor for a task worktree. Never throws: a failing git call
135
+ * degrades to the base branch name, which is what the un-guarded callers did
136
+ * before this helper existed.
137
+ *
138
+ * `taskBranch` is optional because not every caller has one (the main working
139
+ * tree has no task branch at all). Without it there is nothing to compare HEAD
140
+ * against, so the merge-base anchor is used unchanged.
141
+ *
142
+ * `runStartedAt` is what makes the repointed-HEAD answer a measurement instead
143
+ * of a guess; without it the anchor stays `HEAD` (uncommitted work only), the
144
+ * conservative #751 answer that can never claim someone else's commits.
145
+ */
146
+ export async function resolveTaskDiffBase(runGit, baseBranch, opts = {}) {
147
+ const base = await freshestBaseRef(runGit, baseBranch);
148
+ const mergeBase = async () => {
149
+ const res = await runGit(['merge-base', base, 'HEAD']);
150
+ return res.ok && res.stdout.trim() ? res.stdout.trim() : base;
151
+ };
152
+ if (!opts.taskBranch)
153
+ return { base: await mergeBase() };
154
+ const headBranchResult = await runGit(['rev-parse', '--abbrev-ref', 'HEAD']);
155
+ const headBranch = headBranchResult.ok ? headBranchResult.stdout.trim() : '';
156
+ // An unreadable HEAD (no commits yet, broken worktree) is NOT evidence of a
157
+ // repoint — fall through to the merge-base anchor rather than narrowing on a
158
+ // guess. A detached HEAD, on the other hand, is by definition not the task's
159
+ // branch and takes the repointed path below.
160
+ if (!headBranch || headBranch === opts.taskBranch)
161
+ return { base: await mergeBase() };
162
+ const repointedHead = { headBranch, taskBranch: opts.taskBranch };
163
+ const baseline = await checkoutBaseline(runGit, headBranch, opts.runStartedAt);
164
+ if (!baseline)
165
+ return { base: 'HEAD', repointedHead };
166
+ // Two defensible anchors, so report the tighter one: the number must never
167
+ // claim more than the least either measure attributes to this task. The
168
+ // baseline is usually it — but not when the run merged the base branch in
169
+ // afterwards, which drags the whole upstream delta past a pre-merge baseline
170
+ // and leaves the merge-base as the only anchor that still measures the task.
171
+ const anchor = await mergeBase();
172
+ const viaBaseline = await changedLines(runGit, baseline);
173
+ if (viaBaseline === null)
174
+ return { base: anchor, repointedHead };
175
+ const viaMergeBase = await changedLines(runGit, anchor);
176
+ if (viaMergeBase === null || viaBaseline <= viaMergeBase)
177
+ return { base: baseline, repointedHead };
178
+ return { base: anchor, repointedHead };
179
+ }
180
+ //# sourceMappingURL=git-diff-base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-diff-base.js","sourceRoot":"","sources":["../src/git-diff-base.ts"],"names":[],"mappings":"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"}