Skip to content

Commit 57229cb

Browse files
committed
feat(workflow): persist exact replay values
1 parent 5a7a3db commit 57229cb

6 files changed

Lines changed: 28 additions & 0 deletions

File tree

src/db/migrations.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ const migrations: Migration[] = [
3737
name: "workflow-replay-provenance",
3838
up: migrateWorkflowReplayProvenance,
3939
},
40+
{
41+
version: 7,
42+
name: "workflow-exact-replay",
43+
up: migrateWorkflowExactReplay,
44+
},
4045
];
4146

4247
export function migrateDatabase(sqlite: Database.Database): void {
@@ -270,6 +275,7 @@ function migrateWorkflowJournal(sqlite: Database.Database): void {
270275
provider_session_id text,
271276
response_text text,
272277
structured_json text,
278+
return_value_json text,
273279
error text,
274280
isolation text not null default 'shared',
275281
worktree_path text,
@@ -302,6 +308,10 @@ function migrateWorkflowReplayProvenance(sqlite: Database.Database): void {
302308
`);
303309
}
304310

311+
function migrateWorkflowExactReplay(sqlite: Database.Database): void {
312+
addColumnIfMissing(sqlite, "workflow_agent_calls", "return_value_json", "text");
313+
}
314+
305315
function addColumnIfMissing(
306316
sqlite: Database.Database,
307317
table: "workspace_sessions" | "local_agent_sessions" | "workflow_agent_calls",

src/db/schema.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ export const workflowAgentCalls = sqliteTable(
169169
providerSessionId: text("provider_session_id"),
170170
responseText: text("response_text"),
171171
structuredJson: text("structured_json"),
172+
returnValueJson: text("return_value_json"),
172173
error: text("error"),
173174
errorKind: text("error_kind"),
174175
replayMatch: text("replay_match"),

src/oauth-store.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ async function testDatabaseConfiguration(stateDir: string): Promise<void> {
4747
{ version: 4, name: "local-agent-effort-rename" },
4848
{ version: 5, name: "workflow-journal" },
4949
{ version: 6, name: "workflow-replay-provenance" },
50+
{ version: 7, name: "workflow-exact-replay" },
5051
]);
5152
} finally {
5253
database.close();

src/workflow-store.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ try {
8585
callIndex: 0,
8686
responseText: "done",
8787
structuredJson: JSON.stringify({ ok: true }),
88+
returnValueJson: JSON.stringify({ ok: true, exact: true }),
8889
providerSessionId: "sess_1",
8990
dirty: true,
9091
});
@@ -95,6 +96,7 @@ try {
9596
assert.equal(call?.providerSessionId, "sess_1");
9697
assert.equal(call?.effort, "high");
9798
assert.equal(call?.prompt, "review");
99+
assert.equal(call?.returnValueJson, JSON.stringify({ ok: true, exact: true }));
98100
assert.equal(call?.replayReason, "identity_changed:prompt");
99101

100102
store.beginAgentCall({

src/workflow-store.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export interface CompleteAgentCallInput {
7070
callIndex: number;
7171
responseText?: string;
7272
structuredJson?: string;
73+
returnValueJson?: string;
7374
providerSessionId?: string;
7475
dirty?: boolean;
7576
worktreePath?: string;
@@ -153,6 +154,7 @@ interface WorkflowAgentCallRow {
153154
provider_session_id: string | null;
154155
response_text: string | null;
155156
structured_json: string | null;
157+
return_value_json: string | null;
156158
error: string | null;
157159
error_kind: string | null;
158160
replay_match: string | null;
@@ -673,6 +675,13 @@ export class WorkflowStore {
673675
if (input.structuredJson !== undefined) {
674676
assertTextSize(input.structuredJson, WORKFLOW_LIMITS.structuredJsonBytes, "structuredJson");
675677
}
678+
if (input.returnValueJson !== undefined) {
679+
assertTextSize(
680+
input.returnValueJson,
681+
WORKFLOW_LIMITS.replayValueJsonBytes,
682+
"returnValueJson",
683+
);
684+
}
676685
const now = isoNow();
677686
const status: WorkflowAgentCallStatus = input.fromCache ? "from_cache" : "completed";
678687
this.database.sqlite
@@ -682,6 +691,7 @@ export class WorkflowStore {
682691
from_cache = ?,
683692
response_text = ?,
684693
structured_json = ?,
694+
return_value_json = ?,
685695
provider_session_id = coalesce(?, provider_session_id),
686696
worktree_path = coalesce(?, worktree_path),
687697
dirty = ?,
@@ -694,6 +704,7 @@ export class WorkflowStore {
694704
input.fromCache ? "true" : "false",
695705
input.responseText ?? null,
696706
input.structuredJson ?? null,
707+
input.returnValueJson ?? null,
697708
input.providerSessionId ?? null,
698709
input.worktreePath ?? null,
699710
input.dirty === undefined ? null : input.dirty ? "true" : "false",
@@ -894,6 +905,7 @@ function rowToAgentCall(row: WorkflowAgentCallRow): WorkflowAgentCallRecord {
894905
providerSessionId: row.provider_session_id ?? undefined,
895906
responseText: row.response_text ?? undefined,
896907
structuredJson: row.structured_json ?? undefined,
908+
returnValueJson: row.return_value_json ?? undefined,
897909
error: row.error ?? undefined,
898910
errorKind: (row.error_kind as WorkflowErrorKind | null) ?? undefined,
899911
replayMatch:

src/workflow-types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export const WORKFLOW_LIMITS = {
6060
eventDataJsonBytes: 8 * 1024,
6161
responseTextBytes: 1 * 1024 * 1024,
6262
structuredJsonBytes: 256 * 1024,
63+
replayValueJsonBytes: 1 * 1024 * 1024,
6364
resultJsonBytes: 256 * 1024,
6465
argsJsonBytes: 64 * 1024,
6566
scriptSourceBytes: 512 * 1024,
@@ -149,6 +150,7 @@ export interface WorkflowAgentCallRecord {
149150
providerSessionId?: string;
150151
responseText?: string;
151152
structuredJson?: string;
153+
returnValueJson?: string;
152154
error?: string;
153155
errorKind?: WorkflowErrorKind;
154156
replayMatch?: "same_index" | "compatible_key";

0 commit comments

Comments
 (0)