zcode-acp-server 0.47.10 → 0.48.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 +1 -1
- package/dist/backend/adapter.d.ts +129 -0
- package/dist/backend/adapter.d.ts.map +1 -0
- package/dist/backend/adapter.js +71 -0
- package/dist/backend/adapter.js.map +1 -0
- package/dist/backend/client.d.ts +14 -103
- package/dist/backend/client.d.ts.map +1 -1
- package/dist/backend/client.js +63 -413
- package/dist/backend/client.js.map +1 -1
- package/dist/backend/index.d.ts +3 -1
- package/dist/backend/index.d.ts.map +1 -1
- package/dist/backend/index.js +2 -0
- package/dist/backend/index.js.map +1 -1
- package/dist/backend/jsonrpc-child.d.ts +128 -0
- package/dist/backend/jsonrpc-child.d.ts.map +1 -0
- package/dist/backend/jsonrpc-child.js +397 -0
- package/dist/backend/jsonrpc-child.js.map +1 -0
- package/dist/code-fingerprint.json +2 -2
- package/dist/config/options.d.ts.map +1 -1
- package/dist/config/options.js +14 -4
- package/dist/config/options.js.map +1 -1
- package/dist/config/workflow-gate.d.ts +97 -0
- package/dist/config/workflow-gate.d.ts.map +1 -0
- package/dist/config/workflow-gate.js +159 -0
- package/dist/config/workflow-gate.js.map +1 -0
- package/dist/handlers/background-tasks.d.ts.map +1 -1
- package/dist/handlers/background-tasks.js +56 -0
- package/dist/handlers/background-tasks.js.map +1 -1
- package/dist/handlers/dispatch.js +4 -0
- package/dist/handlers/dispatch.js.map +1 -1
- package/dist/handlers/session.d.ts +11 -0
- package/dist/handlers/session.d.ts.map +1 -1
- package/dist/handlers/session.js +80 -32
- package/dist/handlers/session.js.map +1 -1
- package/dist/handlers/slash.d.ts +7 -2
- package/dist/handlers/slash.d.ts.map +1 -1
- package/dist/handlers/slash.js +115 -4
- package/dist/handlers/slash.js.map +1 -1
- package/dist/i18n.d.ts +2 -0
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +6 -0
- package/dist/i18n.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/remote/session-close-endpoint.d.ts.map +1 -1
- package/dist/remote/session-close-endpoint.js +6 -0
- package/dist/remote/session-close-endpoint.js.map +1 -1
- package/dist/remote/settings-endpoint.d.ts.map +1 -1
- package/dist/remote/settings-endpoint.js +380 -3
- package/dist/remote/settings-endpoint.js.map +1 -1
- package/dist/server.d.ts +49 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +80 -0
- package/dist/server.js.map +1 -1
- package/dist/settings/workflow.d.ts +139 -0
- package/dist/settings/workflow.d.ts.map +1 -0
- package/dist/settings/workflow.js +443 -0
- package/dist/settings/workflow.js.map +1 -0
- package/dist/translators/tool-helpers.d.ts.map +1 -1
- package/dist/translators/tool-helpers.js +4 -0
- package/dist/translators/tool-helpers.js.map +1 -1
- package/dist/utils.d.ts +9 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +8 -0
- package/dist/utils.js.map +1 -1
- package/dist/workflow/poller.d.ts +68 -0
- package/dist/workflow/poller.d.ts.map +1 -0
- package/dist/workflow/poller.js +290 -0
- package/dist/workflow/poller.js.map +1 -0
- package/docs/ARCHITECTURE.md +8 -6
- package/docs/BACKLOG.md +20 -2
- package/package.json +1 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic-workflow run progress poller.
|
|
3
|
+
*
|
|
4
|
+
* The backend strips per-actor/per-node workflow progress from the v3 stream
|
|
5
|
+
* (session-mapper filters `dynamic_workflow_run_progress`; the authoritative
|
|
6
|
+
* projection lives behind the v4 conversation API), so an ACP client would see
|
|
7
|
+
* the CreateWorkflow card sit silent for the whole run. This module re-attaches
|
|
8
|
+
* progress by polling the v4 journal query and folding concise progress lines
|
|
9
|
+
* into the card as `tool_call_update` notifications.
|
|
10
|
+
*
|
|
11
|
+
* v4/conversation/workflowRunEvents {sessionId, runId, afterSequence, limit}
|
|
12
|
+
* → {events: [{sequence, type, payload, truncated?}], hasMore}
|
|
13
|
+
*
|
|
14
|
+
* The cursor is the journal sequence (never invalidated), so the poll is
|
|
15
|
+
* stateless and safe to re-issue. Runs are armed by the background-task
|
|
16
|
+
* listener (taskKind "workflow", taskId ≡ runId) — the SINGLE arm point,
|
|
17
|
+
* covering model-launched runs (visible CreateWorkflow card) and
|
|
18
|
+
* settings-launched ones (synthetic tool call, no live card — the fallback
|
|
19
|
+
* [background] card is the fold target). Emissions are append DELTAS (only
|
|
20
|
+
* the lines added since the previous emission) fanned out per-alias via
|
|
21
|
+
* `server.notifyByZcodeSid`, covering both turn-internal and turn-external
|
|
22
|
+
* runs.
|
|
23
|
+
*
|
|
24
|
+
* Everything here is best-effort: request() resolves `{error}` instead of
|
|
25
|
+
* throwing, and every failure path only logs — never into the event loop.
|
|
26
|
+
*/
|
|
27
|
+
import type { ZcodeAcpServer } from "../server.js";
|
|
28
|
+
/** Poll cadence (setTimeout chain, timers unref'd). Injectable for tests. */
|
|
29
|
+
export declare const WORKFLOW_POLL_INTERVAL_MS = 3000;
|
|
30
|
+
/** One v4 journal event (transport.ts:599-646). */
|
|
31
|
+
interface WorkflowRunEvent {
|
|
32
|
+
sequence: number;
|
|
33
|
+
type: string;
|
|
34
|
+
payload?: Record<string, unknown>;
|
|
35
|
+
truncated?: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Reduce one journal event to a concise progress line, or null when the event
|
|
39
|
+
* is chatty (log/report/usage updates) and must not reach the card. Payload
|
|
40
|
+
* fields are read defensively — engine payload shapes are not part of the v4
|
|
41
|
+
* wire contract we consume, and raw ids (actorSessionId) are never printed.
|
|
42
|
+
*/
|
|
43
|
+
export declare function workflowEventLine(ev: WorkflowRunEvent): string | null;
|
|
44
|
+
/**
|
|
45
|
+
* Arm the progress poller for a workflow run. Single-flight per runId: a
|
|
46
|
+
* re-arm (task status updates repeat the launch payload) is a no-op. The
|
|
47
|
+
* first poll fires after one interval.
|
|
48
|
+
*/
|
|
49
|
+
export declare function armWorkflowRunPoller(server: ZcodeAcpServer, zcodeSid: string, opts: {
|
|
50
|
+
runId: string;
|
|
51
|
+
toolCallId: string;
|
|
52
|
+
intervalMs?: number;
|
|
53
|
+
}): void;
|
|
54
|
+
/** Stop the poller for one run (background task reached a terminal status). */
|
|
55
|
+
export declare function stopWorkflowRunPoller(runId: string): void;
|
|
56
|
+
/** Stop every poller (bridge shutdown — mirrors background-task shutdown records). */
|
|
57
|
+
export declare function stopAllWorkflowRunPollers(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Stop every poller armed under one backend session (the session/close
|
|
60
|
+
* cleanup path). Best-effort, never throws — a closed session's journal
|
|
61
|
+
* answers can outlive the runtime, and polling it would only end at the hard
|
|
62
|
+
* cap with a stray timeout notice for a conversation nobody can see anymore.
|
|
63
|
+
*/
|
|
64
|
+
export declare function stopPollersForSession(zcodeSid: string): void;
|
|
65
|
+
/** Test/observability hook: is a poller currently armed for this runId? */
|
|
66
|
+
export declare function workflowPollerActive(runId: string): boolean;
|
|
67
|
+
export {};
|
|
68
|
+
//# sourceMappingURL=poller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poller.d.ts","sourceRoot":"","sources":["../../src/workflow/poller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnD,6EAA6E;AAC7E,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAiB9C,mDAAmD;AACnD,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AA+BD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAqCrE;AA6JD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/D,IAAI,CAsBN;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAKzD;AAED,sFAAsF;AACtF,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAI5D;AAED,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE3D"}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic-workflow run progress poller.
|
|
3
|
+
*
|
|
4
|
+
* The backend strips per-actor/per-node workflow progress from the v3 stream
|
|
5
|
+
* (session-mapper filters `dynamic_workflow_run_progress`; the authoritative
|
|
6
|
+
* projection lives behind the v4 conversation API), so an ACP client would see
|
|
7
|
+
* the CreateWorkflow card sit silent for the whole run. This module re-attaches
|
|
8
|
+
* progress by polling the v4 journal query and folding concise progress lines
|
|
9
|
+
* into the card as `tool_call_update` notifications.
|
|
10
|
+
*
|
|
11
|
+
* v4/conversation/workflowRunEvents {sessionId, runId, afterSequence, limit}
|
|
12
|
+
* → {events: [{sequence, type, payload, truncated?}], hasMore}
|
|
13
|
+
*
|
|
14
|
+
* The cursor is the journal sequence (never invalidated), so the poll is
|
|
15
|
+
* stateless and safe to re-issue. Runs are armed by the background-task
|
|
16
|
+
* listener (taskKind "workflow", taskId ≡ runId) — the SINGLE arm point,
|
|
17
|
+
* covering model-launched runs (visible CreateWorkflow card) and
|
|
18
|
+
* settings-launched ones (synthetic tool call, no live card — the fallback
|
|
19
|
+
* [background] card is the fold target). Emissions are append DELTAS (only
|
|
20
|
+
* the lines added since the previous emission) fanned out per-alias via
|
|
21
|
+
* `server.notifyByZcodeSid`, covering both turn-internal and turn-external
|
|
22
|
+
* runs.
|
|
23
|
+
*
|
|
24
|
+
* Everything here is best-effort: request() resolves `{error}` instead of
|
|
25
|
+
* throwing, and every failure path only logs — never into the event loop.
|
|
26
|
+
*/
|
|
27
|
+
import { log } from "../utils.js";
|
|
28
|
+
/** Poll cadence (setTimeout chain, timers unref'd). Injectable for tests. */
|
|
29
|
+
export const WORKFLOW_POLL_INTERVAL_MS = 3000;
|
|
30
|
+
/** Hard cap: no run polls longer than this, whatever the backend says. */
|
|
31
|
+
const WORKFLOW_POLL_HARD_TIMEOUT_MS = 10 * 60_000;
|
|
32
|
+
/** Consecutive poll failures tolerated before the poller gives up. */
|
|
33
|
+
const MAX_CONSECUTIVE_ERRORS = 5;
|
|
34
|
+
/** Page size per workflowRunEvents request (upstream cap 500). */
|
|
35
|
+
const EVENTS_PAGE_LIMIT = 100;
|
|
36
|
+
/** Pages drained back-to-back per tick while `hasMore` (runaway guard). */
|
|
37
|
+
const MAX_PAGES_PER_TICK = 50;
|
|
38
|
+
/** Cap on accumulated progress lines (keep first/last, drop the middle). */
|
|
39
|
+
const MAX_LINES = 200;
|
|
40
|
+
/** Active runs keyed by runId (taskId ≡ runId upstream — one key per run). */
|
|
41
|
+
const activeRuns = new Map();
|
|
42
|
+
/**
|
|
43
|
+
* Reduce one journal event to a concise progress line, or null when the event
|
|
44
|
+
* is chatty (log/report/usage updates) and must not reach the card. Payload
|
|
45
|
+
* fields are read defensively — engine payload shapes are not part of the v4
|
|
46
|
+
* wire contract we consume, and raw ids (actorSessionId) are never printed.
|
|
47
|
+
*/
|
|
48
|
+
export function workflowEventLine(ev) {
|
|
49
|
+
const p = ev.payload ?? {};
|
|
50
|
+
const str = (k) => typeof p[k] === "string" ? p[k] : undefined;
|
|
51
|
+
const num = (k) => typeof p[k] === "number" ? p[k] : undefined;
|
|
52
|
+
switch (ev.type) {
|
|
53
|
+
case "actor-created": {
|
|
54
|
+
const name = str("name") ?? str("actorName");
|
|
55
|
+
const ordinal = num("ordinal");
|
|
56
|
+
const site = str("siteId") ?? str("actorSiteId");
|
|
57
|
+
const label = name ?? site;
|
|
58
|
+
const tag = ordinal !== undefined ? `#${ordinal}` : (site ?? "");
|
|
59
|
+
return label ? `+ actor ${tag} ${label}` : `+ actor ${tag}`.trim();
|
|
60
|
+
}
|
|
61
|
+
case "phase-entered": {
|
|
62
|
+
const phase = str("phaseName") ?? str("name");
|
|
63
|
+
return phase ? `> phase ${phase}` : "> phase";
|
|
64
|
+
}
|
|
65
|
+
case "run-settled": {
|
|
66
|
+
const status = str("status") ?? "unknown";
|
|
67
|
+
return `= run settled: ${status}`;
|
|
68
|
+
}
|
|
69
|
+
default: {
|
|
70
|
+
// Node lifecycle: only the SETTLED events carry an outcome worth a line.
|
|
71
|
+
if (!ev.type.startsWith("node-"))
|
|
72
|
+
return null;
|
|
73
|
+
const outcome = str("outcome");
|
|
74
|
+
if (outcome !== "ok" && outcome !== "failed" && outcome !== "cancelled")
|
|
75
|
+
return null;
|
|
76
|
+
const ordinal = num("ordinal");
|
|
77
|
+
const site = str("siteId");
|
|
78
|
+
const label = [site, ordinal !== undefined ? `#${ordinal}` : null]
|
|
79
|
+
.filter((x) => x !== null && x !== undefined && x !== "")
|
|
80
|
+
.join("/");
|
|
81
|
+
const icon = outcome === "ok" ? "✓" : outcome === "failed" ? "✗" : "–";
|
|
82
|
+
return label ? `${icon} node ${label} ${outcome}` : `${icon} node ${outcome}`;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Append a line under the cap: keep first/last halves with an ellipsis mark.
|
|
88
|
+
* The capped `lines` buffer is trim accounting only — emission sends the
|
|
89
|
+
* `pending` delta, so a trim that drops still-unemitted lines marks the gap
|
|
90
|
+
* with a one-time `…` line in that tick's delta.
|
|
91
|
+
*/
|
|
92
|
+
function pushLine(run, line) {
|
|
93
|
+
run.lines.push(line);
|
|
94
|
+
run.pending.push(line);
|
|
95
|
+
if (run.lines.length > MAX_LINES) {
|
|
96
|
+
const half = Math.floor(MAX_LINES / 2);
|
|
97
|
+
run.lines = [...run.lines.slice(0, half), "…", ...run.lines.slice(-(half - 1))];
|
|
98
|
+
run.pending.push("…");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Emit the lines added since the previous emission (plus an optional one-off
|
|
103
|
+
* notice line) onto the CreateWorkflow card — append semantics, per-alias
|
|
104
|
+
* fan-out. A tick with nothing new emits nothing.
|
|
105
|
+
*/
|
|
106
|
+
async function emitCardUpdate(run, notice) {
|
|
107
|
+
const delta = [...run.pending, ...(notice ? [notice] : [])];
|
|
108
|
+
run.pending = [];
|
|
109
|
+
if (delta.length === 0)
|
|
110
|
+
return;
|
|
111
|
+
const update = {
|
|
112
|
+
sessionUpdate: "tool_call_update",
|
|
113
|
+
toolCallId: run.toolCallId,
|
|
114
|
+
content: [{ type: "content", content: { type: "text", text: delta.join("\n") } }],
|
|
115
|
+
_meta: { workflowRun: { runId: run.runId, sequence: run.afterSequence } },
|
|
116
|
+
};
|
|
117
|
+
await run.server.notifyByZcodeSid(run.zcodeSid, update);
|
|
118
|
+
}
|
|
119
|
+
/** Tear the run down: clear the timer and forget it. Idempotent. */
|
|
120
|
+
function teardown(run) {
|
|
121
|
+
if (run.timer)
|
|
122
|
+
clearTimeout(run.timer);
|
|
123
|
+
run.timer = null;
|
|
124
|
+
run.stopped = true;
|
|
125
|
+
if (activeRuns.get(run.runId) === run)
|
|
126
|
+
activeRuns.delete(run.runId);
|
|
127
|
+
}
|
|
128
|
+
function scheduleNext(run) {
|
|
129
|
+
if (run.stopped)
|
|
130
|
+
return;
|
|
131
|
+
const t = setTimeout(() => void pollTick(run), run.intervalMs);
|
|
132
|
+
t.unref?.();
|
|
133
|
+
run.timer = t;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* One poll tick: fetch journal pages (draining `hasMore` back-to-back), fold
|
|
137
|
+
* new lines, emit when something meaningful appeared, schedule the next tick.
|
|
138
|
+
*/
|
|
139
|
+
async function pollTick(run) {
|
|
140
|
+
run.timer = null;
|
|
141
|
+
if (run.stopped || run.polling)
|
|
142
|
+
return;
|
|
143
|
+
run.polling = true;
|
|
144
|
+
let emitted = false;
|
|
145
|
+
try {
|
|
146
|
+
if (Date.now() - run.startedAt > WORKFLOW_POLL_HARD_TIMEOUT_MS) {
|
|
147
|
+
log(`workflow poller: run ${run.runId.slice(-8)} hit the 10min hard cap — stopping`);
|
|
148
|
+
await emitCardUpdate(run, "[progress polling stopped: timeout]");
|
|
149
|
+
teardown(run);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const backend = run.server.backend;
|
|
153
|
+
if (!backend || backend.isDead) {
|
|
154
|
+
// Backend gone (respawn/shutdown): counts as an error; consecutive
|
|
155
|
+
// failures stop the poller naturally. Never ensureBackend() from here —
|
|
156
|
+
// a poller must not spawn backends as a side effect.
|
|
157
|
+
await handleError(run, { message: "backend unavailable" });
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
for (let page = 0; page < MAX_PAGES_PER_TICK; page++) {
|
|
161
|
+
const resp = await backend.request(run.server.nextId(), "v4/conversation/workflowRunEvents", {
|
|
162
|
+
sessionId: run.zcodeSid,
|
|
163
|
+
runId: run.runId,
|
|
164
|
+
afterSequence: run.afterSequence,
|
|
165
|
+
limit: EVENTS_PAGE_LIMIT,
|
|
166
|
+
}, 8000);
|
|
167
|
+
if (resp.error) {
|
|
168
|
+
await handleError(run, resp.error);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const result = resp.result;
|
|
172
|
+
const events = Array.isArray(result?.events) ? result.events : [];
|
|
173
|
+
for (const ev of events) {
|
|
174
|
+
if (typeof ev?.sequence === "number" && ev.sequence > run.afterSequence) {
|
|
175
|
+
run.afterSequence = ev.sequence;
|
|
176
|
+
}
|
|
177
|
+
const line = workflowEventLine(ev);
|
|
178
|
+
if (line) {
|
|
179
|
+
pushLine(run, line);
|
|
180
|
+
emitted = true;
|
|
181
|
+
}
|
|
182
|
+
if (ev.type === "run-settled") {
|
|
183
|
+
await emitCardUpdate(run);
|
|
184
|
+
log(`workflow poller: run ${run.runId.slice(-8)} settled — stopping`);
|
|
185
|
+
teardown(run);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (!result?.hasMore)
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
run.consecutiveErrors = 0;
|
|
193
|
+
if (emitted)
|
|
194
|
+
await emitCardUpdate(run);
|
|
195
|
+
}
|
|
196
|
+
catch (e) {
|
|
197
|
+
// request() never throws; anything here is our own bug — count it as an
|
|
198
|
+
// error tick so the consecutive-failure stop still applies.
|
|
199
|
+
await handleError(run, {
|
|
200
|
+
message: e instanceof Error ? e.message : String(e),
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
finally {
|
|
204
|
+
run.polling = false;
|
|
205
|
+
// Stop paths tore the run down (stopped=true); transient errors keep
|
|
206
|
+
// polling. Scheduling from the finally so early `return`s never strand
|
|
207
|
+
// the chain.
|
|
208
|
+
scheduleNext(run);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/** Classify an error response: -32601 stops silently, everything else counts. */
|
|
212
|
+
async function handleError(run, error) {
|
|
213
|
+
if (error.code === -32601) {
|
|
214
|
+
// Backend build without the v4 family — log once, stop without a notice
|
|
215
|
+
// (the run itself is unaffected; only the progress folding is unavailable).
|
|
216
|
+
log(`workflow poller: backend has no v4/conversation/workflowRunEvents — ` +
|
|
217
|
+
`stopping run ${run.runId.slice(-8)}`);
|
|
218
|
+
teardown(run);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
run.consecutiveErrors += 1;
|
|
222
|
+
if (run.consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
|
|
223
|
+
log(`workflow poller: ${run.consecutiveErrors} consecutive failures — ` +
|
|
224
|
+
`stopping run ${run.runId.slice(-8)}`);
|
|
225
|
+
await emitCardUpdate(run, "[progress polling stopped: repeated errors]");
|
|
226
|
+
teardown(run);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
// Transient (timeout / dead pipe / backend respawn window) — retry next tick.
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Arm the progress poller for a workflow run. Single-flight per runId: a
|
|
233
|
+
* re-arm (task status updates repeat the launch payload) is a no-op. The
|
|
234
|
+
* first poll fires after one interval.
|
|
235
|
+
*/
|
|
236
|
+
export function armWorkflowRunPoller(server, zcodeSid, opts) {
|
|
237
|
+
const { runId, toolCallId } = opts;
|
|
238
|
+
if (!runId || !toolCallId)
|
|
239
|
+
return;
|
|
240
|
+
if (activeRuns.has(runId))
|
|
241
|
+
return;
|
|
242
|
+
const run = {
|
|
243
|
+
server,
|
|
244
|
+
zcodeSid,
|
|
245
|
+
runId,
|
|
246
|
+
toolCallId,
|
|
247
|
+
afterSequence: 0,
|
|
248
|
+
lines: [],
|
|
249
|
+
pending: [],
|
|
250
|
+
startedAt: Date.now(),
|
|
251
|
+
intervalMs: opts.intervalMs ?? WORKFLOW_POLL_INTERVAL_MS,
|
|
252
|
+
consecutiveErrors: 0,
|
|
253
|
+
stopped: false,
|
|
254
|
+
timer: null,
|
|
255
|
+
polling: false,
|
|
256
|
+
};
|
|
257
|
+
activeRuns.set(runId, run);
|
|
258
|
+
log(`workflow poller: armed for run ${runId.slice(-8)} on card ${toolCallId.slice(-12)}`);
|
|
259
|
+
scheduleNext(run);
|
|
260
|
+
}
|
|
261
|
+
/** Stop the poller for one run (background task reached a terminal status). */
|
|
262
|
+
export function stopWorkflowRunPoller(runId) {
|
|
263
|
+
const run = activeRuns.get(runId);
|
|
264
|
+
if (!run)
|
|
265
|
+
return;
|
|
266
|
+
teardown(run);
|
|
267
|
+
log(`workflow poller: stopped run ${runId.slice(-8)}`);
|
|
268
|
+
}
|
|
269
|
+
/** Stop every poller (bridge shutdown — mirrors background-task shutdown records). */
|
|
270
|
+
export function stopAllWorkflowRunPollers() {
|
|
271
|
+
for (const run of [...activeRuns.values()])
|
|
272
|
+
teardown(run);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Stop every poller armed under one backend session (the session/close
|
|
276
|
+
* cleanup path). Best-effort, never throws — a closed session's journal
|
|
277
|
+
* answers can outlive the runtime, and polling it would only end at the hard
|
|
278
|
+
* cap with a stray timeout notice for a conversation nobody can see anymore.
|
|
279
|
+
*/
|
|
280
|
+
export function stopPollersForSession(zcodeSid) {
|
|
281
|
+
for (const run of [...activeRuns.values()]) {
|
|
282
|
+
if (run.zcodeSid === zcodeSid)
|
|
283
|
+
teardown(run);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/** Test/observability hook: is a poller currently armed for this runId? */
|
|
287
|
+
export function workflowPollerActive(runId) {
|
|
288
|
+
return activeRuns.has(runId);
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=poller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poller.js","sourceRoot":"","sources":["../../src/workflow/poller.ts"],"names":[],"mappings":"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"}
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -153,11 +153,13 @@ API only because the ZCode backend itself sends them for inference.
|
|
|
153
153
|
|
|
154
154
|
### `backend/` — ZCode process communication
|
|
155
155
|
|
|
156
|
-
| File
|
|
157
|
-
|
|
|
158
|
-
| `
|
|
159
|
-
| `
|
|
160
|
-
| `
|
|
156
|
+
| File | Responsibility |
|
|
157
|
+
| ------------------ | ----------------------------------------------------------------------------------------------------------- |
|
|
158
|
+
| `adapter.ts` | `BackendAdapter` seam (ADR-0023): `BackendKind`, the capability table (single gate source), wire vocabulary |
|
|
159
|
+
| `jsonrpc-child.ts` | Shared stdio JSON-RPC transport: spawn, reader-loop, request multiplexing, watchdog, dialect hooks |
|
|
160
|
+
| `client.ts` | `ZcodeBackend` — the zcode dialect over `JsonRpcChild` (bare frames, arrival responders) |
|
|
161
|
+
| `listener.ts` | EventStreamListener (subscribe/consume the event stream) and TurnMonitor (snapshot polling) |
|
|
162
|
+
| `types.ts` | ZCode JSON-RPC message type definitions |
|
|
161
163
|
|
|
162
164
|
### `translators/` — Event translation
|
|
163
165
|
|
|
@@ -476,7 +478,7 @@ when the bridge exits cleanly enough for its signal handlers to fire
|
|
|
476
478
|
crash, OOM), the handler never runs and the zcode subprocess group is
|
|
477
479
|
orphaned.
|
|
478
480
|
|
|
479
|
-
The watchdog (`backend/
|
|
481
|
+
The watchdog (`backend/jsonrpc-child.ts:startWatchdog`) closes that gap. It is a tiny
|
|
480
482
|
detached child that polls the bridge pid every 2s and, once the bridge is
|
|
481
483
|
gone, sends SIGKILL to the zcode process group, then exits. It is its own
|
|
482
484
|
process-group leader and `unref`'d, so it never holds the event loop open and
|
package/docs/BACKLOG.md
CHANGED
|
@@ -23,6 +23,19 @@ version). Full audit detail with `file:line` evidence:
|
|
|
23
23
|
`.zcode/scratch/alignment-protocol.md` (protocol surface) and
|
|
24
24
|
`.zcode/scratch/alignment-hacks.md` (Gotchas verification).
|
|
25
25
|
|
|
26
|
+
**3.14.3 audit (2026-09-24, commit `328c1a0` — no bridge impact)**: the single
|
|
27
|
+
upstream release commit is entirely the dynamic-workflow subsystem (runtime
|
|
28
|
+
concurrency adjustment, modify/restart reuse, large-run status rendering,
|
|
29
|
+
script-submit token cost) plus bot delivery (`botDeliveryTarget` on
|
|
30
|
+
`session/send` and `automation/create` — both OPTIONAL fields the bridge
|
|
31
|
+
never sends — and the bots providers: feishu/telegram/weixin/webhook).
|
|
32
|
+
app-server stays `0.16.9`; `server-operations.ts` touches only the
|
|
33
|
+
botDeliveryTarget passthrough (stop's `activeAbortController` and compact's
|
|
34
|
+
`state.updated` swallow unchanged); provider bootstrap / runtime headers /
|
|
35
|
+
setModel / goal / fork untouched. `bundled-skills.ts` is the DWF skill pack's
|
|
36
|
+
own distribution channel (explicitly not in the settings page or `$` panel)
|
|
37
|
+
— no overlap with the bridge's filesystem skill discovery.
|
|
38
|
+
|
|
26
39
|
**3.14.0 audit (2026-09-20, app-server 0.16.9 — live-probed end to end)**: the
|
|
27
40
|
dynamic-workflow family (ten model tools led by `CreateWorkflow`) is OFF by
|
|
28
41
|
default headless and enabled per PROCESS via
|
|
@@ -102,7 +115,7 @@ when a concrete ACP/editor need appears. Ranked shortlist in
|
|
|
102
115
|
| `process/childProcesses` (3.12.3) | List a session's child processes (`{pid, serverName, mcpSource, pluginName?}`, pure memory) | Not used; potentially useful for background-task diagnostics |
|
|
103
116
|
| `skills/referenceCatalog`, `plugins/referenceCatalog[WithCategory]` (categorized variant new in 0.16.9) | Session-scoped FROZEN catalogs — the authoritative per-session view vs the bridge's live disk reads | Not used; fixes the stale-catalog class of bug (backend freezes discovery at session start) |
|
|
104
117
|
| `workspace/readPresentation` (3.12.3) | The backend's own view of workspace mode + slash-command list | Not used; cross-check the bridge's disk-based slash discovery for drift |
|
|
105
|
-
| `workflows/*` family (NEW 0.16.9: `list/get/updateMeta/delete/runs/move`, `index.ts:2685-2937, 3618-3625`) | Session-less management of saved dynamic workflows (`<cwd>/.zcode/workflows/`, project+global scopes), run history with `artifacts`, cross-cwd runs query |
|
|
118
|
+
| `workflows/*` family (NEW 0.16.9: `list/get/updateMeta/delete/runs/move`, `index.ts:2685-2937, 3618-3625`) | Session-less management of saved dynamic workflows (`<cwd>/.zcode/workflows/`, project+global scopes), run history with `artifacts`, cross-cwd runs query | **WIRED (2026-09-24, ADR-0029)**: proxied under `/settings/workflows*` + the local `/workflows` slash listing; availability is the remote `/client/configs` verdict (`src/config/workflow-gate.ts`), and `v4/command startSavedWorkflow`/`resumeWorkflowRun` + the `workflowRun*` queries are wired with it (see the v4 section below) |
|
|
106
119
|
| `provider/testModelConnectivity` (3.12.3) | Probe a provider/model endpoint | Not used; model availability comes from the `session/create` response |
|
|
107
120
|
| `runtime/capabilities` (3.12.3; returns `{independentPlanState:true}`) | Trivial capability handshake | Not used; cheap preflight for a `zcode-acp doctor` command |
|
|
108
121
|
| `interaction/providerRuntimeHeadersCancelled` notification (`index.ts:336, 2396-2406`) | Backend cancels a pending runtime-headers refresh (workspace/session/requestId scoped) | Not handled; drop pending answerers immediately on turn cancel instead of waiting them out |
|
|
@@ -212,7 +225,12 @@ Topic model (`transport.ts:83-161`): subscribe with
|
|
|
212
225
|
toSeq]` deltas — the watermark/CAS vocabulary row-targeting commands require
|
|
213
226
|
(`baseRevision` + `baseLogEpoch`, `command.ts:293-317`).
|
|
214
227
|
|
|
215
|
-
The bridge already speaks `v4/command` (the dual stop)
|
|
228
|
+
The bridge already speaks `v4/command` (the dual stop), and since 2026-09-24
|
|
229
|
+
also `startSavedWorkflow` / `resumeWorkflowRun` (Settings API launch routes,
|
|
230
|
+
ADR-0029 — the ack is terminal, awaited via `request()`) plus the seven
|
|
231
|
+
`v4/conversation/workflowRun*` read queries (run progress poller + run-detail
|
|
232
|
+
routes). The launch consent is the API call itself (upstream skips the
|
|
233
|
+
permission popup for hub clicks). Its payload union
|
|
216
234
|
(`command.ts:43-244`) is a single-method stepping stone to
|
|
217
235
|
rewind/edit-turn/feedback/queue UX over ACP without implementing the v4
|
|
218
236
|
subscription mesh: `sendText (requestedDelivery startNow|queue|guide,
|
package/package.json
CHANGED