@molecule/api-ai-tools 1.8.1 → 1.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
3
3
  Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
4
4
  Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
5
5
  To change this document, edit the module-level JSDoc in src/index.ts.
6
- Generated: 2026-10-17T02:50:55.123Z
6
+ Generated: 2026-10-17T05:02:46.912Z
7
7
  -->
8
8
 
9
9
  # @molecule/api-ai-tools
@@ -115,6 +115,24 @@ interface LocatedCommandSegment {
115
115
  * inside a nested `sh -c` string, for the same reason as {@link start}.
116
116
  */
117
117
  assignmentOffset: number | null
118
+ /**
119
+ * The offset in the command one past the statement's last word — where an option of this
120
+ * statement's program belongs, before whatever closes it. Null inside a nested `sh -c` string.
121
+ */
122
+ end: number | null
123
+ /**
124
+ * The offset in the command of the word in command position — the program, once every wrapper
125
+ * in front of it is taken away (`npx --prefix /app <here>playwright test`). Null inside a
126
+ * nested `sh -c` string, and for a statement that only sets variables.
127
+ */
128
+ programOffset: number | null
129
+ /**
130
+ * The separator the shell split at immediately before this statement — `|`, `||`, `&&`, `;`,
131
+ * a newline or `&` — or '' when it is the first statement of the command. It is the parse's own
132
+ * answer, so it is known even where the offsets are not, and a caller deciding whether two
133
+ * statements are one pipeline (`|`, never `;`) asks it instead of reading the text between them.
134
+ */
135
+ separator: string
118
136
  }
119
137
  ```
120
138
 
@@ -235,6 +253,19 @@ interface ToolSchema {
235
253
  }
236
254
  ```
237
255
 
256
+ #### `LeadingSleep`
257
+
258
+ The leading `sleep` a command opens with, and the command that follows it.
259
+
260
+ ```typescript
261
+ interface LeadingSleep {
262
+ /** How many seconds the statement would have slept (GNU sleep sums its operands). */
263
+ seconds: number
264
+ /** What follows the leading statement, trimmed — '' when the sleep was the whole command. */
265
+ rest: string
266
+ }
267
+ ```
268
+
238
269
  #### `SuiteRunInFlight`
239
270
 
240
271
  One suite run, as the rule that decides whether a second may start beside it reads it.
@@ -258,6 +289,20 @@ interface SuiteRunInFlight {
258
289
  }
259
290
  ```
260
291
 
292
+ #### `InstalledPackageFacts`
293
+
294
+ What the filesystem says about a write target under `node_modules` — the half
295
+ of the decision a path's spelling cannot make.
296
+
297
+ ```typescript
298
+ interface InstalledPackageFacts {
299
+ /** Whether the `node_modules` entry the path goes through is a symbolic link. */
300
+ readonly symlink: boolean
301
+ /** Whether a package is really installed there: a `package.json` resolves under the entry. */
302
+ readonly installed: boolean
303
+ }
304
+ ```
305
+
261
306
  #### `TraceRequest`
262
307
 
263
308
  One request a traced page made, as `*.network` records it.
@@ -553,6 +598,27 @@ interface SuiteFilterStrip {
553
598
  }
554
599
  ```
555
600
 
601
+ #### `SuiteRunPipelinePlacement`
602
+
603
+ Whether a finished run's exit code belongs to a stage after the suite runner.
604
+
605
+ ```typescript
606
+ interface SuiteRunPipelinePlacement {
607
+ /**
608
+ * True when a pipe this tool must not drop still follows the suite runner: the code in the
609
+ * result is that stage's, not the run's.
610
+ */
611
+ piped: boolean
612
+ /**
613
+ * True when the suite (or a stage of its pipeline) sits inside a nested `sh -c '<command>'`
614
+ * string, so the parse cannot place it in the command's own text. The caller then says so
615
+ * plainly instead of implying a stage it can point at — and keeps the command's own code when
616
+ * no pipe follows the runner, because on that command the pipeline's last stage IS the run.
617
+ */
618
+ unplaced: boolean
619
+ }
620
+ ```
621
+
556
622
  #### `FailedTest`
