@relayflows/sdk 2.0.20 → 2.0.22
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/agent-reaper.d.ts +4 -0
- package/dist/agent-reaper.d.ts.map +1 -0
- package/dist/agent-reaper.js +53 -0
- package/dist/agent-reaper.js.map +1 -0
- package/dist/agent-transcript.d.ts +186 -0
- package/dist/agent-transcript.d.ts.map +1 -0
- package/dist/agent-transcript.js +585 -0
- package/dist/agent-transcript.js.map +1 -0
- package/dist/child-stop.d.ts +1 -1
- package/dist/child-stop.d.ts.map +1 -1
- package/dist/child-stop.js +68 -12
- package/dist/child-stop.js.map +1 -1
- package/dist/cli/run.js +2 -1
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/status.d.ts +34 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +307 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/step-failure.js +31 -7
- package/dist/cli/step-failure.js.map +1 -1
- package/dist/cli-commands.d.ts +13 -0
- package/dist/cli-commands.d.ts.map +1 -1
- package/dist/cli-commands.js +11 -0
- package/dist/cli-commands.js.map +1 -1
- package/dist/cli.d.ts +2 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +9 -0
- package/dist/cli.js.map +1 -1
- package/dist/failure-kinds.d.ts +15 -2
- package/dist/failure-kinds.d.ts.map +1 -1
- package/dist/failure-kinds.js +8 -0
- package/dist/failure-kinds.js.map +1 -1
- package/dist/journal-reader.d.ts +1 -1
- package/dist/journal-reader.d.ts.map +1 -1
- package/dist/journal-reader.js +3 -1
- package/dist/journal-reader.js.map +1 -1
- package/dist/llm-worker.d.ts.map +1 -1
- package/dist/llm-worker.js +12 -1
- package/dist/llm-worker.js.map +1 -1
- package/dist/permissions-preflight.d.ts +22 -0
- package/dist/permissions-preflight.d.ts.map +1 -0
- package/dist/permissions-preflight.js +49 -0
- package/dist/permissions-preflight.js.map +1 -0
- package/dist/preflight.d.ts.map +1 -1
- package/dist/preflight.js +6 -0
- package/dist/preflight.js.map +1 -1
- package/dist/pty-sidechannel.d.ts +7 -0
- package/dist/pty-sidechannel.d.ts.map +1 -1
- package/dist/pty-sidechannel.js.map +1 -1
- package/dist/redact.d.ts +16 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +104 -0
- package/dist/redact.js.map +1 -0
- package/dist/run-state.d.ts +124 -0
- package/dist/run-state.d.ts.map +1 -0
- package/dist/run-state.js +368 -0
- package/dist/run-state.js.map +1 -0
- package/dist/spec.d.ts +16 -1
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js.map +1 -1
- package/dist/step-env.d.ts +25 -0
- package/dist/step-env.d.ts.map +1 -0
- package/dist/step-env.js +34 -0
- package/dist/step-env.js.map +1 -0
- package/dist/transcript-tail.d.ts +54 -0
- package/dist/transcript-tail.d.ts.map +1 -0
- package/dist/transcript-tail.js +176 -0
- package/dist/transcript-tail.js.map +1 -0
- package/dist/worker-cli.d.ts +18 -0
- package/dist/worker-cli.d.ts.map +1 -1
- package/dist/worker-cli.js +219 -22
- package/dist/worker-cli.js.map +1 -1
- package/dist/worker-usage.d.ts +15 -2
- package/dist/worker-usage.d.ts.map +1 -1
- package/dist/worker-usage.js +40 -3
- package/dist/worker-usage.js.map +1 -1
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +31 -6
- package/dist/worker.js.map +1 -1
- package/dist/wrapper-runtime.d.ts +7 -1
- package/dist/wrapper-runtime.d.ts.map +1 -1
- package/dist/wrapper-runtime.js +7 -1
- package/dist/wrapper-runtime.js.map +1 -1
- package/package.json +2 -2
- package/src/agent-reaper.ts +52 -0
- package/src/agent-transcript.ts +651 -0
- package/src/child-stop.ts +62 -12
- package/src/cli/run.ts +2 -1
- package/src/cli/status.ts +329 -0
- package/src/cli/step-failure.ts +32 -7
- package/src/cli-commands.ts +11 -0
- package/src/cli.ts +8 -0
- package/src/failure-kinds.ts +15 -1
- package/src/journal-reader.ts +4 -2
- package/src/llm-worker.ts +12 -1
- package/src/permissions-preflight.ts +53 -0
- package/src/preflight.ts +6 -0
- package/src/pty-sidechannel.ts +7 -0
- package/src/redact.ts +106 -0
- package/src/run-state.ts +468 -0
- package/src/spec.ts +16 -1
- package/src/step-env.ts +47 -0
- package/src/transcript-tail.ts +193 -0
- package/src/worker-cli.ts +213 -21
- package/src/worker-usage.ts +39 -3
- package/src/worker.ts +32 -6
- package/src/wrapper-runtime.ts +7 -1
package/src/worker-usage.ts
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import type { WorkerCliResult } from './worker-cli.js';
|
|
2
2
|
import { MODEL_PRICING } from './model-pricing.js';
|
|
3
|
+
import { FAILURE_EXCERPT_MAX_BYTES, buildTranscriptDigest, redactText, utf8Tail } from './agent-transcript.js';
|
|
3
4
|
|
|
4
5
|
type RecordValue = Record<string, unknown>;
|
|
5
6
|
const record = (value: unknown): value is RecordValue => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
6
7
|
const count = (value: unknown): value is number => typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
|
|
7
8
|
|
|
9
|
+
/**
|
|
10
|
+
* A completion this decoder refuses. The refusal is appended to stderr, and a
|
|
11
|
+
* digest already built from the frames gets it as its failure — otherwise the
|
|
12
|
+
* digest would still describe the attempt as the provider reported it.
|
|
13
|
+
*/
|
|
8
14
|
function invalid(result: WorkerCliResult, detail: string): WorkerCliResult {
|
|
9
|
-
|
|
15
|
+
const stderr_tail = `${result.stderr_tail}\n${detail}`.trim();
|
|
16
|
+
const transcript = result.transcript === undefined ? undefined : { ...result.transcript,
|
|
17
|
+
failure: { kind: 'stderr' as const, excerpt: utf8Tail(redactText(stderr_tail), FAILURE_EXCERPT_MAX_BYTES) } };
|
|
18
|
+
return { ...result, exit_code: null, stderr_tail, ...(transcript === undefined ? {} : { transcript }) };
|
|
10
19
|
}
|
|
11
20
|
|
|
12
21
|
function usageResult(result: WorkerCliResult, usage: unknown, output: unknown): WorkerCliResult {
|
|
@@ -18,12 +27,26 @@ function usageResult(result: WorkerCliResult, usage: unknown, output: unknown):
|
|
|
18
27
|
tokens_input: usage.input_tokens, tokens_output: usage.output_tokens };
|
|
19
28
|
}
|
|
20
29
|
|
|
21
|
-
/**
|
|
22
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Provider envelopes are execution metadata, never the authored output. The
|
|
32
|
+
* same frames also yield the transcript digest (`agent-transcript.ts`): the
|
|
33
|
+
* metered `tokens_input/output` stay the budget source, and the provider's own
|
|
34
|
+
* cost, model, tool calls and failure ride beside them in `transcript`.
|
|
35
|
+
*/
|
|
36
|
+
export function decodeProviderResult(
|
|
37
|
+
result: WorkerCliResult,
|
|
38
|
+
kind: 'claude' | 'codex',
|
|
39
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
40
|
+
): WorkerCliResult {
|
|
23
41
|
const frames: RecordValue[] = [];
|
|
24
42
|
for (const line of result.stdout_tail.split('\n')) {
|
|
25
43
|
try { const frame: unknown = JSON.parse(line); if (record(frame)) frames.push(frame); } catch { /* Plain text remains output. */ }
|
|
26
44
|
}
|
|
45
|
+
const decoded = decodeUsage(result, frames, kind);
|
|
46
|
+
return { ...decoded, transcript: { ...result.transcript, ...buildTranscriptDigest(frames, kind, decoded, env) } };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function decodeUsage(result: WorkerCliResult, frames: RecordValue[], kind: 'claude' | 'codex'): WorkerCliResult {
|
|
27
50
|
const terminal = [...frames].reverse().find(f => kind === 'claude' ? f.type === 'result' : f.type === 'turn.completed');
|
|
28
51
|
if (terminal === undefined) return result;
|
|
29
52
|
const text = kind === 'claude' ? terminal.result : frames
|
|
@@ -31,6 +54,19 @@ export function decodeProviderResult(result: WorkerCliResult, kind: 'claude' | '
|
|
|
31
54
|
return usageResult(result, terminal.usage, text);
|
|
32
55
|
}
|
|
33
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Claude's terminal `stream-json` frame, recognised line by line as it
|
|
59
|
+
* streams. `failed` mirrors the exit status Claude gives that result: an
|
|
60
|
+
* error flag or a non-success subtype is a failed run.
|
|
61
|
+
*/
|
|
62
|
+
export function claudeResultOutcome(line: string): { failed: boolean } | undefined {
|
|
63
|
+
if (!line.includes('"result"')) return undefined;
|
|
64
|
+
let frame: unknown;
|
|
65
|
+
try { frame = JSON.parse(line); } catch { return undefined; }
|
|
66
|
+
if (!record(frame) || frame.type !== 'result') return undefined;
|
|
67
|
+
return { failed: frame.is_error === true || (typeof frame.subtype === 'string' && frame.subtype !== 'success') };
|
|
68
|
+
}
|
|
69
|
+
|
|
34
70
|
/** Optional wrapper result envelope; existing opaque text output stays valid. */
|
|
35
71
|
export function decodeWrapperResult(result: WorkerCliResult): WorkerCliResult {
|
|
36
72
|
let value: unknown;
|
package/src/worker.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { withWorkerLease } from './worker-lease.js';
|
|
|
10
10
|
import { workerInstruction } from './worker-input.js';
|
|
11
11
|
import { helperCall } from './yaml-helpers.js';
|
|
12
12
|
import { completeHelperDispatch } from './yaml-helper-effect.js';
|
|
13
|
+
import { ARTIFACT_PATHS_MAX, boundTranscriptDigest, type TranscriptDigest } from './agent-transcript.js';
|
|
13
14
|
|
|
14
15
|
export { MODEL_ENV, WAKE_CONTEXT_ENV } from './worker-cli.js';
|
|
15
16
|
|
|
@@ -110,7 +111,7 @@ export class AgentWorker extends EventEmitter {
|
|
|
110
111
|
const completed: WorkerCliResult = await withWorkerLease(this.client, dispatch, signal =>
|
|
111
112
|
typeof spec.cli === 'string' && typeof spec.instruction === 'string'
|
|
112
113
|
? runAgentCli(spec.cli, workerInstruction(spec.instruction, dispatch), dispatch.wake_context, effectiveModel, undefined, signal, 'agent', this.options.dataDir === undefined ? undefined : {
|
|
113
|
-
dataDir: this.options.dataDir, runId: dispatch.run_id, stepId: dispatch.step_id,
|
|
114
|
+
dataDir: this.options.dataDir, runId: dispatch.run_id, stepId: dispatch.step_id, attempt: dispatch.attempt,
|
|
114
115
|
onReady: this.options.onPtyReady, onDrive: () => { humanIntervention = true; },
|
|
115
116
|
}, typeof spec.cwd === 'string' ? spec.cwd : undefined,
|
|
116
117
|
spec.transport === 'relay' ? 'relay' : 'direct',
|
|
@@ -142,8 +143,20 @@ export class AgentWorker extends EventEmitter {
|
|
|
142
143
|
// or `summary` never asked for. An agent that answers with a JSON object
|
|
143
144
|
// therefore journals no artifacts; gate such a step on a deterministic
|
|
144
145
|
// check instead. The relay transport reports none (the agent ran elsewhere).
|
|
146
|
+
//
|
|
147
|
+
// `transcript` is not part of the wrapper either: it is evidence about the
|
|
148
|
+
// attempt, journaled in `trajectory_tail` below on success and failure
|
|
149
|
+
// alike, where the kernel already accepts and bounds it (16 KiB).
|
|
150
|
+
const { transcript, ...wrapper } = result;
|
|
145
151
|
const output = result.relay_task?.status === 'completed' && result.exit_code === 0
|
|
146
|
-
? result.relay_task.output : parseJsonOutput(result.stdout_tail) ??
|
|
152
|
+
? result.relay_task.output : parseJsonOutput(result.stdout_tail) ?? wrapper;
|
|
153
|
+
const trajectoryTail = {
|
|
154
|
+
...(result.relay_task === undefined ? {} : { relay_task: {
|
|
155
|
+
invocation_id: result.relay_task.invocation_id, status: result.relay_task.status,
|
|
156
|
+
task_execution: result.relay_task.task_execution, error: result.relay_task.error,
|
|
157
|
+
} }),
|
|
158
|
+
...(transcript === undefined ? {} : { transcript: transcriptDigest(transcript, dispatch.attempt, result) }),
|
|
159
|
+
};
|
|
147
160
|
|
|
148
161
|
await this.client.stepComplete(
|
|
149
162
|
dispatch.run_id,
|
|
@@ -153,10 +166,7 @@ export class AgentWorker extends EventEmitter {
|
|
|
153
166
|
completionReason,
|
|
154
167
|
{
|
|
155
168
|
output,
|
|
156
|
-
...(
|
|
157
|
-
invocation_id: result.relay_task.invocation_id, status: result.relay_task.status,
|
|
158
|
-
task_execution: result.relay_task.task_execution, error: result.relay_task.error,
|
|
159
|
-
} } }),
|
|
169
|
+
...(Object.keys(trajectoryTail).length === 0 ? {} : { trajectory_tail: trajectoryTail }),
|
|
160
170
|
...(humanIntervention ? { human_intervention: true } : {}),
|
|
161
171
|
...(usage !== undefined ? { usage } : {}),
|
|
162
172
|
started_pins: dispatch.pins,
|
|
@@ -166,6 +176,22 @@ export class AgentWorker extends EventEmitter {
|
|
|
166
176
|
}
|
|
167
177
|
}
|
|
168
178
|
|
|
179
|
+
/**
|
|
180
|
+
* The digest as journaled: the attempt and exit code (dropped from `output` on
|
|
181
|
+
* the JSON path by design) and the artifact paths folded in, then bounded to
|
|
182
|
+
* `TRANSCRIPT_DIGEST_MAX_BYTES` with every cut stated on the digest itself.
|
|
183
|
+
*/
|
|
184
|
+
function transcriptDigest(transcript: TranscriptDigest, attempt: number, result: WorkerCliResult): TranscriptDigest {
|
|
185
|
+
return boundTranscriptDigest({
|
|
186
|
+
attempt,
|
|
187
|
+
exit_code: result.exit_code,
|
|
188
|
+
...transcript,
|
|
189
|
+
...(result.artifacts === undefined ? {} : { artifacts: {
|
|
190
|
+
count: result.artifacts.length, paths: result.artifacts.slice(0, ARTIFACT_PATHS_MAX),
|
|
191
|
+
} }),
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
169
195
|
/**
|
|
170
196
|
* Return an object-shaped JSON payload parsed from `stdout`, or
|
|
171
197
|
* `null` when stdout is empty, non-JSON, or JSON-of-a-scalar/array.
|
package/src/wrapper-runtime.ts
CHANGED
|
@@ -25,7 +25,13 @@ export interface WrapperIdentity {
|
|
|
25
25
|
fingerprint: string;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* Build a wrapper environment from a closed list; ambient credentials never
|
|
30
|
+
* cross. The step discovery names (`RELAYFLOW_DATA_DIR`, `RELAYFLOW_RUN_ID`,
|
|
31
|
+
* `RELAYFLOW_STEP_ID`, `RELAYFLOW_ATTEMPT`) are deliberately not on the list:
|
|
32
|
+
* an ambient value is a parent step's identity, not this one's, so the worker
|
|
33
|
+
* sets them from the dispatch after this filter (step-env.ts).
|
|
34
|
+
*/
|
|
29
35
|
export function wrapperEnvironment(source: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|
30
36
|
const env: NodeJS.ProcessEnv = {};
|
|
31
37
|
for (const name of WRAPPER_ENV_ALLOWLIST) {
|