@nanocollective/nanocoder 1.19.0 → 1.19.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/assets/nanocoder-vscode.vsix +0 -0
- package/dist/ai-sdk-client-preparestep.spec.d.ts +2 -0
- package/dist/ai-sdk-client-preparestep.spec.d.ts.map +1 -0
- package/dist/ai-sdk-client-preparestep.spec.js +246 -0
- package/dist/ai-sdk-client-preparestep.spec.js.map +1 -0
- package/dist/ai-sdk-client.d.ts.map +1 -1
- package/dist/ai-sdk-client.js +108 -16
- package/dist/ai-sdk-client.js.map +1 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +6 -6
- package/dist/app.js.map +1 -1
- package/dist/components/development-mode-indicator.d.ts +15 -0
- package/dist/components/development-mode-indicator.d.ts.map +1 -0
- package/dist/components/development-mode-indicator.js +18 -0
- package/dist/components/development-mode-indicator.js.map +1 -0
- package/dist/components/user-input.d.ts +1 -1
- package/dist/components/user-input.d.ts.map +1 -1
- package/dist/components/user-input.js +7 -7
- package/dist/components/user-input.js.map +1 -1
- package/dist/hooks/useAppState.d.ts +12 -1
- package/dist/hooks/useAppState.d.ts.map +1 -1
- package/dist/hooks/useAppState.js.map +1 -1
- package/dist/hooks/useChatHandler.d.ts +2 -1
- package/dist/hooks/useChatHandler.d.ts.map +1 -1
- package/dist/hooks/useChatHandler.js +61 -58
- package/dist/hooks/useChatHandler.js.map +1 -1
- package/dist/hooks/useToolHandler.d.ts +1 -1
- package/dist/hooks/useToolHandler.d.ts.map +1 -1
- package/dist/hooks/useToolHandler.js +18 -48
- package/dist/hooks/useToolHandler.js.map +1 -1
- package/dist/hooks/useVSCodeServer.d.ts +1 -1
- package/dist/hooks/useVSCodeServer.d.ts.map +1 -1
- package/dist/hooks/useVSCodeServer.js +2 -2
- package/dist/hooks/useVSCodeServer.js.map +1 -1
- package/dist/tools/execute-function.spec.js +1 -49
- package/dist/tools/execute-function.spec.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +4 -8
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/needs-approval.spec.js +22 -83
- package/dist/tools/needs-approval.spec.js.map +1 -1
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +5 -3
- package/dist/tools/read-file.js.map +1 -1
- package/dist/tools/string-replace.d.ts +19 -0
- package/dist/tools/string-replace.d.ts.map +1 -0
- package/dist/tools/string-replace.js +279 -0
- package/dist/tools/string-replace.js.map +1 -0
- package/dist/tools/string-replace.spec.d.ts +2 -0
- package/dist/tools/string-replace.spec.d.ts.map +1 -0
- package/dist/tools/string-replace.spec.js +315 -0
- package/dist/tools/string-replace.spec.js.map +1 -0
- package/dist/tools/{create-file.d.ts → write-file.d.ts} +5 -5
- package/dist/tools/write-file.d.ts.map +1 -0
- package/dist/tools/{create-file.js → write-file.js} +34 -39
- package/dist/tools/write-file.js.map +1 -0
- package/dist/tools/write-file.spec.d.ts +2 -0
- package/dist/tools/write-file.spec.d.ts.map +1 -0
- package/dist/tools/write-file.spec.js +263 -0
- package/dist/tools/write-file.spec.js.map +1 -0
- package/dist/types/core.d.ts +1 -0
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/core.js.map +1 -1
- package/dist/utils/message-builder.d.ts +48 -0
- package/dist/utils/message-builder.d.ts.map +1 -0
- package/dist/utils/message-builder.js +88 -0
- package/dist/utils/message-builder.js.map +1 -0
- package/dist/utils/message-builder.spec.d.ts +2 -0
- package/dist/utils/message-builder.spec.d.ts.map +1 -0
- package/dist/utils/message-builder.spec.js +142 -0
- package/dist/utils/message-builder.spec.js.map +1 -0
- package/dist/vscode/protocol.d.ts +1 -1
- package/dist/vscode/protocol.d.ts.map +1 -1
- package/dist/vscode/protocol.spec.js +5 -5
- package/dist/vscode/protocol.spec.js.map +1 -1
- package/dist/vscode/vscode-server.d.ts +1 -1
- package/dist/vscode/vscode-server.d.ts.map +1 -1
- package/dist/vscode/vscode-server.js +2 -2
- package/dist/vscode/vscode-server.js.map +1 -1
- package/dist/vscode/vscode-server.spec.js +2 -2
- package/dist/vscode/vscode-server.spec.js.map +1 -1
- package/package.json +9 -1
- package/source/app/prompts/main-prompt.md +84 -530
- package/dist/tools/create-file.d.ts.map +0 -1
- package/dist/tools/create-file.js.map +0 -1
- package/dist/tools/delete-lines.d.ts +0 -19
- package/dist/tools/delete-lines.d.ts.map +0 -1
- package/dist/tools/delete-lines.js +0 -328
- package/dist/tools/delete-lines.js.map +0 -1
- package/dist/tools/insert-lines.d.ts +0 -19
- package/dist/tools/insert-lines.d.ts.map +0 -1
- package/dist/tools/insert-lines.js +0 -275
- package/dist/tools/insert-lines.js.map +0 -1
- package/dist/tools/replace-lines.d.ts +0 -20
- package/dist/tools/replace-lines.d.ts.map +0 -1
- package/dist/tools/replace-lines.js +0 -330
- package/dist/tools/replace-lines.js.map +0 -1
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { constants } from 'node:fs';
|
|
3
|
-
import { access, readFile, writeFile } from 'node:fs/promises';
|
|
4
|
-
import { resolve } from 'node:path';
|
|
5
|
-
import { highlight } from 'cli-highlight';
|
|
6
|
-
import { Box, Text } from 'ink';
|
|
7
|
-
import React from 'react';
|
|
8
|
-
import ToolMessage from '../components/tool-message.js';
|
|
9
|
-
import { getColors } from '../config/index.js';
|
|
10
|
-
import { getCurrentMode } from '../context/mode-context.js';
|
|
11
|
-
import { jsonSchema, tool } from '../types/core.js';
|
|
12
|
-
import { getLanguageFromExtension } from '../utils/programming-language-helper.js';
|
|
13
|
-
import { closeDiffInVSCode, isVSCodeConnected, sendFileChangeToVSCode, } from '../vscode/index.js';
|
|
14
|
-
const executeInsertLines = async (args) => {
|
|
15
|
-
const { path, line_number, content } = args;
|
|
16
|
-
// Validate line number
|
|
17
|
-
if (!line_number || line_number < 1) {
|
|
18
|
-
throw new Error(`Invalid line_number: ${line_number}. Must be a positive integer.`);
|
|
19
|
-
}
|
|
20
|
-
const absPath = resolve(path);
|
|
21
|
-
const fileContent = await readFile(absPath, 'utf-8');
|
|
22
|
-
const lines = fileContent.split('\n');
|
|
23
|
-
// Validate line number is within range
|
|
24
|
-
if (line_number > lines.length + 1) {
|
|
25
|
-
throw new Error(`Line number ${line_number} is out of range (file has ${lines.length} lines)`);
|
|
26
|
-
}
|
|
27
|
-
// Insert new lines
|
|
28
|
-
const insertLines = content.split('\n');
|
|
29
|
-
const newLines = [...lines];
|
|
30
|
-
newLines.splice(line_number - 1, 0, ...insertLines);
|
|
31
|
-
// Build new content
|
|
32
|
-
const newContent = newLines.join('\n');
|
|
33
|
-
// Write updated content
|
|
34
|
-
await writeFile(absPath, newContent, 'utf-8');
|
|
35
|
-
// Generate full file contents to show the model the current file state
|
|
36
|
-
let fileContext = '\n\nUpdated file contents:\n';
|
|
37
|
-
for (let i = 0; i < newLines.length; i++) {
|
|
38
|
-
const lineNumStr = String(i + 1).padStart(4, ' ');
|
|
39
|
-
const line = newLines[i] || '';
|
|
40
|
-
fileContext += `${lineNumStr}: ${line}\n`;
|
|
41
|
-
}
|
|
42
|
-
return `Successfully inserted ${insertLines.length} line${insertLines.length > 1 ? 's' : ''} at line ${line_number}.${fileContext}`;
|
|
43
|
-
};
|
|
44
|
-
const insertLinesCoreTool = tool({
|
|
45
|
-
description: 'Insert new lines at a specific line number in a file',
|
|
46
|
-
inputSchema: jsonSchema({
|
|
47
|
-
type: 'object',
|
|
48
|
-
properties: {
|
|
49
|
-
path: {
|
|
50
|
-
type: 'string',
|
|
51
|
-
description: 'The path to the file to edit.',
|
|
52
|
-
},
|
|
53
|
-
line_number: {
|
|
54
|
-
type: 'number',
|
|
55
|
-
description: 'The line number (1-based) where content should be inserted.',
|
|
56
|
-
},
|
|
57
|
-
content: {
|
|
58
|
-
type: 'string',
|
|
59
|
-
description: 'The content to insert. Can contain multiple lines separated by \\n.',
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
required: ['path', 'line_number', 'content'],
|
|
63
|
-
}),
|
|
64
|
-
// Medium risk: file write operation, requires approval except in auto-accept mode
|
|
65
|
-
needsApproval: () => {
|
|
66
|
-
const mode = getCurrentMode();
|
|
67
|
-
return mode !== 'auto-accept'; // true in normal/plan, false in auto-accept
|
|
68
|
-
},
|
|
69
|
-
execute: async (args, _options) => {
|
|
70
|
-
return await executeInsertLines(args);
|
|
71
|
-
},
|
|
72
|
-
});
|
|
73
|
-
const InsertLinesFormatter = React.memo(({ preview }) => {
|
|
74
|
-
return preview;
|
|
75
|
-
});
|
|
76
|
-
async function formatInsertLinesPreview(args, result, colors) {
|
|
77
|
-
const themeColors = colors || getColors();
|
|
78
|
-
const { path, line_number, content } = args;
|
|
79
|
-
const lineNumber = Number(line_number);
|
|
80
|
-
// Validate line number
|
|
81
|
-
if (!lineNumber || lineNumber < 1) {
|
|
82
|
-
throw new Error(`Invalid line_number: ${line_number}. Must be a positive integer.`);
|
|
83
|
-
}
|
|
84
|
-
const isResult = result !== undefined;
|
|
85
|
-
const displayTitle = isResult ? '✓' : '⚒';
|
|
86
|
-
try {
|
|
87
|
-
const fileContent = await readFile(resolve(path), 'utf-8');
|
|
88
|
-
const lines = fileContent.split('\n');
|
|
89
|
-
const ext = (path.split('.').pop() ?? '').toLowerCase();
|
|
90
|
-
const language = getLanguageFromExtension(ext ?? '');
|
|
91
|
-
// For results, show the actual file state after insertion
|
|
92
|
-
if (isResult) {
|
|
93
|
-
const insertLines = content.split('\n');
|
|
94
|
-
const contextLines = 5;
|
|
95
|
-
const showStart = Math.max(0, lineNumber - 1 - contextLines);
|
|
96
|
-
const showEnd = Math.min(lines.length - 1, lineNumber - 1 + insertLines.length + contextLines);
|
|
97
|
-
const contextElements = [];
|
|
98
|
-
for (let i = showStart; i <= showEnd; i++) {
|
|
99
|
-
const lineNumStr = String(i + 1).padStart(4, ' ');
|
|
100
|
-
const line = lines[i] || '';
|
|
101
|
-
const isInsertedLine = i + 1 >= lineNumber && i + 1 < lineNumber + insertLines.length;
|
|
102
|
-
let displayLine;
|
|
103
|
-
try {
|
|
104
|
-
displayLine = highlight(line, { language, theme: 'default' });
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
displayLine = line;
|
|
108
|
-
}
|
|
109
|
-
if (isInsertedLine) {
|
|
110
|
-
contextElements.push(_jsxs(Text, { backgroundColor: themeColors.diffAdded, color: themeColors.diffAddedText, wrap: "wrap", children: [lineNumStr, " + ", displayLine] }, `context-${i}`));
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
contextElements.push(_jsxs(Text, { color: themeColors.secondary, children: [lineNumStr, " ", displayLine] }, `context-${i}`));
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
const messageContent = (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: themeColors.tool, children: [displayTitle, " insert_lines"] }), _jsxs(Box, { children: [_jsx(Text, { color: themeColors.secondary, children: "Path: " }), _jsx(Text, { color: themeColors.primary, children: path })] }), _jsxs(Box, { children: [_jsx(Text, { color: themeColors.secondary, children: "Line: " }), _jsx(Text, { color: themeColors.white, children: lineNumber })] }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(Text, { color: themeColors.success, children: "\u2713 Insert completed successfully" }) }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: themeColors.secondary, children: "Context around insertion:" }), contextElements] })] }));
|
|
117
|
-
return _jsx(ToolMessage, { message: messageContent, hideBox: true });
|
|
118
|
-
}
|
|
119
|
-
// Preview mode - show what will be inserted
|
|
120
|
-
if (lineNumber > lines.length + 1) {
|
|
121
|
-
throw new Error(`Line number ${lineNumber} is out of range (file has ${lines.length} lines)`);
|
|
122
|
-
}
|
|
123
|
-
const insertLines = content.split('\n');
|
|
124
|
-
const contextLines = 3;
|
|
125
|
-
const showStart = Math.max(0, lineNumber - 1 - contextLines);
|
|
126
|
-
const showEnd = Math.min(lines.length - 1, lineNumber - 1 + contextLines);
|
|
127
|
-
const contextBefore = [];
|
|
128
|
-
const insertedLines = [];
|
|
129
|
-
const contextAfter = [];
|
|
130
|
-
// Show context before
|
|
131
|
-
for (let i = showStart; i < lineNumber - 1; i++) {
|
|
132
|
-
const lineNumStr = String(i + 1).padStart(4, ' ');
|
|
133
|
-
const line = lines[i] || '';
|
|
134
|
-
let displayLine;
|
|
135
|
-
try {
|
|
136
|
-
displayLine = highlight(line, { language, theme: 'default' });
|
|
137
|
-
}
|
|
138
|
-
catch {
|
|
139
|
-
displayLine = line;
|
|
140
|
-
}
|
|
141
|
-
contextBefore.push(_jsxs(Text, { color: themeColors.secondary, children: [lineNumStr, " ", displayLine] }, `before-${i}`));
|
|
142
|
-
}
|
|
143
|
-
// Show inserted lines
|
|
144
|
-
for (let i = 0; i < insertLines.length; i++) {
|
|
145
|
-
const lineNumStr = String(lineNumber + i).padStart(4, ' ');
|
|
146
|
-
const line = insertLines[i] ?? '';
|
|
147
|
-
let displayLine;
|
|
148
|
-
try {
|
|
149
|
-
displayLine = highlight(line, { language, theme: 'default' });
|
|
150
|
-
}
|
|
151
|
-
catch {
|
|
152
|
-
displayLine = line;
|
|
153
|
-
}
|
|
154
|
-
insertedLines.push(_jsxs(Text, { backgroundColor: themeColors.diffAdded, color: themeColors.diffAddedText, wrap: "wrap", children: [lineNumStr, " + ", displayLine] }, `insert-${i}`));
|
|
155
|
-
}
|
|
156
|
-
// Show context after
|
|
157
|
-
for (let i = lineNumber - 1; i <= showEnd; i++) {
|
|
158
|
-
const lineNumStr = String(i + insertLines.length + 1).padStart(4, ' ');
|
|
159
|
-
const line = lines[i] || '';
|
|
160
|
-
let displayLine;
|
|
161
|
-
try {
|
|
162
|
-
displayLine = highlight(line, { language, theme: 'default' });
|
|
163
|
-
}
|
|
164
|
-
catch {
|
|
165
|
-
displayLine = line;
|
|
166
|
-
}
|
|
167
|
-
contextAfter.push(_jsxs(Text, { color: themeColors.secondary, children: [lineNumStr, " ", displayLine] }, `after-${i}`));
|
|
168
|
-
}
|
|
169
|
-
const messageContent = (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: themeColors.tool, children: [displayTitle, " insert_lines"] }), _jsxs(Box, { children: [_jsx(Text, { color: themeColors.secondary, children: "Path: " }), _jsx(Text, { color: themeColors.primary, children: path })] }), _jsxs(Box, { children: [_jsx(Text, { color: themeColors.secondary, children: "Line: " }), _jsx(Text, { color: themeColors.white, children: lineNumber })] }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { color: themeColors.success, children: ["\u2713 Inserting ", insertLines.length, " line", insertLines.length > 1 ? 's' : ''] }), _jsxs(Box, { flexDirection: "column", children: [contextBefore, insertedLines, contextAfter] })] })] }));
|
|
170
|
-
return _jsx(ToolMessage, { message: messageContent, hideBox: true });
|
|
171
|
-
}
|
|
172
|
-
catch (error) {
|
|
173
|
-
const errorContent = (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: themeColors.tool, children: "\u2692 insert_lines" }), _jsxs(Box, { children: [_jsx(Text, { color: themeColors.secondary, children: "Path: " }), _jsx(Text, { color: themeColors.primary, children: path })] }), _jsxs(Box, { children: [_jsx(Text, { color: themeColors.error, children: "Error: " }), _jsx(Text, { color: themeColors.error, children: error instanceof Error ? error.message : String(error) })] })] }));
|
|
174
|
-
return _jsx(ToolMessage, { message: errorContent, hideBox: true });
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
// Track VS Code change IDs for cleanup
|
|
178
|
-
const vscodeChangeIds = new Map();
|
|
179
|
-
const insertLinesFormatter = async (args, result) => {
|
|
180
|
-
const colors = getColors();
|
|
181
|
-
const { path } = args;
|
|
182
|
-
const absPath = resolve(path);
|
|
183
|
-
// Send diff to VS Code during preview phase (before execution)
|
|
184
|
-
if (result === undefined && isVSCodeConnected()) {
|
|
185
|
-
const { line_number, content } = args;
|
|
186
|
-
try {
|
|
187
|
-
const fileContent = await readFile(absPath, 'utf-8');
|
|
188
|
-
const lines = fileContent.split('\n');
|
|
189
|
-
const lineNumber = Number(line_number);
|
|
190
|
-
// Build new content for diff preview
|
|
191
|
-
const insertLines = content.split('\n');
|
|
192
|
-
const newLines = [...lines];
|
|
193
|
-
newLines.splice(lineNumber - 1, 0, ...insertLines);
|
|
194
|
-
const newContent = newLines.join('\n');
|
|
195
|
-
const changeId = sendFileChangeToVSCode(absPath, fileContent, newContent, 'insert_lines', {
|
|
196
|
-
path,
|
|
197
|
-
line_number,
|
|
198
|
-
content,
|
|
199
|
-
});
|
|
200
|
-
if (changeId) {
|
|
201
|
-
vscodeChangeIds.set(absPath, changeId);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
catch {
|
|
205
|
-
// Silently ignore errors sending to VS Code
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
else if (result !== undefined && isVSCodeConnected()) {
|
|
209
|
-
// Tool was executed (confirmed or rejected), close the diff
|
|
210
|
-
const changeId = vscodeChangeIds.get(absPath);
|
|
211
|
-
if (changeId) {
|
|
212
|
-
closeDiffInVSCode(changeId);
|
|
213
|
-
vscodeChangeIds.delete(absPath);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
const preview = await formatInsertLinesPreview(args, result, colors);
|
|
217
|
-
return _jsx(InsertLinesFormatter, { preview: preview });
|
|
218
|
-
};
|
|
219
|
-
const insertLinesValidator = async (args) => {
|
|
220
|
-
const { path, line_number } = args;
|
|
221
|
-
// Check if file exists
|
|
222
|
-
const absPath = resolve(path);
|
|
223
|
-
try {
|
|
224
|
-
await access(absPath, constants.F_OK);
|
|
225
|
-
}
|
|
226
|
-
catch (error) {
|
|
227
|
-
if (error &&
|
|
228
|
-
typeof error === 'object' &&
|
|
229
|
-
'code' in error &&
|
|
230
|
-
error.code === 'ENOENT') {
|
|
231
|
-
return {
|
|
232
|
-
valid: false,
|
|
233
|
-
error: `⚒ File "${path}" does not exist`,
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
237
|
-
return {
|
|
238
|
-
valid: false,
|
|
239
|
-
error: `⚒ Cannot access file "${path}": ${errorMessage}`,
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
// Validate line number
|
|
243
|
-
if (!line_number || line_number < 1) {
|
|
244
|
-
return {
|
|
245
|
-
valid: false,
|
|
246
|
-
error: `⚒ Invalid line_number: ${line_number}. Must be a positive integer.`,
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
// Check line number is within valid range (can be 1 past end for append)
|
|
250
|
-
try {
|
|
251
|
-
const fileContent = await readFile(absPath, 'utf-8');
|
|
252
|
-
const lines = fileContent.split('\n');
|
|
253
|
-
if (line_number > lines.length + 1) {
|
|
254
|
-
return {
|
|
255
|
-
valid: false,
|
|
256
|
-
error: `⚒ Line number ${line_number} is out of range (file has ${lines.length} lines, can insert at line ${lines.length + 1})`,
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
catch (error) {
|
|
261
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
262
|
-
return {
|
|
263
|
-
valid: false,
|
|
264
|
-
error: `⚒ Error reading file: ${errorMessage}`,
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
return { valid: true };
|
|
268
|
-
};
|
|
269
|
-
export const insertLinesTool = {
|
|
270
|
-
name: 'insert_lines',
|
|
271
|
-
tool: insertLinesCoreTool,
|
|
272
|
-
formatter: insertLinesFormatter,
|
|
273
|
-
validator: insertLinesValidator,
|
|
274
|
-
};
|
|
275
|
-
//# sourceMappingURL=insert-lines.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"insert-lines.js","sourceRoot":"","sources":["../../source/tools/insert-lines.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
interface ReplaceLinesArgs {
|
|
3
|
-
path: string;
|
|
4
|
-
line_number: number;
|
|
5
|
-
end_line?: number;
|
|
6
|
-
content: string;
|
|
7
|
-
}
|
|
8
|
-
export declare const replaceLinesTool: {
|
|
9
|
-
name: "replace_lines";
|
|
10
|
-
tool: import("ai").Tool<ReplaceLinesArgs, string>;
|
|
11
|
-
formatter: (args: ReplaceLinesArgs, result?: string) => Promise<React.ReactElement>;
|
|
12
|
-
validator: (args: ReplaceLinesArgs) => Promise<{
|
|
13
|
-
valid: true;
|
|
14
|
-
} | {
|
|
15
|
-
valid: false;
|
|
16
|
-
error: string;
|
|
17
|
-
}>;
|
|
18
|
-
};
|
|
19
|
-
export {};
|
|
20
|
-
//# sourceMappingURL=replace-lines.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"replace-lines.d.ts","sourceRoot":"","sources":["../../source/tools/replace-lines.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,MAAM,OAAO,CAAC;AAa1B,UAAU,gBAAgB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CAChB;AAygBD,eAAO,MAAM,gBAAgB;;;sBA7HtB,gBAAgB,WACb,MAAM,KACb,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC;sBAsDvB,gBAAgB,KACpB,OAAO,CAAC;QAAC,KAAK,EAAE,IAAI,CAAA;KAAC,GAAG;QAAC,KAAK,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC;CAyExD,CAAC"}
|
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { constants } from 'node:fs';
|
|
3
|
-
import { access, readFile, writeFile } from 'node:fs/promises';
|
|
4
|
-
import { resolve } from 'node:path';
|
|
5
|
-
import { highlight } from 'cli-highlight';
|
|
6
|
-
import { Box, Text } from 'ink';
|
|
7
|
-
import React from 'react';
|
|
8
|
-
import ToolMessage from '../components/tool-message.js';
|
|
9
|
-
import { getColors } from '../config/index.js';
|
|
10
|
-
import { getCurrentMode } from '../context/mode-context.js';
|
|
11
|
-
import { jsonSchema, tool } from '../types/core.js';
|
|
12
|
-
import { getLanguageFromExtension } from '../utils/programming-language-helper.js';
|
|
13
|
-
import { closeDiffInVSCode, isVSCodeConnected, sendFileChangeToVSCode, } from '../vscode/index.js';
|
|
14
|
-
const executeReplaceLines = async (args) => {
|
|
15
|
-
const { path, line_number, end_line, content } = args;
|
|
16
|
-
// Validate line numbers
|
|
17
|
-
if (!line_number || line_number < 1) {
|
|
18
|
-
throw new Error(`Invalid line_number: ${line_number}. Must be a positive integer.`);
|
|
19
|
-
}
|
|
20
|
-
const endLine = end_line ?? line_number;
|
|
21
|
-
if (endLine < line_number) {
|
|
22
|
-
throw new Error(`end_line (${endLine}) cannot be less than line_number (${line_number}).`);
|
|
23
|
-
}
|
|
24
|
-
const absPath = resolve(path);
|
|
25
|
-
const fileContent = await readFile(absPath, 'utf-8');
|
|
26
|
-
const lines = fileContent.split('\n');
|
|
27
|
-
// Validate line range is within file bounds
|
|
28
|
-
if (line_number > lines.length) {
|
|
29
|
-
throw new Error(`Line number ${line_number} is out of range (file has ${lines.length} lines)`);
|
|
30
|
-
}
|
|
31
|
-
if (endLine > lines.length) {
|
|
32
|
-
throw new Error(`End line ${endLine} is out of range (file has ${lines.length} lines)`);
|
|
33
|
-
}
|
|
34
|
-
// Replace lines
|
|
35
|
-
const replaceLines = content.split('\n');
|
|
36
|
-
const linesToRemove = endLine - line_number + 1;
|
|
37
|
-
const newLines = [...lines];
|
|
38
|
-
newLines.splice(line_number - 1, linesToRemove, ...replaceLines);
|
|
39
|
-
// Build the new content
|
|
40
|
-
const newContent = newLines.join('\n');
|
|
41
|
-
// Write updated content
|
|
42
|
-
await writeFile(absPath, newContent, 'utf-8');
|
|
43
|
-
// Generate full file contents to show the model the current file state
|
|
44
|
-
let fileContext = '\n\nUpdated file contents:\n';
|
|
45
|
-
for (let i = 0; i < newLines.length; i++) {
|
|
46
|
-
const lineNumStr = String(i + 1).padStart(4, ' ');
|
|
47
|
-
const line = newLines[i] || '';
|
|
48
|
-
fileContext += `${lineNumStr}: ${line}\n`;
|
|
49
|
-
}
|
|
50
|
-
const rangeDesc = line_number === endLine
|
|
51
|
-
? `line ${line_number}`
|
|
52
|
-
: `lines ${line_number}-${endLine}`;
|
|
53
|
-
return `Successfully replaced ${rangeDesc} with ${replaceLines.length} line${replaceLines.length > 1 ? 's' : ''}.${fileContext}`;
|
|
54
|
-
};
|
|
55
|
-
const replaceLinesCoreTool = tool({
|
|
56
|
-
description: 'Replace lines in a file (single line or range) with new content',
|
|
57
|
-
inputSchema: jsonSchema({
|
|
58
|
-
type: 'object',
|
|
59
|
-
properties: {
|
|
60
|
-
path: {
|
|
61
|
-
type: 'string',
|
|
62
|
-
description: 'The path to the file to edit.',
|
|
63
|
-
},
|
|
64
|
-
line_number: {
|
|
65
|
-
type: 'number',
|
|
66
|
-
description: 'The starting line number (1-based) to replace.',
|
|
67
|
-
},
|
|
68
|
-
end_line: {
|
|
69
|
-
type: 'number',
|
|
70
|
-
description: 'The ending line number (1-based) to replace. If omitted, only line_number is replaced.',
|
|
71
|
-
},
|
|
72
|
-
content: {
|
|
73
|
-
type: 'string',
|
|
74
|
-
description: 'The replacement content. Can contain multiple lines separated by \\n.',
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
required: ['path', 'line_number', 'content'],
|
|
78
|
-
}),
|
|
79
|
-
// Medium risk: file write operation, requires approval except in auto-accept mode
|
|
80
|
-
needsApproval: () => {
|
|
81
|
-
const mode = getCurrentMode();
|
|
82
|
-
return mode !== 'auto-accept'; // true in normal/plan, false in auto-accept
|
|
83
|
-
},
|
|
84
|
-
execute: async (args, _options) => {
|
|
85
|
-
return await executeReplaceLines(args);
|
|
86
|
-
},
|
|
87
|
-
});
|
|
88
|
-
const ReplaceLinesFormatter = React.memo(({ preview }) => {
|
|
89
|
-
return preview;
|
|
90
|
-
});
|
|
91
|
-
async function formatReplaceLinesPreview(args, result, colors) {
|
|
92
|
-
const themeColors = colors || getColors();
|
|
93
|
-
const { path, line_number, end_line, content } = args;
|
|
94
|
-
const lineNumber = Number(line_number);
|
|
95
|
-
const endLine = Number(end_line) || lineNumber;
|
|
96
|
-
// Validate line numbers
|
|
97
|
-
if (!lineNumber || lineNumber < 1) {
|
|
98
|
-
throw new Error(`Invalid line_number: ${line_number}. Must be a positive integer.`);
|
|
99
|
-
}
|
|
100
|
-
if (endLine < lineNumber) {
|
|
101
|
-
throw new Error(`end_line (${endLine}) cannot be less than line_number (${lineNumber}).`);
|
|
102
|
-
}
|
|
103
|
-
const isResult = result !== undefined;
|
|
104
|
-
const displayTitle = isResult ? '✓' : '⚒';
|
|
105
|
-
try {
|
|
106
|
-
const fileContent = await readFile(resolve(path), 'utf-8');
|
|
107
|
-
const lines = fileContent.split('\n');
|
|
108
|
-
const ext = String(path).split('.').pop()?.toLowerCase();
|
|
109
|
-
const language = getLanguageFromExtension(ext ?? '');
|
|
110
|
-
// For results, show the actual file state after replacement
|
|
111
|
-
if (isResult) {
|
|
112
|
-
const replaceLines = String(content).split('\n');
|
|
113
|
-
const contextLines = 5;
|
|
114
|
-
const showStart = Math.max(0, lineNumber - 1 - contextLines);
|
|
115
|
-
const showEnd = Math.min(lines.length - 1, lineNumber - 1 + replaceLines.length + contextLines);
|
|
116
|
-
const contextElements = [];
|
|
117
|
-
for (let i = showStart; i <= showEnd; i++) {
|
|
118
|
-
const lineNumStr = String(i + 1).padStart(4, ' ');
|
|
119
|
-
const line = lines[i] || '';
|
|
120
|
-
const isReplacedLine = i + 1 >= lineNumber && i + 1 < lineNumber + replaceLines.length;
|
|
121
|
-
let displayLine;
|
|
122
|
-
try {
|
|
123
|
-
displayLine = highlight(line, { language, theme: 'default' });
|
|
124
|
-
}
|
|
125
|
-
catch {
|
|
126
|
-
displayLine = line;
|
|
127
|
-
}
|
|
128
|
-
if (isReplacedLine) {
|
|
129
|
-
contextElements.push(_jsxs(Text, { backgroundColor: themeColors.diffAdded, color: themeColors.diffAddedText, wrap: "wrap", children: [lineNumStr, " + ", displayLine] }, `context-${i}`));
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
contextElements.push(_jsxs(Text, { color: themeColors.secondary, children: [lineNumStr, " ", displayLine] }, `context-${i}`));
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
const rangeDesc = lineNumber === endLine
|
|
136
|
-
? `line ${lineNumber}`
|
|
137
|
-
: `lines ${lineNumber}-${endLine}`;
|
|
138
|
-
const messageContent = (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: themeColors.tool, children: [displayTitle, " replace_lines"] }), _jsxs(Box, { children: [_jsx(Text, { color: themeColors.secondary, children: "Path: " }), _jsx(Text, { color: themeColors.primary, children: path })] }), _jsxs(Box, { children: [_jsx(Text, { color: themeColors.secondary, children: "Range: " }), _jsx(Text, { color: themeColors.white, children: rangeDesc })] }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(Text, { color: themeColors.success, children: "\u2713 Replace completed successfully" }) }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: themeColors.secondary, children: "Context around replacement:" }), contextElements] })] }));
|
|
139
|
-
return _jsx(ToolMessage, { message: messageContent, hideBox: true });
|
|
140
|
-
}
|
|
141
|
-
// Preview mode - show what will be replaced
|
|
142
|
-
if (lineNumber > lines.length || endLine > lines.length) {
|
|
143
|
-
const maxLine = Math.max(lineNumber, endLine);
|
|
144
|
-
throw new Error(`Line ${maxLine} is out of range (file has ${lines.length} lines)`);
|
|
145
|
-
}
|
|
146
|
-
const replaceLines = String(content).split('\n');
|
|
147
|
-
const linesToRemove = endLine - lineNumber + 1;
|
|
148
|
-
const contextLines = 3;
|
|
149
|
-
const showStart = Math.max(0, lineNumber - 1 - contextLines);
|
|
150
|
-
const showEnd = Math.min(lines.length - 1, endLine - 1 + contextLines);
|
|
151
|
-
const contextBefore = [];
|
|
152
|
-
const removedLines = [];
|
|
153
|
-
const addedLines = [];
|
|
154
|
-
const contextAfter = [];
|
|
155
|
-
// Show context before
|
|
156
|
-
for (let i = showStart; i < lineNumber - 1; i++) {
|
|
157
|
-
const lineNumStr = String(i + 1).padStart(4, ' ');
|
|
158
|
-
const line = lines[i] || '';
|
|
159
|
-
let displayLine;
|
|
160
|
-
try {
|
|
161
|
-
displayLine = highlight(line, { language, theme: 'default' });
|
|
162
|
-
}
|
|
163
|
-
catch {
|
|
164
|
-
displayLine = line;
|
|
165
|
-
}
|
|
166
|
-
contextBefore.push(_jsxs(Text, { color: themeColors.secondary, children: [lineNumStr, " ", displayLine] }, `before-${i}`));
|
|
167
|
-
}
|
|
168
|
-
// Show removed lines
|
|
169
|
-
for (let i = lineNumber - 1; i < endLine; i++) {
|
|
170
|
-
const lineNumStr = String(i + 1).padStart(4, ' ');
|
|
171
|
-
const line = lines[i] || '';
|
|
172
|
-
let displayLine;
|
|
173
|
-
try {
|
|
174
|
-
displayLine = highlight(line, { language, theme: 'default' });
|
|
175
|
-
}
|
|
176
|
-
catch {
|
|
177
|
-
displayLine = line;
|
|
178
|
-
}
|
|
179
|
-
removedLines.push(_jsxs(Text, { backgroundColor: themeColors.diffRemoved, color: themeColors.diffRemovedText, wrap: "wrap", children: [lineNumStr, " - ", displayLine] }, `remove-${i}`));
|
|
180
|
-
}
|
|
181
|
-
// Show added lines
|
|
182
|
-
for (let i = 0; i < replaceLines.length; i++) {
|
|
183
|
-
const lineNumStr = String(lineNumber + i).padStart(4, ' ');
|
|
184
|
-
const line = String(replaceLines[i] ?? '');
|
|
185
|
-
let displayLine;
|
|
186
|
-
try {
|
|
187
|
-
displayLine = highlight(line, { language, theme: 'default' });
|
|
188
|
-
}
|
|
189
|
-
catch {
|
|
190
|
-
displayLine = line;
|
|
191
|
-
}
|
|
192
|
-
addedLines.push(_jsxs(Text, { backgroundColor: themeColors.diffAdded, color: themeColors.diffAddedText, wrap: "wrap", children: [lineNumStr, " + ", displayLine] }, `add-${i}`));
|
|
193
|
-
}
|
|
194
|
-
// Show context after
|
|
195
|
-
for (let i = endLine; i <= showEnd; i++) {
|
|
196
|
-
const lineNumStr = String(i + replaceLines.length - linesToRemove + 1).padStart(4, ' ');
|
|
197
|
-
const line = lines[i] || '';
|
|
198
|
-
let displayLine;
|
|
199
|
-
try {
|
|
200
|
-
displayLine = highlight(line, { language, theme: 'default' });
|
|
201
|
-
}
|
|
202
|
-
catch {
|
|
203
|
-
displayLine = line;
|
|
204
|
-
}
|
|
205
|
-
contextAfter.push(_jsxs(Text, { color: themeColors.secondary, children: [lineNumStr, " ", displayLine] }, `after-${i}`));
|
|
206
|
-
}
|
|
207
|
-
const rangeDesc = lineNumber === endLine
|
|
208
|
-
? `line ${lineNumber}`
|
|
209
|
-
: `lines ${lineNumber}-${endLine}`;
|
|
210
|
-
const messageContent = (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: themeColors.tool, children: [displayTitle, " replace_lines"] }), _jsxs(Box, { children: [_jsx(Text, { color: themeColors.secondary, children: "Path: " }), _jsx(Text, { color: themeColors.primary, children: path })] }), _jsxs(Box, { children: [_jsx(Text, { color: themeColors.secondary, children: "Range: " }), _jsx(Text, { color: themeColors.white, children: rangeDesc })] }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { color: themeColors.success, children: ["\u2713 Replacing ", linesToRemove, " line", linesToRemove > 1 ? 's' : '', " with", ' ', replaceLines.length, " line", replaceLines.length > 1 ? 's' : ''] }), _jsxs(Box, { flexDirection: "column", children: [contextBefore, removedLines, addedLines, contextAfter] })] })] }));
|
|
211
|
-
return _jsx(ToolMessage, { message: messageContent, hideBox: true });
|
|
212
|
-
}
|
|
213
|
-
catch (error) {
|
|
214
|
-
const errorContent = (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: themeColors.tool, children: "\u2692 replace_lines" }), _jsxs(Box, { children: [_jsx(Text, { color: themeColors.secondary, children: "Path: " }), _jsx(Text, { color: themeColors.primary, children: path })] }), _jsxs(Box, { children: [_jsx(Text, { color: themeColors.error, children: "Error: " }), _jsx(Text, { color: themeColors.error, children: error instanceof Error ? error.message : String(error) })] })] }));
|
|
215
|
-
return _jsx(ToolMessage, { message: errorContent, hideBox: true });
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
// Track VS Code change IDs for cleanup
|
|
219
|
-
const vscodeChangeIds = new Map();
|
|
220
|
-
const replaceLinesFormatter = async (args, result) => {
|
|
221
|
-
const colors = getColors();
|
|
222
|
-
const { path } = args;
|
|
223
|
-
const absPath = resolve(path);
|
|
224
|
-
// Send diff to VS Code during preview phase (before execution)
|
|
225
|
-
// Only send when result is undefined (preview mode, not after execution)
|
|
226
|
-
if (result === undefined && isVSCodeConnected()) {
|
|
227
|
-
const { line_number, end_line, content } = args;
|
|
228
|
-
try {
|
|
229
|
-
const fileContent = await readFile(absPath, 'utf-8');
|
|
230
|
-
const lines = fileContent.split('\n');
|
|
231
|
-
const lineNumber = Number(line_number);
|
|
232
|
-
const endLine = Number(end_line) || lineNumber;
|
|
233
|
-
// Build new content for diff preview
|
|
234
|
-
const replaceLines = content.split('\n');
|
|
235
|
-
const linesToRemove = endLine - lineNumber + 1;
|
|
236
|
-
const newLines = [...lines];
|
|
237
|
-
newLines.splice(lineNumber - 1, linesToRemove, ...replaceLines);
|
|
238
|
-
const newContent = newLines.join('\n');
|
|
239
|
-
const changeId = sendFileChangeToVSCode(absPath, fileContent, newContent, 'replace_lines', {
|
|
240
|
-
path,
|
|
241
|
-
line_number,
|
|
242
|
-
end_line: endLine,
|
|
243
|
-
content,
|
|
244
|
-
});
|
|
245
|
-
if (changeId) {
|
|
246
|
-
vscodeChangeIds.set(absPath, changeId);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
catch {
|
|
250
|
-
// Silently ignore errors sending to VS Code
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
else if (result !== undefined && isVSCodeConnected()) {
|
|
254
|
-
// Tool was executed (confirmed or rejected), close the diff
|
|
255
|
-
const changeId = vscodeChangeIds.get(absPath);
|
|
256
|
-
if (changeId) {
|
|
257
|
-
closeDiffInVSCode(changeId);
|
|
258
|
-
vscodeChangeIds.delete(absPath);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
const preview = await formatReplaceLinesPreview(args, result, colors);
|
|
262
|
-
return _jsx(ReplaceLinesFormatter, { preview: preview });
|
|
263
|
-
};
|
|
264
|
-
const replaceLinesValidator = async (args) => {
|
|
265
|
-
const { path, line_number, end_line } = args;
|
|
266
|
-
// Check if file exists
|
|
267
|
-
const absPath = resolve(path);
|
|
268
|
-
try {
|
|
269
|
-
await access(absPath, constants.F_OK);
|
|
270
|
-
}
|
|
271
|
-
catch (error) {
|
|
272
|
-
const nodeError = error;
|
|
273
|
-
if (nodeError.code === 'ENOENT') {
|
|
274
|
-
return {
|
|
275
|
-
valid: false,
|
|
276
|
-
error: `⚒ File "${path}" does not exist`,
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
return {
|
|
280
|
-
valid: false,
|
|
281
|
-
error: `⚒ Cannot access file "${path}": ${nodeError.message ?? String(error)}`,
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
// Validate line numbers
|
|
285
|
-
if (!line_number || line_number < 1) {
|
|
286
|
-
return {
|
|
287
|
-
valid: false,
|
|
288
|
-
error: `⚒ Invalid line_number: ${line_number}. Must be a positive integer.`,
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
const endLine = end_line ?? line_number;
|
|
292
|
-
if (endLine < line_number) {
|
|
293
|
-
return {
|
|
294
|
-
valid: false,
|
|
295
|
-
error: `⚒ end_line (${endLine}) cannot be less than line_number (${line_number}).`,
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
// Check line numbers are within file bounds
|
|
299
|
-
try {
|
|
300
|
-
const fileContent = await readFile(absPath, 'utf-8');
|
|
301
|
-
const lines = fileContent.split('\n');
|
|
302
|
-
if (line_number > lines.length) {
|
|
303
|
-
return {
|
|
304
|
-
valid: false,
|
|
305
|
-
error: `⚒ Line number ${line_number} is out of range (file has ${lines.length} lines)`,
|
|
306
|
-
};
|
|
307
|
-
}
|
|
308
|
-
if (endLine > lines.length) {
|
|
309
|
-
return {
|
|
310
|
-
valid: false,
|
|
311
|
-
error: `⚒ End line ${endLine} is out of range (file has ${lines.length} lines)`,
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
catch (error) {
|
|
316
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
317
|
-
return {
|
|
318
|
-
valid: false,
|
|
319
|
-
error: `⚒ Error reading file: ${errorMessage}`,
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
return { valid: true };
|
|
323
|
-
};
|
|
324
|
-
export const replaceLinesTool = {
|
|
325
|
-
name: 'replace_lines',
|
|
326
|
-
tool: replaceLinesCoreTool,
|
|
327
|
-
formatter: replaceLinesFormatter,
|
|
328
|
-
validator: replaceLinesValidator,
|
|
329
|
-
};
|
|
330
|
-
//# sourceMappingURL=replace-lines.js.map
|