557
623
 
558
624
  One failed test, as a running suite's log names it.
@@ -658,6 +724,19 @@ Re-export SkillEntry as DiscoveredSkill for backwards compatibility.
658
724
  type DiscoveredSkill = SkillEntry
659
725
  ```
660
726
 
727
+ #### `InstalledPackageProbe`
728
+
729
+ Looks at the filesystem for {@link InstalledPackageFacts}.
730
+
731
+ The guard cannot `stat` the path itself: the tools act through a backend (a
732
+ sandbox over the network for the fleet), so the caller — which holds that
733
+ backend — supplies the look. {@link shellInstalledPackageProbe} builds one
734
+ from any shell runner.
735
+
736
+ ```typescript
737
+ type InstalledPackageProbe = (path: string) => Promise<InstalledPackageFacts>
738
+ ```
739
+
661
740
  ### Classes
662
741
 
663
742
  #### `ToolInputError`
@@ -1029,6 +1108,26 @@ function commandRunsNoTests(command: string): boolean
1029
1108
 
1030
1109
  **Returns:** True when the command invokes a runner only to print.
1031
1110
 
1111
+ #### `leadingSleepPeek(command)`
1112
+
1113
+ The leading `sleep` of a command, when the first statement is one and it asks for at least
1114
+ {@link MIN_PEEK_SLEEP_SECONDS}.
1115
+
1116
+ The statement is read by {@link locatedCommandSegments} — the same parse every other command
1117
+ classifier uses — so only a `sleep` in command position of the FIRST statement counts. The end
1118
+ of that statement is then found by walking forward from its own start: the statement is
1119
+ `sleep <duration>`, whose words carry no quotes and open no substitution, so the first unquoted
1120
+ `;`, newline or `&` ends it. A `|` is refused: dropping the left side of a pipeline would hand
1121
+ the right side its stdin instead, and a `||` fallback would run on a success that never did.
1122
+
1123
+ ```typescript
1124
+ function leadingSleepPeek(command: string): LeadingSleep | null
1125
+ ```
1126
+
1127
+ - `command` — The shell command the executor sent.
1128
+
1129
+ **Returns:** The seconds and the remaining command, or null when the command does not open with a long `sleep`.
1130
+
1032
1131
  #### `withoutHeredocs(command)`
1033
1132
 
1034
1133
  A command with its heredoc bodies removed: the runs, kills and hosts it names in a file it
@@ -1213,10 +1312,26 @@ function moleculeDistReadNote(path: string): string | null
1213
1312
 
1214
1313
  **Returns:** The note, or null when the path is not inside a package's `dist`.
1215
1314
 
1216
- #### `installedPackageWriteRefusal(path)`
1315
+ #### `shellInstalledPackageProbe(run)`
1217
1316
 
1218
- The refusal for a write whose target is inside an installed package, or null
1219
- when the path is not under a `node_modules` directory.
1317
+ Build an {@link InstalledPackageProbe} from a shell runner (a backend's
1318
+ `run`, or a sandbox's `exec`): one command reports whether the entry is a
1319
+ link and whether a `package.json` resolves under it.
1320
+
1321
+ ```typescript
1322
+ function shellInstalledPackageProbe(
1323
+ run: (command: string) => Promise<{ stdout?: string } | null | undefined>,
1324
+ ): InstalledPackageProbe
1325
+ ```
1326
+
1327
+ - `run` — Runs a command where the path lives.
1328
+
1329
+ **Returns:** The probe.
1330
+
1331
+ #### `installedPackageWriteRefusal(path, probe)`
1332
+
1333
+ The refusal for a write whose target is inside an INSTALLED package, or null
1334
+ when the path is not under `node_modules` or nothing is installed there.
1220
1335
 
1221
1336
  `node_modules` is not the project's code: nothing written there survives the
1222
1337
  next install, no deploy carries it, and a sandbox whose dependency tree is
@@ -1229,17 +1344,29 @@ answered `ok: true`, and 18 s went to noticing, `npm pack`-ing the package and
1229
1344
  putting the file back. Reading these files stays allowed (that is how the
1230
1345
  declarations above are read at all).
1231
1346
 
1232
- The restore route is named because the model that has ALREADY clobbered a file
1233
- (this refusal is too late for it) is the one who needs it, and because the
1234
- obvious repair — `npm install <pkg>` — is itself refused in the pre-installed
1235
- sandbox. `npm pack` + a `tar` extraction over the package directory is what
1236
- m91 used, and what both guards leave alone.
1347
+ What is protected is the INSTALL, not the spelling: the decision comes from
1348
+ {@link InstalledPackageFacts}, never from the path alone (m106 above). Three
1349
+ things are the run's own to remove or replace —
1350
+
1351
+ - a `node_modules` that is a SYMLINK: `rm`/`unlink` removes the link, never the
1352
+ tree it points at, so a link the run made cannot clobber anything;
1353
+ - anything under the run's own `.mol-scratch/` directory;
1354
+ - a `node_modules` with no `package.json` under it (nothing was ever installed).
1355
+
1356
+ A path INSIDE the link is still decided by what resolves there: a link into a
1357
+ real tree is refused, because removing or writing through it reaches the
1358
+
1359
+ _(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/tools.d.ts`.)_
1237
1360
 
