@wjarka/cezarion 0.14.8 → 0.14.9-dev.1009
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.
- package/README.md +131 -2
- package/dist/application-update/bin-recovery.d.ts +5 -0
- package/dist/application-update/bin-recovery.js +96 -0
- package/dist/application-update/bin-recovery.js.map +1 -0
- package/dist/application-update/discovery.d.ts +22 -0
- package/dist/application-update/discovery.js +91 -0
- package/dist/application-update/discovery.js.map +1 -0
- package/dist/application-update/helper.d.ts +57 -0
- package/dist/application-update/helper.js +374 -0
- package/dist/application-update/helper.js.map +1 -0
- package/dist/application-update/launcher.d.ts +8 -0
- package/dist/application-update/launcher.js +53 -0
- package/dist/application-update/launcher.js.map +1 -0
- package/dist/application-update/lock.d.ts +4 -0
- package/dist/application-update/lock.js +70 -0
- package/dist/application-update/lock.js.map +1 -0
- package/dist/application-update/npm-process.d.ts +17 -0
- package/dist/application-update/npm-process.js +133 -0
- package/dist/application-update/npm-process.js.map +1 -0
- package/dist/application-update/service.d.ts +69 -0
- package/dist/application-update/service.js +456 -0
- package/dist/application-update/service.js.map +1 -0
- package/dist/artifacts/cli.d.ts +1 -0
- package/dist/artifacts/cli.js +32 -0
- package/dist/artifacts/cli.js.map +1 -0
- package/dist/artifacts/lifecycle.d.ts +4 -0
- package/dist/artifacts/lifecycle.js +42 -0
- package/dist/artifacts/lifecycle.js.map +1 -0
- package/dist/artifacts/resolve.d.ts +18 -0
- package/dist/artifacts/resolve.js +102 -0
- package/dist/artifacts/resolve.js.map +1 -0
- package/dist/artifacts/store.d.ts +8 -0
- package/dist/artifacts/store.js +323 -0
- package/dist/artifacts/store.js.map +1 -0
- package/dist/automations/scheduler.d.ts +6 -0
- package/dist/automations/scheduler.js +45 -17
- package/dist/automations/scheduler.js.map +1 -1
- package/dist/automations/store.d.ts +12 -4
- package/dist/automations/store.js +199 -22
- package/dist/automations/store.js.map +1 -1
- package/dist/automations/types.d.ts +2 -0
- package/dist/automations/types.js +1 -0
- package/dist/automations/types.js.map +1 -1
- package/dist/ci-wait/mcp.d.ts +3 -0
- package/dist/ci-wait/mcp.js +14 -3
- package/dist/ci-wait/mcp.js.map +1 -1
- package/dist/contract/application-update.d.ts +32 -0
- package/dist/contract/artifacts.d.ts +83 -0
- package/dist/contract/ask-schema.d.ts +32 -0
- package/dist/contract/ask.d.ts +2 -32
- package/dist/contract/automations.d.ts +6 -0
- package/dist/contract/conversations.d.ts +165 -0
- package/dist/contract/delegation.d.ts +68 -0
- package/dist/contract/discovery.d.ts +134 -0
- package/dist/contract/events.d.ts +49 -0
- package/dist/contract/health.d.ts +12 -0
- package/dist/contract/index.d.ts +3 -0
- package/dist/contract/index.js +1654 -1454
- package/dist/contract/projects.d.ts +40 -0
- package/dist/contract/runs.d.ts +186 -0
- package/dist/contract/skills.d.ts +33 -0
- package/dist/core/agent-runner.d.ts +33 -4
- package/dist/core/agent-runner.js +5 -0
- package/dist/core/agent-runner.js.map +1 -1
- package/dist/core/claude-cli-runner.d.ts +6 -12
- package/dist/core/claude-cli-runner.js +90 -20
- package/dist/core/claude-cli-runner.js.map +1 -1
- package/dist/core/codex-app-server-runner.d.ts +2 -1
- package/dist/core/codex-app-server-runner.js +327 -92
- package/dist/core/codex-app-server-runner.js.map +1 -1
- package/dist/core/codex-app-server-transport.d.ts +13 -1
- package/dist/core/codex-app-server-transport.js +58 -17
- package/dist/core/codex-app-server-transport.js.map +1 -1
- package/dist/core/cursor-acp-runner.d.ts +6 -1
- package/dist/core/cursor-acp-runner.js +162 -26
- package/dist/core/cursor-acp-runner.js.map +1 -1
- package/dist/core/cursor-provider-error.d.ts +3 -0
- package/dist/core/cursor-provider-error.js +16 -1
- package/dist/core/cursor-provider-error.js.map +1 -1
- package/dist/core/input-submissions.d.ts +14 -0
- package/dist/core/input-submissions.js +26 -0
- package/dist/core/input-submissions.js.map +1 -0
- package/dist/core/opencode-server-runner.d.ts +4 -1
- package/dist/core/opencode-server-runner.js +156 -26
- package/dist/core/opencode-server-runner.js.map +1 -1
- package/dist/core/pi-runner.d.ts +2 -1
- package/dist/core/pi-runner.js +88 -10
- package/dist/core/pi-runner.js.map +1 -1
- package/dist/core/provider-auth.d.ts +99 -1
- package/dist/core/provider-auth.js +203 -2
- package/dist/core/provider-auth.js.map +1 -1
- package/dist/delegation/cli.d.ts +1 -0
- package/dist/delegation/cli.js +103 -7
- package/dist/delegation/cli.js.map +1 -1
- package/dist/delegation/conversations.js +13 -5
- package/dist/delegation/conversations.js.map +1 -1
- package/dist/delegation/input.d.ts +2 -1
- package/dist/delegation/input.js +6 -1
- package/dist/delegation/input.js.map +1 -1
- package/dist/delegation/policy.d.ts +3 -2
- package/dist/delegation/policy.js +3 -1
- package/dist/delegation/policy.js.map +1 -1
- package/dist/delegation/process-liveness.d.ts +66 -0
- package/dist/delegation/process-liveness.js +215 -0
- package/dist/delegation/process-liveness.js.map +1 -0
- package/dist/delegation/provision.d.ts +1 -1
- package/dist/delegation/provision.js +10 -5
- package/dist/delegation/provision.js.map +1 -1
- package/dist/delegation/questions.d.ts +19 -0
- package/dist/delegation/questions.js +45 -0
- package/dist/delegation/questions.js.map +1 -0
- package/dist/delegation/results.d.ts +1 -1
- package/dist/delegation/results.js +33 -19
- package/dist/delegation/results.js.map +1 -1
- package/dist/delegation/routes.d.ts +185 -11
- package/dist/delegation/routes.js +6 -2
- package/dist/delegation/routes.js.map +1 -1
- package/dist/delegation/service.d.ts +23 -5
- package/dist/delegation/service.js +240 -17
- package/dist/delegation/service.js.map +1 -1
- package/dist/delegation/transport.d.ts +178 -15
- package/dist/delegation/workspace.d.ts +1 -1
- package/dist/delegation/workspace.js +13 -6
- package/dist/delegation/workspace.js.map +1 -1
- package/dist/discovery/catalog.d.ts +14 -0
- package/dist/discovery/catalog.js +31 -0
- package/dist/discovery/catalog.js.map +1 -0
- package/dist/discovery/cli.d.ts +8 -0
- package/dist/discovery/cli.js +104 -0
- package/dist/discovery/cli.js.map +1 -0
- package/dist/git-worktree.d.ts +3 -1
- package/dist/git-worktree.js +26 -4
- package/dist/git-worktree.js.map +1 -1
- package/dist/index.js +93 -26
- package/dist/index.js.map +1 -1
- package/dist/open-url.d.ts +2 -0
- package/dist/open-url.js +20 -0
- package/dist/open-url.js.map +1 -0
- package/dist/release/snapshot.d.ts +3 -3
- package/dist/release/snapshot.js +6 -6
- package/dist/release/snapshot.js.map +1 -1
- package/dist/runs/agent-tmpdir.d.ts +2 -0
- package/dist/runs/agent-tmpdir.js +5 -2
- package/dist/runs/agent-tmpdir.js.map +1 -1
- package/dist/runs/client-request.d.ts +11 -0
- package/dist/runs/client-request.js +26 -0
- package/dist/runs/client-request.js.map +1 -0
- package/dist/runs/delegation-state.d.ts +17 -0
- package/dist/runs/event-history.js +6 -0
- package/dist/runs/event-history.js.map +1 -1
- package/dist/runs/retention.d.ts +7 -2
- package/dist/runs/retention.js +39 -7
- package/dist/runs/retention.js.map +1 -1
- package/dist/runs/store.d.ts +100 -6
- package/dist/runs/store.js +245 -2
- package/dist/runs/store.js.map +1 -1
- package/dist/runs/webhook.d.ts +125 -0
- package/dist/runs/webhook.js +256 -0
- package/dist/runs/webhook.js.map +1 -0
- package/dist/server/project-context.d.ts +2 -0
- package/dist/server/project-context.js +1 -0
- package/dist/server/project-context.js.map +1 -1
- package/dist/server/provider-auth-runtime.d.ts +30 -4
- package/dist/server/provider-auth-runtime.js +71 -6
- package/dist/server/provider-auth-runtime.js.map +1 -1
- package/dist/server/server.d.ts +8226 -4860
- package/dist/server/server.js +311 -15
- package/dist/server/server.js.map +1 -1
- package/dist/server-install/platforms/ubuntu-vps.d.ts +5 -1
- package/dist/server-install/platforms/ubuntu-vps.js +160 -18
- package/dist/server-install/platforms/ubuntu-vps.js.map +1 -1
- package/dist/server-install/steps.d.ts +4 -2
- package/dist/server-install/steps.js +5 -4
- package/dist/server-install/steps.js.map +1 -1
- package/dist/skills-remote.d.ts +30 -5
- package/dist/skills-remote.js +122 -32
- package/dist/skills-remote.js.map +1 -1
- package/dist/skills.js +15 -6
- package/dist/skills.js.map +1 -1
- package/dist/task-cli/cli.d.ts +38 -0
- package/dist/task-cli/cli.js +580 -0
- package/dist/task-cli/cli.js.map +1 -0
- package/dist/task-cli/discovery.d.ts +22 -0
- package/dist/task-cli/discovery.js +96 -0
- package/dist/task-cli/discovery.js.map +1 -0
- package/dist/task-cli/http.d.ts +46 -0
- package/dist/task-cli/http.js +101 -0
- package/dist/task-cli/http.js.map +1 -0
- package/dist/task-cli/projections.d.ts +40 -0
- package/dist/task-cli/projections.js +45 -0
- package/dist/task-cli/projections.js.map +1 -0
- package/dist/task-cli/watch.d.ts +78 -0
- package/dist/task-cli/watch.js +336 -0
- package/dist/task-cli/watch.js.map +1 -0
- package/dist/workflows/run.d.ts +160 -2
- package/dist/workflows/run.js +1141 -108
- package/dist/workflows/run.js.map +1 -1
- package/dist/workspace/agent-profiles.d.ts +22 -0
- package/dist/workspace/agent-profiles.js +15 -0
- package/dist/workspace/agent-profiles.js.map +1 -1
- package/dist/workspace/config.d.ts +9 -0
- package/dist/workspace/config.js +13 -1
- package/dist/workspace/config.js.map +1 -1
- package/dist/workspace/projects-cli.js +1 -1
- package/dist/workspace/projects.d.ts +24 -1
- package/dist/workspace/projects.js +14 -1
- package/dist/workspace/projects.js.map +1 -1
- package/package.json +5 -5
- package/scripts/mock-claude.mjs +64 -2
- package/scripts/mock-codex-app-server.mjs +124 -1
- package/scripts/mock-cursor-acp.mjs +54 -3
- package/scripts/mock-cursor-hang-stdin-late.mjs +35 -0
- package/scripts/mock-cursor-hang-stdin.mjs +30 -0
- package/scripts/mock-opencode-serve.mjs +102 -2
- package/scripts/mock-pi-rpc.mjs +82 -3
- package/web/dist/assets/agent-accounts-CerclGiO.js +1 -0
- package/web/dist/assets/centered-state-DH8qtCz-.js +43 -0
- package/web/dist/assets/collapsible-De2G0xqQ.js +1 -0
- package/web/dist/assets/commit-list-s6JPY3qv.js +1 -0
- package/web/dist/assets/compare-variants-BQu_t-_g.js +1 -0
- package/web/dist/assets/{diff-tRE59UNb2.js → diff-8M5HlDxq2.js} +2 -2
- package/web/dist/assets/diff-controls-B6ok0TtQ.js +1 -0
- package/web/dist/assets/{diff-stat-Cgnl_hYF.js → diff-stat-D1AODN2a.js} +1 -1
- package/web/dist/assets/{diff-view-DN1ort7Q.js → diff-view-Bs5Gh7UF.js} +2 -2
- package/web/dist/assets/dropdown-menu-7KGQMoFj.js +1 -0
- package/web/dist/assets/git-toolbar-DqbapMXr.js +1 -0
- package/web/dist/assets/github-DCkk6sBm.js +1 -0
- package/web/dist/assets/{image-preview-C2JGcBlC.js → image-preview-jzHoEyLM.js} +1 -1
- package/web/dist/assets/index-Bnva-ttR.js +7 -0
- package/web/dist/assets/index-D5NkwqY7.css +1 -0
- package/web/dist/assets/markdown-DvbymqXz.js +2 -0
- package/web/dist/assets/pill-BL6ugwXo.js +1 -0
- package/web/dist/assets/project-router-ChC5Rb-Y.js +1 -0
- package/web/dist/assets/prompt-templates-j8qlK7c-.js +15 -0
- package/web/dist/assets/repo-git-_h1NjOVt.js +1 -0
- package/web/dist/assets/{run-diff-CyG0Nciv.js → run-diff-BuATgZpx.js} +2 -2
- package/web/dist/assets/run-header-DuAWswYM.js +1 -0
- package/web/dist/assets/skills-C-fq5BrZ.js +1 -0
- package/web/dist/assets/{tab-link-BWNp3mLY.js → tab-link-BmGKj9Rt.js} +1 -1
- package/web/dist/assets/task-changes-CHa6JWOS.js +1 -0
- package/web/dist/assets/task-commits-BqCqyWm1.js +1 -0
- package/web/dist/assets/task-files-BSA0l-YP.js +2 -0
- package/web/dist/assets/task-thread-Bw_nQuTx.css +1 -0
- package/web/dist/assets/task-thread-Q7Nj33DH.js +9 -0
- package/web/dist/assets/textarea-ByZ-txS7.js +1 -0
- package/web/dist/assets/thread-loading-DHT9p5o5.js +1 -0
- package/web/dist/assets/token-metrics-k4XoovDS.js +1 -0
- package/web/dist/assets/utils-BTFBhZ55.js +64 -0
- package/web/dist/assets/workflows-HJOd3lVi.js +11 -0
- package/web/dist/assets/{zoomable-image-Z3JDnm0b.js → zoomable-image-Ba6y6Wyl.js} +1 -1
- package/web/dist/index.html +14 -14
- package/web/dist/assets/agent-accounts-BZm_2WAv.js +0 -1
- package/web/dist/assets/alert-dialog-B422RI-k.js +0 -43
- package/web/dist/assets/collapsible-Cy_Fmkrd.js +0 -1
- package/web/dist/assets/commit-list-Dcnk7TnI.js +0 -1
- package/web/dist/assets/compare-variants-Ciqwvd_f.js +0 -1
- package/web/dist/assets/diff-controls-BGrXGi7O.js +0 -1
- package/web/dist/assets/dropdown-menu-dwDGT8MM.js +0 -1
- package/web/dist/assets/git-toolbar-UiHnGvE0.js +0 -1
- package/web/dist/assets/github-D-MrkbJ7.js +0 -1
- package/web/dist/assets/ibm-plex-mono-regular-BF3vfe7_.ttf +0 -0
- package/web/dist/assets/index-BszfYvBq.js +0 -7
- package/web/dist/assets/index-CWh4pKP3.css +0 -1
- package/web/dist/assets/markdown-C_IcKVQd.js +0 -2
- package/web/dist/assets/pill-BsbO6G7y.js +0 -1
- package/web/dist/assets/project-router-DbLkll25.js +0 -1
- package/web/dist/assets/prompt-templates-BlTGJB5W.js +0 -15
- package/web/dist/assets/repo-git-Bm3s6Why.js +0 -1
- package/web/dist/assets/run-header-IFyIGCey.js +0 -1
- package/web/dist/assets/skills-C-C4DVFY.js +0 -1
- package/web/dist/assets/task-changes-D2PHtWUW.js +0 -1
- package/web/dist/assets/task-commits-N5u9U0_R.js +0 -1
- package/web/dist/assets/task-files-BS7c7CFm.js +0 -2
- package/web/dist/assets/task-thread-BQFdz1dJ.css +0 -1
- package/web/dist/assets/task-thread-DGM2dZV-.js +0 -9
- package/web/dist/assets/textarea-FjaU370i.js +0 -1
- package/web/dist/assets/thread-loading-77sJ8Yu_.js +0 -1
- package/web/dist/assets/token-metrics-Clxh03bE.js +0 -1
- package/web/dist/assets/utils-PYYcpCFZ.js +0 -64
- package/web/dist/assets/workflows-Czl0ZfXH.js +0 -11
package/dist/runs/store.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import type { CiWait, ConversationState, AgentInput, DelegationState, WorkerCollectedResult } from '../contract/index.js';
|
|
3
|
+
import type { CiWait, ConversationState, AgentInput, InboxClaim, DelegationState, WorkerCollectedResult } from '../contract/index.js';
|
|
4
4
|
import { type WorkerExecutionIdentity } from '../delegation/execution-identity.ts';
|
|
5
|
+
import { type WorkerProcessRecord } from '../delegation/process-liveness.ts';
|
|
5
6
|
import { workflowDefSchema } from '../workflows/types.ts';
|
|
6
7
|
import type { RunnerId } from '../core/agent-runner.ts';
|
|
7
8
|
export type RunStatus = 'queued' | 'running' | 'waiting' | 'review' | 'done' | 'failed' | 'cancelled';
|
|
@@ -125,6 +126,18 @@ export declare const runRecordSchema: z.ZodObject<{
|
|
|
125
126
|
}>;
|
|
126
127
|
resumed: z.ZodOptional<z.ZodLiteral<true>>;
|
|
127
128
|
instruction: z.ZodOptional<z.ZodString>;
|
|
129
|
+
question: z.ZodOptional<z.ZodObject<{
|
|
130
|
+
questions: z.ZodArray<z.ZodObject<{
|
|
131
|
+
id: z.ZodOptional<z.ZodString>;
|
|
132
|
+
header: z.ZodString;
|
|
133
|
+
question: z.ZodString;
|
|
134
|
+
options: z.ZodArray<z.ZodObject<{
|
|
135
|
+
label: z.ZodString;
|
|
136
|
+
description: z.ZodOptional<z.ZodString>;
|
|
137
|
+
}, z.core.$strict>>;
|
|
138
|
+
multiSelect: z.ZodOptional<z.ZodBoolean>;
|
|
139
|
+
}, z.core.$strict>>;
|
|
140
|
+
}, z.core.$strict>>;
|
|
128
141
|
}, z.core.$strict>>;
|
|
129
142
|
outcomes: z.ZodArray<z.ZodObject<{
|
|
130
143
|
requestId: z.ZodUUID;
|
|
@@ -133,6 +146,7 @@ export declare const runRecordSchema: z.ZodObject<{
|
|
|
133
146
|
"completed-without-reply": "completed-without-reply";
|
|
134
147
|
destroyed: "destroyed";
|
|
135
148
|
failed: "failed";
|
|
149
|
+
"human-fallback": "human-fallback";
|
|
136
150
|
replied: "replied";
|
|
137
151
|
"sender-closed": "sender-closed";
|
|
138
152
|
"timed-out": "timed-out";
|
|
@@ -175,6 +189,7 @@ export declare const runRecordSchema: z.ZodObject<{
|
|
|
175
189
|
"completed-without-reply": "completed-without-reply";
|
|
176
190
|
destroyed: "destroyed";
|
|
177
191
|
failed: "failed";
|
|
192
|
+
"human-fallback": "human-fallback";
|
|
178
193
|
replied: "replied";
|
|
179
194
|
"sender-closed": "sender-closed";
|
|
180
195
|
"timed-out": "timed-out";
|
|
@@ -228,6 +243,7 @@ export declare const runRecordSchema: z.ZodObject<{
|
|
|
228
243
|
"completed-without-reply": "completed-without-reply";
|
|
229
244
|
destroyed: "destroyed";
|
|
230
245
|
failed: "failed";
|
|
246
|
+
"human-fallback": "human-fallback";
|
|
231
247
|
replied: "replied";
|
|
232
248
|
"sender-closed": "sender-closed";
|
|
233
249
|
"timed-out": "timed-out";
|
|
@@ -316,6 +332,7 @@ export declare const runRecordSchema: z.ZodObject<{
|
|
|
316
332
|
"completed-without-reply": "completed-without-reply";
|
|
317
333
|
destroyed: "destroyed";
|
|
318
334
|
failed: "failed";
|
|
335
|
+
"human-fallback": "human-fallback";
|
|
319
336
|
replied: "replied";
|
|
320
337
|
"sender-closed": "sender-closed";
|
|
321
338
|
"timed-out": "timed-out";
|
|
@@ -369,6 +386,7 @@ export declare const runRecordSchema: z.ZodObject<{
|
|
|
369
386
|
"completed-without-reply": "completed-without-reply";
|
|
370
387
|
destroyed: "destroyed";
|
|
371
388
|
failed: "failed";
|
|
389
|
+
"human-fallback": "human-fallback";
|
|
372
390
|
replied: "replied";
|
|
373
391
|
"sender-closed": "sender-closed";
|
|
374
392
|
"timed-out": "timed-out";
|
|
@@ -486,6 +504,15 @@ export declare const runRecordSchema: z.ZodObject<{
|
|
|
486
504
|
text: z.ZodString;
|
|
487
505
|
createdAt: z.ZodISODateTime;
|
|
488
506
|
deliveredAt: z.ZodOptional<z.ZodISODateTime>;
|
|
507
|
+
consumedAt: z.ZodOptional<z.ZodISODateTime>;
|
|
508
|
+
awaitingRead: z.ZodOptional<z.ZodLiteral<true>>;
|
|
509
|
+
inboxClaim: z.ZodOptional<z.ZodObject<{
|
|
510
|
+
receiptId: z.ZodUUID;
|
|
511
|
+
generation: z.ZodUUID;
|
|
512
|
+
expiresAt: z.ZodISODateTime;
|
|
513
|
+
acknowledgedAt: z.ZodOptional<z.ZodISODateTime>;
|
|
514
|
+
memberIds: z.ZodOptional<z.ZodArray<z.ZodUUID>>;
|
|
515
|
+
}, z.core.$strict>>;
|
|
489
516
|
}, z.core.$strict>>>;
|
|
490
517
|
ciWait: z.ZodOptional<z.ZodObject<{
|
|
491
518
|
prUrl: z.ZodString;
|
|
@@ -592,6 +619,11 @@ export declare const runRecordSchema: z.ZodObject<{
|
|
|
592
619
|
systemPrompt: z.ZodOptional<z.ZodString>;
|
|
593
620
|
generateFollowups: z.ZodOptional<z.ZodBoolean>;
|
|
594
621
|
autonomous: z.ZodOptional<z.ZodBoolean>;
|
|
622
|
+
notify: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
|
|
623
|
+
webhook: z.ZodCatch<z.ZodOptional<z.ZodObject<{
|
|
624
|
+
lastDeliveredAt: z.ZodOptional<z.ZodString>;
|
|
625
|
+
lastError: z.ZodOptional<z.ZodString>;
|
|
626
|
+
}, z.core.$strip>>>;
|
|
595
627
|
automation: z.ZodOptional<z.ZodObject<{
|
|
596
628
|
automationId: z.ZodString;
|
|
597
629
|
automationRevision: z.ZodNumber;
|
|
@@ -648,6 +680,8 @@ export declare const runRecordSchema: z.ZodObject<{
|
|
|
648
680
|
worktreeReclaimedAt: z.ZodOptional<z.ZodString>;
|
|
649
681
|
groupId: z.ZodOptional<z.ZodString>;
|
|
650
682
|
variant: z.ZodOptional<z.ZodString>;
|
|
683
|
+
clientRequestId: z.ZodOptional<z.ZodString>;
|
|
684
|
+
clientRequestHash: z.ZodOptional<z.ZodString>;
|
|
651
685
|
peakRssBytes: z.ZodOptional<z.ZodNumber>;
|
|
652
686
|
peakProcCount: z.ZodOptional<z.ZodNumber>;
|
|
653
687
|
archived: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -777,10 +811,22 @@ export declare function parseRunRecords(raw: unknown): z.ZodSafeParseResult<{
|
|
|
777
811
|
state: "accepted" | "continuation-required" | "destroyed" | "late";
|
|
778
812
|
resumed?: true | undefined;
|
|
779
813
|
instruction?: string | undefined;
|
|
814
|
+
question?: {
|
|
815
|
+
questions: {
|
|
816
|
+
id?: string | undefined;
|
|
817
|
+
header: string;
|
|
818
|
+
question: string;
|
|
819
|
+
options: {
|
|
820
|
+
label: string;
|
|
821
|
+
description?: string | undefined;
|
|
822
|
+
}[];
|
|
823
|
+
multiSelect?: boolean | undefined;
|
|
824
|
+
}[];
|
|
825
|
+
} | undefined;
|
|
780
826
|
}[];
|
|
781
827
|
outcomes: {
|
|
782
828
|
requestId: string;
|
|
783
|
-
status: "cancelled" | "completed-without-reply" | "destroyed" | "failed" | "replied" | "sender-closed" | "timed-out";
|
|
829
|
+
status: "cancelled" | "completed-without-reply" | "destroyed" | "failed" | "human-fallback" | "replied" | "sender-closed" | "timed-out";
|
|
784
830
|
observedAt: string;
|
|
785
831
|
replyId?: string | undefined;
|
|
786
832
|
}[];
|
|
@@ -803,7 +849,7 @@ export declare function parseRunRecords(raw: unknown): z.ZodSafeParseResult<{
|
|
|
803
849
|
requestIds?: string[] | undefined;
|
|
804
850
|
requestOutcomes?: {
|
|
805
851
|
requestId: string;
|
|
806
|
-
status: "cancelled" | "completed-without-reply" | "destroyed" | "failed" | "replied" | "sender-closed" | "timed-out";
|
|
852
|
+
status: "cancelled" | "completed-without-reply" | "destroyed" | "failed" | "human-fallback" | "replied" | "sender-closed" | "timed-out";
|
|
807
853
|
observedAt: string;
|
|
808
854
|
replyId?: string | undefined;
|
|
809
855
|
}[] | undefined;
|
|
@@ -830,7 +876,7 @@ export declare function parseRunRecords(raw: unknown): z.ZodSafeParseResult<{
|
|
|
830
876
|
requestIds?: string[] | undefined;
|
|
831
877
|
requestOutcomes?: {
|
|
832
878
|
requestId: string;
|
|
833
|
-
status: "cancelled" | "completed-without-reply" | "destroyed" | "failed" | "replied" | "sender-closed" | "timed-out";
|
|
879
|
+
status: "cancelled" | "completed-without-reply" | "destroyed" | "failed" | "human-fallback" | "replied" | "sender-closed" | "timed-out";
|
|
834
880
|
observedAt: string;
|
|
835
881
|
replyId?: string | undefined;
|
|
836
882
|
}[] | undefined;
|
|
@@ -877,7 +923,7 @@ export declare function parseRunRecords(raw: unknown): z.ZodSafeParseResult<{
|
|
|
877
923
|
requestIds?: string[] | undefined;
|
|
878
924
|
requestOutcomes?: {
|
|
879
925
|
requestId: string;
|
|
880
|
-
status: "cancelled" | "completed-without-reply" | "destroyed" | "failed" | "replied" | "sender-closed" | "timed-out";
|
|
926
|
+
status: "cancelled" | "completed-without-reply" | "destroyed" | "failed" | "human-fallback" | "replied" | "sender-closed" | "timed-out";
|
|
881
927
|
observedAt: string;
|
|
882
928
|
replyId?: string | undefined;
|
|
883
929
|
}[] | undefined;
|
|
@@ -904,7 +950,7 @@ export declare function parseRunRecords(raw: unknown): z.ZodSafeParseResult<{
|
|
|
904
950
|
requestIds?: string[] | undefined;
|
|
905
951
|
requestOutcomes?: {
|
|
906
952
|
requestId: string;
|
|
907
|
-
status: "cancelled" | "completed-without-reply" | "destroyed" | "failed" | "replied" | "sender-closed" | "timed-out";
|
|
953
|
+
status: "cancelled" | "completed-without-reply" | "destroyed" | "failed" | "human-fallback" | "replied" | "sender-closed" | "timed-out";
|
|
908
954
|
observedAt: string;
|
|
909
955
|
replyId?: string | undefined;
|
|
910
956
|
}[] | undefined;
|
|
@@ -974,6 +1020,15 @@ export declare function parseRunRecords(raw: unknown): z.ZodSafeParseResult<{
|
|
|
974
1020
|
text: string;
|
|
975
1021
|
createdAt: string;
|
|
976
1022
|
deliveredAt?: string | undefined;
|
|
1023
|
+
consumedAt?: string | undefined;
|
|
1024
|
+
awaitingRead?: true | undefined;
|
|
1025
|
+
inboxClaim?: {
|
|
1026
|
+
receiptId: string;
|
|
1027
|
+
generation: string;
|
|
1028
|
+
expiresAt: string;
|
|
1029
|
+
acknowledgedAt?: string | undefined;
|
|
1030
|
+
memberIds?: string[] | undefined;
|
|
1031
|
+
} | undefined;
|
|
977
1032
|
}[] | undefined;
|
|
978
1033
|
ciWait?: {
|
|
979
1034
|
prUrl: string;
|
|
@@ -1043,6 +1098,11 @@ export declare function parseRunRecords(raw: unknown): z.ZodSafeParseResult<{
|
|
|
1043
1098
|
systemPrompt?: string | undefined;
|
|
1044
1099
|
generateFollowups?: boolean | undefined;
|
|
1045
1100
|
autonomous?: boolean | undefined;
|
|
1101
|
+
notify?: boolean | undefined;
|
|
1102
|
+
webhook?: {
|
|
1103
|
+
lastDeliveredAt?: string | undefined;
|
|
1104
|
+
lastError?: string | undefined;
|
|
1105
|
+
} | undefined;
|
|
1046
1106
|
automation?: {
|
|
1047
1107
|
automationId: string;
|
|
1048
1108
|
automationRevision: number;
|
|
@@ -1085,6 +1145,8 @@ export declare function parseRunRecords(raw: unknown): z.ZodSafeParseResult<{
|
|
|
1085
1145
|
worktreeReclaimedAt?: string | undefined;
|
|
1086
1146
|
groupId?: string | undefined;
|
|
1087
1147
|
variant?: string | undefined;
|
|
1148
|
+
clientRequestId?: string | undefined;
|
|
1149
|
+
clientRequestHash?: string | undefined;
|
|
1088
1150
|
peakRssBytes?: number | undefined;
|
|
1089
1151
|
peakProcCount?: number | undefined;
|
|
1090
1152
|
archived: boolean;
|
|
@@ -1220,6 +1282,9 @@ export declare class RunStore extends EventEmitter {
|
|
|
1220
1282
|
setRepoHandle(handle: RepoHandle | null): void;
|
|
1221
1283
|
listRuns(): RunRecord[];
|
|
1222
1284
|
getRun(id: string): RunRecord | undefined;
|
|
1285
|
+
/** The run an idempotent start already created (#504), archived or not. A deleted run is gone
|
|
1286
|
+
* with its record, so a retry after deletion honestly creates a fresh one. */
|
|
1287
|
+
findRunByClientRequestId(clientRequestId: string): RunRecord | undefined;
|
|
1223
1288
|
createRun(input: {
|
|
1224
1289
|
title: string;
|
|
1225
1290
|
systemPrompt?: string;
|
|
@@ -1234,9 +1299,13 @@ export declare class RunStore extends EventEmitter {
|
|
|
1234
1299
|
agentProfile?: string;
|
|
1235
1300
|
generateFollowups?: boolean;
|
|
1236
1301
|
autonomous?: boolean;
|
|
1302
|
+
/** Task webhook opt-in (#589), set at creation so the first transition is already covered. */
|
|
1303
|
+
notify?: boolean;
|
|
1237
1304
|
worktree?: false;
|
|
1238
1305
|
groupId?: string;
|
|
1239
1306
|
variant?: string;
|
|
1307
|
+
clientRequestId?: string;
|
|
1308
|
+
clientRequestHash?: string;
|
|
1240
1309
|
steps: Array<Pick<StepState, 'id' | 'name' | 'kind'>>;
|
|
1241
1310
|
}): RunRecord;
|
|
1242
1311
|
/** Build without publishing: owned creation must commit its receipt and run together. */
|
|
@@ -1247,7 +1316,23 @@ export declare class RunStore extends EventEmitter {
|
|
|
1247
1316
|
input: AgentInput;
|
|
1248
1317
|
}): void;
|
|
1249
1318
|
/** Observable atomic input checkpoint: a failed write publishes nothing. */
|
|
1319
|
+
/** Accepted input the harness will never read returns to the queue (#505): only its
|
|
1320
|
+
* delivery and consumption receipts are cleared; order and identity are kept. */
|
|
1321
|
+
requeueUnconsumedAgentInputs(id: string, ids: readonly string[]): void;
|
|
1322
|
+
/** Model consumption observed by the current session (#505). Never un-sets deliveredAt. */
|
|
1323
|
+
commitAgentInputsConsumed(id: string, ids: readonly string[], at: string): void;
|
|
1324
|
+
/** Delivered, but the harness never confirmed reading it (#505): stop awaiting a read. */
|
|
1325
|
+
commitAgentInputsUnconfirmed(id: string, ids: readonly string[]): void;
|
|
1326
|
+
/** Crash recovery (#505): input a harness accepted but was never seen reading goes
|
|
1327
|
+
* back to the queue. Returns the requeued IDs. */
|
|
1328
|
+
requeueAwaitingReadInputs(id: string): string[];
|
|
1250
1329
|
commitAgentInputs(id: string, inputs: readonly AgentInput[], openingContinuationInputId?: string): void;
|
|
1330
|
+
/** Reserve only unread conversation inputs in one durable index replacement. */
|
|
1331
|
+
claimInboxInputs(runId: string, ids: readonly string[], claim: InboxClaim): void;
|
|
1332
|
+
/** A receipt owns every matching input or none; exact ACK retries preserve the first timestamp. */
|
|
1333
|
+
ackInboxInputs(runId: string, receiptId: string, generation: string, at: string): 'acknowledged' | 'already-acknowledged';
|
|
1334
|
+
releaseInboxInputs(runId: string, receiptId: string, generation: string): 'released';
|
|
1335
|
+
clearExpiredInboxClaims(runId: string, now: string): void;
|
|
1251
1336
|
/** CI intent and its wake entry share one atomic index replacement. */
|
|
1252
1337
|
commitCiWait(id: string, wait: CiWait, input?: AgentInput): void;
|
|
1253
1338
|
/** Retire the wait and precisely its pending wake, optionally accepting human input. */
|
|
@@ -1458,6 +1543,15 @@ export declare class RunStore extends EventEmitter {
|
|
|
1458
1543
|
} | undefined;
|
|
1459
1544
|
private writeWorkerExecution;
|
|
1460
1545
|
commitWorkerExecutionStart(id: string): string;
|
|
1546
|
+
/** Private process record (#469): which processes a generation spawned, never part of run JSON or SSE. */
|
|
1547
|
+
private processesPath;
|
|
1548
|
+
/** Tri-state: only ENOENT is `absent` (legacy, scan-only). A present record that is unreadable,
|
|
1549
|
+
* wrongly permissioned, malformed or of another generation is `unknown`: never finalized or reaped. */
|
|
1550
|
+
readWorkerProcesses(id: string, generation: string): WorkerProcessRecord | 'absent' | 'unknown';
|
|
1551
|
+
private writeWorkerProcesses;
|
|
1552
|
+
/** Bound to the current generation. Past the cap the record never drops an entry: the
|
|
1553
|
+
* working-directory scan is the remaining evidence. */
|
|
1554
|
+
appendWorkerProcess(id: string, generation: string, pid: number): boolean;
|
|
1461
1555
|
commitWorkerExecutionComplete(id: string, generation: string): boolean;
|
|
1462
1556
|
/** Cancellation must hit disk before queued no-start evidence authorizes cleanup. */
|
|
1463
1557
|
commitWorkerCancellation(id: string): void;
|
package/dist/runs/store.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { removeArtifacts } from '../artifacts/lifecycle.js';
|
|
2
3
|
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
3
5
|
import { appendFileSync, closeSync, constants, fstatSync, fsyncSync, lstatSync, openSync, readSync, realpathSync, readdirSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
4
6
|
import { join, resolve } from 'node:path';
|
|
5
7
|
import { z } from 'zod';
|
|
6
|
-
import { ciWaitSchema, agentInputSchema, delegationStateSchema, workerCreationReceiptSchema, workerCollectedResultSchema, workerResultFileSchema, continuationMessageSchema, runRecordSchema as contractRunRecordSchema, } from '../contract/index.js';
|
|
8
|
+
import { ciWaitSchema, agentInputSchema, inboxClaimSchema, delegationStateSchema, workerCreationReceiptSchema, workerCollectedResultSchema, workerResultFileSchema, continuationMessageSchema, runRecordSchema as contractRunRecordSchema, } from '../contract/index.js';
|
|
7
9
|
import { storedDelegationStateSchema } from './delegation-state.js';
|
|
8
10
|
import { refreshHumanAskSummary } from './human-ask-summary.js';
|
|
9
11
|
import { workerExecutionIdentitySchema } from '../delegation/execution-identity.js';
|
|
10
12
|
import { reconcileWorkerWait } from '../delegation/wait.js';
|
|
13
|
+
import { processStartToken } from '../delegation/process-liveness.js';
|
|
11
14
|
import { collectSecretValues, redactDeep, redactSecrets } from '../core/secret-redaction.js';
|
|
12
15
|
// Pure, dependency-free reference helpers — the same sanity bound the marker parser applies.
|
|
13
16
|
import { MAX_REF } from './task-refs.js';
|
|
@@ -167,6 +170,10 @@ export const runRecordSchema = z.object({
|
|
|
167
170
|
* group-pick winner-park read it). Additive-safe: absent = falsy = not
|
|
168
171
|
* autonomous. Set at creation from `WorkflowInput.autonomous`. */
|
|
169
172
|
autonomous: z.boolean().optional(),
|
|
173
|
+
/** Task webhook opt-in (#589). Absent = off; `POST /runs/:id/notify` flips it at any time. */
|
|
174
|
+
notify: z.boolean().optional().catch(undefined),
|
|
175
|
+
/** The last task-webhook delivery's outcome (#589), written by `runs/webhook.ts`. */
|
|
176
|
+
webhook: contractRunRecordSchema.shape.webhook.catch(undefined),
|
|
170
177
|
/** Optional provenance for tasks launched by a project GitHub automation. */
|
|
171
178
|
automation: z
|
|
172
179
|
.object({
|
|
@@ -262,6 +269,10 @@ export const runRecordSchema = z.object({
|
|
|
262
269
|
groupId: z.string().optional(),
|
|
263
270
|
/** Variant letter within the group — 'A' | 'B' | 'C' (kept as a string). */
|
|
264
271
|
variant: z.string().optional(),
|
|
272
|
+
/** Idempotent start (#504): the caller's request id and the hash of the start payload it
|
|
273
|
+
* named (`src/runs/client-request.ts`). Absent on every run started without one. */
|
|
274
|
+
clientRequestId: z.string().optional(),
|
|
275
|
+
clientRequestHash: z.string().optional(),
|
|
265
276
|
/** Peak resident memory (bytes) / process count observed across the run's
|
|
266
277
|
* agent process trees (#348) — written when a session's telemetry ends.
|
|
267
278
|
* Optional: old runs.json files and `ps`-less platforms have neither. */
|
|
@@ -695,6 +706,11 @@ export function rescopeRun(run, handle) {
|
|
|
695
706
|
}
|
|
696
707
|
return changed;
|
|
697
708
|
}
|
|
709
|
+
const WORKER_PROCESS_CAP = 32;
|
|
710
|
+
const recordedProcessSchema = z.object({ pid: z.number().int().positive(), startToken: z.string().min(1).max(128).optional() }).strict();
|
|
711
|
+
const workerProcessRecordSchema = z.object({ generation: z.string().uuid(), controller: recordedProcessSchema,
|
|
712
|
+
processes: z.array(recordedProcessSchema).max(WORKER_PROCESS_CAP) }).strict();
|
|
713
|
+
const startToken = (pid) => { const token = processStartToken(pid); return token === undefined ? {} : { startToken: token }; };
|
|
698
714
|
/**
|
|
699
715
|
* File-backed run store: `runs.json` index (atomic tmp+rename writes, the
|
|
700
716
|
* pattern from @cezar/core's IssueStore) plus one append-only NDJSON event
|
|
@@ -776,6 +792,14 @@ export class RunStore extends EventEmitter {
|
|
|
776
792
|
getRun(id) {
|
|
777
793
|
return this.runs.get(id);
|
|
778
794
|
}
|
|
795
|
+
/** The run an idempotent start already created (#504), archived or not. A deleted run is gone
|
|
796
|
+
* with its record, so a retry after deletion honestly creates a fresh one. */
|
|
797
|
+
findRunByClientRequestId(clientRequestId) {
|
|
798
|
+
for (const run of this.runs.values())
|
|
799
|
+
if (run.clientRequestId === clientRequestId)
|
|
800
|
+
return run;
|
|
801
|
+
return undefined;
|
|
802
|
+
}
|
|
779
803
|
createRun(input) {
|
|
780
804
|
const run = this.buildRun(input, randomUUID());
|
|
781
805
|
this.runs.set(run.id, run);
|
|
@@ -804,9 +828,11 @@ export class RunStore extends EventEmitter {
|
|
|
804
828
|
agentProfile: input.agentProfile,
|
|
805
829
|
generateFollowups: input.generateFollowups,
|
|
806
830
|
autonomous: input.autonomous,
|
|
831
|
+
...(input.notify ? { notify: true } : {}),
|
|
807
832
|
worktree: input.worktree,
|
|
808
833
|
groupId: input.groupId,
|
|
809
834
|
variant: input.variant,
|
|
835
|
+
...(input.clientRequestId === undefined ? {} : { clientRequestId: input.clientRequestId, clientRequestHash: input.clientRequestHash }),
|
|
810
836
|
status: 'queued',
|
|
811
837
|
createdAt: new Date().toISOString(),
|
|
812
838
|
tokensUsed: 0,
|
|
@@ -846,11 +872,65 @@ export class RunStore extends EventEmitter {
|
|
|
846
872
|
this.commitIndex(proposed, changed);
|
|
847
873
|
}
|
|
848
874
|
/** Observable atomic input checkpoint: a failed write publishes nothing. */
|
|
875
|
+
/** Accepted input the harness will never read returns to the queue (#505): only its
|
|
876
|
+
* delivery and consumption receipts are cleared; order and identity are kept. */
|
|
877
|
+
requeueUnconsumedAgentInputs(id, ids) {
|
|
878
|
+
const run = this.runs.get(id);
|
|
879
|
+
if (!run?.agentInputs || !ids.length)
|
|
880
|
+
return;
|
|
881
|
+
this.commitAgentInputs(id, run.agentInputs.map(input => {
|
|
882
|
+
if (!ids.includes(input.id))
|
|
883
|
+
return input;
|
|
884
|
+
const { deliveredAt: _delivered, consumedAt: _consumed, awaitingRead: _awaiting, ...queued } = input;
|
|
885
|
+
return queued;
|
|
886
|
+
}));
|
|
887
|
+
}
|
|
888
|
+
/** Model consumption observed by the current session (#505). Never un-sets deliveredAt. */
|
|
889
|
+
commitAgentInputsConsumed(id, ids, at) {
|
|
890
|
+
const run = this.runs.get(id);
|
|
891
|
+
if (!run?.agentInputs || !ids.length)
|
|
892
|
+
return;
|
|
893
|
+
this.commitAgentInputs(id, run.agentInputs.map(input => {
|
|
894
|
+
if (!ids.includes(input.id) || !input.deliveredAt || input.consumedAt)
|
|
895
|
+
return input;
|
|
896
|
+
const { awaitingRead: _awaiting, ...read } = input;
|
|
897
|
+
return { ...read, consumedAt: at };
|
|
898
|
+
}));
|
|
899
|
+
}
|
|
900
|
+
/** Delivered, but the harness never confirmed reading it (#505): stop awaiting a read. */
|
|
901
|
+
commitAgentInputsUnconfirmed(id, ids) {
|
|
902
|
+
const run = this.runs.get(id);
|
|
903
|
+
if (!run?.agentInputs || !ids.length)
|
|
904
|
+
return;
|
|
905
|
+
this.commitAgentInputs(id, run.agentInputs.map(input => {
|
|
906
|
+
if (!ids.includes(input.id) || !input.awaitingRead)
|
|
907
|
+
return input;
|
|
908
|
+
const { awaitingRead: _awaiting, ...unconfirmed } = input;
|
|
909
|
+
return unconfirmed;
|
|
910
|
+
}));
|
|
911
|
+
}
|
|
912
|
+
/** Crash recovery (#505): input a harness accepted but was never seen reading goes
|
|
913
|
+
* back to the queue. Returns the requeued IDs. */
|
|
914
|
+
requeueAwaitingReadInputs(id) {
|
|
915
|
+
const ids = (this.runs.get(id)?.agentInputs ?? []).filter(input => input.awaitingRead && input.deliveredAt && !input.consumedAt).map(input => input.id);
|
|
916
|
+
this.requeueUnconsumedAgentInputs(id, ids);
|
|
917
|
+
return ids;
|
|
918
|
+
}
|
|
849
919
|
commitAgentInputs(id, inputs, openingContinuationInputId) {
|
|
850
920
|
const run = this.runs.get(id);
|
|
851
921
|
if (!run)
|
|
852
922
|
throw new Error('missing agent input target');
|
|
853
923
|
const agentInputs = inputs.map(input => agentInputSchema.parse(input));
|
|
924
|
+
const now = new Date().toISOString();
|
|
925
|
+
for (const input of run.agentInputs ?? []) {
|
|
926
|
+
const claim = input.inboxClaim;
|
|
927
|
+
if (!claim || claim.acknowledgedAt || claim.expiresAt <= now)
|
|
928
|
+
continue;
|
|
929
|
+
const matching = agentInputs.filter(next => next.id === input.id);
|
|
930
|
+
if (matching.length !== 1 || !isDeepStrictEqual(matching[0].inboxClaim, claim)) {
|
|
931
|
+
throw new Error('live inbox receipt changed');
|
|
932
|
+
}
|
|
933
|
+
}
|
|
854
934
|
if (openingContinuationInputId && (run.continuationMessage?.agentInputId !== openingContinuationInputId ||
|
|
855
935
|
!agentInputs.some(input => input.id === openingContinuationInputId && input.deliveredAt)))
|
|
856
936
|
throw new Error('opening agent input checkpoint changed');
|
|
@@ -858,6 +938,96 @@ export class RunStore extends EventEmitter {
|
|
|
858
938
|
proposed.set(id, { ...run, agentInputs, ...(openingContinuationInputId ? { continuationMessage: undefined } : {}) });
|
|
859
939
|
this.commitIndex(proposed, new Set([id]));
|
|
860
940
|
}
|
|
941
|
+
/** Reserve only unread conversation inputs in one durable index replacement. */
|
|
942
|
+
claimInboxInputs(runId, ids, claim) {
|
|
943
|
+
const run = this.runs.get(runId);
|
|
944
|
+
if (!run)
|
|
945
|
+
throw new Error('missing inbox recipient');
|
|
946
|
+
const selected = z.array(z.uuid()).min(1).max(32).refine(values => new Set(values).size === values.length).parse(ids);
|
|
947
|
+
const receipt = inboxClaimSchema.parse({ ...claim, memberIds: selected });
|
|
948
|
+
if (receipt.acknowledgedAt || receipt.expiresAt <= new Date().toISOString())
|
|
949
|
+
throw new Error('inbox claim is not live');
|
|
950
|
+
const inputs = run.agentInputs ?? [];
|
|
951
|
+
if (inputs.some(input => input.inboxClaim?.receiptId === receipt.receiptId))
|
|
952
|
+
throw new Error('inbox receipt already exists');
|
|
953
|
+
for (const id of selected) {
|
|
954
|
+
const matching = inputs.filter(input => input.id === id);
|
|
955
|
+
if (matching.length !== 1 || matching[0]?.source !== 'agent' || !matching[0].conversation ||
|
|
956
|
+
matching[0].deliveredAt || (matching[0].inboxClaim && matching[0].inboxClaim.expiresAt > new Date().toISOString())) {
|
|
957
|
+
throw new Error('inbox input is not available');
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
const selectedIds = new Set(selected);
|
|
961
|
+
const proposed = new Map(this.runs);
|
|
962
|
+
proposed.set(runId, { ...run, agentInputs: inputs.map(input => selectedIds.has(input.id)
|
|
963
|
+
? agentInputSchema.parse({ ...input, inboxClaim: receipt }) : input) });
|
|
964
|
+
this.commitIndex(proposed, new Set([runId]));
|
|
965
|
+
}
|
|
966
|
+
/** A receipt owns every matching input or none; exact ACK retries preserve the first timestamp. */
|
|
967
|
+
ackInboxInputs(runId, receiptId, generation, at) {
|
|
968
|
+
const run = this.runs.get(runId);
|
|
969
|
+
if (!run)
|
|
970
|
+
throw new Error('missing inbox recipient');
|
|
971
|
+
inboxClaimSchema.shape.receiptId.parse(receiptId);
|
|
972
|
+
inboxClaimSchema.shape.generation.parse(generation);
|
|
973
|
+
inboxClaimSchema.shape.expiresAt.parse(at);
|
|
974
|
+
const matching = (run.agentInputs ?? []).filter(input => input.inboxClaim?.receiptId === receiptId);
|
|
975
|
+
const receipt = matching[0]?.inboxClaim;
|
|
976
|
+
const memberIds = receipt?.memberIds;
|
|
977
|
+
if (!memberIds || matching.length !== memberIds.length ||
|
|
978
|
+
!memberIds.every(id => matching.some(input => input.id === id)) ||
|
|
979
|
+
matching.some(input => !isDeepStrictEqual(input.inboxClaim, receipt)) ||
|
|
980
|
+
matching.some(input => input.inboxClaim?.generation !== generation ||
|
|
981
|
+
input.source !== 'agent' || !input.conversation))
|
|
982
|
+
throw new Error('inbox receipt changed');
|
|
983
|
+
if (matching.every(input => input.inboxClaim?.acknowledgedAt && input.deliveredAt === input.inboxClaim.acknowledgedAt)) {
|
|
984
|
+
return 'already-acknowledged';
|
|
985
|
+
}
|
|
986
|
+
if (matching.some(input => input.deliveredAt || input.inboxClaim?.acknowledgedAt || input.inboxClaim.expiresAt <= at)) {
|
|
987
|
+
throw new Error('inbox receipt expired or displaced');
|
|
988
|
+
}
|
|
989
|
+
const proposed = new Map(this.runs);
|
|
990
|
+
proposed.set(runId, { ...run, agentInputs: run.agentInputs.map(input => input.inboxClaim?.receiptId === receiptId
|
|
991
|
+
? agentInputSchema.parse({ ...input, deliveredAt: at, inboxClaim: { ...input.inboxClaim, acknowledgedAt: at } }) : input) });
|
|
992
|
+
this.commitIndex(proposed, new Set([runId]));
|
|
993
|
+
return 'acknowledged';
|
|
994
|
+
}
|
|
995
|
+
releaseInboxInputs(runId, receiptId, generation) {
|
|
996
|
+
const run = this.runs.get(runId);
|
|
997
|
+
if (!run)
|
|
998
|
+
throw new Error('missing inbox recipient');
|
|
999
|
+
inboxClaimSchema.shape.receiptId.parse(receiptId);
|
|
1000
|
+
inboxClaimSchema.shape.generation.parse(generation);
|
|
1001
|
+
const matching = (run.agentInputs ?? []).filter(input => input.inboxClaim?.receiptId === receiptId);
|
|
1002
|
+
if (!matching.length || matching.some(input => input.inboxClaim?.generation !== generation ||
|
|
1003
|
+
input.inboxClaim?.acknowledgedAt || input.deliveredAt))
|
|
1004
|
+
throw new Error('inbox receipt changed');
|
|
1005
|
+
const proposed = new Map(this.runs);
|
|
1006
|
+
proposed.set(runId, { ...run, agentInputs: run.agentInputs.map(input => {
|
|
1007
|
+
if (input.inboxClaim?.receiptId !== receiptId)
|
|
1008
|
+
return input;
|
|
1009
|
+
const { inboxClaim: _claim, ...unclaimed } = input;
|
|
1010
|
+
return agentInputSchema.parse(unclaimed);
|
|
1011
|
+
}) });
|
|
1012
|
+
this.commitIndex(proposed, new Set([runId]));
|
|
1013
|
+
return 'released';
|
|
1014
|
+
}
|
|
1015
|
+
clearExpiredInboxClaims(runId, now) {
|
|
1016
|
+
const run = this.runs.get(runId);
|
|
1017
|
+
if (!run)
|
|
1018
|
+
throw new Error('missing inbox recipient');
|
|
1019
|
+
inboxClaimSchema.shape.expiresAt.parse(now);
|
|
1020
|
+
if (!run.agentInputs?.some(input => input.inboxClaim && !input.inboxClaim.acknowledgedAt && input.inboxClaim.expiresAt <= now))
|
|
1021
|
+
return;
|
|
1022
|
+
const proposed = new Map(this.runs);
|
|
1023
|
+
proposed.set(runId, { ...run, agentInputs: run.agentInputs.map(input => {
|
|
1024
|
+
if (!input.inboxClaim || input.inboxClaim.acknowledgedAt || input.inboxClaim.expiresAt > now)
|
|
1025
|
+
return input;
|
|
1026
|
+
const { inboxClaim: _claim, ...unclaimed } = input;
|
|
1027
|
+
return agentInputSchema.parse(unclaimed);
|
|
1028
|
+
}) });
|
|
1029
|
+
this.commitIndex(proposed, new Set([runId]));
|
|
1030
|
+
}
|
|
861
1031
|
/** CI intent and its wake entry share one atomic index replacement. */
|
|
862
1032
|
commitCiWait(id, wait, input) {
|
|
863
1033
|
const run = this.runs.get(id);
|
|
@@ -1337,7 +1507,7 @@ export class RunStore extends EventEmitter {
|
|
|
1337
1507
|
? startedAgentSteps.reduce((sum, candidate) => sum + (candidate.outputTokens ?? 0), 0)
|
|
1338
1508
|
: undefined;
|
|
1339
1509
|
const cost = run.steps.reduce((sum, s) => sum + (s.costUsd ?? 0), 0);
|
|
1340
|
-
run.costUsd =
|
|
1510
|
+
run.costUsd = run.steps.some((step) => step.costUsd !== undefined) ? cost : undefined;
|
|
1341
1511
|
this.touch(run);
|
|
1342
1512
|
}
|
|
1343
1513
|
setArchived(id, archived) {
|
|
@@ -1808,9 +1978,78 @@ export class RunStore extends EventEmitter {
|
|
|
1808
1978
|
throw new Error('Worker execution checkpoint does not prove safe admission');
|
|
1809
1979
|
}
|
|
1810
1980
|
const generation = randomUUID();
|
|
1981
|
+
// #469: the controller is durable before `starting`, so a crash leaves a provable generation.
|
|
1982
|
+
this.writeWorkerProcesses(id, { generation, controller: { pid: process.pid, ...startToken(process.pid) }, processes: [] });
|
|
1811
1983
|
this.writeWorkerExecution(id, { generation, phase: 'starting' });
|
|
1812
1984
|
return generation;
|
|
1813
1985
|
}
|
|
1986
|
+
/** Private process record (#469): which processes a generation spawned, never part of run JSON or SSE. */
|
|
1987
|
+
processesPath(id) {
|
|
1988
|
+
return this.executionPath(id).replace(/\.execution\.json$/, '.processes.json');
|
|
1989
|
+
}
|
|
1990
|
+
/** Tri-state: only ENOENT is `absent` (legacy, scan-only). A present record that is unreadable,
|
|
1991
|
+
* wrongly permissioned, malformed or of another generation is `unknown`: never finalized or reaped. */
|
|
1992
|
+
readWorkerProcesses(id, generation) {
|
|
1993
|
+
try {
|
|
1994
|
+
const fd = openSync(this.processesPath(id), constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
1995
|
+
try {
|
|
1996
|
+
const info = fstatSync(fd);
|
|
1997
|
+
if (!info.isFile() || info.size > 8192 || (info.mode & 0o077))
|
|
1998
|
+
return 'unknown';
|
|
1999
|
+
const buffer = Buffer.alloc(8193);
|
|
2000
|
+
const count = readSync(fd, buffer, 0, buffer.length, 0);
|
|
2001
|
+
const record = workerProcessRecordSchema.parse(JSON.parse(buffer.subarray(0, count).toString('utf8')));
|
|
2002
|
+
return record.generation === generation ? record : 'unknown';
|
|
2003
|
+
}
|
|
2004
|
+
finally {
|
|
2005
|
+
closeSync(fd);
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
catch (error) {
|
|
2009
|
+
return error.code === 'ENOENT' ? 'absent' : 'unknown';
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
writeWorkerProcesses(id, record) {
|
|
2013
|
+
const path = this.processesPath(id);
|
|
2014
|
+
try {
|
|
2015
|
+
const existing = lstatSync(path);
|
|
2016
|
+
if (!existing.isFile() || existing.isSymbolicLink())
|
|
2017
|
+
throw new Error('Unsafe process record');
|
|
2018
|
+
}
|
|
2019
|
+
catch (error) {
|
|
2020
|
+
if (error.code !== 'ENOENT')
|
|
2021
|
+
throw error;
|
|
2022
|
+
}
|
|
2023
|
+
const temporary = `${path}.${randomUUID()}.tmp`;
|
|
2024
|
+
const fd = openSync(temporary, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
|
|
2025
|
+
try {
|
|
2026
|
+
writeFileSync(fd, JSON.stringify(workerProcessRecordSchema.parse(record)));
|
|
2027
|
+
fsyncSync(fd);
|
|
2028
|
+
}
|
|
2029
|
+
finally {
|
|
2030
|
+
closeSync(fd);
|
|
2031
|
+
}
|
|
2032
|
+
try {
|
|
2033
|
+
renameSync(temporary, path);
|
|
2034
|
+
}
|
|
2035
|
+
finally {
|
|
2036
|
+
rmSync(temporary, { force: true });
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
/** Bound to the current generation. Past the cap the record never drops an entry: the
|
|
2040
|
+
* working-directory scan is the remaining evidence. */
|
|
2041
|
+
appendWorkerProcess(id, generation, pid) {
|
|
2042
|
+
const record = this.readWorkerProcesses(id, generation);
|
|
2043
|
+
if (typeof record === 'string' || this.readWorkerExecution(id)?.generation !== generation)
|
|
2044
|
+
return false;
|
|
2045
|
+
const entry = { pid, ...startToken(pid) };
|
|
2046
|
+
if (record.processes.some(known => known.pid === entry.pid && known.startToken === entry.startToken))
|
|
2047
|
+
return true;
|
|
2048
|
+
if (record.processes.length >= WORKER_PROCESS_CAP)
|
|
2049
|
+
return false;
|
|
2050
|
+
this.writeWorkerProcesses(id, { ...record, processes: [...record.processes, entry] });
|
|
2051
|
+
return true;
|
|
2052
|
+
}
|
|
1814
2053
|
commitWorkerExecutionComplete(id, generation) {
|
|
1815
2054
|
const proof = this.readWorkerExecution(id);
|
|
1816
2055
|
if (!proof || proof.generation !== generation)
|
|
@@ -1933,6 +2172,7 @@ export class RunStore extends EventEmitter {
|
|
|
1933
2172
|
this.removeRunHistoryBytes(id);
|
|
1934
2173
|
// Private process/account evidence is now replaced by the exact parent receipt.
|
|
1935
2174
|
rmSync(this.identityPath(id), { force: true });
|
|
2175
|
+
rmSync(this.processesPath(id), { force: true });
|
|
1936
2176
|
rmSync(this.executionPath(id), { force: true });
|
|
1937
2177
|
const retained = this.readWorkerResult(parent.id, id);
|
|
1938
2178
|
this.commitWorkerResult(parent.id, { ...retained, observedAt: new Date().toISOString(),
|
|
@@ -1974,6 +2214,7 @@ export class RunStore extends EventEmitter {
|
|
|
1974
2214
|
rmSync(this.eventsPath(id), { force: true });
|
|
1975
2215
|
rmSync(this.handoffPath(id), { force: true });
|
|
1976
2216
|
rmSync(this.imagesDir(id), { recursive: true, force: true });
|
|
2217
|
+
removeArtifacts(this.dataDir, id);
|
|
1977
2218
|
}
|
|
1978
2219
|
deleteRun(id) {
|
|
1979
2220
|
if (!this.canDeleteRun(id))
|
|
@@ -1987,6 +2228,7 @@ export class RunStore extends EventEmitter {
|
|
|
1987
2228
|
rmSync(this.eventsPath(id), { force: true });
|
|
1988
2229
|
rmSync(this.handoffPath(id), { force: true });
|
|
1989
2230
|
rmSync(this.imagesDir(id), { recursive: true, force: true });
|
|
2231
|
+
removeArtifacts(this.dataDir, id);
|
|
1990
2232
|
}
|
|
1991
2233
|
catch { /* Ordinary run deletion preserves its existing best-effort behavior. */ }
|
|
1992
2234
|
this.seqs.delete(id);
|
|
@@ -2054,6 +2296,7 @@ export class RunStore extends EventEmitter {
|
|
|
2054
2296
|
rmSync(this.eventsPath(stale.id), { force: true });
|
|
2055
2297
|
rmSync(this.handoffPath(stale.id), { force: true });
|
|
2056
2298
|
rmSync(this.imagesDir(stale.id), { recursive: true, force: true });
|
|
2299
|
+
removeArtifacts(this.dataDir, stale.id);
|
|
2057
2300
|
}
|
|
2058
2301
|
catch {
|
|
2059
2302
|
// best effort
|