@wjarka/cezarion 0.14.8 → 0.14.9-dev.1004

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 (274) hide show
  1. package/README.md +129 -2
  2. package/dist/application-update/bin-recovery.d.ts +5 -0
  3. package/dist/application-update/bin-recovery.js +96 -0
  4. package/dist/application-update/bin-recovery.js.map +1 -0
  5. package/dist/application-update/discovery.d.ts +22 -0
  6. package/dist/application-update/discovery.js +91 -0
  7. package/dist/application-update/discovery.js.map +1 -0
  8. package/dist/application-update/helper.d.ts +57 -0
  9. package/dist/application-update/helper.js +374 -0
  10. package/dist/application-update/helper.js.map +1 -0
  11. package/dist/application-update/launcher.d.ts +8 -0
  12. package/dist/application-update/launcher.js +53 -0
  13. package/dist/application-update/launcher.js.map +1 -0
  14. package/dist/application-update/lock.d.ts +4 -0
  15. package/dist/application-update/lock.js +70 -0
  16. package/dist/application-update/lock.js.map +1 -0
  17. package/dist/application-update/npm-process.d.ts +17 -0
  18. package/dist/application-update/npm-process.js +133 -0
  19. package/dist/application-update/npm-process.js.map +1 -0
  20. package/dist/application-update/service.d.ts +69 -0
  21. package/dist/application-update/service.js +456 -0
  22. package/dist/application-update/service.js.map +1 -0
  23. package/dist/artifacts/cli.d.ts +1 -0
  24. package/dist/artifacts/cli.js +32 -0
  25. package/dist/artifacts/cli.js.map +1 -0
  26. package/dist/artifacts/lifecycle.d.ts +4 -0
  27. package/dist/artifacts/lifecycle.js +42 -0
  28. package/dist/artifacts/lifecycle.js.map +1 -0
  29. package/dist/artifacts/resolve.d.ts +18 -0
  30. package/dist/artifacts/resolve.js +102 -0
  31. package/dist/artifacts/resolve.js.map +1 -0
  32. package/dist/artifacts/store.d.ts +8 -0
  33. package/dist/artifacts/store.js +323 -0
  34. package/dist/artifacts/store.js.map +1 -0
  35. package/dist/automations/scheduler.d.ts +6 -0
  36. package/dist/automations/scheduler.js +45 -17
  37. package/dist/automations/scheduler.js.map +1 -1
  38. package/dist/automations/store.d.ts +12 -4
  39. package/dist/automations/store.js +199 -22
  40. package/dist/automations/store.js.map +1 -1
  41. package/dist/automations/types.d.ts +2 -0
  42. package/dist/automations/types.js +1 -0
  43. package/dist/automations/types.js.map +1 -1
  44. package/dist/ci-wait/mcp.d.ts +3 -0
  45. package/dist/ci-wait/mcp.js +14 -3
  46. package/dist/ci-wait/mcp.js.map +1 -1
  47. package/dist/contract/application-update.d.ts +32 -0
  48. package/dist/contract/artifacts.d.ts +83 -0
  49. package/dist/contract/ask-schema.d.ts +32 -0
  50. package/dist/contract/ask.d.ts +2 -32
  51. package/dist/contract/automations.d.ts +6 -0
  52. package/dist/contract/conversations.d.ts +165 -0
  53. package/dist/contract/delegation.d.ts +68 -0
  54. package/dist/contract/discovery.d.ts +134 -0
  55. package/dist/contract/events.d.ts +49 -0
  56. package/dist/contract/health.d.ts +12 -0
  57. package/dist/contract/index.d.ts +3 -0
  58. package/dist/contract/index.js +1654 -1454
  59. package/dist/contract/projects.d.ts +40 -0
  60. package/dist/contract/runs.d.ts +186 -0
  61. package/dist/contract/skills.d.ts +33 -0
  62. package/dist/core/agent-runner.d.ts +33 -4
  63. package/dist/core/agent-runner.js +5 -0
  64. package/dist/core/agent-runner.js.map +1 -1
  65. package/dist/core/claude-cli-runner.d.ts +6 -12
  66. package/dist/core/claude-cli-runner.js +90 -20
  67. package/dist/core/claude-cli-runner.js.map +1 -1
  68. package/dist/core/codex-app-server-runner.d.ts +2 -1
  69. package/dist/core/codex-app-server-runner.js +327 -92
  70. package/dist/core/codex-app-server-runner.js.map +1 -1
  71. package/dist/core/codex-app-server-transport.d.ts +13 -1
  72. package/dist/core/codex-app-server-transport.js +58 -17
  73. package/dist/core/codex-app-server-transport.js.map +1 -1
  74. package/dist/core/cursor-acp-runner.d.ts +6 -1
  75. package/dist/core/cursor-acp-runner.js +162 -26
  76. package/dist/core/cursor-acp-runner.js.map +1 -1
  77. package/dist/core/cursor-provider-error.d.ts +3 -0
  78. package/dist/core/cursor-provider-error.js +16 -1
  79. package/dist/core/cursor-provider-error.js.map +1 -1
  80. package/dist/core/input-submissions.d.ts +14 -0
  81. package/dist/core/input-submissions.js +26 -0
  82. package/dist/core/input-submissions.js.map +1 -0
  83. package/dist/core/opencode-server-runner.d.ts +4 -1
  84. package/dist/core/opencode-server-runner.js +156 -26
  85. package/dist/core/opencode-server-runner.js.map +1 -1
  86. package/dist/core/pi-runner.d.ts +2 -1
  87. package/dist/core/pi-runner.js +88 -10
  88. package/dist/core/pi-runner.js.map +1 -1
  89. package/dist/core/provider-auth.d.ts +99 -1
  90. package/dist/core/provider-auth.js +203 -2
  91. package/dist/core/provider-auth.js.map +1 -1
  92. package/dist/delegation/cli.d.ts +1 -0
  93. package/dist/delegation/cli.js +103 -7
  94. package/dist/delegation/cli.js.map +1 -1
  95. package/dist/delegation/conversations.js +13 -5
  96. package/dist/delegation/conversations.js.map +1 -1
  97. package/dist/delegation/input.d.ts +2 -1
  98. package/dist/delegation/input.js +6 -1
  99. package/dist/delegation/input.js.map +1 -1
  100. package/dist/delegation/policy.d.ts +3 -2
  101. package/dist/delegation/policy.js +3 -1
  102. package/dist/delegation/policy.js.map +1 -1
  103. package/dist/delegation/process-liveness.d.ts +66 -0
  104. package/dist/delegation/process-liveness.js +215 -0
  105. package/dist/delegation/process-liveness.js.map +1 -0
  106. package/dist/delegation/provision.d.ts +1 -1
  107. package/dist/delegation/provision.js +10 -5
  108. package/dist/delegation/provision.js.map +1 -1
  109. package/dist/delegation/questions.d.ts +19 -0
  110. package/dist/delegation/questions.js +45 -0
  111. package/dist/delegation/questions.js.map +1 -0
  112. package/dist/delegation/results.d.ts +1 -1
  113. package/dist/delegation/results.js +33 -19
  114. package/dist/delegation/results.js.map +1 -1
  115. package/dist/delegation/routes.d.ts +185 -11
  116. package/dist/delegation/routes.js +6 -2
  117. package/dist/delegation/routes.js.map +1 -1
  118. package/dist/delegation/service.d.ts +16 -5
  119. package/dist/delegation/service.js +161 -13
  120. package/dist/delegation/service.js.map +1 -1
  121. package/dist/delegation/transport.d.ts +228 -65
  122. package/dist/discovery/catalog.d.ts +14 -0
  123. package/dist/discovery/catalog.js +31 -0
  124. package/dist/discovery/catalog.js.map +1 -0
  125. package/dist/discovery/cli.d.ts +8 -0
  126. package/dist/discovery/cli.js +104 -0
  127. package/dist/discovery/cli.js.map +1 -0
  128. package/dist/git-worktree.d.ts +3 -1
  129. package/dist/git-worktree.js +26 -4
  130. package/dist/git-worktree.js.map +1 -1
  131. package/dist/index.js +92 -26
  132. package/dist/index.js.map +1 -1
  133. package/dist/open-url.d.ts +2 -0
  134. package/dist/open-url.js +20 -0
  135. package/dist/open-url.js.map +1 -0
  136. package/dist/release/snapshot.d.ts +3 -3
  137. package/dist/release/snapshot.js +6 -6
  138. package/dist/release/snapshot.js.map +1 -1
  139. package/dist/runs/agent-tmpdir.d.ts +2 -0
  140. package/dist/runs/agent-tmpdir.js +5 -2
  141. package/dist/runs/agent-tmpdir.js.map +1 -1
  142. package/dist/runs/client-request.d.ts +11 -0
  143. package/dist/runs/client-request.js +26 -0
  144. package/dist/runs/client-request.js.map +1 -0
  145. package/dist/runs/delegation-state.d.ts +17 -0
  146. package/dist/runs/event-history.js +6 -0
  147. package/dist/runs/event-history.js.map +1 -1
  148. package/dist/runs/retention.d.ts +7 -2
  149. package/dist/runs/retention.js +39 -7
  150. package/dist/runs/retention.js.map +1 -1
  151. package/dist/runs/store.d.ts +100 -6
  152. package/dist/runs/store.js +245 -2
  153. package/dist/runs/store.js.map +1 -1
  154. package/dist/runs/webhook.d.ts +125 -0
  155. package/dist/runs/webhook.js +256 -0
  156. package/dist/runs/webhook.js.map +1 -0
  157. package/dist/server/provider-auth-runtime.d.ts +30 -4
  158. package/dist/server/provider-auth-runtime.js +71 -6
  159. package/dist/server/provider-auth-runtime.js.map +1 -1
  160. package/dist/server/server.d.ts +8226 -4860
  161. package/dist/server/server.js +309 -15
  162. package/dist/server/server.js.map +1 -1
  163. package/dist/server-install/platforms/ubuntu-vps.d.ts +5 -1
  164. package/dist/server-install/platforms/ubuntu-vps.js +160 -18
  165. package/dist/server-install/platforms/ubuntu-vps.js.map +1 -1
  166. package/dist/server-install/steps.d.ts +4 -2
  167. package/dist/server-install/steps.js +5 -4
  168. package/dist/server-install/steps.js.map +1 -1
  169. package/dist/skills-remote.d.ts +30 -5
  170. package/dist/skills-remote.js +122 -32
  171. package/dist/skills-remote.js.map +1 -1
  172. package/dist/skills.js +15 -6
  173. package/dist/skills.js.map +1 -1
  174. package/dist/task-cli/cli.d.ts +38 -0
  175. package/dist/task-cli/cli.js +580 -0
  176. package/dist/task-cli/cli.js.map +1 -0
  177. package/dist/task-cli/discovery.d.ts +22 -0
  178. package/dist/task-cli/discovery.js +96 -0
  179. package/dist/task-cli/discovery.js.map +1 -0
  180. package/dist/task-cli/http.d.ts +46 -0
  181. package/dist/task-cli/http.js +101 -0
  182. package/dist/task-cli/http.js.map +1 -0
  183. package/dist/task-cli/projections.d.ts +40 -0
  184. package/dist/task-cli/projections.js +45 -0
  185. package/dist/task-cli/projections.js.map +1 -0
  186. package/dist/task-cli/watch.d.ts +78 -0
  187. package/dist/task-cli/watch.js +336 -0
  188. package/dist/task-cli/watch.js.map +1 -0
  189. package/dist/workflows/run.d.ts +160 -2
  190. package/dist/workflows/run.js +1141 -108
  191. package/dist/workflows/run.js.map +1 -1
  192. package/dist/workspace/agent-profiles.d.ts +22 -0
  193. package/dist/workspace/agent-profiles.js +15 -0
  194. package/dist/workspace/agent-profiles.js.map +1 -1
  195. package/dist/workspace/config.d.ts +9 -0
  196. package/dist/workspace/config.js +13 -1
  197. package/dist/workspace/config.js.map +1 -1
  198. package/dist/workspace/projects-cli.js +1 -1
  199. package/dist/workspace/projects.d.ts +24 -1
  200. package/dist/workspace/projects.js +14 -1
  201. package/dist/workspace/projects.js.map +1 -1
  202. package/package.json +5 -5
  203. package/scripts/mock-claude.mjs +64 -2
  204. package/scripts/mock-codex-app-server.mjs +124 -1
  205. package/scripts/mock-cursor-acp.mjs +54 -3
  206. package/scripts/mock-cursor-hang-stdin-late.mjs +35 -0
  207. package/scripts/mock-cursor-hang-stdin.mjs +30 -0
  208. package/scripts/mock-opencode-serve.mjs +102 -2
  209. package/scripts/mock-pi-rpc.mjs +82 -3
  210. package/web/dist/assets/agent-accounts-CerclGiO.js +1 -0
  211. package/web/dist/assets/centered-state-DH8qtCz-.js +43 -0
  212. package/web/dist/assets/collapsible-De2G0xqQ.js +1 -0
  213. package/web/dist/assets/commit-list-CQubP1iS.js +1 -0
  214. package/web/dist/assets/compare-variants-C_NijJvg.js +1 -0
  215. package/web/dist/assets/{diff-tRE59UNb2.js → diff-8M5HlDxq2.js} +2 -2
  216. package/web/dist/assets/diff-controls-B6ok0TtQ.js +1 -0
  217. package/web/dist/assets/{diff-stat-Cgnl_hYF.js → diff-stat-D1AODN2a.js} +1 -1
  218. package/web/dist/assets/{diff-view-DN1ort7Q.js → diff-view-Bs5Gh7UF.js} +2 -2
  219. package/web/dist/assets/dropdown-menu-7KGQMoFj.js +1 -0
  220. package/web/dist/assets/git-toolbar-DqbapMXr.js +1 -0
  221. package/web/dist/assets/github-lMHiuYSx.js +1 -0
  222. package/web/dist/assets/{image-preview-C2JGcBlC.js → image-preview-jzHoEyLM.js} +1 -1
  223. package/web/dist/assets/index-D4OJTArJ.js +7 -0
  224. package/web/dist/assets/index-D5NkwqY7.css +1 -0
  225. package/web/dist/assets/markdown-DvbymqXz.js +2 -0
  226. package/web/dist/assets/pill-BL6ugwXo.js +1 -0
  227. package/web/dist/assets/project-router-ChC5Rb-Y.js +1 -0
  228. package/web/dist/assets/prompt-templates-j8qlK7c-.js +15 -0
  229. package/web/dist/assets/repo-git-BbPAgkqb.js +1 -0
  230. package/web/dist/assets/{run-diff-CyG0Nciv.js → run-diff-BuATgZpx.js} +2 -2
  231. package/web/dist/assets/run-header-DuAWswYM.js +1 -0
  232. package/web/dist/assets/skills-DiC2XrU1.js +1 -0
  233. package/web/dist/assets/{tab-link-BWNp3mLY.js → tab-link-BmGKj9Rt.js} +1 -1
  234. package/web/dist/assets/task-changes-CP9kPnsy.js +1 -0
  235. package/web/dist/assets/task-commits-D6NfTw5r.js +1 -0
  236. package/web/dist/assets/task-files-W-b_gtcb.js +2 -0
  237. package/web/dist/assets/task-thread-Bw_nQuTx.css +1 -0
  238. package/web/dist/assets/task-thread-Q7Nj33DH.js +9 -0
  239. package/web/dist/assets/textarea-ByZ-txS7.js +1 -0
  240. package/web/dist/assets/thread-loading-DHT9p5o5.js +1 -0
  241. package/web/dist/assets/token-metrics-k4XoovDS.js +1 -0
  242. package/web/dist/assets/utils-BTFBhZ55.js +64 -0
  243. package/web/dist/assets/workflows-DqQszPHJ.js +11 -0
  244. package/web/dist/assets/{zoomable-image-Z3JDnm0b.js → zoomable-image-Ba6y6Wyl.js} +1 -1
  245. package/web/dist/index.html +14 -14
  246. package/web/dist/assets/agent-accounts-BZm_2WAv.js +0 -1
  247. package/web/dist/assets/alert-dialog-B422RI-k.js +0 -43
  248. package/web/dist/assets/collapsible-Cy_Fmkrd.js +0 -1
  249. package/web/dist/assets/commit-list-Dcnk7TnI.js +0 -1
  250. package/web/dist/assets/compare-variants-Ciqwvd_f.js +0 -1
  251. package/web/dist/assets/diff-controls-BGrXGi7O.js +0 -1
  252. package/web/dist/assets/dropdown-menu-dwDGT8MM.js +0 -1
  253. package/web/dist/assets/git-toolbar-UiHnGvE0.js +0 -1
  254. package/web/dist/assets/github-D-MrkbJ7.js +0 -1
  255. package/web/dist/assets/ibm-plex-mono-regular-BF3vfe7_.ttf +0 -0
  256. package/web/dist/assets/index-BszfYvBq.js +0 -7
  257. package/web/dist/assets/index-CWh4pKP3.css +0 -1
  258. package/web/dist/assets/markdown-C_IcKVQd.js +0 -2
  259. package/web/dist/assets/pill-BsbO6G7y.js +0 -1
  260. package/web/dist/assets/project-router-DbLkll25.js +0 -1
  261. package/web/dist/assets/prompt-templates-BlTGJB5W.js +0 -15
  262. package/web/dist/assets/repo-git-Bm3s6Why.js +0 -1
  263. package/web/dist/assets/run-header-IFyIGCey.js +0 -1
  264. package/web/dist/assets/skills-C-C4DVFY.js +0 -1
  265. package/web/dist/assets/task-changes-D2PHtWUW.js +0 -1
  266. package/web/dist/assets/task-commits-N5u9U0_R.js +0 -1
  267. package/web/dist/assets/task-files-BS7c7CFm.js +0 -2
  268. package/web/dist/assets/task-thread-BQFdz1dJ.css +0 -1
  269. package/web/dist/assets/task-thread-DGM2dZV-.js +0 -9
  270. package/web/dist/assets/textarea-FjaU370i.js +0 -1
  271. package/web/dist/assets/thread-loading-77sJ8Yu_.js +0 -1
  272. package/web/dist/assets/token-metrics-Clxh03bE.js +0 -1
  273. package/web/dist/assets/utils-PYYcpCFZ.js +0 -64
  274. package/web/dist/assets/workflows-Czl0ZfXH.js +0 -11
