@molecule/api-ai-tools 1.9.7 → 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-18T00:28:51.925Z
6
+ Generated: 2026-10-18T04:56:57.682Z
7
7
  -->
8
8
 
9
9
  # @molecule/api-ai-tools
@@ -187,6 +187,14 @@ interface CutRun {
187
187
  seconds: number
188
188
  /** Whether this tool's budget stopped it or the `timeout` the command carried. */
189
189
  stoppedBy: CutBy
190
+ /**
191
+ * Whether this was a detached background task, read with no budget of this tool's own
192
+ * ({@link commandCutRun}'s `budgetSeconds` is 0). A background run is bounded by what its own
193
+ * command carries — so a `command-timeout` cut there is that prefix killing the walk, and the
194
+ * executor must be told to drop the prefix, never to start the run in the background it is
195
+ * already in (X1 xr-molecule-flash-m143 +24:45).
196
+ */
197
+ background: boolean
190
198
  /**
191
199
  * The exit code the run's own process reported, or null when the code in the result belongs to
192
200
  * the pipeline's filter (`… | tail`) rather than to the run — the case that read as success.
@@ -270,6 +278,25 @@ interface GuardOptions {
270
278
  }
271
279
  ```
272
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
+
273
300
  #### `ToolSchema`
274
301
 
275
302
  JSON-schema-backed definition for a single agent tool.
@@ -1020,6 +1047,35 @@ function commandTimeoutSeconds(command: string): number | null
1020
1047
 
1021
1048
  **Returns:** The seconds the command allows itself, or null.
1022
1049
 
1050
+ #### `withoutTimeoutWrapper(command, which)`
1051
+
1052
+ The command with the `timeout <N>` wrapper lifted off the statements `which` selects, and the
1053
+ largest bound that was lifted.
1054
+
1055
+ The platform moves a run to the background precisely because its own bound cannot fit this
1056
+ tool's ceiling, and a background task has no ceiling — its wait is bounded by `wait_for_task`
1057
+ and the turn's deadline. The `timeout N` an executor wrote to fit the ceiling therefore keeps
1058
+ killing the run at N in the background, where nothing needed it: X1 xr-molecule-flash-m143
1059
+ (+24:45) wrote `timeout 280` for a 31-test walk, the tool backgrounded it, and the prefix stopped
1060
+ the walk with no tally — then the cut sentence told the executor to "run it in the background",
1061
+ which is where it already was.
1062
+
1063
+ The wrapper is found by the same parse every other command reader uses ({@link commandStart}):
1064
+ `timeout` in an argument bounds nothing, and the wrapper's own flags (`-k`/`--kill-after`,
1065
+ `-s`/`--signal`) are stepped over, so `timeout -k 5 280 …` is `280`.
1066
+
1067
+ ```typescript
1068
+ function withoutTimeoutWrapper(
1069
+ command: string,
1070
+ which: (segment: CommandSegment) => boolean,
1071
+ ): { command: string; seconds: number | null }
1072
+ ```
1073
+
1074
+ - `command` — The shell command.
1075
+ - `which` — The statements to lift the wrapper from (a suite run, for the background path).
1076
+
1077
+ **Returns:** The rewritten command, and the largest lifted bound (null when nothing was lifted).
1078
+
1023
1079
  #### `runsInCommandPosition(command, pattern)`
1024
1080
 
1025
1081
  Whether any segment of the command runs a program whose command-position text matches
@@ -1296,6 +1352,28 @@ function guardAITool(tool: T, options?: GuardOptions): T
1296
1352
 
1297
1353
  **Returns:** A copy with a guarded `execute`.
1298
1354
 
1355
+ #### `diffLineCount(oldLines, newLines)`
1356
+
1357
+ Count truly added/removed lines between two line arrays using LCS.
1358
+
1359
+ Bounded by construction, so a whole-file edit cannot allocate a quadratic
1360
+ table here: the longest common prefix and suffix are trimmed first (exact —
1361
+ those lines belong to every optimal diff, and on the usual small edit they
1362
+ shrink the table to the edited span), and what is left is capped (see
1363
+ {@link lcsLength}).
1364
+
1365
+ ```typescript
1366
+ function diffLineCount(
1367
+ oldLines: readonly string[],
1368
+ newLines: readonly string[],
1369
+ ): { added: number; removed: number }
1370
+ ```
1371
+
1372
+ - `oldLines` — The original lines array.
1373
+ - `newLines` — The modified lines array.
1374
+
1375
+ **Returns:** An object with the number of added and removed lines.
1376
+
1299
1377
  #### `commandRunsNoTests(command)`
1300
1378
 
1301
1379
  Whether a shell command invokes a test runner and EVERY such invocation only prints — so the
@@ -1323,6 +1401,27 @@ function commandRunsNoTests(command: string): boolean
1323
1401
 
1324
1402
  **Returns:** True when the command invokes a runner only to print.
1325
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
+
1326
1425
  #### `pipelineExitCodeNote(command, exitCode, output)`
1327
1426
 
1328
1427
  The sentence an `exec_command` result carries beside `exitCode` when the code belongs to a
@@ -1780,7 +1879,7 @@ function stalledDocumentSubresource(request: TraceRequest): boolean
1780
1879
 
1781
1880
  **Returns:** True when the request is a document subresource that never finished.
1782
1881
 
1783
- #### `failureTraceNote(items, target, earlierFailures)`
1882
+ #### `failureTraceNote(items, target, earlierFailures, apiPrefixes)`
1784
1883
 
1785
1884
  The note a failed suite run's result carries: what each failing test's page actually sent, and
1786
1885
  what came back.
@@ -1811,12 +1910,14 @@ function failureTraceNote(
1811
1910
  items: readonly TraceArtifact[],
1812
1911
  target: string,
1813
1912
  earlierFailures?: readonly string[],
1913
+ apiPrefixes?: readonly string[],
1814
1914
  ): string | null
1815
1915
  ```
1816
1916
 
1817
1917
  - `items` — The traces {@link parseTraceArtifacts} read.
1818
1918
  - `target` — Where the run went — the deployed host, as the note names it.
1819
1919
  - `earlierFailures` — The failing `file:line`s earlier walks of this suite left, so a repeat is ranked above a one-off. Empty when the caller knows of no earlier walk.
1920
+ - `apiPrefixes` — The API path prefixes the app's client config names (`['/api']`), read from the app by the caller. Empty when the caller could not read one; the traces' own requests may still supply it. Never a hard-coded literal.
1820
1921
 
1821
1922
  **Returns:** The note, or null when no trace held a recorded response, a real failure or a console error.
1822
1923
 
@@ -2075,6 +2176,24 @@ function isSuiteRunCommand(command: string): boolean
2075
2176
 
2076
2177
  **Returns:** True when the command starts one of those runners.
2077
2178
 
2179
+ #### `withoutSuiteTimeout(command)`
2180
+
2181
+ The command with the `timeout <N>` wrapper lifted off the statement that runs the suite, and the
2182
+ bound that was lifted.
2183
+
2184
+ Used where the platform moves a run to the background: the executor wrote the bound to fit this
2185
+ tool's foreground ceiling, and in the background that ceiling no longer applies — the task is
2186
+ bounded by `wait_for_task` and the turn's deadline — so the prefix only kills the walk
2187
+ ({@link withoutTimeoutWrapper}; X1 xr-molecule-flash-m143 +24:45).
2188
+
2189
+ ```typescript
2190
+ function withoutSuiteTimeout(command: string): { command: string; seconds: number | null }
2191
+ ```
2192
+
2193
+ - `command` — The shell command.
2194
+
2195
+ **Returns:** The rewritten command, and the largest lifted bound (null when nothing was lifted).
2196
+
2078
2197
  #### `isPlaywrightRunCommand(command)`
2079
2198
 
2080
2199
  Whether a command starts a Playwright run — a `playwright test` in command position, in a form
@@ -172,6 +172,30 @@ export declare function statementArgumentEnd(command: string, start: number | nu
172
172
  * @returns The seconds the command allows itself, or null.
173
173
  */
174
174
  export declare function commandTimeoutSeconds(command: string): number | null;
175
+ /**
176
+ * The command with the `timeout <N>` wrapper lifted off the statements `which` selects, and the
177
+ * largest bound that was lifted.
178
+ *
179
+ * The platform moves a run to the background precisely because its own bound cannot fit this
180
+ * tool's ceiling, and a background task has no ceiling — its wait is bounded by `wait_for_task`
181
+ * and the turn's deadline. The `timeout N` an executor wrote to fit the ceiling therefore keeps
182
+ * killing the run at N in the background, where nothing needed it: X1 xr-molecule-flash-m143
183
+ * (+24:45) wrote `timeout 280` for a 31-test walk, the tool backgrounded it, and the prefix stopped
184
+ * the walk with no tally — then the cut sentence told the executor to "run it in the background",
185
+ * which is where it already was.
186
+ *
187
+ * The wrapper is found by the same parse every other command reader uses ({@link commandStart}):
188
+ * `timeout` in an argument bounds nothing, and the wrapper's own flags (`-k`/`--kill-after`,
189
+ * `-s`/`--signal`) are stepped over, so `timeout -k 5 280 …` is `280`.
190
+ *
191
+ * @param command - The shell command.
192
+ * @param which - The statements to lift the wrapper from (a suite run, for the background path).
193
+ * @returns The rewritten command, and the largest lifted bound (null when nothing was lifted).
194
+ */
195
+ export declare function withoutTimeoutWrapper(command: string, which: (segment: CommandSegment) => boolean): {
196
+ command: string;
197
+ seconds: number | null;
198
+ };
175
199
  /**
176
200
  * Whether any segment of the command runs a program whose command-position text matches
177
201
  * `pattern` — the one question a runner-kind table asks.
@@ -1 +1 @@
1
- {"version":3,"file":"command-position.d.ts","sourceRoot":"","sources":["../src/command-position.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,uFAAuF;AACvF,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,qFAAqF;IACrF,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,4FAA4F;IAC5F,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAqND;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM3D;AAmjBD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAIjE;AAmCD;;;;;;;;;GASG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,OAAO,EAAE,cAAc,GAAG,IAAI,CAAA;IAC9B,0FAA0F;IAC1F,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9B;;;;OAIG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B;;;OAGG;IACH,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB;;;;OAIG;IACH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;OAKG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAE/E;AAmDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,GAAG,EAAE,MAAM,GAAG,IAAI,GACjB,MAAM,GAAG,IAAI,CAyDf;AAwFD;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOpE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAK/E"}
1
+ {"version":3,"file":"command-position.d.ts","sourceRoot":"","sources":["../src/command-position.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,uFAAuF;AACvF,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,qFAAqF;IACrF,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,4FAA4F;IAC5F,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAqND;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM3D;AAmjBD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAIjE;AAmCD;;;;;;;;;GASG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,OAAO,EAAE,cAAc,GAAG,IAAI,CAAA;IAC9B,0FAA0F;IAC1F,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9B;;;;OAIG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B;;;OAGG;IACH,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB;;;;OAIG;IACH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;OAKG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAE/E;AAmDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,GAAG,EAAE,MAAM,GAAG,IAAI,GACjB,MAAM,GAAG,IAAI,CAyDf;AAwFD;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOpE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,GAC1C;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAoD7C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAK/E"}
@@ -1076,6 +1076,87 @@ export function commandTimeoutSeconds(command) {
1076
1076
  }
1077
1077
  return bound;
1078
1078
  }
1079
+ /**
1080
+ * The command with the `timeout <N>` wrapper lifted off the statements `which` selects, and the
1081
+ * largest bound that was lifted.
1082
+ *
1083
+ * The platform moves a run to the background precisely because its own bound cannot fit this
1084
+ * tool's ceiling, and a background task has no ceiling — its wait is bounded by `wait_for_task`
1085
+ * and the turn's deadline. The `timeout N` an executor wrote to fit the ceiling therefore keeps
1086
+ * killing the run at N in the background, where nothing needed it: X1 xr-molecule-flash-m143
1087
+ * (+24:45) wrote `timeout 280` for a 31-test walk, the tool backgrounded it, and the prefix stopped
1088
+ * the walk with no tally — then the cut sentence told the executor to "run it in the background",
1089
+ * which is where it already was.
1090
+ *
1091
+ * The wrapper is found by the same parse every other command reader uses ({@link commandStart}):
1092
+ * `timeout` in an argument bounds nothing, and the wrapper's own flags (`-k`/`--kill-after`,
1093
+ * `-s`/`--signal`) are stepped over, so `timeout -k 5 280 …` is `280`.
1094
+ *
1095
+ * @param command - The shell command.
1096
+ * @param which - The statements to lift the wrapper from (a suite run, for the background path).
1097
+ * @returns The rewritten command, and the largest lifted bound (null when nothing was lifted).
1098
+ */
1099
+ export function withoutTimeoutWrapper(command, which) {
1100
+ if (typeof command !== 'string' || !command.trim())
1101
+ return { command, seconds: null };
1102
+ /** The spans to remove, as offsets in the command — applied back to front. */
1103
+ const removals = [];
1104
+ let seconds = null;
1105
+ for (const located of locatedSegmentsOf(command, 0)) {
1106
+ const segment = located.segment;
1107
+ if (segment === null || segment.timeoutSeconds === null)
1108
+ continue;
1109
+ // A statement inside a nested `sh -c '…'` has no offsets here: its positions are positions in
1110
+ // that string, so nothing may be spliced at them.
1111
+ if (located.start === null || located.programOffset === null)
1112
+ continue;
1113
+ if (!which(segment))
1114
+ continue;
1115
+ // Every word in front of the program: the assignments and the wrappers. The duration belongs
1116
+ // to the wrapper, so the walk has to see the words, not just the parse's total bound.
1117
+ const prefix = command.slice(located.start, located.programOffset);
1118
+ const words = [];
1119
+ const at = new RegExp(WORD.source, 'g');
1120
+ for (let match = at.exec(prefix); match !== null; match = at.exec(prefix)) {
1121
+ words.push({
1122
+ text: match[0],
1123
+ start: located.start + match.index,
1124
+ end: located.start + match.index + match[0].length,
1125
+ });
1126
+ }
1127
+ for (let i = 0; i < words.length; i += 1) {
1128
+ const word = words[i];
1129
+ if (word === undefined || programName(word.text) !== 'timeout')
1130
+ continue;
1131
+ // The wrapper's own flags, then the duration — the same walk {@link commandStart} makes.
1132
+ const withValue = WRAPPER_VALUE_FLAGS.timeout ?? [];
1133
+ let next = i + 1;
1134
+ while (next < words.length && (words[next]?.text ?? '').startsWith('-')) {
1135
+ const flag = unquoted(words[next]?.text ?? '');
1136
+ next += !flag.includes('=') && withValue.includes(flag) ? 2 : 1;
1137
+ }
1138
+ const duration = words[next];
1139
+ const bound = duration === undefined ? null : durationSeconds(unquoted(duration.text));
1140
+ if (duration === undefined || bound === null)
1141
+ continue;
1142
+ seconds = seconds === null ? bound : Math.max(seconds, bound);
1143
+ // The whitespace between the duration and the program goes too, so the command does not
1144
+ // carry a double space where the wrapper stood.
1145
+ let end = duration.end;
1146
+ while (end < command.length && /\s/.test(command[end] ?? ''))
1147
+ end += 1;
1148
+ removals.push({ start: word.start, end });
1149
+ i = next;
1150
+ }
1151
+ }
1152
+ if (removals.length === 0)
1153
+ return { command, seconds: null };
1154
+ let out = command;
1155
+ for (const removal of removals.sort((a, b) => b.start - a.start)) {
1156
+ out = out.slice(0, removal.start) + out.slice(removal.end);
1157
+ }
1158
+ return { command: out, seconds };
1159
+ }
1079
1160
  /**
1080
1161
  * Whether any segment of the command runs a program whose command-position text matches
1081
1162
  * `pattern` — the one question a runner-kind table asks.
package/dist/cut-run.d.ts CHANGED
@@ -134,6 +134,14 @@ export interface CutRun {
134
134
  seconds: number;
135
135
  /** Whether this tool's budget stopped it or the `timeout` the command carried. */
136
136
  stoppedBy: CutBy;
137
+ /**
138
+ * Whether this was a detached background task, read with no budget of this tool's own
139
+ * ({@link commandCutRun}'s `budgetSeconds` is 0). A background run is bounded by what its own
140
+ * command carries — so a `command-timeout` cut there is that prefix killing the walk, and the
141
+ * executor must be told to drop the prefix, never to start the run in the background it is
142
+ * already in (X1 xr-molecule-flash-m143 +24:45).
143
+ */
144
+ background: boolean;
137
145
  /**
138
146
  * The exit code the run's own process reported, or null when the code in the result belongs to
139
147
  * the pipeline's filter (`… | tail`) rather than to the run — the case that read as success.
@@ -1 +1 @@
1
- {"version":3,"file":"cut-run.d.ts","sourceRoot":"","sources":["../src/cut-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAKH;;;GAGG;AACH,eAAO,MAAM,aAAa,kBAAkB,CAAA;AAE5C,kFAAkF;AAClF,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,OAAO,aAAa,CAAA;AAE1D;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,eAAe,CAGhE;AAiBD;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB,wEAAwE;IACxE,QAAQ,EAAE,OAAO,CAAA;CAClB;AAkDD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CA4B9D;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAKD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,GACb,MAAM,GAAG,IAAI,CAIf;AAED,0BAA0B;AAC1B,MAAM,MAAM,KAAK;AACf,sEAAsE;AACpE,aAAa;AACf,oDAAoD;GAClD,iBAAiB;AACnB;;;;GAIG;GACD,cAAc,CAAA;AAElB,wDAAwD;AACxD,MAAM,WAAW,MAAM;IACrB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAA;IACf,kFAAkF;IAClF,SAAS,EAAE,KAAK,CAAA;IAChB;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB;;;OAGG;IACH,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB;;;OAGG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,qCAAqC;IACrC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAA;IACvB,yEAAyE;IACzE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAsDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,MAAM,EACjB,aAAa,SAAI,EACjB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,GAAG,IAAI,CAgFf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAgB1D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAuBlD"}
1
+ {"version":3,"file":"cut-run.d.ts","sourceRoot":"","sources":["../src/cut-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAKH;;;GAGG;AACH,eAAO,MAAM,aAAa,kBAAkB,CAAA;AAE5C,kFAAkF;AAClF,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,OAAO,aAAa,CAAA;AAE1D;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,eAAe,CAGhE;AAiBD;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB,wEAAwE;IACxE,QAAQ,EAAE,OAAO,CAAA;CAClB;AAkDD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CA4B9D;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAKD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,GACb,MAAM,GAAG,IAAI,CAIf;AAED,0BAA0B;AAC1B,MAAM,MAAM,KAAK;AACf,sEAAsE;AACpE,aAAa;AACf,oDAAoD;GAClD,iBAAiB;AACnB;;;;GAIG;GACD,cAAc,CAAA;AAElB,wDAAwD;AACxD,MAAM,WAAW,MAAM;IACrB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAA;IACf,kFAAkF;IAClF,SAAS,EAAE,KAAK,CAAA;IAChB;;;;;;OAMG;IACH,UAAU,EAAE,OAAO,CAAA;IACnB;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB;;;OAGG;IACH,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB;;;OAGG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,qCAAqC;IACrC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAA;IACvB,yEAAyE;IACzE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAsDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,MAAM,EACjB,aAAa,SAAI,EACjB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,GAAG,IAAI,CAuFf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAiB1D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiClD"}
package/dist/cut-run.js CHANGED
@@ -296,6 +296,9 @@ export function commandCutRun(command, result, elapsedMs, budgetSeconds = 0, raw
296
296
  // tool budget at all (a reader re-reading a background run) the command's own bound is the only
297
297
  // one there is.
298
298
  const ownBoundStops = budgetSeconds === 0 || (declared !== null && declared < budgetSeconds);
299
+ // No budget of this tool's in force is what a background reader is: the task was detached, and
300
+ // nothing bounded it but what its own command carries.
301
+ const background = budgetSeconds === 0;
299
302
  // `timeout`'s own 124 — the code the backend's wrapper returns when the TOOL's budget fires,
300
303
  // whatever the pipeline ended with (`backends/sandbox.ts`). Which of the two bounds fired is the
301
304
  // clock's to say: a run killed at the tool's budget reports at least the budget, and one killed
@@ -308,6 +311,7 @@ export function commandCutRun(command, result, elapsedMs, budgetSeconds = 0, raw
308
311
  return {
309
312
  seconds: ownFired ? declared : budgetSeconds,
310
313
  stoppedBy: ownFired ? 'command-timeout' : 'tool-budget',
314
+ background,
311
315
  exitCode,
312
316
  ...progress,
313
317
  doing,
@@ -317,6 +321,7 @@ export function commandCutRun(command, result, elapsedMs, budgetSeconds = 0, raw
317
321
  return {
318
322
  seconds: declared,
319
323
  stoppedBy: 'command-timeout',
324
+ background,
320
325
  // A code the filter produced is not the run's: `… | tail` handed back 0 forever (m93).
321
326
  exitCode: withheld || exitCode === 0 ? null : exitCode,
322
327
  ...progress,
@@ -329,6 +334,7 @@ export function commandCutRun(command, result, elapsedMs, budgetSeconds = 0, raw
329
334
  return {
330
335
  seconds: budgetSeconds,
331
336
  stoppedBy: 'tool-budget',
337
+ background,
332
338
  exitCode: exitCode === 0 ? null : exitCode,
333
339
  ...progress,
334
340
  doing,
@@ -344,6 +350,7 @@ export function commandCutRun(command, result, elapsedMs, budgetSeconds = 0, raw
344
350
  return {
345
351
  seconds: usedBudget ? budgetSeconds : Math.max(1, Math.round(elapsedMs / 1000)),
346
352
  stoppedBy: usedBudget ? 'tool-budget' : 'process-stop',
353
+ background,
347
354
  exitCode: withheld || exitCode === 0 ? null : exitCode,
348
355
  ...progress,
349
356
  doing,
@@ -377,6 +384,7 @@ export function cutRunFacts(result) {
377
384
  return {
378
385
  seconds: c.seconds,
379
386
  stoppedBy: c.stoppedBy,
387
+ background: c.background === true,
380
388
  exitCode: typeof c.exitCode === 'number' ? c.exitCode : null,
381
389
  ran: typeof c.ran === 'number' ? c.ran : null,
382
390
  total: typeof c.total === 'number' ? c.total : null,
@@ -401,9 +409,19 @@ export function cutRunSentence(run) {
401
409
  const by = run.stoppedBy === 'tool-budget'
402
410
  ? "this tool's limit"
403
411
  : run.stoppedBy === 'command-timeout'
404
- ? `its own \`timeout ${run.seconds}\``
412
+ ? run.background
413
+ ? `the command's own \`timeout ${run.seconds}\`, which killed it at ${run.seconds} s`
414
+ : `its own \`timeout ${run.seconds}\``
405
415
  : 'a process kill outside this tool (no `timeout` of its own and no limit of this tool had fired)';
406
- const background = 'run it in the background (run_in_background + wait_for_task)';
416
+ // What the reader must do next. A run that was ALREADY a background task has nothing to gain
417
+ // from being sent to the background again — when its own `timeout` is what stopped it, that
418
+ // prefix is the thing to drop (X1 xr-molecule-flash-m143 +24:45: three cut sentences in one run
419
+ // told a background walk to "run it in the background", which is where it already was).
420
+ const background = run.background
421
+ ? run.stoppedBy === 'command-timeout'
422
+ ? `drop the \`timeout\` prefix and send it again — in the background a run is bounded by \`wait_for_task\` and the turn's deadline, not by this tool's ceiling, so the bound you wrote is what killed it`
423
+ : 'send it again when you are ready'
424
+ : 'run it in the background (run_in_background + wait_for_task)';
407
425
  const missing = run.ran !== null && run.total !== null ? run.total - run.ran : null;
408
426
  const lead = missing !== null
409
427
  ? `Ran ${run.ran} of ${run.total} ${run.noun} in ${run.seconds} s and was stopped by ${by} — the ${missing} it never reached ${missing === 1 ? 'has' : 'have'} not run; ${background}`
package/dist/index.d.ts CHANGED
@@ -136,7 +136,9 @@ export * from './command-position.js';
136
136
  export * from './cut-run.js';
137
137
  export * from './failure-kind.js';
138
138
  export * from './input-normalizer.js';
139
+ export * from './line-diff.js';
139
140
  export * from './no-test-run.js';
141
+ export * from './output-filter.js';
140
142
  export * from './pipeline-exit-note.js';
141
143
  export * from './schemas.js';
142
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,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
@@ -136,7 +136,9 @@ export * from './command-position.js';
136
136
  export * from './cut-run.js';
137
137
  export * from './failure-kind.js';
138
138
  export * from './input-normalizer.js';
139
+ export * from './line-diff.js';
139
140
  export * from './no-test-run.js';
141
+ export * from './output-filter.js';
140
142
  export * from './pipeline-exit-note.js';
141
143
  export * from './schemas.js';
142
144
  export * from './sleep-peek.js';
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Real added/removed LINE counts for the `diff` a file-writing tool reports.
3
+ *
4
+ * The count is a diff, not an arithmetic delta: replacing one line with another
5
+ * leaves the line count unchanged, so `new.length - old.length` is 0 for the
6
+ * edit that changed the file — a result that reads to the model as "your write
7
+ * did nothing" (X0 xr-molecule-flash-m141 +09:56: `write_file` rewrote
8
+ * `ArticlePreview.tsx`'s favorite label and reported
9
+ * `"linesAdded":0,"linesRemoved":0`). The lines an edit actually changed are
10
+ * found with the same longest-common-subsequence line diff the IDE's tool cards
11
+ * use (`@molecule/app-ide-react`'s `diffLineCount`); it is mirrored here because
12
+ * the API and App halves of the workspace cannot import each other (AGENTS.md
13
+ * Rule 11, enforced by ESLint). Keep the two in step if either changes.
14
+ *
15
+ * @module
16
+ */
17
+ /**
18
+ * Count truly added/removed lines between two line arrays using LCS.
19
+ *
20
+ * Bounded by construction, so a whole-file edit cannot allocate a quadratic
21
+ * table here: the longest common prefix and suffix are trimmed first (exact —
22
+ * those lines belong to every optimal diff, and on the usual small edit they
23
+ * shrink the table to the edited span), and what is left is capped (see
24
+ * {@link lcsLength}).
25
+ *
26
+ * @param oldLines - The original lines array.
27
+ * @param newLines - The modified lines array.
28
+ * @returns An object with the number of added and removed lines.
29
+ */
30
+ export declare function diffLineCount(oldLines: readonly string[], newLines: readonly string[]): {
31
+ added: number;
32
+ removed: number;
33
+ };
34
+ //# sourceMappingURL=line-diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-diff.d.ts","sourceRoot":"","sources":["../src/line-diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAmGH;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC1B;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAuBpC"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Real added/removed LINE counts for the `diff` a file-writing tool reports.
3
+ *
4
+ * The count is a diff, not an arithmetic delta: replacing one line with another
5
+ * leaves the line count unchanged, so `new.length - old.length` is 0 for the
6
+ * edit that changed the file — a result that reads to the model as "your write
7
+ * did nothing" (X0 xr-molecule-flash-m141 +09:56: `write_file` rewrote
8
+ * `ArticlePreview.tsx`'s favorite label and reported
9
+ * `"linesAdded":0,"linesRemoved":0`). The lines an edit actually changed are
10
+ * found with the same longest-common-subsequence line diff the IDE's tool cards
11
+ * use (`@molecule/app-ide-react`'s `diffLineCount`); it is mirrored here because
12
+ * the API and App halves of the workspace cannot import each other (AGENTS.md
13
+ * Rule 11, enforced by ESLint). Keep the two in step if either changes.
14
+ *
15
+ * @module
16
+ */
17
+ /**
18
+ * Largest LCS table the exact diff may build, in cells (old × new). A whole-file
19
+ * edit can be thousands of lines per side, i.e. tens of millions of cells —
20
+ * gigabytes of heap for a summary that only needs two numbers. Above this cap
21
+ * the answer comes from {@link orderedCommonLines}, a provable, order-respecting
22
+ * common subsequence in O(n log n); below it the result is exact. 1 << 22 cells
23
+ * is a few milliseconds, and the two-row table keeps memory at O(min(old, new)).
24
+ */
25
+ const MAX_DIFF_CELLS = 1 << 22;
26
+ /**
27
+ * Longest common subsequence length of two line arrays, in bounded time and
28
+ * memory: two rows of the recurrence instead of the whole table, and — once the
29
+ * table would exceed {@link MAX_DIFF_CELLS} — the order-respecting lower bound
30
+ * from {@link orderedCommonLines}.
31
+ *
32
+ * @param a - The first line array.
33
+ * @param b - The second line array.
34
+ * @returns The common subsequence length (a lower bound for the capped inputs).
35
+ */
36
+ function lcsLength(a, b) {
37
+ if (a.length === 0 || b.length === 0)
38
+ return 0;
39
+ if (a.length * b.length > MAX_DIFF_CELLS)
40
+ return orderedCommonLines(a, b);
41
+ // The recurrence needs only the previous row, and a row is `cols` wide — so
42
+ // the SHORTER array belongs on the `cols` axis, which bounds every row by
43
+ // min(a, b) and is what the memory claim above rests on. The recurrence is
44
+ // symmetric, so the length it returns is the same either way.
45
+ let rows = a;
46
+ let cols = b;
47
+ if (cols.length > rows.length) {
48
+ rows = b;
49
+ cols = a;
50
+ }
51
+ let previous = new Array(cols.length + 1).fill(0);
52
+ let current = new Array(cols.length + 1).fill(0);
53
+ for (let i = 1; i <= rows.length; i++) {
54
+ const line = rows[i - 1];
55
+ for (let j = 1; j <= cols.length; j++) {
56
+ if (line === cols[j - 1]) {
57
+ current[j] = previous[j - 1] + 1;
58
+ }
59
+ else {
60
+ const above = previous[j];
61
+ const left = current[j - 1];
62
+ current[j] = above >= left ? above : left;
63
+ }
64
+ }
65
+ const swap = previous;
66
+ previous = current;
67
+ current = swap;
68
+ }
69
+ return previous[cols.length];
70
+ }
71
+ /**
72
+ * How many lines the two arrays share IN ORDER, for inputs too large for the
73
+ * exact table: the longest run of lines that appear in the same relative order
74
+ * on both sides, found among the lines that occur exactly once in `a` (their
75
+ * position is unambiguous) by reducing their `b` positions to a longest
76
+ * strictly increasing run — the standard patience LIS, O(n log n).
77
+ *
78
+ * Order is the whole point. Counting the lines as a multiset (order thrown
79
+ * away) is only an UPPER bound on the LCS, so it under-reports changes: a
80
+ * 3000-line file whose two halves were swapped shares every line, and the
81
+ * multiset count would report the replacement as `+0 −0` — a result claiming a
82
+ * real edit changed nothing. Every line counted here is a real in-order match,
83
+ * so the answer is a LOWER bound on the LCS and the change count it feeds can
84
+ * only ever be over-stated, never denied.
85
+ *
86
+ * @param a - The first line array.
87
+ * @param b - The second line array.
88
+ * @returns A common subsequence length.
89
+ */
90
+ function orderedCommonLines(a, b) {
91
+ const occurrences = new Map();
92
+ for (const line of a)
93
+ occurrences.set(line, (occurrences.get(line) ?? 0) + 1);
94
+ const position = new Map();
95
+ a.forEach((line, index) => {
96
+ if (occurrences.get(line) === 1)
97
+ position.set(line, index);
98
+ });
99
+ // Patience: `tails[i]` is the smallest `b`-position that ends an increasing
100
+ // run of length `i + 1`.
101
+ const tails = [];
102
+ for (const line of b) {
103
+ const at = position.get(line);
104
+ if (at === undefined)
105
+ continue;
106
+ let lo = 0;
107
+ let hi = tails.length;
108
+ while (lo < hi) {
109
+ const mid = (lo + hi) >> 1;
110
+ if (tails[mid] < at)
111
+ lo = mid + 1;
112
+ else
113
+ hi = mid;
114
+ }
115
+ tails[lo] = at;
116
+ }
117
+ return tails.length;
118
+ }
119
+ /**
120
+ * Count truly added/removed lines between two line arrays using LCS.
121
+ *
122
+ * Bounded by construction, so a whole-file edit cannot allocate a quadratic
123
+ * table here: the longest common prefix and suffix are trimmed first (exact —
124
+ * those lines belong to every optimal diff, and on the usual small edit they
125
+ * shrink the table to the edited span), and what is left is capped (see
126
+ * {@link lcsLength}).
127
+ *
128
+ * @param oldLines - The original lines array.
129
+ * @param newLines - The modified lines array.
130
+ * @returns An object with the number of added and removed lines.
131
+ */
132
+ export function diffLineCount(oldLines, newLines) {
133
+ const oldLength = oldLines.length;
134
+ const newLength = newLines.length;
135
+ const shared = Math.min(oldLength, newLength);
136
+ // Longest common prefix / suffix. `suffix` is bounded by `shared - prefix`, so
137
+ // the two trimmed runs can never overlap each other.
138
+ let prefix = 0;
139
+ while (prefix < shared && oldLines[prefix] === newLines[prefix])
140
+ prefix++;
141
+ let suffix = 0;
142
+ while (suffix < shared - prefix &&
143
+ oldLines[oldLength - 1 - suffix] === newLines[newLength - 1 - suffix]) {
144
+ suffix++;
145
+ }
146
+ const common = prefix +
147
+ suffix +
148
+ lcsLength(oldLines.slice(prefix, oldLength - suffix), newLines.slice(prefix, newLength - suffix));
149
+ return { added: newLength - common, removed: oldLength - common };
150
+ }
@@ -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
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAiJ9C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAahG;AAkOD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAoEnE;;;GAGG;AACH,eAAO,MAAM,iBAAiB,QAEA,CAAA;AAE9B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,QAI6C,CAAA;AAmBlF;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUhE;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;AAoBpF;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC,GACxE,qBAAqB,CAkBvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,qBAAqB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiCxB;AA8ED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CAi7ExF"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAkJ9C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAahG;AAkOD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAqEnE;;;GAGG;AACH,eAAO,MAAM,iBAAiB,QAEA,CAAA;AAE9B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,QAI6C,CAAA;AAmBlF;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUhE;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;AAoBpF;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC,GACxE,qBAAqB,CAkBvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,qBAAqB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiCxB;AA8ED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CAk9ExF"}
package/dist/tools.js CHANGED
@@ -10,6 +10,7 @@ import { posix } from 'path';
10
10
  import { commandCutRun, CUT_AT_BUDGET, cutRunSentence, suiteRunExitCode } from './cut-run.js';
