@molecule/api-ai-tools 1.3.0 → 1.4.1
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/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +52 -27
- package/dist/utilities.d.ts.map +1 -1
- package/dist/utilities.js +2 -1
- package/package.json +2 -2
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;AAoB9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AA+BnE;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,
|
|
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;AAoB9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AA+BnE;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CAmzCxF"}
|
package/dist/tools.js
CHANGED
|
@@ -379,6 +379,13 @@ export function buildTools(backend, config) {
|
|
|
379
379
|
// reads in one imported-app build were misses on files that never existed). Return
|
|
380
380
|
// ground truth in the SAME result — what the parent directory actually contains — so
|
|
381
381
|
// the next read uses a real name instead of another guess.
|
|
382
|
+
// A package's docs are one tool call away wherever node_modules happens to live.
|
|
383
|
+
const moleculePkg = /node_modules\/(@molecule\/[^/]+)\//.exec(path)?.[1];
|
|
384
|
+
if (moleculePkg && /No such file or directory/i.test(message)) {
|
|
385
|
+
return {
|
|
386
|
+
error: `No such file: ${path}. Read ${moleculePkg}'s documentation with read_molecule_doc("${moleculePkg}") instead of looking for it in node_modules.`,
|
|
387
|
+
};
|
|
388
|
+
}
|
|
382
389
|
if (/No such file or directory/i.test(message)) {
|
|
383
390
|
const parent = path.replace(/\/[^/]*$/, '') || '/';
|
|
384
391
|
let listing;
|
|
@@ -413,7 +420,26 @@ export function buildTools(backend, config) {
|
|
|
413
420
|
return { path, entries: entries.map((e) => ({ name: e.name, type: e.type })) };
|
|
414
421
|
}
|
|
415
422
|
catch (e) {
|
|
416
|
-
|
|
423
|
+
const message = e.message;
|
|
424
|
+
// Same ground-truth answer as read_file's miss: a guessed path gets the parent's
|
|
425
|
+
// real contents back, so the next call names something that exists.
|
|
426
|
+
if (/No such file or directory|cannot access/i.test(message)) {
|
|
427
|
+
const parent = path.replace(/\/[^/]*$/, '') || '/';
|
|
428
|
+
try {
|
|
429
|
+
const siblings = await backend.readDir(parent);
|
|
430
|
+
return {
|
|
431
|
+
error: `No such directory: ${path}. ${parent} contains: ${siblings
|
|
432
|
+
.slice(0, 40)
|
|
433
|
+
.map((s) => s.name + (s.type === 'directory' ? '/' : ''))
|
|
434
|
+
.join(', ') || '(nothing)'}${siblings.length > 40 ? ', …' : ''}.`,
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
catch (_parentErr) {
|
|
438
|
+
// The parent is missing too; the plain message below says so.
|
|
439
|
+
return { error: `No such directory: ${path} (and ${parent} does not exist either).` };
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return { error: `Failed to list ${path}: ${message}` };
|
|
417
443
|
}
|
|
418
444
|
},
|
|
419
445
|
async read_file(input) {
|
|
@@ -664,10 +690,15 @@ export function buildTools(backend, config) {
|
|
|
664
690
|
`indentation — or include more surrounding context to make it unique.`,
|
|
665
691
|
};
|
|
666
692
|
}
|
|
667
|
-
if (count > 1)
|
|
693
|
+
if (count > 1) {
|
|
694
|
+
// Say WHERE, so the retry can widen old_string around the one it means.
|
|
695
|
+
const lines = [];
|
|
696
|
+
for (let at = content.indexOf(oldString); at >= 0 && lines.length < 10; at = content.indexOf(oldString, at + 1))
|
|
697
|
+
lines.push(content.slice(0, at).split('\n').length);
|
|
668
698
|
return {
|
|
669
|
-
error: `old_string found ${count} times in ${path} — must be unique. Include more surrounding context.`,
|
|
699
|
+
error: `old_string found ${count} times in ${path} (starting at lines ${lines.join(', ')}${count > lines.length ? ', …' : ''}) — must be unique. Include more surrounding context from the one you mean, or make one edit per occurrence.`,
|
|
670
700
|
};
|
|
701
|
+
}
|
|
671
702
|
// Splice by index rather than `content.replace(oldString, newString)`:
|
|
672
703
|
// String.replace treats `$&`, `$$`, `` $` ``, `$'` in the REPLACEMENT as
|
|
673
704
|
// special patterns, so a new_string containing regex-replacement code
|
|
@@ -904,7 +935,19 @@ export function buildTools(backend, config) {
|
|
|
904
935
|
// offset/limit, so a long log is cheap to follow), and an `.exit` file
|
|
905
936
|
// appears when it finishes — so "is it done?" is a read, not a poll that
|
|
906
937
|
// blocks a turn.
|
|
907
|
-
|
|
938
|
+
// A command that declares its OWN budget larger than this tool's ceiling,
|
|
939
|
+
// and whose output is withheld until the pipeline ends, would be stopped
|
|
940
|
+
// at the ceiling having printed nothing. It used to be REFUSED ("Nothing
|
|
941
|
+
// was run") — which cost the executor a whole step in 48 of 48
|
|
942
|
+
// conversations that tried one (production analytics, 2026-09-26). It
|
|
943
|
+
// now runs in the background instead: the step does the work, and the
|
|
944
|
+
// executor gets a handle to wait on.
|
|
945
|
+
const ceilingSeconds = commandBudgetMs ? Math.max(1, Math.round(commandBudgetMs / 1000)) : 0;
|
|
946
|
+
const declaredSeconds = commandBudgetMs ? declaredBudgetSeconds(command, input.timeout) : 0;
|
|
947
|
+
const overCeiling = commandBudgetMs !== undefined &&
|
|
948
|
+
declaredSeconds > ceilingSeconds &&
|
|
949
|
+
outputIsWithheldUntilExit(command);
|
|
950
|
+
if (input.run_in_background === true || overCeiling) {
|
|
908
951
|
const id = `mol-bg-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
909
952
|
const log = `/tmp/${id}.log`;
|
|
910
953
|
const exitFile = `/tmp/${id}.exit`;
|
|
@@ -921,7 +964,11 @@ export function buildTools(backend, config) {
|
|
|
921
964
|
taskId: id,
|
|
922
965
|
log,
|
|
923
966
|
exitFile,
|
|
924
|
-
note:
|
|
967
|
+
note: (overCeiling
|
|
968
|
+
? `This command asks for ${declaredSeconds}s, more than this tool's ${ceilingSeconds}s, and its ` +
|
|
969
|
+
'output only appears when it ends — so it was started in the background instead. '
|
|
970
|
+
: '') +
|
|
971
|
+
`Started in the background. Its output is being written to ${log} — read it with ` +
|
|
925
972
|
`read_file (use offset/limit to follow a long one). When it finishes, ${exitFile} ` +
|
|
926
973
|
`appears and holds the exit code. If you have other work, do it and check back. If ` +
|
|
927
974
|
`you need this result before you can continue, call wait_for_task with this taskId — ` +
|
|
@@ -934,28 +981,6 @@ export function buildTools(backend, config) {
|
|
|
934
981
|
};
|
|
935
982
|
}
|
|
936
983
|
}
|
|
937
|
-
// A command that declares its OWN budget larger than this tool's ceiling,
|
|
938
|
-
// and whose output is withheld until the pipeline ends, cannot produce
|
|
939
|
-
// anything: it will be stopped at the ceiling having printed nothing.
|
|
940
|
-
// Measured across six agent runs, that combination was ten commands and
|
|
941
|
-
// 49 minutes — 11% of all wall clock — each returning a few hundred bytes.
|
|
942
|
-
// Refusing in five seconds, naming both ways out, is strictly better than
|
|
943
|
-
// spending the ceiling to say the same thing afterwards. A command that
|
|
944
|
-
// declares nothing still RUNS: partial output survives an overrun, so
|
|
945
|
-
// there is something to learn either way.
|
|
946
|
-
if (commandBudgetMs) {
|
|
947
|
-
const ceiling = Math.max(1, Math.round(commandBudgetMs / 1000));
|
|
948
|
-
const declared = declaredBudgetSeconds(command, input.timeout);
|
|
949
|
-
if (declared > ceiling && outputIsWithheldUntilExit(command)) {
|
|
950
|
-
return {
|
|
951
|
-
error: `This command asks for ${declared}s and this tool stops at ${ceiling}s — and its output ` +
|
|
952
|
-
'is piped into tail/head/grep, which print nothing until the pipeline ends, so it ' +
|
|
953
|
-
'would spend the whole budget and hand you back nothing. Either run a smaller unit ' +
|
|
954
|
-
'(one spec file, one build step) that finishes inside the limit, or drop the pipe ' +
|
|
955
|
-
'and use a streaming reporter so the output survives being stopped. Nothing was run.',
|
|
956
|
-
};
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
984
|
try {
|
|
960
985
|
// exec_command runs installs/builds/tests — the old 30s hardcap killed
|
|
961
986
|
// those spuriously; use the (generous, caller-configurable) budget.
|
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
|
@@ -223,7 +223,8 @@ export function checkBlockedCommand(command) {
|
|
|
223
223
|
const envDumpSteer = ' You do NOT need to dump it: the managed service values (DATABASE_URL, etc.) are already ' +
|
|
224
224
|
'in the process environment — read them IN CODE via process.env / your config loader, or ' +
|
|
225
225
|
"check the project's provisioned env file to see WHICH services exist. Printing them only " +
|
|
226
|
-
'leaks secrets into the transcript.'
|
|
226
|
+
'leaks secrets into the transcript. To check whether ONE variable is set without printing ' +
|
|
227
|
+
'it: `test -n "$NAME" && echo set || echo missing`.';
|
|
227
228
|
if (BLOCKED_COMMANDS.test(command))
|
|
228
229
|
return `Command blocked: dumping environment variables is not allowed.${envDumpSteer}`;
|
|
229
230
|
if (BLOCKED_PROC_REDIRECT.test(command))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@molecule/api-ai-tools",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
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",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@molecule/api-ai": "^1.0.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@molecule/api-ai": "1.
|
|
34
|
+
"@molecule/api-ai": "1.3.0",
|
|
35
35
|
"@types/node": "26.1.2",
|
|
36
36
|
"typescript": "6.0.3",
|
|
37
37
|
"vitest": "4.1.11"
|