@@ -0,0 +1,256 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { realpath } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { projectStatus } from '../task-cli/projections.js';
5
+ import { loadWorkspaceConfig } from '../workspace/config.js';
6
+ import { deriveRunContextEvents } from './event-history.js';
7
+ export const WEBHOOK_TIMEOUT_MS = 10_000;
8
+ export const WEBHOOK_ATTEMPTS = 3;
9
+ /** Wait before attempt 2 and attempt 3. */
10
+ export const WEBHOOK_BACKOFF_MS = [1_000, 4_000];
11
+ /** One POST, no retries. Shared by the queue and `POST /projects/:id/webhook/test`. */
12
+ export async function deliverOnce(target, payload, options = {}) {
13
+ try {
14
+ const response = await (options.fetch ?? fetch)(target.url, {
15
+ method: 'POST',
16
+ // A redirect would carry the Bearer token to a URL nobody configured.
17
+ redirect: 'error',
18
+ headers: {
19
+ 'content-type': 'application/json',
20
+ 'user-agent': 'cezar-task-webhook',
21
+ ...(target.token ? { authorization: `Bearer ${target.token}` } : {}),
22
+ },
23
+ body: JSON.stringify(payload),
24
+ signal: AbortSignal.timeout(options.timeoutMs ?? WEBHOOK_TIMEOUT_MS),
25
+ });
26
+ await response.body?.cancel().catch(() => undefined);
27
+ return response.ok
28
+ ? { ok: true, status: response.status }
29
+ : { ok: false, status: response.status, error: `HTTP ${response.status}` };
30
+ }
31
+ catch (error) {
32
+ const name = error instanceof Error ? error.name : '';
33
+ if (name === 'TimeoutError' || name === 'AbortError')
34
+ return { ok: false, error: 'timed out' };
35
+ const cause = error instanceof Error && error.cause instanceof Error ? `: ${error.cause.message}` : '';
36
+ return { ok: false, error: `${error instanceof Error ? error.message : String(error)}${cause}`.slice(0, 500) };
37
+ }
38
+ }
39
+ /** A 4xx other than 408/429 is the endpoint's answer, not a transient failure. */
40
+ function retryable(result) {
41
+ if (result.status === undefined)
42
+ return true;
43
+ return result.status >= 500 || result.status === 408 || result.status === 429;
44
+ }
45
+ const seenOf = (run) => ({
46
+ status: run.status,
47
+ activity: run.activity ?? null,
48
+ ask: run.hasPendingHumanAsk === true,
49
+ });
50
+ export class TaskWebhook {
51
+ store;
52
+ options;
53
+ seen = new Map();
54
+ queues = new Map();
55
+ seqs = new Map();
56
+ onRun = (run) => this.observe(run);
57
+ onDeleted = (id) => this.seen.delete(id);
58
+ disposed = false;
59
+ constructor(store, options) {
60
+ this.store = store;
61
+ this.options = options;
62
+ // Seed from what the store already holds, so a context built after a restart does not
63
+ // report every existing run as a fresh transition.
64
+ for (const run of store.listRuns())
65
+ this.seen.set(run.id, seenOf(run));
66
+ store.on('run', this.onRun);
67
+ store.on('deleted', this.onDeleted);
68
+ }
69
+ dispose() {
70
+ this.disposed = true;
71
+ this.store.off('run', this.onRun);
72
+ this.store.off('deleted', this.onDeleted);
73
+ }
74
+ /** The hand-off delivery (`POST /runs/:id/notify` turning notify on). A run created with
75
+ * `notify: true` gets the same delivery from `observe`. */
76
+ subscribed(runId, message) {
77
+ const run = this.store.getRun(runId);
78
+ if (!run)
79
+ return;
80
+ this.enqueue({ event: 'task.subscribed', run, previousStatus: null, occurredAt: new Date().toISOString(), message });
81
+ }
82
+ /** Resolves once every delivery queued so far has settled (tests, shutdown). */
83
+ async idle() {
84
+ while (this.queues.size > 0)
85
+ await Promise.all([...this.queues.values()]);
86
+ }
87
+ observe(run) {
88
+ const before = this.seen.get(run.id);
89
+ const now = seenOf(run);
90
+ this.seen.set(run.id, now);
91
+ if (!run.notify || this.disposed)
92
+ return;
93
+ const occurredAt = new Date().toISOString();
94
+ // A run created opted in (the New task toggle, `cez task start`) announces itself once, as
95
+ // `POST /runs/:id/notify` does, so the bot learns the id and link while the run is queued.
96
+ if (!before) {
97
+ this.enqueue({ event: 'task.subscribed', run, previousStatus: null, occurredAt });
98
+ return;
99
+ }
100
+ if (before.status !== now.status) {
101
+ this.enqueue({ event: 'task.status', run, previousStatus: before.status, occurredAt });
102
+ }
103
+ if (before.activity !== now.activity) {
104
+ this.enqueue({ event: 'task.activity', run, previousStatus: null, occurredAt });
105
+ }
106
+ if (!before.ask && now.ask) {
107
+ this.enqueue({ event: 'task.question', run, previousStatus: null, occurredAt });
108
+ }
109
+ }
110
+ enqueue(pending) {
111
+ const runId = pending.run.id;
112
+ // Snapshot now: the record object is live and will have moved on by the time this sends.
113
+ const snapshot = { ...pending, run: { ...pending.run } };
114
+ const previous = this.queues.get(runId) ?? Promise.resolve();
115
+ const next = previous
116
+ .then(() => this.deliver(snapshot))
117
+ .catch(() => undefined)
118
+ .finally(() => {
119
+ if (this.queues.get(runId) === next)
120
+ this.queues.delete(runId);
121
+ });
122
+ this.queues.set(runId, next);
123
+ }
124
+ async payload(pending, projectId) {
125
+ const { run } = pending;
126
+ const seq = (this.seqs.get(run.id) ?? 0) + 1;
127
+ this.seqs.set(run.id, seq);
128
+ const origin = this.options.origin() ?? '';
129
+ const url = `${origin}/p/${encodeURIComponent(projectId)}/tasks/${encodeURIComponent(run.id)}`;
130
+ const question = run.hasPendingHumanAsk ? await this.pendingQuestion(run.id) : undefined;
131
+ return {
132
+ event: pending.event,
133
+ deliveryId: randomUUID(),
134
+ seq,
135
+ projectId,
136
+ runId: run.id,
137
+ url,
138
+ status: run.status,
139
+ previousStatus: pending.previousStatus,
140
+ activity: run.activity ?? null,
141
+ occurredAt: pending.occurredAt,
142
+ ...(pending.message === undefined ? {} : { message: pending.message }),
143
+ // The same slim projection `cez task status` prints, so a bot parses one shape.
144
+ task: { ...projectStatus(run, url, question), notify: run.notify === true },
145
+ };
146
+ }
147
+ async pendingQuestion(runId) {
148
+ try {
149
+ const context = await deriveRunContextEvents(join(this.options.dataDir, 'runs', `${runId}.ndjson`));
150
+ return [...context.contextEvents].reverse().find((event) => event.type === 'ask.requested')?.questions;
151
+ }
152
+ catch {
153
+ return undefined;
154
+ }
155
+ }
156
+ async deliver(pending) {
157
+ await this.options.ready?.();
158
+ const project = await this.options.resolveProject().catch(() => undefined);
159
+ // Removed since the run opted in: nothing to send to, and nobody to tell.
160
+ if (!project?.webhook)
161
+ return;
162
+ const payload = await this.payload(pending, project.id);
163
+ const runId = pending.run.id;
164
+ if (this.options.dryRun ?? process.env.CEZ_DRY_RUN === '1') {
165
+ this.store.appendEvent(runId, { type: 'webhook.dry-run', event: payload.event, payload });
166
+ this.store.updateRun(runId, { webhook: { lastDeliveredAt: new Date().toISOString() } });
167
+ return;
168
+ }
169
+ const sleep = this.options.sleep ?? ((ms) => new Promise((done) => setTimeout(done, ms)));
170
+ let result = { ok: false, error: 'not attempted' };
171
+ let attempts = 0;
172
+ while (attempts < WEBHOOK_ATTEMPTS) {
173
+ if (attempts > 0)
174
+ await sleep(WEBHOOK_BACKOFF_MS[attempts - 1] ?? 0);
175
+ attempts += 1;
176
+ result = await deliverOnce(project.webhook, payload, {
177
+ fetch: this.options.fetch,
178
+ timeoutMs: this.options.timeoutMs,
179
+ });
180
+ if (result.ok || !retryable(result))
181
+ break;
182
+ }
183
+ const previous = this.store.getRun(runId)?.webhook;
184
+ if (result.ok) {
185
+ this.store.updateRun(runId, { webhook: { lastDeliveredAt: new Date().toISOString() } });
186
+ return;
187
+ }
188
+ const error = (result.error ?? 'delivery failed').slice(0, 500);
189
+ this.store.updateRun(runId, {
190
+ webhook: { ...(previous?.lastDeliveredAt ? { lastDeliveredAt: previous.lastDeliveredAt } : {}), lastError: error },
191
+ });
192
+ this.store.appendEvent(runId, {
193
+ type: 'webhook.failed',
194
+ event: payload.event,
195
+ deliveryId: payload.deliveryId,
196
+ attempts,
197
+ error,
198
+ ...(result.status === undefined ? {} : { status: result.status }),
199
+ });
200
+ }
201
+ }
202
+ /**
203
+ * Every project's `TaskWebhook`, keyed by store (#589). It exists so the subscriber can be
204
+ * attached BEFORE `manager.recover()`: recovery re-queues, resumes or fails the runs that were
205
+ * live when the last process exited, and a subscriber attached after it would seed those new
206
+ * statuses as the starting state and never report them. `index.ts` attaches the boot project
207
+ * right after opening its store; every lazily built project attaches through
208
+ * `ProjectContexts`' `prepareManager` hook, which runs before that project's recovery.
209
+ *
210
+ * Deliveries wait for `setOrigin`, which `startServer` calls once it knows its port.
211
+ */
212
+ export class TaskWebhooks {
213
+ options;
214
+ hooks = new WeakMap();
215
+ origin;
216
+ markReady;
217
+ ready = new Promise((done) => { this.markReady = done; });
218
+ constructor(options = {}) {
219
+ this.options = options;
220
+ if (options.origin !== undefined)
221
+ this.setOrigin(options.origin);
222
+ }
223
+ setOrigin(origin) {
224
+ this.origin = origin;
225
+ this.markReady();
226
+ }
227
+ /** Idempotent: a store already attached keeps its subscriber and its queue. `id` may be the
228
+ * reserved `default` alias, which resolves to the registry entry holding `root`. */
229
+ attach(project) {
230
+ const existing = this.hooks.get(project.store);
231
+ if (existing)
232
+ return existing;
233
+ const hook = new TaskWebhook(project.store, {
234
+ resolveProject: () => registryWebhook(project.id, project.root),
235
+ origin: () => this.origin,
236
+ ready: () => this.ready,
237
+ dataDir: join(project.root, '.ai/cezar'),
238
+ fetch: this.options.fetch,
239
+ });
240
+ this.hooks.set(project.store, hook);
241
+ return hook;
242
+ }
243
+ get(store) {
244
+ return this.hooks.get(store);
245
+ }
246
+ }
247
+ /** The registry entry this project is, read per delivery so a settings change applies at once. */
248
+ async function registryWebhook(id, root) {
249
+ const projects = (await loadWorkspaceConfig()).projects;
250
+ const real = id === 'default' ? await realpath(root).catch(() => root) : root;
251
+ const entry = id === 'default'
252
+ ? projects.find((project) => project.root === real || project.root === root)
253
+ : projects.find((project) => project.id === id);
254
+ return entry ? { id: entry.id, ...(entry.webhook ? { webhook: entry.webhook } : {}) } : undefined;
255
+ }
256
+ //# sourceMappingURL=webhook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/runs/webhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAkD5D,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AACzC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAClC,2CAA2C;AAC3C,MAAM,CAAC,MAAM,kBAAkB,GAAsB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAoBpE,uFAAuF;AACvF,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAyB,EACzB,OAAgB,EAChB,OAAO,GAAiD,EAAE;IAE1D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE;YAC1D,MAAM,EAAE,MAAM;YACd,sEAAsE;YACtE,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,YAAY,EAAE,oBAAoB;gBAClC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACrE;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;YAC7B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;SACrE,CAAC,CAAC;QACH,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACrD,OAAO,QAAQ,CAAC,EAAE;YAChB,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE;YACvC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;IAC/E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,IAAI,IAAI,KAAK,cAAc,IAAI,IAAI,KAAK,YAAY;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;QAC/F,MAAM,KAAK,GAAG,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvG,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;IACjH,CAAC;AACH,CAAC;AAED,kFAAkF;AAClF,SAAS,SAAS,CAAC,MAAsB;IACvC,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC;AAChF,CAAC;AAgBD,MAAM,MAAM,GAAG,CAAC,GAAc,EAAQ,EAAE,CAAC,CAAC;IACxC,MAAM,EAAE,GAAG,CAAC,MAAM;IAClB,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,IAAI;IAC9B,GAAG,EAAE,GAAG,CAAC,kBAAkB,KAAK,IAAI;CACrC,CAAC,CAAC;AAEH,MAAM,OAAO,WAAW;IASH,KAAK;IACL,OAAO;IATT,IAAI,GAAG,IAAI,GAAG,EAAgB,CAAC;IAC/B,MAAM,GAAG,IAAI,GAAG,EAAyB,CAAC;IAC1C,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACjC,KAAK,GAAG,CAAC,GAAc,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC9C,SAAS,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC1D,QAAQ,GAAG,KAAK,CAAC;IAEzB,YACmB,KAAe,EACf,OAA2B;qBAD3B,KAAK;uBACL,OAAO;QAExB,sFAAsF;QACtF,mDAAmD;QACnD,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,QAAQ,EAAE;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACvE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5B,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IAED,OAAO;QACL,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC;IAED;gEAC4D;IAC5D,UAAU,CAAC,KAAa,EAAE,OAAgB;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACvH,CAAC;IAED,gFAAgF;IAChF,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;YAAE,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC5E,CAAC;IAEO,OAAO,CAAC,GAAc;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC3B,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QACzC,MAAM,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC5C,2FAA2F;QAC3F,2FAA2F;QAC3F,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;YAClF,OAAO;QACT,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC;YACjC,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QACzF,CAAC;QACD,IAAI,MAAM,CAAC,QAAQ,KAAK,GAAG,CAAC,QAAQ,EAAE,CAAC;YACrC,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;QAClF,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;YAC3B,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;IAEO,OAAO,CAAC,OAAgB;QAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,yFAAyF;QACzF,MAAM,QAAQ,GAAY,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;QAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAC7D,MAAM,IAAI,GAAG,QAAQ;aAClB,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;aAClC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;aACtB,OAAO,CAAC,GAAG,EAAE;YACZ,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI;gBAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;QACL,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,OAAgB,EAAE,SAAiB;QACvD,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;QACxB,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC7C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;QAC3C,MAAM,GAAG,GAAG,GAAG,MAAM,MAAM,kBAAkB,CAAC,SAAS,CAAC,UAAU,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QAC/F,MAAM,QAAQ,GAAG,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACzF,OAAO;YACL,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,UAAU,EAAE,UAAU,EAAE;YACxB,GAAG;YACH,SAAS;YACT,KAAK,EAAE,GAAG,CAAC,EAAE;YACb,GAAG;YACH,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,IAAI;YAC9B,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;YACtE,gFAAgF;YAChF,IAAI,EAAE,EAAE,GAAG,aAAa,CAAC,GAAwB,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE;SACjG,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,eAAe,CAAC,KAAa;QACzC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC;YACpG,OAAO,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,eAAe,CAAC,EAAE,SAAS,CAAC;QACzG,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,OAAgB;QACpC,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC3E,0EAA0E;QAC1E,IAAI,CAAC,OAAO,EAAE,OAAO;YAAE,OAAO;QAC9B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,GAAG,EAAE,CAAC;YAC3D,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YAC1F,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,eAAe,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;YACxF,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QACxG,IAAI,MAAM,GAAmB,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;QACnE,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,OAAO,QAAQ,GAAG,gBAAgB,EAAE,CAAC;YACnC,IAAI,QAAQ,GAAG,CAAC;gBAAE,MAAM,KAAK,CAAC,kBAAkB,CAAC,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YACrE,QAAQ,IAAI,CAAC,CAAC;YACd,MAAM,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE;gBACnD,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;gBACzB,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;aAClC,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;gBAAE,MAAM;QAC7C,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QACnD,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACd,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,eAAe,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;YACxF,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,iBAAiB,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAChE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE;YAC1B,OAAO,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE;SACnH,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE;YAC5B,IAAI,EAAE,gBAAgB;YACtB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,QAAQ;YACR,KAAK;YACL,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;SAClE,CAAC,CAAC;IACL,CAAC;CACF;AAED;;;;;;;;;GASG;AACH,MAAM,OAAO,YAAY;IAMM,OAAO;IALnB,KAAK,GAAG,IAAI,OAAO,EAAyB,CAAC;IACtD,MAAM,CAAqB;IAC3B,SAAS,CAAc;IACd,KAAK,GAAG,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAEjF,YAA6B,OAAO,GAA8C,EAAE;uBAAvD,OAAO;QAClC,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnE,CAAC;IAED,SAAS,CAAC,MAAc;QACtB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,EAAE,CAAC;IACnB,CAAC;IAED;yFACqF;IACrF,MAAM,CAAC,OAAsD;QAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC/C,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC9B,MAAM,IAAI,GAAG,IAAI,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE;YAC1C,cAAc,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC;YAC/D,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM;YACzB,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC;YACxC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;SAC1B,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAC,KAAe;QACjB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;CACF;AAED,kGAAkG;AAClG,KAAK,UAAU,eAAe,CAAC,EAAU,EAAE,IAAY;IACrD,MAAM,QAAQ,GAAG,CAAC,MAAM,mBAAmB,EAAE,CAAC,CAAC,QAAQ,CAAC;IACxD,MAAM,IAAI,GAAG,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9E,MAAM,KAAK,GAAG,EAAE,KAAK,SAAS;QAC5B,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,IAAI,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC;QAC5E,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAClD,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACpG,CAAC"}
@@ -1,6 +1,31 @@
1
- import { type ProviderAuthService, type ProviderStatus } from '../core/provider-auth.ts';
1
+ import { type ProviderAuthService, type ProviderId, type ProviderStatus } from '../core/provider-auth.ts';
2
2
  import type { RunStore } from '../runs/store.ts';