11
11
  import { addChangeSpan, changedSpan, countLines, renderEditExcerpt, renderSmallFile, } from './edit-excerpt.js';
12
12
  import { guardToolExecute, missingParamError, ToolInputError } from './input-normalizer.js';
13
+ import { diffLineCount } from './line-diff.js';
13
14
  import { pipelineExitCodeNote } from './pipeline-exit-note.js';
14
15
  import { TOOL_SCHEMAS } from './schemas.js';
15
16
  import { leadingSleepPeek } from './sleep-peek.js';
@@ -362,7 +363,7 @@ async function backgroundTaskState(backend, command, seconds, ceilingMs) {
362
363
  }
363
364
  import { suiteCommandTarget } from './suite-overlap.js';
364
365
  import { diagnosisTraceCommand } from './trace-artifacts.js';
365
- import { checkBlockedCommand, declaredBudgetSeconds, DEFAULT_SEARCH_EXCLUDED_DIRS, directoryReadHint, earlyReturnCause, emptyCallError, failureCausesNote, findPathArgs, findPatternArgs, fusedLine, htmlOutline, isCommandTimeout, isEnvFilePath, isOutsideRoot, isPlaywrightRunCommand, isSuiteRunCommand, isValidGlob, linesWithinSerialized, literalDirPrefix, MAX_BATCH_READ_FILES, MAX_FIND_RESULTS, MAX_HTML_INLINE_CHARS, MAX_OUTPUT_SIZE, MAX_READ_CALL_CHARS, MAX_READ_RETURN_CHARS, MAX_READ_SIZE, MAX_SEARCH_CONTEXT_LINES, MAX_SEARCH_RESULTS, MAX_WRITE_SIZE, outputIsWithheldUntilExit, outputRedirectTarget, parseCheckCommand, parseCheckProblem, pathArgError, printsOnlySource, READ_RESULT_ENVELOPE_CHARS, redactSecrets, redactSecretsInCode, repeatingFailure, repeatingFailureNote, resolvePath, RUNNING_FAILURE_LINES, runningCauseCommand, runningOutputSliceCommand, searchTimeoutError, serializedChars, shellQuote, sliceLines, SMALL_FILE_WHOLE_CHARS, streamingBackgroundCommand, stripControlChars, suiteRunPipelinePlacement, suiteRunPriorityLaunch, truncateMiddle, universalCause, whitespaceTolerantReplace, } from './utilities.js';
366
+ import { checkBlockedCommand, declaredBudgetSeconds, DEFAULT_SEARCH_EXCLUDED_DIRS, directoryReadHint, earlyReturnCause, emptyCallError, failureCausesNote, findPathArgs, findPatternArgs, fusedLine, htmlOutline, isCommandTimeout, isEnvFilePath, isOutsideRoot, isPlaywrightRunCommand, isSuiteRunCommand, isValidGlob, linesWithinSerialized, literalDirPrefix, MAX_BATCH_READ_FILES, MAX_FIND_RESULTS, MAX_HTML_INLINE_CHARS, MAX_OUTPUT_SIZE, MAX_READ_CALL_CHARS, MAX_READ_RETURN_CHARS, MAX_READ_SIZE, MAX_SEARCH_CONTEXT_LINES, MAX_SEARCH_RESULTS, MAX_WRITE_SIZE, outputIsWithheldUntilExit, outputRedirectTarget, parseCheckCommand, parseCheckProblem, pathArgError, printsOnlySource, READ_RESULT_ENVELOPE_CHARS, redactSecrets, redactSecretsInCode, repeatingFailure, repeatingFailureNote, resolvePath, RUNNING_FAILURE_LINES, runningCauseCommand, runningOutputSliceCommand, searchTimeoutError, serializedChars, shellQuote, sliceLines, SMALL_FILE_WHOLE_CHARS, streamingBackgroundCommand, stripControlChars, suiteRunPipelinePlacement, suiteRunPriorityLaunch, truncateMiddle, universalCause, whitespaceTolerantReplace, withoutSuiteTimeout, } from './utilities.js';
366
367
  /**
367
368
  * How long exec_command waits for a command it backgrounded only because the
368
369
  * command asked for more than the tool's ceiling, before handing back a task id.
@@ -921,21 +922,27 @@ export function buildTools(backend, config) {
921
922
  /**
922
923
  * Compute a lightweight diff summary for telemetry and UI badges.
923
924
  *
925
+ * The counts are a real line diff ({@link diffLineCount}), not the change in
926
+ * line count: replacing one line with another leaves the file the same
927
+ * length, and a length delta reported that edit as `0/0` — reading to the
928
+ * model as "your write changed nothing" (xr-molecule-flash-m141 +09:56, a
929
+ * one-line rewrite of `ArticlePreview.tsx`). A write that leaves the content
930
+ * identical is `unchanged` rather than a `modified` with `0/0`, so the two
931
+ * are distinguishable.
932
+ *
924
933
  * @param oldContent - Previous file contents, or `null` when creating a file.
925
934
  * @param newContent - Replacement file contents after a write/edit.
926
- * @returns Counts describing whether the file was created or modified.
935
+ * @returns Counts describing whether the file was created, modified or left unchanged.
927
936
  */
