@smthrs/std 1.0.0-rc.6 → 1.0.0-rc.7

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,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/internal/Exec.ts"],
4
- "sourcesContent": ["/**\n * Buffered shell execution over the permission-aware process spawner.\n *\n * `@smthrs/kernel` used to expose a `Shell` service whose `exec` returned a\n * buffered `{ stdout, stderr, exitCode }`. The kernel replaced it with\n * `ChildProcessSpawner`, Effect's own process boundary, which streams and has\n * no buffered form. This module is the buffered form the shell flows still\n * want, expressed in terms of the spawner so the `proc:spawn` capability check\n * and the command-line resource stay exactly where the kernel put them.\n *\n * Commands run through the platform shell (`shell: true`), matching the old\n * service: the flows take a command *line*, not an argv.\n *\n * @since 1.0.0\n */\n\nimport * as ChildProcessEnvironment from \"@smthrs/kernel/ChildProcessEnvironment\"\nimport * as ChildProcessSpawner from \"@smthrs/kernel/ChildProcessSpawner\"\nimport * as Effect from \"effect/Effect\"\nimport * as ChildProcess from \"effect/process/ChildProcess\"\nimport * as Schema from \"effect/Schema\"\nimport * as Stream from \"effect/Stream\"\nimport * as StdError from \"../StdError.ts\"\n\n/**\n * Failure codes a buffered execution can report, matching the codes the\n * removed kernel `Shell` used so handler-level mapping is unchanged.\n *\n * @category models\n * @since 1.0.0\n */\nexport const ExecErrorCode = Schema.Literals([\"timeout\", \"spawn_error\", \"capture_overflow\"])\n\n/**\n * Failure codes a buffered execution can report.\n *\n * @category models\n * @since 1.0.0\n */\nexport type ExecErrorCode = typeof ExecErrorCode.Type\n\n/**\n * A command that never produced an exit code.\n *\n * A non-zero exit is a successful {@link ExecResult}, not a failure; this\n * error is reserved for a command that could not start or was cut off by its\n * timeout, or whose captured output exceeded a refusing capture bound.\n *\n * @category errors\n * @since 1.0.0\n */\nexport class ExecError extends Schema.TaggedError<ExecError>()(\"@smthrs/std/ExecError\", {\n code: ExecErrorCode,\n message: Schema.String,\n /** The limit a `timeout` ran past, in milliseconds. */\n limitMillis: Schema.optional(Schema.Number)\n}) {}\n\n/**\n * The buffered result of one command.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface ExecResult {\n readonly stdout: string\n readonly stderr: string\n readonly exitCode: number\n /** UTF-8 bytes dropped from the head of stdout to stay inside the capture bound. */\n readonly stdoutDroppedBytes: number\n /** UTF-8 bytes dropped from the head of stderr to stay inside the capture bound. */\n readonly stderrDroppedBytes: number\n}\n\n/**\n * Options accepted by {@link exec}.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface ExecOptions {\n readonly cwd?: string | undefined\n readonly env?: Readonly<Record<string, string>> | undefined\n readonly timeoutMs?: number | undefined\n /**\n * The program's arguments. Present means an argv, absent means a command\n * line for the platform shell. An argv is how a payload reaches a program\n * without being quoted into a string: nothing between here and `execve`\n * re-parses it.\n */\n readonly args?: ReadonlyArray<string> | undefined\n /**\n * Text written to the program's standard input, as data. A script delivered\n * this way is never quoted, escaped, or heredoc-terminated, which is the\n * whole point: quoting corruption cost the measured SWE-bench program twelve\n * probe failures and one instance's most expensive frame.\n */\n readonly stdin?: string | undefined\n /**\n * Bytes retained per captured stream. A stream that prints more keeps its\n * tail and reports what it dropped, so a command printing gigabytes costs a\n * bounded amount of memory rather than the whole of what it printed.\n *\n * Absent means unbounded, which is what a caller wants when it needs every\n * byte a tool produced (`rg --files`, `git worktree list`).\n */\n readonly maxCaptureBytes?: number | undefined\n /** Defaults to `tail`; `refuse` fails if either stream exceeds the bound. */\n readonly overflow?: \"tail\" | \"refuse\" | undefined\n}\n\n/** One captured stream: the text kept, and the bytes dropped to keep it bounded. */\ninterface Capture {\n readonly text: string\n readonly droppedBytes: number\n}\n\ninterface Tail {\n chunks: Array<Uint8Array>\n bytes: number\n dropped: number\n}\n\nconst decoder = new TextDecoder(\"utf-8\")\n\n/**\n * Joins the retained chunks and decodes them, skipping the partial code point a\n * dropped head can leave behind.\n *\n * A UTF-8 continuation byte is `10xxxxxx`, and a code point is at most four\n * bytes, so at most three leading continuation bytes can precede the first\n * whole character. Skipping them is counted as dropped rather than decoded to a\n * replacement character the process never printed.\n */\nconst decodeTail = (state: Tail): Capture => {\n const bytes = new Uint8Array(state.bytes)\n let offset = 0\n for (const chunk of state.chunks) {\n bytes.set(chunk, offset)\n offset += chunk.byteLength\n }\n if (state.dropped === 0) return { text: decoder.decode(bytes), droppedBytes: 0 }\n let start = 0\n while (start < bytes.byteLength && start < 3 && (bytes[start]! & 0b1100_0000) === 0b1000_0000) start++\n return { text: decoder.decode(bytes.subarray(start)), droppedBytes: state.dropped + start }\n}\n\nconst boundedTail = <E>(\n stream: Stream.Stream<Uint8Array, E>,\n maxBytes: number,\n overflow: \"tail\" | \"refuse\" | undefined\n): Effect.Effect<Capture, E> =>\n Stream.runFold(\n stream,\n (): Tail => ({ chunks: [], bytes: 0, dropped: 0 }),\n (state, chunk) => {\n if (chunk.byteLength === 0) return state\n state.chunks.push(chunk)\n state.bytes += chunk.byteLength\n while (state.bytes > maxBytes && state.chunks.length > 0) {\n const excess = state.bytes - maxBytes\n const first = state.chunks[0]!\n if (first.byteLength <= excess) {\n state.chunks.shift()\n state.bytes -= first.byteLength\n state.dropped += first.byteLength\n } else {\n state.chunks[0] = first.subarray(excess)\n state.bytes -= excess\n state.dropped += excess\n }\n }\n return state\n }\n ).pipe(Effect.map((state) =>\n overflow === \"refuse\" && state.dropped > 0\n ? { text: \"\", droppedBytes: state.dropped }\n : decodeTail(state)\n ))\n\nconst capture = <E>(\n stream: Stream.Stream<Uint8Array, E>,\n maxBytes: number | undefined,\n overflow: \"tail\" | \"refuse\" | undefined\n): Effect.Effect<Capture, E> =>\n maxBytes === undefined\n ? Effect.map(Stream.mkString(Stream.decodeText(stream)), (text) => ({ text, droppedBytes: 0 }))\n : boundedTail(stream, maxBytes, overflow)\n\nconst unbounded = (\n command: string,\n options: ExecOptions\n): Effect.Effect<ExecResult, ExecError, ChildProcessSpawner.ChildProcessSpawner> =>\n Effect.gen(function*() {\n const spawner = yield* ChildProcessSpawner.ChildProcessSpawner\n const settings: ChildProcess.CommandOptions = {\n ...(options.args === undefined ? { shell: true } : {}),\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n env: ChildProcessEnvironment.make(process.env, options.env),\n extendEnv: false,\n ...(options.stdin === undefined\n ? {}\n : { stdin: Stream.make(new TextEncoder().encode(options.stdin)) })\n }\n const handle = yield* spawner.spawn(\n options.args === undefined\n ? ChildProcess.make(command, settings)\n : ChildProcess.make(command, [...options.args], settings)\n )\n // stdout, stderr, and the exit code have to be consumed concurrently: a\n // command that fills a pipe blocks until the pipe is drained, so waiting\n // for exit first would deadlock on any output larger than the buffer.\n const [stdout, stderr, exitCode] = yield* Effect.all(\n [\n capture(handle.stdout, options.maxCaptureBytes, options.overflow),\n capture(handle.stderr, options.maxCaptureBytes, options.overflow),\n handle.exitCode\n ],\n { concurrency: \"unbounded\" }\n )\n if (options.overflow === \"refuse\") {\n const overflowed = [\n stdout.droppedBytes > 0 ? \"stdout\" : undefined,\n stderr.droppedBytes > 0 ? \"stderr\" : undefined\n ]\n .filter((stream): stream is string => stream !== undefined)\n if (overflowed.length > 0) {\n return yield* Effect.fail(\n new ExecError({\n code: \"capture_overflow\",\n message: `${command} ${\n overflowed.join(\" and \")\n } exceeded the ${options.maxCaptureBytes}-byte capture cap; refusing partial output`\n })\n )\n }\n }\n return {\n stdout: stdout.text,\n stderr: stderr.text,\n exitCode,\n stdoutDroppedBytes: stdout.droppedBytes,\n stderrDroppedBytes: stderr.droppedBytes\n }\n }).pipe(\n Effect.scoped,\n Effect.mapError((error) =>\n error instanceof ExecError ? error : new ExecError({\n code: \"spawn_error\",\n message: `exec: ${command}: ${error.message}`\n })\n )\n )\n\n/**\n * Runs a command line through the platform shell and buffers its output.\n *\n * Cancellation is scope closure: the spawn is scoped, so an interrupted fiber\n * \u2014 including the one a `timeoutMs` interrupts \u2014 terminates the process rather\n * than leaking it.\n *\n * @category execution\n * @since 1.0.0\n */\nexport const exec = (\n command: string,\n options: ExecOptions = {}\n): Effect.Effect<ExecResult, ExecError, ChildProcessSpawner.ChildProcessSpawner> =>\n options.timeoutMs === undefined\n ? unbounded(command, options)\n : Effect.timeoutOrElse(unbounded(command, options), {\n duration: options.timeoutMs,\n orElse: () =>\n Effect.fail(\n new ExecError({\n code: \"timeout\",\n message: `exec: \\`${command}\\` exceeded ${options.timeoutMs}ms`,\n limitMillis: options.timeoutMs\n })\n )\n })\n\n/**\n * The model-facing failure code a command that never produced an exit code\n * carries.\n *\n * A timeout keeps its own code, because \"the command never finished\" and \"the\n * command never started\" are different things to a caller deciding whether to\n * retry. Every other way of producing no exit code is a host failure.\n *\n * @category errors\n * @since 1.0.0\n */\nexport const toStdErrorCode = (error: ExecError): StdError.Code =>\n error.code === \"timeout\" ? \"timeout\" : \"command_failed\"\n\n/**\n * The model-facing failure one execution error becomes.\n *\n * A timeout names the command, which is what the caller asked for and all a\n * timeout has to say. Any other failure carries the message the execution\n * produced, which already names the command.\n *\n * @category errors\n * @since 1.0.0\n */\nexport const toStdError = (command: string, error: ExecError): StdError.StdError =>\n new StdError.StdError({\n code: toStdErrorCode(error),\n message: error.code === \"timeout\"\n ? `Command timed out: ${command}`\n : `Command failed to start: ${error.message}`,\n ...(error.limitMillis === undefined ? {} : { limitMillis: error.limitMillis })\n })\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Buffered shell execution over the permission-aware process spawner.\n *\n * `@smthrs/kernel` used to expose a `Shell` service whose `exec` returned a\n * buffered `{ stdout, stderr, exitCode }`. The kernel replaced it with\n * `ChildProcessSpawner`, Effect's own process boundary, which streams and has\n * no buffered form. This module is the buffered form the shell flows still\n * want, expressed in terms of the spawner so the `proc:spawn` capability check\n * and the command-line resource stay exactly where the kernel put them.\n *\n * Commands run through the platform shell (`shell: true`), matching the old\n * service: the flows take a command *line*, not an argv.\n *\n * @since 1.0.0\n */\n\nimport * as ChildProcessEnvironment from \"@smthrs/kernel/ChildProcessEnvironment\"\nimport * as ChildProcessSpawner from \"@smthrs/kernel/ChildProcessSpawner\"\nimport * as Effect from \"effect/Effect\"\nimport * as ChildProcess from \"effect/process/ChildProcess\"\nimport * as Schema from \"effect/Schema\"\nimport * as Stream from \"effect/Stream\"\nimport * as StdError from \"../StdError.ts\"\nimport { elideMiddle } from \"./Text.ts\"\n\n/**\n * Failure codes a buffered execution can report, matching the codes the\n * removed kernel `Shell` used so handler-level mapping is unchanged.\n *\n * @category models\n * @since 1.0.0\n */\nexport const ExecErrorCode = Schema.Literals([\"timeout\", \"spawn_error\", \"capture_overflow\"])\n\n/**\n * Failure codes a buffered execution can report.\n *\n * @category models\n * @since 1.0.0\n */\nexport type ExecErrorCode = typeof ExecErrorCode.Type\n\n/**\n * A command that never produced an exit code.\n *\n * A non-zero exit is a successful {@link ExecResult}, not a failure; this\n * error is reserved for a command that could not start or was cut off by its\n * timeout, or whose captured output exceeded a refusing capture bound.\n *\n * @category errors\n * @since 1.0.0\n */\nexport class ExecError extends Schema.TaggedError<ExecError>()(\"@smthrs/std/ExecError\", {\n code: ExecErrorCode,\n message: Schema.String,\n /** The limit a `timeout` ran past, in milliseconds. */\n limitMillis: Schema.optional(Schema.Number)\n}) {}\n\n/**\n * The buffered result of one command.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface ExecResult {\n readonly stdout: string\n readonly stderr: string\n readonly exitCode: number\n /** UTF-8 bytes of stdout dropped to stay inside the capture bound; see `overflow`. */\n readonly stdoutDroppedBytes: number\n /** UTF-8 bytes of stderr dropped to stay inside the capture bound; see `overflow`. */\n readonly stderrDroppedBytes: number\n}\n\n/**\n * Options accepted by {@link exec}.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface ExecOptions {\n readonly cwd?: string | undefined\n readonly env?: Readonly<Record<string, string>> | undefined\n readonly timeoutMs?: number | undefined\n /**\n * The program's arguments. Present means an argv, absent means a command\n * line for the platform shell. An argv is how a payload reaches a program\n * without being quoted into a string: nothing between here and `execve`\n * re-parses it.\n */\n readonly args?: ReadonlyArray<string> | undefined\n /**\n * Text written to the program's standard input, as data. A script delivered\n * this way is never quoted, escaped, or heredoc-terminated, which is the\n * whole point: quoting corruption cost the measured SWE-bench program twelve\n * probe failures and one instance's most expensive frame.\n */\n readonly stdin?: string | undefined\n /**\n * Bytes retained per captured stream. A stream that prints more keeps what\n * `overflow` names and reports what it dropped, so a command printing\n * gigabytes costs a bounded amount of memory rather than the whole of what it\n * printed.\n *\n * Absent means unbounded, which is what a caller wants when it needs every\n * byte a tool produced (`rg --files`, `git worktree list`).\n */\n readonly maxCaptureBytes?: number | undefined\n /**\n * What a stream past the bound keeps. `tail`, the default, keeps its last\n * bytes. `ends` keeps its first and last halves and puts one line naming the\n * dropped bytes where the middle was. `refuse` fails if either stream exceeds\n * the bound.\n */\n readonly overflow?: Overflow | undefined\n}\n\ntype Overflow = \"tail\" | \"ends\" | \"refuse\"\n\n/** One captured stream: the text kept, and the bytes dropped to keep it bounded. */\ninterface Capture {\n readonly text: string\n readonly droppedBytes: number\n}\n\ninterface Tail {\n chunks: Array<Uint8Array>\n bytes: number\n dropped: number\n}\n\n/** A stream's first bytes and its last ones: what `overflow: \"ends\"` keeps. */\ninterface Ends {\n readonly head: Array<Uint8Array>\n headBytes: number\n readonly tail: Tail\n}\n\nconst decoder = new TextDecoder(\"utf-8\")\n\nconst emptyTail = (): Tail => ({ chunks: [], bytes: 0, dropped: 0 })\n\n/** A UTF-8 continuation byte is `10xxxxxx`; every other byte starts a character. */\nconst isContinuation = (byte: number): boolean => (byte & 0b1100_0000) === 0b1000_0000\n\nconst join = (chunks: ReadonlyArray<Uint8Array>, size: number): Uint8Array => {\n const bytes = new Uint8Array(size)\n let offset = 0\n for (const chunk of chunks) {\n bytes.set(chunk, offset)\n offset += chunk.byteLength\n }\n return bytes\n}\n\n/** Appends one chunk and drops from the front whatever no longer fits. */\nconst keepTail = (state: Tail, chunk: Uint8Array, maxBytes: number): void => {\n if (chunk.byteLength === 0) return\n state.chunks.push(chunk)\n state.bytes += chunk.byteLength\n while (state.bytes > maxBytes && state.chunks.length > 0) {\n const excess = state.bytes - maxBytes\n const first = state.chunks[0]!\n if (first.byteLength <= excess) {\n state.chunks.shift()\n state.bytes -= first.byteLength\n state.dropped += first.byteLength\n } else {\n state.chunks[0] = first.subarray(excess)\n state.bytes -= excess\n state.dropped += excess\n }\n }\n}\n\n/**\n * Joins the retained chunks and decodes them, skipping the partial code point a\n * dropped head can leave behind.\n *\n * A code point is at most four bytes, so at most three leading continuation\n * bytes can precede the first whole character. Skipping them is counted as\n * dropped rather than decoded to a replacement character the process never\n * printed.\n */\nconst decodeTail = (state: Tail): Capture => {\n const bytes = join(state.chunks, state.bytes)\n if (state.dropped === 0) return { text: decoder.decode(bytes), droppedBytes: 0 }\n let start = 0\n while (start < bytes.byteLength && start < 3 && isContinuation(bytes[start]!)) start++\n return { text: decoder.decode(bytes.subarray(start)), droppedBytes: state.dropped + start }\n}\n\n/**\n * The length of a cut head without the character the cut left unfinished.\n *\n * Its last character starts at the last byte that is not a continuation byte,\n * and that byte says how many bytes the character needs. One that needs more\n * than the head holds is dropped, for the same reason {@link decodeTail} skips\n * a partial code point.\n */\nconst wholeLength = (bytes: Uint8Array): number => {\n for (let back = 1; back <= Math.min(3, bytes.byteLength); back++) {\n const byte = bytes[bytes.byteLength - back]!\n if (isContinuation(byte)) continue\n const width = byte >= 0b1111_0000 ? 4 : byte >= 0b1110_0000 ? 3 : byte >= 0b1100_0000 ? 2 : 1\n return width > back ? bytes.byteLength - back : bytes.byteLength\n }\n return bytes.byteLength\n}\n\n/**\n * Decodes a stream kept by its ends. A stream that fit is decoded whole;\n * otherwise each end is cut on a character boundary and one line naming every\n * byte between them stands where the middle was.\n */\nconst decodeEnds = (state: Ends): Capture => {\n if (state.tail.dropped === 0) {\n const whole = join([...state.head, ...state.tail.chunks], state.headBytes + state.tail.bytes)\n return { text: decoder.decode(whole), droppedBytes: 0 }\n }\n const head = join(state.head, state.headBytes)\n const kept = wholeLength(head)\n const tail = decodeTail(state.tail)\n const droppedBytes = head.byteLength - kept + tail.droppedBytes\n return { text: elideMiddle(decoder.decode(head.subarray(0, kept)), droppedBytes, tail.text), droppedBytes }\n}\n\nconst boundedTail = <E>(\n stream: Stream.Stream<Uint8Array, E>,\n maxBytes: number,\n overflow: Overflow | undefined\n): Effect.Effect<Capture, E> =>\n Stream.runFold(stream, emptyTail, (state, chunk) => {\n keepTail(state, chunk, maxBytes)\n return state\n }).pipe(Effect.map((state) =>\n overflow === \"refuse\" && state.dropped > 0\n ? { text: \"\", droppedBytes: state.dropped }\n : decodeTail(state)\n ))\n\n/**\n * Keeps the first half of the bound and the last half. The head fills first,\n * and every byte after it passes through the tail, which drops from its front:\n * what falls out of the tail is the middle.\n */\nconst boundedEnds = <E>(stream: Stream.Stream<Uint8Array, E>, maxBytes: number): Effect.Effect<Capture, E> => {\n const headBytes = Math.floor(maxBytes / 2)\n return Stream.runFold(stream, (): Ends => ({ head: [], headBytes: 0, tail: emptyTail() }), (state, chunk) => {\n const taken = Math.min(headBytes - state.headBytes, chunk.byteLength)\n if (taken > 0) {\n state.head.push(chunk.subarray(0, taken))\n state.headBytes += taken\n }\n keepTail(state.tail, chunk.subarray(taken), maxBytes - headBytes)\n return state\n }).pipe(Effect.map(decodeEnds))\n}\n\nconst capture = <E>(\n stream: Stream.Stream<Uint8Array, E>,\n maxBytes: number | undefined,\n overflow: Overflow | undefined\n): Effect.Effect<Capture, E> =>\n maxBytes === undefined\n ? Effect.map(Stream.mkString(Stream.decodeText(stream)), (text) => ({ text, droppedBytes: 0 }))\n : overflow === \"ends\"\n ? boundedEnds(stream, maxBytes)\n : boundedTail(stream, maxBytes, overflow)\n\nconst unbounded = (\n command: string,\n options: ExecOptions\n): Effect.Effect<ExecResult, ExecError, ChildProcessSpawner.ChildProcessSpawner> =>\n Effect.gen(function*() {\n const spawner = yield* ChildProcessSpawner.ChildProcessSpawner\n const settings: ChildProcess.CommandOptions = {\n ...(options.args === undefined ? { shell: true } : {}),\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n env: ChildProcessEnvironment.make(process.env, options.env),\n extendEnv: false,\n ...(options.stdin === undefined\n ? {}\n : { stdin: Stream.make(new TextEncoder().encode(options.stdin)) })\n }\n const handle = yield* spawner.spawn(\n options.args === undefined\n ? ChildProcess.make(command, settings)\n : ChildProcess.make(command, [...options.args], settings)\n )\n // stdout, stderr, and the exit code have to be consumed concurrently: a\n // command that fills a pipe blocks until the pipe is drained, so waiting\n // for exit first would deadlock on any output larger than the buffer.\n const [stdout, stderr, exitCode] = yield* Effect.all(\n [\n capture(handle.stdout, options.maxCaptureBytes, options.overflow),\n capture(handle.stderr, options.maxCaptureBytes, options.overflow),\n handle.exitCode\n ],\n { concurrency: \"unbounded\" }\n )\n if (options.overflow === \"refuse\") {\n const overflowed = [\n stdout.droppedBytes > 0 ? \"stdout\" : undefined,\n stderr.droppedBytes > 0 ? \"stderr\" : undefined\n ]\n .filter((stream): stream is string => stream !== undefined)\n if (overflowed.length > 0) {\n return yield* Effect.fail(\n new ExecError({\n code: \"capture_overflow\",\n message: `${command} ${\n overflowed.join(\" and \")\n } exceeded the ${options.maxCaptureBytes}-byte capture cap; refusing partial output`\n })\n )\n }\n }\n return {\n stdout: stdout.text,\n stderr: stderr.text,\n exitCode,\n stdoutDroppedBytes: stdout.droppedBytes,\n stderrDroppedBytes: stderr.droppedBytes\n }\n }).pipe(\n Effect.scoped,\n Effect.mapError((error) =>\n error instanceof ExecError ? error : new ExecError({\n code: \"spawn_error\",\n message: `exec: ${command}: ${error.message}`\n })\n )\n )\n\n/**\n * Runs a command line through the platform shell and buffers its output.\n *\n * Cancellation is scope closure: the spawn is scoped, so an interrupted fiber\n * \u2014 including the one a `timeoutMs` interrupts \u2014 terminates the process rather\n * than leaking it.\n *\n * @category execution\n * @since 1.0.0\n */\nexport const exec = (\n command: string,\n options: ExecOptions = {}\n): Effect.Effect<ExecResult, ExecError, ChildProcessSpawner.ChildProcessSpawner> =>\n options.timeoutMs === undefined\n ? unbounded(command, options)\n : Effect.timeoutOrElse(unbounded(command, options), {\n duration: options.timeoutMs,\n orElse: () =>\n Effect.fail(\n new ExecError({\n code: \"timeout\",\n message: `exec: \\`${command}\\` exceeded ${options.timeoutMs}ms`,\n limitMillis: options.timeoutMs\n })\n )\n })\n\n/**\n * The model-facing failure code a command that never produced an exit code\n * carries.\n *\n * A timeout keeps its own code, because \"the command never finished\" and \"the\n * command never started\" are different things to a caller deciding whether to\n * retry. Every other way of producing no exit code is a host failure.\n *\n * @category errors\n * @since 1.0.0\n */\nexport const toStdErrorCode = (error: ExecError): StdError.Code =>\n error.code === \"timeout\" ? \"timeout\" : \"command_failed\"\n\n/**\n * The model-facing failure one execution error becomes.\n *\n * A timeout names the command, which is what the caller asked for and all a\n * timeout has to say. Any other failure carries the message the execution\n * produced, which already names the command.\n *\n * @category errors\n * @since 1.0.0\n */\nexport const toStdError = (command: string, error: ExecError): StdError.StdError =>\n new StdError.StdError({\n code: toStdErrorCode(error),\n message: error.code === \"timeout\"\n ? `Command timed out: ${command}`\n : `Command failed to start: ${error.message}`,\n ...(error.limitMillis === undefined ? {} : { limitMillis: error.limitMillis })\n })\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -85,6 +85,17 @@ export interface Page {
85
85
  export declare const truncateBytes: (text: string, maxBytes: number, options: {
86
86
  readonly keep: "head" | "tail";
87
87
  }) => Truncation;
88
+ /**
89
+ * Joins the start and the end of a stream cut in the middle around one line
90
+ * naming the bytes cut between them.
91
+ *
92
+ * The line stands alone, so a start that stops mid-line is ended before it.
93
+ * Only the line's own newlines are added; `droppedBytes` counts printed bytes.
94
+ *
95
+ * @category rendering
96
+ * @since 1.0.0-rc.5
97
+ */
98
+ export declare const elideMiddle: (start: string, droppedBytes: number, end: string) => string;
88
99
  /**
89
100
  * Splits on LF without counting a terminal LF as a line.
90
101
  * Carriage returns remain part of each line, including the CR in CRLF, so
@@ -1 +1 @@
1
- {"version":3,"file":"Text.d.ts","sourceRoot":"","sources":["../../../src/internal/Text.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,OAAQ,CAAA;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,WAAW,OAAQ,CAAA;AAEhC;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,MAAM,CAAA;AAEnC;;;;;GAKG;AACH,eAAO,MAAM,cAAc,OAAQ,CAAA;AAEnC;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,QAAS,CAAA;AAEtC;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,QAAS,CAAA;AAE5C;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAKD;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EACZ,UAAU,MAAM,EAChB,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,KAC1C,UAwBF,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,KAAG,aAAa,CAAC,MAAM,CAI9D,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,KAAK,GAChB,MAAM,MAAM,EACZ,SAAS;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,KAC3D,IAWF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,MAAM,GAAI,MAAM,MAAM,EAAE,OAAO,MAAM,EAAE,OAAO,MAAM,KAAG,MACL,CAAA"}
1
+ {"version":3,"file":"Text.d.ts","sourceRoot":"","sources":["../../../src/internal/Text.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,OAAQ,CAAA;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,WAAW,OAAQ,CAAA;AAEhC;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,MAAM,CAAA;AAEnC;;;;;GAKG;AACH,eAAO,MAAM,cAAc,OAAQ,CAAA;AAEnC;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,QAAS,CAAA;AAEtC;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,QAAS,CAAA;AAE5C;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAKD;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EACZ,UAAU,MAAM,EAChB,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,KAC1C,UAwBF,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,EAAE,cAAc,MAAM,EAAE,KAAK,MAAM,KAAG,MAG1D,CAAA;AAErB;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,KAAG,aAAa,CAAC,MAAM,CAI9D,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,KAAK,GAChB,MAAM,MAAM,EACZ,SAAS;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,KAC3D,IAWF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,MAAM,GAAI,MAAM,MAAM,EAAE,OAAO,MAAM,EAAE,OAAO,MAAM,KAAG,MACL,CAAA"}
@@ -24,6 +24,7 @@ __export(Text_exports, {
24
24
  MAX_LINE_CHARS: () => MAX_LINE_CHARS,
25
25
  MAX_OUTPUT_BYTES: () => MAX_OUTPUT_BYTES,
26
26
  MAX_SHELL_OUTPUT_BYTES: () => MAX_SHELL_OUTPUT_BYTES,
27
+ elideMiddle: () => elideMiddle,
27
28
  notice: () => notice,
28
29
  slice: () => slice,
29
30
  sourceLines: () => sourceLines,
@@ -61,6 +62,8 @@ const truncateBytes = (text, maxBytes, options) => {
61
62
  }
62
63
  }
63
64
  };
65
+ const elideMiddle = (start, droppedBytes, end) => `${start}${start === "" || start.endsWith("\n") ? "" : "\n"}[${droppedBytes} ${droppedBytes === 1 ? "byte" : "bytes"} omitted]
66
+ ${end}`;
64
67
  const sourceLines = (text) => {
65
68
  const lines = text.length === 0 ? [] : text.split("\n");
66
69
  if (text.endsWith("\n")) lines.pop();
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/internal/Text.ts"],
4
- "sourcesContent": ["/**\n * Shared text paging, numbering, and byte-budget helpers.\n *\n * Every limit here is a display budget, not a policy limit: exceeding one is\n * always disclosed to the model rather than silently applied.\n *\n * @since 1.0.0\n */\n\n/**\n * Default number of lines or entries returned by a paged flow.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const DEFAULT_READ_LIMIT = 2_000\n\n/**\n * Maximum number of directory entries or glob paths returned in one call.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const MAX_ENTRIES = 1_000\n\n/**\n * Maximum number of grep matches returned in one call.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const MAX_GREP_MATCHES = 200\n\n/**\n * Maximum number of Unicode scalar values displayed for a single line.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const MAX_LINE_CHARS = 2_000\n\n/**\n * Maximum UTF-8 byte budget for one rendered text payload.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const MAX_OUTPUT_BYTES = 60_000\n\n/**\n * Maximum UTF-8 byte budget captured per shell output stream.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const MAX_SHELL_OUTPUT_BYTES = 30_000\n\n/**\n * A byte-budgeted rendering of a text value.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Truncation {\n readonly text: string\n readonly truncated: boolean\n readonly keptBytes: number\n readonly droppedBytes: number\n}\n\n/**\n * One page of source lines.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Page {\n readonly lines: ReadonlyArray<string>\n readonly startLine: number\n readonly endLine: number\n readonly totalLines: number\n}\n\nconst encoder = new TextEncoder()\nconst fatalDecoder = new TextDecoder(\"utf-8\", { fatal: true })\n\n/**\n * Trims a string to a UTF-8 byte budget without splitting a code point.\n *\n * `keep: \"head\"` retains the beginning of the value; `keep: \"tail\"` retains\n * the end, which is what shell output needs because the interesting part of an\n * overflowing stream is almost always its last lines.\n *\n * @category rendering\n * @since 1.0.0\n */\nexport const truncateBytes = (\n text: string,\n maxBytes: number,\n options: { readonly keep: \"head\" | \"tail\" }\n): Truncation => {\n const bytes = encoder.encode(text)\n if (bytes.byteLength <= maxBytes) {\n return { text, truncated: false, keptBytes: bytes.byteLength, droppedBytes: 0 }\n }\n let start = options.keep === \"head\" ? 0 : bytes.byteLength - maxBytes\n let end = options.keep === \"head\" ? maxBytes : bytes.byteLength\n // TextEncoder produces valid UTF-8. Moving a cut inward reaches a scalar\n // boundary after at most three continuation bytes, so decoding must succeed.\n while (true) {\n try {\n const decoded = fatalDecoder.decode(bytes.subarray(start, end))\n const keptBytes = end - start\n return {\n text: decoded,\n truncated: true,\n keptBytes,\n droppedBytes: bytes.byteLength - keptBytes\n }\n } catch {\n if (options.keep === \"head\") end--\n else start++\n }\n }\n}\n\n/**\n * Splits on LF without counting a terminal LF as a line.\n * Carriage returns remain part of each line, including the CR in CRLF, so\n * joining a page with LF preserves its bytes except for the final LF.\n *\n * @category parsing\n * @since 1.0.0\n */\nexport const sourceLines = (text: string): ReadonlyArray<string> => {\n const lines = text.length === 0 ? [] : text.split(\"\\n\")\n if (text.endsWith(\"\\n\")) lines.pop()\n return lines\n}\n\n/**\n * Selects a 1-based page of lines from a text value.\n *\n * @category paging\n * @since 1.0.0\n */\nexport const slice = (\n text: string,\n options: { readonly offset: number; readonly limit: number }\n): Page => {\n const lines = sourceLines(text)\n const totalLines = lines.length\n const startLine = Math.max(1, options.offset)\n const endLine = Math.min(totalLines, startLine + Math.max(0, options.limit) - 1)\n return {\n lines: lines.slice(startLine - 1, endLine),\n startLine,\n endLine,\n totalLines\n }\n}\n\n/**\n * Renders the disclosure appended whenever output was capped.\n *\n * @category rendering\n * @since 1.0.0\n */\nexport const notice = (unit: string, shown: number, total: number): string =>\n `Showing ${shown} of ${total} ${unit}; output was truncated.`\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeO,MAAM,qBAAqB;AAQ3B,MAAM,cAAc;AAQpB,MAAM,mBAAmB;AAQzB,MAAM,iBAAiB;AAQvB,MAAM,mBAAmB;AAQzB,MAAM,yBAAyB;AA4BtC,MAAM,UAAU,IAAI,YAAY;AAChC,MAAM,eAAe,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC;AAYtD,MAAM,gBAAgB,CAC3B,MACA,UACA,YACe;AACf,QAAM,QAAQ,QAAQ,OAAO,IAAI;AACjC,MAAI,MAAM,cAAc,UAAU;AAChC,WAAO,EAAE,MAAM,WAAW,OAAO,WAAW,MAAM,YAAY,cAAc,EAAE;AAAA,EAChF;AACA,MAAI,QAAQ,QAAQ,SAAS,SAAS,IAAI,MAAM,aAAa;AAC7D,MAAI,MAAM,QAAQ,SAAS,SAAS,WAAW,MAAM;AAGrD,SAAO,MAAM;AACX,QAAI;AACF,YAAM,UAAU,aAAa,OAAO,MAAM,SAAS,OAAO,GAAG,CAAC;AAC9D,YAAM,YAAY,MAAM;AACxB,aAAO;AAAA,QACL,MAAM;AAAA,QACN,WAAW;AAAA,QACX;AAAA,QACA,cAAc,MAAM,aAAa;AAAA,MACnC;AAAA,IACF,QAAQ;AACN,UAAI,QAAQ,SAAS,OAAQ;AAAA,UACxB;AAAA,IACP;AAAA,EACF;AACF;AAUO,MAAM,cAAc,CAAC,SAAwC;AAClE,QAAM,QAAQ,KAAK,WAAW,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI;AACtD,MAAI,KAAK,SAAS,IAAI,EAAG,OAAM,IAAI;AACnC,SAAO;AACT;AAQO,MAAM,QAAQ,CACnB,MACA,YACS;AACT,QAAM,QAAQ,YAAY,IAAI;AAC9B,QAAM,aAAa,MAAM;AACzB,QAAM,YAAY,KAAK,IAAI,GAAG,QAAQ,MAAM;AAC5C,QAAM,UAAU,KAAK,IAAI,YAAY,YAAY,KAAK,IAAI,GAAG,QAAQ,KAAK,IAAI,CAAC;AAC/E,SAAO;AAAA,IACL,OAAO,MAAM,MAAM,YAAY,GAAG,OAAO;AAAA,IACzC;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAQO,MAAM,SAAS,CAAC,MAAc,OAAe,UAClD,WAAW,KAAK,OAAO,KAAK,IAAI,IAAI;",
4
+ "sourcesContent": ["/**\n * Shared text paging, numbering, and byte-budget helpers.\n *\n * Every limit here is a display budget, not a policy limit: exceeding one is\n * always disclosed to the model rather than silently applied.\n *\n * @since 1.0.0\n */\n\n/**\n * Default number of lines or entries returned by a paged flow.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const DEFAULT_READ_LIMIT = 2_000\n\n/**\n * Maximum number of directory entries or glob paths returned in one call.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const MAX_ENTRIES = 1_000\n\n/**\n * Maximum number of grep matches returned in one call.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const MAX_GREP_MATCHES = 200\n\n/**\n * Maximum number of Unicode scalar values displayed for a single line.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const MAX_LINE_CHARS = 2_000\n\n/**\n * Maximum UTF-8 byte budget for one rendered text payload.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const MAX_OUTPUT_BYTES = 60_000\n\n/**\n * Maximum UTF-8 byte budget captured per shell output stream.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const MAX_SHELL_OUTPUT_BYTES = 30_000\n\n/**\n * A byte-budgeted rendering of a text value.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Truncation {\n readonly text: string\n readonly truncated: boolean\n readonly keptBytes: number\n readonly droppedBytes: number\n}\n\n/**\n * One page of source lines.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Page {\n readonly lines: ReadonlyArray<string>\n readonly startLine: number\n readonly endLine: number\n readonly totalLines: number\n}\n\nconst encoder = new TextEncoder()\nconst fatalDecoder = new TextDecoder(\"utf-8\", { fatal: true })\n\n/**\n * Trims a string to a UTF-8 byte budget without splitting a code point.\n *\n * `keep: \"head\"` retains the beginning of the value; `keep: \"tail\"` retains\n * the end, which is what shell output needs because the interesting part of an\n * overflowing stream is almost always its last lines.\n *\n * @category rendering\n * @since 1.0.0\n */\nexport const truncateBytes = (\n text: string,\n maxBytes: number,\n options: { readonly keep: \"head\" | \"tail\" }\n): Truncation => {\n const bytes = encoder.encode(text)\n if (bytes.byteLength <= maxBytes) {\n return { text, truncated: false, keptBytes: bytes.byteLength, droppedBytes: 0 }\n }\n let start = options.keep === \"head\" ? 0 : bytes.byteLength - maxBytes\n let end = options.keep === \"head\" ? maxBytes : bytes.byteLength\n // TextEncoder produces valid UTF-8. Moving a cut inward reaches a scalar\n // boundary after at most three continuation bytes, so decoding must succeed.\n while (true) {\n try {\n const decoded = fatalDecoder.decode(bytes.subarray(start, end))\n const keptBytes = end - start\n return {\n text: decoded,\n truncated: true,\n keptBytes,\n droppedBytes: bytes.byteLength - keptBytes\n }\n } catch {\n if (options.keep === \"head\") end--\n else start++\n }\n }\n}\n\n/**\n * Joins the start and the end of a stream cut in the middle around one line\n * naming the bytes cut between them.\n *\n * The line stands alone, so a start that stops mid-line is ended before it.\n * Only the line's own newlines are added; `droppedBytes` counts printed bytes.\n *\n * @category rendering\n * @since 1.0.0-rc.5\n */\nexport const elideMiddle = (start: string, droppedBytes: number, end: string): string =>\n `${start}${start === \"\" || start.endsWith(\"\\n\") ? \"\" : \"\\n\"}[${droppedBytes} ${\n droppedBytes === 1 ? \"byte\" : \"bytes\"\n } omitted]\\n${end}`\n\n/**\n * Splits on LF without counting a terminal LF as a line.\n * Carriage returns remain part of each line, including the CR in CRLF, so\n * joining a page with LF preserves its bytes except for the final LF.\n *\n * @category parsing\n * @since 1.0.0\n */\nexport const sourceLines = (text: string): ReadonlyArray<string> => {\n const lines = text.length === 0 ? [] : text.split(\"\\n\")\n if (text.endsWith(\"\\n\")) lines.pop()\n return lines\n}\n\n/**\n * Selects a 1-based page of lines from a text value.\n *\n * @category paging\n * @since 1.0.0\n */\nexport const slice = (\n text: string,\n options: { readonly offset: number; readonly limit: number }\n): Page => {\n const lines = sourceLines(text)\n const totalLines = lines.length\n const startLine = Math.max(1, options.offset)\n const endLine = Math.min(totalLines, startLine + Math.max(0, options.limit) - 1)\n return {\n lines: lines.slice(startLine - 1, endLine),\n startLine,\n endLine,\n totalLines\n }\n}\n\n/**\n * Renders the disclosure appended whenever output was capped.\n *\n * @category rendering\n * @since 1.0.0\n */\nexport const notice = (unit: string, shown: number, total: number): string =>\n `Showing ${shown} of ${total} ${unit}; output was truncated.`\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeO,MAAM,qBAAqB;AAQ3B,MAAM,cAAc;AAQpB,MAAM,mBAAmB;AAQzB,MAAM,iBAAiB;AAQvB,MAAM,mBAAmB;AAQzB,MAAM,yBAAyB;AA4BtC,MAAM,UAAU,IAAI,YAAY;AAChC,MAAM,eAAe,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC;AAYtD,MAAM,gBAAgB,CAC3B,MACA,UACA,YACe;AACf,QAAM,QAAQ,QAAQ,OAAO,IAAI;AACjC,MAAI,MAAM,cAAc,UAAU;AAChC,WAAO,EAAE,MAAM,WAAW,OAAO,WAAW,MAAM,YAAY,cAAc,EAAE;AAAA,EAChF;AACA,MAAI,QAAQ,QAAQ,SAAS,SAAS,IAAI,MAAM,aAAa;AAC7D,MAAI,MAAM,QAAQ,SAAS,SAAS,WAAW,MAAM;AAGrD,SAAO,MAAM;AACX,QAAI;AACF,YAAM,UAAU,aAAa,OAAO,MAAM,SAAS,OAAO,GAAG,CAAC;AAC9D,YAAM,YAAY,MAAM;AACxB,aAAO;AAAA,QACL,MAAM;AAAA,QACN,WAAW;AAAA,QACX;AAAA,QACA,cAAc,MAAM,aAAa;AAAA,MACnC;AAAA,IACF,QAAQ;AACN,UAAI,QAAQ,SAAS,OAAQ;AAAA,UACxB;AAAA,IACP;AAAA,EACF;AACF;AAYO,MAAM,cAAc,CAAC,OAAe,cAAsB,QAC/D,GAAG,KAAK,GAAG,UAAU,MAAM,MAAM,SAAS,IAAI,IAAI,KAAK,IAAI,IAAI,YAAY,IACzE,iBAAiB,IAAI,SAAS,OAChC;AAAA,EAAc,GAAG;AAUZ,MAAM,cAAc,CAAC,SAAwC;AAClE,QAAM,QAAQ,KAAK,WAAW,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI;AACtD,MAAI,KAAK,SAAS,IAAI,EAAG,OAAM,IAAI;AACnC,SAAO;AACT;AAQO,MAAM,QAAQ,CACnB,MACA,YACS;AACT,QAAM,QAAQ,YAAY,IAAI;AAC9B,QAAM,aAAa,MAAM;AACzB,QAAM,YAAY,KAAK,IAAI,GAAG,QAAQ,MAAM;AAC5C,QAAM,UAAU,KAAK,IAAI,YAAY,YAAY,KAAK,IAAI,GAAG,QAAQ,KAAK,IAAI,CAAC;AAC/E,SAAO;AAAA,IACL,OAAO,MAAM,MAAM,YAAY,GAAG,OAAO;AAAA,IACzC;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAQO,MAAM,SAAS,CAAC,MAAc,OAAe,UAClD,WAAW,KAAK,OAAO,KAAK,IAAI,IAAI;",
6
6
  "names": []
7
7
  }
@@ -133,6 +133,16 @@ export declare const Output: Schema.Struct<{
133
133
  * @since 1.0.0
134
134
  */
135
135
  export type Output = typeof Output.Type;
136
+ /**
137
+ * The text of a stream cut to its start and end: the start, one line naming
138
+ * the bytes omitted between them, and the end. A host that captures output
139
+ * itself, such as a terminal behind {@link inTerminal}, cuts with this so every
140
+ * {@link Output} reads the same.
141
+ *
142
+ * @category rendering
143
+ * @since 1.0.0-rc.5
144
+ */
145
+ export declare const elideMiddle: (start: string, droppedBytes: number, end: string) => string;
136
146
  /**
137
147
  * Static conservative effect envelope for the bash flow.
138
148
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Bash.d.ts","sourceRoot":"","sources":["../../src/Bash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,KAAK,mBAAmB,MAAM,oCAAoC,CAAA;AAC9E,OAAO,KAAK,IAAI,MAAM,qBAAqB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAQvC,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AAGzC;;;;;GAKG;AACH,eAAO,MAAM,IAAI,SAAS,CAAA;AAE1B;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,yMACgL,CAAA;AAExM;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,SAAU,CAAA;AAmCzC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;IAiChB,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAErC;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;EA6BjB,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AAEvC;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,4CAKlB,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,KAAK,+CAajC,CAAA;AAEN;;;;;GAKG;AACH,eAAO,MAAM,YAAY,UAAkC,CAAA;AAE3D;;;;;GAKG;AACH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAsF,CAAA;AAUvG;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY;;;;;;;;CAIf,CAAA;AA2LV;;;;;;;;GAQG;AACH,eAAO,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2FAwCd,CAAA;AAEF;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,KAAK,KAAG,UAAU,GAAG,QAAQ,CAAC,QAAuB,CAAA;AAEvF;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,EAC1B,SAAS,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qDAapE,CAAA;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAAI,UAAU,MAAM,EAAE,WAAW,MAAM,GAAG,SAAS,KAAG,QAAQ,CAAC,QAMxF,CAAA;AAEJ;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,MAAM,GAAI,UAAU,MAAM,MAErC,OAAO,KAAK,KACX,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC,mBAAmB,GAAG,IAAI,CAAC,IAAI,CACO,CAAA"}
1
+ {"version":3,"file":"Bash.d.ts","sourceRoot":"","sources":["../../src/Bash.ts"],"names":[],"mappings":"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"}
package/dist/esm/Bash.js CHANGED
@@ -25,7 +25,7 @@ import { capability, envelope } from "./internal/Declaration.js";
25
25
  import * as Diagnostics from "./internal/Diagnostics.js";
26
26
  import { outsideEnvelope } from "./internal/EnvelopePrecheck.js";
27
27
  import * as Exec from "./internal/Exec.js";
28
- import { MAX_SHELL_OUTPUT_BYTES, truncateBytes } from "./internal/Text.js";
28
+ import { elideMiddle as elide, MAX_SHELL_OUTPUT_BYTES } from "./internal/Text.js";
29
29
  import * as Probe from "./Probe.js";
30
30
  import * as StdError from "./StdError.js";
31
31
  import * as TreeFingerprint from "./TreeFingerprint.js";
@@ -151,10 +151,10 @@ export const Input = Schema.Union([
151
151
  export const Output = Schema.Struct({
152
152
  exitCode: Schema.Number.annotate({ description: "Command exit code, including non-zero codes" }),
153
153
  stdout: Schema.String.annotate({
154
- description: "Captured stdout; only the tail, and not the whole output, when stdoutTruncated is true"
154
+ description: "Captured stdout; when stdoutTruncated is true, only its start and end, with one line naming the bytes omitted between them"
155
155
  }),
156
156
  stderr: Schema.String.annotate({
157
- description: "Captured stderr; only the tail, and not the whole output, when stderrTruncated is true"
157
+ description: "Captured stderr; when stderrTruncated is true, only its start and end, with one line naming the bytes omitted between them"
158
158
  }),
159
159
  stdoutTruncated: Schema.Boolean.annotate({
160
160
  description: "Whether stdout exceeded the capture limit, leaving stdout a fragment that must not be written to a file"
@@ -162,8 +162,8 @@ export const Output = Schema.Struct({
162
162
  stderrTruncated: Schema.Boolean.annotate({
163
163
  description: "Whether stderr exceeded the capture limit, leaving stderr a fragment that must not be written to a file"
164
164
  }),
165
- stdoutDroppedBytes: Schema.Number.annotate({ description: "UTF-8 bytes omitted from the start of stdout" }),
166
- stderrDroppedBytes: Schema.Number.annotate({ description: "UTF-8 bytes omitted from the start of stderr" }),
165
+ stdoutDroppedBytes: Schema.Number.annotate({ description: "UTF-8 bytes omitted from the middle of stdout" }),
166
+ stderrDroppedBytes: Schema.Number.annotate({ description: "UTF-8 bytes omitted from the middle of stderr" }),
167
167
  invalidProbe: Schema.optional(Probe.InvalidProbe.annotate({
168
168
  description: "Reserved for a confirmed launch failure; an exit code alone does not establish one"
169
169
  })),
@@ -171,6 +171,16 @@ export const Output = Schema.Struct({
171
171
  description: "Present for a containerised command whose working directory was measured before and after it: true when the tree changed, false when it held still. Absent when the tree was not measured, which is never read as unchanged."
172
172
  }))
173
173
  });
174
+ /**
175
+ * The text of a stream cut to its start and end: the start, one line naming
176
+ * the bytes omitted between them, and the end. A host that captures output
177
+ * itself, such as a terminal behind {@link inTerminal}, cuts with this so every
178
+ * {@link Output} reads the same.
179
+ *
180
+ * @category rendering
181
+ * @since 1.0.0-rc.5
182
+ */
183
+ export const elideMiddle = elide;
174
184
  /**
175
185
  * Static conservative effect envelope for the bash flow.
176
186
  *
@@ -424,6 +434,7 @@ export const run = Effect.fn("Bash.run")(function* (input) {
424
434
  ...(spawned.env === undefined ? {} : { env: spawned.env }),
425
435
  timeoutMs: input.timeoutMs ?? DEFAULT_TIMEOUT_MS,
426
436
  maxCaptureBytes: MAX_SHELL_OUTPUT_BYTES,
437
+ overflow: "ends",
427
438
  ...(spawned.args === undefined ? {} : { args: spawned.args }),
428
439
  ...(spawned.stdin === undefined ? {} : { stdin: spawned.stdin })
429
440
  }).pipe(Effect.mapError((error) => Exec.toStdError(spawned.quoted, error)));
@@ -432,18 +443,16 @@ export const run = Effect.fn("Bash.run")(function* (input) {
432
443
  // open; a container's files are not the ones it was sent.
433
444
  if (!contained)
434
445
  yield* Diagnostics.refresh;
435
- const stdout = truncateBytes(result.stdout, MAX_SHELL_OUTPUT_BYTES, { keep: "tail" });
436
- const stderr = truncateBytes(result.stderr, MAX_SHELL_OUTPUT_BYTES, { keep: "tail" });
437
446
  // Exit codes alone cannot establish whether the shell refused to launch a
438
447
  // command or a launched runner chose that status after executing tests.
439
448
  return {
440
449
  exitCode: result.exitCode,
441
- stdout: stdout.text,
442
- stderr: stderr.text,
443
- stdoutTruncated: result.stdoutDroppedBytes > 0 || stdout.truncated,
444
- stderrTruncated: result.stderrDroppedBytes > 0 || stderr.truncated,
445
- stdoutDroppedBytes: result.stdoutDroppedBytes + stdout.droppedBytes,
446
- stderrDroppedBytes: result.stderrDroppedBytes + stderr.droppedBytes,
450
+ stdout: result.stdout,
451
+ stderr: result.stderr,
452
+ stdoutTruncated: result.stdoutDroppedBytes > 0,
453
+ stderrTruncated: result.stderrDroppedBytes > 0,
454
+ stdoutDroppedBytes: result.stdoutDroppedBytes,
455
+ stderrDroppedBytes: result.stderrDroppedBytes,
447
456
  ...(mutated === undefined ? {} : { mutated })
448
457
  };
449
458
  });
@@ -1 +1 @@
1
- {"version":3,"file":"Bash.js","sourceRoot":"","sources":["../../src/Bash.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Bash flow declaration and portable handler.\n *\n * Two ways in, and the difference is where the payload is parsed. `command` is\n * a line for the platform shell, exactly as before. `script` is program text\n * delivered to an interpreter on standard input, as data: nothing quotes it,\n * escapes it, or terminates it with a heredoc marker, so the class of failure\n * that produced `docker exec c bash -lc '…python - <<EOF…'` cannot occur. Its\n * `args` reach the script as arguments rather than as interpolated text.\n *\n * `container` names a container the host knows how to reach, and the argv is\n * built by the injected {@link Container} transport rather than typed by the\n * caller. A host that binds no transport refuses such a call by saying so; the\n * requirement is optional here precisely so a host without containers is not\n * forced to declare one.\n *\n * @since 1.0.0\n */\n\nimport type * as ChildProcessSpawner from \"@smthrs/kernel/ChildProcessSpawner\"\nimport * as Path from \"@smthrs/kernel/Path\"\nimport * as Effect from \"effect/Effect\"\nimport * as Option from \"effect/Option\"\nimport * as Schema from \"effect/Schema\"\nimport * as Container from \"./Container.ts\"\nimport { capability, envelope } from \"./internal/Declaration.ts\"\nimport * as Diagnostics from \"./internal/Diagnostics.ts\"\nimport { outsideEnvelope } from \"./internal/EnvelopePrecheck.ts\"\nimport * as Exec from \"./internal/Exec.ts\"\nimport { MAX_SHELL_OUTPUT_BYTES, truncateBytes } from \"./internal/Text.ts\"\nimport * as Probe from \"./Probe.ts\"\nimport * as StdError from \"./StdError.ts\"\nimport * as TreeFingerprint from \"./TreeFingerprint.ts\"\n\n/**\n * Registry name for the bash flow.\n *\n * @category identifiers\n * @since 1.0.0\n */\nexport const name = \"bash\"\n\n/**\n * Model-facing description of the bash flow.\n *\n * Capped at 200 characters and read every frame, which is why the\n * invalid-probe contract is not restated here: the cell contract teaches it\n * once, and a result that has one explains itself.\n *\n * @category descriptions\n * @since 1.0.0\n */\nexport const description =\n \"Run a shell command, or an interpreter over a script passed as data instead of quoted into a line. container routes it through the host's container transport. mode:hermetic pre-checks path tokens.\"\n\n/**\n * Default command timeout in milliseconds.\n *\n * Ten minutes lets full builds and test suites finish while ensuring a stalled\n * process eventually releases the flow.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const DEFAULT_TIMEOUT_MS = 600_000\n\nconst Command = Schema.optional(Schema.String.annotate({\n description: \"Shell command line to execute; give this or script, never both\"\n}))\nconst Script = Schema.optional(Schema.String.annotate({\n description: \"Program text delivered to the interpreter on stdin as data, so it needs no quoting or heredoc\"\n}))\nconst Interpreter = Schema.optional(Schema.String.annotate({\n description:\n \"Program that reads script on stdin; defaults to bash. python, python3, sh, zsh, node, ruby and perl are known\"\n}))\nconst Args = Schema.optional(\n Schema.Array(Schema.String).annotate({\n description: \"Arguments passed to the script as data, never interpolated into it\"\n })\n)\nconst Stdin = Schema.optional(Schema.String.annotate({\n description: \"Text written to the command's standard input; use script instead when the text is the program\"\n}))\nconst ContainerName = Schema.optional(Schema.String.annotate({\n description: \"Run inside this container through the host's container transport; requires mode:unhermetic\"\n}))\nconst Cwd = Schema.optional(Schema.String).annotate({\n description: \"Working directory for the command\",\n message: \"cwd must be a path string. For a checkpoint, pass { at: ctx.base } as the third ctx.call argument.\"\n})\nconst Env = Schema.optional(\n Schema.Record(Schema.String, Schema.String).annotate({ description: \"Environment variables for the command\" })\n)\nconst TimeoutMs = Schema.optional(Schema.Number).annotate({\n description: \"Wall-clock timeout in milliseconds; defaults to 600000 ms\",\n message: \"timeoutMs must be a number of milliseconds.\"\n})\n\n/**\n * Input schema for the bash flow.\n *\n * The mode named `hermetic` requires explicit read and write envelopes for a\n * lexical pre-check; it does not by itself confine the process. Unhermetic mode\n * deliberately omits those declarations so the distinction stays visible in\n * the input shape.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Input = Schema.Union([\n Schema.Struct({\n mode: Schema.Literal(\"hermetic\").annotate({\n description: \"Lexically pre-check explicit path tokens against declared reads and writes; does not sandbox\"\n }),\n command: Command,\n script: Script,\n interpreter: Interpreter,\n args: Args,\n stdin: Stdin,\n container: ContainerName,\n reads: Schema.Array(Schema.NonEmptyString).annotate({ description: \"Paths or path globs the command may read\" }),\n writes: Schema.Array(Schema.NonEmptyString).annotate({ description: \"Paths or path globs the command may write\" }),\n cwd: Cwd,\n env: Env,\n timeoutMs: TimeoutMs\n }),\n Schema.Struct({\n // Omitted means unhermetic: it is the envelope `effects` already declares\n // for every call, so the default grants nothing a named mode would not.\n mode: Schema.Literal(\"unhermetic\").annotate({\n description: \"Run without a declared filesystem envelope as an irreversible effect; the default\"\n }).pipe(Schema.optionalKey, Schema.withDecodingDefaultKey(Effect.succeed(\"unhermetic\" as const))),\n command: Command,\n script: Script,\n interpreter: Interpreter,\n args: Args,\n stdin: Stdin,\n container: ContainerName,\n cwd: Cwd,\n env: Env,\n timeoutMs: TimeoutMs\n })\n])\n\n/**\n * Decoded input accepted by the bash handler.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Input = typeof Input.Type\n\n/**\n * Output schema for the bash flow.\n *\n * `invalidProbe` is present when the shell itself refused to start the\n * command, which its exit code says outright: 127 for a program it could not\n * find, 126 for one it could not execute. Only that. Reading a runner's own\n * wording is a judgment rather than a fact, and `Probe.classify` makes it with\n * Jev for the `test` flow, whose caller is asking about a suite; a shell call\n * is any command at all and stays free of the gateway. See `Probe`.\n *\n * The `<stream>Truncated` flags are a wire convention, not a display detail.\n * A truncated capture is a fragment of what the process printed, and the\n * harness reads these flags to refuse a later write of those exact bytes —\n * `@smthrs/harness/TruncatedOutput` is the consuming half. Renaming a flag, or\n * dropping it when the capture is cut, disarms that guard silently.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Output = Schema.Struct({\n exitCode: Schema.Number.annotate({ description: \"Command exit code, including non-zero codes\" }),\n stdout: Schema.String.annotate({\n description: \"Captured stdout; only the tail, and not the whole output, when stdoutTruncated is true\"\n }),\n stderr: Schema.String.annotate({\n description: \"Captured stderr; only the tail, and not the whole output, when stderrTruncated is true\"\n }),\n stdoutTruncated: Schema.Boolean.annotate({\n description:\n \"Whether stdout exceeded the capture limit, leaving stdout a fragment that must not be written to a file\"\n }),\n stderrTruncated: Schema.Boolean.annotate({\n description:\n \"Whether stderr exceeded the capture limit, leaving stderr a fragment that must not be written to a file\"\n }),\n stdoutDroppedBytes: Schema.Number.annotate({ description: \"UTF-8 bytes omitted from the start of stdout\" }),\n stderrDroppedBytes: Schema.Number.annotate({ description: \"UTF-8 bytes omitted from the start of stderr\" }),\n invalidProbe: Schema.optional(\n Probe.InvalidProbe.annotate({\n description: \"Reserved for a confirmed launch failure; an exit code alone does not establish one\"\n })\n ),\n mutated: Schema.optional(\n Schema.Boolean.annotate({\n description:\n \"Present for a containerised command whose working directory was measured before and after it: true when the tree changed, false when it held still. Absent when the tree was not measured, which is never read as unchanged.\"\n })\n )\n})\n\n/**\n * Decoded output returned by the bash handler.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Output = typeof Output.Type\n\n/**\n * Static conservative effect envelope for the bash flow.\n *\n * The declaration is the registry-time worst case because the mode is not\n * known until an invocation is decoded.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effects = envelope({\n tier: \"irreversible\",\n mode: \"expected\",\n reads: [],\n writes: []\n})\n\n/**\n * Narrows the effect envelope for a decoded invocation.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effectsFor = (input: Input) =>\n input.mode === \"hermetic\"\n ? envelope({\n tier: \"irreversible\",\n mode: \"hermetic\",\n reads: input.reads,\n writes: input.writes\n })\n : envelope({\n tier: \"irreversible\",\n mode: \"expected\",\n reads: [],\n writes: []\n })\n\n/**\n * Capabilities required by the bash flow.\n *\n * @category capabilities\n * @since 1.0.0\n */\nexport const capabilities = [capability(\"proc:spawn\", \"*\")]\n\n/**\n * Declaration-only bash flow.\n *\n * @category flows\n * @since 1.0.0\n */\nexport const flow = { name, description, input: Input, output: Output, capabilities, effects } as const\n\n/*\n * `bash` declares no activity on purpose. What a shell call does is in the\n * command, not in the declaration: the same flow runs a test suite, a type\n * check, and `cat`. A reader that recognises a direct runner says so from the\n * recorded command; everything else stays unknown, which is what an absent\n * activity means.\n */\n\n/**\n * How one recorded call to this flow reads: the verb for each settlement, the\n * input field that is its subject, and the measured output fields a one-line\n * summary may count.\n *\n * Display metadata only, governed by `@smthrs/registry`\n * `Descriptor.CallPresentation` and checked where `StandardFlows` binds it.\n *\n * @category presentation\n * @since 1.0.0-rc.0\n */\nexport const presentation = {\n verb: { pending: \"running\", success: \"ran\", failure: \"failed to run\" },\n subject: \"command\",\n result: \"command\"\n} as const\n\n/**\n * Select standard input explicitly. Shells need `--` before script arguments\n * so even an argument such as `-c` cannot replace the stdin program.\n * Other supported interpreters treat arguments after `-` as program data.\n */\nconst stdinArguments = (interpreter: string): ReadonlyArray<string> | undefined => {\n switch (interpreter) {\n case \"bash\":\n case \"zsh\":\n case \"sh\":\n case \"dash\":\n return [\"-s\", \"--\"]\n case \"python\":\n case \"python3\":\n case \"node\":\n case \"ruby\":\n case \"perl\":\n return [\"-\"]\n default:\n return undefined\n }\n}\n\n/** Whether a script is shell text the lexical pre-check can actually read. */\nconst shells = new Set([\"bash\", \"zsh\", \"sh\", \"dash\"])\n\n/** What one invocation runs, before any container transport rewrites it. */\ninterface Plan {\n readonly file: string\n readonly args: ReadonlyArray<string> | undefined\n readonly stdin: string | undefined\n readonly env: Record<string, string> | undefined\n readonly quoted: string\n}\n\nconst invalid = (message: string): StdError.StdError => new StdError.StdError({ code: \"invalid_input\", message })\n\n/** The invocation an input names, or the failure explaining why it names none. */\nconst plan = (input: Input): Plan | StdError.StdError => {\n const interpreter = input.interpreter ?? \"bash\"\n if (input.command !== undefined && input.script !== undefined) {\n return invalid(\"Give command or script, never both: a script is program text, a command is a shell line\")\n }\n if (input.command === undefined && input.script === undefined) {\n return invalid(\"Give either command (a shell line) or script (program text run by interpreter)\")\n }\n if (input.script !== undefined && input.stdin !== undefined) {\n return invalid(\"A script already arrives on standard input, so it cannot also carry stdin\")\n }\n if (input.command !== undefined && input.args !== undefined) {\n return invalid(\"args belong to a script; a command carries its own arguments in the line\")\n }\n if (input.command !== undefined && input.interpreter !== undefined) {\n return invalid(\"interpreter runs a script; a command runs in the platform shell\")\n }\n if (input.mode === \"hermetic\" && input.container !== undefined) {\n return invalid(\n \"A container has its own filesystem, so declared reads and writes cannot describe it. Use mode:unhermetic for a containerised command\"\n )\n }\n if (input.mode === \"hermetic\" && input.script !== undefined && !shells.has(interpreter)) {\n return invalid(\n `The hermetic pre-check reads shell text, and ${interpreter} is not a shell. Run this script with mode:unhermetic, or express it as shell`\n )\n }\n if (input.command !== undefined) {\n return { file: input.command, args: undefined, stdin: input.stdin, env: input.env, quoted: input.command }\n }\n const selector = stdinArguments(interpreter)\n if (selector === undefined) {\n return invalid(`Unsupported script interpreter: ${interpreter}`)\n }\n const args = [...selector, ...(input.args ?? [])]\n return {\n file: interpreter,\n args,\n stdin: input.script,\n env: input.env,\n quoted: [interpreter, ...args].join(\" \")\n }\n}\n\n/**\n * The plan, refused when its input names no one invocation or when a hermetic\n * call's paths fall outside its declared envelope. Spawned and terminal\n * execution share this one check.\n */\nconst precheck = (input: Input, path: Path.Path): Plan | StdError.StdError => {\n const intent = plan(input)\n if (intent instanceof StdError.StdError || input.mode !== \"hermetic\") return intent\n // A planned call carries exactly one of command or script.\n return outsideEnvelope(input, input.command ?? input.script!, path) ?? intent\n}\n\n/** The plan as the host will spawn it, once the container transport has had it. */\nconst routed = (\n plan: Plan,\n input: Input,\n transport: Option.Option<Container.Container>\n): Effect.Effect<Plan, StdError.StdError> => {\n if (input.container === undefined) return Effect.succeed(plan)\n if (Option.isNone(transport)) return Effect.fail(Container.unavailable(input.container))\n return Effect.map(\n transport.value.exec(request(plan, input, input.container)),\n (routing): Plan => ({\n file: routing.file,\n args: routing.args,\n stdin: plan.stdin,\n env: routing.env,\n // Diagnostics describe the logical invocation, not transport arguments.\n quoted: plan.quoted\n })\n )\n}\n\n/**\n * One containerised request, always through a login shell.\n *\n * A container's environment is what its profile makes it. The images this\n * harness runs against activate the project's interpreter — a conda env, a\n * virtualenv, a modified `PATH` — from `/etc/profile.d`, so a program spawned\n * directly by `docker exec` gets a different Python from the one that owns the\n * repository's dependencies. That is measured, not theoretical: r90 typed\n * `docker exec … bash -lc '…'` by hand and got the activation for free, r91\n * routed `interpreter: \"python3\"` straight at the container and filled its\n * traces with `ModuleNotFoundError: No module named 'numpy'` and\n * `exec: \"/usr/local/bin/python\": no such file or directory`. Thirty of 45\n * instances then spent 138 cells scanning `/opt` for the real interpreter.\n *\n * So the login shell is the transport's, not the caller's. A command line is\n * one argument to `bash -lc`, as before. A program run under an interpreter\n * becomes `bash -lc 'exec \"$@\"' bash <interpreter> <args…>`: the shell reads\n * the profile, then `exec` replaces it with the interpreter, so the script\n * still arrives on the inherited standard input and no argument is ever\n * re-parsed as shell text.\n */\nconst request = (plan: Plan, input: Input, container: string): Container.Request => ({\n container,\n file: \"bash\",\n args: plan.args === undefined\n ? [\"-lc\", plan.file]\n : [\"-lc\", `exec \"$@\"`, \"bash\", plan.file, ...plan.args],\n ...(input.cwd === undefined ? {} : { cwd: input.cwd }),\n ...(input.env === undefined ? {} : { env: input.env }),\n stdin: plan.stdin !== undefined\n})\n\n/** How long one fingerprint of the container's working directory may take. */\nconst FINGERPRINT_TIMEOUT_MS = 60_000\n\n/**\n * Measures the tree a containerised command is about to run in, or just ran in.\n *\n * The host's workspace walk cannot see a container's filesystem, so the\n * measurement is taken where the tree is: `TreeFingerprint.script` runs\n * through the same transport as the command, in the same working directory,\n * and answers with one checksum. Every way this can fail — no transport, a\n * container without `find` or `stat`, a timeout, a bounded listing — is read\n * as \"unmeasured\" and reported as an absent `mutated`, never as a tree that\n * held still. The time it costs is bounded by the command's own timeout so a\n * stalled container cannot spend more waiting to be measured than it may\n * spend running.\n */\nconst fingerprint = (\n input: Input,\n transport: Option.Option<Container.Container>\n): Effect.Effect<TreeFingerprint.Measurement | undefined, never, ChildProcessSpawner.ChildProcessSpawner> =>\n Effect.gen(function*() {\n if (input.container === undefined || Option.isNone(transport)) return undefined\n const routing = yield* transport.value.exec({\n container: input.container,\n file: \"sh\",\n args: [\"-c\", TreeFingerprint.script()],\n ...(input.cwd === undefined ? {} : { cwd: input.cwd }),\n stdin: false\n })\n const result = yield* Exec.exec(routing.file, {\n ...(routing.env === undefined ? {} : { env: routing.env }),\n timeoutMs: Math.min(input.timeoutMs ?? DEFAULT_TIMEOUT_MS, FINGERPRINT_TIMEOUT_MS),\n maxCaptureBytes: MAX_SHELL_OUTPUT_BYTES,\n args: routing.args\n })\n return result.exitCode === 0 ? TreeFingerprint.parse(result.stdout) : undefined\n }).pipe(Effect.orElseSucceed(() => undefined))\n\n/**\n * Executes a shell command through the permission-aware kernel service.\n *\n * Non-zero exit codes remain successful values. Only timeout, host, permission,\n * and declared-envelope pre-check failures use the typed error channel.\n *\n * @category handlers\n * @since 1.0.0\n */\nexport const run = Effect.fn(\"Bash.run\")(function*(\n input: Input\n): Effect.fn.Return<Output, StdError.StdError, ChildProcessSpawner.ChildProcessSpawner | Path.Path> {\n const intent = precheck(input, yield* Path.Path)\n if (intent instanceof StdError.StdError) return yield* Effect.fail(intent)\n // The working directory belongs to the container. The transport supplies\n // any environment overrides its host process needs to forward into it.\n const contained = input.container !== undefined\n const transport = yield* Effect.serviceOption(Container.Container)\n const spawned = yield* routed(intent, input, transport)\n\n // The tree the command runs in, before it runs. Measured in the container\n // because nothing on this host can see it; see `TreeFingerprint`.\n const before = yield* fingerprint(input, transport)\n const result = yield* Exec.exec(spawned.file, {\n ...(input.cwd === undefined || contained ? {} : { cwd: input.cwd }),\n ...(spawned.env === undefined ? {} : { env: spawned.env }),\n timeoutMs: input.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n maxCaptureBytes: MAX_SHELL_OUTPUT_BYTES,\n ...(spawned.args === undefined ? {} : { args: spawned.args }),\n ...(spawned.stdin === undefined ? {} : { stdin: spawned.stdin })\n }).pipe(Effect.mapError((error) => Exec.toStdError(spawned.quoted, error)))\n const mutated = TreeFingerprint.moved(before, yield* fingerprint(input, transport))\n // A command on this host may have changed files a language server holds\n // open; a container's files are not the ones it was sent.\n if (!contained) yield* Diagnostics.refresh\n const stdout = truncateBytes(result.stdout, MAX_SHELL_OUTPUT_BYTES, { keep: \"tail\" })\n const stderr = truncateBytes(result.stderr, MAX_SHELL_OUTPUT_BYTES, { keep: \"tail\" })\n // Exit codes alone cannot establish whether the shell refused to launch a\n // command or a launched runner chose that status after executing tests.\n return {\n exitCode: result.exitCode,\n stdout: stdout.text,\n stderr: stderr.text,\n stdoutTruncated: result.stdoutDroppedBytes > 0 || stdout.truncated,\n stderrTruncated: result.stderrDroppedBytes > 0 || stderr.truncated,\n stdoutDroppedBytes: result.stdoutDroppedBytes + stdout.droppedBytes,\n stderrDroppedBytes: result.stderrDroppedBytes + stderr.droppedBytes,\n ...(mutated === undefined ? {} : { mutated })\n }\n})\n\n/**\n * What one call runs, after planning and before any transport: the program,\n * its arguments (absent for a shell command line), standard input, the\n * caller's environment, and the logical invocation as a person reads it.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Invocation {\n readonly file: string\n readonly args: ReadonlyArray<string> | undefined\n readonly stdin: string | undefined\n readonly env: Record<string, string> | undefined\n readonly quoted: string\n}\n\n/**\n * The invocation `input` names, or the typed refusal explaining why it names\n * none. The same plan {@link run} spawns; a terminal provider runs it instead.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const invocation = (input: Input): Invocation | StdError.StdError => plan(input)\n\n/**\n * {@link run}'s contract through a registered terminal (T-TRM-05): the same\n * plan, hermetic pre-check, bounded output and diagnostics refresh, with\n * execution supplied by `execute` instead of a spawn on this host. A terminal\n * has no container transport, so a containerised call is refused before it\n * reaches `execute`.\n *\n * @category handlers\n * @since 1.0.0\n */\nexport const inTerminal = <R>(\n execute: (input: Input) => Effect.Effect<Output, StdError.StdError, R>\n) =>\n Effect.fn(\"Bash.inTerminal\")(function*(\n input: Input\n ): Effect.fn.Return<Output, StdError.StdError, R | Path.Path> {\n const intent = precheck(input, yield* Path.Path)\n if (intent instanceof StdError.StdError) return yield* Effect.fail(intent)\n if (input.container !== undefined) return yield* Effect.fail(Container.unavailable(input.container))\n const output = yield* execute(input)\n // The terminal ran on this workspace: files a language server holds may\n // have changed, exactly as after a spawn here.\n yield* Diagnostics.refresh\n return output\n })\n\n/**\n * The refusal a sealed host answers a call outside its container with.\n *\n * @category errors\n * @since 1.0.0-rc.1\n */\nexport const outsideContainer = (sealedTo: string, requested: string | undefined): StdError.StdError =>\n new StdError.StdError({\n code: \"outside_container\",\n message: requested === undefined\n ? `This host runs commands only inside container \"${sealedTo}\". Name it: { mode: \"unhermetic\", container: \"${sealedTo}\", command: \"...\" }.`\n : `This host runs commands only inside container \"${sealedTo}\", not \"${requested}\".`\n })\n\n/**\n * {@link run}, sealed to one container.\n *\n * A host that must not be reachable from the cell (a benchmark host holding\n * other tasks' tests and reference solutions, say) binds this instead of\n * {@link run}: a call naming `sealedTo` runs as usual, and every other call,\n * including one with no container that would run on the host, fails with\n * `outside_container` before anything is spawned.\n *\n * @category handlers\n * @since 1.0.0-rc.1\n */\nexport const sealed = (sealedTo: string) =>\n(\n input: Input\n): Effect.Effect<Output, StdError.StdError, ChildProcessSpawner.ChildProcessSpawner | Path.Path> =>\n input.container === sealedTo ? run(input) : Effect.fail(outsideContainer(sealedTo, input.container))\n"]}
1
+ {"version":3,"file":"Bash.js","sourceRoot":"","sources":["../../src/Bash.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Bash flow declaration and portable handler.\n *\n * Two ways in, and the difference is where the payload is parsed. `command` is\n * a line for the platform shell, exactly as before. `script` is program text\n * delivered to an interpreter on standard input, as data: nothing quotes it,\n * escapes it, or terminates it with a heredoc marker, so the class of failure\n * that produced `docker exec c bash -lc '…python - <<EOF…'` cannot occur. Its\n * `args` reach the script as arguments rather than as interpolated text.\n *\n * `container` names a container the host knows how to reach, and the argv is\n * built by the injected {@link Container} transport rather than typed by the\n * caller. A host that binds no transport refuses such a call by saying so; the\n * requirement is optional here precisely so a host without containers is not\n * forced to declare one.\n *\n * @since 1.0.0\n */\n\nimport type * as ChildProcessSpawner from \"@smthrs/kernel/ChildProcessSpawner\"\nimport * as Path from \"@smthrs/kernel/Path\"\nimport * as Effect from \"effect/Effect\"\nimport * as Option from \"effect/Option\"\nimport * as Schema from \"effect/Schema\"\nimport * as Container from \"./Container.ts\"\nimport { capability, envelope } from \"./internal/Declaration.ts\"\nimport * as Diagnostics from \"./internal/Diagnostics.ts\"\nimport { outsideEnvelope } from \"./internal/EnvelopePrecheck.ts\"\nimport * as Exec from \"./internal/Exec.ts\"\nimport { elideMiddle as elide, MAX_SHELL_OUTPUT_BYTES } from \"./internal/Text.ts\"\nimport * as Probe from \"./Probe.ts\"\nimport * as StdError from \"./StdError.ts\"\nimport * as TreeFingerprint from \"./TreeFingerprint.ts\"\n\n/**\n * Registry name for the bash flow.\n *\n * @category identifiers\n * @since 1.0.0\n */\nexport const name = \"bash\"\n\n/**\n * Model-facing description of the bash flow.\n *\n * Capped at 200 characters and read every frame, which is why the\n * invalid-probe contract is not restated here: the cell contract teaches it\n * once, and a result that has one explains itself.\n *\n * @category descriptions\n * @since 1.0.0\n */\nexport const description =\n \"Run a shell command, or an interpreter over a script passed as data instead of quoted into a line. container routes it through the host's container transport. mode:hermetic pre-checks path tokens.\"\n\n/**\n * Default command timeout in milliseconds.\n *\n * Ten minutes lets full builds and test suites finish while ensuring a stalled\n * process eventually releases the flow.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const DEFAULT_TIMEOUT_MS = 600_000\n\nconst Command = Schema.optional(Schema.String.annotate({\n description: \"Shell command line to execute; give this or script, never both\"\n}))\nconst Script = Schema.optional(Schema.String.annotate({\n description: \"Program text delivered to the interpreter on stdin as data, so it needs no quoting or heredoc\"\n}))\nconst Interpreter = Schema.optional(Schema.String.annotate({\n description:\n \"Program that reads script on stdin; defaults to bash. python, python3, sh, zsh, node, ruby and perl are known\"\n}))\nconst Args = Schema.optional(\n Schema.Array(Schema.String).annotate({\n description: \"Arguments passed to the script as data, never interpolated into it\"\n })\n)\nconst Stdin = Schema.optional(Schema.String.annotate({\n description: \"Text written to the command's standard input; use script instead when the text is the program\"\n}))\nconst ContainerName = Schema.optional(Schema.String.annotate({\n description: \"Run inside this container through the host's container transport; requires mode:unhermetic\"\n}))\nconst Cwd = Schema.optional(Schema.String).annotate({\n description: \"Working directory for the command\",\n message: \"cwd must be a path string. For a checkpoint, pass { at: ctx.base } as the third ctx.call argument.\"\n})\nconst Env = Schema.optional(\n Schema.Record(Schema.String, Schema.String).annotate({ description: \"Environment variables for the command\" })\n)\nconst TimeoutMs = Schema.optional(Schema.Number).annotate({\n description: \"Wall-clock timeout in milliseconds; defaults to 600000 ms\",\n message: \"timeoutMs must be a number of milliseconds.\"\n})\n\n/**\n * Input schema for the bash flow.\n *\n * The mode named `hermetic` requires explicit read and write envelopes for a\n * lexical pre-check; it does not by itself confine the process. Unhermetic mode\n * deliberately omits those declarations so the distinction stays visible in\n * the input shape.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Input = Schema.Union([\n Schema.Struct({\n mode: Schema.Literal(\"hermetic\").annotate({\n description: \"Lexically pre-check explicit path tokens against declared reads and writes; does not sandbox\"\n }),\n command: Command,\n script: Script,\n interpreter: Interpreter,\n args: Args,\n stdin: Stdin,\n container: ContainerName,\n reads: Schema.Array(Schema.NonEmptyString).annotate({ description: \"Paths or path globs the command may read\" }),\n writes: Schema.Array(Schema.NonEmptyString).annotate({ description: \"Paths or path globs the command may write\" }),\n cwd: Cwd,\n env: Env,\n timeoutMs: TimeoutMs\n }),\n Schema.Struct({\n // Omitted means unhermetic: it is the envelope `effects` already declares\n // for every call, so the default grants nothing a named mode would not.\n mode: Schema.Literal(\"unhermetic\").annotate({\n description: \"Run without a declared filesystem envelope as an irreversible effect; the default\"\n }).pipe(Schema.optionalKey, Schema.withDecodingDefaultKey(Effect.succeed(\"unhermetic\" as const))),\n command: Command,\n script: Script,\n interpreter: Interpreter,\n args: Args,\n stdin: Stdin,\n container: ContainerName,\n cwd: Cwd,\n env: Env,\n timeoutMs: TimeoutMs\n })\n])\n\n/**\n * Decoded input accepted by the bash handler.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Input = typeof Input.Type\n\n/**\n * Output schema for the bash flow.\n *\n * `invalidProbe` is present when the shell itself refused to start the\n * command, which its exit code says outright: 127 for a program it could not\n * find, 126 for one it could not execute. Only that. Reading a runner's own\n * wording is a judgment rather than a fact, and `Probe.classify` makes it with\n * Jev for the `test` flow, whose caller is asking about a suite; a shell call\n * is any command at all and stays free of the gateway. See `Probe`.\n *\n * The `<stream>Truncated` flags are a wire convention, not a display detail.\n * A truncated capture is a fragment of what the process printed, and the\n * harness reads these flags to refuse a later write of those exact bytes —\n * `@smthrs/harness/TruncatedOutput` is the consuming half. Renaming a flag, or\n * dropping it when the capture is cut, disarms that guard silently.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Output = Schema.Struct({\n exitCode: Schema.Number.annotate({ description: \"Command exit code, including non-zero codes\" }),\n stdout: Schema.String.annotate({\n description:\n \"Captured stdout; when stdoutTruncated is true, only its start and end, with one line naming the bytes omitted between them\"\n }),\n stderr: Schema.String.annotate({\n description:\n \"Captured stderr; when stderrTruncated is true, only its start and end, with one line naming the bytes omitted between them\"\n }),\n stdoutTruncated: Schema.Boolean.annotate({\n description:\n \"Whether stdout exceeded the capture limit, leaving stdout a fragment that must not be written to a file\"\n }),\n stderrTruncated: Schema.Boolean.annotate({\n description:\n \"Whether stderr exceeded the capture limit, leaving stderr a fragment that must not be written to a file\"\n }),\n stdoutDroppedBytes: Schema.Number.annotate({ description: \"UTF-8 bytes omitted from the middle of stdout\" }),\n stderrDroppedBytes: Schema.Number.annotate({ description: \"UTF-8 bytes omitted from the middle of stderr\" }),\n invalidProbe: Schema.optional(\n Probe.InvalidProbe.annotate({\n description: \"Reserved for a confirmed launch failure; an exit code alone does not establish one\"\n })\n ),\n mutated: Schema.optional(\n Schema.Boolean.annotate({\n description:\n \"Present for a containerised command whose working directory was measured before and after it: true when the tree changed, false when it held still. Absent when the tree was not measured, which is never read as unchanged.\"\n })\n )\n})\n\n/**\n * Decoded output returned by the bash handler.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Output = typeof Output.Type\n\n/**\n * The text of a stream cut to its start and end: the start, one line naming\n * the bytes omitted between them, and the end. A host that captures output\n * itself, such as a terminal behind {@link inTerminal}, cuts with this so every\n * {@link Output} reads the same.\n *\n * @category rendering\n * @since 1.0.0-rc.5\n */\nexport const elideMiddle: (start: string, droppedBytes: number, end: string) => string = elide\n\n/**\n * Static conservative effect envelope for the bash flow.\n *\n * The declaration is the registry-time worst case because the mode is not\n * known until an invocation is decoded.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effects = envelope({\n tier: \"irreversible\",\n mode: \"expected\",\n reads: [],\n writes: []\n})\n\n/**\n * Narrows the effect envelope for a decoded invocation.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effectsFor = (input: Input) =>\n input.mode === \"hermetic\"\n ? envelope({\n tier: \"irreversible\",\n mode: \"hermetic\",\n reads: input.reads,\n writes: input.writes\n })\n : envelope({\n tier: \"irreversible\",\n mode: \"expected\",\n reads: [],\n writes: []\n })\n\n/**\n * Capabilities required by the bash flow.\n *\n * @category capabilities\n * @since 1.0.0\n */\nexport const capabilities = [capability(\"proc:spawn\", \"*\")]\n\n/**\n * Declaration-only bash flow.\n *\n * @category flows\n * @since 1.0.0\n */\nexport const flow = { name, description, input: Input, output: Output, capabilities, effects } as const\n\n/*\n * `bash` declares no activity on purpose. What a shell call does is in the\n * command, not in the declaration: the same flow runs a test suite, a type\n * check, and `cat`. A reader that recognises a direct runner says so from the\n * recorded command; everything else stays unknown, which is what an absent\n * activity means.\n */\n\n/**\n * How one recorded call to this flow reads: the verb for each settlement, the\n * input field that is its subject, and the measured output fields a one-line\n * summary may count.\n *\n * Display metadata only, governed by `@smthrs/registry`\n * `Descriptor.CallPresentation` and checked where `StandardFlows` binds it.\n *\n * @category presentation\n * @since 1.0.0-rc.0\n */\nexport const presentation = {\n verb: { pending: \"running\", success: \"ran\", failure: \"failed to run\" },\n subject: \"command\",\n result: \"command\"\n} as const\n\n/**\n * Select standard input explicitly. Shells need `--` before script arguments\n * so even an argument such as `-c` cannot replace the stdin program.\n * Other supported interpreters treat arguments after `-` as program data.\n */\nconst stdinArguments = (interpreter: string): ReadonlyArray<string> | undefined => {\n switch (interpreter) {\n case \"bash\":\n case \"zsh\":\n case \"sh\":\n case \"dash\":\n return [\"-s\", \"--\"]\n case \"python\":\n case \"python3\":\n case \"node\":\n case \"ruby\":\n case \"perl\":\n return [\"-\"]\n default:\n return undefined\n }\n}\n\n/** Whether a script is shell text the lexical pre-check can actually read. */\nconst shells = new Set([\"bash\", \"zsh\", \"sh\", \"dash\"])\n\n/** What one invocation runs, before any container transport rewrites it. */\ninterface Plan {\n readonly file: string\n readonly args: ReadonlyArray<string> | undefined\n readonly stdin: string | undefined\n readonly env: Record<string, string> | undefined\n readonly quoted: string\n}\n\nconst invalid = (message: string): StdError.StdError => new StdError.StdError({ code: \"invalid_input\", message })\n\n/** The invocation an input names, or the failure explaining why it names none. */\nconst plan = (input: Input): Plan | StdError.StdError => {\n const interpreter = input.interpreter ?? \"bash\"\n if (input.command !== undefined && input.script !== undefined) {\n return invalid(\"Give command or script, never both: a script is program text, a command is a shell line\")\n }\n if (input.command === undefined && input.script === undefined) {\n return invalid(\"Give either command (a shell line) or script (program text run by interpreter)\")\n }\n if (input.script !== undefined && input.stdin !== undefined) {\n return invalid(\"A script already arrives on standard input, so it cannot also carry stdin\")\n }\n if (input.command !== undefined && input.args !== undefined) {\n return invalid(\"args belong to a script; a command carries its own arguments in the line\")\n }\n if (input.command !== undefined && input.interpreter !== undefined) {\n return invalid(\"interpreter runs a script; a command runs in the platform shell\")\n }\n if (input.mode === \"hermetic\" && input.container !== undefined) {\n return invalid(\n \"A container has its own filesystem, so declared reads and writes cannot describe it. Use mode:unhermetic for a containerised command\"\n )\n }\n if (input.mode === \"hermetic\" && input.script !== undefined && !shells.has(interpreter)) {\n return invalid(\n `The hermetic pre-check reads shell text, and ${interpreter} is not a shell. Run this script with mode:unhermetic, or express it as shell`\n )\n }\n if (input.command !== undefined) {\n return { file: input.command, args: undefined, stdin: input.stdin, env: input.env, quoted: input.command }\n }\n const selector = stdinArguments(interpreter)\n if (selector === undefined) {\n return invalid(`Unsupported script interpreter: ${interpreter}`)\n }\n const args = [...selector, ...(input.args ?? [])]\n return {\n file: interpreter,\n args,\n stdin: input.script,\n env: input.env,\n quoted: [interpreter, ...args].join(\" \")\n }\n}\n\n/**\n * The plan, refused when its input names no one invocation or when a hermetic\n * call's paths fall outside its declared envelope. Spawned and terminal\n * execution share this one check.\n */\nconst precheck = (input: Input, path: Path.Path): Plan | StdError.StdError => {\n const intent = plan(input)\n if (intent instanceof StdError.StdError || input.mode !== \"hermetic\") return intent\n // A planned call carries exactly one of command or script.\n return outsideEnvelope(input, input.command ?? input.script!, path) ?? intent\n}\n\n/** The plan as the host will spawn it, once the container transport has had it. */\nconst routed = (\n plan: Plan,\n input: Input,\n transport: Option.Option<Container.Container>\n): Effect.Effect<Plan, StdError.StdError> => {\n if (input.container === undefined) return Effect.succeed(plan)\n if (Option.isNone(transport)) return Effect.fail(Container.unavailable(input.container))\n return Effect.map(\n transport.value.exec(request(plan, input, input.container)),\n (routing): Plan => ({\n file: routing.file,\n args: routing.args,\n stdin: plan.stdin,\n env: routing.env,\n // Diagnostics describe the logical invocation, not transport arguments.\n quoted: plan.quoted\n })\n )\n}\n\n/**\n * One containerised request, always through a login shell.\n *\n * A container's environment is what its profile makes it. The images this\n * harness runs against activate the project's interpreter — a conda env, a\n * virtualenv, a modified `PATH` — from `/etc/profile.d`, so a program spawned\n * directly by `docker exec` gets a different Python from the one that owns the\n * repository's dependencies. That is measured, not theoretical: r90 typed\n * `docker exec … bash -lc '…'` by hand and got the activation for free, r91\n * routed `interpreter: \"python3\"` straight at the container and filled its\n * traces with `ModuleNotFoundError: No module named 'numpy'` and\n * `exec: \"/usr/local/bin/python\": no such file or directory`. Thirty of 45\n * instances then spent 138 cells scanning `/opt` for the real interpreter.\n *\n * So the login shell is the transport's, not the caller's. A command line is\n * one argument to `bash -lc`, as before. A program run under an interpreter\n * becomes `bash -lc 'exec \"$@\"' bash <interpreter> <args…>`: the shell reads\n * the profile, then `exec` replaces it with the interpreter, so the script\n * still arrives on the inherited standard input and no argument is ever\n * re-parsed as shell text.\n */\nconst request = (plan: Plan, input: Input, container: string): Container.Request => ({\n container,\n file: \"bash\",\n args: plan.args === undefined\n ? [\"-lc\", plan.file]\n : [\"-lc\", `exec \"$@\"`, \"bash\", plan.file, ...plan.args],\n ...(input.cwd === undefined ? {} : { cwd: input.cwd }),\n ...(input.env === undefined ? {} : { env: input.env }),\n stdin: plan.stdin !== undefined\n})\n\n/** How long one fingerprint of the container's working directory may take. */\nconst FINGERPRINT_TIMEOUT_MS = 60_000\n\n/**\n * Measures the tree a containerised command is about to run in, or just ran in.\n *\n * The host's workspace walk cannot see a container's filesystem, so the\n * measurement is taken where the tree is: `TreeFingerprint.script` runs\n * through the same transport as the command, in the same working directory,\n * and answers with one checksum. Every way this can fail — no transport, a\n * container without `find` or `stat`, a timeout, a bounded listing — is read\n * as \"unmeasured\" and reported as an absent `mutated`, never as a tree that\n * held still. The time it costs is bounded by the command's own timeout so a\n * stalled container cannot spend more waiting to be measured than it may\n * spend running.\n */\nconst fingerprint = (\n input: Input,\n transport: Option.Option<Container.Container>\n): Effect.Effect<TreeFingerprint.Measurement | undefined, never, ChildProcessSpawner.ChildProcessSpawner> =>\n Effect.gen(function*() {\n if (input.container === undefined || Option.isNone(transport)) return undefined\n const routing = yield* transport.value.exec({\n container: input.container,\n file: \"sh\",\n args: [\"-c\", TreeFingerprint.script()],\n ...(input.cwd === undefined ? {} : { cwd: input.cwd }),\n stdin: false\n })\n const result = yield* Exec.exec(routing.file, {\n ...(routing.env === undefined ? {} : { env: routing.env }),\n timeoutMs: Math.min(input.timeoutMs ?? DEFAULT_TIMEOUT_MS, FINGERPRINT_TIMEOUT_MS),\n maxCaptureBytes: MAX_SHELL_OUTPUT_BYTES,\n args: routing.args\n })\n return result.exitCode === 0 ? TreeFingerprint.parse(result.stdout) : undefined\n }).pipe(Effect.orElseSucceed(() => undefined))\n\n/**\n * Executes a shell command through the permission-aware kernel service.\n *\n * Non-zero exit codes remain successful values. Only timeout, host, permission,\n * and declared-envelope pre-check failures use the typed error channel.\n *\n * @category handlers\n * @since 1.0.0\n */\nexport const run = Effect.fn(\"Bash.run\")(function*(\n input: Input\n): Effect.fn.Return<Output, StdError.StdError, ChildProcessSpawner.ChildProcessSpawner | Path.Path> {\n const intent = precheck(input, yield* Path.Path)\n if (intent instanceof StdError.StdError) return yield* Effect.fail(intent)\n // The working directory belongs to the container. The transport supplies\n // any environment overrides its host process needs to forward into it.\n const contained = input.container !== undefined\n const transport = yield* Effect.serviceOption(Container.Container)\n const spawned = yield* routed(intent, input, transport)\n\n // The tree the command runs in, before it runs. Measured in the container\n // because nothing on this host can see it; see `TreeFingerprint`.\n const before = yield* fingerprint(input, transport)\n const result = yield* Exec.exec(spawned.file, {\n ...(input.cwd === undefined || contained ? {} : { cwd: input.cwd }),\n ...(spawned.env === undefined ? {} : { env: spawned.env }),\n timeoutMs: input.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n maxCaptureBytes: MAX_SHELL_OUTPUT_BYTES,\n overflow: \"ends\",\n ...(spawned.args === undefined ? {} : { args: spawned.args }),\n ...(spawned.stdin === undefined ? {} : { stdin: spawned.stdin })\n }).pipe(Effect.mapError((error) => Exec.toStdError(spawned.quoted, error)))\n const mutated = TreeFingerprint.moved(before, yield* fingerprint(input, transport))\n // A command on this host may have changed files a language server holds\n // open; a container's files are not the ones it was sent.\n if (!contained) yield* Diagnostics.refresh\n // Exit codes alone cannot establish whether the shell refused to launch a\n // command or a launched runner chose that status after executing tests.\n return {\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n stdoutTruncated: result.stdoutDroppedBytes > 0,\n stderrTruncated: result.stderrDroppedBytes > 0,\n stdoutDroppedBytes: result.stdoutDroppedBytes,\n stderrDroppedBytes: result.stderrDroppedBytes,\n ...(mutated === undefined ? {} : { mutated })\n }\n})\n\n/**\n * What one call runs, after planning and before any transport: the program,\n * its arguments (absent for a shell command line), standard input, the\n * caller's environment, and the logical invocation as a person reads it.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Invocation {\n readonly file: string\n readonly args: ReadonlyArray<string> | undefined\n readonly stdin: string | undefined\n readonly env: Record<string, string> | undefined\n readonly quoted: string\n}\n\n/**\n * The invocation `input` names, or the typed refusal explaining why it names\n * none. The same plan {@link run} spawns; a terminal provider runs it instead.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const invocation = (input: Input): Invocation | StdError.StdError => plan(input)\n\n/**\n * {@link run}'s contract through a registered terminal (T-TRM-05): the same\n * plan, hermetic pre-check, bounded output and diagnostics refresh, with\n * execution supplied by `execute` instead of a spawn on this host. A terminal\n * has no container transport, so a containerised call is refused before it\n * reaches `execute`.\n *\n * @category handlers\n * @since 1.0.0\n */\nexport const inTerminal = <R>(\n execute: (input: Input) => Effect.Effect<Output, StdError.StdError, R>\n) =>\n Effect.fn(\"Bash.inTerminal\")(function*(\n input: Input\n ): Effect.fn.Return<Output, StdError.StdError, R | Path.Path> {\n const intent = precheck(input, yield* Path.Path)\n if (intent instanceof StdError.StdError) return yield* Effect.fail(intent)\n if (input.container !== undefined) return yield* Effect.fail(Container.unavailable(input.container))\n const output = yield* execute(input)\n // The terminal ran on this workspace: files a language server holds may\n // have changed, exactly as after a spawn here.\n yield* Diagnostics.refresh\n return output\n })\n\n/**\n * The refusal a sealed host answers a call outside its container with.\n *\n * @category errors\n * @since 1.0.0-rc.1\n */\nexport const outsideContainer = (sealedTo: string, requested: string | undefined): StdError.StdError =>\n new StdError.StdError({\n code: \"outside_container\",\n message: requested === undefined\n ? `This host runs commands only inside container \"${sealedTo}\". Name it: { mode: \"unhermetic\", container: \"${sealedTo}\", command: \"...\" }.`\n : `This host runs commands only inside container \"${sealedTo}\", not \"${requested}\".`\n })\n\n/**\n * {@link run}, sealed to one container.\n *\n * A host that must not be reachable from the cell (a benchmark host holding\n * other tasks' tests and reference solutions, say) binds this instead of\n * {@link run}: a call naming `sealedTo` runs as usual, and every other call,\n * including one with no container that would run on the host, fails with\n * `outside_container` before anything is spawned.\n *\n * @category handlers\n * @since 1.0.0-rc.1\n */\nexport const sealed = (sealedTo: string) =>\n(\n input: Input\n): Effect.Effect<Output, StdError.StdError, ChildProcessSpawner.ChildProcessSpawner | Path.Path> =>\n input.container === sealedTo ? run(input) : Effect.fail(outsideContainer(sealedTo, input.container))\n"]}
@@ -60,9 +60,9 @@ export interface ExecResult {
60
60
  readonly stdout: string;
61
61
  readonly stderr: string;
62
62
  readonly exitCode: number;
63
- /** UTF-8 bytes dropped from the head of stdout to stay inside the capture bound. */
63
+ /** UTF-8 bytes of stdout dropped to stay inside the capture bound; see `overflow`. */
64
64
  readonly stdoutDroppedBytes: number;
65
- /** UTF-8 bytes dropped from the head of stderr to stay inside the capture bound. */
65
+ /** UTF-8 bytes of stderr dropped to stay inside the capture bound; see `overflow`. */
66
66
  readonly stderrDroppedBytes: number;
67
67
  }
68
68
  /**
@@ -90,17 +90,24 @@ export interface ExecOptions {
90
90
  */
91
91
  readonly stdin?: string | undefined;
92
92
  /**
93
- * Bytes retained per captured stream. A stream that prints more keeps its
94
- * tail and reports what it dropped, so a command printing gigabytes costs a
95
- * bounded amount of memory rather than the whole of what it printed.
93
+ * Bytes retained per captured stream. A stream that prints more keeps what
94
+ * `overflow` names and reports what it dropped, so a command printing
95
+ * gigabytes costs a bounded amount of memory rather than the whole of what it
96
+ * printed.
96
97
  *
97
98
  * Absent means unbounded, which is what a caller wants when it needs every
98
99
  * byte a tool produced (`rg --files`, `git worktree list`).
99
100
  */
100
101
  readonly maxCaptureBytes?: number | undefined;
101
- /** Defaults to `tail`; `refuse` fails if either stream exceeds the bound. */
102
- readonly overflow?: "tail" | "refuse" | undefined;
102
+ /**
103
+ * What a stream past the bound keeps. `tail`, the default, keeps its last
104
+ * bytes. `ends` keeps its first and last halves and puts one line naming the
105
+ * dropped bytes where the middle was. `refuse` fails if either stream exceeds
106
+ * the bound.
107
+ */
108
+ readonly overflow?: Overflow | undefined;
103
109
  }
110
+ type Overflow = "tail" | "ends" | "refuse";
104
111
  /**
105
112
  * Runs a command line through the platform shell and buffers its output.
106
113
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Exec.d.ts","sourceRoot":"","sources":["../../../src/internal/Exec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,mBAAmB,MAAM,oCAAoC,CAAA;AACzE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAE1C;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,0EAAkE,CAAA;AAE5F;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;;;;IAenD,uDAAuD;;;AAbzD;;;;;;;;;GASG;AACH,qBAAa,SAAU,SAAQ,cAK7B;CAAG;AAEL;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,oFAAoF;IACpF,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;IACnC,oFAAoF;IACpF,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;CACpC;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAA;IAC3D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;IACjD;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC;;;;;;;OAOG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7C,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAA;CAClD;AAiJD;;;;;;;;;GASG;AACH,eAAO,MAAM,IAAI,GACf,SAAS,MAAM,EACf,UAAS,WAAgB,KACxB,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,EAAE,mBAAmB,CAAC,mBAAmB,CAazE,CAAA;AAEN;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,SAAS,KAAG,QAAQ,CAAC,IACF,CAAA;AAEzD;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,EAAE,OAAO,SAAS,KAAG,QAAQ,CAAC,QAOpE,CAAA"}
1
+ {"version":3,"file":"Exec.d.ts","sourceRoot":"","sources":["../../../src/internal/Exec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,mBAAmB,MAAM,oCAAoC,CAAA;AACzE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAG1C;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,0EAAkE,CAAA;AAE5F;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;;;;IAenD,uDAAuD;;;AAbzD;;;;;;;;;GASG;AACH,qBAAa,SAAU,SAAQ,cAK7B;CAAG;AAEL;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,sFAAsF;IACtF,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;IACnC,sFAAsF;IACtF,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;CACpC;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAA;IAC3D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;IACjD;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7C;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAA;CACzC;AAED,KAAK,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAA;AA0N1C;;;;;;;;;GASG;AACH,eAAO,MAAM,IAAI,GACf,SAAS,MAAM,EACf,UAAS,WAAgB,KACxB,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,EAAE,mBAAmB,CAAC,mBAAmB,CAazE,CAAA;AAEN;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,SAAS,KAAG,QAAQ,CAAC,IACF,CAAA;AAEzD;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,EAAE,OAAO,SAAS,KAAG,QAAQ,CAAC,QAOpE,CAAA"}