3
- export declare function watchProviderRuntimeAuthFailures(store: RunStore, providerAuth: ProviderAuthService, onInvalidated: (status: ProviderStatus) => void): () => void;
3
+ import { type RuntimeAuthVerificationTarget } from '../workspace/agent-profiles.ts';
4
+ /** Where the self-check's probe is aimed. Injectable so tests can pin the account resolution;
5
+ * the default reads `~/.cezar/agent-accounts.json` (see {@link resolveRuntimeAuthVerificationTarget}).
6
+ * Resolving to `null` means "this incident cannot be checked" — the latch then stands. */
7
+ export type RuntimeAuthProfileResolver = (provider: ProviderId, profileId: string | undefined) => Promise<RuntimeAuthVerificationTarget | null>;
8
+ /**
9
+ * Watch a run store for the vendor errors that mean "your credentials were rejected", latch the
10
+ * provider, and — because the latch is only ever as good as the pattern match that raised it —
11
+ * immediately ask the provider's own CLI whether it was true.
12
+ *
13
+ * The self-check is aimed at the account the failing step actually ran under (`step.profileId`,
14
+ * falling back to the run's `agentProfile` for step-less errors): a named account can be rejected
15
+ * while the default login is fine, and verifying the default would clear the latch and let every
16
+ * future run on the broken account fail again. When the recorded account cannot be resolved at
17
+ * all, the incident stays latched — an unverifiable rejection is not a recovered one.
18
+ *
19
+ * `onProviderStatus` carries BOTH edges: the invalidation, and the recovery when the self-check
20
+ * finds the credentials were never gone. One callback rather than two on purpose — every caller
21
+ * wires it to the same `provider-status` fan-out, and the cockpit already folds a `connected` row
22
+ * over a latched one (`applyProviderStatusRow` drops the stale incident id), so recovery needs no
23
+ * new wiring at any of the observer's construction sites. The channel speaks DEFAULT rows (the
24
+ * cockpit's parser drops `profileId`), so a DEFAULT recovery publishes its verified row while a
25
+ * NAMED recovery publishes the provider's current cached default row — the account's own answer
26
+ * stays under the account, and a disconnected default is never shown connected.
27
+ */
28
+ export declare function watchProviderRuntimeAuthFailures(store: RunStore, providerAuth: ProviderAuthService, onProviderStatus: (status: ProviderStatus) => void, resolveProfile?: RuntimeAuthProfileResolver): () => void;
4
29
  /**
5
30
  * Process-wide dedupe for store observation. The same boot store is wired
6
31
  * before recovery and again when the HTTP app is constructed; lazy stores are
@@ -9,9 +34,10 @@ export declare function watchProviderRuntimeAuthFailures(store: RunStore, provid
9
34
  */