928
937
  function computeDiff(oldContent, newContent) {
929
938
  if (oldContent === null) {
930
- return { type: 'created', linesAdded: newContent.split('\n').length, linesRemoved: 0 };
939
+ return { type: 'created', linesAdded: countLines(newContent), linesRemoved: 0 };
931
940
  }
932
- const oldLines = oldContent.split('\n');
933
- const newLines = newContent.split('\n');
934
- return {
935
- type: 'modified',
936
- linesAdded: Math.max(0, newLines.length - oldLines.length),
937
- linesRemoved: Math.max(0, oldLines.length - newLines.length),
938
- };
941
+ if (oldContent === newContent) {
942
+ return { type: 'unchanged', linesAdded: 0, linesRemoved: 0 };
943
+ }
944
+ const { added, removed } = diffLineCount(oldContent.split('\n'), newContent.split('\n'));
945
+ return { type: 'modified', linesAdded: added, linesRemoved: removed };
939
946
  }
940
947
  // ── Tool implementations ───────────────────────────────────────
941
948
  /**
@@ -2137,6 +2144,16 @@ export function buildTools(backend, config) {
2137
2144
  // an executor's commands routinely carry quotes, heredocs and
2138
2145
  // newlines, and re-quoting them into a detached `sh -c` is how a
2139
2146
  // background runner corrupts the very thing it is running.
2147
+ // The platform moved this run to the background because its own bound could not fit
2148
+ // this tool's ceiling — and in the background the ceiling no longer applies, so the
2149
+ // `timeout N` the executor wrote to fit it is the only bound left, and it kills the
2150
+ // walk mid-run with no tally (X1 xr-molecule-flash-m143 +24:45). Lift it from the
2151
+ // statement that runs the suite. A run the EXECUTOR detached keeps the bound it chose.
2152
+ const lifted = overCeiling && input.run_in_background !== true
2153
+ ? withoutSuiteTimeout(command)
2154
+ : { command, seconds: null };
2155
+ if (lifted.seconds !== null)
2156
+ command = lifted.command;
2140
2157
  // Keep the log growing while it runs (see streamingBackgroundCommand):
2141
2158
  // an empty log is what wait_for_task reads as stuck.
2142
2159
  const streaming = streamingBackgroundCommand(command);
@@ -2144,6 +2161,12 @@ export function buildTools(backend, config) {
2144
2161
  // its changes are what this branch reports the run's own settings in.
2145
2162
  if (traced.change)
2146
2163
  streaming.changes.unshift(traced.change);
2164
+ // Said once, in the result that also hands back the task id or the run's output.
2165
+ if (lifted.seconds !== null) {
2166
+ streaming.changes.unshift(`Dropped your \`timeout ${lifted.seconds}\` from the suite run: in the background it ` +
2167
+ 'is bounded by `wait_for_task` and the turn’s deadline, not by this tool’s ' +
2168
+ 'ceiling, so the bound you wrote would only have killed the walk.');
2169
+ }
2147
2170
  // A whole-suite run starves the sandbox it shares with the app and with
2148
2171
  // every command the executor sends next, so it starts at lower CPU and
2149
2172
  // IO priority (see suiteRunPriorityLaunch). Foreground runs are never
@@ -2210,8 +2233,15 @@ export function buildTools(backend, config) {
2210
2233
  ? { truncated: true, fullOutput: log }
2211
2234
  : {}),
2212
2235
  error: (sleepNote ? `${sleepNote} ` : '') +
2213
- `${cutRunSentence(cut)} ` +
2214
- (isSuiteRunCommand(command) ? SUITE_OVER_BUDGET_ADVICE : SPLIT_WORK_ADVICE),
2236
+ cutRunSentence(cut) +
2237
+ // A suite stopped in the background is never sent to the background again:
2238
+ // the sentence says what to do, and the advice's reason (it “takes the run
2239
+ // off this budget and writes its output to a log”) has already happened.
2240
+ (cut.background
2241
+ ? ''
2242
+ : ` ${isSuiteRunCommand(command)
2243
+ ? SUITE_OVER_BUDGET_ADVICE
2244
+ : SPLIT_WORK_ADVICE}`),
2215
2245
  };
2216
2246
  }
2217
2247
  // The exit file holds the PIPELINE's code: when a stage this rewrite could not
@@ -250,14 +250,24 @@ export declare function stalledDocumentSubresource(request: TraceRequest): boole
250
250
  * fetch stalled for 27 s (xr-molecule-flash-m135 +34:10). The page shell's incidental requests
251
251
  * (`/sw.js`, the manifest, a favicon, a font) stay out, for m125's reason.
252
252
  *
253
+ * A 404 whose path lacks the API prefix the app's own calls carry is called out with that prefix
254
+ * ({@link missingApiPrefixRequests}): xr-molecule-flash-m145 posted `/users` to `vite preview`,
255
+ * whose 404 was answered by the static server because the HTTP client's `baseURL` was never set —
256
+ * and the note printed "read the handler this route reaches in your own source", which presumes a
257
+ * request that never reached the API. The prefix is READ (the caller passes what the app's client
258
+ * config names; the traces add what their own requests show) and never assumed to be `/api`.
259
+ *
253
260
  * @param items - The traces {@link parseTraceArtifacts} read.
254
261
  * @param target - Where the run went — the deployed host, as the note names it.
255
262
  * @param earlierFailures - The failing `file:line`s earlier walks of this suite left, so a repeat
256
263
  * is ranked above a one-off. Empty when the caller knows of no earlier walk.
264
+ * @param apiPrefixes - The API path prefixes the app's client config names (`['/api']`), read from
265
+ * the app by the caller. Empty when the caller could not read one; the traces' own requests may
266
+ * still supply it. Never a hard-coded literal.
257
267
  * @returns The note, or null when no trace held a recorded response, a real failure or a console
258
268
  * error.
259
269
  */
