@the-open-engine/zeroshot 6.39.1 → 6.40.0
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 +45 -1
- package/cli/agent-provider-boundary.js +19 -0
- package/cli/agent-provider-boundary.ts +79 -0
- package/cli/export-stream.js +94 -0
- package/cli/export-stream.ts +118 -0
- package/cli/index.js +132 -61
- package/cli/json-export.js +2 -38
- package/cli/json-export.ts +2 -56
- package/cli/semantic-canonical.js +60 -0
- package/cli/semantic-canonical.ts +59 -0
- package/cli/semantic-contract.js +97 -0
- package/cli/semantic-contract.ts +153 -0
- package/cli/semantic-events.js +53 -0
- package/cli/semantic-events.ts +65 -0
- package/cli/semantic-evidence.js +63 -0
- package/cli/semantic-evidence.ts +65 -0
- package/cli/semantic-export.js +186 -0
- package/cli/semantic-export.ts +245 -0
- package/cli/semantic-json.js +69 -0
- package/cli/semantic-json.ts +69 -0
- package/cli/semantic-line-scanner.js +56 -0
- package/cli/semantic-line-scanner.ts +54 -0
- package/cli/semantic-parser.js +78 -0
- package/cli/semantic-parser.ts +95 -0
- package/cli/semantic-provider-line.js +91 -0
- package/cli/semantic-provider-line.ts +106 -0
- package/cli/trace-evidence.js +86 -0
- package/cli/trace-evidence.ts +115 -0
- package/cli/trace-export.js +120 -0
- package/cli/trace-export.ts +164 -0
- package/cli/trace-output-record.js +15 -0
- package/cli/trace-output-record.ts +18 -0
- package/cli/trace-output.js +98 -0
- package/cli/trace-output.ts +119 -0
- package/cluster-templates/conductor-bootstrap.json +1 -1
- package/lib/agent-cli-provider/adapters/claude.js +1 -1
- package/lib/agent-cli-provider/adapters/claude.js.map +1 -1
- package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/codex.js +26 -1
- package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
- package/lib/agent-cli-provider/adapters/omp.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/omp.js +1 -1
- package/lib/agent-cli-provider/adapters/omp.js.map +1 -1
- package/lib/agent-cli-provider/log-prefix.d.ts.map +1 -1
- package/lib/agent-cli-provider/log-prefix.js +8 -6
- package/lib/agent-cli-provider/log-prefix.js.map +1 -1
- package/lib/agent-cli-provider/omp/sdk-environment-policy.d.ts +4 -0
- package/lib/agent-cli-provider/omp/sdk-environment-policy.d.ts.map +1 -0
- package/lib/agent-cli-provider/omp/sdk-environment-policy.js +37 -0
- package/lib/agent-cli-provider/omp/sdk-environment-policy.js.map +1 -0
- package/lib/agent-cli-provider/omp/sdk-process-private-runtime.d.ts.map +1 -1
- package/lib/agent-cli-provider/omp/sdk-process-private-runtime.js +4 -15
- package/lib/agent-cli-provider/omp/sdk-process-private-runtime.js.map +1 -1
- package/lib/agent-cli-provider/omp/sdk-process-result.d.ts +2 -0
- package/lib/agent-cli-provider/omp/sdk-process-result.d.ts.map +1 -1
- package/lib/agent-cli-provider/omp/sdk-process-result.js +2 -2
- package/lib/agent-cli-provider/omp/sdk-process-result.js.map +1 -1
- package/lib/agent-cli-provider/omp/sdk-process-runner.d.ts.map +1 -1
- package/lib/agent-cli-provider/omp/sdk-process-runner.js +6 -1
- package/lib/agent-cli-provider/omp/sdk-process-runner.js.map +1 -1
- package/lib/agent-cli-provider/provider-registry.d.ts +3 -1
- package/lib/agent-cli-provider/provider-registry.d.ts.map +1 -1
- package/lib/agent-cli-provider/provider-registry.js +9 -2
- package/lib/agent-cli-provider/provider-registry.js.map +1 -1
- package/lib/agent-cli-provider/single-agent-runtime.d.ts +4 -1
- package/lib/agent-cli-provider/single-agent-runtime.d.ts.map +1 -1
- package/lib/agent-cli-provider/single-agent-runtime.js +18 -15
- package/lib/agent-cli-provider/single-agent-runtime.js.map +1 -1
- package/lib/agent-cli-provider/types.d.ts +3 -0
- package/lib/agent-cli-provider/types.d.ts.map +1 -1
- package/lib/agent-cli-provider/types.js.map +1 -1
- package/lib/cluster-worker/engine-adapter-common.js +18 -0
- package/lib/cluster-worker/engine-adapter.js +2 -1
- package/lib/git-remote-utils.js +22 -5
- package/lib/stream-json-parser.js +6 -5
- package/npm-shrinkwrap.json +2 -2
- package/package.json +7 -4
- package/scripts/omp/runtime-identities.js +31 -18
- package/scripts/omp/runtime.js +2 -0
- package/src/agent/agent-lifecycle.js +17 -1
- package/src/agent/agent-task-executor.js +36 -40
- package/src/agent/output-extraction-failures.js +73 -0
- package/src/agent/output-extraction-failures.ts +100 -0
- package/src/agent/output-extraction-json.js +5 -6
- package/src/agent/output-extraction-json.ts +4 -7
- package/src/agent/output-extraction-types.ts +5 -0
- package/src/agent/provider-terminal-failure.js +2 -2
- package/src/agent/provider-terminal-failure.ts +4 -2
- package/src/agent-cli-provider/adapters/claude.ts +1 -1
- package/src/agent-cli-provider/adapters/codex.ts +36 -1
- package/src/agent-cli-provider/adapters/omp.ts +2 -1
- package/src/agent-cli-provider/log-prefix.ts +12 -7
- package/src/agent-cli-provider/omp/sdk-environment-policy.ts +38 -0
- package/src/agent-cli-provider/omp/sdk-process-private-runtime.ts +4 -16
- package/src/agent-cli-provider/omp/sdk-process-result.ts +4 -2
- package/src/agent-cli-provider/omp/sdk-process-runner.ts +7 -1
- package/src/agent-cli-provider/provider-registry.ts +10 -2
- package/src/agent-cli-provider/single-agent-runtime.ts +24 -15
- package/src/agent-cli-provider/types.ts +3 -0
- package/src/agents/git-pusher-template.js +61 -71
- package/src/attach/socket-paths.js +1 -1
- package/src/attach/socket-paths.ts +1 -1
- package/src/claude-task-runner.js +9 -9
- package/src/foreground-benchmark-run.js +24 -12
- package/src/legacy-lib/git-remote-utils.ts +23 -5
- package/src/legacy-lib/stream-json-parser.ts +10 -5
- package/src/omp-session-verifier.js +8 -5
- package/src/orchestrator.js +42 -0
- package/src/preflight.js +31 -6
- package/src/providers/index.js +4 -22
- package/src/task-execution-context.js +22 -0
- package/src/task-log-line.d.ts +20 -0
- package/src/task-log-line.js +80 -0
- package/src/watcher-prompt-channel.js +1 -1
- package/src/worktree-claude-config.js +25 -0
- package/src/worktree-claude-config.ts +28 -0
- package/task-lib/commands/logs.js +5 -8
- package/task-lib/runner.js +57 -22
- package/task-lib/sdk-watcher-output.js +31 -0
- package/task-lib/sdk-watcher.js +4 -11
- package/task-lib/watcher-output-runtime.js +30 -16
|
@@ -7,6 +7,7 @@ import { createRequire } from 'module';
|
|
|
7
7
|
// Import cluster's stream parser (shared between task and cluster)
|
|
8
8
|
const require = createRequire(import.meta.url);
|
|
9
9
|
const { parseChunk } = require('../../lib/stream-json-parser');
|
|
10
|
+
const { decodeTaskLogLine } = require('../../src/task-log-line');
|
|
10
11
|
|
|
11
12
|
// Tool icons for different tool types
|
|
12
13
|
const TOOL_ICONS = {
|
|
@@ -271,16 +272,12 @@ function handleMulti(event) {
|
|
|
271
272
|
}
|
|
272
273
|
|
|
273
274
|
// Parse a raw log line (may have timestamp prefix)
|
|
274
|
-
function parseLogLine(line) {
|
|
275
|
-
|
|
275
|
+
export function parseLogLine(line) {
|
|
276
|
+
const decoded = decodeTaskLogLine(line);
|
|
277
|
+
if (!decoded.providerOutput) return [];
|
|
278
|
+
const trimmed = decoded.content.trim();
|
|
276
279
|
if (!trimmed) return [];
|
|
277
280
|
|
|
278
|
-
// Strip timestamp prefix if present: [1234567890]{...} -> {...}
|
|
279
|
-
const timestampMatch = trimmed.match(/^\[\d+\](.*)$/);
|
|
280
|
-
if (timestampMatch) {
|
|
281
|
-
trimmed = timestampMatch[1];
|
|
282
|
-
}
|
|
283
|
-
|
|
284
281
|
// Non-JSON lines output as-is
|
|
285
282
|
if (!trimmed.startsWith('{')) {
|
|
286
283
|
return [{ type: 'text', text: trimmed + '\n' }];
|
package/task-lib/runner.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { join, dirname, resolve as resolvePath } from 'path';
|
|
1
|
+
import { execFileSync, spawn } from 'child_process';
|
|
2
|
+
import { isAbsolute, join, dirname, relative, resolve as resolvePath } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import { mkdirSync } from 'fs';
|
|
5
5
|
import { LOGS_DIR } from './config.js';
|
|
@@ -17,6 +17,8 @@ import {
|
|
|
17
17
|
import { createRequire } from 'module';
|
|
18
18
|
|
|
19
19
|
const require = createRequire(import.meta.url);
|
|
20
|
+
const { resolveTaskExecutionContext } = require('../src/task-execution-context.js');
|
|
21
|
+
export { resolveTaskExecutionContext };
|
|
20
22
|
const {
|
|
21
23
|
buildOmpPrompt,
|
|
22
24
|
getProviderRegistryEntry,
|
|
@@ -43,8 +45,6 @@ const {
|
|
|
43
45
|
partitionPathFor,
|
|
44
46
|
createOmpSessionPartitionDirectory,
|
|
45
47
|
} = require('../src/omp-session-partition');
|
|
46
|
-
const TASK_EXECUTION_CONTEXT_ENV = 'ZEROSHOT_TASK_EXECUTION_CONTEXT';
|
|
47
|
-
const TASK_EXECUTION_CONTEXTS = new Set(['host', 'detached', 'docker', 'benchmark']);
|
|
48
48
|
export {
|
|
49
49
|
isOwnedProcessTreeRunning,
|
|
50
50
|
isProcessRunning,
|
|
@@ -401,8 +401,22 @@ function resolveOutputFormat(options) {
|
|
|
401
401
|
}
|
|
402
402
|
|
|
403
403
|
function resolveJsonSchema(options, outputFormat) {
|
|
404
|
-
let jsonSchema = options.jsonSchema
|
|
405
|
-
if (jsonSchema
|
|
404
|
+
let jsonSchema = options.jsonSchema ?? null;
|
|
405
|
+
if (typeof jsonSchema === 'string') {
|
|
406
|
+
try {
|
|
407
|
+
jsonSchema = JSON.parse(jsonSchema);
|
|
408
|
+
} catch (error) {
|
|
409
|
+
throw new Error(`--json-schema must be valid JSON: ${error.message}`);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (
|
|
413
|
+
jsonSchema !== null &&
|
|
414
|
+
typeof jsonSchema !== 'boolean' &&
|
|
415
|
+
(typeof jsonSchema !== 'object' || Array.isArray(jsonSchema))
|
|
416
|
+
) {
|
|
417
|
+
throw new Error('--json-schema must be a boolean or JSON Schema object.');
|
|
418
|
+
}
|
|
419
|
+
if (jsonSchema !== null && outputFormat !== 'json') {
|
|
406
420
|
console.warn('Warning: --json-schema requires --output-format json, ignoring schema');
|
|
407
421
|
jsonSchema = null;
|
|
408
422
|
}
|
|
@@ -411,11 +425,13 @@ function resolveJsonSchema(options, outputFormat) {
|
|
|
411
425
|
|
|
412
426
|
function buildProviderOptions(options, runtime, modelSelection) {
|
|
413
427
|
const structuredOutputRecovery = options.structuredOutputRecovery === true;
|
|
428
|
+
const executionContext = resolveTaskExecutionContext();
|
|
414
429
|
return {
|
|
415
430
|
outputFormat: runtime.outputFormat,
|
|
416
431
|
jsonSchema: runtime.jsonSchema,
|
|
417
432
|
cwd: runtime.cwd,
|
|
418
|
-
executionContext
|
|
433
|
+
...codexGitMetadataOption(options, runtime.cwd, executionContext),
|
|
434
|
+
executionContext,
|
|
419
435
|
autoApprove: !structuredOutputRecovery,
|
|
420
436
|
...(modelSelection === undefined ? {} : { modelSpec: modelSelection.modelSpec }),
|
|
421
437
|
...(structuredOutputRecovery ? {} : mcpConfigOption(options)),
|
|
@@ -430,15 +446,35 @@ function buildProviderOptions(options, runtime, modelSelection) {
|
|
|
430
446
|
};
|
|
431
447
|
}
|
|
432
448
|
|
|
433
|
-
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
449
|
+
function codexGitMetadataOption(options, cwd, executionContext) {
|
|
450
|
+
const settings = loadSettings();
|
|
451
|
+
const providerName = normalizeProviderName(
|
|
452
|
+
options.provider || settings.defaultProvider || getDefaultProviderId()
|
|
453
|
+
);
|
|
454
|
+
if (providerName !== 'codex') return {};
|
|
455
|
+
if (executionContext === 'docker' || executionContext === 'benchmark') return {};
|
|
456
|
+
const directories = resolveCodexGitMetadataDirectories(cwd);
|
|
457
|
+
return directories.length === 0 ? {} : { additionalWritableDirectories: directories };
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
export function resolveCodexGitMetadataDirectories(cwd, runGit = execFileSync) {
|
|
461
|
+
try {
|
|
462
|
+
const raw = runGit('git', ['rev-parse', '--git-common-dir'], {
|
|
463
|
+
cwd,
|
|
464
|
+
encoding: 'utf8',
|
|
465
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
466
|
+
});
|
|
467
|
+
const commonDirectory = resolvePath(cwd, raw.trim());
|
|
468
|
+
const fromWorkspace = relative(resolvePath(cwd), commonDirectory);
|
|
469
|
+
const outsideWorkspace =
|
|
470
|
+
isAbsolute(fromWorkspace) ||
|
|
471
|
+
fromWorkspace === '..' ||
|
|
472
|
+
fromWorkspace.startsWith('../') ||
|
|
473
|
+
fromWorkspace.startsWith('..\\');
|
|
474
|
+
return outsideWorkspace ? [commonDirectory] : [];
|
|
475
|
+
} catch {
|
|
476
|
+
return [];
|
|
440
477
|
}
|
|
441
|
-
return context;
|
|
442
478
|
}
|
|
443
479
|
|
|
444
480
|
function claudeSettingsFileOption() {
|
|
@@ -655,14 +691,14 @@ function resolveWatcherScript(options, providerName, invoke) {
|
|
|
655
691
|
function spawnWatcher({ watcherScript, id, cwd, logFile, finalArgs, watcherConfig, rpcPrompt }) {
|
|
656
692
|
const sendsPrompt = typeof rpcPrompt === 'string';
|
|
657
693
|
const watcherEnv = buildWatcherEnv();
|
|
658
|
-
const watcher =
|
|
659
|
-
|
|
660
|
-
[id, cwd, logFile, JSON.stringify(finalArgs), JSON.stringify(watcherConfig)],
|
|
694
|
+
const watcher = spawn(
|
|
695
|
+
process.execPath,
|
|
696
|
+
[watcherScript, id, cwd, logFile, JSON.stringify(finalArgs), JSON.stringify(watcherConfig)],
|
|
661
697
|
{
|
|
662
698
|
detached: true,
|
|
663
|
-
// A prompt-carrying lane needs a
|
|
664
|
-
//
|
|
665
|
-
stdio: sendsPrompt ? ['pipe', 'ignore', 'ignore'
|
|
699
|
+
// A prompt-carrying lane needs only a private stdin pipe; detached watchers have no parent
|
|
700
|
+
// messaging contract, so an IPC channel would add a second, racy wrapper-lifetime owner.
|
|
701
|
+
stdio: sendsPrompt ? ['pipe', 'ignore', 'ignore'] : 'ignore',
|
|
666
702
|
windowsHide: true,
|
|
667
703
|
env: watcherEnv,
|
|
668
704
|
}
|
|
@@ -673,7 +709,6 @@ function spawnWatcher({ watcherScript, id, cwd, logFile, finalArgs, watcherConfi
|
|
|
673
709
|
if (sendsPrompt) sendWatcherPrompt(watcher.stdin, rpcPrompt);
|
|
674
710
|
|
|
675
711
|
watcher.unref();
|
|
676
|
-
watcher.disconnect(); // Close IPC channel so parent can exit
|
|
677
712
|
}
|
|
678
713
|
|
|
679
714
|
export function buildWatcherEnv(sourceEnv = process.env) {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
|
+
const {
|
|
5
|
+
formatTaskLogMarker,
|
|
6
|
+
formatTaskLogStderr,
|
|
7
|
+
formatTaskLogStdout,
|
|
8
|
+
} = require('../src/task-log-line.js');
|
|
9
|
+
|
|
10
|
+
export function markSdkTaskLog(log, timestamp = Date.now()) {
|
|
11
|
+
log(formatTaskLogMarker(timestamp));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function normalizedTerminalEvent(terminal) {
|
|
15
|
+
if (terminal.type === 'result') return terminal.event;
|
|
16
|
+
return {
|
|
17
|
+
type: 'result',
|
|
18
|
+
success: false,
|
|
19
|
+
error: { ...terminal.frame.error },
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function logSdkTerminal(log, result, now = Date.now) {
|
|
24
|
+
for (const frame of result.progress) {
|
|
25
|
+
log(formatTaskLogStdout(now(), JSON.stringify(frame)));
|
|
26
|
+
}
|
|
27
|
+
log(formatTaskLogStdout(now(), JSON.stringify(normalizedTerminalEvent(result.terminal))));
|
|
28
|
+
for (const line of (result.diagnosticStderr || '').replace(/\r/g, '').split('\n')) {
|
|
29
|
+
if (line) log(formatTaskLogStderr(now(), line));
|
|
30
|
+
}
|
|
31
|
+
}
|
package/task-lib/sdk-watcher.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { appendFileSync } from 'fs';
|
|
8
8
|
import { getTask, updateTask } from './store.js';
|
|
9
9
|
import { createCommandSpecCleanup } from './command-spec-cleanup.js';
|
|
10
|
+
import { logSdkTerminal, markSdkTaskLog } from './sdk-watcher-output.js';
|
|
10
11
|
import {
|
|
11
12
|
completePendingWatcherCancellation,
|
|
12
13
|
completeWatcherFailure,
|
|
@@ -72,16 +73,6 @@ function completionFor(result) {
|
|
|
72
73
|
};
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
function logTerminal(result) {
|
|
76
|
-
for (const frame of result.progress) log(`[${Date.now()}]${JSON.stringify(frame)}\n`);
|
|
77
|
-
const terminal =
|
|
78
|
-
result.terminal.type === 'result' ? result.terminal.event : result.terminal.frame;
|
|
79
|
-
log(`[${Date.now()}]${JSON.stringify(terminal)}\n`);
|
|
80
|
-
if (result.diagnosticStderr) {
|
|
81
|
-
log(`[${Date.now()}][SDK-DIAGNOSTIC] ${result.diagnosticStderr}\n`);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
76
|
async function terminateOwnedProviderBoundary() {
|
|
86
77
|
if (terminalResult) return terminalResult.cleanupAttestation.clean === true;
|
|
87
78
|
if (!running) return true;
|
|
@@ -116,6 +107,8 @@ process.on('unhandledRejection', (reason) => {
|
|
|
116
107
|
void crashWithError(reason, 'unhandledRejection');
|
|
117
108
|
});
|
|
118
109
|
|
|
110
|
+
markSdkTaskLog(log);
|
|
111
|
+
|
|
119
112
|
if (
|
|
120
113
|
await completePendingWatcherCancellation({
|
|
121
114
|
taskId,
|
|
@@ -139,7 +132,7 @@ try {
|
|
|
139
132
|
if (getTask(taskId)?.cancelRequested) running.cancel();
|
|
140
133
|
|
|
141
134
|
terminalResult = await running.result;
|
|
142
|
-
|
|
135
|
+
logSdkTerminal(log, terminalResult);
|
|
143
136
|
await completeWatcherTask({
|
|
144
137
|
taskId,
|
|
145
138
|
completion: completionFor(terminalResult),
|
|
@@ -8,6 +8,14 @@ import {
|
|
|
8
8
|
supportsProviderStructuredOutputRecovery,
|
|
9
9
|
} from './provider-helper-runtime.js';
|
|
10
10
|
import { terminateProcess } from './process-termination.js';
|
|
11
|
+
import { createRequire } from 'module';
|
|
12
|
+
|
|
13
|
+
const require = createRequire(import.meta.url);
|
|
14
|
+
const {
|
|
15
|
+
TASK_LOG_STDOUT_PREFIX,
|
|
16
|
+
formatTaskLogMarker,
|
|
17
|
+
formatTaskLogStdout,
|
|
18
|
+
} = require('../src/task-log-line.js');
|
|
11
19
|
|
|
12
20
|
export const COMMAND_CLEANUP_UNINITIALIZED = Symbol('command-cleanup-uninitialized');
|
|
13
21
|
|
|
@@ -69,7 +77,7 @@ function createCodexOutputPassthrough({ log, captureProviderSession }) {
|
|
|
69
77
|
let offset = 0;
|
|
70
78
|
while (offset < text.length) {
|
|
71
79
|
if (atLineStart) {
|
|
72
|
-
logged.push(`[${timestamp}]`);
|
|
80
|
+
logged.push(`[${timestamp}]${TASK_LOG_STDOUT_PREFIX}`);
|
|
73
81
|
atLineStart = false;
|
|
74
82
|
}
|
|
75
83
|
const newline = text.indexOf('\n', offset);
|
|
@@ -128,7 +136,7 @@ function createBoundedLinePassthrough({
|
|
|
128
136
|
}
|
|
129
137
|
if (byteLength > MAX_WATCHER_CONTROL_RECORD_BYTES) {
|
|
130
138
|
if (deferRawUntilOverflow && log) {
|
|
131
|
-
log(`[${lineTimestamp}]${inspectionParts.join('')}${part}`);
|
|
139
|
+
log(`[${lineTimestamp}]${linePrefix}${inspectionParts.join('')}${part}`);
|
|
132
140
|
rawOverflowStreaming = true;
|
|
133
141
|
}
|
|
134
142
|
inspectable = false;
|
|
@@ -310,8 +318,10 @@ export function completeWatcherFailure({ error, source, ...completionOptions })
|
|
|
310
318
|
* frames, prompt text, or control payloads.
|
|
311
319
|
*/
|
|
312
320
|
export function createRpcWatcherOutputRuntime({ log }) {
|
|
321
|
+
log(formatTaskLogMarker(Date.now()));
|
|
322
|
+
|
|
313
323
|
function logEvent(event) {
|
|
314
|
-
log(
|
|
324
|
+
log(formatTaskLogStdout(Date.now(), JSON.stringify(event)));
|
|
315
325
|
}
|
|
316
326
|
|
|
317
327
|
function complete(result) {
|
|
@@ -350,6 +360,7 @@ export function createWatcherOutputRuntime({
|
|
|
350
360
|
let finalResultJson = null;
|
|
351
361
|
let streamingModeError = null;
|
|
352
362
|
let fatalError = null;
|
|
363
|
+
log(formatTaskLogMarker(Date.now()));
|
|
353
364
|
const captureProviderSession = providerSessionCapture?.captureLine || (() => {});
|
|
354
365
|
const codexOutputPassthrough =
|
|
355
366
|
providerName === 'codex' ? createCodexOutputPassthrough({ log, captureProviderSession }) : null;
|
|
@@ -358,6 +369,7 @@ export function createWatcherOutputRuntime({
|
|
|
358
369
|
: createBoundedLinePassthrough({
|
|
359
370
|
log,
|
|
360
371
|
deferRawUntilOverflow: silentJsonMode,
|
|
372
|
+
linePrefix: TASK_LOG_STDOUT_PREFIX,
|
|
361
373
|
handleLine: (line, timestamp, { oversized }) =>
|
|
362
374
|
handleOutputLine(line, timestamp, {
|
|
363
375
|
alreadyLogged: !silentJsonMode,
|
|
@@ -366,19 +378,20 @@ export function createWatcherOutputRuntime({
|
|
|
366
378
|
});
|
|
367
379
|
const stderrPassthrough = createBoundedLinePassthrough({
|
|
368
380
|
log,
|
|
369
|
-
//
|
|
370
|
-
//
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
handleLine: (line, timestamp) => maybeHandleFatalError(line, timestamp),
|
|
381
|
+
// Stderr must never be mistaken for provider protocol output. Fatal detection still receives
|
|
382
|
+
// the raw line through handleLine; only the persisted task-log representation is tagged.
|
|
383
|
+
linePrefix: '[ZEROSHOT][PROVIDER_STDERR] ',
|
|
384
|
+
handleLine: (line, timestamp) => maybeHandleFatalError(line, timestamp, true),
|
|
374
385
|
});
|
|
375
386
|
|
|
376
|
-
function maybeHandleFatalError(line, timestamp) {
|
|
387
|
+
function maybeHandleFatalError(line, timestamp, rawPersisted = false) {
|
|
377
388
|
if (fatalError) return false;
|
|
378
389
|
const detected = detectProviderFatalError(providerName, line);
|
|
379
390
|
if (!detected) return false;
|
|
380
391
|
fatalError = detected;
|
|
381
|
-
if (silentJsonMode)
|
|
392
|
+
if (silentJsonMode && !rawPersisted) {
|
|
393
|
+
log(formatTaskLogStdout(timestamp, line));
|
|
394
|
+
}
|
|
382
395
|
log(`[${timestamp}][ZEROSHOT][FATAL] ${detected}\n`);
|
|
383
396
|
stopProvider(timestamp);
|
|
384
397
|
return true;
|
|
@@ -413,12 +426,12 @@ export function createWatcherOutputRuntime({
|
|
|
413
426
|
if (silentJsonMode && !line.trim()) return;
|
|
414
427
|
// Pi reserves stdout for JSON lifecycle events. Error text inside an assistant message may be
|
|
415
428
|
// followed by an automatic retry, so only Pi stderr can prove a pre-agent startup failure.
|
|
416
|
-
if (providerName !== 'pi') maybeHandleFatalError(line, timestamp);
|
|
429
|
+
if (providerName !== 'pi') maybeHandleFatalError(line, timestamp, alreadyLogged);
|
|
417
430
|
if (captureStreamingError(line, timestamp)) return;
|
|
418
431
|
if (silentJsonMode) {
|
|
419
432
|
maybeCaptureStructuredOutput(line);
|
|
420
433
|
} else if (!alreadyLogged) {
|
|
421
|
-
log(
|
|
434
|
+
log(formatTaskLogStdout(timestamp, line));
|
|
422
435
|
}
|
|
423
436
|
}
|
|
424
437
|
|
|
@@ -444,11 +457,10 @@ export function createWatcherOutputRuntime({
|
|
|
444
457
|
if (silentJsonMode) {
|
|
445
458
|
finalResultJson = recoveredLine;
|
|
446
459
|
} else {
|
|
447
|
-
log(
|
|
460
|
+
log(formatTaskLogStdout(timestamp, recoveredLine));
|
|
448
461
|
}
|
|
449
462
|
} else if (streamingModeError.line) {
|
|
450
|
-
|
|
451
|
-
log(`${prefix}${streamingModeError.line}\n`);
|
|
463
|
+
log(formatTaskLogStdout(streamingModeError.timestamp, streamingModeError.line));
|
|
452
464
|
}
|
|
453
465
|
return recovered;
|
|
454
466
|
}
|
|
@@ -463,7 +475,9 @@ export function createWatcherOutputRuntime({
|
|
|
463
475
|
if (stderrBuffer !== null) stderrPassthrough.flush();
|
|
464
476
|
const recovered = attemptRecovery(code, timestamp);
|
|
465
477
|
const sessionIdentityError = providerSessionCapture?.getCompletionError() || null;
|
|
466
|
-
if (silentJsonMode && finalResultJson)
|
|
478
|
+
if (silentJsonMode && finalResultJson) {
|
|
479
|
+
log(formatTaskLogStdout(timestamp, finalResultJson));
|
|
480
|
+
}
|
|
467
481
|
if (config.outputFormat !== 'json') {
|
|
468
482
|
log(`\n${'='.repeat(50)}\n`);
|
|
469
483
|
log(`Finished: ${new Date().toISOString()}\n`);
|