@molecule/api-ai-tools 1.6.5 → 1.7.0

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.
@@ -110,6 +110,20 @@ export declare function outputIsWithheldUntilExit(command: string): boolean;
110
110
  * @returns The target as written, or null (`/dev/null` and `&1`/`&2` are not files).
111
111
  */
112
112
  export declare function outputRedirectTarget(command: string): string | null;
113
+ /**
114
+ * Playwright's switch for printing each failure's own error as that test fails, instead of only in
115
+ * the summary at the end: `list` reads it in its constructor (`ListReporterOptions.printFailuresInline`,
116
+ * `playwright/lib/reporters/list.js` — 1.63, the version the toolchain pins), and when it prints
117
+ * inline the end-of-run repeat is suppressed with it (`epilogue(!printFailuresInline)`), so one
118
+ * reporter still prints each failure exactly once.
119
+ *
120
+ * A background suite is put on `list` (see {@link streamingBackgroundCommand}) and this with it, so
121
+ * the log names its causes WHILE it walks. Without it the log's only failure lines are `✘` rows:
122
+ * X1 xr-molecule-flash-m99 (+19:27 → +21:00, 2026-10-16) was told to `grep -n -A 20 '<test name>'`
123
+ * the log, got nothing back through four greps, inferred causes from the spec prose instead, and
124
+ * edited `app/src` while the run was still walking — which voids the run.
125
+ */
126
+ export declare const PLAYWRIGHT_FAILURES_INLINE_ENV = "PLAYWRIGHT_LIST_PRINT_FAILURES_INLINE";
113
127
  /**
114
128
  * Rewrite a command about to run in the background so its log grows while it
115
129
  * runs. Two shapes left the log empty until exit, and an empty log is what
@@ -135,6 +149,11 @@ export declare function outputRedirectTarget(command: string): string | null;
135
149
  * `junit`) is the
136
150
  * executor's own and is left exactly as it is — so is any reporter this build does not know.
137
151
  *
152
+ * A run put on `list` is also given {@link PLAYWRIGHT_FAILURES_INLINE_ENV}, so each failure's own
153
+ * error is in the log as that test fails rather than only at the end: a suite that is still walking
154
+ * is exactly when the executor reads the log, and without it a running log carries `✘` rows and
155
+ * nothing else (xr-molecule-flash-m99 spent ~90 s on greps of one, then fixed what it guessed).
156
+ *
138
157
  * Only the command's last step is touched, and only its reporter, and only when that step runs
139
158
  * something: `npx playwright test --list` takes two seconds and writes nothing per test, so
140
159
  * neither reporter nor `--retries=0` is added to it ({@link isPlaywrightRunCommand}).
@@ -274,6 +293,81 @@ export declare function isValidGlob(pattern: string): boolean;
274
293
  * `-path '…'` alternatives, ORed inside parens when there is more than one.
275
294
  */
276
295
  export declare function findPatternArgs(pattern: string): string;
