@probelabs/probe 0.6.0-rc331 → 0.6.0-rc332

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.
Files changed (43) hide show
  1. package/bin/binaries/{probe-v0.6.0-rc331-aarch64-apple-darwin.tar.gz → probe-v0.6.0-rc332-aarch64-apple-darwin.tar.gz} +0 -0
  2. package/bin/binaries/{probe-v0.6.0-rc331-aarch64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc332-aarch64-unknown-linux-musl.tar.gz} +0 -0
  3. package/bin/binaries/{probe-v0.6.0-rc331-x86_64-apple-darwin.tar.gz → probe-v0.6.0-rc332-x86_64-apple-darwin.tar.gz} +0 -0
  4. package/bin/binaries/{probe-v0.6.0-rc331-x86_64-pc-windows-msvc.zip → probe-v0.6.0-rc332-x86_64-pc-windows-msvc.zip} +0 -0
  5. package/bin/binaries/{probe-v0.6.0-rc331-x86_64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc332-x86_64-unknown-linux-musl.tar.gz} +0 -0
  6. package/build/agent/ProbeAgent.d.ts +105 -4
  7. package/build/agent/ProbeAgent.js +209 -12
  8. package/build/agent/bashExecutor.js +36 -101
  9. package/build/agent/engines/codex.js +367 -88
  10. package/build/agent/engines/governed-answer-failure.js +152 -0
  11. package/build/agent/engines/governed-codex-profile.js +198 -0
  12. package/build/agent/governance/acknowledgedJsonlChannel.js +328 -0
  13. package/build/agent/governance/atomicTerminalReceipt.js +188 -0
  14. package/build/agent/governance/index.d.ts +130 -0
  15. package/build/agent/governance/index.js +8 -0
  16. package/build/agent/mcp/built-in-server.js +152 -53
  17. package/build/agent/mcp/index.d.ts +65 -0
  18. package/build/agent/mcp/index.js +6 -1
  19. package/build/agent/probeTool.js +1 -1
  20. package/build/agent/processSupervisor.js +351 -0
  21. package/build/agent/tools.js +14 -8
  22. package/build/index.js +2 -0
  23. package/cjs/agent/ProbeAgent.cjs +13238 -11968
  24. package/cjs/index.cjs +75955 -74126
  25. package/index.d.ts +149 -4
  26. package/package.json +6 -2
  27. package/src/agent/ProbeAgent.d.ts +105 -4
  28. package/src/agent/ProbeAgent.js +209 -12
  29. package/src/agent/bashExecutor.js +36 -101
  30. package/src/agent/engines/codex.js +367 -88
  31. package/src/agent/engines/governed-answer-failure.js +152 -0
  32. package/src/agent/engines/governed-codex-profile.js +198 -0
  33. package/src/agent/governance/acknowledgedJsonlChannel.js +328 -0
  34. package/src/agent/governance/atomicTerminalReceipt.js +188 -0
  35. package/src/agent/governance/index.d.ts +130 -0
  36. package/src/agent/governance/index.js +8 -0
  37. package/src/agent/mcp/built-in-server.js +152 -53
  38. package/src/agent/mcp/index.d.ts +65 -0
  39. package/src/agent/mcp/index.js +6 -1
  40. package/src/agent/probeTool.js +1 -1
  41. package/src/agent/processSupervisor.js +351 -0
  42. package/src/agent/tools.js +14 -8
  43. package/src/index.js +2 -0
@@ -3,10 +3,10 @@
3
3
  * @module agent/bashExecutor
4
4
  */
5
5
 
6
- import { spawn } from 'child_process';
7
- import { resolve, join } from 'path';
6
+ import { resolve } from 'path';
8
7
  import { existsSync } from 'fs';
9
8
  import { parseCommandForExecution, isComplexCommand } from './bashCommandUtils.js';
9
+ import { spawnGovernedProcess } from './processSupervisor.js';
10
10
 
11
11
  // ─── Interactive Command Detection ─────────────────────────────────────────
12
12
 
@@ -261,7 +261,7 @@ export async function executeBashCommand(command, options = {}) {
261
261
  console.log(`[BashExecutor] Timeout: ${timeout}ms`);
262
262
  }
263
263
 
