@united-workforce/cli 0.6.1 → 0.8.1
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 +120 -5
- package/dist/.build-fingerprint +1 -1
- package/dist/__tests__/agent-resolution-llm-free.test.js +9 -2
- package/dist/__tests__/agent-resolution-llm-free.test.js.map +1 -1
- package/dist/__tests__/broker-prompt.test.d.ts +10 -0
- package/dist/__tests__/broker-prompt.test.d.ts.map +1 -0
- package/dist/__tests__/broker-prompt.test.js +129 -0
- package/dist/__tests__/broker-prompt.test.js.map +1 -0
- package/dist/__tests__/broker-step-active-turns.test.d.ts +20 -0
- package/dist/__tests__/broker-step-active-turns.test.d.ts.map +1 -0
- package/dist/__tests__/broker-step-active-turns.test.js +428 -0
- package/dist/__tests__/broker-step-active-turns.test.js.map +1 -0
- package/dist/__tests__/broker-step-turn-chain-phase2.test.d.ts +13 -0
- package/dist/__tests__/broker-step-turn-chain-phase2.test.d.ts.map +1 -0
- package/dist/__tests__/broker-step-turn-chain-phase2.test.js +429 -0
- package/dist/__tests__/broker-step-turn-chain-phase2.test.js.map +1 -0
- package/dist/__tests__/config.test.js +33 -37
- package/dist/__tests__/config.test.js.map +1 -1
- package/dist/__tests__/e2e-broker-step-suspend.test.d.ts +18 -0
- package/dist/__tests__/e2e-broker-step-suspend.test.d.ts.map +1 -0
- package/dist/__tests__/e2e-broker-step-suspend.test.js +313 -0
- package/dist/__tests__/e2e-broker-step-suspend.test.js.map +1 -0
- package/dist/__tests__/e2e-broker-step.test.d.ts +13 -0
- package/dist/__tests__/e2e-broker-step.test.d.ts.map +1 -0
- package/dist/__tests__/e2e-broker-step.test.js +278 -0
- package/dist/__tests__/e2e-broker-step.test.js.map +1 -0
- package/dist/__tests__/e2e-mock-agent.test.js +1 -1
- package/dist/__tests__/e2e-mock-agent.test.js.map +1 -1
- package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.d.ts +28 -0
- package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.d.ts.map +1 -0
- package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.js +322 -0
- package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.js.map +1 -0
- package/dist/__tests__/log-tag-validity.test.d.ts +2 -0
- package/dist/__tests__/log-tag-validity.test.d.ts.map +1 -0
- package/dist/__tests__/log-tag-validity.test.js +110 -0
- package/dist/__tests__/log-tag-validity.test.js.map +1 -0
- package/dist/__tests__/setup-agent-discovery.test.js +35 -23
- package/dist/__tests__/setup-agent-discovery.test.js.map +1 -1
- package/dist/__tests__/setup-no-llm.test.js +5 -2
- package/dist/__tests__/setup-no-llm.test.js.map +1 -1
- package/dist/__tests__/step-ask.test.js +9 -6
- package/dist/__tests__/step-ask.test.js.map +1 -1
- package/dist/__tests__/step-show-json.test.js +5 -5
- package/dist/__tests__/step-show-json.test.js.map +1 -1
- package/dist/__tests__/step-show-text.test.d.ts +2 -0
- package/dist/__tests__/step-show-text.test.d.ts.map +1 -0
- package/dist/__tests__/step-show-text.test.js +192 -0
- package/dist/__tests__/step-show-text.test.js.map +1 -0
- package/dist/__tests__/step-turns-cli-subprocess.test.d.ts +21 -0
- package/dist/__tests__/step-turns-cli-subprocess.test.d.ts.map +1 -0
- package/dist/__tests__/step-turns-cli-subprocess.test.js +356 -0
- package/dist/__tests__/step-turns-cli-subprocess.test.js.map +1 -0
- package/dist/__tests__/step-turns-panorama-phase3.test.d.ts +21 -0
- package/dist/__tests__/step-turns-panorama-phase3.test.d.ts.map +1 -0
- package/dist/__tests__/step-turns-panorama-phase3.test.js +476 -0
- package/dist/__tests__/step-turns-panorama-phase3.test.js.map +1 -0
- package/dist/__tests__/step-turns.test.d.ts +24 -0
- package/dist/__tests__/step-turns.test.d.ts.map +1 -0
- package/dist/__tests__/step-turns.test.js +646 -0
- package/dist/__tests__/step-turns.test.js.map +1 -0
- package/dist/__tests__/store-turn-chain.test.d.ts +2 -0
- package/dist/__tests__/store-turn-chain.test.d.ts.map +1 -0
- package/dist/__tests__/store-turn-chain.test.js +341 -0
- package/dist/__tests__/store-turn-chain.test.js.map +1 -0
- package/dist/__tests__/thread-agent-failure-suspended.test.js +3 -3
- package/dist/__tests__/thread-agent-failure-suspended.test.js.map +1 -1
- package/dist/__tests__/thread-list-limit-offset.test.d.ts +24 -0
- package/dist/__tests__/thread-list-limit-offset.test.d.ts.map +1 -0
- package/dist/__tests__/thread-list-limit-offset.test.js +254 -0
- package/dist/__tests__/thread-list-limit-offset.test.js.map +1 -0
- package/dist/__tests__/thread-list-template-ms-date.test.js +7 -2
- package/dist/__tests__/thread-list-template-ms-date.test.js.map +1 -1
- package/dist/__tests__/thread-poke.test.js +6 -6
- package/dist/__tests__/thread-poke.test.js.map +1 -1
- package/dist/__tests__/thread-resume.test.js +2 -2
- package/dist/__tests__/thread-resume.test.js.map +1 -1
- package/dist/__tests__/thread-suspend-step.test.js +1 -1
- package/dist/__tests__/thread-suspend-step.test.js.map +1 -1
- package/dist/__tests__/thread.test.js +28 -14
- package/dist/__tests__/thread.test.js.map +1 -1
- package/dist/cli.js +910 -344
- package/dist/cli.js.map +1 -1
- package/dist/commands/broker-step.d.ts +117 -0
- package/dist/commands/broker-step.d.ts.map +1 -0
- package/dist/commands/broker-step.js +654 -0
- package/dist/commands/broker-step.js.map +1 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +2 -23
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/prompt.d.ts.map +1 -1
- package/dist/commands/prompt.js +43 -51
- package/dist/commands/prompt.js.map +1 -1
- package/dist/commands/setup.d.ts +6 -4
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +24 -27
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/step.d.ts +54 -6
- package/dist/commands/step.d.ts.map +1 -1
- package/dist/commands/step.js +484 -134
- package/dist/commands/step.js.map +1 -1
- package/dist/commands/thread.d.ts +4 -0
- package/dist/commands/thread.d.ts.map +1 -1
- package/dist/commands/thread.js +77 -151
- package/dist/commands/thread.js.map +1 -1
- package/dist/output-mappers.d.ts +8 -0
- package/dist/output-mappers.d.ts.map +1 -1
- package/dist/output-mappers.js +72 -18
- package/dist/output-mappers.js.map +1 -1
- package/dist/schemas.d.ts +3 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +17 -3
- package/dist/schemas.js.map +1 -1
- package/dist/store.d.ts +147 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +254 -1
- package/dist/store.js.map +1 -1
- package/dist/text-renderers.d.ts.map +1 -1
- package/dist/text-renderers.js +27 -2
- package/dist/text-renderers.js.map +1 -1
- package/package.json +7 -5
- package/src/__tests__/agent-resolution-llm-free.test.ts +14 -2
- package/src/__tests__/broker-prompt.test.ts +142 -0
- package/src/__tests__/broker-step-active-turns.test.ts +509 -0
- package/src/__tests__/broker-step-turn-chain-phase2.test.ts +525 -0
- package/src/__tests__/config.test.ts +35 -39
- package/src/__tests__/e2e-broker-step-suspend.test.ts +351 -0
- package/src/__tests__/e2e-broker-step.test.ts +320 -0
- package/src/__tests__/e2e-mock-agent.test.ts +1 -1
- package/src/__tests__/e2e-thread-resume-timeout-suspend.test.ts +360 -0
- package/src/__tests__/log-tag-validity.test.ts +124 -0
- package/src/__tests__/setup-agent-discovery.test.ts +35 -23
- package/src/__tests__/setup-no-llm.test.ts +5 -2
- package/src/__tests__/step-ask.test.ts +9 -6
- package/src/__tests__/step-show-json.test.ts +5 -5
- package/src/__tests__/step-show-text.test.ts +236 -0
- package/src/__tests__/step-turns-cli-subprocess.test.ts +411 -0
- package/src/__tests__/step-turns-panorama-phase3.test.ts +579 -0
- package/src/__tests__/step-turns.test.ts +734 -0
- package/src/__tests__/store-turn-chain.test.ts +386 -0
- package/src/__tests__/thread-agent-failure-suspended.test.ts +3 -3
- package/src/__tests__/thread-list-limit-offset.test.ts +305 -0
- package/src/__tests__/thread-list-template-ms-date.test.ts +7 -2
- package/src/__tests__/thread-poke.test.ts +6 -6
- package/src/__tests__/thread-resume.test.ts +2 -2
- package/src/__tests__/thread-suspend-step.test.ts +1 -1
- package/src/__tests__/thread.test.ts +29 -15
- package/src/cli.ts +1056 -483
- package/src/commands/broker-step.ts +913 -0
- package/src/commands/config.ts +2 -24
- package/src/commands/prompt.ts +43 -51
- package/src/commands/setup.ts +25 -29
- package/src/commands/step.ts +645 -176
- package/src/commands/thread.ts +87 -192
- package/src/output-mappers.ts +99 -21
- package/src/schemas.ts +32 -2
- package/src/store.ts +297 -2
- package/src/text-renderers.ts +35 -2
- package/dist/__tests__/adapter-json-roundtrip.test.d.ts +0 -2
- package/dist/__tests__/adapter-json-roundtrip.test.d.ts.map +0 -1
- package/dist/__tests__/adapter-json-roundtrip.test.js +0 -160
- package/dist/__tests__/adapter-json-roundtrip.test.js.map +0 -1
- package/dist/__tests__/spawn-agent-json.test.d.ts +0 -2
- package/dist/__tests__/spawn-agent-json.test.d.ts.map +0 -1
- package/dist/__tests__/spawn-agent-json.test.js +0 -79
- package/dist/__tests__/spawn-agent-json.test.js.map +0 -1
- package/src/__tests__/adapter-json-roundtrip.test.ts +0 -193
- package/src/__tests__/spawn-agent-json.test.ts +0 -100
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 2 (#398 + #419) — realtime turn persistence in `executeBrokerStep`.
|
|
3
|
+
*
|
|
4
|
+
* Updated for Phase 2 (#419):
|
|
5
|
+
* - Turns are now written with `prev`+`owner` chain instead of accumulating in
|
|
6
|
+
* `@uwf/active-turns/<tid>/<role>` array var
|
|
7
|
+
* - Detail node no longer contains `turns` array — use `turnsOfStep()` to retrieve
|
|
8
|
+
* - Thread-keyed active vars (`@uwf/active-step/<tid>`, `@uwf/active-turn-head/<tid>`)
|
|
9
|
+
*
|
|
10
|
+
* Covers the acceptance steps:
|
|
11
|
+
* Step 1 — broker-step's `onTurn` writes each turn with `prev`+`owner` chain;
|
|
12
|
+
* the turn chain grows 1→2→3.
|
|
13
|
+
* Step 2 — on completion, detail has `turnCount===3` (no `turns` array);
|
|
14
|
+
* turns are accessible via `turnsOfStep()`.
|
|
15
|
+
* Step 3 — a crash-rerun is a fresh attempt: new step-start isolates old turns
|
|
16
|
+
* via different `owner` reference.
|
|
17
|
+
* Step 4 — cross-process visibility: thread-keyed turn head var is observable.
|
|
18
|
+
*/
|
|
19
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
20
|
+
import { tmpdir } from "node:os";
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
import { putSchema } from "@ocas/core";
|
|
23
|
+
import { createFsStore, createSqliteVarStore } from "@ocas/fs";
|
|
24
|
+
import { createProcessLogger } from "@united-workforce/util";
|
|
25
|
+
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
|
26
|
+
import { executeBrokerStep } from "../commands/broker-step.js";
|
|
27
|
+
import { ACTIVE_TURNS_VAR_PREFIX, activeTurnsVarName, appendActiveTurn, createUwfStore, getActiveTurnHead, readActiveTurns, turnsOfStep, walkTurnChain, } from "../store.js";
|
|
28
|
+
// ── SSE plumbing ─────────────────────────────────────────────────────────────
|
|
29
|
+
function sseFrame(id, event, data) {
|
|
30
|
+
return `id: ${id}\nevent: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
|
|
31
|
+
}
|
|
32
|
+
function turnFrame(id, index, content) {
|
|
33
|
+
return sseFrame(id, "turn", {
|
|
34
|
+
type: "@sumeru/turn",
|
|
35
|
+
value: { index, role: "assistant", content, timestamp: "", toolCalls: null },
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function doneFrame(id, turnCount) {
|
|
39
|
+
return sseFrame(id, "done", {
|
|
40
|
+
type: "@sumeru/summary",
|
|
41
|
+
value: { turnCount, tokens: { in: 9, out: 4 }, durationMs: 42 },
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function delay(ms) {
|
|
45
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
46
|
+
}
|
|
47
|
+
/** How long each assistant turn is held back, so readers can sample between them. */
|
|
48
|
+
const PER_TURN_MS = 40;
|
|
49
|
+
/**
|
|
50
|
+
* Build a paced SSE Response: each frame is enqueued `PER_TURN_MS` after the
|
|
51
|
+
* previous, so the broker's reader loop fires `onTurn` one turn at a time and a
|
|
52
|
+
* concurrent reader can observe the active var growing. Robust to consumer
|
|
53
|
+
* cancellation (the broker cancels its reader in a `finally`), so a late
|
|
54
|
+
* `enqueue`/`close` after cancel is swallowed rather than surfacing as an
|
|
55
|
+
* unhandled rejection.
|
|
56
|
+
*/
|
|
57
|
+
function buildPacedSseResponse(frames) {
|
|
58
|
+
const encoder = new TextEncoder();
|
|
59
|
+
let cancelled = false;
|
|
60
|
+
const stream = new ReadableStream({
|
|
61
|
+
start(controller) {
|
|
62
|
+
void (async () => {
|
|
63
|
+
try {
|
|
64
|
+
for (const frame of frames) {
|
|
65
|
+
if (cancelled)
|
|
66
|
+
return;
|
|
67
|
+
controller.enqueue(encoder.encode(frame));
|
|
68
|
+
await delay(PER_TURN_MS);
|
|
69
|
+
}
|
|
70
|
+
if (!cancelled)
|
|
71
|
+
controller.close();
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// Consumer closed/cancelled the stream first — nothing to do.
|
|
75
|
+
}
|
|
76
|
+
})();
|
|
77
|
+
},
|
|
78
|
+
cancel() {
|
|
79
|
+
cancelled = true;
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
return new Response(stream, {
|
|
83
|
+
status: 200,
|
|
84
|
+
headers: { "Content-Type": "text/event-stream; charset=utf-8" },
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function buildJsonResponse(status, body) {
|
|
88
|
+
return new Response(JSON.stringify(body), {
|
|
89
|
+
status,
|
|
90
|
+
headers: { "Content-Type": "application/json" },
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// ── Fixture: role schema + workflow ──────────────────────────────────────────
|
|
94
|
+
const ROLE_OUTPUT_SCHEMA = {
|
|
95
|
+
title: "coder-output",
|
|
96
|
+
type: "object",
|
|
97
|
+
required: ["$status"],
|
|
98
|
+
properties: {
|
|
99
|
+
$status: { type: "string", enum: ["done", "failed"] },
|
|
100
|
+
summary: { type: "string" },
|
|
101
|
+
},
|
|
102
|
+
additionalProperties: false,
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* The final assistant turn carries valid frontmatter so extraction succeeds on
|
|
106
|
+
* the primary send (no retries → exactly one onTurn per emitted turn). Its
|
|
107
|
+
* stored content is this whole block (byte-for-byte), which is what the
|
|
108
|
+
* solidified `detail.turns[last]` holds.
|
|
109
|
+
*/
|
|
110
|
+
const FINAL_TURN = `---
|
|
111
|
+
$status: done
|
|
112
|
+
summary: shipped
|
|
113
|
+
---
|
|
114
|
+
the final answer`;
|
|
115
|
+
const HOST = "http://127.0.0.1:7900";
|
|
116
|
+
const GATEWAY = "coder-gw";
|
|
117
|
+
const ALIAS = "coder-agent";
|
|
118
|
+
const SESSION_ID = "ses_active_turns";
|
|
119
|
+
const THREAD_ID = "06FCACTIVETURNSPHASE2A001";
|
|
120
|
+
const ROLE = "coder";
|
|
121
|
+
function buildConfig() {
|
|
122
|
+
return {
|
|
123
|
+
agents: { [ALIAS]: { host: HOST, gateway: GATEWAY } },
|
|
124
|
+
defaultAgent: ALIAS,
|
|
125
|
+
agentOverrides: null,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
async function buildWorkflow(uwf) {
|
|
129
|
+
const frontmatterHash = (await putSchema(uwf.store, ROLE_OUTPUT_SCHEMA));
|
|
130
|
+
const workflow = {
|
|
131
|
+
version: 1,
|
|
132
|
+
name: "active-turns-wf",
|
|
133
|
+
description: "phase2 realtime turns",
|
|
134
|
+
roles: {
|
|
135
|
+
[ROLE]: {
|
|
136
|
+
description: "writes code",
|
|
137
|
+
goal: "produce a change",
|
|
138
|
+
capabilities: [],
|
|
139
|
+
procedure: "do the work",
|
|
140
|
+
output: "frontmatter+body",
|
|
141
|
+
frontmatter: frontmatterHash,
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
graph: {
|
|
145
|
+
[ROLE]: {
|
|
146
|
+
done: { role: "$END", prompt: "", location: null },
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
const startHash = (await uwf.store.cas.put(uwf.schemas.startNode, {
|
|
151
|
+
workflow: await uwf.store.cas.put(uwf.schemas.workflow, workflow),
|
|
152
|
+
prompt: "task",
|
|
153
|
+
cwd: "/tmp/work",
|
|
154
|
+
}));
|
|
155
|
+
return { workflow, startHash };
|
|
156
|
+
}
|
|
157
|
+
function resolveFetchUrl(input) {
|
|
158
|
+
if (typeof input === "string")
|
|
159
|
+
return input;
|
|
160
|
+
if (input instanceof URL)
|
|
161
|
+
return input.href;
|
|
162
|
+
return input.url;
|
|
163
|
+
}
|
|
164
|
+
/** Drive one broker step end-to-end with the configured fixture. */
|
|
165
|
+
function runStep(uwf, workflow, startHash, tmpDir) {
|
|
166
|
+
return executeBrokerStep({
|
|
167
|
+
storageRoot: tmpDir,
|
|
168
|
+
uwf,
|
|
169
|
+
config: buildConfig(),
|
|
170
|
+
workflow,
|
|
171
|
+
threadId: THREAD_ID,
|
|
172
|
+
role: ROLE,
|
|
173
|
+
edgePrompt: "go",
|
|
174
|
+
effectiveCwd: "/tmp/work",
|
|
175
|
+
startHash,
|
|
176
|
+
prevHash: null,
|
|
177
|
+
agentOverride: null,
|
|
178
|
+
previousAttempts: null,
|
|
179
|
+
plog: createProcessLogger({
|
|
180
|
+
storageRoot: tmpDir,
|
|
181
|
+
context: { thread: THREAD_ID, workflow: "active-turns-wf" },
|
|
182
|
+
}),
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
/** Resolve the `content` of a turn node hash, or `null`. */
|
|
186
|
+
function turnContent(store, hash) {
|
|
187
|
+
const node = store.cas.get(hash);
|
|
188
|
+
if (node === null)
|
|
189
|
+
return null;
|
|
190
|
+
const payload = node.payload;
|
|
191
|
+
return typeof payload.content === "string" ? payload.content : null;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* An *independent* reader of the shared on-disk store — a fresh CAS (its own
|
|
195
|
+
* hash-set scan) and a fresh SQLite connection — simulating "process B" reading
|
|
196
|
+
* the WAL-committed active var while "process A" runs the step.
|
|
197
|
+
*/
|
|
198
|
+
function openReader(casDir) {
|
|
199
|
+
const cas = createFsStore(casDir);
|
|
200
|
+
const { var: varStore, tag, close } = createSqliteVarStore(join(casDir, "vars"), cas);
|
|
201
|
+
return { store: { cas, var: varStore, tag }, close };
|
|
202
|
+
}
|
|
203
|
+
// ── Tests ────────────────────────────────────────────────────────────────────
|
|
204
|
+
describe("active-turns realtime persistence (#398)", () => {
|
|
205
|
+
let tmpDir;
|
|
206
|
+
let casDir;
|
|
207
|
+
let savedOcasHome;
|
|
208
|
+
let messageBodies;
|
|
209
|
+
beforeEach(async () => {
|
|
210
|
+
savedOcasHome = process.env.OCAS_HOME;
|
|
211
|
+
tmpDir = await mkdtemp(join(tmpdir(), "active-turns-"));
|
|
212
|
+
casDir = join(tmpDir, "cas");
|
|
213
|
+
process.env.OCAS_HOME = casDir;
|
|
214
|
+
messageBodies = [];
|
|
215
|
+
vi.stubGlobal("fetch", async (input, init) => {
|
|
216
|
+
const url = resolveFetchUrl(input);
|
|
217
|
+
if (url.endsWith(`/gateways/${GATEWAY}/sessions`)) {
|
|
218
|
+
return buildJsonResponse(201, {
|
|
219
|
+
type: "@sumeru/session",
|
|
220
|
+
value: { id: SESSION_ID, gateway: GATEWAY },
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
if (url.endsWith(`/sessions/${SESSION_ID}/messages`)) {
|
|
224
|
+
messageBodies.push(typeof init?.body === "string" ? init.body : "");
|
|
225
|
+
return buildPacedSseResponse([
|
|
226
|
+
turnFrame(1, 0, "t1"),
|
|
227
|
+
turnFrame(2, 1, "t2"),
|
|
228
|
+
turnFrame(3, 2, FINAL_TURN),
|
|
229
|
+
doneFrame(4, 3),
|
|
230
|
+
]);
|
|
231
|
+
}
|
|
232
|
+
return buildJsonResponse(500, { error: "unexpected url", url });
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
afterEach(async () => {
|
|
236
|
+
vi.unstubAllGlobals();
|
|
237
|
+
if (savedOcasHome === undefined)
|
|
238
|
+
delete process.env.OCAS_HOME;
|
|
239
|
+
else
|
|
240
|
+
process.env.OCAS_HOME = savedOcasHome;
|
|
241
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
242
|
+
});
|
|
243
|
+
// Step 1 — the turn chain grows 1 → 2 → 3 as onTurn fires (Phase 2: via turn chain, not role-keyed var).
|
|
244
|
+
test("turn chain grows 1 -> 2 -> 3 via prev+owner chain as turns stream", async () => {
|
|
245
|
+
const uwf = await createUwfStore(tmpDir);
|
|
246
|
+
const { workflow, startHash } = await buildWorkflow(uwf);
|
|
247
|
+
const p = runStep(uwf, workflow, startHash, tmpDir);
|
|
248
|
+
// Sample the turn chain head while the step is in flight.
|
|
249
|
+
const chainLengths = [];
|
|
250
|
+
let finished = false;
|
|
251
|
+
void p.finally(() => {
|
|
252
|
+
finished = true;
|
|
253
|
+
});
|
|
254
|
+
while (!finished) {
|
|
255
|
+
const head = getActiveTurnHead(uwf.store, THREAD_ID);
|
|
256
|
+
const len = head !== null ? walkTurnChain(uwf, head).length : 0;
|
|
257
|
+
chainLengths.push(len);
|
|
258
|
+
await delay(PER_TURN_MS / 4);
|
|
259
|
+
}
|
|
260
|
+
const result = await p;
|
|
261
|
+
// Monotonic growth: first occurrences of 1, 2, 3 appear in order.
|
|
262
|
+
const firstIndexOf = (n) => chainLengths.indexOf(n);
|
|
263
|
+
expect(firstIndexOf(1)).toBeGreaterThanOrEqual(0);
|
|
264
|
+
expect(firstIndexOf(2)).toBeGreaterThan(firstIndexOf(1));
|
|
265
|
+
expect(firstIndexOf(3)).toBeGreaterThan(firstIndexOf(2));
|
|
266
|
+
// The chain never shrinks while accumulating.
|
|
267
|
+
const beforeFinal = chainLengths.slice(0, chainLengths.indexOf(3) + 1);
|
|
268
|
+
for (let i = 1; i < beforeFinal.length; i++) {
|
|
269
|
+
expect(beforeFinal[i]).toBeGreaterThanOrEqual(beforeFinal[i - 1]);
|
|
270
|
+
}
|
|
271
|
+
// Verify turns via turn chain (Phase 2: no detail.turns array)
|
|
272
|
+
expect(result.isError).toBe(false);
|
|
273
|
+
const turnHead = getActiveTurnHead(uwf.store, THREAD_ID);
|
|
274
|
+
expect(turnHead).not.toBeNull();
|
|
275
|
+
const chain = walkTurnChain(uwf, turnHead);
|
|
276
|
+
expect(chain).toHaveLength(3);
|
|
277
|
+
const contents = chain.map((h) => turnContent(uwf.store, h));
|
|
278
|
+
expect(contents).toEqual(["t1", "t2", FINAL_TURN]);
|
|
279
|
+
for (const h of chain) {
|
|
280
|
+
const node = uwf.store.cas.get(h);
|
|
281
|
+
expect((node?.payload).role).toBe("assistant");
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
// Step 2 — completion: detail has turnCount===3 (no turns array); turns via turnsOfStep.
|
|
285
|
+
test("detail has turnCount===3 (no turns array); turns accessible via turnsOfStep", async () => {
|
|
286
|
+
const uwf = await createUwfStore(tmpDir);
|
|
287
|
+
const { workflow, startHash } = await buildWorkflow(uwf);
|
|
288
|
+
const result = await runStep(uwf, workflow, startHash, tmpDir);
|
|
289
|
+
expect(result.isError).toBe(false);
|
|
290
|
+
const detail = uwf.store.cas.get(result.detailHash)?.payload;
|
|
291
|
+
expect(detail.turnCount).toBe(3);
|
|
292
|
+
expect(detail.turns).toBeUndefined(); // Phase 2: no turns array
|
|
293
|
+
expect(detail.sessionId).toBe(SESSION_ID);
|
|
294
|
+
expect(detail.duration).toBeGreaterThanOrEqual(0);
|
|
295
|
+
// Get turns via turn chain
|
|
296
|
+
const turnHead = getActiveTurnHead(uwf.store, THREAD_ID);
|
|
297
|
+
expect(turnHead).not.toBeNull();
|
|
298
|
+
// Get the step-start owner from first turn
|
|
299
|
+
const firstTurn = uwf.store.cas.get(walkTurnChain(uwf, turnHead)[0])
|
|
300
|
+
?.payload;
|
|
301
|
+
const stepStartHash = firstTurn.owner;
|
|
302
|
+
const stepTurns = turnsOfStep(uwf, turnHead, stepStartHash);
|
|
303
|
+
expect(stepTurns).toHaveLength(3);
|
|
304
|
+
expect(stepTurns.map((h) => turnContent(uwf.store, h))).toEqual(["t1", "t2", FINAL_TURN]);
|
|
305
|
+
// Role-keyed var is cleared (backward compat)
|
|
306
|
+
const vars = uwf.varStore.list({ exactName: activeTurnsVarName(THREAD_ID, ROLE) });
|
|
307
|
+
expect(vars).toEqual([]);
|
|
308
|
+
// Backward-compat: frontmatter extraction still works
|
|
309
|
+
expect(result.frontmatter).toEqual({ $status: "done", summary: "shipped" });
|
|
310
|
+
});
|
|
311
|
+
// Step 3 — crash-rerun: new step-start isolates old turns via different owner.
|
|
312
|
+
test("crash-rerun: new step-start isolates old turns via different owner", async () => {
|
|
313
|
+
const uwf = await createUwfStore(tmpDir);
|
|
314
|
+
const { workflow, startHash } = await buildWorkflow(uwf);
|
|
315
|
+
// Seed a residual active var (two stale turns) from a "crashed" prior attempt.
|
|
316
|
+
// Phase 2: these will be ignored because the new step gets a new step-start
|
|
317
|
+
// with different owner hash.
|
|
318
|
+
const turnSchemaHash = putSchema(uwf.store, {
|
|
319
|
+
title: "broker-turn",
|
|
320
|
+
type: "object",
|
|
321
|
+
required: ["role", "content"],
|
|
322
|
+
properties: {
|
|
323
|
+
role: { type: "string", enum: ["assistant", "tool"] },
|
|
324
|
+
content: { type: "string" },
|
|
325
|
+
},
|
|
326
|
+
additionalProperties: false,
|
|
327
|
+
});
|
|
328
|
+
for (const stale of ["old1", "old2"]) {
|
|
329
|
+
const h = uwf.store.cas.put(turnSchemaHash, { role: "assistant", content: stale });
|
|
330
|
+
appendActiveTurn(uwf.store, THREAD_ID, ROLE, h);
|
|
331
|
+
}
|
|
332
|
+
expect(readActiveTurns(uwf.store, THREAD_ID, ROLE)).toHaveLength(2);
|
|
333
|
+
const result = await runStep(uwf, workflow, startHash, tmpDir);
|
|
334
|
+
expect(result.isError).toBe(false);
|
|
335
|
+
const detail = uwf.store.cas.get(result.detailHash)?.payload;
|
|
336
|
+
// Only the new attempt's 3 turns counted
|
|
337
|
+
expect(detail.turnCount).toBe(3);
|
|
338
|
+
// Get the new step's turns via turnsOfStep
|
|
339
|
+
const turnHead = getActiveTurnHead(uwf.store, THREAD_ID);
|
|
340
|
+
expect(turnHead).not.toBeNull();
|
|
341
|
+
// Get the step-start owner from the first new turn (will be the new step-start)
|
|
342
|
+
const chain = walkTurnChain(uwf, turnHead);
|
|
343
|
+
// The chain includes ALL turns (old + new), but filtered by owner gives only new ones
|
|
344
|
+
expect(chain.length).toBeGreaterThanOrEqual(3);
|
|
345
|
+
// Find the new step-start (the one that owns the turns with content "t1", "t2", etc.)
|
|
346
|
+
const newTurns = chain.filter((h) => {
|
|
347
|
+
const c = turnContent(uwf.store, h);
|
|
348
|
+
return c === "t1" || c === "t2" || c === FINAL_TURN;
|
|
349
|
+
});
|
|
350
|
+
expect(newTurns).toHaveLength(3);
|
|
351
|
+
const newStepOwner = (uwf.store.cas.get(newTurns[0])?.payload).owner;
|
|
352
|
+
const filteredTurns = turnsOfStep(uwf, turnHead, newStepOwner);
|
|
353
|
+
expect(filteredTurns).toHaveLength(3);
|
|
354
|
+
const contents = filteredTurns.map((h) => turnContent(uwf.store, h));
|
|
355
|
+
expect(contents).toEqual(["t1", "t2", FINAL_TURN]);
|
|
356
|
+
expect(contents).not.toContain("old1");
|
|
357
|
+
expect(contents).not.toContain("old2");
|
|
358
|
+
// Role-keyed active var deleted after step.
|
|
359
|
+
expect(uwf.varStore.list({ exactName: activeTurnsVarName(THREAD_ID, ROLE) })).toEqual([]);
|
|
360
|
+
});
|
|
361
|
+
// Step 4 — cross-process visibility via the thread-keyed turn head var.
|
|
362
|
+
test("an independent reader sees the growing turn chain mid-flight", async () => {
|
|
363
|
+
const uwf = await createUwfStore(tmpDir);
|
|
364
|
+
const { workflow, startHash } = await buildWorkflow(uwf);
|
|
365
|
+
const p = runStep(uwf, workflow, startHash, tmpDir);
|
|
366
|
+
// Sample turn chain from independent reader while step runs
|
|
367
|
+
const { counts, contents } = await sampleTurnChainWhileRunning(casDir, uwf, tmpDir, p);
|
|
368
|
+
// Progress was visible before completion: a non-empty, growing chain.
|
|
369
|
+
const maxObserved = Math.max(...counts);
|
|
370
|
+
expect(maxObserved).toBeGreaterThanOrEqual(2);
|
|
371
|
+
expect(counts.some((n) => n > 0 && n < 3)).toBe(true);
|
|
372
|
+
expect(contents.has("t1")).toBe(true);
|
|
373
|
+
// After completion the role-keyed var is gone
|
|
374
|
+
const after = openReader(casDir);
|
|
375
|
+
try {
|
|
376
|
+
expect(after.store.var.list({ namePrefix: `${ACTIVE_TURNS_VAR_PREFIX}${THREAD_ID}/` })).toEqual([]);
|
|
377
|
+
}
|
|
378
|
+
finally {
|
|
379
|
+
after.close();
|
|
380
|
+
}
|
|
381
|
+
// Thread-keyed turn head var still points to the chain
|
|
382
|
+
const finalHead = getActiveTurnHead(uwf.store, THREAD_ID);
|
|
383
|
+
expect(finalHead).not.toBeNull();
|
|
384
|
+
expect(walkTurnChain(uwf, finalHead)).toHaveLength(3);
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
/**
|
|
388
|
+
* Sample the turn chain from an independent reader while a step runs.
|
|
389
|
+
* Returns observed chain lengths and contents.
|
|
390
|
+
*/
|
|
391
|
+
async function sampleTurnChainWhileRunning(casDir, uwf, tmpDir, stepPromise) {
|
|
392
|
+
const counts = [];
|
|
393
|
+
const contents = new Set();
|
|
394
|
+
let finished = false;
|
|
395
|
+
void stepPromise.finally(() => {
|
|
396
|
+
finished = true;
|
|
397
|
+
});
|
|
398
|
+
while (!finished) {
|
|
399
|
+
const reader = openReader(casDir);
|
|
400
|
+
try {
|
|
401
|
+
const head = getActiveTurnHead(reader.store, THREAD_ID);
|
|
402
|
+
if (head !== null) {
|
|
403
|
+
const chain = walkTurnChain({
|
|
404
|
+
store: reader.store,
|
|
405
|
+
schemas: uwf.schemas,
|
|
406
|
+
storageRoot: tmpDir,
|
|
407
|
+
varStore: uwf.varStore,
|
|
408
|
+
}, head);
|
|
409
|
+
counts.push(chain.length);
|
|
410
|
+
for (const h of chain) {
|
|
411
|
+
const c = turnContent(reader.store, h);
|
|
412
|
+
if (c !== null)
|
|
413
|
+
contents.add(c);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
counts.push(0);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
finally {
|
|
421
|
+
reader.close();
|
|
422
|
+
}
|
|
423
|
+
await delay(PER_TURN_MS / 3);
|
|
424
|
+
}
|
|
425
|
+
await stepPromise;
|
|
426
|
+
return { counts, contents, finished };
|
|
427
|
+
}
|
|
428
|
+
//# sourceMappingURL=broker-step-active-turns.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broker-step-active-turns.test.js","sourceRoot":"","sources":["../../src/__tests__/broker-step-active-turns.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 2 (#419) — Turn chain with prev+owner fields and thread-keyed active vars.
|
|
3
|
+
*
|
|
4
|
+
* Covers the spec acceptance scenarios:
|
|
5
|
+
* 1. onTurn writes each turn with prev pointer and owner reference
|
|
6
|
+
* 2. Step-start/step-complete dual node lifecycle
|
|
7
|
+
* 3. Same role multi-round ownership (#412 regression test)
|
|
8
|
+
* 4. Thread-keyed active vars (not role-keyed)
|
|
9
|
+
* 5. Crash recovery isolation (new attempt gets new step-start)
|
|
10
|
+
* 6. Detail node has no turns array (turns self-contained via chain)
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=broker-step-turn-chain-phase2.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broker-step-turn-chain-phase2.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/broker-step-turn-chain-phase2.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|