@molecule/api-ai-tools 1.5.7 → 1.5.8
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 +16 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +28 -7
- package/dist/utilities.d.ts +10 -0
- package/dist/utilities.d.ts.map +1 -1
- package/dist/utilities.js +25 -2
- 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-15T23:00:29.499Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/api-ai-tools
|
|
@@ -614,6 +614,21 @@ function outputIsWithheldUntilExit(command: string): boolean
|
|
|
614
614
|
|
|
615
615
|
**Returns:** True when a kill would return no useful output.
|
|
616
616
|
|
|
617
|
+
#### `outputRedirectTarget(command)`
|
|
618
|
+
|
|
619
|
+
The file a command sends its own output to, when it redirects it (`> out.txt`,
|
|
620
|
+
`>> log`, `&> run.log`, `| tee [-a] file`), or null. A background command that does
|
|
621
|
+
this leaves its task log empty, so the log is the wrong place to look and an empty
|
|
622
|
+
log proves nothing (X1 flash-m29).
|
|
623
|
+
|
|
624
|
+
```typescript
|
|
625
|
+
function outputRedirectTarget(command: string): string | null
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
- `command` — The shell command.
|
|
629
|
+
|
|
630
|
+
**Returns:** The target as written, or null (`/dev/null` and `&1`/`&2` are not files).
|
|
631
|
+
|
|
617
632
|
#### `parseCheckCommand(path)`
|
|
618
633
|
|
|
619
634
|
The shell command that parses one file and exits non-zero with the error
|
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;
|
|
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;AA8B9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAwCnE;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CA2/CxF"}
|
package/dist/tools.js
CHANGED
|
@@ -23,7 +23,9 @@ const waitedByTask = new Map();
|
|
|
23
23
|
* m21, 2026-10-15).
|
|
24
24
|
*/
|
|
25
25
|
const logBytesByTask = new Map();
|
|
26
|
-
|
|
26
|
+
/** The file a background command writes its own output to, when it redirects it. */
|
|
27
|
+
const outputFileByTask = new Map();
|
|
28
|
+
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, outputRedirectTarget, parseCheckCommand, parseCheckProblem, pathArgError, redactSecrets, redactSecretsInCode, resolvePath, shellQuote, sliceLines, streamingBackgroundCommand, stripControlChars, truncateMiddle, whitespaceTolerantReplace, } from './utilities.js';
|
|
27
29
|
/**
|
|
28
30
|
* How long exec_command waits for a command it backgrounded only because the
|
|
29
31
|
* command asked for more than the tool's ceiling, before handing back a task id.
|
|
@@ -1032,9 +1034,13 @@ export function buildTools(backend, config) {
|
|
|
1032
1034
|
// executor gets a handle to wait on.
|
|
1033
1035
|
const ceilingSeconds = commandBudgetMs ? Math.max(1, Math.round(commandBudgetMs / 1000)) : 0;
|
|
1034
1036
|
const declaredSeconds = commandBudgetMs ? declaredBudgetSeconds(command, input.timeout) : 0;
|
|
1037
|
+
// A Playwright run with its output held back by a pipe is backgrounded without
|
|
1038
|
+
// declaring a budget too: a suite routinely outlasts the ceiling, and killed there
|
|
1039
|
+
// behind `| tail` it returns nothing (X1 flash-m29 lost a 290 s run that way).
|
|
1040
|
+
// A short one still comes back as a foreground result, through the grace below.
|
|
1035
1041
|
const overCeiling = commandBudgetMs !== undefined &&
|
|
1036
|
-
|
|
1037
|
-
|
|
1042
|
+
outputIsWithheldUntilExit(command) &&
|
|
1043
|
+
(declaredSeconds > ceilingSeconds || /\bplaywright\s+test\b/.test(command));
|
|
1038
1044
|
if (input.run_in_background === true || overCeiling) {
|
|
1039
1045
|
const id = `mol-bg-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
1040
1046
|
const log = `/tmp/${id}.log`;
|
|
@@ -1048,6 +1054,14 @@ export function buildTools(backend, config) {
|
|
|
1048
1054
|
// Keep the log growing while it runs (see streamingBackgroundCommand):
|
|
1049
1055
|
// an empty log is what wait_for_task reads as stuck.
|
|
1050
1056
|
const streaming = streamingBackgroundCommand(command);
|
|
1057
|
+
const ownTarget = outputRedirectTarget(streaming.command);
|
|
1058
|
+
const ownFile = ownTarget
|
|
1059
|
+
? ownTarget.startsWith('/')
|
|
1060
|
+
? ownTarget
|
|
1061
|
+
: `${cwd}/${ownTarget}`
|
|
1062
|
+
: null;
|
|
1063
|
+
if (ownFile)
|
|
1064
|
+
outputFileByTask.set(id, ownFile);
|
|
1051
1065
|
await backend.writeFile(script, `${streaming.command}\n`);
|
|
1052
1066
|
await backend.run(`nohup sh -c ${shellQuote(`sh ${script} > ${log} 2>&1; echo $? > ${exitFile}`)} ` +
|
|
1053
1067
|
`> /dev/null 2>&1 & echo $! > /tmp/${id}.pid`, { cwd, timeout: 15_000 });
|
|
@@ -1094,15 +1108,21 @@ export function buildTools(backend, config) {
|
|
|
1094
1108
|
log,
|
|
1095
1109
|
exitFile,
|
|
1096
1110
|
note: (overCeiling
|
|
1097
|
-
?
|
|
1098
|
-
|
|
1111
|
+
? declaredSeconds > ceilingSeconds
|
|
1112
|
+
? `This command asks for ${declaredSeconds}s, more than this tool's ${ceilingSeconds}s, and its ` +
|
|
1113
|
+
'output only appears when it ends — so it was started in the background instead. '
|
|
1114
|
+
: `A Playwright run can take longer than this tool's ${ceilingSeconds}s, and behind a pipe its ` +
|
|
1115
|
+
'output only appears when it ends — so it was started in the background instead. '
|
|
1099
1116
|
: '') +
|
|
1100
1117
|
`Started in the background. Its output is written to ${log} and comes back as the ` +
|
|
1101
1118
|
`stdout of wait_for_task when the command finishes (read_file cannot reach /tmp — ` +
|
|
1102
1119
|
`to peek mid-run, exec_command: tail ${log}). If you have other work, do it and ` +
|
|
1103
1120
|
`check back. If you need this result before you can continue, call wait_for_task ` +
|
|
1104
1121
|
`with this taskId — never sleep and read the log by hand.` +
|
|
1105
|
-
(streaming.changes.length ? ` ${streaming.changes.join(' ')}` : '')
|
|
1122
|
+
(streaming.changes.length ? ` ${streaming.changes.join(' ')}` : '') +
|
|
1123
|
+
(ownFile
|
|
1124
|
+
? ` This command writes its own output to ${ownFile}, so the task log stays empty: peek with exec_command: tail ${ownFile}.`
|
|
1125
|
+
: ''),
|
|
1106
1126
|
};
|
|
1107
1127
|
}
|
|
1108
1128
|
catch (e) {
|
|
@@ -1239,7 +1259,8 @@ export function buildTools(backend, config) {
|
|
|
1239
1259
|
return null;
|
|
1240
1260
|
let r;
|
|
1241
1261
|
try {
|
|
1242
|
-
|
|
1262
|
+
const own = outputFileByTask.get(taskId);
|
|
1263
|
+
r = await backend.run(`cat /tmp/${taskId}.log${own ? ` ${shellQuote(own)}` : ''} 2>/dev/null | wc -c`, { timeout: 5_000 });
|
|
1243
1264
|
}
|
|
1244
1265
|
catch (_error) {
|
|
1245
1266
|
// No answer about the log: treat the size as unknown, which keeps the
|
package/dist/utilities.d.ts
CHANGED
|
@@ -89,6 +89,16 @@ 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
|
+
* The file a command sends its own output to, when it redirects it (`> out.txt`,
|
|
94
|
+
* `>> log`, `&> run.log`, `| tee [-a] file`), or null. A background command that does
|
|
95
|
+
* this leaves its task log empty, so the log is the wrong place to look and an empty
|
|
96
|
+
* log proves nothing (X1 flash-m29).
|
|
97
|
+
*
|
|
98
|
+
* @param command - The shell command.
|
|
99
|
+
* @returns The target as written, or null (`/dev/null` and `&1`/`&2` are not files).
|
|
100
|
+
*/
|
|
101
|
+
export declare function outputRedirectTarget(command: string): string | null;
|
|
92
102
|
/**
|
|
93
103
|
* Rewrite a command about to run in the background so its log grows while it
|
|
94
104
|
* runs. Two shapes left the log empty until exit, and an empty log is what
|
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;
|
|
1
|
+
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"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"}
|
package/dist/utilities.js
CHANGED
|
@@ -67,8 +67,11 @@ const SECRET_ENV_ASSIGNMENT = new RegExp(
|
|
|
67
67
|
// un-masked exactly the plainest env vars.
|
|
68
68
|
`^((?:export[ \\t]+)?[A-Za-z0-9_]*(?:${SECRET_KEYWORDS})[A-Za-z0-9_]*)=(?![{<])(.+)$`, 'gim');
|
|
69
69
|
/** Catch JSON-formatted env dumps like { KEY: 'value' } from node/python. */
|
|
70
|
-
const SECRET_JSON_DQ = new RegExp(
|
|
71
|
-
|
|
70
|
+
const SECRET_JSON_DQ = new RegExp(
|
|
71
|
+
// A value ends at its closing quote OR the end of its line: cut off mid-value (`head -c`),
|
|
72
|
+
// the old pattern ran on to a quote on a LATER line and swallowed the lines between (flash-m32).
|
|
73
|
+
`(['"]?(?:\\w*(?:${SECRET_KEYWORDS})\\w*)['"]?\\s*[:=]\\s*)"(?:[^"\\\\\\n]|\\\\.)*(?:"|(?=\\n)|$)`, 'gi');
|
|
74
|
+
const SECRET_JSON_SQ = new RegExp(`(['"]?(?:\\w*(?:${SECRET_KEYWORDS})\\w*)['"]?\\s*[:=]\\s*)'(?:[^'\\\\\\n]|\\\\.)*(?:'|(?=\\n)|$)`, 'gi');
|
|
72
75
|
/**
|
|
73
76
|
* Exact VALUES that are UI vocabulary, never credentials — kept verbatim even when they
|
|
74
77
|
* sit next to a keyword-looking name. Frontend auth code is full of these: a JSX ternary
|
|
@@ -189,6 +192,26 @@ export function declaredBudgetSeconds(command, timeoutParam) {
|
|
|
189
192
|
export function outputIsWithheldUntilExit(command) {
|
|
190
193
|
return /\|\s*(?:tail|head|grep|egrep|fgrep|sort|uniq|wc|jq)\b/.test(command);
|
|
191
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* The file a command sends its own output to, when it redirects it (`> out.txt`,
|
|
197
|
+
* `>> log`, `&> run.log`, `| tee [-a] file`), or null. A background command that does
|
|
198
|
+
* this leaves its task log empty, so the log is the wrong place to look and an empty
|
|
199
|
+
* log proves nothing (X1 flash-m29).
|
|
200
|
+
*
|
|
201
|
+
* @param command - The shell command.
|
|
202
|
+
* @returns The target as written, or null (`/dev/null` and `&1`/`&2` are not files).
|
|
203
|
+
*/
|
|
204
|
+
export function outputRedirectTarget(command) {
|
|
205
|
+
const tee = /\|\s*tee\s+(?:-a\s+)?([^\s;&|]+)/.exec(command);
|
|
206
|
+
if (tee)
|
|
207
|
+
return tee[1];
|
|
208
|
+
let last = null;
|
|
209
|
+
for (const m of command.matchAll(/(?:^|[^0-9&>])(?:&>|1?>>?)\s*([^\s;&|]+)/g)) {
|
|
210
|
+
if (m[1] !== '/dev/null' && !m[1].startsWith('&'))
|
|
211
|
+
last = m[1];
|
|
212
|
+
}
|
|
213
|
+
return last;
|
|
214
|
+
}
|
|
192
215
|
/** A trailing `| tail -N` / `| tail -n N` (stderr redirects before it stay). */
|
|
193
216
|
const TRAILING_TAIL = /\s*\|\s*tail(?:\s+-n)?\s+[-+]?\d+\s*$/;
|
|
194
217
|
/**
|