1238
1361
  ```typescript
1239
- function installedPackageWriteRefusal(path: string): string | null
1362
+ function installedPackageWriteRefusal(
1363
+ path: string,
1364
+ probe?: InstalledPackageProbe,
1365
+ ): Promise<string | null>
1240
1366
  ```
1241
1367
 
1242
1368
  - `path` — An absolute path a tool is about to write.
1369
+ - `probe` — Looks at the filesystem where the path lives.
1243
1370
 
1244
1371
  **Returns:** The one-line refusal naming the package, or null when nothing is installed there.
1245
1372
 
@@ -1602,23 +1729,40 @@ function stripTrailingSuiteFilters(command: string): SuiteFilterStrip
1602
1729
 
1603
1730
  **Returns:** The rewritten command and the stages dropped.
1604
1731
 
1732
+ #### `suiteRunPipelinePlacement(command)`
1733
+
1734
+ Where the suite runner's exit code comes from: the runner itself, or a stage piped after it.
1735
+
1736
+ {@link suiteRunPipedAfterRunner}'s one question, with the honest third answer kept apart. The
1737
+ code a finished run reports is its LAST pipeline stage's, so a stage after the runner makes the
1738
+ code the stage's — but only when such a stage EXISTS. The platform used to report "piped" for
1739
+ any run whose statements it could not place in the text, which one heredoc body was enough to
1740
+ cause: on X1 xr-molecule-flash-m105 (+08:12) a config written in the same `exec_command` made
1741
+ the run come back with no exit code at all, and the note under it claimed a stage after the
1742
+ runner that was not there. The parse now places every statement (`locatedCommandSegments`), so
1743
+ "unplaced" is the rare, named case rather than a guess dressed as an answer.
1744
+
1745
+ ```typescript
1746
+ function suiteRunPipelinePlacement(command: string): SuiteRunPipelinePlacement
1747
+ ```
1748
+
1749
+ - `command` — The shell command, after the streaming rewrite when one was applied.
1750
+
1751
+ **Returns:** Whether a stage follows the runner, and whether the run could be placed at all.
1752
+
1605
1753
  #### `suiteRunPipedAfterRunner(command)`
1606
1754
 
1607
1755
  Whether the command's last step runs a suite whose output still passes through a stage after
1608
1756
  the runner — one {@link stripTrailingSuiteFilters} could not prove is output-only (`| tee log`,
1609
1757
  `| xargs …`). The pipeline's exit status is that stage's, not the run's.
1610
1758
 
1611
- A command whose stages cannot be placed in the text (irregular whitespace inside the run) is
1612
- reported as piped too: whether a pipe follows the runner is then UNKNOWN, and an unknown exit
1613
- code that gets trusted is a failing run read as a pass — the failure this rule exists to stop.
1614
-
1615
1759
  ```typescript
1616
1760
  function suiteRunPipedAfterRunner(command: string): boolean
1617
1761
  ```
