@stigmer/runner 3.0.8-dev.20260613085218 → 3.0.9-dev.20260615145121
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/dist/.build-fingerprint +1 -1
- package/dist/activities/execute-cursor/hook-script.d.ts +23 -12
- package/dist/activities/execute-cursor/hook-script.js +85 -51
- package/dist/activities/execute-cursor/hook-script.js.map +1 -1
- package/dist/activities/execute-cursor/index.js +220 -79
- package/dist/activities/execute-cursor/index.js.map +1 -1
- package/dist/activities/execute-cursor/message-translator.d.ts +51 -9
- package/dist/activities/execute-cursor/message-translator.js +146 -20
- package/dist/activities/execute-cursor/message-translator.js.map +1 -1
- package/dist/activities/execute-cursor/persist-decision.d.ts +42 -0
- package/dist/activities/execute-cursor/persist-decision.js +30 -0
- package/dist/activities/execute-cursor/persist-decision.js.map +1 -0
- package/dist/activities/execute-cursor/prompt-builder.d.ts +25 -0
- package/dist/activities/execute-cursor/prompt-builder.js +54 -0
- package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
- package/dist/activities/execute-cursor/workspace-setup.d.ts +8 -2
- package/dist/activities/execute-cursor/workspace-setup.js +62 -30
- package/dist/activities/execute-cursor/workspace-setup.js.map +1 -1
- package/dist/activities/execute-deep-agent/index.js +15 -5
- package/dist/activities/execute-deep-agent/index.js.map +1 -1
- package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +0 -1
- package/dist/activities/execute-deep-agent/status-builder-shared.js +32 -8
- package/dist/activities/execute-deep-agent/status-builder-shared.js.map +1 -1
- package/dist/activities/execute-deep-agent/status-builder.js +4 -5
- package/dist/activities/execute-deep-agent/status-builder.js.map +1 -1
- package/dist/activities/execute-deep-agent/streaming-v3.js +4 -5
- package/dist/activities/execute-deep-agent/streaming-v3.js.map +1 -1
- package/dist/activities/execute-deep-agent/streaming.d.ts +9 -1
- package/dist/activities/execute-deep-agent/streaming.js +4 -5
- package/dist/activities/execute-deep-agent/streaming.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-tracker.js +4 -5
- package/dist/activities/execute-deep-agent/subagent-tracker.js.map +1 -1
- package/dist/activities/execute-deep-agent/v3-status-builder.js +6 -5
- package/dist/activities/execute-deep-agent/v3-status-builder.js.map +1 -1
- package/dist/config.d.ts +21 -0
- package/dist/config.js +12 -0
- package/dist/config.js.map +1 -1
- package/dist/in-flight.d.ts +35 -0
- package/dist/in-flight.js +61 -0
- package/dist/in-flight.js.map +1 -0
- package/dist/runner-manager.d.ts +2 -0
- package/dist/runner-manager.js +90 -29
- package/dist/runner-manager.js.map +1 -1
- package/dist/runner.d.ts +2 -0
- package/dist/runner.js +2 -0
- package/dist/runner.js.map +1 -1
- package/dist/shared/grpc-retry.d.ts +9 -20
- package/dist/shared/grpc-retry.js +9 -52
- package/dist/shared/grpc-retry.js.map +1 -1
- package/dist/shared/stall-watchdog.d.ts +68 -0
- package/dist/shared/stall-watchdog.js +102 -0
- package/dist/shared/stall-watchdog.js.map +1 -0
- package/dist/shared/status-offload.d.ts +84 -0
- package/dist/shared/status-offload.js +292 -0
- package/dist/shared/status-offload.js.map +1 -0
- package/dist/shared/status.d.ts +34 -3
- package/dist/shared/status.js +102 -9
- package/dist/shared/status.js.map +1 -1
- package/dist/{activities/execute-deep-agent → shared}/streaming-scheduler.d.ts +4 -0
- package/dist/{activities/execute-deep-agent → shared}/streaming-scheduler.js +4 -0
- package/dist/shared/streaming-scheduler.js.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/config.test.ts +8 -0
- package/src/__tests__/in-flight.test.ts +84 -0
- package/src/activities/__tests__/classify-tool-approvals.test.ts +1 -0
- package/src/activities/__tests__/discover-mcp-server.test.ts +1 -0
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +74 -0
- package/src/activities/execute-cursor/__tests__/hook-script.test.ts +90 -15
- package/src/activities/execute-cursor/__tests__/message-translator.test.ts +124 -12
- package/src/activities/execute-cursor/__tests__/persist-decision.test.ts +99 -0
- package/src/activities/execute-cursor/__tests__/tool-result-image.test.ts +244 -0
- package/src/activities/execute-cursor/__tests__/workspace-setup.test.ts +53 -4
- package/src/activities/execute-cursor/hook-script.ts +85 -51
- package/src/activities/execute-cursor/index.ts +187 -38
- package/src/activities/execute-cursor/message-translator.ts +146 -20
- package/src/activities/execute-cursor/persist-decision.ts +54 -0
- package/src/activities/execute-cursor/prompt-builder.ts +59 -0
- package/src/activities/execute-cursor/workspace-setup.ts +76 -44
- package/src/activities/execute-deep-agent/__tests__/index.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/status-builder-shared.test.ts +66 -0
- package/src/activities/execute-deep-agent/__tests__/status-builder.test.ts +6 -3
- package/src/activities/execute-deep-agent/__tests__/streaming-v3.test.ts +70 -0
- package/src/activities/execute-deep-agent/index.ts +17 -5
- package/src/activities/execute-deep-agent/status-builder-shared.ts +27 -5
- package/src/activities/execute-deep-agent/status-builder.ts +3 -5
- package/src/activities/execute-deep-agent/streaming-v3.ts +5 -5
- package/src/activities/execute-deep-agent/streaming.ts +14 -5
- package/src/activities/execute-deep-agent/subagent-tracker.ts +4 -5
- package/src/activities/execute-deep-agent/v3-status-builder.ts +5 -5
- package/src/config.ts +27 -0
- package/src/in-flight.ts +71 -0
- package/src/runner-manager.ts +127 -33
- package/src/runner.ts +6 -0
- package/src/shared/__tests__/artifact-storage.test.ts +1 -0
- package/src/shared/__tests__/grpc-retry-extended.test.ts +6 -144
- package/src/shared/__tests__/grpc-retry.test.ts +5 -134
- package/src/shared/__tests__/stall-watchdog.test.ts +193 -0
- package/src/shared/__tests__/status-offload.test.ts +256 -0
- package/src/shared/__tests__/status.test.ts +199 -0
- package/src/shared/grpc-retry.ts +9 -72
- package/src/shared/stall-watchdog.ts +122 -0
- package/src/shared/status-offload.ts +342 -0
- package/src/shared/status.ts +142 -8
- package/src/{activities/execute-deep-agent → shared}/streaming-scheduler.ts +4 -0
- package/dist/activities/execute-deep-agent/streaming-scheduler.js.map +0 -1
- /package/src/{activities/execute-deep-agent → shared}/__tests__/streaming-scheduler.test.ts +0 -0
package/src/shared/status.ts
CHANGED
|
@@ -19,28 +19,162 @@ import {
|
|
|
19
19
|
ExecutionPhase,
|
|
20
20
|
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
21
21
|
import type { StigmerClient } from "../client/stigmer-client.js";
|
|
22
|
+
import {
|
|
23
|
+
offloadOversizedToolOutputs,
|
|
24
|
+
enforceStatusSizeLimit,
|
|
25
|
+
STATUS_PAYLOAD_HARD_LIMIT_BYTES,
|
|
26
|
+
type ToolOutputOffloadContext,
|
|
27
|
+
} from "./status-offload.js";
|
|
28
|
+
import {
|
|
29
|
+
isRetryableError,
|
|
30
|
+
isTerminalError,
|
|
31
|
+
type RetryOptions,
|
|
32
|
+
} from "./grpc-retry.js";
|
|
22
33
|
|
|
23
34
|
export function utcTimestamp(): string {
|
|
24
35
|
return new Date().toISOString().replace("+00:00", "Z");
|
|
25
36
|
}
|
|
26
37
|
|
|
38
|
+
/**
|
|
39
|
+
* A connect-rpc `resource_exhausted` (gRPC code 8) — the payload exceeded the
|
|
40
|
+
* server's receive cap. Matched by code and, defensively, by the message buf's
|
|
41
|
+
* size check emits ("exceeds maximum size").
|
|
42
|
+
*/
|
|
43
|
+
function isPayloadTooLarge(err: unknown): boolean {
|
|
44
|
+
if (typeof err === "object" && err !== null && "code" in err) {
|
|
45
|
+
if ((err as { code?: unknown }).code === 8) return true;
|
|
46
|
+
}
|
|
47
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
48
|
+
return /resource_exhausted|exceeds maximum size/i.test(msg);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Options controlling how a status payload is bounded and persisted. */
|
|
52
|
+
export interface PersistStatusOptions {
|
|
53
|
+
/**
|
|
54
|
+
* When supplied, oversized tool outputs (a screenshot's base64, a multi-MB
|
|
55
|
+
* dump) are spilled to artifact storage before persisting — the only path
|
|
56
|
+
* that populates a renderable `ToolCallOutputRef`. When omitted, the
|
|
57
|
+
* aggregate size backstop still runs, so the payload is bounded regardless.
|
|
58
|
+
*/
|
|
59
|
+
readonly offload?: ToolOutputOffloadContext;
|
|
60
|
+
/**
|
|
61
|
+
* Transient-error backoff policy. Omitted fields fall back to
|
|
62
|
+
* {@link DEFAULT_PERSIST_RETRY}; an omitted `retry` uses it entirely.
|
|
63
|
+
*/
|
|
64
|
+
readonly retry?: RetryOptions;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Default transient-retry policy: three attempts with exponential backoff.
|
|
69
|
+
* Applied to every persist so a transient drop (server restart, brief
|
|
70
|
+
* unavailability) recovers silently instead of dropping a status update.
|
|
71
|
+
*/
|
|
72
|
+
const DEFAULT_PERSIST_RETRY = {
|
|
73
|
+
baseDelayMs: 100,
|
|
74
|
+
backoffFactor: 2,
|
|
75
|
+
maxRetries: 3,
|
|
76
|
+
} as const;
|
|
77
|
+
|
|
78
|
+
function defaultDelay(ms: number): Promise<void> {
|
|
79
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
80
|
+
}
|
|
81
|
+
|
|
27
82
|
/**
|
|
28
83
|
* Persist execution status via gRPC. Returns the control signal from the
|
|
29
|
-
* backend (e.g. STOP to abort the execution).
|
|
30
|
-
*
|
|
84
|
+
* backend (e.g. STOP to abort the execution).
|
|
85
|
+
*
|
|
86
|
+
* This is the single, unforgeable chokepoint for status persistence across
|
|
87
|
+
* every harness (streaming and terminal, native and Cursor). Routing all
|
|
88
|
+
* persistence through here guarantees three invariants that must never be
|
|
89
|
+
* skipped by an individual call site:
|
|
90
|
+
*
|
|
91
|
+
* 1. Size bounding — when `offload` is supplied, oversized tool outputs are
|
|
92
|
+
* spilled to artifact storage first (the path that makes screenshots
|
|
93
|
+
* render); an aggregate backstop then runs unconditionally so callers
|
|
94
|
+
* without storage are still protected from the 4 MiB gRPC cap.
|
|
95
|
+
* 2. Transient resilience — `Unavailable`/`DeadlineExceeded` back off and
|
|
96
|
+
* retry (default three attempts); terminal errors never retry.
|
|
97
|
+
* 3. Oversize recovery — a `resource_exhausted` rejection is never silently
|
|
98
|
+
* swallowed: we hard-elide and retry once, so an oversized payload can
|
|
99
|
+
* never freeze persistence invisibly (the bug that stalled the UI).
|
|
31
100
|
*/
|
|
32
101
|
export async function persistStatus(
|
|
33
102
|
client: StigmerClient,
|
|
34
103
|
executionId: string,
|
|
35
104
|
status: AgentExecutionStatus,
|
|
105
|
+
options: PersistStatusOptions = {},
|
|
36
106
|
): Promise<ExecutionControlSignal> {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
107
|
+
const { offload, retry } = options;
|
|
108
|
+
|
|
109
|
+
if (offload) {
|
|
110
|
+
try {
|
|
111
|
+
await offloadOversizedToolOutputs(status, offload);
|
|
112
|
+
} catch (err) {
|
|
113
|
+
console.warn(`[persistStatus] ${executionId}: tool-output offload failed (non-fatal): ${err}`);
|
|
114
|
+
}
|
|
43
115
|
}
|
|
116
|
+
if (enforceStatusSizeLimit(status)) {
|
|
117
|
+
console.warn(
|
|
118
|
+
`[persistStatus] ${executionId}: status exceeded the soft size limit; ` +
|
|
119
|
+
`elided oversized inline fields to fit under the gRPC cap`,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const baseDelayMs = retry?.baseDelayMs ?? DEFAULT_PERSIST_RETRY.baseDelayMs;
|
|
124
|
+
const backoffFactor = retry?.backoffFactor ?? DEFAULT_PERSIST_RETRY.backoffFactor;
|
|
125
|
+
const maxRetries = retry?.maxRetries ?? DEFAULT_PERSIST_RETRY.maxRetries;
|
|
126
|
+
const delay = retry?.delayFn ?? defaultDelay;
|
|
127
|
+
|
|
128
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
129
|
+
try {
|
|
130
|
+
const response = await client.updateStatus(executionId, status);
|
|
131
|
+
return response.signal;
|
|
132
|
+
} catch (err) {
|
|
133
|
+
// Oversize rejection is recoverable exactly once and out-of-band from the
|
|
134
|
+
// transient budget: hard-elide the largest inline fields and retry now.
|
|
135
|
+
if (isPayloadTooLarge(err)) {
|
|
136
|
+
console.error(
|
|
137
|
+
`[persistStatus] ${executionId}: payload rejected as too large despite ` +
|
|
138
|
+
`the size guard; hard-eliding and retrying once`,
|
|
139
|
+
);
|
|
140
|
+
enforceStatusSizeLimit(status, STATUS_PAYLOAD_HARD_LIMIT_BYTES);
|
|
141
|
+
try {
|
|
142
|
+
const response = await client.updateStatus(executionId, status);
|
|
143
|
+
return response.signal;
|
|
144
|
+
} catch (retryErr) {
|
|
145
|
+
console.error(`[persistStatus] ${executionId}: still failing after hard elide:`, retryErr);
|
|
146
|
+
return ExecutionControlSignal.UNSPECIFIED;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Terminal errors (invalid argument, not found, permission denied) are
|
|
151
|
+
// deterministic — retrying cannot help.
|
|
152
|
+
if (isTerminalError(err)) {
|
|
153
|
+
console.error(
|
|
154
|
+
`[persistStatus] ${executionId}: terminal error persisting status ` +
|
|
155
|
+
`(attempt ${attempt + 1}/${maxRetries + 1}): ${err}`,
|
|
156
|
+
);
|
|
157
|
+
return ExecutionControlSignal.UNSPECIFIED;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Transient errors back off and retry until the budget is exhausted.
|
|
161
|
+
if (isRetryableError(err) && attempt < maxRetries) {
|
|
162
|
+
const delayMs = baseDelayMs * Math.pow(backoffFactor, attempt);
|
|
163
|
+
console.warn(
|
|
164
|
+
`[persistStatus] ${executionId}: retryable error ` +
|
|
165
|
+
`(attempt ${attempt + 1}/${maxRetries + 1}, retry in ${delayMs}ms): ${err}`,
|
|
166
|
+
);
|
|
167
|
+
await delay(delayMs);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Non-retryable, non-terminal (e.g. a bare Error), or retries exhausted.
|
|
172
|
+
console.error(`Failed to persist status for ${executionId}:`, err);
|
|
173
|
+
return ExecutionControlSignal.UNSPECIFIED;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return ExecutionControlSignal.UNSPECIFIED;
|
|
44
178
|
}
|
|
45
179
|
|
|
46
180
|
/**
|
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
* OR firstUpdate
|
|
14
14
|
*
|
|
15
15
|
* Ported from Python StreamingUpdateScheduler.
|
|
16
|
+
*
|
|
17
|
+
* Shared infrastructure: both the native deep-agent harness and the Cursor
|
|
18
|
+
* harness drive their incremental status persistence through this scheduler so
|
|
19
|
+
* the live stream cadence is identical across harnesses.
|
|
16
20
|
*/
|
|
17
21
|
|
|
18
22
|
export enum UpdateReason {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"streaming-scheduler.js","sourceRoot":"","sources":["../../../src/activities/execute-deep-agent/streaming-scheduler.ts"],"names":[],"mappings":"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"}
|
|
File without changes
|