snow-ai 0.3.7 → 0.3.8

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 (53) hide show
  1. package/dist/agents/compactAgent.js +7 -3
  2. package/dist/agents/summaryAgent.d.ts +57 -0
  3. package/dist/agents/summaryAgent.js +259 -0
  4. package/dist/api/anthropic.d.ts +1 -0
  5. package/dist/api/anthropic.js +20 -13
  6. package/dist/api/chat.d.ts +1 -0
  7. package/dist/api/chat.js +23 -12
  8. package/dist/api/gemini.d.ts +1 -0
  9. package/dist/api/gemini.js +14 -8
  10. package/dist/api/responses.d.ts +1 -0
  11. package/dist/api/responses.js +23 -15
  12. package/dist/app.js +15 -2
  13. package/dist/hooks/useCommandHandler.js +58 -0
  14. package/dist/hooks/useCommandPanel.d.ts +2 -1
  15. package/dist/hooks/useCommandPanel.js +6 -1
  16. package/dist/hooks/useConversation.js +44 -24
  17. package/dist/hooks/useSnapshotState.d.ts +2 -0
  18. package/dist/mcp/filesystem.d.ts +131 -46
  19. package/dist/mcp/filesystem.js +188 -35
  20. package/dist/mcp/types/filesystem.types.d.ts +91 -0
  21. package/dist/mcp/utils/filesystem/batch-operations.utils.d.ts +39 -0
  22. package/dist/mcp/utils/filesystem/batch-operations.utils.js +182 -0
  23. package/dist/ui/components/ChatInput.d.ts +2 -1
  24. package/dist/ui/components/ChatInput.js +3 -3
  25. package/dist/ui/components/CommandPanel.d.ts +2 -1
  26. package/dist/ui/components/CommandPanel.js +18 -3
  27. package/dist/ui/components/MarkdownRenderer.js +10 -1
  28. package/dist/ui/components/MessageList.js +1 -1
  29. package/dist/ui/components/PendingMessages.js +1 -1
  30. package/dist/ui/components/PendingToolCalls.d.ts +11 -0
  31. package/dist/ui/components/PendingToolCalls.js +35 -0
  32. package/dist/ui/components/ToolResultPreview.d.ts +1 -1
  33. package/dist/ui/components/ToolResultPreview.js +116 -152
  34. package/dist/ui/pages/ChatScreen.d.ts +1 -0
  35. package/dist/ui/pages/ChatScreen.js +99 -60
  36. package/dist/utils/chatExporter.d.ts +9 -0
  37. package/dist/utils/chatExporter.js +126 -0
  38. package/dist/utils/commandExecutor.d.ts +1 -1
  39. package/dist/utils/commands/export.d.ts +2 -0
  40. package/dist/utils/commands/export.js +12 -0
  41. package/dist/utils/commands/init.js +3 -3
  42. package/dist/utils/fileDialog.d.ts +9 -0
  43. package/dist/utils/fileDialog.js +74 -0
  44. package/dist/utils/fileUtils.js +3 -3
  45. package/dist/utils/incrementalSnapshot.d.ts +7 -0
  46. package/dist/utils/incrementalSnapshot.js +35 -0
  47. package/dist/utils/messageFormatter.js +89 -6
  48. package/dist/utils/sessionConverter.js +11 -0
  49. package/dist/utils/sessionManager.d.ts +5 -0
  50. package/dist/utils/sessionManager.js +45 -0
  51. package/dist/utils/toolDisplayConfig.d.ts +16 -0
  52. package/dist/utils/toolDisplayConfig.js +42 -0
  53. package/package.json +1 -1
package/dist/app.js CHANGED
@@ -16,6 +16,9 @@ export default function App({ version, skipWelcome, headlessPrompt }) {
16
16
  return (React.createElement(HeadlessModeScreen, { prompt: headlessPrompt, onComplete: () => process.exit(0) }));
17
17
  }
18
18
  const [currentView, setCurrentView] = useState(skipWelcome ? 'chat' : 'welcome');
