@molecule/api-ai-tools 1.5.9 → 1.5.11
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 +57 -16
- package/dist/utilities.d.ts.map +1 -1
- package/dist/utilities.js +5 -2
- package/package.json +1 -1
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;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,
|
|
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,CAwiDxF"}
|
package/dist/tools.js
CHANGED
|
@@ -142,22 +142,37 @@ export function buildTools(backend, config) {
|
|
|
142
142
|
async function checkSymlink(path) {
|
|
143
143
|
if (!symlinkGuards)
|
|
144
144
|
return null;
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
145
|
+
// One retry: the first commands on a just-attached sandbox can fail at once (X1
|
|
146
|
+
// flash-m44: three paths refused in 332 ms, the same check passing a beat later).
|
|
147
|
+
let lastError;
|
|
148
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
149
|
+
const started = Date.now();
|
|
150
|
+
try {
|
|
151
|
+
const result = await backend.run(`readlink -f ${shellQuote(path)} 2>/dev/null || echo ${shellQuote(path)}`, { timeout: 5000 });
|
|
152
|
+
const realPath = result.stdout.trim();
|
|
153
|
+
if (realPath && realPath !== root && !realPath.startsWith(root + '/')) {
|
|
154
|
+
return 'Access denied: path resolves outside the project workspace';
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
lastError = Object.assign(error instanceof Error ? error : new Error(String(error)), {
|
|
160
|
+
elapsedMs: Date.now() - started,
|
|
161
|
+
});
|
|
162
|
+
if (attempt === 0)
|
|
163
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
150
164
|
}
|
|
151
|
-
return null;
|
|
152
165
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
166
|
+
// Deny conservatively, and say what failed: "access denied" read as a forbidden path,
|
|
167
|
+
// and a fixed "did not answer within 5 s" hid an error that took 332 ms.
|
|
168
|
+
const err = lastError;
|
|
169
|
+
const timedOut = err?.name === 'TimeoutError' || (err?.elapsedMs ?? 0) >= 4900;
|
|
170
|
+
return timedOut
|
|
171
|
+
? 'Unable to verify path safety: the sandbox did not answer the check within 5 s (it may be ' +
|
|
158
172
|
'restarting or out of memory), so the path was refused to stay safe. Retry in a moment; if ' +
|
|
159
|
-
'every file tool fails this way, the sandbox needs a restart.'
|
|
160
|
-
|
|
173
|
+
'every file tool fails this way, the sandbox needs a restart.'
|
|
174
|
+
: `Unable to verify path safety: the sandbox's command channel failed (${err?.name ?? 'Error'}: ${String(err?.message ?? err).slice(0, 160)}), ` +
|
|
175
|
+
'so the path was refused to stay safe. Retry the call; if every file tool fails this way, the sandbox needs a restart.';
|
|
161
176
|
}
|
|
162
177
|
/**
|
|
163
178
|
* Strip control characters and optionally redact secrets from tool output.
|
|
@@ -434,12 +449,15 @@ export function buildTools(backend, config) {
|
|
|
434
449
|
// the next read uses a real name instead of another guess.
|
|
435
450
|
// A package's docs are one tool call away wherever node_modules happens to live.
|
|
436
451
|
const moleculePkg = /node_modules\/(@molecule\/[^/]+)\//.exec(path)?.[1];
|
|
437
|
-
|
|
452
|
+
// Docker's `cat` says "No such file or directory"; E2B's SDK says "path '…' does not
|
|
453
|
+
// exist" (X1 flash-m44: the hints below never fired on E2B).
|
|
454
|
+
const notFound = /No such file or directory|does not exist|ENOENT/i.test(message);
|
|
455
|
+
if (moleculePkg && notFound) {
|
|
438
456
|
return {
|
|
439
457
|
error: `No such file: ${path}. Read ${moleculePkg}'s documentation with read_molecule_doc("${moleculePkg}") instead of looking for it in node_modules.`,
|
|
440
458
|
};
|
|
441
459
|
}
|
|
442
|
-
if (
|
|
460
|
+
if (notFound) {
|
|
443
461
|
const parent = path.replace(/\/[^/]*$/, '') || '/';
|
|
444
462
|
let listing;
|
|
445
463
|
try {
|
|
@@ -476,7 +494,7 @@ export function buildTools(backend, config) {
|
|
|
476
494
|
const message = e.message;
|
|
477
495
|
// Same ground-truth answer as read_file's miss: a guessed path gets the parent's
|
|
478
496
|
// real contents back, so the next call names something that exists.
|
|
479
|
-
if (/No such file or directory|cannot access/i.test(message)) {
|
|
497
|
+
if (/No such file or directory|cannot access|does not exist|ENOENT/i.test(message)) {
|
|
480
498
|
const parent = path.replace(/\/[^/]*$/, '') || '/';
|
|
481
499
|
try {
|
|
482
500
|
const siblings = await backend.readDir(parent);
|
|
@@ -703,6 +721,29 @@ export function buildTools(backend, config) {
|
|
|
703
721
|
error: `old_string not found in ${path}. The file's ACTUAL content near your target (copy the exact text from here):\n${snippet}`,
|
|
704
722
|
};
|
|
705
723
|
};
|
|
724
|
+
// An import block the model rebuilt in its own order: the linter's
|
|
725
|
+
// import sort owns that order, so name it and show the real block. X1
|
|
726
|
+
// flash-m42 sent the same block three times in three orders.
|
|
727
|
+
// Only when old_string is import statements and nothing else.
|
|
728
|
+
const imported = /^(?:\s*import\b[^;]*?\bfrom\s+(['"])([^'"]+)\1;?)+\s*$/.exec(oldString)?.[2];
|
|
729
|
+
if (imported) {
|
|
730
|
+
const at = fileLines.findIndex((l) => l.includes(`'${imported}'`) || l.includes(`"${imported}"`));
|
|
731
|
+
if (at >= 0) {
|
|
732
|
+
let start = at;
|
|
733
|
+
while (start > 0 && !/^\s*import\b/.test(fileLines[start]))
|
|
734
|
+
start--;
|
|
735
|
+
const block = fileLines
|
|
736
|
+
.slice(start, at + 1)
|
|
737
|
+
.map((l, i) => `${start + i + 1}: ${l}`)
|
|
738
|
+
.join('\n');
|
|
739
|
+
return {
|
|
740
|
+
error: `old_string not found in ${path}: it is an import block, and the linter's import ` +
|
|
741
|
+
`sort decides its order, so do not rebuild it. The file's import from ` +
|
|
742
|
+
`'${imported}' reads:\n${block}\nEdit one line of it, or add your import as a ` +
|
|
743
|
+
'new line and let the linter sort it.',
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
}
|
|
706
747
|
const distinctiveLines = [
|
|
707
748
|
...new Set(oldString
|
|
708
749
|
.split('\n')
|
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;AA6FhD;;;;;;;;;;;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;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,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
|
@@ -204,11 +204,14 @@ export function outputIsWithheldUntilExit(command) {
|
|
|
204
204
|
* @returns The target as written, or null (`/dev/null` and `&1`/`&2` are not files).
|
|
205
205
|
*/
|
|
206
206
|
export function outputRedirectTarget(command) {
|
|
207
|
-
|
|
207
|
+
// A heredoc that writes a file (`cat > cfg.ts <<'EOF' … EOF`) is not where the run's output
|
|
208
|
+
// goes: X1 flash-m44 was told its config file was the suite's log.
|
|
209
|
+
const text = command.replace(/[^\n;&|]*<<-?\s*(['"]?)(\w+)\1[\s\S]*?\n\s*\2\b/g, '');
|
|
210
|
+
const tee = /\|\s*tee\s+(?:-a\s+)?([^\s;&|]+)/.exec(text);
|
|
208
211
|
if (tee)
|
|
209
212
|
return tee[1];
|
|
210
213
|
let last = null;
|
|
211
|
-
for (const m of
|
|
214
|
+
for (const m of text.matchAll(/(?:^|[^0-9&>])(?:&>|1?>>?)\s*([^\s;&|]+)/g)) {
|
|
212
215
|
if (m[1] !== '/dev/null' && !m[1].startsWith('&'))
|
|
213
216
|
last = m[1];
|
|
214
217
|
}
|