296
+ /**
297
+ * The `-path` alternatives of {@link findPatternArgs}, for a pattern whose
298
+ * directory the caller has already rooted the search at.
299
+ *
300
+ * `find_files` narrows the search root itself when the pattern spells its own
301
+ * directory out (see {@link literalDirPrefix}) — `node_modules` plus
302
+ * `@molecule/api-resource-user/dist/*.d.ts` searched that one directory. The
303
+ * remainder (`*.d.ts`) must then keep the `-path` form rather than collapsing to
304
+ * `-name`: `*` crosses `/` in an fnmatch glob, so the `-path` form still finds a
305
+ * declaration file in a `dist/utilities/` subdirectory, which `-name '*.d.ts'`
306
+ * would drop (a silent partial answer, which is worse than the timeout it
307
+ * replaced).
308
+ *
309
+ * @param pattern - The pattern's remainder, with a `/` in it or not.
310
+ * @returns One or more `-path '…'` alternatives, ORed inside parens when there
311
+ * is more than one.
312
+ */
313
+ export declare function findPathArgs(pattern: string): string;
314
+ /**
315
+ * The directory a GLOB pattern spells out, when it spells one out: everything
316
+ * before the pattern's first glob character, trimmed back to the last `/`.
317
+ *
318
+ * A pattern is matched against the whole path with a leading "any parent"
319
+ * anchor ({@link findPatternArgs}), so `find` visits every entry below the
320
+ * search root. Handed `/workspace/node_modules` and
321
+ * `@molecule/api-resource-user/dist/*.d.ts` — a directory named outright —
322
+ * `find` walked the sandbox's entire dependency tree and hit the tool's 10 s
323
+ * deadline without printing a result (xr-molecule-flash-m94: the one directory
324
+ * the model meant answered a `list_files` in 0 s). The literal prefix is that
325
+ * directory, and rooting the search at it is what keeps the call instant.
326
+ *
327
+ * A BARE first segment (`helpers/*`, `bonds/*`, `e2e/*.spec.ts`) is NOT one:
328
+ * `helpers/*` means "a `helpers/` directory anywhere below the root", which the
329
+ * tool documents and a live run relied on (xr-molecule-flash-m77 — a path
330
+ * pattern is not anchored to one depth). Rooting those at
331
+ * `<root>/helpers` would answer with a SUBSET, silently: the nested
332
+ * `api/src/helpers/` matches would disappear, and a missing file reads as
333
+ * "no such file". So a prefix is returned only when it names a path of two or
334
+ * more segments (`@molecule/api-resource-user/dist`), which is the shape that
335
+ * is a directory rather than a directory name.
336
+ *
337
+ * @param pattern - A pattern already accepted by {@link isValidGlob}.
338
+ * @returns The literal directory prefix, without a trailing slash, or null when
339
+ * the pattern has no glob character, no `/`, or only a bare name before one.
340
+ */
341
+ export declare function literalDirPrefix(pattern: string): string | null;
342
+ /**
343
+ * Whether a backend error is the sandbox's own command deadline.
344
+ *
345
+ * The E2B SDK answers a timed-out `exec` with its generic text —
346
+ * `[deadline_exceeded] the operation timed out: … It can be modified by passing
347
+ * 'timeoutMs' when making the request. Use '0' to disable the timeout.` — which
348
+ * names an option the executor cannot set and says nothing about the search
349
+ * that died. Handing that sentence to the model is what xr-molecule-flash-m94
350
+ * read after `find_files` spent 10 s walking `node_modules`; the tool answers
351
+ * the deadline in its own words instead (see {@link searchTimeoutError}).
352
+ *
353
+ * @param error - The error the backend threw.
354
+ * @returns True when the error reads as a timeout or a deadline.
355
+ */
356
+ export declare function isCommandTimeout(error: unknown): boolean;
357
+ /**
358
+ * The answer a search tool gives when the backend's deadline fires: what was
359
+ * searched, for what, how long the tool allowed, and the two ways to get an
360
+ * answer — a narrower `path`, or a listing. Never the vendor's `timeoutMs`
361
+ * sentence (see {@link isCommandTimeout}).
362
+ *
363
+ * @param tool - The tool that timed out (`find_files`, `search_files`).
364
+ * @param searched - The directory the search actually covered.
365
+ * @param pattern - The pattern it was searching for.
366
+ * @param seconds - The tool's own limit, in seconds.
367
+ * @param hint - What to do differently — the narrower target or the listing tool.
368
+ * @returns The message's text.
369
+ */
370
+ export declare function searchTimeoutError(tool: string, searched: string, pattern: string, seconds: number, hint: string): string;
277
371
  /**
278
372
  * Validate a file tool's `path` argument is a non-empty string. A weak model
279
373
  * sometimes omits it or passes a non-string, which would otherwise crash
@@ -527,10 +621,12 @@ export declare const RUNNING_FAILURE_LINE_RE = "^[[:space:]]*(\u2718|\u2717|\u00
527
621
  * The shell command whose stdout is the interesting part of a log that is still being written:
528
622
  * the failure lines so far (capped at {@link RUNNING_FAILURE_LINES}), then the end of the log.
529
623
  *
530
- * A Playwright `list` run prints one line per test as it finishes and its error blocks only at
531
- * the end, so the LAST bytes of a running log are its least informative part — in X1 flash-m61
532
- * the last 3 000 bytes of a 139-test walk were the skip list, and all 61 failures were above
533
- * them, which cost the run the grep it had to make anyway.
624
+ * A Playwright `list` run prints one line per test as it finishes, so the LAST bytes of a running
625
+ * log are its least informative part — in X1 flash-m61 the last 3 000 bytes of a 139-test walk
626
+ * were the skip list, and all 61 failures were above them, which cost the run the grep it had to
627
+ * make anyway. A background run also carries each failure's own error as it fails
628
+ * ({@link PLAYWRIGHT_FAILURES_INLINE_ENV}), and {@link RUNNING_FAILURE_LINE_RE} already matches
629
+ * those blocks' headers and their `Error:` lines, so this slice shows the causes too.
534
630
  *
535
631
  * @param log - The task log path.
536
632
  * @param own - A file the command redirects its own output to, if any.
@@ -586,9 +682,11 @@ export interface RepeatingFailure {
586
682
  * The cause repeating among a running suite's failures, or null.
587
683
  *
588
684
  * Playwright's `list` reporter prints one line per test as it finishes — its mark, its title
589
- * path and how long it ran — and defers each failure's error to the summary at the end, so
590
- * mid-run the only signature those lines carry is the duration. Where the log carries the
591
- * failure bodies (a `line` reporter's output, or a finished run's summary) the signature is the
685
+ * path and how long it ran — and, on a run the platform started in the background, each failure's
686
+ * own error with it ({@link PLAYWRIGHT_FAILURES_INLINE_ENV}); a `list` run with no error bodies in
687
+ * its log (an older Playwright, a log the bodies have been cut from) carries only the duration as
688
+ * a signature. Where the log carries the failure bodies (either inline, or in a finished run's
689
+ * summary) the signature is the
592
690
  * error itself — {@link failureMessage}: the error class plus the locator or the values that
593
691
  * differ — which is stronger (it needs no assumption about how long a failure should take), so
594
692
  * the message is looked for first and the duration is then left with the tests whose bodies the
@@ -651,6 +749,38 @@ export interface UniversalCause {
651
749
  * @returns The cause's count and files, or null when the run is not failing whole.
652
750
  */