19
+ // Add a key to force remount ChatScreen when returning from welcome screen
20
+ // This ensures configuration changes are picked up
21
+ const [chatScreenKey, setChatScreenKey] = useState(0);
19
22
  const [exitNotification, setExitNotification] = useState({
20
23
  show: false,
21
24
  message: '',
@@ -27,16 +30,26 @@ export default function App({ version, skipWelcome, headlessPrompt }) {
27
30
  // Global navigation handler
28
31
  useEffect(() => {
29
32
  const unsubscribe = onNavigate(event => {
33
+ // When navigating to welcome from chat (e.g., /home command),
34
+ // increment key so next time chat is entered, it remounts with fresh config
35
+ if (event.destination === 'welcome' && currentView === 'chat') {
36
+ setChatScreenKey(prev => prev + 1);
37
+ }
30
38
  setCurrentView(event.destination);
31
39
  });
32
40
  return unsubscribe;
33
- }, []);
41
+ }, [currentView]);
34
42
  const handleMenuSelect = (value) => {
35
43
  if (value === 'chat' ||
36
44
  value === 'settings' ||
37
45
  value === 'mcp' ||
38
46
  value === 'systemprompt' ||
39
47
  value === 'customheaders') {
48
+ // When entering chat from welcome screen, increment key to force remount
49
+ // This ensures any configuration changes are picked up
50
+ if (value === 'chat' && currentView === 'welcome') {
51
+ setChatScreenKey(prev => prev + 1);
52
+ }
40
53
  setCurrentView(value);
41
54
  }
42
55
  else if (value === 'exit') {
@@ -48,7 +61,7 @@ export default function App({ version, skipWelcome, headlessPrompt }) {
48
61
  case 'welcome':
49
62
  return (React.createElement(WelcomeScreen, { version: version, onMenuSelect: handleMenuSelect }));
50
63
  case 'chat':
51
- return React.createElement(ChatScreen, { skipWelcome: skipWelcome });
64
+ return React.createElement(ChatScreen, { key: chatScreenKey, skipWelcome: skipWelcome });
52
65
  case 'settings':
53
66
  return (React.createElement(Box, { flexDirection: "column" },
54
67
  React.createElement(Text, { color: "blue" }, "Settings"),
@@ -4,6 +4,8 @@ import { sessionManager } from '../utils/sessionManager.js';
4
4
  import { compressContext } from '../utils/contextCompressor.js';
5
5
  import { navigateTo } from './useGlobalNavigation.js';
6
6
  import { resetTerminal } from '../utils/terminal.js';
7
+ import { showSaveDialog, isFileDialogSupported } from '../utils/fileDialog.js';
8
+ import { exportMessagesToFile } from '../utils/chatExporter.js';
7
9
  export function useCommandHandler(options) {
8
10
  const { stdout } = useStdout();
9
11
  const handleCommandExecution = useCallback(async (commandName, result) => {
@@ -193,6 +195,62 @@ export function useCommandHandler(options) {
193
195
  // Auto-send the review prompt using advanced model (not basic model), hide the prompt from UI
194
196
  options.processMessage(result.prompt, undefined, false, true);
195
197
  }
198
+ else if (result.success && result.action === 'exportChat') {
199
+ // Handle export chat command
200
+ // Show loading message first
201
+ const loadingMessage = {
202
+ role: 'command',
203
+ content: 'Opening file save dialog...',
204
+ commandName: commandName,
205
+ };
206
+ options.setMessages(prev => [...prev, loadingMessage]);
207
+ try {
208
+ // Check if file dialog is supported
209
+ if (!isFileDialogSupported()) {
210
+ const errorMessage = {
211
+ role: 'command',
212
+ content: 'File dialog not supported on this platform. Export cancelled.',
213
+ commandName: commandName,
214
+ };
215
+ options.setMessages(prev => [...prev, errorMessage]);
216
+ return;
217
+ }
218
+ // Generate default filename with timestamp
219
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('.')[0];
220
+ const defaultFilename = `snow-chat-${timestamp}.txt`;
221
+ // Show native save dialog
222
+ const filePath = await showSaveDialog(defaultFilename, 'Export Chat Conversation');
223
+ if (!filePath) {
224
+ // User cancelled
225
+ const cancelMessage = {
226
+ role: 'command',
227
+ content: 'Export cancelled by user.',
228
+ commandName: commandName,
229
+ };
230
+ options.setMessages(prev => [...prev, cancelMessage]);
231
+ return;
232
+ }
233
+ // Export messages to file
234
+ await exportMessagesToFile(options.messages, filePath);
235
+ // Show success message
236
+ const successMessage = {
237
+ role: 'command',
238
+ content: `✓ Chat exported successfully to:\n${filePath}`,
239
+ commandName: commandName,
240
+ };
241
+ options.setMessages(prev => [...prev, successMessage]);
242
+ }
243
+ catch (error) {
244
+ // Show error message
245
+ const errorMsg = error instanceof Error ? error.message : 'Unknown error';
246
+ const errorMessage = {
247
+ role: 'command',
248
+ content: `✗ Export failed: ${errorMsg}`,
249
+ commandName: commandName,
250
+ };
251
+ options.setMessages(prev => [...prev, errorMessage]);
252
+ }
253
+ }
196
254
  else if (result.message) {
197
255
  // For commands that just return a message (like /role, /init without SNOW.md, etc.)
198
256
  // Display the message as a command message
@@ -1,5 +1,5 @@
1
1
  import { TextBuffer } from '../utils/textBuffer.js';
2
- export declare function useCommandPanel(buffer: TextBuffer): {
2
+ export declare function useCommandPanel(buffer: TextBuffer, isProcessing?: boolean): {
3
3
  showCommands: boolean;
4
4
  setShowCommands: import("react").Dispatch<import("react").SetStateAction<boolean>>;
5
5
  commandSelectedIndex: number;
@@ -13,4 +13,5 @@ export declare function useCommandPanel(buffer: TextBuffer): {
13
13
  name: string;
14
14
  description: string;
15
15
  }[];
16
+ isProcessing: boolean;
16
17
  };
@@ -30,8 +30,12 @@ const commands = [
30
30
  name: 'usage',
31
31
  description: 'View token usage statistics with interactive charts',
32
32
  },
33
+ {
34
+ name: 'export',
35
+ description: 'Export chat conversation to text file with save dialog',
36
+ },
33
37
  ];
34
- export function useCommandPanel(buffer) {
38
+ export function useCommandPanel(buffer, isProcessing = false) {
35
39
  const [showCommands, setShowCommands] = useState(false);
36
40
  const [commandSelectedIndex, setCommandSelectedIndex] = useState(0);
37
41
  // Get filtered commands based on current input
@@ -62,5 +66,6 @@ export function useCommandPanel(buffer) {
62
66
  getFilteredCommands,
63
67
  updateCommandPanelState,
64
68
  commands,
69
+ isProcessing, // Export isProcessing for CommandPanel to use
65
70
  };
66
71
  }
@@ -11,6 +11,7 @@ import { sessionManager } from '../utils/sessionManager.js';
11
11
  import { formatTodoContext } from '../utils/todoPreprocessor.js';
12
12
  import { formatToolCallMessage } from '../utils/messageFormatter.js';
13
13
  import { resourceMonitor } from '../utils/resourceMonitor.js';
14
+ import { isToolNeedTwoStepDisplay } from '../utils/toolDisplayConfig.js';
14
15
  /**
15
16
  * Handle conversation with streaming and tool calls
16
17
  * Returns the usage data collected during the conversation
@@ -85,7 +86,7 @@ export async function handleConversationWithTools(options) {
85
86
  }
86
87
  };
87
88
  try {
88
- encoder = encoding_for_model('gpt-4');
89
+ encoder = encoding_for_model('gpt-5');
89
90
  resourceMonitor.trackEncoderCreated();
90
91
  }
91
92
  catch (e) {
@@ -95,8 +96,8 @@ export async function handleConversationWithTools(options) {
95
96
  setStreamTokenCount(0);
96
97
  const config = getOpenAiConfig();
97
98
  const model = options.useBasicModel
98
- ? config.basicModel || config.advancedModel || 'gpt-4.1'
99
- : config.advancedModel || 'gpt-4.1';
99
+ ? config.basicModel || config.advancedModel || 'gpt-5'
100
+ : config.advancedModel || 'gpt-5';
100
101
  // Tool calling loop (no limit on rounds)
101
102
  let finalAssistantMessage = null;
102
103
  // Accumulate usage data across all rounds
@@ -238,7 +239,8 @@ export async function handleConversationWithTools(options) {
238
239
  else {
239
240
  // Add to existing usage for UI display
240
241
  accumulatedUsage.prompt_tokens += chunk.usage.prompt_tokens || 0;
241
- accumulatedUsage.completion_tokens += chunk.usage.completion_tokens || 0;
242
+ accumulatedUsage.completion_tokens +=
243
+ chunk.usage.completion_tokens || 0;
242
244
  accumulatedUsage.total_tokens += chunk.usage.total_tokens || 0;
243
245
  if (chunk.usage.cache_creation_input_tokens !== undefined) {
244
246
  accumulatedUsage.cache_creation_input_tokens =
@@ -293,7 +295,7 @@ export async function handleConversationWithTools(options) {
293
295
  },
294
296
  ]);
295
297
  }
296
- // Display tool calls in UI with pending status
298
+ // Display tool calls in UI - 只有耗时工具才显示进行中状态
297
299
  for (const toolCall of receivedToolCalls) {
298
300
  const toolDisplay = formatToolCallMessage(toolCall);
299
301
  let toolArgs;
@@ -303,21 +305,24 @@ export async function handleConversationWithTools(options) {
303
305
  catch (e) {
304
306
  toolArgs = {};
305
307
  }
306
- setMessages(prev => [
307
- ...prev,
308
- {
309
- role: 'assistant',
310
- content: `⚡ ${toolDisplay.toolName}`,
311
- streaming: false,
312
- toolCall: {
313
- name: toolCall.function.name,
314
- arguments: toolArgs,
308
+ // 只有耗时工具才在动态区显示进行中状态
309
+ if (isToolNeedTwoStepDisplay(toolCall.function.name)) {
310
+ setMessages(prev => [
311
+ ...prev,
312
+ {
313
+ role: 'assistant',
314
+ content: `⚡ ${toolDisplay.toolName}`,
315
+ streaming: false,
316
+ toolCall: {
317
+ name: toolCall.function.name,
318
+ arguments: toolArgs,
319
+ },
320
+ toolDisplay,
321
+ toolCallId: toolCall.id, // Store tool call ID for later update
322
+ toolPending: true, // Mark as pending execution
315
323
  },
316
- toolDisplay,
317
- toolCallId: toolCall.id, // Store tool call ID for later update
318
- toolPending: true, // Mark as pending execution
319
- },
320
- ]);
324
+ ]);
325
+ }
321
326
  }
322
327
  // Filter tools that need confirmation (not in always-approved list OR session-approved list)
323
328
  const toolsNeedingConfirmation = [];
@@ -377,7 +382,7 @@ export async function handleConversationWithTools(options) {
377
382
  // Add all tools to approved list
378
383
  approvedTools.push(...toolsNeedingConfirmation);
379
384
  }
380
- // Execute approved tools with sub-agent message callback
385
+ // Execute approved tools with sub-agent message callback and terminal output callback
381
386
  const toolResults = await executeToolCalls(approvedTools, controller.signal, setStreamTokenCount, async (subAgentMessage) => {
382
387
  // Handle sub-agent messages - display and save to session
383
388
  setMessages(prev => {
@@ -603,6 +608,7 @@ export async function handleConversationWithTools(options) {
603
608
  !isError) {
604
609
  try {
605
610
  const resultData = JSON.parse(result.content);
611
+ // Handle single file edit
606
612
  if (resultData.oldContent && resultData.newContent) {
607
613
  editDiffData = {
608
614
  oldContent: resultData.oldContent,
@@ -613,14 +619,24 @@ export async function handleConversationWithTools(options) {
613
619
  contextStartLine: resultData.contextStartLine,
614
620
  };
615
621
  }
622
+ // Handle batch edit
623
+ else if (resultData.results &&
624
+ Array.isArray(resultData.results)) {
625
+ editDiffData = {
626
+ batchResults: resultData.results,
627
+ isBatch: true,
628
+ };
629
+ }
616
630
  }
617
631
  catch (e) {
618
632
  // If parsing fails, just show regular result
619
633
  }
620
634
  }
621
- // Append completed message to static area (don't remove pending message)
622
- // Static area doesn't support deletion, only append
623
- // Completed message only shows diff data (for edit tools), no other parameters
635
+ // 处理工具执行结果的显示
636
+ // - 耗时工具(两步显示):完成消息追加到静态区,之前的进行中消息已包含参数
637
+ // - 普通工具(单步显示):完成消息需要包含参数和结果,使用 toolDisplay
638
+ // 获取工具参数的格式化信息
639
+ const toolDisplay = formatToolCallMessage(toolCall);
624
640
  setMessages(prev => [
625
641
  ...prev,
626
642
  // Add new completed message
@@ -633,7 +649,11 @@ export async function handleConversationWithTools(options) {
633
649
  name: toolCall.function.name,
634
650
  arguments: editDiffData,
635
651
  }
636
- : undefined, // Don't show arguments for completed tools (already shown in pending)
652
+ : undefined,
653
+ // 为普通工具添加参数显示(耗时工具在进行中状态已经显示过参数)
654
+ toolDisplay: !isToolNeedTwoStepDisplay(toolCall.function.name)
655
+ ? toolDisplay
656
+ : undefined,
637
657
  // Store tool result for preview rendering
638
658
  toolResult: !isError ? result.content : undefined,
639
659
  },
@@ -5,10 +5,12 @@ export declare function useSnapshotState(messagesLength: number): {
5
5
  messageIndex: number;
6
6
  fileCount: number;
7
7
  filePaths?: string[];
8
+ message?: string;
8
9
  } | null;
9
10
  setPendingRollback: import("react").Dispatch<import("react").SetStateAction<{
10
11
  messageIndex: number;
11
12
  fileCount: number;
12
13
  filePaths?: string[];
14
+ message?: string;
13
15
  } | null>>;
14
16
  };
@@ -1,5 +1,4 @@
1
- import { type Diagnostic } from '../utils/vscodeConnection.js';
2
- import type { StructureAnalysis } from './types/filesystem.types.js';
1
+ import type { EditBySearchConfig, EditByLineConfig, EditBySearchResult, EditByLineResult } from './types/filesystem.types.js';
3
2
  /**
4
3
  * Filesystem MCP Service
5
4
  * Provides basic file operations: read, create, and delete files
@@ -13,13 +12,17 @@ export declare class FilesystemMCPService {
13
12
  constructor(basePath?: string);
14
13
  /**
15
14
  * Get the content of a file with optional line range
16
- * @param filePath - Path to the file (relative to base path or absolute) or array of file paths
17
- * @param startLine - Starting line number (1-indexed, inclusive, optional - defaults to 1)
18
- * @param endLine - Ending line number (1-indexed, inclusive, optional - defaults to 500 or file end)
15
+ * @param filePath - Path to the file (relative to base path or absolute) or array of file paths or array of file config objects
16
+ * @param startLine - Starting line number (1-indexed, inclusive, optional - defaults to 1). Used for single file or as default for array of strings
17
+ * @param endLine - Ending line number (1-indexed, inclusive, optional - defaults to file end). Used for single file or as default for array of strings
19
18
  * @returns Object containing the requested content with line numbers and metadata
20
19
  * @throws Error if file doesn't exist or cannot be read
21
20
  */
22
- getFileContent(filePath: string | string[], startLine?: number, endLine?: number): Promise<{
21
+ getFileContent(filePath: string | string[] | Array<{
22
+ path: string;
23
+ startLine?: number;
24
+ endLine?: number;
25
+ }>, startLine?: number, endLine?: number): Promise<{
23
26
  content: string;
24
27
  startLine: number;
25
28
  endLine: number;
@@ -77,57 +80,42 @@ export declare class FilesystemMCPService {
77
80
  created: Date;
78
81
  }>;
79
82
  /**
80
- * Edit a file by searching for exact content and replacing it
83
+ * Edit file(s) by searching for exact content and replacing it
81
84
  * This method uses SMART MATCHING to handle whitespace differences automatically.
82
85
  *
83
- * @param filePath - Path to the file to edit
84
- * @param searchContent - Content to search for (whitespace will be normalized automatically)
85
- * @param replaceContent - New content to replace the search content with
86
+ * @param filePath - Path to the file to edit, or array of file paths, or array of edit config objects
87
+ * @param searchContent - Content to search for (for single file or unified mode)
88
+ * @param replaceContent - New content to replace (for single file or unified mode)
86
89
  * @param occurrence - Which occurrence to replace (1-indexed, default: 1, use -1 for all)
87
90
  * @param contextLines - Number of context lines to return before and after the edit (default: 8)
88
91
  * @returns Object containing success message, before/after comparison, and diagnostics from IDE (VSCode or JetBrains)
89
92
  * @throws Error if search content is not found or multiple matches exist
90
93
  */
91
- editFileBySearch(filePath: string, searchContent: string, replaceContent: string, occurrence?: number, contextLines?: number): Promise<{
92
- message: string;
93
- oldContent: string;
94
- newContent: string;
95
- replacedContent: string;
96
- matchLocation: {
97
- startLine: number;
98
- endLine: number;
99
- };
100
- contextStartLine: number;
101
- contextEndLine: number;
102
- totalLines: number;
103
- structureAnalysis?: StructureAnalysis;
104
- diagnostics?: Diagnostic[];
105
- }>;
94
+ editFileBySearch(filePath: string | string[] | EditBySearchConfig[], searchContent?: string, replaceContent?: string, occurrence?: number, contextLines?: number): Promise<EditBySearchResult>;
95
+ /**
96
+ * Internal method: Edit a single file by search-replace
97
+ * @private
98
+ */
99
+ private editFileBySearchSingle;
106
100
  /**
107
- * Edit a file by replacing lines within a specified range
101
+ * Edit file(s) by replacing lines within a specified range
108
102
  * BEST PRACTICE: Keep edits small and focused (≤15 lines recommended) for better accuracy.
109
103
  * For larger changes, make multiple parallel edits to non-overlapping sections instead of one large edit.
110
104
  *
111
- * @param filePath - Path to the file to edit
112
- * @param startLine - Starting line number (1-indexed, inclusive) - get from filesystem-read output
113
- * @param endLine - Ending line number (1-indexed, inclusive) - get from filesystem-read output
114
- * @param newContent - New content to replace the specified lines (WITHOUT line numbers)
105
+ * @param filePath - Path to the file to edit, or array of file paths, or array of edit config objects
106
+ * @param startLine - Starting line number (for single file or unified mode)
107
+ * @param endLine - Ending line number (for single file or unified mode)
108
+ * @param newContent - New content to replace (for single file or unified mode)
115
109
  * @param contextLines - Number of context lines to return before and after the edit (default: 8)
116
110
  * @returns Object containing success message, precise before/after comparison, and diagnostics from IDE (VSCode or JetBrains)
117
111
  * @throws Error if file editing fails
118
112
  */
119
- editFile(filePath: string, startLine: number, endLine: number, newContent: string, contextLines?: number): Promise<{
120
- message: string;
121
- oldContent: string;
122
- newContent: string;
123
- replacedLines: string;
124
- contextStartLine: number;
125
- contextEndLine: number;
126
- totalLines: number;
127
- linesModified: number;
128
- structureAnalysis?: StructureAnalysis;
129
- diagnostics?: Diagnostic[];
130
- }>;
113
+ editFile(filePath: string | string[] | EditByLineConfig[], startLine?: number, endLine?: number, newContent?: string, contextLines?: number): Promise<EditByLineResult>;
114
+ /**
115
+ * Internal method: Edit a single file by line range
116
+ * @private
117
+ */
118
+ private editFileSingle;
131
119
  /**
132
120
  * Resolve path relative to base path and normalize it
133
121
  * @private
@@ -155,6 +143,29 @@ export declare const mcpTools: ({
155
143
  type: string;
156
144
  items: {
157
145
  type: string;
146
+ properties?: undefined;
147
+ required?: undefined;
148
+ };
149
+ description: string;
150
+ } | {
151
+ type: string;
152
+ items: {
153
+ type: string;
154
+ properties: {
155
+ path: {
156
+ type: string;
157
+ description: string;
158
+ };
159
+ startLine: {
160
+ type: string;
161
+ description: string;
162
+ };
163
+ endLine: {
164
+ type: string;
165
+ description: string;
166
+ };
167
+ };
168
+ required: string[];
158
169
  };
159
170
  description: string;
160
171
  })[];
@@ -283,9 +294,46 @@ export declare const mcpTools: ({
283
294
  type: string;
284
295
  properties: {
285
296
  filePath: {
286
- type: string;
297
+ oneOf: ({
298
+ type: string;
299
+ description: string;
300
+ items?: undefined;
301
+ } | {
302
+ type: string;
303
+ items: {
304
+ type: string;
305
+ properties?: undefined;
306
+ required?: undefined;
307
+ };
308
+ description: string;
309
+ } | {
310
+ type: string;
311
+ items: {
312
+ type: string;
313
+ properties: {
314
+ path: {
315
+ type: string;
316
+ description: string;
317
+ };
318
+ searchContent: {
319
+ type: string;
320
+ description: string;
321
+ };
322
+ replaceContent: {
323
+ type: string;
324
+ description: string;
325
+ };
326
+ occurrence: {
327
+ type: string;
328
+ description: string;
329
+ };
330
+ };
331
+ required: string[];
332
+ };
333
+ description: string;
334
+ })[];
287
335
  description: string;
288
- oneOf?: undefined;
336
+ type?: undefined;
289
337
  };
290
338
  searchContent: {
291
339
  type: string;
@@ -322,9 +370,46 @@ export declare const mcpTools: ({
322
370
  type: string;
323
371
  properties: {
324
372
  filePath: {
325
- type: string;
373
+ oneOf: ({
374
+ type: string;
375
+ description: string;
376
+ items?: undefined;
377
+ } | {
378
+ type: string;
379
+ items: {
380
+ type: string;
381
+ properties?: undefined;
382
+ required?: undefined;
383
+ };
384
+ description: string;
385
+ } | {
386
+ type: string;
387
+ items: {
388
+ type: string;
389
+ properties: {
390
+ path: {
391
+ type: string;
392
+ description: string;
393
+ };
394
+ startLine: {
395
+ type: string;
396
+ description: string;
397
+ };
398
+ endLine: {
399
+ type: string;
400
+ description: string;
401
+ };
402
+ newContent: {
403
+ type: string;
404
+ description: string;
405
+ };
406
+ };
407
+ required: string[];
408
+ };
409
+ description: string;
410
+ })[];
326
411
  description: string;
327
- oneOf?: undefined;
412
+ type?: undefined;
328
413
  };
329
414
  startLine: {
330
415
  type: string;