10
35
  export declare class ProviderRuntimeAuthObserver {
11
36
  private readonly providerAuth;
12
- private readonly onInvalidated;
37
+ private readonly onProviderStatus;
38
+ private readonly resolveProfile;
13
39
  private readonly watched;
14
- constructor(providerAuth: ProviderAuthService, onInvalidated: (status: ProviderStatus) => void);
40
+ constructor(providerAuth: ProviderAuthService, onProviderStatus: (status: ProviderStatus) => void, resolveProfile?: RuntimeAuthProfileResolver);
15
41
  watch(store: RunStore): void;
16
42
  }
17
43
  /**
@@ -1,6 +1,27 @@
1
1
  import { isRuntimeProviderAuthFailure, } from '../core/provider-auth.js';
2
+ import { resolveRuntimeAuthVerificationTarget, } from '../workspace/agent-profiles.js';
2
3
  const AUTH_ERROR_EVENT_TYPES = new Set(['error', 'session.error', 'note']);
3
- export function watchProviderRuntimeAuthFailures(store, providerAuth, onInvalidated) {
4
+ /**
5
+ * Watch a run store for the vendor errors that mean "your credentials were rejected", latch the
6
+ * provider, and — because the latch is only ever as good as the pattern match that raised it —
7
+ * immediately ask the provider's own CLI whether it was true.
8
+ *
9
+ * The self-check is aimed at the account the failing step actually ran under (`step.profileId`,
10
+ * falling back to the run's `agentProfile` for step-less errors): a named account can be rejected
11
+ * while the default login is fine, and verifying the default would clear the latch and let every
12
+ * future run on the broken account fail again. When the recorded account cannot be resolved at
13
+ * all, the incident stays latched — an unverifiable rejection is not a recovered one.
14
+ *
15
+ * `onProviderStatus` carries BOTH edges: the invalidation, and the recovery when the self-check
16
+ * finds the credentials were never gone. One callback rather than two on purpose — every caller
17
+ * wires it to the same `provider-status` fan-out, and the cockpit already folds a `connected` row
18
+ * over a latched one (`applyProviderStatusRow` drops the stale incident id), so recovery needs no
19
+ * new wiring at any of the observer's construction sites. The channel speaks DEFAULT rows (the
20
+ * cockpit's parser drops `profileId`), so a DEFAULT recovery publishes its verified row while a
21
+ * NAMED recovery publishes the provider's current cached default row — the account's own answer
22
+ * stays under the account, and a disconnected default is never shown connected.
23
+ */
24
+ export function watchProviderRuntimeAuthFailures(store, providerAuth, onProviderStatus, resolveProfile = resolveRuntimeAuthVerificationTarget) {
4
25
  const onEvent = ({ runId, event }) => {
5
26
  if (!AUTH_ERROR_EVENT_TYPES.has(event.type))
6
27
  return;
@@ -14,11 +35,16 @@ export function watchProviderRuntimeAuthFailures(store, providerAuth, onInvalida
14
35
  ? run.steps.find(({ id }) => id === event.stepId)
15
36
  : undefined;
16
37
  const provider = step?.backend ?? run.runner ?? 'claude';
38
+ // The run-level profile belongs to the run's RUNNER: a mixed-backend step failing on another
39
+ // backend ran under THAT backend's own default login, and asking the resolver for the runner's
40
+ // profile under the wrong provider can only mis-answer the check or stall it unresolved.
41
+ const profileId = step?.profileId
42
+ ?? (provider === (run.runner ?? 'claude') ? run.agentProfile : undefined);
17
43
  const report = providerAuth.reportRuntimeAuthFailure(provider);
18
44
  if (!report)
19
45
  return;
20
46
  if (report.transitioned)
21
- onInvalidated(report.status);
47
+ onProviderStatus(report.status);
22
48
  const duplicate = store.readEvents(runId).some((candidate) => candidate.type === 'provider-auth-required'
23
49
  && candidate.provider === provider
24
50
  && candidate.authFailureId === report.status.authFailureId);
@@ -30,6 +56,43 @@ export function watchProviderRuntimeAuthFailures(store, providerAuth, onInvalida
30
56
  ...(event.stepId ? { stepId: event.stepId } : {}),
31
57
  });
32
58
  }
59
+ // The self-check rides the LATCH EDGE, not every matching line: the second and third auth-shaped
60
+ // error of one failing run describe the incident already standing, and re-asking the CLI about it
61
+ // would only spend spawns on an answer we have. The service's own cooldown backstops the case the
62
+ // edge cannot see — a rejection that re-latches right after a successful recovery.
63
+ if (!report.transitioned)
64
+ return;
65
+ // The check carries the incident's generation THROUGH the account-resolution wait: while the
66
+ // resolver is pending a newer failure can replace the incident, and an older question must
67
+ // then stand down rather than answer for it.
68
+ const observed = { generation: report.generation };
69
+ void (async () => {
70
+ const target = await resolveProfile(provider, profileId);
71
+ // An account we cannot name cannot be verified: leave the latch exactly as it stands and let
72
+ // Settings' Try again — which asks no such question — stay the way out.
73
+ if (!target)
74
+ return;
75
+ const recovered = target.kind === 'profile'
76
+ ? await providerAuth.verifyRuntimeAuthFailure(provider, {
77
+ id: target.id,
78
+ configDir: target.configDir,
79
+ }, observed)
80
+ : await providerAuth.verifyRuntimeAuthFailure(provider, undefined, observed);
81
+ if (!recovered)
82
+ return;
83
+ if (target.kind !== 'profile') {
84
+ onProviderStatus(recovered);
85
+ return;
86
+ }
87
+ // A NAMED recovery answers for one account, not for the provider's default login, and this
88
+ // channel carries default rows — the cockpit's parser drops `profileId`, so publishing the
89
+ // account row would mark a disconnected default connected. Publish the provider's CURRENT
90
+ // default row (cache only, no spawn) so observers see the latch lift with the default's own
91
+ // answer; with nothing cached there is no default row to reconcile on this channel.
92
+ const defaultRow = providerAuth.peekStatus()?.providers.find(({ provider: id }) => id === provider);
93
+ if (defaultRow)
94
+ onProviderStatus(defaultRow);
95
+ })().catch(() => { });
33
96
  };