1618
1762
 
1619
1763
  - `command` — The shell command, after the streaming rewrite when one was applied.
1620
1764
 
1621
- **Returns:** True when a pipe this tool must not drop still follows the suite runner, or when the command runs a suite the parse cannot place.
1765
+ **Returns:** True when a pipe this tool must not drop still follows the suite runner.
1622
1766
 
1623
1767
  #### `suiteRunPriorityLaunch(command, launch)`
1624
1768
 
@@ -2231,9 +2375,12 @@ executor reads, so one round of fixes covers all of them rather than the one cau
2231
2375
  stopped early happened to reach.
2232
2376
 
2233
2377
  A test the request excludes is not one of the causes — it is dropped and named once, at the
2234
- end, so a result never asks to fix a test it also says to ignore. Where the caller knows how
2235
- the run was started, the note also hands over the narrowed re-run of exactly those tests
2236
- ({@link rerunOfRunningSuite}) instead of leaving the executor to re-run the whole suite.
2378
+ end, so a result never asks to fix a test it also says to ignore. A test the runner itself
2379
+ declared `flaky` (it failed once and passed on its config retry) is not a cause either: it is
2380
+ named apart from them, once, as what the tally called it ({@link flakyTestsDeclared}). Where
2381
+ the caller knows how the run was started, the note also hands over the narrowed re-run of
2382
+ exactly those tests ({@link rerunOfRunningSuite}) instead of leaving the executor to re-run the
2383
+ whole suite.
2237
2384
 
2238
2385
  ```typescript
2239
2386
  function failureCausesNote(
@@ -2414,6 +2561,15 @@ Canonical tool schemas shared by the agent runtime and documentation.
2414
2561
  const TOOL_SCHEMAS: Record<string, ToolSchema>
2415
2562
  ```
2416
2563
 
2564
+ #### `MIN_PEEK_SLEEP_SECONDS`
2565
+
2566
+ The shortest leading sleep the platform drops: below it the wall clock it costs is noise, and a
2567
+ short settle (`sleep 2; curl …`) is a legitimate thing to run.
2568
+
2569
+ ```typescript
2570
+ const MIN_PEEK_SLEEP_SECONDS: 5
2571
+ ```
2572
+
2417
2573
  #### `SPLIT_WORK_ADVICE`
2418
2574
 
2419
2575
  The closing advice on an over-budget message for a command that is not a test
@@ -21,8 +21,14 @@
21
21
  * Not command position, and therefore not an invocation: a runner named as an argument
22
22
  * (`head -30 run-api-tests-hurl.sh`, `grep -n playwright e2e/README.md`,
23
23
  * `git show HEAD:run-api-tests.sh`), and a runner named in a heredoc body — a file a command
24
- * WRITES is the caller's business, so a command with a heredoc goes through the caller's own
25
- * stripper first (`withoutHeredocs`, in `./suite-overlap.js`).
24
+ * WRITES is not a command it runs, so the bodies are blanked to spaces before anything is split
25
+ * ({@link blankHeredocBodies}); offsets stay exact, because the blanking preserves every position.
26
+ *
27
+ * The parser also answers WHERE each statement sits ({@link locatedCommandSegments}): `start`,
28
+ * `end`, `programOffset` and `assignmentOffset` are the offsets a caller splices at. They are
29
+ * token positions from this walk, never a search for re-joined text — the words are joined back
30
+ * with single spaces for matching, so `command.indexOf(segment.text)` fails on irregular spacing,
31
+ * on grouping braces, and on anything a heredoc body shifts (xr-molecule-flash-m105 +08:12).
26
32
  *
27
33
  * @module
28
34
  */
@@ -58,6 +64,66 @@ export declare function durationSeconds(word: string): number | null;
58
64
  * @returns One entry per statement or pipeline stage that runs something, in order.
59
65
  */
60
66
  export declare function commandSegments(command: string): CommandSegment[];
