@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.
Files changed (97) hide show
  1. package/assets/nanocoder-vscode.vsix +0 -0
  2. package/dist/ai-sdk-client-preparestep.spec.d.ts +2 -0
  3. package/dist/ai-sdk-client-preparestep.spec.d.ts.map +1 -0
  4. package/dist/ai-sdk-client-preparestep.spec.js +246 -0
  5. package/dist/ai-sdk-client-preparestep.spec.js.map +1 -0
  6. package/dist/ai-sdk-client.d.ts.map +1 -1
  7. package/dist/ai-sdk-client.js +108 -16
  8. package/dist/ai-sdk-client.js.map +1 -1
  9. package/dist/app.d.ts.map +1 -1
  10. package/dist/app.js +6 -6
  11. package/dist/app.js.map +1 -1
  12. package/dist/components/development-mode-indicator.d.ts +15 -0
  13. package/dist/components/development-mode-indicator.d.ts.map +1 -0
  14. package/dist/components/development-mode-indicator.js +18 -0
  15. package/dist/components/development-mode-indicator.js.map +1 -0
  16. package/dist/components/user-input.d.ts +1 -1
  17. package/dist/components/user-input.d.ts.map +1 -1
  18. package/dist/components/user-input.js +7 -7
  19. package/dist/components/user-input.js.map +1 -1
  20. package/dist/hooks/useAppState.d.ts +12 -1
  21. package/dist/hooks/useAppState.d.ts.map +1 -1
  22. package/dist/hooks/useAppState.js.map +1 -1
  23. package/dist/hooks/useChatHandler.d.ts +2 -1
  24. package/dist/hooks/useChatHandler.d.ts.map +1 -1
  25. package/dist/hooks/useChatHandler.js +61 -58
  26. package/dist/hooks/useChatHandler.js.map +1 -1
  27. package/dist/hooks/useToolHandler.d.ts +1 -1
  28. package/dist/hooks/useToolHandler.d.ts.map +1 -1
  29. package/dist/hooks/useToolHandler.js +18 -48
  30. package/dist/hooks/useToolHandler.js.map +1 -1
  31. package/dist/hooks/useVSCodeServer.d.ts +1 -1
  32. package/dist/hooks/useVSCodeServer.d.ts.map +1 -1
  33. package/dist/hooks/useVSCodeServer.js +2 -2
  34. package/dist/hooks/useVSCodeServer.js.map +1 -1
  35. package/dist/tools/execute-function.spec.js +1 -49
  36. package/dist/tools/execute-function.spec.js.map +1 -1
  37. package/dist/tools/index.d.ts.map +1 -1
  38. package/dist/tools/index.js +4 -8
  39. package/dist/tools/index.js.map +1 -1
  40. package/dist/tools/needs-approval.spec.js +22 -83
  41. package/dist/tools/needs-approval.spec.js.map +1 -1
  42. package/dist/tools/read-file.d.ts.map +1 -1
  43. package/dist/tools/read-file.js +5 -3
  44. package/dist/tools/read-file.js.map +1 -1
  45. package/dist/tools/string-replace.d.ts +19 -0
  46. package/dist/tools/string-replace.d.ts.map +1 -0
  47. package/dist/tools/string-replace.js +279 -0
  48. package/dist/tools/string-replace.js.map +1 -0
  49. package/dist/tools/string-replace.spec.d.ts +2 -0
  50. package/dist/tools/string-replace.spec.d.ts.map +1 -0
  51. package/dist/tools/string-replace.spec.js +315 -0
  52. package/dist/tools/string-replace.spec.js.map +1 -0
  53. package/dist/tools/{create-file.d.ts → write-file.d.ts} +5 -5
  54. package/dist/tools/write-file.d.ts.map +1 -0
  55. package/dist/tools/{create-file.js → write-file.js} +34 -39
  56. package/dist/tools/write-file.js.map +1 -0
  57. package/dist/tools/write-file.spec.d.ts +2 -0
  58. package/dist/tools/write-file.spec.d.ts.map +1 -0
  59. package/dist/tools/write-file.spec.js +263 -0
  60. package/dist/tools/write-file.spec.js.map +1 -0
  61. package/dist/types/core.d.ts +1 -0
  62. package/dist/types/core.d.ts.map +1 -1
  63. package/dist/types/core.js.map +1 -1
  64. package/dist/utils/message-builder.d.ts +48 -0
  65. package/dist/utils/message-builder.d.ts.map +1 -0
  66. package/dist/utils/message-builder.js +88 -0
  67. package/dist/utils/message-builder.js.map +1 -0
  68. package/dist/utils/message-builder.spec.d.ts +2 -0
  69. package/dist/utils/message-builder.spec.d.ts.map +1 -0
  70. package/dist/utils/message-builder.spec.js +142 -0
  71. package/dist/utils/message-builder.spec.js.map +1 -0
  72. package/dist/vscode/protocol.d.ts +1 -1
  73. package/dist/vscode/protocol.d.ts.map +1 -1
  74. package/dist/vscode/protocol.spec.js +5 -5
  75. package/dist/vscode/protocol.spec.js.map +1 -1
  76. package/dist/vscode/vscode-server.d.ts +1 -1
  77. package/dist/vscode/vscode-server.d.ts.map +1 -1
  78. package/dist/vscode/vscode-server.js +2 -2
  79. package/dist/vscode/vscode-server.js.map +1 -1
  80. package/dist/vscode/vscode-server.spec.js +2 -2
  81. package/dist/vscode/vscode-server.spec.js.map +1 -1
  82. package/package.json +9 -1
  83. package/source/app/prompts/main-prompt.md +84 -530
  84. package/dist/tools/create-file.d.ts.map +0 -1
  85. package/dist/tools/create-file.js.map +0 -1
  86. package/dist/tools/delete-lines.d.ts +0 -19
  87. package/dist/tools/delete-lines.d.ts.map +0 -1
  88. package/dist/tools/delete-lines.js +0 -328
  89. package/dist/tools/delete-lines.js.map +0 -1
  90. package/dist/tools/insert-lines.d.ts +0 -19
  91. package/dist/tools/insert-lines.d.ts.map +0 -1
  92. package/dist/tools/insert-lines.js +0 -275
  93. package/dist/tools/insert-lines.js.map +0 -1
  94. package/dist/tools/replace-lines.d.ts +0 -20
  95. package/dist/tools/replace-lines.d.ts.map +0 -1
  96. package/dist/tools/replace-lines.js +0 -330
  97. package/dist/tools/replace-lines.js.map +0 -1
