@molecule/api-ai-tools 1.10.5 → 1.10.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +149 -2
- package/dist/browser-probe.d.ts +82 -0
- package/dist/browser-probe.d.ts.map +1 -0
- package/dist/browser-probe.js +526 -0
- package/dist/command-position.d.ts.map +1 -1
- package/dist/command-position.js +51 -7
- package/dist/cut-run.d.ts +7 -0
- package/dist/cut-run.d.ts.map +1 -1
- package/dist/cut-run.js +10 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/inline-script.d.ts +11 -1
- package/dist/inline-script.d.ts.map +1 -1
- package/dist/inline-script.js +50 -6
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +15 -3
- package/dist/server-command.d.ts +16 -0
- package/dist/server-command.d.ts.map +1 -1
- package/dist/server-command.js +37 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +52 -4
- package/dist/trace-artifacts.d.ts +70 -6
- package/dist/trace-artifacts.d.ts.map +1 -1
- package/dist/trace-artifacts.js +610 -53
- 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-19T22:30:20.727Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/api-ai-tools
|
|
@@ -58,6 +58,28 @@ npm install @molecule/api-ai-tools @molecule/api-ai
|
|
|
58
58
|
|
|
59
59
|
### Interfaces
|
|
60
60
|
|
|
61
|
+
#### `BrowserProbeLeak`
|
|
62
|
+
|
|
63
|
+
A browser launch bound to a variable, proven to have no cleanup path.
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
interface BrowserProbeLeak {
|
|
67
|
+
/** The variable the launched browser is bound to (`browser` in the m257 probe). */
|
|
68
|
+
readonly variable: string
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
#### `ForegroundBrowserProbe`
|
|
73
|
+
|
|
74
|
+
A foreground command that directly executes such a script.
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
interface ForegroundBrowserProbe extends BrowserProbeLeak {
|
|
78
|
+
/** The script file as the command named it. */
|
|
79
|
+
readonly script: string
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
61
83
|
#### `CommandSegment`
|
|
62
84
|
|
|
63
85
|
One statement or pipeline stage of a shell command: what it runs, and with what.
|
|
@@ -222,6 +244,13 @@ interface CutRun {
|
|
|
222
244
|
* is slow, so the sentence must not send it to the background (xr-molecule-flash-m200 +03:45).
|
|
223
245
|
*/
|
|
224
246
|
inlineScript?: string | null
|
|
247
|
+
/**
|
|
248
|
+
* The variable a leaked standalone browser launch is bound to, when the command ran such a probe
|
|
249
|
+
* and the cut reader could only classify it after the run (xr-molecule-flash-m257). A leaked
|
|
250
|
+
* handle is not a slow workload: the background is the one place it must not be sent, so the
|
|
251
|
+
* sentence names the close instead.
|
|
252
|
+
*/
|
|
253
|
+
browserProbe?: string | null
|
|
225
254
|
}
|
|
226
255
|
```
|
|
227
256
|
|
|
@@ -584,6 +613,13 @@ selector. xr-molecule-flash-m169 (+13:09) spent its fix rounds on the wrong comp
|
|
|
584
613
|
markup detail while `GET /api/tags` was returning the missing "trending" and `PopularTags`
|
|
585
614
|
sliced the response to its first 20 entries (the m99 top-N class, in the frontend).
|
|
586
615
|
|
|
616
|
+
The text must be a value the response held, never a substring of one: a whole JSON string or
|
|
617
|
+
number value, or a word bounded by non-alphanumerics. A text of 2 characters or fewer, or one
|
|
618
|
+
made of digits only, must be a whole JSON value. xr-molecule-flash-m208's pagination assertion
|
|
619
|
+
waited for "2" and the raw substring hit `pag1792394785820` in a tags response, so the note led
|
|
620
|
+
with a response that had nothing to do with the failure; when no response holds the text that
|
|
621
|
+
way, the field is absent and the note leads with its next finding.
|
|
622
|
+
|
|
587
623
|
```typescript
|
|
588
624
|
interface TraceMissingText {
|
|
589
625
|
/** The text the assertion waited for (`trending`). */
|
|
@@ -765,6 +801,15 @@ interface TraceArtifact {
|
|
|
765
801
|
* leaving the run to probe computed styles (xr-molecule-flash-m197).
|
|
766
802
|
*/
|
|
767
803
|
hiddenBox?: TraceHiddenBox
|
|
804
|
+
/**
|
|
805
|
+
* The method+path groups this test's page sent {@link TRACE_NOTE_LOOP_REPEATS} times or more,
|
|
806
|
+
* most-repeated first — a render loop the note leads with (xr-molecule-flash-m215: 2,106
|
|
807
|
+
* `GET /api/articles/<slug>` in one test, printed as four identical `→ 200` lines). Counted over
|
|
808
|
+
* every network entry of the failing page, not the capped {@link TraceArtifact.requests} list.
|
|
809
|
+
*
|
|
810
|
+
* Absent when no group reached the threshold, and on traces read before this field existed.
|
|
811
|
+
*/
|
|
812
|
+
repeated?: TraceRequestRepeat[]
|
|
768
813
|
}
|
|
769
814
|
```
|
|
770
815
|
|
|
@@ -819,6 +864,13 @@ interface TraceRunReport {
|
|
|
819
864
|
* Empty when the caller could not read the app's config.
|
|
820
865
|
*/
|
|
821
866
|
authEndpoints?: readonly string[]
|
|
867
|
+
/**
|
|
868
|
+
* The app source files whose code sends a repeated request, read by the caller from the
|
|
869
|
+
* project (`app/src/**`) before this note is written. A loop's sentence names the component to
|
|
870
|
+
* read instead of leaving the run to search for it (xr-molecule-flash-m215's `Editor.tsx`).
|
|
871
|
+
* Empty when the caller could not read the app or no file states the path.
|
|
872
|
+
*/
|
|
873
|
+
callSites?: readonly { method: string; path: string; file: string }[]
|
|
822
874
|
}
|
|
823
875
|
```
|
|
824
876
|
|
|
@@ -1446,6 +1498,58 @@ function createSandboxBackend(sandbox: SandboxLike, projectRoot?: string): Execu
|
|
|
1446
1498
|
|
|
1447
1499
|
**Returns:** A backend that proxies all filesystem calls into the sandbox.
|
|
1448
1500
|
|
|
1501
|
+
#### `standaloneBrowserLeak(source)`
|
|
1502
|
+
|
|
1503
|
+
The browser variable a standalone script launches and never closes, when that can be proven from
|
|
1504
|
+
the source alone.
|
|
1505
|
+
|
|
1506
|
+
The proof is a closed world: one plain TOP-LEVEL launch binding whose engine is genuinely
|
|
1507
|
+
Playwright's, every reference to it a known non-closing method call, and no cleanup, escape or
|
|
1508
|
+
persistent-process path anywhere in the source. A source with two launches is read one binding
|
|
1509
|
+
at a time — a proven leak in either one is enough, because that handle alone keeps Node alive.
|
|
1510
|
+
|
|
1511
|
+
```typescript
|
|
1512
|
+
function standaloneBrowserLeak(source: string): BrowserProbeLeak | null
|
|
1513
|
+
```
|
|
1514
|
+
|
|
1515
|
+
- `source` — The script's source, as read from disk.
|
|
1516
|
+
|
|
1517
|
+
**Returns:** The leaking binding, or null when the script is clean or ambiguous.
|
|
1518
|
+
|
|
1519
|
+
#### `browserProbeRefusal(probe, budgetSeconds, piped)`
|
|
1520
|
+
|
|
1521
|
+
The refusal for a foreground command that would run a leaking browser probe: it never returns,
|
|
1522
|
+
and the one move that makes it return is closing the browser (or letting the Playwright runner
|
|
1523
|
+
own it), never moving the leak to the background.
|
|
1524
|
+
|
|
1525
|
+
```typescript
|
|
1526
|
+
function browserProbeRefusal(
|
|
1527
|
+
probe: ForegroundBrowserProbe,
|
|
1528
|
+
budgetSeconds: number,
|
|
1529
|
+
piped?: boolean,
|
|
1530
|
+
): string
|
|
1531
|
+
```
|
|
1532
|
+
|
|
1533
|
+
- `probe` — The leaked probe, from `foregroundBrowserProbe`.
|
|
1534
|
+
- `budgetSeconds` — The tool's budget, which the probe would consume whole.
|
|
1535
|
+
- `piped` — Whether the command pipes through `tail`/`head`, which withholds the probe's output.
|
|
1536
|
+
|
|
1537
|
+
**Returns:** The refusal sentence.
|
|
1538
|
+
|
|
1539
|
+
#### `browserProbeOverBudgetAdvice(probe)`
|
|
1540
|
+
|
|
1541
|
+
The over-budget advice for a leak discovered at cut time (the preflight could not read the script
|
|
1542
|
+
before the run — e.g. the same command wrote it). It names the lifecycle fix and says explicitly
|
|
1543
|
+
that the background is not one: a leaked handle hangs there too.
|
|
1544
|
+
|
|
1545
|
+
```typescript
|
|
1546
|
+
function browserProbeOverBudgetAdvice(probe: ForegroundBrowserProbe): string
|
|
1547
|
+
```
|
|
1548
|
+
|
|
1549
|
+
- `probe` — The leaked probe.
|
|
1550
|
+
|
|
1551
|
+
**Returns:** The sentence the cut result carries.
|
|
1552
|
+
|
|
1449
1553
|
#### `durationSeconds(word)`
|
|
1450
1554
|
|
|
1451
1555
|
The seconds a duration word stands for.
|
|
@@ -1767,7 +1871,12 @@ function allConnectionFailures(failures: readonly (RunFailureClass | null)[]): b
|
|
|
1767
1871
|
The interpreter of an INLINE program that only reads and writes local files — the shape that gets
|
|
1768
1872
|
{@link INLINE_SCRIPT_BUDGET_MS} instead of the tool's command budget.
|
|
1769
1873
|
|
|
1770
|
-
|
|
1874
|
+
EVERY statement of the command must be proven local, not just one of them: each is either an
|
|
1875
|
+
inline interpreter program or a plain file utility ({@link LOCAL_UTILITY}). A statement that runs
|
|
1876
|
+
a script FILE (`node smoke.mjs`, `python3 x.py`, `bash x.sh`) or names a program this module does
|
|
1877
|
+
not know can do anything at all, so the command keeps the full budget.
|
|
1878
|
+
|
|
1879
|
+
An inline program with any external effect keeps the full budget too: no network, install, test
|
|
1771
1880
|
runner, build or server verb may appear anywhere in the command ({@link EXTERNAL_EFFECT}), and
|
|
1772
1881
|
the command must not be a suite run or a foreground server (the platform's own classifiers).
|
|
1773
1882
|
|
|
@@ -2010,6 +2119,29 @@ function foregroundServerCommand(
|
|
|
2010
2119
|
|
|
2011
2120
|
**Returns:** The serving program, or null when the command starts no server in the foreground.
|
|
2012
2121
|
|
|
2122
|
+
#### `foregroundBrowserProbe(command, readScript)`
|
|
2123
|
+
|
|
2124
|
+
A FOREGROUND command that directly runs a standalone script which launches a browser and never
|
|
2125
|
+
closes it — the same never-returns lifecycle class as {@link foregroundServerCommand}, read from
|
|
2126
|
+
the script's SOURCE by {@link standaloneBrowserLeak}.
|
|
2127
|
+
|
|
2128
|
+
The boundaries are the server preflight's, so the two readers cannot disagree about what they are
|
|
2129
|
+
allowed to touch: a backgrounded launch, a test runner and a test file are left alone, and a
|
|
2130
|
+
script the backend will not answer for is a command this reading cannot classify, never a
|
|
2131
|
+
refusal. A Playwright suite is owned by its runner's browser fixture and is never read here.
|
|
2132
|
+
|
|
2133
|
+
```typescript
|
|
2134
|
+
function foregroundBrowserProbe(
|
|
2135
|
+
command: string,
|
|
2136
|
+
readScript: (path: string) => Promise<string>,
|
|
2137
|
+
): Promise<ForegroundBrowserProbe | null>
|
|
2138
|
+
```
|
|
2139
|
+
|
|
2140
|
+
- `command` — The command as the executor sent it.
|
|
2141
|
+
- `readScript` — Reads a script file the command names (`backend.readFile`).
|
|
2142
|
+
|
|
2143
|
+
**Returns:** The leaked probe's variable and script path, or null when the command is not one.
|
|
2144
|
+
|
|
2013
2145
|
#### `serverCommandRefusal(server, budgetSeconds)`
|
|
2014
2146
|
|
|
2015
2147
|
The refusal for a foreground command that starts a server: why it would never return, and the
|
|
@@ -4112,6 +4244,21 @@ How many requests the note names per test.
|
|
|
4112
4244
|
const MAX_TRACE_NOTE_REQUESTS: 4
|
|
4113
4245
|
```
|
|
4114
4246
|
|
|
4247
|
+
#### `TRACE_NOTE_LOOP_REPEATS`
|
|
4248
|
+
|
|
4249
|
+
How many times ONE test may send the same method+path before the note calls it a render loop.
|
|
4250
|
+
|
|
4251
|
+
xr-molecule-flash-m215 (+27:27 → +29:42): an Editor effect with `[seeded, slug, t]` in its
|
|
4252
|
+
dependency list re-fetched `GET /api/articles/<slug>` 2,106 times in one test. The trace reader
|
|
4253
|
+
caps and de-duplicates its request list, so the note printed four identical `→ 200` lines and
|
|
4254
|
+
the run patched the component's seeding, rebuilt and re-ran before unzipping the trace by hand.
|
|
4255
|
+
Twenty is far above the retries a correct page makes (a few on a flaky call) and far below any
|
|
4256
|
+
render loop.
|
|
4257
|
+
|
|
4258
|
+
```typescript
|
|
4259
|
+
const TRACE_NOTE_LOOP_REPEATS: 20
|
|
4260
|
+
```
|
|
4261
|
+
|
|
4115
4262
|
#### `TRACE_NOTE_URL_CHARS`
|
|
4116
4263
|
|
|
4117
4264
|
How long a URL the note prints, before the middle is cut.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A standalone Playwright probe that launches a browser and never closes it — the
|
|
3
|
+
* resource-lifecycle hang `exec_command` did not yet classify.
|
|
4
|
+
*
|
|
5
|
+
* X1 xr-molecule-flash-m257 (+10:44 → +15:34) ran
|
|
6
|
+
* `cd /workspace/my-app/app && node /workspace/.mol-scratch/fav-probe.mjs 2>&1 | tail -5`. The
|
|
7
|
+
* 30-line script binds `const browser = await chromium.launch()`, walks a real page, reaches its
|
|
8
|
+
* last `console.log`, and ends without `browser.close()`, `disconnect()`, a disposal scope or
|
|
9
|
+
* `process.exit()`. Chromium is a live handle, so Node never exits: the tool waited its whole 290 s
|
|
10
|
+
* budget, returned `status: cut_at_budget` with empty stdout (the `| tail` held it), and then
|
|
11
|
+
* advised "run it in the background" — advice for a slow workload, not for a leaked handle.
|
|
12
|
+
*
|
|
13
|
+
* That is the same lifecycle class {@link foregroundServerCommand} already refuses: a foreground
|
|
14
|
+
* process that never returns. So the same preflight seam reads it, with a deliberately narrow
|
|
15
|
+
* closed-world proof:
|
|
16
|
+
*
|
|
17
|
+
* - the script is DIRECTLY executed (`node`/`tsx`/`bun`/`deno` naming a script file, never a
|
|
18
|
+
* test-runner invocation or a test/fixture file — those are the runner's business);
|
|
19
|
+
* - the source, with comments and string/template/regex literals blanked, binds a browser by a
|
|
20
|
+
* TOP-LEVEL (brace depth 0) `const|let|var <x> = await chromium|firefox|webkit.launch(`
|
|
21
|
+
* assignment, where the engine (or its namespace) is imported/required from `playwright`,
|
|
22
|
+
* `playwright-core` or `@playwright/test` — a locally bound stub is not Playwright;
|
|
23
|
+
* - every reference to `<x>` is a known browser method that does NOT close it (`newPage`,
|
|
24
|
+
* `newContext`, `on`, `version`, …), and the binding is never aliased, passed to a helper, or
|
|
25
|
+
* read as a property;
|
|
26
|
+
* - nothing in the source is a cleanup path (any `.close(`/`.disconnect(`/`.dispose(`, a `using`
|
|
27
|
+
* scope, a cleanup-named import), an escape (`process.exit`, `eval`, `new Function`, dynamic
|
|
28
|
+
* `import`), or a persistent-process intent (`launchServer`, `connect`, a server `.listen`, a
|
|
29
|
+
* timer or signal handler).
|
|
30
|
+
*
|
|
31
|
+
* Anything ambiguous is left alone. A wrong refusal costs a valid probe — the review that found
|
|
32
|
+
* the m257 leak also proved five harmless scripts a raw substring match would refuse (a local
|
|
33
|
+
* engine stub, the launch text in a string, in a comment, in a template literal, and inside a
|
|
34
|
+
* function that is never called) — and a missed leak costs the same budget the tool already had.
|
|
35
|
+
* This is a lifecycle diagnostic, never an egress or security gate.
|
|
36
|
+
*
|
|
37
|
+
* @module
|
|
38
|
+
*/
|
|
39
|
+
/** A browser launch bound to a variable, proven to have no cleanup path. */
|
|
40
|
+
export interface BrowserProbeLeak {
|
|
41
|
+
/** The variable the launched browser is bound to (`browser` in the m257 probe). */
|
|
42
|
+
readonly variable: string;
|
|
43
|
+
}
|
|
44
|
+
/** A foreground command that directly executes such a script. */
|
|
45
|
+
export interface ForegroundBrowserProbe extends BrowserProbeLeak {
|
|
46
|
+
/** The script file as the command named it. */
|
|
47
|
+
readonly script: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The browser variable a standalone script launches and never closes, when that can be proven from
|
|
51
|
+
* the source alone.
|
|
52
|
+
*
|
|
53
|
+
* The proof is a closed world: one plain TOP-LEVEL launch binding whose engine is genuinely
|
|
54
|
+
* Playwright's, every reference to it a known non-closing method call, and no cleanup, escape or
|
|
55
|
+
* persistent-process path anywhere in the source. A source with two launches is read one binding
|
|
56
|
+
* at a time — a proven leak in either one is enough, because that handle alone keeps Node alive.
|
|
57
|
+
*
|
|
58
|
+
* @param source - The script's source, as read from disk.
|
|
59
|
+
* @returns The leaking binding, or null when the script is clean or ambiguous.
|
|
60
|
+
*/
|
|
61
|
+
export declare function standaloneBrowserLeak(source: string): BrowserProbeLeak | null;
|
|
62
|
+
/**
|
|
63
|
+
* The refusal for a foreground command that would run a leaking browser probe: it never returns,
|
|
64
|
+
* and the one move that makes it return is closing the browser (or letting the Playwright runner
|
|
65
|
+
* own it), never moving the leak to the background.
|
|
66
|
+
*
|
|
67
|
+
* @param probe - The leaked probe, from `foregroundBrowserProbe`.
|
|
68
|
+
* @param budgetSeconds - The tool's budget, which the probe would consume whole.
|
|
69
|
+
* @param piped - Whether the command pipes through `tail`/`head`, which withholds the probe's output.
|
|
70
|
+
* @returns The refusal sentence.
|
|
71
|
+
*/
|
|
72
|
+
export declare function browserProbeRefusal(probe: ForegroundBrowserProbe, budgetSeconds: number, piped?: boolean): string;
|
|
73
|
+
/**
|
|
74
|
+
* The over-budget advice for a leak discovered at cut time (the preflight could not read the script
|
|
75
|
+
* before the run — e.g. the same command wrote it). It names the lifecycle fix and says explicitly
|
|
76
|
+
* that the background is not one: a leaked handle hangs there too.
|
|
77
|
+
*
|
|
78
|
+
* @param probe - The leaked probe.
|
|
79
|
+
* @returns The sentence the cut result carries.
|
|
80
|
+
*/
|
|
81
|
+
export declare function browserProbeOverBudgetAdvice(probe: ForegroundBrowserProbe): string;
|
|
82
|
+
//# sourceMappingURL=browser-probe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-probe.d.ts","sourceRoot":"","sources":["../src/browser-probe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,4EAA4E;AAC5E,MAAM,WAAW,gBAAgB;IAC/B,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED,iEAAiE;AACjE,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,+CAA+C;IAC/C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AA6aD;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAyB7E;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,sBAAsB,EAC7B,aAAa,EAAE,MAAM,EACrB,KAAK,UAAQ,GACZ,MAAM,CAaR;AAED;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CASlF"}
|