@agent-relay/sdk 3.2.18 → 3.2.20
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/bin/agent-relay-broker-darwin-arm64 +0 -0
- package/bin/agent-relay-broker-darwin-x64 +0 -0
- package/bin/agent-relay-broker-linux-arm64 +0 -0
- package/bin/agent-relay-broker-linux-x64 +0 -0
- package/dist/workflows/__tests__/e2big-and-verify.test.d.ts +2 -0
- package/dist/workflows/__tests__/e2big-and-verify.test.d.ts.map +1 -0
- package/dist/workflows/__tests__/e2big-and-verify.test.js +62 -0
- package/dist/workflows/__tests__/e2big-and-verify.test.js.map +1 -0
- package/dist/workflows/runner.d.ts +4 -0
- package/dist/workflows/runner.d.ts.map +1 -1
- package/dist/workflows/runner.js +76 -39
- package/dist/workflows/runner.js.map +1 -1
- package/package.json +2 -2
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2big-and-verify.test.d.ts","sourceRoot":"","sources":["../../../src/workflows/__tests__/e2big-and-verify.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
vi.mock('@relaycast/sdk', () => ({
|
|
3
|
+
RelayCast: vi.fn(),
|
|
4
|
+
RelayError: class RelayError extends Error {
|
|
5
|
+
},
|
|
6
|
+
}));
|
|
7
|
+
vi.mock('../../relay.js', () => ({
|
|
8
|
+
AgentRelay: vi.fn(),
|
|
9
|
+
}));
|
|
10
|
+
const { WorkflowRunner } = await import('../runner.js');
|
|
11
|
+
describe('runVerification output_contains (token double-count fix)', () => {
|
|
12
|
+
function createRunner() {
|
|
13
|
+
return new WorkflowRunner({ cwd: '/tmp/test' });
|
|
14
|
+
}
|
|
15
|
+
function runVerification(runner, check, output, stepName, injectedTaskText) {
|
|
16
|
+
return runner.runVerification(check, output, stepName, injectedTaskText, {
|
|
17
|
+
allowFailure: true,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
it('passes when token is in output and not in task injection', () => {
|
|
21
|
+
const runner = createRunner();
|
|
22
|
+
const result = runVerification(runner, { type: 'output_contains', value: 'DONE' }, 'Task completed. DONE', 'step1');
|
|
23
|
+
expect(result.passed).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
it('fails when token is missing from output entirely', () => {
|
|
26
|
+
const runner = createRunner();
|
|
27
|
+
const result = runVerification(runner, { type: 'output_contains', value: 'DONE' }, 'Task completed without the marker', 'step1');
|
|
28
|
+
expect(result.passed).toBe(false);
|
|
29
|
+
expect(result.error).toContain('does not contain "DONE"');
|
|
30
|
+
});
|
|
31
|
+
it('passes when token is in both task injection and agent output', () => {
|
|
32
|
+
const runner = createRunner();
|
|
33
|
+
const result = runVerification(runner, { type: 'output_contains', value: 'REFLECTION_COMPLETE' }, 'Your task: output REFLECTION_COMPLETE when done\n\nI have finished. REFLECTION_COMPLETE', 'step1', 'Your task: output REFLECTION_COMPLETE when done');
|
|
34
|
+
expect(result.passed).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
it('fails when token appears only in task injection (not produced by agent)', () => {
|
|
37
|
+
const runner = createRunner();
|
|
38
|
+
const result = runVerification(runner, { type: 'output_contains', value: 'REFLECTION_COMPLETE' }, 'Your task: output REFLECTION_COMPLETE when done\n\nI worked on it but forgot the marker.', 'step1', 'Your task: output REFLECTION_COMPLETE when done');
|
|
39
|
+
expect(result.passed).toBe(false);
|
|
40
|
+
expect(result.error).toContain('does not contain "REFLECTION_COMPLETE"');
|
|
41
|
+
});
|
|
42
|
+
it('handles token appearing multiple times in task injection', () => {
|
|
43
|
+
const runner = createRunner();
|
|
44
|
+
const taskText = 'Output DONE when done. Remember: DONE is required.';
|
|
45
|
+
const output = taskText + '\n\nAll work complete. DONE';
|
|
46
|
+
const result = runVerification(runner, { type: 'output_contains', value: 'DONE' }, output, 'step1', taskText);
|
|
47
|
+
expect(result.passed).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
it('fails when token appears same number of times as in task injection', () => {
|
|
50
|
+
const runner = createRunner();
|
|
51
|
+
const taskText = 'Output DONE when done. Remember: DONE is required.';
|
|
52
|
+
const output = taskText + '\n\nAll work complete but no marker here.';
|
|
53
|
+
const result = runVerification(runner, { type: 'output_contains', value: 'DONE' }, output, 'step1', taskText);
|
|
54
|
+
expect(result.passed).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
it('handles empty token gracefully', () => {
|
|
57
|
+
const runner = createRunner();
|
|
58
|
+
const result = runVerification(runner, { type: 'output_contains', value: '' }, 'some output', 'step1');
|
|
59
|
+
expect(result.passed).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=e2big-and-verify.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2big-and-verify.test.js","sourceRoot":"","sources":["../../../src/workflows/__tests__/e2big-and-verify.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -183,6 +183,7 @@ export declare class WorkflowRunner {
|
|
|
183
183
|
private readonly activeReviewers;
|
|
184
184
|
/** Structured CLI session reports captured during the current run, keyed by step name. */
|
|
185
185
|
private readonly agentReports;
|
|
186
|
+
private static readonly PTY_TASK_ARG_SIZE_LIMIT;
|
|
186
187
|
constructor(options?: WorkflowRunnerOptions);
|
|
187
188
|
/** Expand environment variables like $HOME or $VAR in a path string. */
|
|
188
189
|
private static resolveEnvVars;
|
|
@@ -326,6 +327,9 @@ export declare class WorkflowRunner {
|
|
|
326
327
|
private hasOwnerCompletionMarker;
|
|
327
328
|
private parseOwnerDecision;
|
|
328
329
|
private stripEchoedPromptLines;
|
|
330
|
+
private stripInjectedTaskEcho;
|
|
331
|
+
private outputContainsVerificationToken;
|
|
332
|
+
private prepareInteractiveSpawnTask;
|
|
329
333
|
private firstMeaningfulLine;
|
|
330
334
|
private judgeOwnerCompletionByEvidence;
|
|
331
335
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/workflows/runner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/workflows/runner.ts"],"names":[],"mappings":"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"}
|
package/dist/workflows/runner.js
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { spawn as cpSpawn } from 'node:child_process';
|
|
7
7
|
import { randomBytes } from 'node:crypto';
|
|
8
|
-
import { createWriteStream, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync, } from 'node:fs';
|
|
9
|
-
import { readFile, writeFile } from 'node:fs/promises';
|
|
8
|
+
import { createWriteStream, existsSync, mkdtempSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync, } from 'node:fs';
|
|
9
|
+
import { readFile, writeFile, unlink } from 'node:fs/promises';
|
|
10
|
+
import { tmpdir } from 'node:os';
|
|
10
11
|
import path from 'node:path';
|
|
11
12
|
import chalk from 'chalk';
|
|
12
13
|
import { parse as parseYaml } from 'yaml';
|
|
@@ -114,6 +115,7 @@ export class WorkflowRunner {
|
|
|
114
115
|
activeReviewers = new Map();
|
|
115
116
|
/** Structured CLI session reports captured during the current run, keyed by step name. */
|
|
116
117
|
agentReports = new Map();
|
|
118
|
+
static PTY_TASK_ARG_SIZE_LIMIT = 2 * 1024 * 1024; // 2 MB
|
|
117
119
|
constructor(options = {}) {
|
|
118
120
|
this.db = options.db ?? new InMemoryWorkflowDb();
|
|
119
121
|
this.workspaceId = options.workspaceId ?? 'local';
|
|
@@ -2783,6 +2785,7 @@ export class WorkflowRunner {
|
|
|
2783
2785
|
let ownerOutput;
|
|
2784
2786
|
let ownerElapsed;
|
|
2785
2787
|
let completionReason;
|
|
2788
|
+
let promptTaskText;
|
|
2786
2789
|
if (usesDedicatedOwner) {
|
|
2787
2790
|
const result = await this.executeSupervisedAgentStep(step, { specialist: effectiveSpecialist, owner: effectiveOwner, reviewer: reviewDef }, resolvedTask, timeoutMs);
|
|
2788
2791
|
specialistOutput = result.specialistOutput;
|
|
@@ -2823,13 +2826,19 @@ export class WorkflowRunner {
|
|
|
2823
2826
|
: undefined,
|
|
2824
2827
|
});
|
|
2825
2828
|
const output = typeof spawnResult === 'string' ? spawnResult : spawnResult.output;
|
|
2829
|
+
promptTaskText =
|
|
2830
|
+
typeof spawnResult === 'string'
|
|
2831
|
+
? effectiveOwner.interactive === false
|
|
2832
|
+
? undefined
|
|
2833
|
+
: ownerTask
|
|
2834
|
+
: spawnResult.promptTaskText ?? ownerTask;
|
|
2826
2835
|
lastExitCode = typeof spawnResult === 'string' ? undefined : spawnResult.exitCode;
|
|
2827
2836
|
lastExitSignal = typeof spawnResult === 'string' ? undefined : spawnResult.exitSignal;
|
|
2828
2837
|
ownerElapsed = Date.now() - ownerStartTime;
|
|
2829
2838
|
this.log(`[${step.name}] Owner "${effectiveOwner.name}" exited`);
|
|
2830
2839
|
if (usesOwnerFlow) {
|
|
2831
2840
|
try {
|
|
2832
|
-
const completionDecision = this.resolveOwnerCompletionDecision(step, output, output, ownerTask,
|
|
2841
|
+
const completionDecision = this.resolveOwnerCompletionDecision(step, output, output, promptTaskText ?? ownerTask, promptTaskText ?? ownerTask);
|
|
2833
2842
|
completionReason = completionDecision.completionReason;
|
|
2834
2843
|
}
|
|
2835
2844
|
catch (error) {
|
|
@@ -2864,7 +2873,7 @@ export class WorkflowRunner {
|
|
|
2864
2873
|
// Self-owned interactive steps still need verification fallback so
|
|
2865
2874
|
// explicit OWNER_DECISION output is not mandatory for the happy path.
|
|
2866
2875
|
if (step.verification && (!usesOwnerFlow || !usesDedicatedOwner) && !completionReason) {
|
|
2867
|
-
const verificationResult = this.runVerification(step.verification, specialistOutput, step.name,
|
|
2876
|
+
const verificationResult = this.runVerification(step.verification, specialistOutput, step.name, promptTaskText);
|
|
2868
2877
|
completionReason = verificationResult.completionReason;
|
|
2869
2878
|
}
|
|
2870
2879
|
// Retry-style owner decisions are control-flow signals, not terminal success states.
|
|
@@ -3120,7 +3129,8 @@ export class WorkflowRunner {
|
|
|
3120
3129
|
detail: `Worker ${workerRuntimeName} exited`,
|
|
3121
3130
|
raw: { worker: workerRuntimeName, exitCode: result.exitCode, exitSignal: result.exitSignal },
|
|
3122
3131
|
});
|
|
3123
|
-
if (step.verification?.type === 'output_contains' &&
|
|
3132
|
+
if (step.verification?.type === 'output_contains' &&
|
|
3133
|
+
this.outputContainsVerificationToken(result.output, step.verification.value, result.promptTaskText)) {
|
|
3124
3134
|
this.log(`[${step.name}] Verification gate observed: output contains ${JSON.stringify(step.verification.value)}`);
|
|
3125
3135
|
}
|
|
3126
3136
|
})
|
|
@@ -3163,8 +3173,9 @@ export class WorkflowRunner {
|
|
|
3163
3173
|
const ownerElapsed = Date.now() - ownerStartTime;
|
|
3164
3174
|
const ownerOutput = ownerResultObj.output;
|
|
3165
3175
|
this.log(`[${step.name}] Owner "${supervised.owner.name}" exited`);
|
|
3166
|
-
const
|
|
3167
|
-
const
|
|
3176
|
+
const workerResultObj = await workerPromise;
|
|
3177
|
+
const specialistOutput = workerResultObj.output;
|
|
3178
|
+
const completionDecision = this.resolveOwnerCompletionDecision(step, ownerOutput, specialistOutput, ownerResultObj.promptTaskText ?? supervisorTask, workerResultObj.promptTaskText ?? specialistTask);
|
|
3168
3179
|
return {
|
|
3169
3180
|
specialistOutput,
|
|
3170
3181
|
ownerOutput,
|
|
@@ -3379,6 +3390,10 @@ export class WorkflowRunner {
|
|
|
3379
3390
|
}
|
|
3380
3391
|
hasOwnerCompletionMarker(step, output, injectedTaskText) {
|
|
3381
3392
|
const marker = `STEP_COMPLETE:${step.name}`;
|
|
3393
|
+
const strippedOutput = this.stripInjectedTaskEcho(output, injectedTaskText);
|
|
3394
|
+
if (strippedOutput.includes(marker)) {
|
|
3395
|
+
return true;
|
|
3396
|
+
}
|
|
3382
3397
|
const taskHasMarker = injectedTaskText.includes(marker);
|
|
3383
3398
|
const first = output.indexOf(marker);
|
|
3384
3399
|
if (first === -1) {
|
|
@@ -3451,6 +3466,49 @@ export class WorkflowRunner {
|
|
|
3451
3466
|
.filter((line) => patterns.every((pattern) => !pattern.test(line)))
|
|
3452
3467
|
.join('\n');
|
|
3453
3468
|
}
|
|
3469
|
+
stripInjectedTaskEcho(output, injectedTaskText) {
|
|
3470
|
+
if (!injectedTaskText) {
|
|
3471
|
+
return output;
|
|
3472
|
+
}
|
|
3473
|
+
const candidates = [
|
|
3474
|
+
injectedTaskText,
|
|
3475
|
+
injectedTaskText.replace(/\r\n/g, '\n'),
|
|
3476
|
+
injectedTaskText.replace(/\n/g, '\r\n'),
|
|
3477
|
+
].filter((candidate, index, all) => candidate.length > 0 && all.indexOf(candidate) === index);
|
|
3478
|
+
for (const candidate of candidates) {
|
|
3479
|
+
const start = output.indexOf(candidate);
|
|
3480
|
+
if (start !== -1) {
|
|
3481
|
+
return output.slice(0, start) + output.slice(start + candidate.length);
|
|
3482
|
+
}
|
|
3483
|
+
}
|
|
3484
|
+
return output;
|
|
3485
|
+
}
|
|
3486
|
+
outputContainsVerificationToken(output, token, injectedTaskText) {
|
|
3487
|
+
if (!token) {
|
|
3488
|
+
return false;
|
|
3489
|
+
}
|
|
3490
|
+
return this.stripInjectedTaskEcho(output, injectedTaskText).includes(token);
|
|
3491
|
+
}
|
|
3492
|
+
prepareInteractiveSpawnTask(agentName, taskText) {
|
|
3493
|
+
if (Buffer.byteLength(taskText, 'utf8') <= WorkflowRunner.PTY_TASK_ARG_SIZE_LIMIT) {
|
|
3494
|
+
return {
|
|
3495
|
+
spawnTaskText: taskText,
|
|
3496
|
+
promptTaskText: taskText,
|
|
3497
|
+
};
|
|
3498
|
+
}
|
|
3499
|
+
const taskTmpDir = mkdtempSync(path.join(tmpdir(), 'relay-pty-task-'));
|
|
3500
|
+
const taskTmpFile = path.join(taskTmpDir, `${agentName}-${Date.now()}.txt`);
|
|
3501
|
+
writeFileSync(taskTmpFile, taskText, { encoding: 'utf8', mode: 0o600, flag: 'wx' });
|
|
3502
|
+
const promptTaskText = `TASK_FILE:${taskTmpFile}\n` +
|
|
3503
|
+
'Read that file completely before taking any action.\n' +
|
|
3504
|
+
'Treat the file contents as the full workflow task and follow them exactly.\n' +
|
|
3505
|
+
'Do not ask for the task again.';
|
|
3506
|
+
return {
|
|
3507
|
+
spawnTaskText: promptTaskText,
|
|
3508
|
+
promptTaskText,
|
|
3509
|
+
taskTmpFile,
|
|
3510
|
+
};
|
|
3511
|
+
}
|
|
3454
3512
|
firstMeaningfulLine(output) {
|
|
3455
3513
|
return output
|
|
3456
3514
|
.split('\n')
|
|
@@ -4044,6 +4102,7 @@ export class WorkflowRunner {
|
|
|
4044
4102
|
'(b) outputting the exact text "/exit" on its own line as a fallback. ' +
|
|
4045
4103
|
'Do not wait for further input — terminate immediately after finishing. ' +
|
|
4046
4104
|
'Do NOT spawn sub-agents unless the task explicitly requires it.';
|
|
4105
|
+
const preparedTask = this.prepareInteractiveSpawnTask(agentName, taskWithExit);
|
|
4047
4106
|
// Register PTY output listener before spawning so we capture everything
|
|
4048
4107
|
this.ptyOutputBuffers.set(agentName, []);
|
|
4049
4108
|
// Open a log file so `agents:logs <name>` works for workflow-spawned agents
|
|
@@ -4077,7 +4136,7 @@ export class WorkflowRunner {
|
|
|
4077
4136
|
model: agentDef.constraints?.model,
|
|
4078
4137
|
args: interactiveSpawnPolicy.args,
|
|
4079
4138
|
channels: agentChannels,
|
|
4080
|
-
task:
|
|
4139
|
+
task: preparedTask.spawnTaskText,
|
|
4081
4140
|
idleThresholdSecs: agentDef.constraints?.idleThresholdSecs,
|
|
4082
4141
|
cwd: agentCwd,
|
|
4083
4142
|
});
|
|
@@ -4159,7 +4218,7 @@ export class WorkflowRunner {
|
|
|
4159
4218
|
// Register agent handle for hub-mediated nudging
|
|
4160
4219
|
this.activeAgentHandles.set(agentName, agent);
|
|
4161
4220
|
// Wait for agent to exit, with idle nudging if configured
|
|
4162
|
-
exitResult = await this.waitForExitWithIdleNudging(agent, agentDef, step, timeoutMs, options.preserveOnIdle ?? this.shouldPreserveIdleSupervisor(agentDef, step, options.evidenceRole));
|
|
4221
|
+
exitResult = await this.waitForExitWithIdleNudging(agent, agentDef, step, timeoutMs, preparedTask.promptTaskText, options.preserveOnIdle ?? this.shouldPreserveIdleSupervisor(agentDef, step, options.evidenceRole));
|
|
4163
4222
|
// Stop heartbeat now that agent has exited
|
|
4164
4223
|
stopHeartbeat?.();
|
|
4165
4224
|
if (exitResult === 'timeout') {
|
|
@@ -4169,7 +4228,7 @@ export class WorkflowRunner {
|
|
|
4169
4228
|
let timeoutRecovered = false;
|
|
4170
4229
|
if (step.verification) {
|
|
4171
4230
|
const ptyOutput = (this.ptyOutputBuffers.get(agentName) ?? []).join('');
|
|
4172
|
-
const verificationResult = this.runVerification(step.verification, ptyOutput, step.name,
|
|
4231
|
+
const verificationResult = this.runVerification(step.verification, ptyOutput, step.name, preparedTask.promptTaskText, { allowFailure: true });
|
|
4173
4232
|
if (verificationResult.passed) {
|
|
4174
4233
|
this.log(`[${step.name}] Agent timed out but verification passed — treating as complete`);
|
|
4175
4234
|
this.postToChannel(`**[${step.name}]** Agent idle after completing work — verification passed, releasing`);
|
|
@@ -4216,6 +4275,9 @@ export class WorkflowRunner {
|
|
|
4216
4275
|
this.unregisterWorker(agentName);
|
|
4217
4276
|
this.supervisedRuntimeAgents.delete(agentName);
|
|
4218
4277
|
this.runtimeStepAgents.delete(agentName);
|
|
4278
|
+
if (preparedTask.taskTmpFile) {
|
|
4279
|
+
await unlink(preparedTask.taskTmpFile).catch(() => undefined);
|
|
4280
|
+
}
|
|
4219
4281
|
}
|
|
4220
4282
|
let output;
|
|
4221
4283
|
if (ptyChunks.length > 0) {
|
|
@@ -4243,6 +4305,7 @@ export class WorkflowRunner {
|
|
|
4243
4305
|
output,
|
|
4244
4306
|
exitCode: agent?.exitCode,
|
|
4245
4307
|
exitSignal: agent?.exitSignal,
|
|
4308
|
+
promptTaskText: preparedTask.promptTaskText,
|
|
4246
4309
|
};
|
|
4247
4310
|
}
|
|
4248
4311
|
// ── Idle nudging ────────────────────────────────────────────────────────
|
|
@@ -4288,7 +4351,7 @@ export class WorkflowRunner {
|
|
|
4288
4351
|
* Wait for agent exit with idle detection and nudging.
|
|
4289
4352
|
* If no idle nudge config is set, falls through to simple waitForExit.
|
|
4290
4353
|
*/
|
|
4291
|
-
async waitForExitWithIdleNudging(agent, agentDef, step, timeoutMs, preserveIdleSupervisor = false) {
|
|
4354
|
+
async waitForExitWithIdleNudging(agent, agentDef, step, timeoutMs, promptTaskText, preserveIdleSupervisor = false) {
|
|
4292
4355
|
const nudgeConfig = this.currentConfig?.swarm.idleNudge;
|
|
4293
4356
|
if (!nudgeConfig) {
|
|
4294
4357
|
if (preserveIdleSupervisor) {
|
|
@@ -4309,22 +4372,10 @@ export class WorkflowRunner {
|
|
|
4309
4372
|
]);
|
|
4310
4373
|
if (result.kind === 'idle' && result.result === 'idle') {
|
|
4311
4374
|
// Check verification before treating idle as complete.
|
|
4312
|
-
// Mirror runVerification's double-occurrence guard: if the task text
|
|
4313
|
-
// contains the token (from the prompt instruction), require a second
|
|
4314
|
-
// occurrence from the agent's actual output to avoid false positives.
|
|
4315
4375
|
if (step.verification && step.verification.type === 'output_contains') {
|
|
4316
4376
|
const token = step.verification.value;
|
|
4317
4377
|
const ptyOutput = (this.ptyOutputBuffers.get(agent.name) ?? []).join('');
|
|
4318
|
-
const
|
|
4319
|
-
const taskHasToken = taskText.includes(token);
|
|
4320
|
-
let verificationPassed = true;
|
|
4321
|
-
if (taskHasToken) {
|
|
4322
|
-
const first = ptyOutput.indexOf(token);
|
|
4323
|
-
verificationPassed = first !== -1 && ptyOutput.includes(token, first + token.length);
|
|
4324
|
-
}
|
|
4325
|
-
else {
|
|
4326
|
-
verificationPassed = ptyOutput.includes(token);
|
|
4327
|
-
}
|
|
4378
|
+
const verificationPassed = this.outputContainsVerificationToken(ptyOutput, token, promptTaskText);
|
|
4328
4379
|
if (!verificationPassed) {
|
|
4329
4380
|
// The broker fires agent_idle only once per idle transition.
|
|
4330
4381
|
// If the agent is still working (will produce output then idle again),
|
|
@@ -4504,22 +4555,8 @@ export class WorkflowRunner {
|
|
|
4504
4555
|
};
|
|
4505
4556
|
switch (check.type) {
|
|
4506
4557
|
case 'output_contains': {
|
|
4507
|
-
// Guard against false positives: the PTY captures the injected task text
|
|
4508
|
-
// verbatim, so if the verification token appears in the task itself the
|
|
4509
|
-
// check would pass immediately without the agent doing any real work.
|
|
4510
|
-
// When the task contains the token, require a SECOND occurrence — one
|
|
4511
|
-
// from the task injection and one from the agent's actual response.
|
|
4512
4558
|
const token = check.value;
|
|
4513
|
-
|
|
4514
|
-
if (taskHasToken) {
|
|
4515
|
-
const first = output.indexOf(token);
|
|
4516
|
-
const hasSecond = first !== -1 && output.includes(token, first + token.length);
|
|
4517
|
-
if (!hasSecond) {
|
|
4518
|
-
return fail(`Verification failed for "${stepName}": output does not contain "${token}" ` +
|
|
4519
|
-
`(token found only in task injection — agent must output it explicitly)`);
|
|
4520
|
-
}
|
|
4521
|
-
}
|
|
4522
|
-
else if (!output.includes(token)) {
|
|
4559
|
+
if (!this.outputContainsVerificationToken(output, token, injectedTaskText)) {
|
|
4523
4560
|
return fail(`Verification failed for "${stepName}": output does not contain "${token}"`);
|
|
4524
4561
|
}
|
|
4525
4562
|
break;
|