653
751
  export declare function universalCause(log: string, found: RepeatingFailure): UniversalCause | null;
752
+ /**
753
+ * The ONE finding that ends a wait early, and the only one a note may hand a stop command over
754
+ * for: a PROVEN cause that is failing the whole run.
755
+ *
756
+ * Both halves are load-bearing, each of them learned from a run that lost minutes to the other.
757
+ *
758
+ * - **Failing the WHOLE run** is {@link universalCause}: every failure the log names, across
759
+ * {@link UNIVERSAL_CAUSE_FILES} spec files or more, with nothing passing since the first — the
760
+ * dont-stop-runs rule. X1 flash-m83 (2026-10-16) stopped eight local runs at their first
761
+ * repeating cause in 14.5 minutes and never finished one, and a run that still has other causes
762
+ * left to name is the only thing that will name them.
763
+ * - **A PROVEN cause** is an error repeated VERBATIM. A shared DURATION is a LEAD, never a cause:
764
+ * a suite whose config sets a timeout spends that timeout on every failure that waits for
765
+ * anything, so three unrelated tests timing out together look exactly like one broken run
766
+ * (`~7 s` is a property of the CONFIG, not of the cause — {@link normalizedSignature}). X1
767
+ * xr-molecule-flash-m99 (2026-10-16) was told `status: 'repeating_failure'` twice on that
768
+ * shape — three `url-navigation.spec.ts` tests at ~16.2 s, one `timeout: 15_000` plus teardown
769
+ * — read the early return as "stop waiting, edit now", and voided a run that was still walking;
770
+ * the second cost a 224 s wait that ended with no result at all.
771
+ *
772
+ * Neither half alone is enough, and {@link repeatingFailure} finding a signature is not either:
773
+ * that answers "is a cause repeating among this run's failures", which is worth telling the
774
+ * executor mid-run as a NOTE while the wait goes on. This answers the narrower question the wait
775
+ * needs — is the run over as a measuring instrument — and it is THE one predicate behind both
776
+ * that decision and the note's wording, so the two cannot come to different verdicts.
777
+ *
778
+ * @param found - What {@link repeatingFailure} found mid-run.
779
+ * @param universal - What {@link universalCause} found for it, if anything.
780
+ * @returns The cause to stop the run over, or null — in which case nothing may be stopped, the
781
+ * wait keeps going, and the finding rides the run's result as a note.
782
+ */
783
+ export declare function earlyReturnCause(found: RepeatingFailure, universal: UniversalCause | null | undefined): UniversalCause | null;
654
784
  /** One cause of failure in a run, and the tests it hit. */
655
785
  export interface FailureCause {
656
786
  /** The error line its tests all reported, or null when only the duration ties them together. */
@@ -669,11 +799,11 @@ export interface FailureCause {
669
799
  * bodies to read; X1 flash-m83 (2026-10-16) spent three deploys (6.7 minutes) each fixing a
670
800
  * single cause, two of them found by runs stopped before they walked the rest.
671
801
  *
672
- * The signature is the cause itself where the log carries the failures' bodies (a finished run,
673
- * or a `line` reporter) — {@link failureMessage}: the error class plus the locator or the values
674
- * that differ — and how long they took where it does not (a still-running `list` log, which is
675
- * why a duration group is labelled as a duration and not as a proven cause). A test the log
676
- * printed twice, or failed twice, is one test.
802
+ * The signature is the cause itself where the log carries the failures' bodies (a finished run, a
803
+ * background `list` run — whose failures print as they fail — or a `line` reporter) —
804
+ * {@link failureMessage}: the error class plus the locator or the values that differ — and how long
805
+ * they took where it does not, which is why a duration group is labelled as a duration and not as a
806
+ * proven cause. A test the log printed twice, or failed twice, is one test.
677
807
  *
678
808
  * @param log - The log of a finished or running run.
679
809
  * @returns The causes, the one with the most tests first.
