@codeworksh/harness 0.3.0-dev.20261019181702 → 0.4.0-canary.50.1.g9fe7a616

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/effect.mjs CHANGED
@@ -6450,8 +6450,10 @@ const windowBytes = (limits) => limits.maxBytes * 2;
6450
6450
  */
6451
6451
  const script = (command, file, limits, pipeline, report) => [
6452
6452
  `f=${(0, shell_exports.quote)(file)}`,
6453
+ `c=${(0, shell_exports.quote)(command)}`,
6454
+ "if command -v bash >/dev/null 2>&1; then s=bash; else s=sh; fi",
6453
6455
  "run() (",
6454
- command,
6456
+ " if [ \"$s\" = bash ]; then bash -c \"$c\"; else eval \"$c\"; fi",
6455
6457
  ")",
6456
6458
  `if mkdir -p ${(0, shell_exports.quote)(posix.dirname(file))} 2>/dev/null && (umask 077 2>/dev/null; set -C && : > "$f" && : > "$f.rc" && : > "$f.pid") 2>/dev/null; then`,
6457
6459
  " echo \"$$ $(ps -o pgid= -p $$ 2>/dev/null)\" > \"$f.pid\"",
@@ -6468,18 +6470,19 @@ const script = (command, file, limits, pipeline, report) => [
6468
6470
  `printf '%s\\n' ${(0, shell_exports.quote)(unsaved(file))}`,
6469
6471
  "run 2>&1"
6470
6472
  ].join("\n");
6471
- const header = new RegExp(`^${HEADER} (\\d+) (\\d+) ([01])(?: (\\d+))?$`, "m");
6473
+ const header = new RegExp(`^${HEADER} (\\d+) (\\d+) ([01]) (bash|sh)(?: (\\d+))?$`, "m");
6472
6474
  const parse$4 = (match) => ({
6473
6475
  bytes: Number(match[1]),
6474
6476
  newlines: Number(match[2]),
6475
- kept: match[3] === "1"
6477
+ kept: match[3] === "1",
6478
+ shell: match[4] === "sh" ? "sh" : "bash"
6476
6479
  });
6477
6480
  /**
6478
6481
  * For a backend that streams: all output still flows back as it is produced, and
6479
6482
  * a copy lands in the file. The report rides on stderr, the wrapper's own channel
6480
6483
  * since the command's is folded into stdout.
6481
6484
  */
6482
- const streaming = (command, file, limits) => script(command, file, limits, (source) => `${source} | tee -a "$f"`, [`printf '${HEADER} %s %s %s\\n' "$b" "$n" "$keep" >&2`]);
6485
+ const streaming = (command, file, limits) => script(command, file, limits, (source) => `${source} | tee -a "$f"`, [`printf '${HEADER} %s %s %s %s\\n' "$b" "$n" "$keep" "$s" >&2`]);
6483
6486
  /** Read {@link streaming}'s stderr: the report, if it got that far, and anything else the wrapper said. */
6484
6487
  const report = (stderr) => {
6485
6488
  const match = header.exec(stderr);
@@ -6501,7 +6504,7 @@ const buffered = (command, file, limits) => {
6501
6504
  const tail = `tail -n ${limits.maxLines} "$f" | tail -c ${windowBytes(limits)}`;
6502
6505
  return script(command, file, limits, (source) => `{ ${source} | cat; } >> "$f"`, [
6503
6506
  `w=$(${tail} | wc -c | awk '{ print $1 }')`,
6504
- `printf '${HEADER} %s %s %s %s\\n' "$b" "$n" "$keep" "$w"`,
6507
+ `printf '${HEADER} %s %s %s %s %s\\n' "$b" "$n" "$keep" "$s" "$w"`,
6505
6508
  tail
6506
6509
  ]);
6507
6510
  };
@@ -6509,11 +6512,11 @@ const buffered = (command, file, limits) => {
6509
6512
  const window = (stdout) => {
6510
6513
  const newline = stdout.indexOf("\n");
6511
6514
  const match = header.exec(newline === -1 ? stdout : stdout.slice(0, newline));
6512
- if (match === null || match[4] === void 0) return void 0;
6515
+ if (match === null || match[5] === void 0) return void 0;
6513
6516
  return {
6514
6517
  ...parse$4(match),
6515
6518
  text: stdout.slice(newline + 1),
6516
- textBytes: Number(match[4])
6519
+ textBytes: Number(match[5])
6517
6520
  };
6518
6521
  };
6519
6522
  /**
@@ -6661,7 +6664,9 @@ const BashSuccess = Schema.Struct({
6661
6664
  /** Non-zero exit — expected, model-visible. Carries the same shape as success. */
6662
6665
  var BashFailed = class extends Schema.TaggedError()("BashFailed", {
6663
6666
  ...outputFields,
6664
- exitCode: Schema.Finite
6667
+ exitCode: Schema.Finite,
6668
+ /** The shell that ran the command, when the sandbox reported it. */
6669
+ shell: Schema.optional(Schema.Literals(["bash", "sh"]))
6665
6670
  }) {};
6666
6671
  /** Deadline exceeded — expected, model-visible. Carries the partial output produced so far. */
6667
6672
  var BashTimedOut = class extends Schema.TaggedError()("BashTimedOut", {
@@ -6671,7 +6676,7 @@ var BashTimedOut = class extends Schema.TaggedError()("BashTimedOut", {
6671
6676
  const BashFailure = Schema.Union([BashFailed, BashTimedOut]);
6672
6677
  /** The reason for a failure, after any output: the model sees nothing else of `details`. */
6673
6678
  const withStatus = (failure) => {
6674
- const status = failure._tag === "BashTimedOut" ? `Command timed out after ${failure.timeoutSeconds} seconds` : failure.exitCode === -1 ? "Command terminated without an exit code" : `Command exited with code ${failure.exitCode}`;
6679
+ const status = failure._tag === "BashTimedOut" ? `Command timed out after ${failure.timeoutSeconds} seconds` : failure.exitCode === -1 ? "Command terminated without an exit code" : `Command exited with code ${failure.exitCode}${failure.shell === "sh" ? " (ran under sh: bash is not on PATH in this sandbox)" : ""}`;
6675
6680
  return failure.output ? `${failure.output.replace(/\n$/, "")}\n\n${status}` : status;
6676
6681
  };
6677
6682
  const bashDef = tool_exports.define({
@@ -6725,6 +6730,7 @@ const present = (snap, lastLineBytes, saved) => {
6725
6730
  };
6726
6731
  };
6727
6732
  const utf8 = new TextEncoder();
6733
+ const shellOf = (report) => report !== void 0 ? { shell: report.shell } : {};
6728
6734
  /**
6729
6735
  * A command cut off by its deadline never reached the wrapper's own cleanup: kill
6730
6736
  * what is left of it and remove its side files, keeping the output file only when
@@ -6758,7 +6764,8 @@ const runBuffered = (shell, params, file) => Effect.gen(function* () {
6758
6764
  const presented = present(acc.snapshot(), acc.getLastLineBytes(), window$1?.kept === true ? file : void 0);
6759
6765
  if (result.exitCode !== 0) return yield* new BashFailed({
6760
6766
  exitCode: result.exitCode,
6761
- ...presented
6767
+ ...presented,
6768
+ ...shellOf(window$1)
6762
6769
  });
6763
6770
  return {
6764
6771
  exitCode: result.exitCode,
@@ -6816,7 +6823,8 @@ const runStreaming = (shell, stream, params, file) => Effect.gen(function* () {
6816
6823
  const code = yield* Ref.get(exitCode);
6817
6824
  if (code === null || code !== 0) return yield* new BashFailed({
6818
6825
  exitCode: code ?? -1,
6819
- ...presented
6826
+ ...presented,
6827
+ ...shellOf(report$1)
6820
6828
  });
6821
6829
  return {
6822
6830
  exitCode: code,