@molecule/api-ai-tools 1.9.1 → 1.9.2

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-17T07:58:25.504Z
6
+ Generated: 2026-10-17T09:38:26.898Z
7
7
  -->
8
8
 
9
9
  # @molecule/api-ai-tools
@@ -1227,6 +1227,30 @@ function commandRunsNoTests(command: string): boolean
1227
1227
 
1228
1228
  **Returns:** True when the command invokes a runner only to print.
1229
1229
 
1230
+ #### `pipelineExitCodeNote(command, exitCode, output)`
1231
+
1232
+ The sentence an `exec_command` result carries beside `exitCode` when the code belongs to a
1233
+ pipeline's last stage rather than to the check that printed the output.
1234
+
1235
+ Two shapes, both from a hand-run check with an unguarded pipe:
1236
+
1237
+ - the code says 0 and the output carries failures (`tsc | head` reports `head`'s 0);
1238
+ - the code is non-zero and the checker printed no failures (`tsc | head && tail missing.log`
1239
+ reports `tail`'s 1, and the checker was clean).
1240
+
1241
+ A command with no pipe, a pipe guarded by `pipefail`, a pipeline where no checker runs, or a
1242
+ code and an output that agree all return null.
1243
+
1244
+ ```typescript
1245
+ function pipelineExitCodeNote(command: string, exitCode: number, output: string): string | null
1246
+ ```
1247
+
1248
+ - `command` — The command as the executor sent it.
1249
+ - `exitCode` — The code the shell reported (the pipeline's last stage's).
1250
+ - `output` — The command's raw stdout and stderr, for the checker's own text.
1251
+
1252
+ **Returns:** One sentence naming the stage the code came from, or null.
1253
+
1230
1254
  #### `leadingSleepPeek(command)`
1231
1255
 
1232
1256
  The leading `sleep` of a command, when the first statement is one and it asks for at least
package/dist/index.d.ts CHANGED
@@ -137,6 +137,7 @@ export * from './cut-run.js';
137
137
  export * from './failure-kind.js';
138
138
  export * from './input-normalizer.js';
139
139
  export * from './no-test-run.js';
140
+ export * from './pipeline-exit-note.js';
140
141
  export * from './schemas.js';
141
142
  export * from './sleep-peek.js';
142
143
  export * from './suite-overlap.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkIG;AAEH,cAAc,qBAAqB,CAAA;AACnC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,kBAAkB,CAAA;AAChC,cAAc,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,kBAAkB,CAAA;AAChC,cAAc,yBAAyB,CAAA;AACvC,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,YAAY,CAAA;AAC1B,cAAc,sBAAsB,CAAA;AACpC,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA"}
package/dist/index.js CHANGED
@@ -137,6 +137,7 @@ export * from './cut-run.js';
137
137
  export * from './failure-kind.js';
138
138
  export * from './input-normalizer.js';
139
139
  export * from './no-test-run.js';
140
+ export * from './pipeline-exit-note.js';
140
141
  export * from './schemas.js';
141
142
  export * from './sleep-peek.js';
142
143
  export * from './suite-overlap.js';
@@ -0,0 +1,37 @@
1
+ /**
2
+ * The exit code a hand-run check's result carries is the pipeline's LAST stage's, and a weak
3
+ * executor reads the number as the check's verdict.
4
+ *
5
+ * `npx tsc --noEmit 2>&1 | head -40` reports `head`'s 0 while the output above it carries a type
6
+ * error, and `… | head -40 && tail -30 missing.log` reports `tail`'s 1 while the checker was clean —
7
+ * both measured in xr-molecule-flash-m117 (+04:06, +08:05). A model that trusts the code concludes
8
+ * "clean" and ships a build that does not compile, or hunts an error that is not there. This module
9
+ * says which stage produced the code, and what the output actually carries, in one sentence beside
10
+ * `exitCode`.
11
+ *
12
+ * The parse is the package's own shell reader ({@link locatedCommandSegments}), so a `|` inside
13
+ * quotes or a heredoc is not a stage, and `set -o pipefail` (where it really runs) turns the note
14
+ * off: then the code IS the check's.
15
+ *
16
+ * @module
17
+ */
18
+ /**
19
+ * The sentence an `exec_command` result carries beside `exitCode` when the code belongs to a
20
+ * pipeline's last stage rather than to the check that printed the output.
21
+ *
22
+ * Two shapes, both from a hand-run check with an unguarded pipe:
23
+ *
24
+ * - the code says 0 and the output carries failures (`tsc | head` reports `head`'s 0);
25
+ * - the code is non-zero and the checker printed no failures (`tsc | head && tail missing.log`
26
+ * reports `tail`'s 1, and the checker was clean).
27
+ *
28
+ * A command with no pipe, a pipe guarded by `pipefail`, a pipeline where no checker runs, or a
29
+ * code and an output that agree all return null.
30
+ *
31
+ * @param command - The command as the executor sent it.
32
+ * @param exitCode - The code the shell reported (the pipeline's last stage's).
33
+ * @param output - The command's raw stdout and stderr, for the checker's own text.
34
+ * @returns One sentence naming the stage the code came from, or null.
35
+ */
36
+ export declare function pipelineExitCodeNote(command: string, exitCode: number, output: string): string | null;
37
+ //# sourceMappingURL=pipeline-exit-note.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-exit-note.d.ts","sourceRoot":"","sources":["../src/pipeline-exit-note.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA2GH;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,MAAM,GAAG,IAAI,CAsCf"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * The exit code a hand-run check's result carries is the pipeline's LAST stage's, and a weak
3
+ * executor reads the number as the check's verdict.
4
+ *
5
+ * `npx tsc --noEmit 2>&1 | head -40` reports `head`'s 0 while the output above it carries a type
6
+ * error, and `… | head -40 && tail -30 missing.log` reports `tail`'s 1 while the checker was clean —
7
+ * both measured in xr-molecule-flash-m117 (+04:06, +08:05). A model that trusts the code concludes
8
+ * "clean" and ships a build that does not compile, or hunts an error that is not there. This module
9
+ * says which stage produced the code, and what the output actually carries, in one sentence beside
10
+ * `exitCode`.
11
+ *
12
+ * The parse is the package's own shell reader ({@link locatedCommandSegments}), so a `|` inside
13
+ * quotes or a heredoc is not a stage, and `set -o pipefail` (where it really runs) turns the note
14
+ * off: then the code IS the check's.
15
+ *
16
+ * @module
17
+ */
18
+ import { locatedCommandSegments } from './command-position.js';
19
+ /** The shells whose `-o pipefail` makes a pipeline report its first failing stage. */
20
+ const PIPEFAIL_SHELLS = new Set(['ash', 'bash', 'dash', 'ksh', 'sh', 'zsh']);
21
+ /**
22
+ * The programs a pipeline may end with when all they do is read what was printed and print it
23
+ * again — the stages that hand back their own status in place of the check's.
24
+ */
25
+ const OUTPUT_ONLY_FILTERS = new Set([
26
+ 'awk',
27
+ 'cat',
28
+ 'column',
29
+ 'cut',
30
+ 'egrep',
31
+ 'fgrep',
32
+ 'fmt',
33
+ 'fold',
34
+ 'grep',
35
+ 'head',
36
+ 'jq',
37
+ 'nl',
38
+ 'rg',
39
+ 'sed',
40
+ 'sort',
41
+ 'tail',
42
+ 'tr',
43
+ 'uniq',
44
+ 'wc',
45
+ ]);
46
+ /** `1 type error` / `2 type errors`. */
47
+ const plural = (count, one, many) => `${count} ${count === 1 ? one : many}`;
48
+ /**
49
+ * The failure count a runner's tally names. Vitest prints two tallies — `Test Files 1 failed`
50
+ * above `Tests 2 failed` — and the last one is the tests, which is the number the note means.
51
+ *
52
+ * @param output - The runner's output.
53
+ * @returns The count in the last `N failed` tally, or 0.
54
+ */
55
+ const failedTally = (output) => {
56
+ const tallies = [...output.matchAll(/\b(\d+) failed\b/g)];
57
+ return Number(tallies.at(-1)?.[1] ?? 0);
58
+ };
59
+ /** The checkers whose output says pass or fail in text of its own. */
60
+ const CHECKERS = [
61
+ {
62
+ name: 'tsc',
63
+ runs: (program) => program === 'tsc' || program === 'vue-tsc',
64
+ failures: (output) => {
65
+ const errors = output.match(/\berror TS\d+/g)?.length ?? 0;
66
+ if (errors > 0)
67
+ return errors;
68
+ const found = /\bFound (\d+) errors?/.exec(output);
69
+ return found ? Number(found[1]) : 0;
70
+ },
71
+ label: (count) => plural(count, 'type error', 'type errors'),
72
+ },
73
+ {
74
+ name: 'eslint',
75
+ runs: (program) => program === 'eslint',
76
+ failures: (output) => {
77
+ const problems = /✖\s*(\d+)\s+problems?/.exec(output);
78
+ return problems ? Number(problems[1]) : 0;
79
+ },
80
+ label: (count) => plural(count, 'lint problem', 'lint problems'),
81
+ },
82
+ {
83
+ name: 'vitest',
84
+ runs: (program) => program === 'vitest',
85
+ failures: failedTally,
86
+ label: (count) => plural(count, 'failing test', 'failing tests'),
87
+ },
88
+ {
89
+ name: 'playwright',
90
+ runs: (_program, text) => /^playwright\s+test\b/.test(text),
91
+ failures: failedTally,
92
+ label: (count) => plural(count, 'failing test', 'failing tests'),
93
+ },
94
+ ];
95
+ /** Whether the command turns on `pipefail`, so a pipeline reports the check's own status. */
96
+ function guardedByPipefail(segments) {
97
+ return segments.some(({ program, args }) => (program === 'set' || PIPEFAIL_SHELLS.has(program)) && args.includes('pipefail'));
98
+ }
99
+ /**
100
+ * The sentence an `exec_command` result carries beside `exitCode` when the code belongs to a
101
+ * pipeline's last stage rather than to the check that printed the output.
102
+ *
103
+ * Two shapes, both from a hand-run check with an unguarded pipe:
104
+ *
105
+ * - the code says 0 and the output carries failures (`tsc | head` reports `head`'s 0);
106
+ * - the code is non-zero and the checker printed no failures (`tsc | head && tail missing.log`
107
+ * reports `tail`'s 1, and the checker was clean).
108
+ *
109
+ * A command with no pipe, a pipe guarded by `pipefail`, a pipeline where no checker runs, or a
110
+ * code and an output that agree all return null.
111
+ *
112
+ * @param command - The command as the executor sent it.
113
+ * @param exitCode - The code the shell reported (the pipeline's last stage's).
114
+ * @param output - The command's raw stdout and stderr, for the checker's own text.
115
+ * @returns One sentence naming the stage the code came from, or null.
116
+ */
117
+ export function pipelineExitCodeNote(command, exitCode, output) {
118
+ const running = locatedCommandSegments(command).filter((entry) => entry.segment !== null);
119
+ if (running.length < 2)
120
+ return null;
121
+ if (!running.some((entry) => entry.separator.trim() === '|'))
122
+ return null;
123
+ const segments = running.map((entry) => entry.segment);
124
+ if (guardedByPipefail(segments))
125
+ return null;
126
+ let checkerAt = -1;
127
+ for (let i = segments.length - 1; i >= 0; i -= 1) {
128
+ const segment = segments[i];
129
+ if (CHECKERS.some((checker) => checker.runs(segment.program, segment.text))) {
130
+ checkerAt = i;
131
+ break;
132
+ }
133
+ }
134
+ if (checkerAt < 0)
135
+ return null;
136
+ // The check's own status is lost only when a stage of the SAME pipeline follows it; a `&&` after
137
+ // the check already reports a real failure of its own, and a check followed by nothing reports
138
+ // its own code.
139
+ if (running[checkerAt + 1]?.separator.trim() !== '|')
140
+ return null;
141
+ const checkerSegment = segments[checkerAt];
142
+ const checker = CHECKERS.find((candidate) => candidate.runs(checkerSegment.program, checkerSegment.text));
143
+ const last = segments[segments.length - 1];
144
+ const failures = checker.failures(output);
145
+ if (exitCode === 0 && failures > 0) {
146
+ return (`the exit code 0 is the last stage's (${last.program}), not ${checker.name}'s — ` +
147
+ `the output carries ${checker.label(failures)}`);
148
+ }
149
+ if (exitCode !== 0 && failures === 0 && OUTPUT_ONLY_FILTERS.has(last.program)) {
150
+ return (`the exit code ${exitCode} is the last stage's (${last.program}), not ${checker.name}'s — ` +
151
+ 'the checker printed no errors');
152
+ }
153
+ return null;
154
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAgJ9C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAahG;AAiOD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAmEnE;;;GAGG;AACH,eAAO,MAAM,iBAAiB,QAEA,CAAA;AAE9B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,QAI6C,CAAA;AAmBlF;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUhE;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;AAoBpF;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC,GACxE,qBAAqB,CAkBvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,qBAAqB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiCxB;AAgDD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CAu2ExF"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAiJ9C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAahG;AAiOD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAmEnE;;;GAGG;AACH,eAAO,MAAM,iBAAiB,QAEA,CAAA;AAE9B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,QAI6C,CAAA;AAmBlF;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUhE;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;AAoBpF;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC,GACxE,qBAAqB,CAkBvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,qBAAqB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiCxB;AAgDD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CAy3ExF"}
package/dist/tools.js CHANGED
@@ -9,6 +9,7 @@
9
9
  import { commandCutRun, CUT_AT_BUDGET, cutRunSentence, suiteRunExitCode } from './cut-run.js';
10
10
  import { addChangeSpan, changedSpan, countLines, renderEditExcerpt, renderSmallFile, } from './edit-excerpt.js';
11
11
  import { guardToolExecute, missingParamError, ToolInputError } from './input-normalizer.js';
12
+ import { pipelineExitCodeNote } from './pipeline-exit-note.js';
12
13
  import { TOOL_SCHEMAS } from './schemas.js';
13
14
  import { leadingSleepPeek } from './sleep-peek.js';
14
15
  /**
@@ -2172,6 +2173,12 @@ export function buildTools(backend, config) {
2172
2173
  const placement = suiteRunPipelinePlacement(streaming.command);
2173
2174
  const reported = suiteRunExitCode(code, output, placement.piped);
2174
2175
  const exitNote = suiteExitCodeNote(placement, reported);
2176
+ // The same question the foreground path asks: when the code is a filter's, say
2177
+ // which stage produced it (and what the output carries) rather than leaving a
2178
+ // 0 beside a printed error.
2179
+ const pipeNote = reported === null
2180
+ ? null
2181
+ : pipelineExitCodeNote(streaming.command, reported, output);
2175
2182
  const notes = [
2176
2183
  ...(sleepNote ? [sleepNote] : []),
2177
2184
  ...streaming.changes,
@@ -2181,6 +2188,7 @@ export function buildTools(backend, config) {
2181
2188
  stdout,
2182
2189
  stderr: '',
2183
2190
  exitCode: reported,
2191
+ ...(pipeNote === null ? {} : { exitCodeNote: pipeNote }),
2184
2192
  ...(output.length > MAX_OUTPUT_SIZE ? { truncated: true, fullOutput: log } : {}),
2185
2193
  ...(notes.length ? { note: notes.join(' ') } : {}),
2186
2194
  };
@@ -2305,10 +2313,16 @@ export function buildTools(backend, config) {
2305
2313
  (isSuiteRunCommand(command) ? SUITE_OVER_BUDGET_ADVICE : SPLIT_WORK_ADVICE),
2306
2314
  };
2307
2315
  }
2316
+ // A pipeline reports its LAST stage's code: `tsc | head` says 0 beside a printed type
2317
+ // error, and `tsc | head && tail missing.log` says 1 beside a clean check. Name the
2318
+ // stage the number came from (pipeline-exit-note.ts) — the field the executor trusts
2319
+ // most must not contradict the text it can read.
2320
+ const exitCodeNote = pipelineExitCodeNote(command, result.exitCode, `${result.stdout}\n${result.stderr}`);
2308
2321
  return {
2309
2322
  stdout,
2310
2323
  stderr,
2311
2324
  exitCode: result.exitCode,
2325
+ ...(exitCodeNote === null ? {} : { exitCodeNote }),
2312
2326
  ...(peekedTask?.slice.trim() ? { outputSoFar: sanitizeOutput(peekedTask.slice) } : {}),
2313
2327
  ...(sleepNote || ceilingNote || traced.change
2314
2328
  ? {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/api-ai-tools",
3
- "version": "1.9.1",
3
+ "version": "1.9.2",
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",