@ank1015/llm-agents 0.0.2
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/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/README.md +117 -0
- package/dist/agents/skills/index.d.ts +37 -0
- package/dist/agents/skills/index.d.ts.map +1 -0
- package/dist/agents/skills/index.js +386 -0
- package/dist/agents/skills/index.js.map +1 -0
- package/dist/agents/system-prompt.d.ts +7 -0
- package/dist/agents/system-prompt.d.ts.map +1 -0
- package/dist/agents/system-prompt.js +106 -0
- package/dist/agents/system-prompt.js.map +1 -0
- package/dist/agents/tools.d.ts +3 -0
- package/dist/agents/tools.d.ts.map +1 -0
- package/dist/agents/tools.js +3 -0
- package/dist/agents/tools.js.map +1 -0
- package/dist/helpers/ai-image/ai-image.d.ts +75 -0
- package/dist/helpers/ai-image/ai-image.d.ts.map +1 -0
- package/dist/helpers/ai-image/ai-image.js +438 -0
- package/dist/helpers/ai-image/ai-image.js.map +1 -0
- package/dist/helpers/ai-image/index.d.ts +3 -0
- package/dist/helpers/ai-image/index.d.ts.map +1 -0
- package/dist/helpers/ai-image/index.js +2 -0
- package/dist/helpers/ai-image/index.js.map +1 -0
- package/dist/helpers/index.d.ts +2 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +2 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/bash.d.ts +55 -0
- package/dist/tools/bash.d.ts.map +1 -0
- package/dist/tools/bash.js +246 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/edit-diff.d.ts +63 -0
- package/dist/tools/edit-diff.d.ts.map +1 -0
- package/dist/tools/edit-diff.js +246 -0
- package/dist/tools/edit-diff.js.map +1 -0
- package/dist/tools/edit.d.ts +39 -0
- package/dist/tools/edit.d.ts.map +1 -0
- package/dist/tools/edit.js +150 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/find.d.ts +39 -0
- package/dist/tools/find.d.ts.map +1 -0
- package/dist/tools/find.js +206 -0
- package/dist/tools/find.js.map +1 -0
- package/dist/tools/grep.d.ts +45 -0
- package/dist/tools/grep.d.ts.map +1 -0
- package/dist/tools/grep.js +244 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/index.d.ts +73 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +66 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/ls.d.ts +40 -0
- package/dist/tools/ls.d.ts.map +1 -0
- package/dist/tools/ls.js +121 -0
- package/dist/tools/ls.js.map +1 -0
- package/dist/tools/path-utils.d.ts +8 -0
- package/dist/tools/path-utils.d.ts.map +1 -0
- package/dist/tools/path-utils.js +81 -0
- package/dist/tools/path-utils.js.map +1 -0
- package/dist/tools/read.d.ts +39 -0
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +177 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/truncate.d.ts +70 -0
- package/dist/tools/truncate.d.ts.map +1 -0
- package/dist/tools/truncate.js +205 -0
- package/dist/tools/truncate.js.map +1 -0
- package/dist/tools/utils/config.d.ts +16 -0
- package/dist/tools/utils/config.d.ts.map +1 -0
- package/dist/tools/utils/config.js +40 -0
- package/dist/tools/utils/config.js.map +1 -0
- package/dist/tools/utils/image-resize.d.ts +36 -0
- package/dist/tools/utils/image-resize.d.ts.map +1 -0
- package/dist/tools/utils/image-resize.js +183 -0
- package/dist/tools/utils/image-resize.js.map +1 -0
- package/dist/tools/utils/mime.d.ts +3 -0
- package/dist/tools/utils/mime.d.ts.map +1 -0
- package/dist/tools/utils/mime.js +41 -0
- package/dist/tools/utils/mime.js.map +1 -0
- package/dist/tools/utils/photon.d.ts +21 -0
- package/dist/tools/utils/photon.d.ts.map +1 -0
- package/dist/tools/utils/photon.js +121 -0
- package/dist/tools/utils/photon.js.map +1 -0
- package/dist/tools/utils/shell.d.ts +26 -0
- package/dist/tools/utils/shell.d.ts.map +1 -0
- package/dist/tools/utils/shell.js +177 -0
- package/dist/tools/utils/shell.js.map +1 -0
- package/dist/tools/utils/tools-manager.d.ts +3 -0
- package/dist/tools/utils/tools-manager.d.ts.map +1 -0
- package/dist/tools/utils/tools-manager.js +209 -0
- package/dist/tools/utils/tools-manager.js.map +1 -0
- package/dist/tools/write.d.ts +29 -0
- package/dist/tools/write.d.ts.map +1 -0
- package/dist/tools/write.js +83 -0
- package/dist/tools/write.js.map +1 -0
- package/package.json +73 -0
- package/skills/ai-images/SKILL.md +45 -0
- package/skills/ai-images/references/create.md +106 -0
- package/skills/ai-images/references/edit.md +107 -0
- package/skills/registry.json +10 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared diff computation utilities for the edit tool.
|
|
3
|
+
* Used by both edit.ts (for execution) and tool-execution.ts (for preview rendering).
|
|
4
|
+
*/
|
|
5
|
+
import { constants } from 'fs';
|
|
6
|
+
import { access, readFile } from 'fs/promises';
|
|
7
|
+
import * as Diff from 'diff';
|
|
8
|
+
import { resolveToCwd } from './path-utils.js';
|
|
9
|
+
export function detectLineEnding(content) {
|
|
10
|
+
const crlfIdx = content.indexOf('\r\n');
|
|
11
|
+
const lfIdx = content.indexOf('\n');
|
|
12
|
+
if (lfIdx === -1)
|
|
13
|
+
return '\n';
|
|
14
|
+
if (crlfIdx === -1)
|
|
15
|
+
return '\n';
|
|
16
|
+
return crlfIdx < lfIdx ? '\r\n' : '\n';
|
|
17
|
+
}
|
|
18
|
+
export function normalizeToLF(text) {
|
|
19
|
+
return text.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
20
|
+
}
|
|
21
|
+
export function restoreLineEndings(text, ending) {
|
|
22
|
+
return ending === '\r\n' ? text.replace(/\n/g, '\r\n') : text;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Normalize text for fuzzy matching. Applies progressive transformations:
|
|
26
|
+
* - Strip trailing whitespace from each line
|
|
27
|
+
* - Normalize smart quotes to ASCII equivalents
|
|
28
|
+
* - Normalize Unicode dashes/hyphens to ASCII hyphen
|
|
29
|
+
* - Normalize special Unicode spaces to regular space
|
|
30
|
+
*/
|
|
31
|
+
export function normalizeForFuzzyMatch(text) {
|
|
32
|
+
return (text
|
|
33
|
+
// Strip trailing whitespace per line
|
|
34
|
+
.split('\n')
|
|
35
|
+
.map((line) => line.trimEnd())
|
|
36
|
+
.join('\n')
|
|
37
|
+
// Smart single quotes → '
|
|
38
|
+
.replace(/[\u2018\u2019\u201A\u201B]/g, "'")
|
|
39
|
+
// Smart double quotes → "
|
|
40
|
+
.replace(/[\u201C\u201D\u201E\u201F]/g, '"')
|
|
41
|
+
// Various dashes/hyphens → -
|
|
42
|
+
// U+2010 hyphen, U+2011 non-breaking hyphen, U+2012 figure dash,
|
|
43
|
+
// U+2013 en-dash, U+2014 em-dash, U+2015 horizontal bar, U+2212 minus
|
|
44
|
+
.replace(/[\u2010\u2011\u2012\u2013\u2014\u2015\u2212]/g, '-')
|
|
45
|
+
// Special spaces → regular space
|
|
46
|
+
// U+00A0 NBSP, U+2002-U+200A various spaces, U+202F narrow NBSP,
|
|
47
|
+
// U+205F medium math space, U+3000 ideographic space
|
|
48
|
+
.replace(/[\u00A0\u2002-\u200A\u202F\u205F\u3000]/g, ' '));
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Find oldText in content, trying exact match first, then fuzzy match.
|
|
52
|
+
* When fuzzy matching is used, the returned contentForReplacement is the
|
|
53
|
+
* fuzzy-normalized version of the content (trailing whitespace stripped,
|
|
54
|
+
* Unicode quotes/dashes normalized to ASCII).
|
|
55
|
+
*/
|
|
56
|
+
export function fuzzyFindText(content, oldText) {
|
|
57
|
+
// Try exact match first
|
|
58
|
+
const exactIndex = content.indexOf(oldText);
|
|
59
|
+
if (exactIndex !== -1) {
|
|
60
|
+
return {
|
|
61
|
+
found: true,
|
|
62
|
+
index: exactIndex,
|
|
63
|
+
matchLength: oldText.length,
|
|
64
|
+
usedFuzzyMatch: false,
|
|
65
|
+
contentForReplacement: content,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
// Try fuzzy match - work entirely in normalized space
|
|
69
|
+
const fuzzyContent = normalizeForFuzzyMatch(content);
|
|
70
|
+
const fuzzyOldText = normalizeForFuzzyMatch(oldText);
|
|
71
|
+
const fuzzyIndex = fuzzyContent.indexOf(fuzzyOldText);
|
|
72
|
+
if (fuzzyIndex === -1) {
|
|
73
|
+
return {
|
|
74
|
+
found: false,
|
|
75
|
+
index: -1,
|
|
76
|
+
matchLength: 0,
|
|
77
|
+
usedFuzzyMatch: false,
|
|
78
|
+
contentForReplacement: content,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// When fuzzy matching, we work in the normalized space for replacement.
|
|
82
|
+
// This means the output will have normalized whitespace/quotes/dashes,
|
|
83
|
+
// which is acceptable since we're fixing minor formatting differences anyway.
|
|
84
|
+
return {
|
|
85
|
+
found: true,
|
|
86
|
+
index: fuzzyIndex,
|
|
87
|
+
matchLength: fuzzyOldText.length,
|
|
88
|
+
usedFuzzyMatch: true,
|
|
89
|
+
contentForReplacement: fuzzyContent,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/** Strip UTF-8 BOM if present, return both the BOM (if any) and the text without it */
|
|
93
|
+
export function stripBom(content) {
|
|
94
|
+
return content.startsWith('\uFEFF')
|
|
95
|
+
? { bom: '\uFEFF', text: content.slice(1) }
|
|
96
|
+
: { bom: '', text: content };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Generate a unified diff string with line numbers and context.
|
|
100
|
+
* Returns both the diff string and the first changed line number (in the new file).
|
|
101
|
+
*/
|
|
102
|
+
export function generateDiffString(oldContent, newContent, contextLines = 4) {
|
|
103
|
+
const parts = Diff.diffLines(oldContent, newContent);
|
|
104
|
+
const output = [];
|
|
105
|
+
const oldLines = oldContent.split('\n');
|
|
106
|
+
const newLines = newContent.split('\n');
|
|
107
|
+
const maxLineNum = Math.max(oldLines.length, newLines.length);
|
|
108
|
+
const lineNumWidth = String(maxLineNum).length;
|
|
109
|
+
let oldLineNum = 1;
|
|
110
|
+
let newLineNum = 1;
|
|
111
|
+
let lastWasChange = false;
|
|
112
|
+
let firstChangedLine;
|
|
113
|
+
for (let i = 0; i < parts.length; i++) {
|
|
114
|
+
const part = parts[i];
|
|
115
|
+
const raw = part.value.split('\n');
|
|
116
|
+
if (raw[raw.length - 1] === '') {
|
|
117
|
+
raw.pop();
|
|
118
|
+
}
|
|
119
|
+
if (part.added || part.removed) {
|
|
120
|
+
// Capture the first changed line (in the new file)
|
|
121
|
+
if (firstChangedLine === undefined) {
|
|
122
|
+
firstChangedLine = newLineNum;
|
|
123
|
+
}
|
|
124
|
+
// Show the change
|
|
125
|
+
for (const line of raw) {
|
|
126
|
+
if (part.added) {
|
|
127
|
+
const lineNum = String(newLineNum).padStart(lineNumWidth, ' ');
|
|
128
|
+
output.push(`+${lineNum} ${line}`);
|
|
129
|
+
newLineNum++;
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
// removed
|
|
133
|
+
const lineNum = String(oldLineNum).padStart(lineNumWidth, ' ');
|
|
134
|
+
output.push(`-${lineNum} ${line}`);
|
|
135
|
+
oldLineNum++;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
lastWasChange = true;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
// Context lines - only show a few before/after changes
|
|
142
|
+
const nextPart = parts[i + 1];
|
|
143
|
+
const nextPartIsChange = i < parts.length - 1 && nextPart !== undefined && (nextPart.added || nextPart.removed);
|
|
144
|
+
if (lastWasChange || nextPartIsChange) {
|
|
145
|
+
// Show context
|
|
146
|
+
let linesToShow = raw;
|
|
147
|
+
let skipStart = 0;
|
|
148
|
+
let skipEnd = 0;
|
|
149
|
+
if (!lastWasChange) {
|
|
150
|
+
// Show only last N lines as leading context
|
|
151
|
+
skipStart = Math.max(0, raw.length - contextLines);
|
|
152
|
+
linesToShow = raw.slice(skipStart);
|
|
153
|
+
}
|
|
154
|
+
if (!nextPartIsChange && linesToShow.length > contextLines) {
|
|
155
|
+
// Show only first N lines as trailing context
|
|
156
|
+
skipEnd = linesToShow.length - contextLines;
|
|
157
|
+
linesToShow = linesToShow.slice(0, contextLines);
|
|
158
|
+
}
|
|
159
|
+
// Add ellipsis if we skipped lines at start
|
|
160
|
+
if (skipStart > 0) {
|
|
161
|
+
output.push(` ${''.padStart(lineNumWidth, ' ')} ...`);
|
|
162
|
+
// Update line numbers for the skipped leading context
|
|
163
|
+
oldLineNum += skipStart;
|
|
164
|
+
newLineNum += skipStart;
|
|
165
|
+
}
|
|
166
|
+
for (const line of linesToShow) {
|
|
167
|
+
const lineNum = String(oldLineNum).padStart(lineNumWidth, ' ');
|
|
168
|
+
output.push(` ${lineNum} ${line}`);
|
|
169
|
+
oldLineNum++;
|
|
170
|
+
newLineNum++;
|
|
171
|
+
}
|
|
172
|
+
// Add ellipsis if we skipped lines at end
|
|
173
|
+
if (skipEnd > 0) {
|
|
174
|
+
output.push(` ${''.padStart(lineNumWidth, ' ')} ...`);
|
|
175
|
+
// Update line numbers for the skipped trailing context
|
|
176
|
+
oldLineNum += skipEnd;
|
|
177
|
+
newLineNum += skipEnd;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
// Skip these context lines entirely
|
|
182
|
+
oldLineNum += raw.length;
|
|
183
|
+
newLineNum += raw.length;
|
|
184
|
+
}
|
|
185
|
+
lastWasChange = false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return { diff: output.join('\n'), firstChangedLine };
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Compute the diff for an edit operation without applying it.
|
|
192
|
+
* Used for preview rendering in the TUI before the tool executes.
|
|
193
|
+
*/
|
|
194
|
+
export async function computeEditDiff(path, oldText, newText, cwd) {
|
|
195
|
+
const absolutePath = resolveToCwd(path, cwd);
|
|
196
|
+
try {
|
|
197
|
+
// Check if file exists and is readable
|
|
198
|
+
try {
|
|
199
|
+
await access(absolutePath, constants.R_OK);
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return { error: `File not found: ${path}` };
|
|
203
|
+
}
|
|
204
|
+
// Read the file
|
|
205
|
+
const rawContent = await readFile(absolutePath, 'utf-8');
|
|
206
|
+
// Strip BOM before matching (LLM won't include invisible BOM in oldText)
|
|
207
|
+
const { text: content } = stripBom(rawContent);
|
|
208
|
+
const normalizedContent = normalizeToLF(content);
|
|
209
|
+
const normalizedOldText = normalizeToLF(oldText);
|
|
210
|
+
const normalizedNewText = normalizeToLF(newText);
|
|
211
|
+
// Find the old text using fuzzy matching (tries exact match first, then fuzzy)
|
|
212
|
+
const matchResult = fuzzyFindText(normalizedContent, normalizedOldText);
|
|
213
|
+
if (!matchResult.found) {
|
|
214
|
+
return {
|
|
215
|
+
error: `Could not find the exact text in ${path}. The old text must match exactly including all whitespace and newlines.`,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
// Count occurrences using fuzzy-normalized content for consistency
|
|
219
|
+
const fuzzyContent = normalizeForFuzzyMatch(normalizedContent);
|
|
220
|
+
const fuzzyOldText = normalizeForFuzzyMatch(normalizedOldText);
|
|
221
|
+
const occurrences = fuzzyContent.split(fuzzyOldText).length - 1;
|
|
222
|
+
if (occurrences > 1) {
|
|
223
|
+
return {
|
|
224
|
+
error: `Found ${occurrences} occurrences of the text in ${path}. The text must be unique. Please provide more context to make it unique.`,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
// Compute the new content using the matched position
|
|
228
|
+
// When fuzzy matching was used, contentForReplacement is the normalized version
|
|
229
|
+
const baseContent = matchResult.contentForReplacement;
|
|
230
|
+
const newContent = baseContent.substring(0, matchResult.index) +
|
|
231
|
+
normalizedNewText +
|
|
232
|
+
baseContent.substring(matchResult.index + matchResult.matchLength);
|
|
233
|
+
// Check if it would actually change anything
|
|
234
|
+
if (baseContent === newContent) {
|
|
235
|
+
return {
|
|
236
|
+
error: `No changes would be made to ${path}. The replacement produces identical content.`,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
// Generate the diff
|
|
240
|
+
return generateDiffString(baseContent, newContent);
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=edit-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit-diff.js","sourceRoot":"","sources":["../../src/tools/edit-diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type Static } from '@sinclair/typebox';
|
|
2
|
+
import type { AgentTool } from '@ank1015/llm-sdk';
|
|
3
|
+
declare const editSchema: import("@sinclair/typebox").TObject<{
|
|
4
|
+
path: import("@sinclair/typebox").TString;
|
|
5
|
+
oldText: import("@sinclair/typebox").TString;
|
|
6
|
+
newText: import("@sinclair/typebox").TString;
|
|
7
|
+
}>;
|
|
8
|
+
export type EditToolInput = Static<typeof editSchema>;
|
|
9
|
+
export interface EditToolDetails {
|
|
10
|
+
/** Unified diff of the changes made */
|
|
11
|
+
diff: string;
|
|
12
|
+
/** Line number of the first change in the new file (for editor navigation) */
|
|
13
|
+
firstChangedLine?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Pluggable operations for the edit tool.
|
|
17
|
+
* Override these to delegate file editing to remote systems (e.g., SSH).
|
|
18
|
+
*/
|
|
19
|
+
export interface EditOperations {
|
|
20
|
+
/** Read file contents as a Buffer */
|
|
21
|
+
readFile: (absolutePath: string) => Promise<Buffer>;
|
|
22
|
+
/** Write content to a file */
|
|
23
|
+
writeFile: (absolutePath: string, content: string) => Promise<void>;
|
|
24
|
+
/** Check if file is readable and writable (throw if not) */
|
|
25
|
+
access: (absolutePath: string) => Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
export interface EditToolOptions {
|
|
28
|
+
/** Custom operations for file editing. Default: local filesystem */
|
|
29
|
+
operations?: EditOperations;
|
|
30
|
+
}
|
|
31
|
+
export declare function createEditTool(cwd: string, options?: EditToolOptions): AgentTool<typeof editSchema>;
|
|
32
|
+
/** Default edit tool using process.cwd() - for backwards compatibility */
|
|
33
|
+
export declare const editTool: AgentTool<import("@sinclair/typebox").TObject<{
|
|
34
|
+
path: import("@sinclair/typebox").TString;
|
|
35
|
+
oldText: import("@sinclair/typebox").TString;
|
|
36
|
+
newText: import("@sinclair/typebox").TString;
|
|
37
|
+
}>, unknown>;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=edit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AAatD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,QAAA,MAAM,UAAU;;;;EAId,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC9B,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,qCAAqC;IACrC,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,8BAA8B;IAC9B,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,4DAA4D;IAC5D,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD;AAQD,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACxB,SAAS,CAAC,OAAO,UAAU,CAAC,CA6K9B;AAED,0EAA0E;AAC1E,eAAO,MAAM,QAAQ;;;;YAAgC,CAAC"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { constants } from 'fs';
|
|
2
|
+
import { access as fsAccess, readFile as fsReadFile, writeFile as fsWriteFile } from 'fs/promises';
|
|
3
|
+
import { Type } from '@sinclair/typebox';
|
|
4
|
+
import { detectLineEnding, fuzzyFindText, generateDiffString, normalizeForFuzzyMatch, normalizeToLF, restoreLineEndings, stripBom, } from './edit-diff.js';
|
|
5
|
+
import { resolveToCwd } from './path-utils.js';
|
|
6
|
+
const editSchema = Type.Object({
|
|
7
|
+
path: Type.String({ description: 'Path to the file to edit (relative or absolute)' }),
|
|
8
|
+
oldText: Type.String({ description: 'Exact text to find and replace (must match exactly)' }),
|
|
9
|
+
newText: Type.String({ description: 'New text to replace the old text with' }),
|
|
10
|
+
});
|
|
11
|
+
const defaultEditOperations = {
|
|
12
|
+
readFile: (path) => fsReadFile(path),
|
|
13
|
+
writeFile: (path, content) => fsWriteFile(path, content, 'utf-8'),
|
|
14
|
+
access: (path) => fsAccess(path, constants.R_OK | constants.W_OK),
|
|
15
|
+
};
|
|
16
|
+
export function createEditTool(cwd, options) {
|
|
17
|
+
const ops = options?.operations ?? defaultEditOperations;
|
|
18
|
+
return {
|
|
19
|
+
name: 'edit',
|
|
20
|
+
label: 'edit',
|
|
21
|
+
description: 'Edit a file by replacing exact text. The oldText must match exactly (including whitespace). Use this for precise, surgical edits.',
|
|
22
|
+
parameters: editSchema,
|
|
23
|
+
execute: async (_toolCallId, { path, oldText, newText }, signal) => {
|
|
24
|
+
const absolutePath = resolveToCwd(path, cwd);
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
// Check if already aborted
|
|
27
|
+
if (signal?.aborted) {
|
|
28
|
+
reject(new Error('Operation aborted'));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
let aborted = false;
|
|
32
|
+
// Set up abort handler
|
|
33
|
+
const onAbort = () => {
|
|
34
|
+
aborted = true;
|
|
35
|
+
reject(new Error('Operation aborted'));
|
|
36
|
+
};
|
|
37
|
+
if (signal) {
|
|
38
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
39
|
+
}
|
|
40
|
+
// Perform the edit operation
|
|
41
|
+
(async () => {
|
|
42
|
+
try {
|
|
43
|
+
// Check if file exists
|
|
44
|
+
try {
|
|
45
|
+
await ops.access(absolutePath);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
if (signal) {
|
|
49
|
+
signal.removeEventListener('abort', onAbort);
|
|
50
|
+
}
|
|
51
|
+
reject(new Error(`File not found: ${path}`));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// Check if aborted before reading
|
|
55
|
+
if (aborted) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
// Read the file
|
|
59
|
+
const buffer = await ops.readFile(absolutePath);
|
|
60
|
+
const rawContent = buffer.toString('utf-8');
|
|
61
|
+
// Check if aborted after reading
|
|
62
|
+
if (aborted) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
// Strip BOM before matching (LLM won't include invisible BOM in oldText)
|
|
66
|
+
const { bom, text: content } = stripBom(rawContent);
|
|
67
|
+
const originalEnding = detectLineEnding(content);
|
|
68
|
+
const normalizedContent = normalizeToLF(content);
|
|
69
|
+
const normalizedOldText = normalizeToLF(oldText);
|
|
70
|
+
const normalizedNewText = normalizeToLF(newText);
|
|
71
|
+
// Find the old text using fuzzy matching (tries exact match first, then fuzzy)
|
|
72
|
+
const matchResult = fuzzyFindText(normalizedContent, normalizedOldText);
|
|
73
|
+
if (!matchResult.found) {
|
|
74
|
+
if (signal) {
|
|
75
|
+
signal.removeEventListener('abort', onAbort);
|
|
76
|
+
}
|
|
77
|
+
reject(new Error(`Could not find the exact text in ${path}. The old text must match exactly including all whitespace and newlines.`));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// Count occurrences using fuzzy-normalized content for consistency
|
|
81
|
+
const fuzzyContent = normalizeForFuzzyMatch(normalizedContent);
|
|
82
|
+
const fuzzyOldText = normalizeForFuzzyMatch(normalizedOldText);
|
|
83
|
+
const occurrences = fuzzyContent.split(fuzzyOldText).length - 1;
|
|
84
|
+
if (occurrences > 1) {
|
|
85
|
+
if (signal) {
|
|
86
|
+
signal.removeEventListener('abort', onAbort);
|
|
87
|
+
}
|
|
88
|
+
reject(new Error(`Found ${occurrences} occurrences of the text in ${path}. The text must be unique. Please provide more context to make it unique.`));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// Check if aborted before writing
|
|
92
|
+
if (aborted) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// Perform replacement using the matched text position
|
|
96
|
+
// When fuzzy matching was used, contentForReplacement is the normalized version
|
|
97
|
+
const baseContent = matchResult.contentForReplacement;
|
|
98
|
+
const newContent = baseContent.substring(0, matchResult.index) +
|
|
99
|
+
normalizedNewText +
|
|
100
|
+
baseContent.substring(matchResult.index + matchResult.matchLength);
|
|
101
|
+
// Verify the replacement actually changed something
|
|
102
|
+
if (baseContent === newContent) {
|
|
103
|
+
if (signal) {
|
|
104
|
+
signal.removeEventListener('abort', onAbort);
|
|
105
|
+
}
|
|
106
|
+
reject(new Error(`No changes made to ${path}. The replacement produced identical content. This might indicate an issue with special characters or the text not existing as expected.`));
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const finalContent = bom + restoreLineEndings(newContent, originalEnding);
|
|
110
|
+
await ops.writeFile(absolutePath, finalContent);
|
|
111
|
+
// Check if aborted after writing
|
|
112
|
+
if (aborted) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// Clean up abort handler
|
|
116
|
+
if (signal) {
|
|
117
|
+
signal.removeEventListener('abort', onAbort);
|
|
118
|
+
}
|
|
119
|
+
const diffResult = generateDiffString(baseContent, newContent);
|
|
120
|
+
const editDetails = { diff: diffResult.diff };
|
|
121
|
+
if (diffResult.firstChangedLine !== undefined) {
|
|
122
|
+
editDetails.firstChangedLine = diffResult.firstChangedLine;
|
|
123
|
+
}
|
|
124
|
+
resolve({
|
|
125
|
+
content: [
|
|
126
|
+
{
|
|
127
|
+
type: 'text',
|
|
128
|
+
content: `Successfully replaced text in ${path}.`,
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
details: editDetails,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
// Clean up abort handler
|
|
136
|
+
if (signal) {
|
|
137
|
+
signal.removeEventListener('abort', onAbort);
|
|
138
|
+
}
|
|
139
|
+
if (!aborted) {
|
|
140
|
+
reject(error);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
})();
|
|
144
|
+
});
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/** Default edit tool using process.cwd() - for backwards compatibility */
|
|
149
|
+
export const editTool = createEditTool(process.cwd());
|
|
150
|
+
//# sourceMappingURL=edit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type Static } from '@sinclair/typebox';
|
|
2
|
+
import { type TruncationResult } from './truncate.js';
|
|
3
|
+
import type { AgentTool } from '@ank1015/llm-sdk';
|
|
4
|
+
declare const findSchema: import("@sinclair/typebox").TObject<{
|
|
5
|
+
pattern: import("@sinclair/typebox").TString;
|
|
6
|
+
path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
7
|
+
limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
8
|
+
}>;
|
|
9
|
+
export type FindToolInput = Static<typeof findSchema>;
|
|
10
|
+
export interface FindToolDetails {
|
|
11
|
+
truncation?: TruncationResult;
|
|
12
|
+
resultLimitReached?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Pluggable operations for the find tool.
|
|
16
|
+
* Override these to delegate file search to remote systems (e.g., SSH).
|
|
17
|
+
*/
|
|
18
|
+
export interface FindOperations {
|
|
19
|
+
/** Check if path exists */
|
|
20
|
+
exists: (absolutePath: string) => Promise<boolean> | boolean;
|
|
21
|
+
/** Find files matching glob pattern. Returns relative paths. */
|
|
22
|
+
glob: (pattern: string, cwd: string, options: {
|
|
23
|
+
ignore: string[];
|
|
24
|
+
limit: number;
|
|
25
|
+
}) => Promise<string[]> | string[];
|
|
26
|
+
}
|
|
27
|
+
export interface FindToolOptions {
|
|
28
|
+
/** Custom operations for find. Default: local filesystem + fd */
|
|
29
|
+
operations?: FindOperations;
|
|
30
|
+
}
|
|
31
|
+
export declare function createFindTool(cwd: string, options?: FindToolOptions): AgentTool<typeof findSchema>;
|
|
32
|
+
/** Default find tool using process.cwd() - for backwards compatibility */
|
|
33
|
+
export declare const findTool: AgentTool<import("@sinclair/typebox").TObject<{
|
|
34
|
+
pattern: import("@sinclair/typebox").TString;
|
|
35
|
+
path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
36
|
+
limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
37
|
+
}>, unknown>;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=find.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find.d.ts","sourceRoot":"","sources":["../../src/tools/find.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AAItD,OAAO,EAAiC,KAAK,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AAGnG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,QAAA,MAAM,UAAU;;;;EAQd,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAItD,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,2BAA2B;IAC3B,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAC7D,gEAAgE;IAChE,IAAI,EAAE,CACJ,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KACzC,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC;CACnC;AAUD,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACxB,SAAS,CAAC,OAAO,UAAU,CAAC,CA0N9B;AAED,0EAA0E;AAC1E,eAAO,MAAM,QAAQ;;;;YAAgC,CAAC"}
|