@@ -720,11 +850,15 @@ export declare function rerunOfRunningSuite(run: {
720
850
  * tests, so the note never names one or two tests as a cause.
721
851
  *
722
852
  * The note names the cause early so the executor can START FIXING while the run keeps walking,
723
- * and it asks for the run to be stopped only when {@link universalCause} says the cause is
724
- * failing the whole run. X1 flash-m76 (2026-10-16) spent 4.0 minutes walking 15 tests whose one
725
- * cause was certain at the third, 47 s in, and the note answers exactly that; X1 flash-m83 then
726
- * stopped eight runs at their first repeating cause in 14.5 minutes and never finished one, so
727
- * the note must not say to stop when the run still has other causes to name.
853
+ * and it hands a stop command over only when {@link earlyReturnCause} says so — the SAME
854
+ * predicate the wait uses to decide whether to return early, so a finding the wait keeps waiting
855
+ * on is a finding this note never asks to stop for. X1 flash-m76 (2026-10-16) spent 4.0 minutes
856
+ * walking 15 tests whose one cause was certain at the third, 47 s in, and the note answers
857
+ * exactly that; X1 flash-m83 then stopped eight runs at their first repeating cause in 14.5
858
+ * minutes and never finished one, so the note must not say to stop when the run still has other
859
+ * causes to name. X1 xr-molecule-flash-m99 (2026-10-16) is the third shape: a shared duration is
860
+ * not a cause at all, so a lead reaches the executor as a note on a result it is still waiting
861
+ * for — never as a verdict with a stop command in it.
728
862
  *
729
863
  * The run is STILL WALKING while this note is written — both callers produce it mid-run — so a
730
864
  * re-run of one of its tests is a second run against the same app and database, and the platform
@@ -738,7 +872,7 @@ export declare function rerunOfRunningSuite(run: {
738
872
  *
739
873
  * @param found - What {@link repeatingFailure} found.
740
874
  * @param o - The run's facts: its `taskId`, its `log` path, `stop` — the shell command that
741
- * stops it, printed only for a {@link UniversalCause} — `universal`, what
875
+ * stops it, printed only for an {@link earlyReturnCause} — `universal`, what
742
876
  * {@link universalCause} found (absent means the run is not failing whole), and `run`, how the
743
877
  * run was started ({@link rerunOfRunningSuite}) when the caller knows it.
744
878
  * @returns The note.
@@ -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
@@ -327,6 +327,20 @@ function lastReporterFlag(step) {
327
327
  * carries every result twice.
328
328
  */
329
329
  const PRINTING_REPORTERS = new Set(['list', 'line', 'dot', 'basic', 'spec']);
330
+ /**
331
+ * Playwright's switch for printing each failure's own error as that test fails, instead of only in
332
+ * the summary at the end: `list` reads it in its constructor (`ListReporterOptions.printFailuresInline`,
333
+ * `playwright/lib/reporters/list.js` — 1.63, the version the toolchain pins), and when it prints
334
+ * inline the end-of-run repeat is suppressed with it (`epilogue(!printFailuresInline)`), so one
335
+ * reporter still prints each failure exactly once.
336
+ *
337
+ * A background suite is put on `list` (see {@link streamingBackgroundCommand}) and this with it, so
338
+ * the log names its causes WHILE it walks. Without it the log's only failure lines are `✘` rows:
339
+ * X1 xr-molecule-flash-m99 (+19:27 → +21:00, 2026-10-16) was told to `grep -n -A 20 '<test name>'`
340
+ * the log, got nothing back through four greps, inferred causes from the spec prose instead, and
341
+ * edited `app/src` while the run was still walking — which voids the run.
342
+ */
343
+ export const PLAYWRIGHT_FAILURES_INLINE_ENV = 'PLAYWRIGHT_LIST_PRINT_FAILURES_INLINE';
330
344
  /**
331
345
  * Rewrite a command about to run in the background so its log grows while it
332
346
  * runs. Two shapes left the log empty until exit, and an empty log is what
@@ -352,6 +366,11 @@ const PRINTING_REPORTERS = new Set(['list', 'line', 'dot', 'basic', 'spec']);
352
366
  * `junit`) is the
353
367
  * executor's own and is left exactly as it is — so is any reporter this build does not know.
354
368
  *
369
+ * A run put on `list` is also given {@link PLAYWRIGHT_FAILURES_INLINE_ENV}, so each failure's own
370
+ * error is in the log as that test fails rather than only at the end: a suite that is still walking
371
+ * is exactly when the executor reads the log, and without it a running log carries `✘` rows and
372
+ * nothing else (xr-molecule-flash-m99 spent ~90 s on greps of one, then fixed what it guessed).
373
+ *
355
374
  * Only the command's last step is touched, and only its reporter, and only when that step runs
356
375
  * something: `npx playwright test --list` takes two seconds and writes nothing per test, so
357
376
  * neither reporter nor `--retries=0` is added to it ({@link isPlaywrightRunCommand}).
@@ -441,6 +460,20 @@ export function streamingBackgroundCommand(command) {
441
460
  changes.push('Added `--reporter=list` so each test result is written to the log as it finishes ' +
442
461
  '(the config reporter may print nothing until the end).');
443
462
  }
463
+ // The run's failures, in the log as they fail (see PLAYWRIGHT_FAILURES_INLINE_ENV). Only for a
464
+ // run that ends on `list` — a run whose only reporters are machine formats has no failure lines
465
+ // to make inline, and this is inert for one — and set as an `export` at the head of the whole
466
+ // command, never mid-command: the last step may be a wrapper (`timeout 280 npx playwright test`)
467
+ // or start a line of its own (a multi-line command's last line), and an assignment written in
468
+ // front of either would be read as the program to run.
469
+ const endsOnListReporter = finalPlaywrightRun &&
470
+ (reporters === null || reporters.values.some((v) => PRINTING_REPORTERS.has(v)));
471
+ if (endsOnListReporter) {
472
+ out = `export ${PLAYWRIGHT_FAILURES_INLINE_ENV}=1; ${out}`;
473
+ changes.push('Each failure’s own error is now written into the log as that test fails, not only in the ' +
474
+ 'summary at the end — so a run that is still walking already says what its failures are, ' +
475
+ 'and you need not wait for it to end to start on them.');
476
+ }
444
477
  if (finalPlaywrightRun && diagnosis && !/--retries\b/.test(lastStep)) {
445
478
  out = `${out.trimEnd()} --retries=0`;
446
479
  changes.push('Added `--retries=0`: a diagnosis or re-run walks each failure once; keep the suite’s retries for the proof run.');
@@ -684,9 +717,104 @@ export function isValidGlob(pattern) {
684
717
  export function findPatternArgs(pattern) {
685
718
  if (!pattern.includes('/'))
686
719
  return `-name ${shellQuote(pattern)}`;
720
+ return findPathArgs(pattern);
721
+ }
722
+ /**
723
+ * The `-path` alternatives of {@link findPatternArgs}, for a pattern whose
724
+ * directory the caller has already rooted the search at.
725
+ *
726
+ * `find_files` narrows the search root itself when the pattern spells its own
727
+ * directory out (see {@link literalDirPrefix}) — `node_modules` plus
728
+ * `@molecule/api-resource-user/dist/*.d.ts` searched that one directory. The
729
+ * remainder (`*.d.ts`) must then keep the `-path` form rather than collapsing to
730
+ * `-name`: `*` crosses `/` in an fnmatch glob, so the `-path` form still finds a
731
+ * declaration file in a `dist/utilities/` subdirectory, which `-name '*.d.ts'`
732
+ * would drop (a silent partial answer, which is worse than the timeout it
733
+ * replaced).
734
+ *
735
+ * @param pattern - The pattern's remainder, with a `/` in it or not.
736
+ * @returns One or more `-path '…'` alternatives, ORed inside parens when there
737
+ * is more than one.
738
+ */
739
+ export function findPathArgs(pattern) {
687
740
  const paths = pathPatternVariants(pattern).map((p) => `-path ${shellQuote(`*/${p}`)}`);
688
741
  return paths.length === 1 ? paths[0] : `\\( ${paths.join(' -o ')} \\)`;
689
742
  }
743
+ /**
744
+ * The directory a GLOB pattern spells out, when it spells one out: everything
745
+ * before the pattern's first glob character, trimmed back to the last `/`.
746
+ *
747
+ * A pattern is matched against the whole path with a leading "any parent"
748
+ * anchor ({@link findPatternArgs}), so `find` visits every entry below the
749
+ * search root. Handed `/workspace/node_modules` and
750
+ * `@molecule/api-resource-user/dist/*.d.ts` — a directory named outright —
751
+ * `find` walked the sandbox's entire dependency tree and hit the tool's 10 s
752
+ * deadline without printing a result (xr-molecule-flash-m94: the one directory
753
+ * the model meant answered a `list_files` in 0 s). The literal prefix is that
754
+ * directory, and rooting the search at it is what keeps the call instant.
755
+ *
756
+ * A BARE first segment (`helpers/*`, `bonds/*`, `e2e/*.spec.ts`) is NOT one:
757
+ * `helpers/*` means "a `helpers/` directory anywhere below the root", which the
758
+ * tool documents and a live run relied on (xr-molecule-flash-m77 — a path
759
+ * pattern is not anchored to one depth). Rooting those at
760
+ * `<root>/helpers` would answer with a SUBSET, silently: the nested
761
+ * `api/src/helpers/` matches would disappear, and a missing file reads as
762
+ * "no such file". So a prefix is returned only when it names a path of two or
763
+ * more segments (`@molecule/api-resource-user/dist`), which is the shape that
764
+ * is a directory rather than a directory name.
765
+ *
766
+ * @param pattern - A pattern already accepted by {@link isValidGlob}.
767
+ * @returns The literal directory prefix, without a trailing slash, or null when
768
+ * the pattern has no glob character, no `/`, or only a bare name before one.
769
+ */
770
+ export function literalDirPrefix(pattern) {
771
+ const stripped = pattern.replace(/^(?:\.?\/)+/, '');
772
+ const firstGlob = stripped.search(/[?*[]/);
773
+ // No glob at all: the pattern IS a path, and the whole-tree form already
774
+ // finds it at any depth.
775
+ if (firstGlob === -1)
776
+ return null;
777
+ const at = stripped.slice(0, firstGlob).lastIndexOf('/');
778
+ if (at <= 0)
779
+ return null;
780
+ const prefix = stripped.slice(0, at);
781
+ return prefix.includes('/') ? prefix : null;
782
+ }
783
+ /**
784
+ * Whether a backend error is the sandbox's own command deadline.
785
+ *
786
+ * The E2B SDK answers a timed-out `exec` with its generic text —
787
+ * `[deadline_exceeded] the operation timed out: … It can be modified by passing
788
+ * 'timeoutMs' when making the request. Use '0' to disable the timeout.` — which
789
+ * names an option the executor cannot set and says nothing about the search
790
+ * that died. Handing that sentence to the model is what xr-molecule-flash-m94
791
+ * read after `find_files` spent 10 s walking `node_modules`; the tool answers
792
+ * the deadline in its own words instead (see {@link searchTimeoutError}).
793
+ *
794
+ * @param error - The error the backend threw.
795
+ * @returns True when the error reads as a timeout or a deadline.
796
+ */
797
+ export function isCommandTimeout(error) {
798
+ const message = error instanceof Error ? error.message : String(error);
799
+ return /deadline[_ ]?exceeded|timed out|timeout/i.test(message);
800
+ }
801
+ /**
802
+ * The answer a search tool gives when the backend's deadline fires: what was
803
+ * searched, for what, how long the tool allowed, and the two ways to get an
804
+ * answer — a narrower `path`, or a listing. Never the vendor's `timeoutMs`
805
+ * sentence (see {@link isCommandTimeout}).
806
+ *
807
+ * @param tool - The tool that timed out (`find_files`, `search_files`).
808
+ * @param searched - The directory the search actually covered.
809
+ * @param pattern - The pattern it was searching for.
810
+ * @param seconds - The tool's own limit, in seconds.
811
+ * @param hint - What to do differently — the narrower target or the listing tool.
812
+ * @returns The message's text.
813
+ */
814
+ export function searchTimeoutError(tool, searched, pattern, seconds, hint) {
815
+ return (`${tool} timed out after ${seconds}s searching ${searched} for "${pattern}" — the sandbox stopped the ` +
816
+ `command at its deadline, so there is no result (this is not an empty directory). ${hint}`);
817
+ }
690
818
  /**
691
819
  * The `-path` globs for a pattern that contains a slash, one per way each
692
820
  * doubled-star directory segment can stand for zero directories.
@@ -1185,10 +1313,12 @@ export const RUNNING_FAILURE_LINE_RE = '^[[:space:]]*(✘|✗|×|✖|✕|[0-9]+\
1185
1313
  * The shell command whose stdout is the interesting part of a log that is still being written:
1186
1314
  * the failure lines so far (capped at {@link RUNNING_FAILURE_LINES}), then the end of the log.
1187
1315
  *
1188
- * A Playwright `list` run prints one line per test as it finishes and its error blocks only at
1189
- * the end, so the LAST bytes of a running log are its least informative part — in X1 flash-m61
1190
- * the last 3 000 bytes of a 139-test walk were the skip list, and all 61 failures were above
1191
- * them, which cost the run the grep it had to make anyway.
1316
+ * A Playwright `list` run prints one line per test as it finishes, so the LAST bytes of a running
1317
+ * log are its least informative part — in X1 flash-m61 the last 3 000 bytes of a 139-test walk
1318
+ * were the skip list, and all 61 failures were above them, which cost the run the grep it had to
1319
+ * make anyway. A background run also carries each failure's own error as it fails
1320
+ * ({@link PLAYWRIGHT_FAILURES_INLINE_ENV}), and {@link RUNNING_FAILURE_LINE_RE} already matches
1321
+ * those blocks' headers and their `Error:` lines, so this slice shows the causes too.
1192
1322
  *
1193
1323
  * @param log - The task log path.
1194
1324
  * @param own - A file the command redirects its own output to, if any.
@@ -1434,9 +1564,11 @@ function distinctTests(tests) {
1434
1564
  * The cause repeating among a running suite's failures, or null.
1435
1565
  *
1436
1566
  * Playwright's `list` reporter prints one line per test as it finishes — its mark, its title
1437
- * path and how long it ran — and defers each failure's error to the summary at the end, so
1438
- * mid-run the only signature those lines carry is the duration. Where the log carries the
1439
- * failure bodies (a `line` reporter's output, or a finished run's summary) the signature is the
1567
+ * path and how long it ran — and, on a run the platform started in the background, each failure's
1568
+ * own error with it ({@link PLAYWRIGHT_FAILURES_INLINE_ENV}); a `list` run with no error bodies in
1569
+ * its log (an older Playwright, a log the bodies have been cut from) carries only the duration as
1570
+ * a signature. Where the log carries the failure bodies (either inline, or in a finished run's
1571
+ * summary) the signature is the
1440
1572
  * error itself — {@link failureMessage}: the error class plus the locator or the values that
1441
1573
  * differ — which is stronger (it needs no assumption about how long a failure should take), so
1442
1574
  * the message is looked for first and the duration is then left with the tests whose bodies the
@@ -1619,6 +1751,42 @@ export function universalCause(log, found) {
1619
1751
  return null;
1620
1752
  return { count: found.count, files };
1621
1753
  }
1754
+ /**
1755
+ * The ONE finding that ends a wait early, and the only one a note may hand a stop command over
1756
+ * for: a PROVEN cause that is failing the whole run.
1757
+ *
1758
+ * Both halves are load-bearing, each of them learned from a run that lost minutes to the other.
1759
+ *
1760
+ * - **Failing the WHOLE run** is {@link universalCause}: every failure the log names, across
1761
+ * {@link UNIVERSAL_CAUSE_FILES} spec files or more, with nothing passing since the first — the
1762
+ * dont-stop-runs rule. X1 flash-m83 (2026-10-16) stopped eight local runs at their first
1763
+ * repeating cause in 14.5 minutes and never finished one, and a run that still has other causes
1764
+ * left to name is the only thing that will name them.
1765
+ * - **A PROVEN cause** is an error repeated VERBATIM. A shared DURATION is a LEAD, never a cause:
1766
+ * a suite whose config sets a timeout spends that timeout on every failure that waits for
1767
+ * anything, so three unrelated tests timing out together look exactly like one broken run
1768
+ * (`~7 s` is a property of the CONFIG, not of the cause — {@link normalizedSignature}). X1
1769
+ * xr-molecule-flash-m99 (2026-10-16) was told `status: 'repeating_failure'` twice on that
1770
+ * shape — three `url-navigation.spec.ts` tests at ~16.2 s, one `timeout: 15_000` plus teardown
1771
+ * — read the early return as "stop waiting, edit now", and voided a run that was still walking;
1772
+ * the second cost a 224 s wait that ended with no result at all.
1773
+ *
1774
+ * Neither half alone is enough, and {@link repeatingFailure} finding a signature is not either:
1775
+ * that answers "is a cause repeating among this run's failures", which is worth telling the
1776
+ * executor mid-run as a NOTE while the wait goes on. This answers the narrower question the wait
1777
+ * needs — is the run over as a measuring instrument — and it is THE one predicate behind both
1778
+ * that decision and the note's wording, so the two cannot come to different verdicts.
1779
+ *
1780
+ * @param found - What {@link repeatingFailure} found mid-run.
1781
+ * @param universal - What {@link universalCause} found for it, if anything.
1782
+ * @returns The cause to stop the run over, or null — in which case nothing may be stopped, the
1783
+ * wait keeps going, and the finding rides the run's result as a note.
1784
+ */
1785
+ export function earlyReturnCause(found, universal) {
1786
+ if (found.message === null)
1787
+ return null;
1788
+ return universal ?? null;
1789
+ }
1622
1790
  /**
1623
1791
  * Every failure a run names, grouped by the cause behind it — one group per cause, with the
1624
1792
  * tests it hit.
@@ -1628,11 +1796,11 @@ export function universalCause(log, found) {
1628
1796
  * bodies to read; X1 flash-m83 (2026-10-16) spent three deploys (6.7 minutes) each fixing a
1629
1797
  * single cause, two of them found by runs stopped before they walked the rest.
1630
1798
  *
1631
- * The signature is the cause itself where the log carries the failures' bodies (a finished run,
1632
- * or a `line` reporter) — {@link failureMessage}: the error class plus the locator or the values
1633
- * that differ — and how long they took where it does not (a still-running `list` log, which is
1634
- * why a duration group is labelled as a duration and not as a proven cause). A test the log
1635
- * printed twice, or failed twice, is one test.
1799
+ * The signature is the cause itself where the log carries the failures' bodies (a finished run, a
1800
+ * background `list` run — whose failures print as they fail — or a `line` reporter) —
1801
+ * {@link failureMessage}: the error class plus the locator or the values that differ — and how long
1802
+ * they took where it does not, which is why a duration group is labelled as a duration and not as a
1803
+ * proven cause. A test the log printed twice, or failed twice, is one test.
1636
1804
  *
1637
1805
  * @param log - The log of a finished or running run.
1638
1806
  * @returns The causes, the one with the most tests first.
@@ -1658,8 +1826,9 @@ export function failuresByCause(log) {
1658
1826
  if (tests.length > 0)
1659
1827
  causes.push({ message, seconds: null, tests });
1660
1828
  }
1661
- // The failures with no body of their own — every failure of a still-running `list` log — are
1662
- // grouped by how long they took: a band is opened by its first test and takes the ones that
1829
+ // The failures with no body of their own — a `list` log with no error blocks in it, from a run
1830
+ // not started in the background — are grouped by how long they took: a band is opened by its
1831
+ // first test and takes the ones that
1663
1832
  // then ran the same length, the same band {@link repeatingFailure} uses.
1664
1833
  const claimed = new Set(causes.flatMap((c) => c.tests.map(testKey)));
1665
1834
  const unclaimed = distinctTests(failedTests(text)).filter((t) => t.seconds !== null && !claimed.has(testKey(t)));
@@ -1746,11 +1915,15 @@ export function rerunOfRunningSuite(run, locations) {
1746
1915
  * tests, so the note never names one or two tests as a cause.
1747
1916
  *
1748
1917
  * The note names the cause early so the executor can START FIXING while the run keeps walking,
1749
- * and it asks for the run to be stopped only when {@link universalCause} says the cause is
1750
- * failing the whole run. X1 flash-m76 (2026-10-16) spent 4.0 minutes walking 15 tests whose one
1751
- * cause was certain at the third, 47 s in, and the note answers exactly that; X1 flash-m83 then
1752
- * stopped eight runs at their first repeating cause in 14.5 minutes and never finished one, so
1753
- * the note must not say to stop when the run still has other causes to name.
1918
+ * and it hands a stop command over only when {@link earlyReturnCause} says so — the SAME
1919
+ * predicate the wait uses to decide whether to return early, so a finding the wait keeps waiting
1920
+ * on is a finding this note never asks to stop for. X1 flash-m76 (2026-10-16) spent 4.0 minutes
1921
+ * walking 15 tests whose one cause was certain at the third, 47 s in, and the note answers
1922
+ * exactly that; X1 flash-m83 then stopped eight runs at their first repeating cause in 14.5
1923
+ * minutes and never finished one, so the note must not say to stop when the run still has other
1924
+ * causes to name. X1 xr-molecule-flash-m99 (2026-10-16) is the third shape: a shared duration is
1925
+ * not a cause at all, so a lead reaches the executor as a note on a result it is still waiting
1926
+ * for — never as a verdict with a stop command in it.
1754
1927
  *
1755
1928
  * The run is STILL WALKING while this note is written — both callers produce it mid-run — so a
1756
1929
  * re-run of one of its tests is a second run against the same app and database, and the platform
@@ -1764,7 +1937,7 @@ export function rerunOfRunningSuite(run, locations) {
1764
1937
  *
1765
1938
  * @param found - What {@link repeatingFailure} found.
1766
1939
  * @param o - The run's facts: its `taskId`, its `log` path, `stop` — the shell command that
1767
- * stops it, printed only for a {@link UniversalCause} — `universal`, what
1940
+ * stops it, printed only for an {@link earlyReturnCause} — `universal`, what
1768
1941
  * {@link universalCause} found (absent means the run is not failing whole), and `run`, how the
1769
1942
  * run was started ({@link rerunOfRunningSuite}) when the caller knows it.
1770
1943
  * @returns The note.
@@ -1822,8 +1995,11 @@ export function repeatingFailureNote(found, o) {
1822
1995
  // directory the run started in. Without that record it says the timing and nothing more.
1823
1996
  const thenRun = aRunIsInTheWay && rerun ? `\nSend this once the run ends:\n ${rerun}` : '';
1824
1997
  const where = `task ${o.taskId}, log ${o.log}`;
1825
- if (o.universal) {
1826
- const files = o.universal.files.map(shortFile);
1998
+ // The ONE predicate behind this wording and the wait's own early return (`earlyReturnCause`), so
1999
+ // a finding the wait keeps waiting on can never be handed a stop command here.
2000
+ const stop = earlyReturnCause(found, o.universal);
2001
+ if (stop) {
2002
+ const files = stop.files.map(shortFile);
1827
2003
  const shown = files.slice(0, 4).join(', ');
1828
2004
  const moreFiles = files.length > 4 ? `, … and ${files.length - 4} more` : '';
1829
2005
  return (`Every test this run has walked so far has failed the same way — all ${found.count} of ` +
@@ -1833,15 +2009,20 @@ export function repeatingFailureNote(found, o) {
1833
2009
  `repeats this one cause. Stop it and fix that cause first: \`exec_command: ${o.stop}\`, ` +
1834
2010
  `then run the whole suite again. It is still going (${where}).${reproduce}`);
1835
2011
  }
2012
+ // Everything else is a note on a run the wait is still waiting for, and both its shapes end the
2013
+ // same way: the run finishes, because it is the only thing that names the causes this finding is
2014
+ // not. What it does NOT carry is the "Stop it if every test fails this way" clause — that one
2015
+ // belongs to a PROVEN cause the run is still walking (the sentence below), never to a lead:
2016
+ // xr-molecule-flash-m99's executor read it on a shared duration and voided the run.
1836
2017
  const keepGoing = `Let the rest of the run finish — it is the only thing that will name the causes that are NOT ` +
1837
2018
  `this one, and a run stopped at its first repeating cause costs a second whole run to find ` +
1838
- `them. Stop it only if every test it walks fails this same way (the app unreachable, a 5xx on ` +
1839
- `every request, the same selector timing out on every test of every file so far). ` +
1840
- `It is still going (${where}).`;
2019
+ `them. It is still going (${where}).`;
1841
2020
  if (isCause)
1842
2021
  return (`${found.count} different tests in this run have already failed the same way — ${signature} — ` +
1843
2022
  `so one cause is repeating:\n${rows}${more}\n` +
1844
- `Start fixing it now, while the run keeps walking.${reproduce} ${keepGoing}${thenRun}`);
2023
+ `Start fixing it now, while the run keeps walking. Stop it only if every test it walks ` +
2024
+ `fails this same way (the app unreachable, a 5xx on every request, the same selector timing ` +
2025
+ `out on every test of every file so far).${reproduce} ${keepGoing}${thenRun}`);
1845
2026
  return (`${found.count} different tests in this run each failed after ~${found.seconds}s — the same ` +
1846
2027
  `duration to within half a second. A shared duration is a lead, not a cause: a suite whose ` +
1847
2028
  `config sets a timeout spends that timeout on every failure that waits for anything, so ` +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/api-ai-tools",
3
- "version": "1.6.5",
3
+ "version": "1.7.0",
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",
@@ -31,7 +31,7 @@
31
31
  "@molecule/api-ai": "^1.0.1"
32
32
  },
33
33
  "devDependencies": {
34
- "@molecule/api-ai": "1.3.3",
34
+ "@molecule/api-ai": "1.3.4",
35
35
  "@types/node": "26.1.2",
36
36
  "esbuild": "0.28.2",
37
37
  "typescript": "6.0.3",