@molecule/api-ai-tools 1.5.3 → 1.5.5
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 +23 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +7 -3
- package/dist/utilities.d.ts +20 -0
- package/dist/utilities.d.ts.map +1 -1
- package/dist/utilities.js +43 -1
- 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-15T20:27:42.092Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/api-ai-tools
|
|
@@ -750,6 +750,28 @@ function sliceLines(
|
|
|
750
750
|
|
|
751
751
|
**Returns:** The window plus its position, or null when neither was given.
|
|
752
752
|
|
|
753
|
+
#### `streamingBackgroundCommand(command)`
|
|
754
|
+
|
|
755
|
+
Rewrite a command about to run in the background so its log grows while it
|
|
756
|
+
runs. Two shapes left the log empty until exit, and an empty log is what
|
|
757
|
+
`wait_for_task` reads as "stuck", so working suites were reported stuck and
|
|
758
|
+
killed (X1 run flash-m15 lost 20 of its 60 minutes this way, 2026-10-15):
|
|
759
|
+
|
|
760
|
+
- a trailing `| tail -N`, which holds everything back until the command ends.
|
|
761
|
+
It is dropped: `wait_for_task` already returns the end of the log.
|
|
762
|
+
- `playwright test` with no `--reporter`, which runs the config's reporter —
|
|
763
|
+
often `html`, which prints nothing per test. `--reporter=line` is added
|
|
764
|
+
when the playwright run is the command's last step and nothing is piped or
|
|
765
|
+
redirected from it ( aside); the results are the same, printed as they happen.
|
|
766
|
+
|
|
767
|
+
```typescript
|
|
768
|
+
function streamingBackgroundCommand(command: string): { command: string; changes: string[] }
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
- `command` — The command as the executor sent it.
|
|
772
|
+
|
|
773
|
+
**Returns:** The command to run and one sentence per change made (empty when none).
|
|
774
|
+
|
|
753
775
|
#### `stripControlChars(s)`
|
|
754
776
|
|
|
755
777
|
Strip C0 control chars (except tab, newline, CR) that break PostgreSQL JSONB
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -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;AA2B9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;
|
|
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;AA2B9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAiCnE;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CA06CxF"}
|
package/dist/tools.js
CHANGED
|
@@ -23,7 +23,7 @@ const waitedByTask = new Map();
|
|
|
23
23
|
* m21, 2026-10-15).
|
|
24
24
|
*/
|
|
25
25
|
const logBytesByTask = new Map();
|
|
26
|
-
import { checkBlockedCommand, declaredBudgetSeconds, DEFAULT_SEARCH_EXCLUDED_DIRS, directoryReadHint, isEnvFilePath, isOutsideRoot, isValidGlob, MAX_BATCH_READ_BYTES, MAX_BATCH_READ_FILES, MAX_FIND_RESULTS, MAX_OUTPUT_SIZE, MAX_READ_RETURN_CHARS, MAX_READ_SIZE, MAX_SEARCH_CONTEXT_LINES, MAX_SEARCH_RESULTS, MAX_WRITE_SIZE, outputIsWithheldUntilExit, parseCheckCommand, parseCheckProblem, pathArgError, redactSecrets, redactSecretsInCode, resolvePath, shellQuote, sliceLines, stripControlChars, truncateMiddle, whitespaceTolerantReplace, } from './utilities.js';
|
|
26
|
+
import { checkBlockedCommand, declaredBudgetSeconds, DEFAULT_SEARCH_EXCLUDED_DIRS, directoryReadHint, isEnvFilePath, isOutsideRoot, isValidGlob, MAX_BATCH_READ_BYTES, MAX_BATCH_READ_FILES, MAX_FIND_RESULTS, MAX_OUTPUT_SIZE, MAX_READ_RETURN_CHARS, MAX_READ_SIZE, MAX_SEARCH_CONTEXT_LINES, MAX_SEARCH_RESULTS, MAX_WRITE_SIZE, outputIsWithheldUntilExit, parseCheckCommand, parseCheckProblem, pathArgError, redactSecrets, redactSecretsInCode, resolvePath, shellQuote, sliceLines, streamingBackgroundCommand, stripControlChars, truncateMiddle, whitespaceTolerantReplace, } from './utilities.js';
|
|
27
27
|
/**
|
|
28
28
|
* Build a complete set of AI agent tools bound to an execution backend.
|
|
29
29
|
*
|
|
@@ -1021,7 +1021,10 @@ export function buildTools(backend, config) {
|
|
|
1021
1021
|
// an executor's commands routinely carry quotes, heredocs and
|
|
1022
1022
|
// newlines, and re-quoting them into a detached `sh -c` is how a
|
|
1023
1023
|
// background runner corrupts the very thing it is running.
|
|
1024
|
-
|
|
1024
|
+
// Keep the log growing while it runs (see streamingBackgroundCommand):
|
|
1025
|
+
// an empty log is what wait_for_task reads as stuck.
|
|
1026
|
+
const streaming = streamingBackgroundCommand(command);
|
|
1027
|
+
await backend.writeFile(script, `${streaming.command}\n`);
|
|
1025
1028
|
await backend.run(`nohup sh -c ${shellQuote(`sh ${script} > ${log} 2>&1; echo $? > ${exitFile}`)} ` +
|
|
1026
1029
|
`> /dev/null 2>&1 & echo $! > /tmp/${id}.pid`, { cwd, timeout: 15_000 });
|
|
1027
1030
|
return {
|
|
@@ -1036,7 +1039,8 @@ export function buildTools(backend, config) {
|
|
|
1036
1039
|
`stdout of wait_for_task when the command finishes (read_file cannot reach /tmp — ` +
|
|
1037
1040
|
`to peek mid-run, exec_command: tail ${log}). If you have other work, do it and ` +
|
|
1038
1041
|
`check back. If you need this result before you can continue, call wait_for_task ` +
|
|
1039
|
-
`with this taskId — never sleep and read the log by hand
|
|
1042
|
+
`with this taskId — never sleep and read the log by hand.` +
|
|
1043
|
+
(streaming.changes.length ? ` ${streaming.changes.join(' ')}` : ''),
|
|
1040
1044
|
};
|
|
1041
1045
|
}
|
|
1042
1046
|
catch (e) {
|
package/dist/utilities.d.ts
CHANGED
|
@@ -89,6 +89,26 @@ export declare function declaredBudgetSeconds(command: string, timeoutParam: unk
|
|
|
89
89
|
* @returns True when a kill would return no useful output.
|
|
90
90
|
*/
|
|
91
91
|
export declare function outputIsWithheldUntilExit(command: string): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Rewrite a command about to run in the background so its log grows while it
|
|
94
|
+
* runs. Two shapes left the log empty until exit, and an empty log is what
|
|
95
|
+
* `wait_for_task` reads as "stuck", so working suites were reported stuck and
|
|
96
|
+
* killed (X1 run flash-m15 lost 20 of its 60 minutes this way, 2026-10-15):
|
|
97
|
+
*
|
|
98
|
+
* - a trailing `| tail -N`, which holds everything back until the command ends.
|
|
99
|
+
* It is dropped: `wait_for_task` already returns the end of the log.
|
|
100
|
+
* - `playwright test` with no `--reporter`, which runs the config's reporter —
|
|
101
|
+
* often `html`, which prints nothing per test. `--reporter=line` is added
|
|
102
|
+
* when the playwright run is the command's last step and nothing is piped or
|
|
103
|
+
* redirected from it ( aside); the results are the same, printed as they happen.
|
|
104
|
+
*
|
|
105
|
+
* @param command - The command as the executor sent it.
|
|
106
|
+
* @returns The command to run and one sentence per change made (empty when none).
|
|
107
|
+
*/
|
|
108
|
+
export declare function streamingBackgroundCommand(command: string): {
|
|
109
|
+
command: string;
|
|
110
|
+
changes: string[];
|
|
111
|
+
};
|
|
92
112
|
/**
|
|
93
113
|
* Check if a command is blocked for security reasons. Returns error message or null if allowed.
|
|
94
114
|
*
|
package/dist/utilities.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAS5C;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,GAAG,MAAM,KAAG,MAEE,CAAA;AAyFhD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK/C;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGnD;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,MAAM,CAUpF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAElE;AA2BD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"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"}
|
package/dist/utilities.js
CHANGED
|
@@ -189,6 +189,44 @@ export function declaredBudgetSeconds(command, timeoutParam) {
|
|
|
189
189
|
export function outputIsWithheldUntilExit(command) {
|
|
190
190
|
return /\|\s*(?:tail|head|grep|egrep|fgrep|sort|uniq|wc|jq)\b/.test(command);
|
|
191
191
|
}
|
|
192
|
+
/** A trailing `| tail -N` / `| tail -n N` (stderr redirects before it stay). */
|
|
193
|
+
const TRAILING_TAIL = /\s*\|\s*tail(?:\s+-n)?\s+[-+]?\d+\s*$/;
|
|
194
|
+
/**
|
|
195
|
+
* Rewrite a command about to run in the background so its log grows while it
|
|
196
|
+
* runs. Two shapes left the log empty until exit, and an empty log is what
|
|
197
|
+
* `wait_for_task` reads as "stuck", so working suites were reported stuck and
|
|
198
|
+
* killed (X1 run flash-m15 lost 20 of its 60 minutes this way, 2026-10-15):
|
|
199
|
+
*
|
|
200
|
+
* - a trailing `| tail -N`, which holds everything back until the command ends.
|
|
201
|
+
* It is dropped: `wait_for_task` already returns the end of the log.
|
|
202
|
+
* - `playwright test` with no `--reporter`, which runs the config's reporter —
|
|
203
|
+
* often `html`, which prints nothing per test. `--reporter=line` is added
|
|
204
|
+
* when the playwright run is the command's last step and nothing is piped or
|
|
205
|
+
* redirected from it ( aside); the results are the same, printed as they happen.
|
|
206
|
+
*
|
|
207
|
+
* @param command - The command as the executor sent it.
|
|
208
|
+
* @returns The command to run and one sentence per change made (empty when none).
|
|
209
|
+
*/
|
|
210
|
+
export function streamingBackgroundCommand(command) {
|
|
211
|
+
const changes = [];
|
|
212
|
+
let out = command;
|
|
213
|
+
const tail = TRAILING_TAIL.exec(out);
|
|
214
|
+
if (tail) {
|
|
215
|
+
out = out.slice(0, tail.index);
|
|
216
|
+
changes.push(`Dropped the trailing \`${tail[0].trim()}\`: it holds all output back until the command ends, ` +
|
|
217
|
+
'and wait_for_task returns the end of the log anyway.');
|
|
218
|
+
}
|
|
219
|
+
const lastStep = out.split(/&&|\|\||;/).at(-1) ?? '';
|
|
220
|
+
if (/\bplaywright\s+test\b/.test(lastStep) &&
|
|
221
|
+
!/--reporter\b/.test(lastStep) &&
|
|
222
|
+
// `2>&1` only joins stderr to the log; any other pipe or redirect sends the output elsewhere.
|
|
223
|
+
!/[|>]/.test(lastStep.replace(/\d?>&\d/g, ''))) {
|
|
224
|
+
out = `${out.trimEnd()} --reporter=line`;
|
|
225
|
+
changes.push('Added `--reporter=line` so each test result is written to the log as it finishes ' +
|
|
226
|
+
'(the config reporter may print nothing until the end).');
|
|
227
|
+
}
|
|
228
|
+
return { command: out, changes };
|
|
229
|
+
}
|
|
192
230
|
// ── Command blocking ──────────────────────────────────────────────────────────
|
|
193
231
|
/**
|
|
194
232
|
* Commands that dump environment variables — blocked to prevent secret leakage.
|
|
@@ -220,7 +258,11 @@ export function checkBlockedCommand(command) {
|
|
|
220
258
|
// These blocks fire when the executor tries to DUMP the environment (usually to discover
|
|
221
259
|
// what managed services are configured). Don't just refuse — redirect: the values are
|
|
222
260
|
// already in the process environment, so it never needs to print them.
|
|
223
|
-
|
|
261
|
+
// A blocked command runs NONE of its parts: X1 run m53 lost the `mkdir -p …`
|
|
262
|
+
// chained before a blocked env read and only found out from the retry.
|
|
263
|
+
const envDumpSteer = ' Nothing in this command ran — none of its other parts either, so run those again ' +
|
|
264
|
+
'without the dump.' +
|
|
265
|
+
' You do NOT need to dump it: the managed service values (DATABASE_URL, etc.) are already ' +
|
|
224
266
|
'in the process environment — read them IN CODE via process.env / your config loader, or ' +
|
|
225
267
|
"check the project's provisioned env file to see WHICH services exist. Printing them only " +
|
|
226
268
|
'leaks secrets into the transcript. To check whether ONE variable is set without printing ' +
|