@molecule/api-ai-tools 1.9.15 → 1.9.18
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 +340 -23
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/output-filter.d.ts +5 -1
- package/dist/output-filter.d.ts.map +1 -1
- package/dist/output-filter.js +12 -3
- package/dist/server-command.d.ts +73 -0
- package/dist/server-command.d.ts.map +1 -0
- package/dist/server-command.js +180 -0
- package/dist/suite-overlap.d.ts +20 -1
- package/dist/suite-overlap.d.ts.map +1 -1
- package/dist/suite-overlap.js +48 -3
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +88 -7
- package/dist/trace-artifacts.d.ts +135 -10
- package/dist/trace-artifacts.d.ts.map +1 -1
- package/dist/trace-artifacts.js +797 -125
- package/dist/types.d.ts +39 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utilities.d.ts +52 -1
- package/dist/utilities.d.ts.map +1 -1
- package/dist/utilities.js +143 -23
- package/package.json +1 -1
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-
|
|
6
|
+
Generated: 2026-10-18T15:48:52.035Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/api-ai-tools
|
|
@@ -309,6 +309,17 @@ interface ToolSchema {
|
|
|
309
309
|
}
|
|
310
310
|
```
|
|
311
311
|
|
|
312
|
+
#### `ForegroundServer`
|
|
313
|
+
|
|
314
|
+
A foreground command that starts a server, as the refusal names it.
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
interface ForegroundServer {
|
|
318
|
+
/** The program (and script, when there is one) that serves. */
|
|
319
|
+
readonly program: string
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
312
323
|
#### `LeadingSleep`
|
|
313
324
|
|
|
314
325
|
The leading `sleep` a command opens with, and the command that follows it.
|
|
@@ -345,6 +356,20 @@ interface SuiteRunInFlight {
|
|
|
345
356
|
}
|
|
346
357
|
```
|
|
347
358
|
|
|
359
|
+
#### `DiagnosisRunContext`
|
|
360
|
+
|
|
361
|
+
What a caller knows about the run being judged beyond its command text.
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
interface DiagnosisRunContext {
|
|
365
|
+
/**
|
|
366
|
+
* The test titles the person's request excludes by name — the same reading molecule-dev's
|
|
367
|
+
* `excludedTestTitles` gives the rest of the platform.
|
|
368
|
+
*/
|
|
369
|
+
approvedExclusions?: readonly string[]
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
348
373
|
#### `InstalledPackageFacts`
|
|
349
374
|
|
|
350
375
|
What the filesystem says about a write target under `node_modules` — the half
|
|
@@ -426,6 +451,14 @@ interface TraceRequest {
|
|
|
426
451
|
* credential-less request from one whose credential is a cookie.
|
|
427
452
|
*/
|
|
428
453
|
sentCookie?: boolean
|
|
454
|
+
/**
|
|
455
|
+
* The trace member this request came from — the browser context Playwright numbered (`1`, `3`).
|
|
456
|
+
* A test that opens a second browser context writes one trace member per context, and a test's
|
|
457
|
+
* request is only evidence about the page it was made on (xr-molecule-flash-m160).
|
|
458
|
+
*/
|
|
459
|
+
context?: string
|
|
460
|
+
/** The page the request was made on, as the HAR entry's `pageref` records it. */
|
|
461
|
+
pageId?: string
|
|
429
462
|
}
|
|
430
463
|
```
|
|
431
464
|
|
|
@@ -472,6 +505,59 @@ interface TraceAction {
|
|
|
472
505
|
start: number
|
|
473
506
|
/** When it finished, or null when the run ended before it did. */
|
|
474
507
|
end: number | null
|
|
508
|
+
/** The browser context the action was recorded in (`1`, `3`), when the trace names one. */
|
|
509
|
+
context?: string
|
|
510
|
+
/** The page the action ran on, from the frame snapshot the trace paired with it. */
|
|
511
|
+
pageId?: string
|
|
512
|
+
/** The frame the action ran in, from the same snapshot. */
|
|
513
|
+
frameId?: string
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
#### `TraceContextEvidence`
|
|
518
|
+
|
|
519
|
+
What a browser context OTHER than the failing page's recorded — the second context a
|
|
520
|
+
two-context test opens for its own setup.
|
|
521
|
+
|
|
522
|
+
Its actions and requests belong to a different page: a request it sent is not the failing
|
|
523
|
+
action's effect, and the URL it left the page on is not where the assertion's page went
|
|
524
|
+
(xr-molecule-flash-m160: the helper context created an article in an editor page while the
|
|
525
|
+
primary page moved to the profile the assertion then failed on, and the note called the
|
|
526
|
+
editor page the failing page).
|
|
527
|
+
|
|
528
|
+
```typescript
|
|
529
|
+
interface TraceContextEvidence {
|
|
530
|
+
/** The trace member's context id (`3`). */
|
|
531
|
+
context: string
|
|
532
|
+
/**
|
|
533
|
+
* The app requests that context made, bounded — failures first, then the answered ones — each
|
|
534
|
+
* labelled by the note as set-up work rather than the failing page's.
|
|
535
|
+
*/
|
|
536
|
+
requests: TraceRequest[]
|
|
537
|
+
}
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
#### `TraceMissingText`
|
|
541
|
+
|
|
542
|
+
The text a failing assertion waited for that a same-page API response carried and the page never
|
|
543
|
+
rendered.
|
|
544
|
+
|
|
545
|
+
The assertion's own error names the text (a `has-text(…)` / `getByText(…)` / `toContainText(…)`
|
|
546
|
+
argument), and the trace's network log holds the response that contained it. That pair is the
|
|
547
|
+
whole diagnosis: the API returned the value and the page dropped it before rendering, so the cut
|
|
548
|
+
is in the component that maps the response onto the list — not in the API, the route or the
|
|
549
|
+
selector. xr-molecule-flash-m169 (+13:09) spent its fix rounds on the wrong component and on a
|
|
550
|
+
markup detail while `GET /api/tags` was returning the missing "trending" and `PopularTags`
|
|
551
|
+
sliced the response to its first 20 entries (the m99 top-N class, in the frontend).
|
|
552
|
+
|
|
553
|
+
```typescript
|
|
554
|
+
interface TraceMissingText {
|
|
555
|
+
/** The text the assertion waited for (`trending`). */
|
|
556
|
+
text: string
|
|
557
|
+
/** The method of the response that carried it (`GET`). */
|
|
558
|
+
method: string
|
|
559
|
+
/** The path of the response that carried it (`/api/tags`). */
|
|
560
|
+
path: string
|
|
475
561
|
}
|
|
476
562
|
```
|
|
477
563
|
|
|
@@ -506,19 +592,55 @@ interface TraceArtifact {
|
|
|
506
592
|
*/
|
|
507
593
|
console: string[]
|
|
508
594
|
/**
|
|
509
|
-
* The test's LAST user action before the failing assertion
|
|
510
|
-
* row leads with, when the trace carries the action times
|
|
595
|
+
* The test's LAST user action before the failing assertion ON THE PAGE THE ASSERTION RAN ON, and
|
|
596
|
+
* the requests it caused — what the row leads with, when the trace carries the action times
|
|
597
|
+
* ({@link TraceLastAction}).
|
|
511
598
|
*
|
|
512
|
-
*
|
|
513
|
-
*
|
|
599
|
+
* A test that opens a second browser context writes one trace member per context, and the
|
|
600
|
+
* archive does not order them by time: the last action of the concatenation may belong to the
|
|
601
|
+
* helper's page while the assertion failed on another (xr-molecule-flash-m160). The action is
|
|
602
|
+
* therefore the failing page's own, and its `pageAfter` is that page's last frame snapshot.
|
|
603
|
+
*
|
|
604
|
+
* Absent on traces read before this field existed, on traces whose network entries recorded no
|
|
605
|
+
* clock, and on a trace with more than one used context whose failing page cannot be identified
|
|
606
|
+
* ({@link TraceArtifact.unattributed}) — the row then falls back to {@link lead}, or to no
|
|
607
|
+
* causal claim at all.
|
|
514
608
|
*/
|
|
515
609
|
lastAction?: TraceLastAction
|
|
516
610
|
/**
|
|
517
611
|
* The page's own actions in the order the trace recorded them, bounded — what a test that ran
|
|
518
612
|
* out of a per-test budget spends its time on. A test that repeats one action prints it once per
|
|
519
|
-
* repeat, so the gap between two starts is one repeat's measured cost.
|
|
613
|
+
* repeat, so the gap between two starts is one repeat's measured cost. Scoped to the page the
|
|
614
|
+
* failing assertion ran on; a second browser context's actions are not this test's page.
|
|
520
615
|
*/
|
|
521
616
|
actions: TraceAction[]
|
|
617
|
+
/**
|
|
618
|
+
* True when the trace held more than one browser context and none of them could be tied to the
|
|
619
|
+
* failing assertion's page. The note then makes no causal claim — no "the test's last action",
|
|
620
|
+
* no "the page stayed at …" — rather than attributing one context's click and URL to another
|
|
621
|
+
* context's assertion (xr-molecule-flash-m160).
|
|
622
|
+
*/
|
|
623
|
+
unattributed?: true
|
|
624
|
+
/**
|
|
625
|
+
* The browser contexts the test opened BESIDES the failing assertion's page, with the app
|
|
626
|
+
* requests each made. Kept apart so the note can name them as set-up work instead of printing
|
|
627
|
+
* their requests as the failing action's effects (xr-molecule-flash-m160).
|
|
628
|
+
*
|
|
629
|
+
* Absent when the trace recorded one context only, when every other context made no request,
|
|
630
|
+
* and on traces read before this field existed.
|
|
631
|
+
*/
|
|
632
|
+
otherContexts?: TraceContextEvidence[]
|
|
633
|
+
/**
|
|
634
|
+
* The text the failing assertion waited for and a same-page API response carried, when the trace
|
|
635
|
+
* recorded both. The note leads with it: the value reached the browser and the page did not
|
|
636
|
+
* render it, so the next read is where that response is mapped — never the API or the selector
|
|
637
|
+
* (xr-molecule-flash-m169).
|
|
638
|
+
*
|
|
639
|
+
* Absent when the assertion waited for no text (a text-free selector, a strict-mode violation),
|
|
640
|
+
* when no page-scoped `fetch`/`xhr` answered 2xx/3xx with the text in its body, and on traces
|
|
641
|
+
* read before this field existed.
|
|
642
|
+
*/
|
|
643
|
+
missingText?: TraceMissingText
|
|
522
644
|
}
|
|
523
645
|
```
|
|
524
646
|
|
|
@@ -565,6 +687,14 @@ interface TraceRunReport {
|
|
|
565
687
|
* contradicts it.
|
|
566
688
|
*/
|
|
567
689
|
productionBuildAdvised?: boolean
|
|
690
|
+
/**
|
|
691
|
+
* The endpoints the app's own auth config names for a credential exchange — a login, a
|
|
692
|
+
* registration, a token endpoint (`loginEndpoint: '/users/login'`, resolved from the app's
|
|
693
|
+
* source). A 401/403 there answers credentials the app was ASKED to check, never a token the
|
|
694
|
+
* client failed to attach, so the note says so even when the path is mounted somewhere unusual.
|
|
695
|
+
* Empty when the caller could not read the app's config.
|
|
696
|
+
*/
|
|
697
|
+
authEndpoints?: readonly string[]
|
|
568
698
|
}
|
|
569
699
|
```
|
|
570
700
|
|
|
@@ -633,6 +763,33 @@ interface ExecutionBackend {
|
|
|
633
763
|
}
|
|
634
764
|
```
|
|
635
765
|
|
|
766
|
+
#### `SuiteBudgetPin`
|
|
767
|
+
|
|
768
|
+
The supplied suite's own settings, put back on a run whose runner config changes them.
|
|
769
|
+
|
|
770
|
+
A graded suite is walked by the grader under its own per-test budget, worker count and
|
|
771
|
+
timeouts. An executor's run that reads a config setting different numbers measures a run the
|
|
772
|
+
grader never sees: a shorter budget fails tests the graded walk passes, a longer one passes
|
|
773
|
+
tests the graded walk times out on. The platform that knows the suite supplies these values
|
|
774
|
+
before the run ({@link ToolBuildConfig.suiteBudget}); the shared tool puts the flags on the
|
|
775
|
+
runner's own command line, where Playwright lets them win over every config file.
|
|
776
|
+
|
|
777
|
+
```typescript
|
|
778
|
+
interface SuiteBudgetPin {
|
|
779
|
+
/**
|
|
780
|
+
* The Playwright flags that carry the suite's own settings onto the command
|
|
781
|
+
* (`--timeout=15000`, `--workers=1`), as the consumer's own scan reads them. Empty when the
|
|
782
|
+
* difference is in settings no flag carries — the pin is then the sentence alone.
|
|
783
|
+
*/
|
|
784
|
+
flags: string[]
|
|
785
|
+
/**
|
|
786
|
+
* One sentence for the run's result: this run uses the suite's own budget, and which settings
|
|
787
|
+
* a config keeps because Playwright has no flag for them.
|
|
788
|
+
*/
|
|
789
|
+
note: string
|
|
790
|
+
}
|
|
791
|
+
```
|
|
792
|
+
|
|
636
793
|
#### `ToolBuildConfig`
|
|
637
794
|
|
|
638
795
|
Configuration for building the tool set.
|
|
@@ -740,6 +897,23 @@ interface ToolBuildConfig {
|
|
|
740
897
|
*/
|
|
741
898
|
excludedTestTitles?: () => readonly string[]
|
|
742
899
|
|
|
900
|
+
/**
|
|
901
|
+
* The supplied suite's own budget, when the Playwright config a command would load sets
|
|
902
|
+
* different settings, asked BEFORE the run executes. The consumer knows where the suite and its
|
|
903
|
+
* base config live; this shared package does not, so the reading is the consumer's and the
|
|
904
|
+
* mechanics — putting the flags on the runner's own arguments, before the pipeline and outside
|
|
905
|
+
* any redirect or group closer — are this tool's.
|
|
906
|
+
*
|
|
907
|
+
* Called for a Playwright suite command only, and only the LAST suite step is touched. A run
|
|
908
|
+
* that already keeps the suite's settings, or a sandbox with no supplied suite, answers `null`.
|
|
909
|
+
* Unset (or a hook that throws) changes nothing: the command runs as the model wrote it.
|
|
910
|
+
*
|
|
911
|
+
* @param command - The shell command, as the model sent it.
|
|
912
|
+
* @param cwd - The resolved working directory it will run in.
|
|
913
|
+
* @returns The flags and the sentence, or null when nothing is put back.
|
|
914
|
+
*/
|
|
915
|
+
suiteBudget?: (command: string, cwd: string) => Promise<SuiteBudgetPin | null | undefined>
|
|
916
|
+
|
|
743
917
|
/** Post-write hook (e.g. auto-format via Prettier/ESLint). Called after every write_file/edit_file. */
|
|
744
918
|
onAfterWrite?: (path: string) => Promise<void>
|
|
745
919
|
|
|
@@ -1521,7 +1695,7 @@ function commandRunsNoTests(command: string): boolean
|
|
|
1521
1695
|
|
|
1522
1696
|
**Returns:** True when the command invokes a runner only to print.
|
|
1523
1697
|
|
|
1524
|
-
#### `outputFilterAfterRunner(command, runs)`
|
|
1698
|
+
#### `outputFilterAfterRunner(command, runs, occurrence)`
|
|
1525
1699
|
|
|
1526
1700
|
The output filter that follows the runner in `command`, or null when there is none.
|
|
1527
1701
|
|
|
@@ -1534,11 +1708,13 @@ middle stage were cut out, so a chain is not answered here at all. A filter befo
|
|
|
1534
1708
|
function outputFilterAfterRunner(
|
|
1535
1709
|
command: string,
|
|
1536
1710
|
runs: (segment: CommandSegment) => boolean,
|
|
1711
|
+
occurrence?: number,
|
|
1537
1712
|
): RunnerOutputFilter | null
|
|
1538
1713
|
```
|
|
1539
1714
|
|
|
1540
1715
|
- `command` — The command as the executor sent it.
|
|
1541
1716
|
- `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).
|
|
1717
|
+
- `occurrence` — Which runner invocation the output belongs to, 1-based. A command can run the same runner more than once (xr-molecule-flash-m170: the suite bare, then with `HOST=…`), and each invocation carries its OWN pipe; a reader judging the second walk must name the second walk's cut, never the first's.
|
|
1542
1718
|
|
|
1543
1719
|
**Returns:** The filter and the unfiltered command, or null.
|
|
1544
1720
|
|
|
@@ -1566,6 +1742,56 @@ function pipelineExitCodeNote(command: string, exitCode: number, output: string)
|
|
|
1566
1742
|
|
|
1567
1743
|
**Returns:** One sentence naming the stage the code came from, or null.
|
|
1568
1744
|
|
|
1745
|
+
#### `startsServerProgram(command)`
|
|
1746
|
+
|
|
1747
|
+
Whether a command, read from its TEXT alone, starts a server that stays up in the foreground.
|
|
1748
|
+
|
|
1749
|
+
The over-budget reader's shape: at that point the command has already run, and only its text is
|
|
1750
|
+
left to say whether "run a smaller unit" was ever the right advice.
|
|
1751
|
+
|
|
1752
|
+
```typescript
|
|
1753
|
+
function startsServerProgram(command: string): boolean
|
|
1754
|
+
```
|
|
1755
|
+
|
|
1756
|
+
- `command` — The command as the executor sent it.
|
|
1757
|
+
|
|
1758
|
+
**Returns:** True when a foreground statement of the command starts a server.
|
|
1759
|
+
|
|
1760
|
+
#### `foregroundServerCommand(command, readScript)`
|
|
1761
|
+
|
|
1762
|
+
A FOREGROUND command that starts a server, including one that only names a script whose SOURCE
|
|
1763
|
+
imports the app's server and calls its `create()`/`listen()`.
|
|
1764
|
+
|
|
1765
|
+
The script read is best-effort: a path the backend will not answer for is a command this reading
|
|
1766
|
+
cannot classify, never a refusal. A backgrounded launch, a test runner and a test file are all
|
|
1767
|
+
left alone.
|
|
1768
|
+
|
|
1769
|
+
```typescript
|
|
1770
|
+
function foregroundServerCommand(
|
|
1771
|
+
command: string,
|
|
1772
|
+
readScript: (path: string) => Promise<string>,
|
|
1773
|
+
): Promise<ForegroundServer | null>
|
|
1774
|
+
```
|
|
1775
|
+
|
|
1776
|
+
- `command` — The command as the executor sent it.
|
|
1777
|
+
- `readScript` — Reads a script file the command names (`backend.readFile`).
|
|
1778
|
+
|
|
1779
|
+
**Returns:** The serving program, or null when the command starts no server in the foreground.
|
|
1780
|
+
|
|
1781
|
+
#### `serverCommandRefusal(server, budgetSeconds)`
|
|
1782
|
+
|
|
1783
|
+
The refusal for a foreground command that starts a server: why it would never return, and the
|
|
1784
|
+
two shapes that do work — a background launch, or a probe of the API already running.
|
|
1785
|
+
|
|
1786
|
+
```typescript
|
|
1787
|
+
function serverCommandRefusal(server: ForegroundServer, budgetSeconds: number): string
|
|
1788
|
+
```
|
|
1789
|
+
|
|
1790
|
+
- `server` — The serving program, from {@link foregroundServerCommand}.
|
|
1791
|
+
- `budgetSeconds` — The tool's budget, which a foreground server would consume whole.
|
|
1792
|
+
|
|
1793
|
+
**Returns:** The refusal sentence.
|
|
1794
|
+
|
|
1569
1795
|
#### `leadingSleepPeek(command)`
|
|
1570
1796
|
|
|
1571
1797
|
The leading `sleep` of a command, when the first statement is one and it asks for at least
|
|
@@ -1703,7 +1929,7 @@ function suiteRunInTheWay(candidate: { target: string }, inFlight: readonly T[])
|
|
|
1703
1929
|
|
|
1704
1930
|
**Returns:** The first run in the way, or null.
|
|
1705
1931
|
|
|
1706
|
-
#### `isDiagnosisRun(command)`
|
|
1932
|
+
#### `isDiagnosisRun(command, context)`
|
|
1707
1933
|
|
|
1708
1934
|
Whether a command walks a PART of a suite instead of all of it: a cap that stops it at a failure
|
|
1709
1935
|
count, the failures the last run printed (`--last-failed`, `--only-changed`), a title filter, or
|
|
@@ -1732,10 +1958,11 @@ absorb it).
|
|
|
1732
1958
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/suite-overlap.d.ts`.)_
|
|
1733
1959
|
|
|
1734
1960
|
```typescript
|
|
1735
|
-
function isDiagnosisRun(command: string): boolean
|
|
1961
|
+
function isDiagnosisRun(command: string, context?: DiagnosisRunContext): boolean
|
|
1736
1962
|
```
|
|
1737
1963
|
|
|
1738
1964
|
- `command` — The command as the executor sent it.
|
|
1965
|
+
- `context` — The request's approved exclusions, when the caller knows them.
|
|
1739
1966
|
|
|
1740
1967
|
**Returns:** True when the run is a diagnosis or a re-run, not the whole suite.
|
|
1741
1968
|
|
|
@@ -1905,9 +2132,9 @@ over anything else when it is the page talking to the app (`fetch`/`xhr`/`docume
|
|
|
1905
2132
|
test's trace holds the whole page load. A request with no response and NO error text was aborted
|
|
1906
2133
|
or still in flight when the test ended; it is kept too, but as what it is, not as a failure.
|
|
1907
2134
|
|
|
1908
|
-
A
|
|
1909
|
-
|
|
1910
|
-
|
|
2135
|
+
A trace.zip holds ONE trace member per browser context the test used (beside the runner's own
|
|
2136
|
+
`test.trace`), and the archive's member order is not the test's chronology. Each member is read
|
|
2137
|
+
as its own context: actions and requests keep their context id, requests and frame snapshots
|
|
1911
2138
|
|
|
1912
2139
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/trace-artifacts.d.ts`.)_
|
|
1913
2140
|
|
|
@@ -2064,15 +2291,21 @@ function suiteRecordsTraces(configText: string): boolean
|
|
|
2064
2291
|
|
|
2065
2292
|
#### `diagnosisTraceCommand(args)`
|
|
2066
2293
|
|
|
2067
|
-
The command a
|
|
2294
|
+
The command a Playwright run needs to leave a readable trace behind, when the suite's config
|
|
2068
2295
|
would record none.
|
|
2069
2296
|
|
|
2070
2297
|
The failing tests' requests are only readable if the run wrote them down (see the module doc),
|
|
2071
2298
|
and the config is where the decision about that lives — the platform does not edit the suite's
|
|
2072
|
-
config, so it passes the flag instead,
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2299
|
+
config, so it passes the flag instead, on every Playwright run that starts tests and does not
|
|
2300
|
+
already decide its own `--trace`. That includes the whole-suite proof run, which an earlier
|
|
2301
|
+
version of this function skipped on the reasoning that its flags are graded: the flag changes
|
|
2302
|
+
what is RETAINED, not what passes. `retain-on-failure` keeps the trace only of a test that
|
|
2303
|
+
fails — Playwright records it and deletes it when the test passes (playwright's
|
|
2304
|
+
`_shouldAbandonTrace` unlinks the temporary trace files of a passing test) — so a green proof
|
|
2305
|
+
run keeps nothing extra. A failing one keeps the network log its failures need.
|
|
2306
|
+
xr-molecule-flash-m163 (+24:58) is why the proof run is no longer skipped: its one deployed
|
|
2307
|
+
failure left only an `error-context.md`, the executor spent the next calls hunting a `trace.zip`
|
|
2308
|
+
that could not exist, and then shipped a guessed fix.
|
|
2076
2309
|
|
|
2077
2310
|
```typescript
|
|
2078
2311
|
function diagnosisTraceCommand(args: {
|
|
@@ -2248,7 +2481,7 @@ function outputRedirectTarget(command: string): string | null
|
|
|
2248
2481
|
|
|
2249
2482
|
**Returns:** The target, or null (`/dev/null` and `&1`/`&2` are not files).
|
|
2250
2483
|
|
|
2251
|
-
#### `streamingBackgroundCommand(command)`
|
|
2484
|
+
#### `streamingBackgroundCommand(command, context)`
|
|
2252
2485
|
|
|
2253
2486
|
Rewrite a command about to run in the background so its log grows while it
|
|
2254
2487
|
runs. Two shapes left the log empty until exit, and an empty log is what
|
|
@@ -2274,14 +2507,14 @@ into the log twice, which on X1 flash-m83 (2026-10-16) made a `--reporter=list,l
|
|
|
2274
2507
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/utilities.d.ts`.)_
|
|
2275
2508
|
|
|
2276
2509
|
```typescript
|
|
2277
|
-
function streamingBackgroundCommand(
|
|
2278
|
-
command: string
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
}
|
|
2510
|
+
function streamingBackgroundCommand(
|
|
2511
|
+
command: string,
|
|
2512
|
+
context?: DiagnosisRunContext,
|
|
2513
|
+
): { command: string; changes: string[]; error?: string }
|
|
2282
2514
|
```
|
|
2283
2515
|
|
|
2284
2516
|
- `command` — The command as the executor sent it.
|
|
2517
|
+
- `context` — What the caller knows beyond the command: the tests the person's request excludes by name ({@link DiagnosisRunContext}). A `--grep-invert` of exactly those is the request's own scope, not a diagnosis, so it keeps the suite's retries on a deployed proof (xr-molecule-flash-m170 +33:16).
|
|
2285
2518
|
|
|
2286
2519
|
**Returns:** The command to run and one sentence per change made (empty when none), or `error` when the command starts the suite more than once.
|
|
2287
2520
|
|
|
@@ -2319,6 +2552,61 @@ function isSuiteRunCommand(command: string): boolean
|
|
|
2319
2552
|
|
|
2320
2553
|
**Returns:** True when the command starts one of those runners.
|
|
2321
2554
|
|
|
2555
|
+
#### `repeatedSuiteRunError(command)`
|
|
2556
|
+
|
|
2557
|
+
The refusal for a command that starts the suite MORE THAN ONCE — the ONE reading every launch
|
|
2558
|
+
site asks, foreground and background alike.
|
|
2559
|
+
|
|
2560
|
+
Each statement is a whole walk of the same suite against the same app, and only the last of them
|
|
2561
|
+
is rewritten, so the earlier ones measure nothing the first did. X1 xr-molecule-flash-m157
|
|
2562
|
+
(+14:02) chained two whole walks of one 138-test suite with `;` (4.5 minutes each) and the
|
|
2563
|
+
background launcher refused it; X1 xr-molecule-flash-m170 (+06:02) chained two invocations of the
|
|
2564
|
+
suite's own runner script in the foreground, where nothing counted them, and the note reported
|
|
2565
|
+
the passing second walk as the first walk's 13 failures.
|
|
2566
|
+
|
|
2567
|
+
The one run handed back is the LAST suite statement, rewritten exactly as
|
|
2568
|
+
{@link streamingBackgroundCommand} rewrites a run (a filter or `| tail` after the runner is
|
|
2569
|
+
dropped, and a Playwright run gets the reporter that prints failures). Its own count is one —
|
|
2570
|
+
guarded, so this cannot recurse.
|
|
2571
|
+
|
|
2572
|
+
```typescript
|
|
2573
|
+
function repeatedSuiteRunError(command: string): string | null
|
|
2574
|
+
```
|
|
2575
|
+
|
|
2576
|
+
- `command` — The shell command as the executor sent it.
|
|
2577
|
+
|
|
2578
|
+
**Returns:** The refusal sentence, or null when the command starts the suite zero or one time.
|
|
2579
|
+
|
|
2580
|
+
#### `suiteRunBudgetCommand(command, flags)`
|
|
2581
|
+
|
|
2582
|
+
A command with the supplied suite's own settings written back onto its runner as Playwright
|
|
2583
|
+
flags, and the flags that could not be placed.
|
|
2584
|
+
|
|
2585
|
+
The grader walks the suite under its OWN budget, so a run whose runner config sets a different
|
|
2586
|
+
timeout or worker count measures a run the grader never sees (xr-molecule-flash-m169: a 60 s
|
|
2587
|
+
wrapper config produced a green local proof the official 15 s grader then failed). Playwright
|
|
2588
|
+
lets a command-line flag win over every config file, so the suite's values are put on the
|
|
2589
|
+
runner's own arguments — written where {@link statementArgumentEnd} places them, never after a
|
|
2590
|
+
pipe, redirect or group closer. Only the command's LAST suite step is touched: that is the run
|
|
2591
|
+
every launch site measures.
|
|
2592
|
+
|
|
2593
|
+
A flag the command already carries is REWRITTEN in place (last occurrence wins, as it does for
|
|
2594
|
+
Playwright); a flag it does not carry is inserted at the end of the runner's arguments. A
|
|
2595
|
+
command whose runner cannot be placed is returned exactly as written, with every flag reported
|
|
2596
|
+
as unplaced, so the caller states the fact instead of claiming a pin it did not make.
|
|
2597
|
+
|
|
2598
|
+
```typescript
|
|
2599
|
+
function suiteRunBudgetCommand(
|
|
2600
|
+
command: string,
|
|
2601
|
+
flags: readonly string[],
|
|
2602
|
+
): { command: string; placed: string[]; unplaced: string[] }
|
|
2603
|
+
```
|
|
2604
|
+
|
|
2605
|
+
- `command` — The shell command about to run.
|
|
2606
|
+
- `flags` — The flags to put on it, each as `--name=value`.
|
|
2607
|
+
|
|
2608
|
+
**Returns:** The command to run, the flags placed on it, and the ones it could not carry.
|
|
2609
|
+
|
|
2322
2610
|
#### `withoutSuiteTimeout(command)`
|
|
2323
2611
|
|
|
2324
2612
|
The command with the `timeout <N>` wrapper lifted off the statement that runs the suite, and the
|
|
@@ -3261,6 +3549,35 @@ Canonical tool schemas shared by the agent runtime and documentation.
|
|
|
3261
3549
|
const TOOL_SCHEMAS: Record<string, ToolSchema>
|
|
3262
3550
|
```
|
|
3263
3551
|
|
|
3552
|
+
#### `BACKGROUNDED`
|
|
3553
|
+
|
|
3554
|
+
A background launch: a single `&` (not `&&`, not a `2>&1`) or an explicit detacher. A
|
|
3555
|
+
backgrounded launch never holds the tool, so every reading here stops at it.
|
|
3556
|
+
|
|
3557
|
+
```typescript
|
|
3558
|
+
const BACKGROUNDED: RegExp
|
|
3559
|
+
```
|
|
3560
|
+
|
|
3561
|
+
#### `SERVER_PROGRAM`
|
|
3562
|
+
|
|
3563
|
+
A program that SERVES: the scaffold's entry (`server.ts`/`server.js`), a package manager's
|
|
3564
|
+
`start`/`dev`/`serve`/`preview` script, a Vite dev or preview server, `next start|dev`, or a
|
|
3565
|
+
Python WSGI server. Matched against a command segment's own text, and against a script's SOURCE
|
|
3566
|
+
when the command only names the script file.
|
|
3567
|
+
|
|
3568
|
+
```typescript
|
|
3569
|
+
const SERVER_PROGRAM: RegExp
|
|
3570
|
+
```
|
|
3571
|
+
|
|
3572
|
+
#### `SERVER_OVER_BUDGET_ADVICE`
|
|
3573
|
+
|
|
3574
|
+
The closing advice on an over-budget message for a command recognised as a server start: there
|
|
3575
|
+
is no tally to split, and the run has to leave the foreground budget to keep serving.
|
|
3576
|
+
|
|
3577
|
+
```typescript
|
|
3578
|
+
const SERVER_OVER_BUDGET_ADVICE: string
|
|
3579
|
+
```
|
|
3580
|
+
|
|
3264
3581
|
#### `MIN_PEEK_SLEEP_SECONDS`
|
|
3265
3582
|
|
|
3266
3583
|
The shortest leading sleep the platform drops: below it the wall clock it costs is noise, and a
|
package/dist/index.d.ts
CHANGED
|
@@ -141,6 +141,7 @@ export * from './no-test-run.js';
|
|
|
141
141
|
export * from './output-filter.js';
|
|
142
142
|
export * from './pipeline-exit-note.js';
|
|
143
143
|
export * from './schemas.js';
|
|
144
|
+
export * from './server-command.js';
|
|
144
145
|
export * from './sleep-peek.js';
|
|
145
146
|
export * from './suite-overlap.js';
|
|
146
147
|
export * from './system-prompt.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkIG;AAEH,cAAc,qBAAqB,CAAA;AACnC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,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"}
|
|
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,qBAAqB,CAAA;AACnC,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
|
@@ -141,6 +141,7 @@ export * from './no-test-run.js';
|
|
|
141
141
|
export * from './output-filter.js';
|
|
142
142
|
export * from './pipeline-exit-note.js';
|
|
143
143
|
export * from './schemas.js';
|
|
144
|
+
export * from './server-command.js';
|
|
144
145
|
export * from './sleep-peek.js';
|
|
145
146
|
export * from './suite-overlap.js';
|
|
146
147
|
export * from './system-prompt.js';
|
package/dist/output-filter.d.ts
CHANGED
|
@@ -42,7 +42,11 @@ export interface RunnerOutputFilter {
|
|
|
42
42
|
* @param runs - Whether a segment is the runner this run is about (the caller knows its own kind:
|
|
43
43
|
* {@link CommandSegment.program} is the program, once wrapper words like `timeout 280` and
|
|
44
44
|
* `npx` are taken away).
|
|
45
|
+
* @param occurrence - Which runner invocation the output belongs to, 1-based. A command can run
|
|
46
|
+
* the same runner more than once (xr-molecule-flash-m170: the suite bare, then with `HOST=…`),
|
|
47
|
+
* and each invocation carries its OWN pipe; a reader judging the second walk must name the
|
|
48
|
+
* second walk's cut, never the first's.
|
|
45
49
|
* @returns The filter and the unfiltered command, or null.
|
|
46
50
|
*/
|
|
47
|
-
export declare function outputFilterAfterRunner(command: string, runs: (segment: CommandSegment) => boolean): RunnerOutputFilter | null;
|
|
51
|
+
export declare function outputFilterAfterRunner(command: string, runs: (segment: CommandSegment) => boolean, occurrence?: number): RunnerOutputFilter | null;
|
|
48
52
|
//# sourceMappingURL=output-filter.d.ts.map
|
|
@@ -1 +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
|
|
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;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,EAC1C,UAAU,SAAI,GACb,kBAAkB,GAAG,IAAI,CAsB3B"}
|
package/dist/output-filter.js
CHANGED
|
@@ -35,14 +35,23 @@ const CUTTING_FILTERS = new Set(['awk', 'cut', 'grep', 'head', 'sed', 'tail']);
|
|
|
35
35
|
* @param runs - Whether a segment is the runner this run is about (the caller knows its own kind:
|
|
36
36
|
* {@link CommandSegment.program} is the program, once wrapper words like `timeout 280` and
|
|
37
37
|
* `npx` are taken away).
|
|
38
|
+
* @param occurrence - Which runner invocation the output belongs to, 1-based. A command can run
|
|
39
|
+
* the same runner more than once (xr-molecule-flash-m170: the suite bare, then with `HOST=…`),
|
|
40
|
+
* and each invocation carries its OWN pipe; a reader judging the second walk must name the
|
|
41
|
+
* second walk's cut, never the first's.
|
|
38
42
|
* @returns The filter and the unfiltered command, or null.
|
|
39
43
|
*/
|
|
40
|
-
export function outputFilterAfterRunner(command, runs) {
|
|
44
|
+
export function outputFilterAfterRunner(command, runs, occurrence = 1) {
|
|
41
45
|
if (typeof command !== 'string' || command.trim() === '')
|
|
42
46
|
return null;
|
|
43
47
|
const entries = locatedCommandSegments(command);
|
|
44
|
-
const
|
|
45
|
-
|
|
48
|
+
const runners = [];
|
|
49
|
+
entries.forEach((entry, index) => {
|
|
50
|
+
if (entry.segment !== null && runs(entry.segment))
|
|
51
|
+
runners.push(index);
|
|
52
|
+
});
|
|
53
|
+
const runnerAt = runners[occurrence - 1];
|
|
54
|
+
if (runnerAt === undefined || runnerAt + 1 >= entries.length)
|
|
46
55
|
return null;
|
|
47
56
|
const runner = entries[runnerAt];
|
|
48
57
|
const filter = entries[runnerAt + 1];
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "This command starts a server, and a server never exits" — ONE reading of a server launch,
|
|
3
|
+
* shared by the `exec_command` refusal, the over-budget advice, and the platform's own-server note
|
|
4
|
+
* (`molecule-dev/api/src/ai/own-server-note.ts` imports {@link SERVER_PROGRAM} and
|
|
5
|
+
* {@link BACKGROUNDED} from here), so every surface that names a server names the same commands.
|
|
6
|
+
*
|
|
7
|
+
* X1 xr-molecule-flash-m167 (+19:16 → +24:04) wrote `/tmp/probe.mts` whose body imports the app's
|
|
8
|
+
* `api/src/server.ts` and calls its `create(0)`, then ran it in the FOREGROUND:
|
|
9
|
+
* `npx tsx --env-file=.env /tmp/probe.mts 2>&1 | tail -15`. The scaffold's `create()` calls
|
|
10
|
+
* `server.listen(port)` and returns the server, so the process never exits — and behind `| tail`
|
|
11
|
+
* it printed nothing until it did. The tool waited its whole 290 s budget and answered with "run
|
|
12
|
+
* a smaller unit", advice about the wrong axis for a process that was never going to return.
|
|
13
|
+
*
|
|
14
|
+
* A server started in the background is a different thing: it is the launch the platform records
|
|
15
|
+
* and hands a task id for, and the over-budget advice below keeps it off the foreground budget.
|
|
16
|
+
*
|
|
17
|
+
* @module
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* A background launch: a single `&` (not `&&`, not a `2>&1`) or an explicit detacher. A
|
|
21
|
+
* backgrounded launch never holds the tool, so every reading here stops at it.
|
|
22
|
+
*/
|
|
23
|
+
export declare const BACKGROUNDED: RegExp;
|
|
24
|
+
/**
|
|
25
|
+
* A program that SERVES: the scaffold's entry (`server.ts`/`server.js`), a package manager's
|
|
26
|
+
* `start`/`dev`/`serve`/`preview` script, a Vite dev or preview server, `next start|dev`, or a
|
|
27
|
+
* Python WSGI server. Matched against a command segment's own text, and against a script's SOURCE
|
|
28
|
+
* when the command only names the script file.
|
|
29
|
+
*/
|
|
30
|
+
export declare const SERVER_PROGRAM: RegExp;
|
|
31
|
+
/**
|
|
32
|
+
* Whether a command, read from its TEXT alone, starts a server that stays up in the foreground.
|
|
33
|
+
*
|
|
34
|
+
* The over-budget reader's shape: at that point the command has already run, and only its text is
|
|
35
|
+
* left to say whether "run a smaller unit" was ever the right advice.
|
|
36
|
+
*
|
|
37
|
+
* @param command - The command as the executor sent it.
|
|
38
|
+
* @returns True when a foreground statement of the command starts a server.
|
|
39
|
+
*/
|
|
40
|
+
export declare function startsServerProgram(command: string): boolean;
|
|
41
|
+
/** A foreground command that starts a server, as the refusal names it. */
|
|
42
|
+
export interface ForegroundServer {
|
|
43
|
+
/** The program (and script, when there is one) that serves. */
|
|
44
|
+
readonly program: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* A FOREGROUND command that starts a server, including one that only names a script whose SOURCE
|
|
48
|
+
* imports the app's server and calls its `create()`/`listen()`.
|
|
49
|
+
*
|
|
50
|
+
* The script read is best-effort: a path the backend will not answer for is a command this reading
|
|
51
|
+
* cannot classify, never a refusal. A backgrounded launch, a test runner and a test file are all
|
|
52
|
+
* left alone.
|
|
53
|
+
*
|
|
54
|
+
* @param command - The command as the executor sent it.
|
|
55
|
+
* @param readScript - Reads a script file the command names (`backend.readFile`).
|
|
56
|
+
* @returns The serving program, or null when the command starts no server in the foreground.
|
|
57
|
+
*/
|
|
58
|
+
export declare function foregroundServerCommand(command: string, readScript: (path: string) => Promise<string>): Promise<ForegroundServer | null>;
|
|
59
|
+
/**
|
|
60
|
+
* The refusal for a foreground command that starts a server: why it would never return, and the
|
|
61
|
+
* two shapes that do work — a background launch, or a probe of the API already running.
|
|
62
|
+
*
|
|
63
|
+
* @param server - The serving program, from {@link foregroundServerCommand}.
|
|
64
|
+
* @param budgetSeconds - The tool's budget, which a foreground server would consume whole.
|
|
65
|
+
* @returns The refusal sentence.
|
|
66
|
+
*/
|
|
67
|
+
export declare function serverCommandRefusal(server: ForegroundServer, budgetSeconds: number): string;
|
|
68
|
+
/**
|
|
69
|
+
* The closing advice on an over-budget message for a command recognised as a server start: there
|
|
70
|
+
* is no tally to split, and the run has to leave the foreground budget to keep serving.
|
|
71
|
+
*/
|
|
72
|
+
export declare const SERVER_OVER_BUDGET_ADVICE: string;
|
|
73
|
+
//# sourceMappingURL=server-command.d.ts.map
|