260
- export declare function failureTraceNote(items: readonly TraceArtifact[], target: string, earlierFailures?: readonly string[]): string | null;
270
+ export declare function failureTraceNote(items: readonly TraceArtifact[], target: string, earlierFailures?: readonly string[], apiPrefixes?: readonly string[]): string | null;
261
271
  /**
262
272
  * Whether a Playwright config records traces for the tests that fail.
263
273
  *
@@ -1 +1 @@
1
- {"version":3,"file":"trace-artifacts.d.ts","sourceRoot":"","sources":["../src/trace-artifacts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAMH,iEAAiE;AACjE,MAAM,WAAW,YAAY;IAC3B,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,iGAAiG;IACjG,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAA;IACd;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,oFAAoF;IACpF,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,gFAAgF;AAChF,MAAM,WAAW,WAAW;IAC1B,yFAAyF;IACzF,GAAG,EAAE,MAAM,CAAA;IACX,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAA;IACb,kEAAkE;IAClE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CACnB;AAED,iGAAiG;AACjG,MAAM,WAAW,aAAa;IAC5B,0FAA0F;IAC1F,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAA;IACZ,6FAA6F;IAC7F,QAAQ,EAAE,YAAY,EAAE,CAAA;IACxB;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,YAAY,CAAA;IACnB,0DAA0D;IAC1D,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB;;;;OAIG;IACH,OAAO,EAAE,WAAW,EAAE,CAAA;CACvB;AAED,sDAAsD;AACtD,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,sDAAsD;AACtD,eAAO,MAAM,mBAAmB,IAAI,CAAA;AAEpC,4DAA4D;AAC5D,eAAO,MAAM,kBAAkB,IAAI,CAAA;AAEnC,sFAAsF;AACtF,eAAO,MAAM,kBAAkB,KAAK,CAAA;AAEpC,yFAAyF;AACzF,eAAO,MAAM,qBAAqB,MAAM,CAAA;AAExC,uDAAuD;AACvD,eAAO,MAAM,oBAAoB,IAAI,CAAA;AAErC,iDAAiD;AACjD,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC,gEAAgE;AAChE,eAAO,MAAM,oBAAoB,KAAK,CAAA;AAEtC,wFAAwF;AACxF,eAAO,MAAM,qBAAqB,MAAM,CAAA;AAExC,kFAAkF;AAClF,eAAO,MAAM,oBAAoB,MAAM,CAAA;AAEvC;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAK5C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,oBAAoB,QAAO,MA0VvC,CAAA;AAsBD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE,CAgCnE;AA+HD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAKnE;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAG5D;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAGhE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAMzE;AAsJD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,aAAa,EAAE,EAC/B,MAAM,EAAE,MAAM,EACd,eAAe,GAAE,SAAS,MAAM,EAAO,GACtC,MAAM,GAAG,IAAI,CA2Kf;AAaD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAG9D;AAED,iFAAiF;AACjF,eAAO,MAAM,oBAAoB,8BAA8B,CAAA;AAwG/D,oGAAoG;AACpG,MAAM,WAAW,qBAAqB;IACpC,0BAA0B;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,4EAA4E;IAC5E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CAC5C,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA2BjC"}
1
+ {"version":3,"file":"trace-artifacts.d.ts","sourceRoot":"","sources":["../src/trace-artifacts.ts"],"names":[],"mappings":"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"}
@@ -810,6 +810,94 @@ function transportFailure(items) {
810
810
  }
811
811
  return null;
812
812
  }
813
+ /**
814
+ * A request's path when the trace recorded a same-origin path — `/users` — or null for an
815
+ * absolute URL (another origin's path is no evidence about this app's API).
816
+ *
817
+ * @param request - One request a trace recorded.
818
+ * @returns The path without a query or trailing slash, or null.
819
+ */
820
+ function sameOriginPath(request) {
821
+ const raw = String(request.path ?? '').split(/[?#]/)[0] ?? '';
822
+ if (!raw.startsWith('/') || raw === '/')
823
+ return null;
824
+ return raw.replace(/\/+$/, '');
825
+ }
826
+ /**
827
+ * The API path prefixes the traced requests themselves show.
828
+ *
829
+ * A request whose path ends with another traced request's path carries that other path's prefix
830
+ * (`/api/users` beside `/users` → `/api`) — the trace's own evidence, with no literal in the code.
831
+ *
832
+ * @param items - The traces the note is about.
833
+ * @returns The one-segment prefixes (`/api`), sorted; empty when the traces show none.
834
+ */
835
+ function tracedApiPrefixes(items) {
836
+ const paths = items.flatMap((item) => item.requests.map(sameOriginPath).filter((path) => path !== null));
837
+ const prefixes = new Set();
838
+ for (const longer of paths) {
839
+ for (const shorter of paths) {
840
+ if (longer === shorter || shorter.length < 2 || !longer.endsWith(shorter))
841
+ continue;
842
+ const prefix = longer.slice(0, longer.length - shorter.length);
843
+ if (/^\/[^/]+$/.test(prefix))
844
+ prefixes.add(prefix);
845
+ }
846
+ }
847
+ return [...prefixes].sort();
848
+ }
849
+ /**
850
+ * The failed 404s whose path carries none of the known API prefixes.
851
+ *
852
+ * Only a run where the prefix is KNOWABLE diagnoses: the caller reads it from the app's client
853
+ * config, and the traces' own requests add what they show ({@link tracedApiPrefixes}). With no
854
+ * known prefix, an unprefixed path is just a path — assuming `/api` is how a correct request gets
855
+ * a wrong note.
856
+ *
857
+ * @param items - The traces the note is about.
858
+ * @param apiPrefixes - Prefixes the app's client config names (`['/api']`), never a literal.
859
+ * @returns One entry per distinct failed 404, in trace order.
860
+ */
861
+ function missingApiPrefixRequests(items, apiPrefixes) {
862
+ const prefixes = new Set([...apiPrefixes, ...tracedApiPrefixes(items)]
863
+ .map((prefix) => `/${String(prefix).replace(/^\/+|\/+$/g, '')}`)
864
+ .filter((prefix) => prefix !== '/'));
865
+ if (prefixes.size === 0)
866
+ return [];
867
+ const known = [...prefixes];
868
+ const out = [];
869
+ const seen = new Set();
870
+ for (const item of items) {
871
+ for (const request of item.requests) {
872
+ // A document navigation is a page route, never an API call — a 404 on one says nothing
873
+ // about the client's base URL.
874
+ if (request.status !== 404 || request.type === 'document' || !failedRequest(request))
875
+ continue;
876
+ const path = sameOriginPath(request);
877
+ if (path === null)
878
+ continue;
879
+ if (known.some((prefix) => path === prefix || path.startsWith(`${prefix}/`)))
880
+ continue;
881
+ const key = `${request.method} ${path}`;
882
+ if (seen.has(key))
883
+ continue;
884
+ seen.add(key);
885
+ out.push({ method: request.method, path, prefix: known[0] ?? '' });
886
+ }
887
+ }
888
+ return out;
889
+ }
890
+ /**
891
+ * The sentence naming a request that reached the page origin without the app's API prefix.
892
+ *
893
+ * @param request - The failed request and the prefix its sibling calls carry.
894
+ * @returns The sentence the note appends.
895
+ */
896
+ function missingApiPrefixSentence(request) {
897
+ return (`\`${request.method} ${request.path}\` → 404: this request went to \`${request.path}\` ` +
898
+ `without the \`${request.prefix}\` prefix — the HTTP client's base URL is not set: is ` +
899
+ '`setupProviders()` (which runs the HTTP bond setup) called in `main.tsx`?');
900
+ }
813
901
  /**
814
902
  * The note a failed suite run's result carries: what each failing test's page actually sent, and
815
903
  * what came back.
@@ -854,14 +942,24 @@ function transportFailure(items) {
854
942
  * fetch stalled for 27 s (xr-molecule-flash-m135 +34:10). The page shell's incidental requests
855
943
  * (`/sw.js`, the manifest, a favicon, a font) stay out, for m125's reason.
856
944
  *
945
+ * A 404 whose path lacks the API prefix the app's own calls carry is called out with that prefix
946
+ * ({@link missingApiPrefixRequests}): xr-molecule-flash-m145 posted `/users` to `vite preview`,
947
+ * whose 404 was answered by the static server because the HTTP client's `baseURL` was never set —
948
+ * and the note printed "read the handler this route reaches in your own source", which presumes a
949
+ * request that never reached the API. The prefix is READ (the caller passes what the app's client
950
+ * config names; the traces add what their own requests show) and never assumed to be `/api`.
951
+ *
857
952
  * @param items - The traces {@link parseTraceArtifacts} read.
858
953
  * @param target - Where the run went — the deployed host, as the note names it.
859
954
  * @param earlierFailures - The failing `file:line`s earlier walks of this suite left, so a repeat
860
955
  * is ranked above a one-off. Empty when the caller knows of no earlier walk.
956
+ * @param apiPrefixes - The API path prefixes the app's client config names (`['/api']`), read from
957
+ * the app by the caller. Empty when the caller could not read one; the traces' own requests may
958
+ * still supply it. Never a hard-coded literal.
861
959
  * @returns The note, or null when no trace held a recorded response, a real failure or a console
862
960
  * error.
863
961
  */
864
- export function failureTraceNote(items, target, earlierFailures = []) {
962
+ export function failureTraceNote(items, target, earlierFailures = [], apiPrefixes = []) {
865
963
  const candidates = items.filter(traceRowEvidence);
866
964
  if (candidates.length === 0)
867
965
  return null;
@@ -885,6 +983,22 @@ export function failureTraceNote(items, target, earlierFailures = []) {
885
983
  const wrapped = traced.some((item) => item.requests.some((request) => request.sent !== undefined && wrappedInData(request.sent)));
886
984
  // The "one of these requests failing" answer is only honest when a listed request really failed.
887
985
  const anyFailed = traced.some((item) => item.requests.some(failedRequest));
986
+ // m145's shape: the app's HTTP client lost its base URL, so every API call reached the page
987
+ // origin without the prefix the app mounts its routes under. The prefix is READ — the caller's
988
+ // client config plus what the traces show — never assumed to be `/api`.
989
+ const missingPrefix = missingApiPrefixRequests(traced, apiPrefixes);
990
+ const failedRequests = traced.flatMap((item) => item.requests.filter(failedRequest));
991
+ const missingKeys = new Set(missingPrefix.map((request) => `${request.method} ${request.path}`));
992
+ const everyFailureLacksPrefix = failedRequests.length > 0 &&
993
+ failedRequests.every((request) => {
994
+ const path = sameOriginPath(request);
995
+ return path !== null && missingKeys.has(`${request.method} ${path}`);
996
+ });
997
+ // The route advice goes when every failure is one of these: a request that never reached the
998
+ // API has no handler to read (m145's note sent the run to the PWA and then to the handler).
999
+ const prefixAdvice = missingPrefix.length > 0
1000
+ ? ` ${missingPrefix.slice(0, 2).map(missingApiPrefixSentence).join(' ')}`
1001
+ : '';
888
1002
  // The document subresources that never finished anywhere in this read — the assets a timed-out
889
1003
  // navigation was waiting on, when there is no failed request to explain the timeout.
890
1004
  const stalledAssets = [
@@ -994,9 +1108,11 @@ export function failureTraceNote(items, target, earlierFailures = []) {
994
1108
  `requests that failed, the ones that got no response, and its last answered ones):\n` +
995
1109
  `${rows.join('\n')}${more}\n` +
996
1110
  (anyFailed
997
- ? 'A click that changed nothing is usually one of these requests failing, not the selector: ' +
998
- 'read the handler this route reaches in your own source, and stop `catch`-ing the request of a ' +
999
- 'user action silently — log it.'
1111
+ ? everyFailureLacksPrefix
1112
+ ? ''
1113
+ : 'A click that changed nothing is usually one of these requests failing, not the selector: ' +
1114
+ 'read the handler this route reaches in your own source, and stop `catch`-ing the request of a ' +
1115
+ 'user action silently — log it.'
1000
1116
  : stalledAssets.length > 0
1001
1117
  ? 'No listed request failed — none got a 4xx/5xx or a network error — but the document did ' +
1002
1118
  'not finish loading because its own subresource never answered. Do not read this as a ' +
@@ -1007,6 +1123,7 @@ export function failureTraceNote(items, target, earlierFailures = []) {
1007
1123
  'row): if it is not the request the test meant — an unfollow sent where the test clicked ' +
1008
1124
  'follow — the state the click read was stale before it. Otherwise read the state the ' +
1009
1125
  'failing test waited on.') +
1126
+ prefixAdvice +
1010
1127
  (wrapped
1011
1128
  ? ' The API received a body wrapped in `data`: app-http’s `post(url, data, config)` / ' +
1012
1129
  '`put(url, data, config)` / `patch(url, data, config)` take the body as their SECOND ' +
@@ -193,6 +193,22 @@ export declare function streamingBackgroundCommand(command: string): {
193
193
  * @returns True when the command starts one of those runners.
194
194
  */
195
195
  export declare function isSuiteRunCommand(command: string): boolean;
196
+ /**
197
+ * The command with the `timeout <N>` wrapper lifted off the statement that runs the suite, and the
198
+ * bound that was lifted.
199
+ *
200
+ * Used where the platform moves a run to the background: the executor wrote the bound to fit this
201
+ * tool's foreground ceiling, and in the background that ceiling no longer applies — the task is
202
+ * bounded by `wait_for_task` and the turn's deadline — so the prefix only kills the walk
203
+ * ({@link withoutTimeoutWrapper}; X1 xr-molecule-flash-m143 +24:45).
204
+ *
205
+ * @param command - The shell command.
206
+ * @returns The rewritten command, and the largest lifted bound (null when nothing was lifted).
207
+ */
208
+ export declare function withoutSuiteTimeout(command: string): {
209
+ command: string;
210
+ seconds: number | null;
211
+ };
196
212
  /**
197
213
  * Whether a command starts a Playwright run — a `playwright test` in command position, in a form
198
214
  * that runs something.
@@ -1 +1 @@
1
- {"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"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"}
package/dist/utilities.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * @module
6
6
  */
7
7
  import { posix } from 'path';
8
- import { commandSegments, locatedCommandSegments, statementArgumentEnd, } from './command-position.js';
8
+ import { commandSegments, locatedCommandSegments, statementArgumentEnd, withoutTimeoutWrapper, } from './command-position.js';
9
9
  import { classifyRunFailure } from './failure-kind.js';
10
10
  import { commandRunsNoTests } from './no-test-run.js';
11
11
  import { isDiagnosisRun, scopedRerunCommand, suiteCommandTarget, suiteRunInTheWay, withoutHeredocs, withSuiteConfig, } from './suite-overlap.js';
@@ -590,6 +590,21 @@ export function isSuiteRunCommand(command) {
590
590
  return false;
591
591
  return commandSegments(command).some((segment) => SUITE_RUN_COMMANDS.some((re) => re.test(segment.text)));
592
592
  }
593
+ /**
594
+ * The command with the `timeout <N>` wrapper lifted off the statement that runs the suite, and the
595
+ * bound that was lifted.
596
+ *
597
+ * Used where the platform moves a run to the background: the executor wrote the bound to fit this
598
+ * tool's foreground ceiling, and in the background that ceiling no longer applies — the task is
599
+ * bounded by `wait_for_task` and the turn's deadline — so the prefix only kills the walk
600
+ * ({@link withoutTimeoutWrapper}; X1 xr-molecule-flash-m143 +24:45).
601
+ *
602
+ * @param command - The shell command.
603
+ * @returns The rewritten command, and the largest lifted bound (null when nothing was lifted).
604
+ */
605
+ export function withoutSuiteTimeout(command) {
606
+ return withoutTimeoutWrapper(command, (segment) => isSuiteRunCommand(segment.text));
607
+ }
593
608
  /**
594
609
  * Whether a command starts a Playwright run — a `playwright test` in command position, in a form
595
610
  * that runs something.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/api-ai-tools",
3
- "version": "1.9.7",
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",