67
+ /**
68
+ * One statement of a shell command, with where it sits and the variables it sets for itself.
69
+ *
70
+ * `commandSegments` answers WHAT runs; this answers where, and what the shell binds to it — the
71
+ * two things a caller that WRITES into a command needs. The platform composes a run from the
72
+ * executor's own command in more than one place, and a value written for the runner belongs in
73
+ * the runner's own statement: `APP_BASE=https://… cd app && npx playwright test` sets the variable
74
+ * for `cd` alone, so the Playwright config falls back to the local app while the command line
75
+ * still names the deployed host (xr-molecule-flash-m103 +28:08).
76
+ */
77
+ export interface LocatedCommandSegment {
78
+ /**
79
+ * What the statement runs, or null when it only sets variables (`BASE=http://…` on its own):
80
+ * that shape persists in the shell, so a caller following assignments across `;`/`&&` has to
81
+ * see it.
82
+ */
83
+ segment: CommandSegment | null;
84
+ /** The statement's own leading `NAME=value` words, as written (`TEST_MODE=fullstack`). */
85
+ assignments: readonly string[];
86
+ /**
87
+ * The offset in the command of the statement's first word, or null for a segment inside a
88
+ * nested `sh -c '<command>'` string — its positions are offsets in THAT string, not in this
89
+ * command, so nothing may be spliced at them.
90
+ */
91
+ start: number | null;
92
+ /**
93
+ * The offset in the command just before the word the statement runs — after its own leading
94
+ * `NAME=value` words and their whitespace. A `NAME=value` written here is in the environment of
95
+ * the program the statement runs (`… TEST_MODE=fullstack <here>npx playwright test`). Null
96
+ * inside a nested `sh -c` string, for the same reason as {@link start}.
97
+ */
98
+ assignmentOffset: number | null;
99
+ /**
100
+ * The offset in the command one past the statement's last word — where an option of this
101
+ * statement's program belongs, before whatever closes it. Null inside a nested `sh -c` string.
102
+ */
103
+ end: number | null;
104
+ /**
105
+ * The offset in the command of the word in command position — the program, once every wrapper
106
+ * in front of it is taken away (`npx --prefix /app <here>playwright test`). Null inside a
107
+ * nested `sh -c` string, and for a statement that only sets variables.
108
+ */
109
+ programOffset: number | null;
110
+ /**
111
+ * The separator the shell split at immediately before this statement — `|`, `||`, `&&`, `;`,
112
+ * a newline or `&` — or '' when it is the first statement of the command. It is the parse's own
113
+ * answer, so it is known even where the offsets are not, and a caller deciding whether two
114
+ * statements are one pipeline (`|`, never `;`) asks it instead of reading the text between them.
115
+ */
116
+ separator: string;
117
+ }
118
+ /**
119
+ * Every statement of a command, with its own assignments and where it sits — assignment-only
120
+ * statements included, because the variables those persist are exactly what a later statement of
121
+ * the same command reads.
122
+ *
123
+ * @param command - The shell command.
124
+ * @returns One entry per statement or pipeline stage, in order.
125
+ */
126
+ export declare function locatedCommandSegments(command: string): LocatedCommandSegment[];
61
127
  /**
62
128
  * The bound a command puts on its own run: the largest `timeout <N>` any of its segments runs
63
129
  * under (`timeout 280 hurl --test …` → 280), or null when it carries none.
@@ -1 +1 @@
1
- {"version":3,"file":"command-position.d.ts","sourceRoot":"","sources":["../src/command-position.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,uFAAuF;AACvF,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,qFAAqF;IACrF,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,4FAA4F;IAC5F,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AA2MD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM3D;AAuSD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAEjE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOpE;AAoCD;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAK/E"}
1
+ {"version":3,"file":"command-position.d.ts","sourceRoot":"","sources":["../src/command-position.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,uFAAuF;AACvF,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,qFAAqF;IACrF,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,4FAA4F;IAC5F,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AA2MD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM3D;AA+cD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAIjE;AAmCD;;;;;;;;;GASG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,OAAO,EAAE,cAAc,GAAG,IAAI,CAAA;IAC9B,0FAA0F;IAC1F,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9B;;;;OAIG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B;;;OAGG;IACH,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB;;;;OAIG;IACH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAE/E;AA4ED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOpE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAK/E"}