34
97
  store.on('event', onEvent);
35
98
  return () => store.off('event', onEvent);
@@ -42,17 +105,19 @@ export function watchProviderRuntimeAuthFailures(store, providerAuth, onInvalida
42
105
  */
43
106
  export class ProviderRuntimeAuthObserver {
44
107
  providerAuth;
45
- onInvalidated;
108
+ onProviderStatus;
109
+ resolveProfile;
46
110
  watched = new WeakSet();
47
- constructor(providerAuth, onInvalidated) {
111
+ constructor(providerAuth, onProviderStatus, resolveProfile = resolveRuntimeAuthVerificationTarget) {
48
112
  this.providerAuth = providerAuth;
49
- this.onInvalidated = onInvalidated;
113
+ this.onProviderStatus = onProviderStatus;
114
+ this.resolveProfile = resolveProfile;
50
115
  }
51
116
  watch(store) {
52
117
  if (this.watched.has(store))
53
118
  return;
54
119
  this.watched.add(store);
55
- watchProviderRuntimeAuthFailures(store, this.providerAuth, this.onInvalidated);
120
+ watchProviderRuntimeAuthFailures(store, this.providerAuth, this.onProviderStatus, this.resolveProfile);
56
121
  }
57
122
  }
58
123
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"provider-auth-runtime.js","sourceRoot":"","sources":["../../src/server/provider-auth-runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider-auth-runtime.js","sourceRoot":"","sources":["../../src/server/provider-auth-runtime.ts"],"names":[],"mappings":"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"}