@@ -0,0 +1,315 @@
1
+ import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import test from 'ava';
5
+ import { setCurrentMode } from '../context/mode-context.js';
6
+ import { stringReplaceTool } from './string-replace.js';
7
+ // ============================================================================
8
+ // Test Helpers
9
+ // ============================================================================
10
+ let testDir;
11
+ // Create a temporary directory before each test
12
+ test.beforeEach(async () => {
13
+ testDir = await mkdtemp(join(tmpdir(), 'string-replace-test-'));
14
+ });
15
+ // Clean up temporary directory after each test
16
+ test.afterEach(async () => {
17
+ if (testDir) {
18
+ await rm(testDir, { recursive: true, force: true });
19
+ }
20
+ });
21
+ // Helper to execute the string_replace tool
22
+ async function executeStringReplace(args) {
23
+ // biome-ignore lint/suspicious/noExplicitAny: Tool internals require any
24
+ return await stringReplaceTool.tool.execute(args, {
25
+ toolCallId: 'test',
26
+ messages: [],
27
+ });
28
+ }
29
+ // Helper to create a test file
30
+ async function createTestFile(filename, content) {
31
+ const filePath = join(testDir, filename);
32
+ await writeFile(filePath, content, 'utf-8');
33
+ return filePath;
34
+ }
35
+ // ============================================================================
36
+ // Approval Tests
37
+ // ============================================================================
38
+ test('string_replace requires approval in normal mode', async (t) => {
39
+ setCurrentMode('normal');
40
+ const needsApproval = stringReplaceTool.tool.needsApproval;
41
+ if (typeof needsApproval === 'function') {
42
+ const result = await needsApproval({
43
+ path: 'test.txt',
44
+ old_str: 'old',
45
+ new_str: 'new',
46
+ }, { toolCallId: 'test', messages: [] });
47
+ t.true(result);
48
+ }
49
+ else {
50
+ t.is(needsApproval, true);
51
+ }
52
+ });
53
+ test('string_replace does NOT require approval in auto-accept mode', async (t) => {
54
+ setCurrentMode('auto-accept');
55
+ const needsApproval = stringReplaceTool.tool.needsApproval;
56
+ if (typeof needsApproval === 'function') {
57
+ const result = await needsApproval({
58
+ path: 'test.txt',
59
+ old_str: 'old',
60
+ new_str: 'new',
61
+ }, { toolCallId: 'test', messages: [] });
62
+ t.false(result);
63
+ }
64
+ else {
65
+ t.is(needsApproval, false);
66
+ }
67
+ });
68
+ test('string_replace requires approval in plan mode', async (t) => {
69
+ setCurrentMode('plan');
70
+ const needsApproval = stringReplaceTool.tool.needsApproval;
71
+ if (typeof needsApproval === 'function') {
72
+ const result = await needsApproval({
73
+ path: 'test.txt',
74
+ old_str: 'old',
75
+ new_str: 'new',
76
+ }, { toolCallId: 'test', messages: [] });
77
+ t.true(result);
78
+ }
79
+ else {
80
+ t.is(needsApproval, true);
81
+ }
82
+ });
83
+ // ============================================================================
84
+ // Basic Replacement Tests
85
+ // ============================================================================
86
+ test('string_replace: basic single-line replacement', async (t) => {
87
+ const filePath = await createTestFile('test.txt', 'Hello World\nGoodbye World\n');
88
+ const result = await executeStringReplace({
89
+ path: filePath,
90
+ old_str: 'Hello World',
91
+ new_str: 'Hi Universe',
92
+ });
93
+ const newContent = await readFile(filePath, 'utf-8');
94
+ t.is(newContent, 'Hi Universe\nGoodbye World\n');
95
+ t.true(result.includes('Successfully replaced'));
96
+ });
97
+ test('string_replace: multi-line replacement', async (t) => {
98
+ const filePath = await createTestFile('test.ts', 'function foo() {\n return 1;\n}\n');
99
+ const result = await executeStringReplace({
100
+ path: filePath,
101
+ old_str: 'function foo() {\n return 1;\n}',
102
+ new_str: 'function foo() {\n return 2;\n}',
103
+ });
104
+ const newContent = await readFile(filePath, 'utf-8');
105
+ t.is(newContent, 'function foo() {\n return 2;\n}\n');
106
+ t.true(result.includes('Successfully replaced'));
107
+ });
108
+ test('string_replace: insert content (add lines)', async (t) => {
109
+ const filePath = await createTestFile('test.ts', "import fs from 'fs';\n\nfunction main() {}\n");
110
+ const result = await executeStringReplace({
111
+ path: filePath,
112
+ old_str: "import fs from 'fs';\n\nfunction main() {}",
113
+ new_str: "import fs from 'fs';\nimport path from 'path';\n\nfunction main() {}",
114
+ });
115
+ const newContent = await readFile(filePath, 'utf-8');
116
+ t.true(newContent.includes("import path from 'path';"));
117
+ t.true(result.includes('Successfully replaced'));
118
+ });
119
+ test('string_replace: delete content (remove lines)', async (t) => {
120
+ const filePath = await createTestFile('test.ts', 'const x = 1;\nconst unused = 2;\nconst y = 3;\n');
121
+ const result = await executeStringReplace({
122
+ path: filePath,
123
+ old_str: 'const x = 1;\nconst unused = 2;\nconst y = 3;',
124
+ new_str: 'const x = 1;\nconst y = 3;',
125
+ });
126
+ const newContent = await readFile(filePath, 'utf-8');
127
+ t.false(newContent.includes('unused'));
128
+ t.true(result.includes('Successfully replaced'));
129
+ });
130
+ test('string_replace: replace with empty string (delete)', async (t) => {
131
+ const filePath = await createTestFile('test.txt', 'Keep this\nDelete this\nKeep this too\n');
132
+ const result = await executeStringReplace({
133
+ path: filePath,
134
+ old_str: 'Delete this\n',
135
+ new_str: '',
136
+ });
137
+ const newContent = await readFile(filePath, 'utf-8');
138
+ t.is(newContent, 'Keep this\nKeep this too\n');
139
+ t.true(result.includes('Successfully replaced'));
140
+ });
141
+ // ============================================================================
142
+ // Error Handling Tests
143
+ // ============================================================================
144
+ test('string_replace: error when content not found', async (t) => {
145
+ const filePath = await createTestFile('test.txt', 'Hello World\n');
146
+ await t.throwsAsync(async () => {
147
+ await executeStringReplace({
148
+ path: filePath,
149
+ old_str: 'This does not exist',
150
+ new_str: 'New content',
151
+ });
152
+ }, {
153
+ message: /Content not found in file/,
154
+ });
155
+ });
156
+ test('string_replace: error when multiple matches found', async (t) => {
157
+ const filePath = await createTestFile('test.txt', 'Hello World\nHello World\n');
158
+ await t.throwsAsync(async () => {
159
+ await executeStringReplace({
160
+ path: filePath,
161
+ old_str: 'Hello World',
162
+ new_str: 'Hi Universe',
163
+ });
164
+ }, {
165
+ message: /Found 2 matches/,
166
+ });
167
+ });
168
+ test('string_replace: error when file does not exist', async (t) => {
169
+ await t.throwsAsync(async () => {
170
+ await executeStringReplace({
171
+ path: join(testDir, 'nonexistent.txt'),
172
+ old_str: 'old',
173
+ new_str: 'new',
174
+ });
175
+ }, {
176
+ message: /ENOENT/,
177
+ });
178
+ });
179
+ test('string_replace: error when old_str is empty', async (t) => {
180
+ const filePath = await createTestFile('test.txt', 'content\n');
181
+ await t.throwsAsync(async () => {
182
+ await executeStringReplace({
183
+ path: filePath,
184
+ old_str: '',
185
+ new_str: 'new',
186
+ });
187
+ }, {
188
+ message: /old_str cannot be empty/,
189
+ });
190
+ });
191
+ // ============================================================================
192
+ // Context Matching Tests
193
+ // ============================================================================
194
+ test('string_replace: unique match with surrounding context', async (t) => {
195
+ const filePath = await createTestFile('test.ts', 'const a = 1;\nconst b = 2;\nconst c = 3;\n');
196
+ // Include context to make it unique
197
+ const result = await executeStringReplace({
198
+ path: filePath,
199
+ old_str: 'const a = 1;\nconst b = 2;',
200
+ new_str: 'const a = 1;\nconst b = 5;',
201
+ });
202
+ const newContent = await readFile(filePath, 'utf-8');
203
+ t.is(newContent, 'const a = 1;\nconst b = 5;\nconst c = 3;\n');
204
+ t.true(result.includes('Successfully replaced'));
205
+ });
206
+ test('string_replace: whitespace must match exactly', async (t) => {
207
+ const filePath = await createTestFile('test.ts', 'function foo() {\n return 1;\n}\n');
208
+ // This should fail because indentation doesn't match
209
+ await t.throwsAsync(async () => {
210
+ await executeStringReplace({
211
+ path: filePath,
212
+ old_str: 'function foo() {\nreturn 1;\n}', // Missing indentation
213
+ new_str: 'function foo() {\n return 2;\n}',
214
+ });
215
+ }, {
216
+ message: /Content not found/,
217
+ });
218
+ });
219
+ // ============================================================================
220
+ // Large File Tests
221
+ // ============================================================================
222
+ test('string_replace: works with large replacements', async (t) => {
223
+ // Create a large block of text to replace
224
+ const largeOldBlock = Array.from({ length: 60 }, (_, i) => `line ${i + 1}`).join('\n');
225
+ const largeNewBlock = Array.from({ length: 60 }, (_, i) => `new line ${i + 1}`).join('\n');
226
+ const filePath = await createTestFile('test.txt', `${largeOldBlock}\n`);
227
+ const result = await executeStringReplace({
228
+ path: filePath,
229
+ old_str: largeOldBlock,
230
+ new_str: largeNewBlock,
231
+ });
232
+ const newContent = await readFile(filePath, 'utf-8');
233
+ t.true(newContent.includes('new line 1'));
234
+ t.true(newContent.includes('new line 60'));
235
+ t.true(result.includes('Successfully replaced'));
236
+ });
237
+ // ============================================================================
238
+ // Validator Tests
239
+ // ============================================================================
240
+ test('string_replace validator: accepts valid input', async (t) => {
241
+ const filePath = await createTestFile('test.txt', 'Hello World\n');
242
+ if (!stringReplaceTool.validator) {
243
+ t.fail('Validator not defined');
244
+ return;
245
+ }
246
+ const result = await stringReplaceTool.validator({
247
+ path: filePath,
248
+ old_str: 'Hello',
249
+ new_str: 'Hi',
250
+ });
251
+ t.true(result.valid);
252
+ });
253
+ test('string_replace validator: rejects non-existent file', async (t) => {
254
+ if (!stringReplaceTool.validator) {
255
+ t.fail('Validator not defined');
256
+ return;
257
+ }
258
+ const result = await stringReplaceTool.validator({
259
+ path: join(testDir, 'nonexistent.txt'),
260
+ old_str: 'old',
261
+ new_str: 'new',
262
+ });
263
+ t.false(result.valid);
264
+ if (!result.valid) {
265
+ t.true(result.error.includes('does not exist'));
266
+ }
267
+ });
268
+ test('string_replace validator: rejects empty old_str', async (t) => {
269
+ const filePath = await createTestFile('test.txt', 'content\n');
270
+ if (!stringReplaceTool.validator) {
271
+ t.fail('Validator not defined');
272
+ return;
273
+ }
274
+ const result = await stringReplaceTool.validator({
275
+ path: filePath,
276
+ old_str: '',
277
+ new_str: 'new',
278
+ });
279
+ t.false(result.valid);
280
+ if (!result.valid) {
281
+ t.true(result.error.includes('cannot be empty'));
282
+ }
283
+ });
284
+ // ============================================================================
285
+ // Special Character Tests
286
+ // ============================================================================
287
+ test('string_replace: handles special regex characters', async (t) => {
288
+ const filePath = await createTestFile('test.txt', 'const regex = /test.*pattern/;\n');
289
+ const result = await executeStringReplace({
290
+ path: filePath,
291
+ old_str: 'const regex = /test.*pattern/;',
292
+ new_str: 'const regex = /new.*pattern/;',
293
+ });
294
+ const newContent = await readFile(filePath, 'utf-8');
295
+ t.is(newContent, 'const regex = /new.*pattern/;\n');
296
+ t.true(result.includes('Successfully replaced'));
297
+ });
298
+ test('string_replace: handles quotes and escapes', async (t) => {
299
+ const filePath = await createTestFile('test.ts', 'const str = "Hello \\"World\\"";\n');
300
+ const result = await executeStringReplace({
301
+ path: filePath,
302
+ old_str: 'const str = "Hello \\"World\\""',
303
+ new_str: 'const str = "Hi \\"Universe\\""',
304
+ });
305
+ const newContent = await readFile(filePath, 'utf-8');
306
+ t.true(newContent.includes('Hi \\"Universe\\"'));
307
+ t.true(result.includes('Successfully replaced'));
308
+ });
309
+ // ============================================================================
310
+ // Cleanup
311
+ // ============================================================================
312
+ test.after(() => {
313
+ setCurrentMode('normal');
314
+ });
315
+ //# sourceMappingURL=string-replace.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string-replace.spec.js","sourceRoot":"","sources":["../../source/tools/string-replace.spec.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,16 @@
1
1
  import React from 'react';