264
- return new Promise((resolve, reject) => {
264
+ return new Promise((resolve) => {
265
265
  // Create environment with non-interactive safety defaults.
266
266
  // These prevent commands from opening editors or TTY prompts
267
267
  // when stdin is not available (which would cause hangs).
@@ -276,14 +276,13 @@ export async function executeBashCommand(command, options = {}) {
276
276
  // Check if this is a complex command (contains pipes, operators, etc.)
277
277
  const isComplex = isComplexCommand(command);
278
278
 
279
- let cmd, cmdArgs, useShell;
279
+ let cmd, cmdArgs;
280
280
 
281
281
  if (isComplex) {
282
282
  // For complex commands, use sh -c to execute through shell
283
283
  // This is only reached if the permission checker allowed the complex command
284
284
  cmd = 'sh';
285
285
  cmdArgs = ['-c', command];
286
- useShell = false; // We explicitly use sh -c, not spawn's shell option
287
286
  if (debug) {
288
287
  console.log(`[BashExecutor] Complex command - using sh -c`);
289
288
  }
@@ -304,7 +303,6 @@ export async function executeBashCommand(command, options = {}) {
304
303
  return;
305
304
  }
306
305
  [cmd, ...cmdArgs] = args;
307
- useShell = false;
308
306
  }
309
307
 
310
308
  // Spawn the process in a new session (detached: true → setsid on Linux).
@@ -312,83 +310,42 @@ export async function executeBashCommand(command, options = {}) {
312
310
  // /dev/tty unavailable. Any program that tries to open an interactive
313
311
  // editor or TTY prompt (e.g. vim from git rebase) will get ENXIO and
314
312
  // fail immediately instead of hanging forever.
315
- const child = spawn(cmd, cmdArgs, {
313
+ const governed = spawnGovernedProcess({
314
+ command: cmd,
315
+ args: cmdArgs,
316
316
  cwd,
317
317
  env: processEnv,
318
- stdio: ['ignore', 'pipe', 'pipe'], // stdin ignored, capture stdout/stderr
319
- shell: useShell, // false for security
320
- detached: true, // new session — no controlling terminal
321
- windowsHide: true
318
+ executionTimeoutMs: timeout,
319
+ terminationGraceMs: 5000,
320
+ cleanupTimeoutMs: 10000,
321
+ stdoutByteCap: maxBuffer,
322
+ stderrByteCap: maxBuffer,
323
+ signalScope: 'process-group'
322
324
  });
323
-
324
- let stdout = '';
325
- let stderr = '';
326
- let killed = false;
327
- let timeoutHandle;
328
-
329
- // Helper: kill the entire process group (negative PID) so that
330
- // sub-processes spawned by the command (e.g. an editor) are also killed.
331
- // Falls back to killing just the child if process.kill fails.
332
- const killProcessGroup = (signal) => {
333
- try {
334
- if (child.pid) process.kill(-child.pid, signal);
335
- } catch {
336
- try { child.kill(signal); } catch { /* already dead */ }
337
- }
338
- };
339
-
340
- // Set timeout
341
- if (timeout > 0) {
342
- timeoutHandle = setTimeout(() => {
343
- if (!killed) {
344
- killed = true;
345
- killProcessGroup('SIGTERM');
346
-
347
- // Force kill after 5 seconds if still running
348
- setTimeout(() => {
349
- if (child.exitCode === null) {
350
- killProcessGroup('SIGKILL');
351
- }
352
- }, 5000);
353
- }
354
- }, timeout);
355
- }
356
-
357
- // Handle stdout
358
- child.stdout.on('data', (data) => {
359
- const chunk = data.toString();
360
- if (stdout.length + chunk.length <= maxBuffer) {
361
- stdout += chunk;
362
- } else {
363
- // Buffer overflow
364
- if (!killed) {
365
- killed = true;
366
- killProcessGroup('SIGTERM');
367
- }
368
- }
369
- });
370
-
371
- // Handle stderr
372
- child.stderr.on('data', (data) => {
373
- const chunk = data.toString();
374
- if (stderr.length + chunk.length <= maxBuffer) {
375
- stderr += chunk;
376
- } else {
377
- // Buffer overflow
378
- if (!killed) {
379
- killed = true;
380
- killProcessGroup('SIGTERM');
325
+ governed.result.then(receipt => {
326
+ const duration = Date.now() - startTime;
327
+ if (receipt.classification === 'spawn_error') {
328
+ if (debug) {
329
+ console.log(`[BashExecutor] Spawn error: ${receipt.error ?? 'spawn failed'}`);
381
330
  }
382
- }
383
- });
384
-
385
- // Handle process exit
386
- child.on('close', (code, signal) => {
387
- if (timeoutHandle) {
388
- clearTimeout(timeoutHandle);
331
+ resolve({
332
+ success: false,
333
+ error: `Failed to execute command: ${receipt.error ?? 'spawn failed'}`,
334
+ stdout: '',
335
+ stderr: '',
336
+ exitCode: 1,
337
+ command,
338
+ workingDirectory: cwd,
339
+ duration
340
+ });
341
+ return;
389
342
  }
390
343
 
391
- const duration = Date.now() - startTime;
344
+ const stdout = receipt.stdout;
345
+ const stderr = receipt.stderr;
346
+ const code = receipt.exitCode;
347
+ const signal = receipt.signal;
348
+ const killed = ['execution_timeout', 'output_overflow', 'terminated', 'aborted', 'cleanup_timeout'].includes(receipt.classification);
392
349
 
393
350
  if (debug) {
394
351
  console.log(`[BashExecutor] Command completed - Code: ${code}, Signal: ${signal}, Duration: ${duration}ms`);
@@ -400,7 +357,7 @@ export async function executeBashCommand(command, options = {}) {
400
357
 
401
358
  if (killed) {
402
359
  success = false;
403
- if (stdout.length + stderr.length > maxBuffer) {
360
+ if (receipt.classification === 'output_overflow') {
404
361
  error = `Command output exceeded maximum buffer size (${maxBuffer} bytes)`;
405
362
  } else {
406
363
  error = `Command timed out after ${timeout}ms`;
@@ -423,28 +380,6 @@ export async function executeBashCommand(command, options = {}) {
423
380
  killed
424
381
  });
425
382
  });
426
-
427
- // Handle spawn errors
428
- child.on('error', (error) => {
429
- if (timeoutHandle) {
430
- clearTimeout(timeoutHandle);
431
- }
432
-
433
- if (debug) {
434
- console.log(`[BashExecutor] Spawn error:`, error);
435
- }
436
-
437
- resolve({
438
- success: false,
439
- error: `Failed to execute command: ${error.message}`,
440
- stdout: '',
441
- stderr: '',
442
- exitCode: 1,
443
- command,
444
- workingDirectory: cwd,
445
- duration: Date.now() - startTime
446
- });
447
- });
448
383
  });
449
384
  }
450
385
 
@@ -557,4 +492,4 @@ export function validateExecutionOptions(options = {}) {
557
492
  errors,
558
493
  warnings
559
494
  };
560
- }
495
+ }