@molecule/api-ai-tools 1.5.14 → 1.5.15
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 +26 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +46 -9
- package/dist/utilities.d.ts +16 -0
- package/dist/utilities.d.ts.map +1 -1
- package/dist/utilities.js +34 -0
- 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-16T05:16:44.196Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/api-ai-tools
|
|
@@ -887,6 +887,22 @@ function parseCheckProblem(result: {
|
|
|
887
887
|
|
|
888
888
|
**Returns:** The message for the tool result, or null.
|
|
889
889
|
|
|
890
|
+
#### `fusedLine(content, newString)`
|
|
891
|
+
|
|
892
|
+
The line a replacement fused when it dropped the newline its `old_string`
|
|
893
|
+
ended with: `new_string`'s text is followed on the same line by what used to
|
|
894
|
+
be the next line. Read off the file as it now is, so the line shown is the
|
|
895
|
+
line the parser is actually complaining about.
|
|
896
|
+
|
|
897
|
+
```typescript
|
|
898
|
+
function fusedLine(content: string, newString: string): { line: number; text: string } | null
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
- `content` — The file's content after the edit.
|
|
902
|
+
- `newString` — A replacement's `new_string`, whose `old_string` ended with a newline.
|
|
903
|
+
|
|
904
|
+
**Returns:** The fused line's 1-based number and its text, or null when the replacement's text is not followed by more of the same line (it ends the file, the following newline survived, or another replacement rewrote it).
|
|
905
|
+
|
|
890
906
|
### Constants
|
|
891
907
|
|
|
892
908
|
#### `TOOL_SCHEMAS`
|
|
@@ -1061,6 +1077,15 @@ Peer dependencies:
|
|
|
1061
1077
|
Line numbers count the way `read_file` does, so they are valid offsets. The
|
|
1062
1078
|
excerpt is redacted like a read. The existing fields (`ok`,
|
|
1063
1079
|
`replacementsApplied`, `alreadyApplied`, `syntaxError`) are unchanged.
|
|
1080
|
+
- **A dropped line break and the parse error it causes are reported as ONE
|
|
1081
|
+
thing.** When a replacement's `old_string` ended with a newline and its
|
|
1082
|
+
`new_string` does not (so the next line is pulled up onto it) and the file
|
|
1083
|
+
then fails its parse check, `edit_file` returns a single `syntaxError` that
|
|
1084
|
+
names the replacement, shows the fused line with its number, and says to
|
|
1085
|
+
re-send that replacement with the newline restored — instead of the
|
|
1086
|
+
`newlineNote` hint beside an unrelated-looking parse error, which an executor
|
|
1087
|
+
repairs by rewriting the fused line's text and fuses the next one. The
|
|
1088
|
+
`newlineNote` alone is still returned when the file parses.
|
|
1064
1089
|
- **A parameter under another name is not a broken tool.** Every tool's input
|
|
1065
1090
|
is normalized first (`cmd` → `command`, `file` → `path`, camelCase ⇄
|
|
1066
1091
|
snake_case), and a handler that throws returns an error naming the missing
|
package/dist/index.d.ts
CHANGED
|
@@ -38,6 +38,15 @@
|
|
|
38
38
|
* Line numbers count the way `read_file` does, so they are valid offsets. The
|
|
39
39
|
* excerpt is redacted like a read. The existing fields (`ok`,
|
|
40
40
|
* `replacementsApplied`, `alreadyApplied`, `syntaxError`) are unchanged.
|
|
41
|
+
* - **A dropped line break and the parse error it causes are reported as ONE
|
|
42
|
+
* thing.** When a replacement's `old_string` ended with a newline and its
|
|
43
|
+
* `new_string` does not (so the next line is pulled up onto it) and the file
|
|
44
|
+
* then fails its parse check, `edit_file` returns a single `syntaxError` that
|
|
45
|
+
* names the replacement, shows the fused line with its number, and says to
|
|
46
|
+
* re-send that replacement with the newline restored — instead of the
|
|
47
|
+
* `newlineNote` hint beside an unrelated-looking parse error, which an executor
|
|
48
|
+
* repairs by rewriting the fused line's text and fuses the next one. The
|
|
49
|
+
* `newlineNote` alone is still returned when the file parses.
|
|
41
50
|
* - **A parameter under another name is not a broken tool.** Every tool's input
|
|
42
51
|
* is normalized first (`cmd` → `command`, `file` → `path`, camelCase ⇄
|
|
43
52
|
* snake_case), and a handler that throws returns an error naming the missing
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkHG;AAEH,cAAc,qBAAqB,CAAA;AACnC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,oBAAoB,CAAA;AAClC,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -38,6 +38,15 @@
|
|
|
38
38
|
* Line numbers count the way `read_file` does, so they are valid offsets. The
|
|
39
39
|
* excerpt is redacted like a read. The existing fields (`ok`,
|
|
40
40
|
* `replacementsApplied`, `alreadyApplied`, `syntaxError`) are unchanged.
|
|
41
|
+
* - **A dropped line break and the parse error it causes are reported as ONE
|
|
42
|
+
* thing.** When a replacement's `old_string` ended with a newline and its
|
|
43
|
+
* `new_string` does not (so the next line is pulled up onto it) and the file
|
|
44
|
+
* then fails its parse check, `edit_file` returns a single `syntaxError` that
|
|
45
|
+
* names the replacement, shows the fused line with its number, and says to
|
|
46
|
+
* re-send that replacement with the newline restored — instead of the
|
|
47
|
+
* `newlineNote` hint beside an unrelated-looking parse error, which an executor
|
|
48
|
+
* repairs by rewriting the fused line's text and fuses the next one. The
|
|
49
|
+
* `newlineNote` alone is still returned when the file parses.
|
|
41
50
|
* - **A parameter under another name is not a broken tool.** Every tool's input
|
|
42
51
|
* is normalized first (`cmd` → `command`, `file` → `path`, camelCase ⇄
|
|
43
52
|
* snake_case), and a handler that throws returns an error naming the missing
|
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;
|
|
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;AA0CnE;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CAooDxF"}
|
package/dist/tools.js
CHANGED
|
@@ -25,7 +25,7 @@ const waitedByTask = new Map();
|
|
|
25
25
|
const logBytesByTask = new Map();
|
|
26
26
|
/** The file a background command writes its own output to, when it redirects it. */
|
|
27
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, SMALL_FILE_WHOLE_CHARS, streamingBackgroundCommand, stripControlChars, truncateMiddle, whitespaceTolerantReplace, } from './utilities.js';
|
|
28
|
+
import { checkBlockedCommand, declaredBudgetSeconds, DEFAULT_SEARCH_EXCLUDED_DIRS, directoryReadHint, fusedLine, 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, SMALL_FILE_WHOLE_CHARS, streamingBackgroundCommand, stripControlChars, truncateMiddle, whitespaceTolerantReplace, } from './utilities.js';
|
|
29
29
|
/**
|
|
30
30
|
* How long exec_command waits for a command it backgrounded only because the
|
|
31
31
|
* command asked for more than the tool's ceiling, before handing back a task id.
|
|
@@ -876,24 +876,61 @@ export function buildTools(backend, config) {
|
|
|
876
876
|
// A replacement whose old text ended in a newline and whose new text does not
|
|
877
877
|
// joins the line after it onto its last line. Applied as written, but said:
|
|
878
878
|
// flash-m28 saw two lines merged only one round trip later.
|
|
879
|
-
const
|
|
879
|
+
const dropped = replacements
|
|
880
|
+
.map((r, i) => ({ ...r, position: i + 1 }))
|
|
881
|
+
.filter((r) => typeof r.old_string === 'string' &&
|
|
880
882
|
typeof r.new_string === 'string' &&
|
|
881
883
|
r.old_string.endsWith('\n') &&
|
|
882
884
|
r.new_string !== '' &&
|
|
883
|
-
!r.new_string.endsWith('\n'))
|
|
885
|
+
!r.new_string.endsWith('\n'));
|
|
886
|
+
const syntax = await syntaxErrorAfterWrite(path);
|
|
887
|
+
// Those two facts are ONE accident, and reported apart the model repairs the
|
|
888
|
+
// wrong one: flash-m55 dropped the boundary on two consecutive edit_file calls,
|
|
889
|
+
// both left `handlers/conduit.ts` unparseable, and it fixed the fused LINE's
|
|
890
|
+
// text — which re-fused the next line in the same batch. When the parse error
|
|
891
|
+
// follows a dropped newline, name the fused line and the single edit that
|
|
892
|
+
// undoes it, instead of a style note beside an unrelated-looking parse error.
|
|
893
|
+
const which = dropped.length === 1
|
|
894
|
+
? `replacement ${dropped[0].position}`
|
|
895
|
+
: `replacements ${dropped.map((r) => r.position).join(', ')}`;
|
|
896
|
+
const located = dropped.flatMap((r) => {
|
|
897
|
+
const line = fusedLine(finalContent, r.new_string);
|
|
898
|
+
return line ? [line] : [];
|
|
899
|
+
});
|
|
900
|
+
const fused = located.slice(0, 3);
|
|
901
|
+
const fusedOmitted = located.length - fused.length;
|
|
902
|
+
const shownFused = fused
|
|
903
|
+
.map((l) => ` ${l.line}: ${l.text.length > 200 ? `${l.text.slice(0, 200)}…` : l.text}`)
|
|
904
|
+
.join('\n');
|
|
905
|
+
const fusedNote = syntax.syntaxError && dropped.length > 0
|
|
906
|
+
? 'The file no longer parses after this change, and ' +
|
|
907
|
+
`${which} removed the line break that followed the replaced text — so the next line ` +
|
|
908
|
+
'now continues on the line before it, and that fused line is what the parser rejects:\n' +
|
|
909
|
+
(shownFused || ` (not located as the file now reads — read_file ${path})`) +
|
|
910
|
+
(fusedOmitted > 0
|
|
911
|
+
? `\n (${fusedOmitted} more fused line(s) — read_file ${path})`
|
|
912
|
+
: '') +
|
|
913
|
+
`\nRe-send ${which} with the trailing newline restored on new_string (change nothing ` +
|
|
914
|
+
"else about it). Editing the FUSED LINE's text instead fuses the next line the same " +
|
|
915
|
+
`way (flash-m55: three edits in a row).\n${syntax.syntaxError}`
|
|
916
|
+
: null;
|
|
884
917
|
return {
|
|
885
918
|
path,
|
|
886
919
|
ok: true,
|
|
887
920
|
replacementsApplied: replacements.length - alreadyApplied,
|
|
888
|
-
...(
|
|
889
|
-
? {
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
921
|
+
...(fusedNote
|
|
922
|
+
? { syntaxError: fusedNote }
|
|
923
|
+
: {
|
|
924
|
+
...(dropped.length > 0
|
|
925
|
+
? {
|
|
926
|
+
newlineNote: `${dropped.length === 1 ? 'A replacement' : `${dropped.length} replacements`} removed the line break after the replaced text (old_string ended with a newline, new_string does not), so the next line now continues on the same line. Check the excerpt; add the newline back if that was not intended.`,
|
|
927
|
+
}
|
|
928
|
+
: {}),
|
|
929
|
+
...syntax,
|
|
930
|
+
}),
|
|
893
931
|
...(alreadyApplied > 0 ? { alreadyApplied, note: alreadyNote } : {}),
|
|
894
932
|
totalLines: countLines(finalContent),
|
|
895
933
|
...(excerpt ? { excerpt: sanitizeFileContent(excerpt, path) } : {}),
|
|
896
|
-
...(await syntaxErrorAfterWrite(path)),
|
|
897
934
|
};
|
|
898
935
|
}
|
|
899
936
|
catch (e) {
|
package/dist/utilities.d.ts
CHANGED
|
@@ -339,4 +339,20 @@ export declare function parseCheckProblem(result: {
|
|
|
339
339
|
stderr: string;
|
|
340
340
|
exitCode: number;
|
|
341
341
|
}): string | null;
|
|
342
|
+
/**
|
|
343
|
+
* The line a replacement fused when it dropped the newline its `old_string`
|
|
344
|
+
* ended with: `new_string`'s text is followed on the same line by what used to
|
|
345
|
+
* be the next line. Read off the file as it now is, so the line shown is the
|
|
346
|
+
* line the parser is actually complaining about.
|
|
347
|
+
*
|
|
348
|
+
* @param content - The file's content after the edit.
|
|
349
|
+
* @param newString - A replacement's `new_string`, whose `old_string` ended with a newline.
|
|
350
|
+
* @returns The fused line's 1-based number and its text, or null when the
|
|
351
|
+
* replacement's text is not followed by more of the same line (it ends the
|
|
352
|
+
* file, the following newline survived, or another replacement rewrote it).
|
|
353
|
+
*/
|
|
354
|
+
export declare function fusedLine(content: string, newString: string): {
|
|
355
|
+
line: number;
|
|
356
|
+
text: string;
|
|
357
|
+
} | null;
|
|
342
358
|
//# sourceMappingURL=utilities.d.ts.map
|
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
|
@@ -103,6 +103,10 @@ const jsonValueReplacer = (quote) => (match, prefix) => {
|
|
|
103
103
|
const inner = value.slice(1, -1);
|
|
104
104
|
// An empty value hides nothing, and a suite fixture's `"password": ""` is the fact a
|
|
105
105
|
// failing assertion turns on (X1 flash-m52).
|
|
106
|
+
// A version (`"jsonwebtoken": "9.0.2"`, a package name that holds a keyword) is not a
|
|
107
|
+
// credential, and a masked one hid which version is installed (X1 flash-m57).
|
|
108
|
+
if (/^[\^~]?\d+\.\d+\.\d+(?:[-+][\w.-]+)?$/.test(inner))
|
|
109
|
+
return match;
|
|
106
110
|
if (inner === '' || NON_SECRET_VALUES.has(inner.toLowerCase()))
|
|
107
111
|
return match;
|
|
108
112
|
return `${prefix}${quote}[REDACTED]${quote}`;
|
|
@@ -720,3 +724,33 @@ export function parseCheckProblem(result) {
|
|
|
720
724
|
return null;
|
|
721
725
|
return text.slice(0, 1200);
|
|
722
726
|
}
|
|
727
|
+
/**
|
|
728
|
+
* The line a replacement fused when it dropped the newline its `old_string`
|
|
729
|
+
* ended with: `new_string`'s text is followed on the same line by what used to
|
|
730
|
+
* be the next line. Read off the file as it now is, so the line shown is the
|
|
731
|
+
* line the parser is actually complaining about.
|
|
732
|
+
*
|
|
733
|
+
* @param content - The file's content after the edit.
|
|
734
|
+
* @param newString - A replacement's `new_string`, whose `old_string` ended with a newline.
|
|
735
|
+
* @returns The fused line's 1-based number and its text, or null when the
|
|
736
|
+
* replacement's text is not followed by more of the same line (it ends the
|
|
737
|
+
* file, the following newline survived, or another replacement rewrote it).
|
|
738
|
+
*/
|
|
739
|
+
export function fusedLine(content, newString) {
|
|
740
|
+
for (let at = content.indexOf(newString); at >= 0; at = content.indexOf(newString, at + 1)) {
|
|
741
|
+
const endsAt = at + newString.length;
|
|
742
|
+
const next = content[endsAt];
|
|
743
|
+
// End of file (nothing was joined) or a newline (the boundary survived) are
|
|
744
|
+
// both "not fused". A later replacement in the same batch may have rewritten
|
|
745
|
+
// this text, so keep looking rather than giving up on the first occurrence.
|
|
746
|
+
if (next === undefined || next === '\n')
|
|
747
|
+
continue;
|
|
748
|
+
const lineStart = content.lastIndexOf('\n', at) + 1;
|
|
749
|
+
const lineEnd = content.indexOf('\n', endsAt);
|
|
750
|
+
return {
|
|
751
|
+
line: content.slice(0, lineStart).split('\n').length,
|
|
752
|
+
text: content.slice(lineStart, lineEnd === -1 ? undefined : lineEnd),
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
return null;
|
|
756
|
+
}
|