2
- interface CreateFileArgs {
2
+ interface WriteFileArgs {
3
3
  path?: string;
4
4
  file_path?: string;
5
5
  content?: string;
6
6
  }
7
- export declare const createFileTool: {
8
- name: "create_file";
7
+ export declare const writeFileTool: {
8
+ name: "write_file";
9
9
  tool: import("ai").Tool<{
10
10
  path: string;
11
11
  content: string;
12
12
  }, string>;
13
- formatter: (args: CreateFileArgs, result?: string) => Promise<React.ReactElement>;
13
+ formatter: (args: WriteFileArgs, result?: string) => Promise<React.ReactElement>;
14
14
  validator: (args: {
15
15
  path: string;
16
16
  content: string;
@@ -22,4 +22,4 @@ export declare const createFileTool: {
22
22
  }>;
23
23
  };
24
24
  export {};
25
- //# sourceMappingURL=create-file.d.ts.map
25
+ //# sourceMappingURL=write-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-file.d.ts","sourceRoot":"","sources":["../../source/tools/write-file.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,MAAM,OAAO,CAAC;AAoE1B,UAAU,aAAa;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAwKD,eAAO,MAAM,aAAa;;;cApMM,MAAM;iBAAW,MAAM;;sBAqGhD,aAAa,WACV,MAAM,KACb,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC;sBA2CU;QACvC,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KAChB,KAAG,OAAO,CAAC;QAAC,KAAK,EAAE,IAAI,CAAA;KAAC,GAAG;QAAC,KAAK,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC;CAoDzD,CAAC"}
@@ -11,13 +11,28 @@ import { ThemeContext } from '../hooks/useTheme.js';
11
11
  import { jsonSchema, tool } from '../types/core.js';
12
12
  import { getLanguageFromExtension } from '../utils/programming-language-helper.js';
13
13
  import { closeDiffInVSCode, isVSCodeConnected, sendFileChangeToVSCode, } from '../vscode/index.js';
14
- const executeCreateFile = async (args) => {
14
+ const executeWriteFile = async (args) => {
15
15
  const absPath = resolve(args.path);
16
+ const fileExists = existsSync(absPath);
16
17
  await writeFile(absPath, args.content, 'utf-8');
17
- return 'File written successfully';
18
+ // Read back to verify and show actual content
19
+ const actualContent = await readFile(absPath, 'utf-8');
20
+ const lines = actualContent.split('\n');
21
+ const lineCount = lines.length;
22
+ const charCount = actualContent.length;
23
+ const estimatedTokens = Math.ceil(charCount / 4);
24
+ // Generate full file contents to show the model the current file state
25
+ let fileContext = '\n\nFile contents after write:\n';
26
+ for (let i = 0; i < lines.length; i++) {
27
+ const lineNumStr = String(i + 1).padStart(4, ' ');
28
+ const line = lines[i] || '';
29
+ fileContext += `${lineNumStr}: ${line}\n`;
30
+ }
31
+ const action = fileExists ? 'overwritten' : 'written';
32
+ return `File ${action} successfully (${lineCount} lines, ${charCount} characters, ~${estimatedTokens} tokens).${fileContext}`;
18
33
  };
19
- const createFileCoreTool = tool({
20
- description: 'Create a new file with the specified content (overwrites if file exists)',
34
+ const writeFileCoreTool = tool({
35
+ description: 'Write content to a file (creates new file or overwrites existing file). Use this for complete file rewrites, generated code, or when most of the file needs to change. For small targeted edits, use string_replace instead.',
21
36
  inputSchema: jsonSchema({
22
37
  type: 'object',
23
38
  properties: {
@@ -27,7 +42,7 @@ const createFileCoreTool = tool({
27
42
  },
28
43
  content: {
29
44
  type: 'string',
30
- description: 'The content to write to the file.',
45
+ description: 'The complete content to write to the file.',
31
46
  },
32
47
  },
33
48
  required: ['path', 'content'],
@@ -38,11 +53,11 @@ const createFileCoreTool = tool({
38
53
  return mode !== 'auto-accept'; // true in normal/plan, false in auto-accept
39
54
  },
40
55
  execute: async (args, _options) => {
41
- return await executeCreateFile(args);
56
+ return await executeWriteFile(args);
42
57
  },
43
58
  });
44
59
  // Create a component that will re-render when theme changes
45
- const CreateFileFormatter = React.memo(({ args }) => {
60
+ const WriteFileFormatter = React.memo(({ args }) => {
46
61
  const themeContext = React.useContext(ThemeContext);
47
62
  if (!themeContext) {
48
63
  throw new Error('ThemeContext is required');
@@ -54,7 +69,7 @@ const CreateFileFormatter = React.memo(({ args }) => {
54
69
  const charCount = newContent.length;
55
70
  // Estimate tokens (rough approximation: ~4 characters per token)
56
71
  const estimatedTokens = Math.ceil(charCount / 4);
57
- const messageContent = (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: colors.tool, children: "\u2692 create_file" }), _jsxs(Box, { children: [_jsx(Text, { color: colors.secondary, children: "Path: " }), _jsx(Text, { color: colors.white, children: path })] }), _jsxs(Box, { children: [_jsx(Text, { color: colors.secondary, children: "Size: " }), _jsxs(Text, { color: colors.white, children: [lineCount, " lines, ", charCount, " characters (~", estimatedTokens, " tokens)"] })] }), newContent.length > 0 ? (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: colors.white, children: "File content:" }), newContent.split('\n').map((line, i) => {
72
+ const messageContent = (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: colors.tool, children: "\u2692 write_file" }), _jsxs(Box, { children: [_jsx(Text, { color: colors.secondary, children: "Path: " }), _jsx(Text, { color: colors.white, children: path })] }), _jsxs(Box, { children: [_jsx(Text, { color: colors.secondary, children: "Size: " }), _jsxs(Text, { color: colors.white, children: [lineCount, " lines, ", charCount, " characters (~", estimatedTokens, " tokens)"] })] }), newContent.length > 0 ? (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: colors.white, children: "File content:" }), newContent.split('\n').map((line, i) => {
58
73
  const lineNumStr = String(i + 1).padStart(4, ' ');
59
74
  const ext = path.split('.').pop()?.toLowerCase() ?? '';
60
75
  const language = getLanguageFromExtension(ext);
@@ -70,7 +85,7 @@ const CreateFileFormatter = React.memo(({ args }) => {
70
85
  });
71
86
  // Track VS Code change IDs for cleanup
72
87
  const vscodeChangeIds = new Map();
73
- const createFileFormatter = async (args, result) => {
88
+ const writeFileFormatter = async (args, result) => {
74
89
  const path = args.path || args.file_path || '';
75
90
  const absPath = resolve(path);
76
91
  // Send diff to VS Code during preview phase (before execution)
@@ -86,7 +101,7 @@ const createFileFormatter = async (args, result) => {
86
101
  // File might exist but not be readable
87
102
  }
88
103
  }
89
- const changeId = sendFileChangeToVSCode(absPath, originalContent, content, 'create_file', {
104
+ const changeId = sendFileChangeToVSCode(absPath, originalContent, content, 'write_file', {
90
105
  path,
91
106
  content,
92
107
  });
@@ -102,30 +117,10 @@ const createFileFormatter = async (args, result) => {
102
117
  vscodeChangeIds.delete(absPath);
103
118
  }
104
119
  }
105
- return _jsx(CreateFileFormatter, { args: args });
120
+ return _jsx(WriteFileFormatter, { args: args });
106
121
  };
107
- const createFileValidator = async (args) => {
122
+ const writeFileValidator = async (args) => {
108
123
  const absPath = resolve(args.path);
109
- // Check if file already exists
110
- try {
111
- await access(absPath, constants.F_OK);
112
- return {
113
- valid: false,
114
- error: `⚒ File "${args.path}" already exists. Use a file editing tool instead.`,
115
- };
116
- }
117
- catch (error) {
118
- // ENOENT is good - file doesn't exist
119
- if (error && typeof error === 'object' && 'code' in error) {
120
- if (error.code !== 'ENOENT') {
121
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
122
- return {
123
- valid: false,
124
- error: `⚒ Cannot access path "${args.path}": ${errorMessage}`,
125
- };
126
- }
127
- }
128
- }
129
124
  // Check if parent directory exists
130
125
  const parentDir = dirname(absPath);
131
126
  try {
@@ -160,16 +155,16 @@ const createFileValidator = async (args) => {
160
155
  if (pattern.test(absPath)) {
161
156
  return {
162
157
  valid: false,
163
- error: `⚒ Cannot create files in system directory: "${args.path}"`,
158
+ error: `⚒ Cannot write files to system directory: "${args.path}"`,
164
159
  };
165
160
  }
166
161
  }
167
162
  return { valid: true };
168
163
  };
169
- export const createFileTool = {
170
- name: 'create_file',
171
- tool: createFileCoreTool,
172
- formatter: createFileFormatter,
173
- validator: createFileValidator,
164
+ export const writeFileTool = {
165
+ name: 'write_file',
166
+ tool: writeFileCoreTool,
167
+ formatter: writeFileFormatter,
168
+ validator: writeFileValidator,
174
169
  };
175
- //# sourceMappingURL=create-file.js.map
170
+ //# sourceMappingURL=write-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-file.js","sourceRoot":"","sources":["../../source/tools/write-file.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=write-file.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-file.spec.d.ts","sourceRoot":"","sources":["../../source/tools/write-file.spec.ts"],"names":[],"mappings":""}