@molecule/api-ai-tools 1.9.8 → 1.9.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
3
3
  Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
4
4
  Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
5
5
  To change this document, edit the module-level JSDoc in src/index.ts.
6
- Generated: 2026-10-18T02:50:39.697Z
6
+ Generated: 2026-10-18T04:56:57.682Z
7
7
  -->
8
8
 
9
9
  # @molecule/api-ai-tools
@@ -278,6 +278,25 @@ interface GuardOptions {
278
278
  }
279
279
  ```
280
280
 
281
+ #### `RunnerOutputFilter`
282
+
283
+ A cutting stage that follows the runner, and the command with the whole pipe removed.
284
+
285
+ ```typescript
286
+ interface RunnerOutputFilter {
287
+ /** The stage exactly as the runner's command wrote it — `tail -6`. */
288
+ stage: string
289
+ /** The pipe as a sentence names it — `| tail -6`. */
290
+ pipe: string
291
+ /**
292
+ * The command with the pipe and the stage removed — `hurl --variable uid=… --test /tmp/t.hurl
293
+ * 2>&1`. This is a command to send again as written, not a re-typing of it: it is a slice of the
294
+ * original with the filter's own range cut out, so every other word, quote and redirect stays.
295
+ */
296
+ command: string
297
+ }
298
+ ```
299
+
281
300
  #### `ToolSchema`
282
301
 
283
302
  JSON-schema-backed definition for a single agent tool.
@@ -1382,6 +1401,27 @@ function commandRunsNoTests(command: string): boolean
1382
1401
 
1383
1402
  **Returns:** True when the command invokes a runner only to print.
1384
1403
 
1404
+ #### `outputFilterAfterRunner(command, runs)`
1405
+
1406
+ The output filter that follows the runner in `command`, or null when there is none.
1407
+
1408
+ Only a stage of the runner's OWN pipeline counts (its separator is `|`), and only when it is the
1409
+ LAST stage of that pipeline: a `| grep … | wc -l` chain would leave a dangling pipe if the
1410
+ middle stage were cut out, so a chain is not answered here at all. A filter before the runner
1411
+ (`cat run.log | tail -20 && hurl …`) reads something else's output and is not this.
1412
+
1413
+ ```typescript
1414
+ function outputFilterAfterRunner(
1415
+ command: string,
1416
+ runs: (segment: CommandSegment) => boolean,
1417
+ ): RunnerOutputFilter | null
1418
+ ```
1419
+
1420
+ - `command` — The command as the executor sent it.
1421
+ - `runs` — Whether a segment is the runner this run is about (the caller knows its own kind: {@link CommandSegment.program} is the program, once wrapper words like `timeout 280` and `npx` are taken away).
1422
+
1423
+ **Returns:** The filter and the unfiltered command, or null.
1424
+
1385
1425
  #### `pipelineExitCodeNote(command, exitCode, output)`
1386
1426
 
1387
1427
  The sentence an `exec_command` result carries beside `exitCode` when the code belongs to a
package/dist/index.d.ts CHANGED
@@ -138,6 +138,7 @@ export * from './failure-kind.js';
138
138
  export * from './input-normalizer.js';
139
139
  export * from './line-diff.js';
140
140
  export * from './no-test-run.js';
141
+ export * from './output-filter.js';
141
142
  export * from './pipeline-exit-note.js';
142
143
  export * from './schemas.js';
143
144
  export * from './sleep-peek.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkIG;AAEH,cAAc,qBAAqB,CAAA;AACnC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,yBAAyB,CAAA;AACvC,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,YAAY,CAAA;AAC1B,cAAc,sBAAsB,CAAA;AACpC,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkIG;AAEH,cAAc,qBAAqB,CAAA;AACnC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,YAAY,CAAA;AAC1B,cAAc,sBAAsB,CAAA;AACpC,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA"}
package/dist/index.js CHANGED
@@ -138,6 +138,7 @@ export * from './failure-kind.js';
138
138
  export * from './input-normalizer.js';
139
139
  export * from './line-diff.js';
140
140
  export * from './no-test-run.js';
141
+ export * from './output-filter.js';
141
142
  export * from './pipeline-exit-note.js';
142
143
  export * from './schemas.js';
143
144
  export * from './sleep-peek.js';
@@ -0,0 +1,48 @@
1
+ /**
2
+ * A run whose own command piped its output through `tail`/`head`/`grep`/`sed`/`awk`/`cut`, so the
3
+ * failure the runner printed is not in what came back.
4
+ *
5
+ * xr-molecule-flash-m147 (+10:12) sent `hurl --variable uid=… --test /tmp/t.hurl 2>&1 | tail -6`.
6
+ * The six lines that survived are Hurl's closing tally; the failed assertion was above the cut.
7
+ * The platform, seeing a red run with no assertion block, said the cause was "the transport or the
8
+ * run itself" — a sentence that sends the reader at the network for a status assertion it never
9
+ * saw. The command was in the platform's hands the whole time: the pipe is the reader's own filter,
10
+ * not a fact about the run.
11
+ *
12
+ * This module answers the one question that lets a caller say so: is an output-slicing stage of
13
+ * THIS command's pipeline sitting after the runner, and what is the command without it? The parse
14
+ * is the package's own shell reader ({@link locatedCommandSegments}), so a `|` inside quotes or a
15
+ * heredoc is not a stage, and only a stage of the runner's own pipeline is considered.
16
+ *
17
+ * @module
18
+ */
19
+ import { type CommandSegment } from './command-position.js';
20
+ /** A cutting stage that follows the runner, and the command with the whole pipe removed. */
21
+ export interface RunnerOutputFilter {
22
+ /** The stage exactly as the runner's command wrote it — `tail -6`. */
23
+ stage: string;
24
+ /** The pipe as a sentence names it — `| tail -6`. */
25
+ pipe: string;
26
+ /**
27
+ * The command with the pipe and the stage removed — `hurl --variable uid=… --test /tmp/t.hurl
28
+ * 2>&1`. This is a command to send again as written, not a re-typing of it: it is a slice of the
29
+ * original with the filter's own range cut out, so every other word, quote and redirect stays.
30
+ */
31
+ command: string;
32
+ }
33
+ /**
34
+ * The output filter that follows the runner in `command`, or null when there is none.
35
+ *
36
+ * Only a stage of the runner's OWN pipeline counts (its separator is `|`), and only when it is the
37
+ * LAST stage of that pipeline: a `| grep … | wc -l` chain would leave a dangling pipe if the
38
+ * middle stage were cut out, so a chain is not answered here at all. A filter before the runner
39
+ * (`cat run.log | tail -20 && hurl …`) reads something else's output and is not this.
40
+ *
41
+ * @param command - The command as the executor sent it.
42
+ * @param runs - Whether a segment is the runner this run is about (the caller knows its own kind:
43
+ * {@link CommandSegment.program} is the program, once wrapper words like `timeout 280` and
44
+ * `npx` are taken away).
45
+ * @returns The filter and the unfiltered command, or null.
46
+ */
47
+ export declare function outputFilterAfterRunner(command: string, runs: (segment: CommandSegment) => boolean): RunnerOutputFilter | null;
48
+ //# sourceMappingURL=output-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-filter.d.ts","sourceRoot":"","sources":["../src/output-filter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,KAAK,cAAc,EAA0B,MAAM,uBAAuB,CAAA;AASnF,4FAA4F;AAC5F,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAA;IACb,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,GACzC,kBAAkB,GAAG,IAAI,CAkB3B"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * A run whose own command piped its output through `tail`/`head`/`grep`/`sed`/`awk`/`cut`, so the
3
+ * failure the runner printed is not in what came back.
4
+ *
5
+ * xr-molecule-flash-m147 (+10:12) sent `hurl --variable uid=… --test /tmp/t.hurl 2>&1 | tail -6`.
6
+ * The six lines that survived are Hurl's closing tally; the failed assertion was above the cut.
7
+ * The platform, seeing a red run with no assertion block, said the cause was "the transport or the
8
+ * run itself" — a sentence that sends the reader at the network for a status assertion it never
9
+ * saw. The command was in the platform's hands the whole time: the pipe is the reader's own filter,
10
+ * not a fact about the run.
11
+ *
12
+ * This module answers the one question that lets a caller say so: is an output-slicing stage of
13
+ * THIS command's pipeline sitting after the runner, and what is the command without it? The parse
14
+ * is the package's own shell reader ({@link locatedCommandSegments}), so a `|` inside quotes or a
15
+ * heredoc is not a stage, and only a stage of the runner's own pipeline is considered.
16
+ *
17
+ * @module
18
+ */
19
+ import { locatedCommandSegments } from './command-position.js';
20
+ /**
21
+ * The programs whose job is to re-shape what an earlier stage printed and that can DROP lines —
22
+ * the reader's own cut, never part of the run. `tee`, `sort` and `wc` are output plumbing too, but
23
+ * they do not hide a failure, so they are not read as the cause of a missing one.
24
+ */
25
+ const CUTTING_FILTERS = new Set(['awk', 'cut', 'grep', 'head', 'sed', 'tail']);
26
+ /**
27
+ * The output filter that follows the runner in `command`, or null when there is none.
28
+ *
29
+ * Only a stage of the runner's OWN pipeline counts (its separator is `|`), and only when it is the
30
+ * LAST stage of that pipeline: a `| grep … | wc -l` chain would leave a dangling pipe if the
31
+ * middle stage were cut out, so a chain is not answered here at all. A filter before the runner
32
+ * (`cat run.log | tail -20 && hurl …`) reads something else's output and is not this.
33
+ *
34
+ * @param command - The command as the executor sent it.
35
+ * @param runs - Whether a segment is the runner this run is about (the caller knows its own kind:
36
+ * {@link CommandSegment.program} is the program, once wrapper words like `timeout 280` and
37
+ * `npx` are taken away).
38
+ * @returns The filter and the unfiltered command, or null.
39
+ */
40
+ export function outputFilterAfterRunner(command, runs) {
41
+ if (typeof command !== 'string' || command.trim() === '')
42
+ return null;
43
+ const entries = locatedCommandSegments(command);
44
+ const runnerAt = entries.findIndex((entry) => entry.segment !== null && runs(entry.segment));
45
+ if (runnerAt < 0 || runnerAt + 1 >= entries.length)
46
+ return null;
47
+ const runner = entries[runnerAt];
48
+ const filter = entries[runnerAt + 1];
49
+ // The stage must be fed by the runner's own pipe, and nothing may be piped out of the filter:
50
+ // those are the two positions where cutting it out leaves a command that still runs the run.
51
+ if (!runner || !filter || filter.separator.trim() !== '|')
52
+ return null;
53
+ if (!filter.segment || !CUTTING_FILTERS.has(filter.segment.program))
54
+ return null;
55
+ if (filter.terminator.trim() === '|')
56
+ return null;
57
+ if (runner.end === null || filter.start === null || filter.end === null)
58
+ return null;
59
+ return {
60
+ stage: command.slice(filter.start, filter.end),
61
+ pipe: `| ${command.slice(filter.start, filter.end)}`,
62
+ command: `${command.slice(0, runner.end)}${command.slice(filter.end)}`,
63
+ };
64
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/api-ai-tools",
3
- "version": "1.9.8",
3
+ "version": "1.9.9",
4
4
  "description": "Shared AI agent tools with backend abstraction for sandbox and local execution",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",