@the-open-engine/zeroshot 6.34.0 → 6.34.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.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@the-open-engine/zeroshot",
3
- "version": "6.34.0",
3
+ "version": "6.34.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@the-open-engine/zeroshot",
9
- "version": "6.34.0",
9
+ "version": "6.34.1",
10
10
  "hasInstallScript": true,
11
11
  "license": "MIT",
12
12
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@the-open-engine/zeroshot",
3
- "version": "6.34.0",
3
+ "version": "6.34.1",
4
4
  "description": "Independent executor–verifier orchestration for software changes.",
5
5
  "main": "src/orchestrator.js",
6
6
  "bin": {
@@ -11,8 +11,10 @@
11
11
  */
12
12
 
13
13
  const { spawn, spawnSync } = require('child_process');
14
+ const { createHash } = require('crypto');
14
15
  const path = require('path');
15
16
  const fs = require('fs');
17
+ const { StringDecoder } = require('string_decoder');
16
18
  const { getNestedExecutionRegistry, TaskExecutionHandle } = require('./task-execution-handle');
17
19
  const os = require('os');
18
20
  const { parseProviderChunk, getProvider } = require('../providers');
@@ -57,6 +59,8 @@ const {
57
59
  isStructuredOutputInvalidError,
58
60
  } = require('./structured-output-error');
59
61
  const TASK_TERMINAL_STATUSES = new Set(['completed', 'failed', 'killed', 'stale']);
62
+ const MAX_CONTROL_PLANE_RECORD_BYTES = 1024 * 1024;
63
+ const LOG_READ_CHUNK_BYTES = 64 * 1024;
60
64
  function runCommandWithTimeout(command, args, options = {}, callback = null) {
61
65
  const timeout = options.timeout ?? 30000;
62
66
  if (timeout <= 0) {
@@ -1225,11 +1229,20 @@ function createLogFollowState() {
1225
1229
  pollInterval: null,
1226
1230
  statusCheckInterval: null,
1227
1231
  resolved: false,
1228
- lineBuffer: '',
1232
+ lineBuffer: createLogRecordBuffer(),
1233
+ logDecoder: new StringDecoder('utf8'),
1229
1234
  consecutiveExecFailures: 0,
1230
1235
  };
1231
1236
  }
1232
1237
 
1238
+ function createLogRecordBuffer() {
1239
+ return {
1240
+ byteLength: 0,
1241
+ fragments: [],
1242
+ oversized: null,
1243
+ };
1244
+ }
1245
+
1233
1246
  function lookupLogFilePath(ctPath, taskId) {
1234
1247
  try {
1235
1248
  return runCommandSync(ctPath, ['get-log-path', taskId], {
@@ -1310,15 +1323,82 @@ function broadcastAgentLine({ agent, providerName, state, line }) {
1310
1323
  });
1311
1324
  }
1312
1325
 
1313
- function appendContentToBuffer(state, content, onLine) {
1314
- state.lineBuffer += content;
1315
- const lines = state.lineBuffer.split('\n');
1326
+ function appendLogRecordFragment(buffer, fragment) {
1327
+ const fragmentBytes = Buffer.byteLength(fragment);
1328
+ buffer.byteLength += fragmentBytes;
1329
+ if (buffer.oversized) {
1330
+ buffer.oversized.digest.update(fragment);
1331
+ return;
1332
+ }
1333
+ if (buffer.byteLength <= MAX_CONTROL_PLANE_RECORD_BYTES) {
1334
+ buffer.fragments.push(fragment);
1335
+ return;
1336
+ }
1316
1337
 
1317
- for (let i = 0; i < lines.length - 1; i++) {
1318
- onLine(lines[i]);
1338
+ const retainedPrefix = buffer.fragments.join('');
1339
+ const prefixProbe = `${retainedPrefix}${fragment.slice(0, Math.max(0, 32 - retainedPrefix.length))}`;
1340
+ const timestampPrefix = prefixProbe.match(/^\[\d{13}\]/)?.[0] || '';
1341
+ const digest = createHash('sha256');
1342
+ for (const retained of buffer.fragments) digest.update(retained);
1343
+ digest.update(fragment);
1344
+ buffer.fragments = [];
1345
+ buffer.oversized = { digest, timestampPrefix };
1346
+ }
1347
+
1348
+ function completeLogRecord(buffer, onLine, skipEmpty = false) {
1349
+ let line;
1350
+ if (buffer.oversized) {
1351
+ const digest = buffer.oversized.digest.digest('hex');
1352
+ line =
1353
+ `${buffer.oversized.timestampPrefix}[ZEROSHOT] Provider output record retained in task log ` +
1354
+ `but omitted from the control plane (byte_length=${buffer.byteLength}, sha256=${digest})`;
1355
+ } else {
1356
+ line = buffer.fragments.join('');
1319
1357
  }
1358
+ buffer.byteLength = 0;
1359
+ buffer.fragments = [];
1360
+ buffer.oversized = null;
1361
+ if (!skipEmpty || line.trim()) onLine(line);
1362
+ }
1320
1363
 
1321
- state.lineBuffer = lines[lines.length - 1];
1364
+ function appendContentToBuffer(state, content, onLine, skipEmpty = false) {
1365
+ let offset = 0;
1366
+ while (offset < content.length) {
1367
+ const newline = content.indexOf('\n', offset);
1368
+ if (newline === -1) {
1369
+ appendLogRecordFragment(state.lineBuffer, content.slice(offset));
1370
+ return;
1371
+ }
1372
+ appendLogRecordFragment(state.lineBuffer, content.slice(offset, newline));
1373
+ completeLogRecord(state.lineBuffer, onLine, skipEmpty);
1374
+ offset = newline + 1;
1375
+ }
1376
+ }
1377
+
1378
+ function replayCompleteLogContent(content, onLine) {
1379
+ const replayState = { lineBuffer: createLogRecordBuffer() };
1380
+ appendContentToBuffer(replayState, content, onLine, true);
1381
+ if (replayState.lineBuffer.byteLength > 0) {
1382
+ completeLogRecord(replayState.lineBuffer, onLine, true);
1383
+ }
1384
+ }
1385
+
1386
+ function readLogFileDelta({ fsModule, logFilePath, state, currentSize, onNewContent }) {
1387
+ const fd = fsModule.openSync(logFilePath, 'r');
1388
+ try {
1389
+ let offset = state.lastSize;
1390
+ const buffer = Buffer.allocUnsafe(LOG_READ_CHUNK_BYTES);
1391
+ while (offset < currentSize) {
1392
+ const requested = Math.min(buffer.length, currentSize - offset);
1393
+ const bytesRead = fsModule.readSync(fd, buffer, 0, requested, offset);
1394
+ if (bytesRead === 0) break;
1395
+ onNewContent(state.logDecoder.write(buffer.subarray(0, bytesRead)));
1396
+ offset += bytesRead;
1397
+ }
1398
+ state.lastSize = offset;
1399
+ } finally {
1400
+ fsModule.closeSync(fd);
1401
+ }
1322
1402
  }
1323
1403
 
1324
1404
  function pollLogFileForUpdates({ agent, fsModule, ctPath, taskId, state, onNewContent }) {
@@ -1340,13 +1420,13 @@ function pollLogFileForUpdates({ agent, fsModule, ctPath, taskId, state, onNewCo
1340
1420
  const currentSize = stats.size;
1341
1421
 
1342
1422
  if (currentSize > state.lastSize) {
1343
- const fd = fsModule.openSync(state.logFilePath, 'r');
1344
- const buffer = Buffer.alloc(currentSize - state.lastSize);
1345
- fsModule.readSync(fd, buffer, 0, buffer.length, state.lastSize);
1346
- fsModule.closeSync(fd);
1347
-
1348
- onNewContent(buffer.toString('utf-8'));
1349
- state.lastSize = currentSize;
1423
+ readLogFileDelta({
1424
+ fsModule,
1425
+ logFilePath: state.logFilePath,
1426
+ state,
1427
+ currentSize,
1428
+ onNewContent,
1429
+ });
1350
1430
  }
1351
1431
  } catch (err) {
1352
1432
  const error = /** @type {Error} */ (err);
@@ -2215,7 +2295,8 @@ function createIsolatedLogState(skipStructuredResultCheck = false, nested = fals
2215
2295
  tailProcess: null,
2216
2296
  statusCheckInterval: null,
2217
2297
  timeoutTimer: null,
2218
- lineBuffer: '',
2298
+ lineBuffer: createLogRecordBuffer(),
2299
+ tailDecoder: new StringDecoder('utf8'),
2219
2300
  skipStructuredResultCheck,
2220
2301
  nested,
2221
2302
  };
@@ -2376,9 +2457,7 @@ function settleIsolatedTerminalStatus({
2376
2457
 
2377
2458
  if (finalReadResult.code === 0 && finalReadResult.stdout) {
2378
2459
  state.fullOutput = finalReadResult.stdout;
2379
- for (const line of state.fullOutput.split('\n')) {
2380
- if (line.trim()) onLine(line);
2381
- }
2460
+ replayCompleteLogContent(state.fullOutput, onLine);
2382
2461
  }
2383
2462
 
2384
2463
  const vertexModelError =
@@ -2566,16 +2645,14 @@ function broadcastIsolatedLine({ agent, providerName, taskId, state, line }) {
2566
2645
  }
2567
2646
 
2568
2647
  function appendIsolatedContent(state, content, onLine) {
2569
- state.lineBuffer += content;
2570
- const lines = state.lineBuffer.split('\n');
2571
-
2572
- for (let i = 0; i < lines.length - 1; i++) {
2573
- if (lines[i].trim()) {
2574
- onLine(lines[i]);
2575
- }
2576
- }
2648
+ appendContentToBuffer(state, content, onLine, true);
2649
+ }
2577
2650
 
2578
- state.lineBuffer = lines[lines.length - 1];
2651
+ function consumeIsolatedTailChunk(state, data, onLine) {
2652
+ const chunk = typeof data === 'string' ? data : state.tailDecoder.write(data);
2653
+ if (!chunk) return;
2654
+ state.fullOutput += chunk;
2655
+ appendIsolatedContent(state, chunk, onLine);
2579
2656
  }
2580
2657
 
2581
2658
  function startIsolatedTail({ agent, manager, clusterId, logFilePath, state, onLine }) {
@@ -2586,9 +2663,7 @@ function startIsolatedTail({ agent, manager, clusterId, logFilePath, state, onLi
2586
2663
  ]);
2587
2664
 
2588
2665
  state.tailProcess.stdout.on('data', (data) => {
2589
- const chunk = data.toString();
2590
- state.fullOutput += chunk;
2591
- appendIsolatedContent(state, chunk, onLine);
2666
+ consumeIsolatedTailChunk(state, data, onLine);
2592
2667
  });
2593
2668
 
2594
2669
  state.tailProcess.stderr.on('data', (data) => {
@@ -2599,6 +2674,7 @@ function startIsolatedTail({ agent, manager, clusterId, logFilePath, state, onLi
2599
2674
  });
2600
2675
 
2601
2676
  state.tailProcess.on('close', (exitCode) => {
2677
+ consumeIsolatedTailChunk(state, state.tailDecoder.end(), onLine);
2602
2678
  if (!state.taskExited) {
2603
2679
  agent._log(`[${agent.id}] tail process exited with code ${exitCode}`);
2604
2680
  }
@@ -3091,4 +3167,7 @@ module.exports = {
3091
3167
  buildTaskRunArgs,
3092
3168
  rebuildProviderSessionAfterCommit,
3093
3169
  killTask,
3170
+ createLogRecordBuffer,
3171
+ appendContentToBuffer,
3172
+ consumeIsolatedTailChunk,
3094
3173
  };
@@ -1,4 +1,5 @@
1
1
  import { spawn } from 'child_process';
2
+ import { StringDecoder } from 'string_decoder';
2
3
  import {
3
4
  detectProviderFatalError,
4
5
  detectProviderStreamingModeError,
@@ -9,6 +10,8 @@ import { terminateProcess } from './process-termination.js';
9
10
 
10
11
  export const COMMAND_CLEANUP_UNINITIALIZED = Symbol('command-cleanup-uninitialized');
11
12
 
13
+ const MAX_CODEX_CONTROL_RECORD_BYTES = 64 * 1024;
14
+
12
15
  export function spawnWatcherProvider(command, finalArgs, options) {
13
16
  return spawn(command, finalArgs, {
14
17
  ...options,
@@ -38,6 +41,72 @@ function splitBufferLines(buffer, chunk) {
38
41
  return { lines: lines.slice(0, -1), remaining: lines.at(-1) || '' };
39
42
  }
40
43
 
44
+ function createCodexOutputPassthrough({ log, captureProviderSession }) {
45
+ const decoder = new StringDecoder('utf8');
46
+ let atLineStart = true;
47
+ let inspectable = true;
48
+ let inspectionBytes = 0;
49
+ let inspectionParts = [];
50
+
51
+ function inspectPart(part) {
52
+ if (!inspectable || !part) return;
53
+ inspectionBytes += Buffer.byteLength(part);
54
+ if (inspectionBytes > MAX_CODEX_CONTROL_RECORD_BYTES) {
55
+ inspectable = false;
56
+ inspectionParts = [];
57
+ return;
58
+ }
59
+ inspectionParts.push(part);
60
+ }
61
+
62
+ function finishLine() {
63
+ if (inspectable) captureProviderSession(inspectionParts.join(''));
64
+ atLineStart = true;
65
+ inspectable = true;
66
+ inspectionBytes = 0;
67
+ inspectionParts = [];
68
+ }
69
+
70
+ function writeText(text, timestamp) {
71
+ if (!text) return;
72
+ const logged = [];
73
+ let offset = 0;
74
+ while (offset < text.length) {
75
+ if (atLineStart) {
76
+ logged.push(`[${timestamp}]`);
77
+ atLineStart = false;
78
+ }
79
+ const newline = text.indexOf('\n', offset);
80
+ if (newline === -1) {
81
+ const part = text.slice(offset);
82
+ inspectPart(part);
83
+ logged.push(part);
84
+ break;
85
+ }
86
+ const part = text.slice(offset, newline);
87
+ inspectPart(part);
88
+ logged.push(part, '\n');
89
+ finishLine();
90
+ offset = newline + 1;
91
+ }
92
+ log(logged.join(''));
93
+ }
94
+
95
+ return {
96
+ consume(chunk) {
97
+ const text = typeof chunk === 'string' ? chunk : decoder.write(chunk);
98
+ writeText(text, Date.now());
99
+ },
100
+ flush() {
101
+ writeText(decoder.end(), Date.now());
102
+ if (!atLineStart) {
103
+ finishLine();
104
+ log('\n');
105
+ }
106
+ },
107
+ };
108
+ }
109
+
41
110
  export function resolveWatcherCommand(config, commandSpec, fallbackArgs, normalizeProviderName) {
42
111
  return {
43
112
  providerName: normalizeProviderName(config.provider || 'claude'),
@@ -189,6 +258,8 @@ export function createWatcherOutputRuntime({
189
258
  let streamingModeError = null;
190
259
  let fatalError = null;
191
260
  const captureProviderSession = providerSessionCapture?.captureLine || (() => {});
261
+ const codexOutputPassthrough =
262
+ providerName === 'codex' ? createCodexOutputPassthrough({ log, captureProviderSession }) : null;
192
263
 
193
264
  function maybeHandleFatalError(line, timestamp) {
194
265
  if (fatalError) return false;
@@ -230,6 +301,10 @@ export function createWatcherOutputRuntime({
230
301
  }
231
302
 
232
303
  function consumeOutput(buffer, chunk) {
304
+ if (codexOutputPassthrough) {
305
+ codexOutputPassthrough.consume(chunk);
306
+ return '';
307
+ }
233
308
  const timestamp = Date.now();
234
309
  const { lines, remaining } = splitBufferLines(buffer, chunk.toString());
235
310
  for (const line of lines) handleOutputLine(line, timestamp);
@@ -284,7 +359,11 @@ export function createWatcherOutputRuntime({
284
359
 
285
360
  function complete({ code, signal, outputBuffer, stderrBuffer = null }) {
286
361
  const timestamp = Date.now();
287
- flushOutput(outputBuffer, timestamp);
362
+ if (codexOutputPassthrough) {
363
+ codexOutputPassthrough.flush();
364
+ } else {
365
+ flushOutput(outputBuffer, timestamp);
366
+ }
288
367
  if (stderrBuffer !== null) flushStderr(stderrBuffer, timestamp);
289
368
  const recovered = attemptRecovery(code, timestamp);
290
369
  const sessionIdentityError = providerSessionCapture?.getCompletionError() || null;