snow-ai 0.2.11 → 0.2.13

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 (41) hide show
  1. package/dist/api/anthropic.d.ts +2 -0
  2. package/dist/api/anthropic.js +64 -18
  3. package/dist/api/chat.d.ts +3 -0
  4. package/dist/api/chat.js +5 -4
  5. package/dist/api/gemini.d.ts +3 -0
  6. package/dist/api/gemini.js +168 -101
  7. package/dist/api/responses.d.ts +3 -0
  8. package/dist/api/responses.js +5 -4
  9. package/dist/api/systemPrompt.d.ts +1 -1
  10. package/dist/api/systemPrompt.js +149 -40
  11. package/dist/hooks/useConversation.d.ts +1 -1
  12. package/dist/hooks/useConversation.js +5 -3
  13. package/dist/hooks/useGlobalNavigation.js +2 -0
  14. package/dist/hooks/useToolConfirmation.d.ts +2 -1
  15. package/dist/hooks/useToolConfirmation.js +2 -1
  16. package/dist/mcp/filesystem.d.ts +16 -1
  17. package/dist/mcp/filesystem.js +193 -89
  18. package/dist/mcp/multiLanguageASTParser.d.ts +67 -0
  19. package/dist/mcp/multiLanguageASTParser.js +360 -0
  20. package/dist/mcp/todo.d.ts +1 -1
  21. package/dist/mcp/todo.js +21 -26
  22. package/dist/ui/components/ChatInput.d.ts +4 -1
  23. package/dist/ui/components/ChatInput.js +105 -39
  24. package/dist/ui/components/DiffViewer.d.ts +1 -2
  25. package/dist/ui/components/DiffViewer.js +65 -65
  26. package/dist/ui/components/MCPInfoPanel.js +1 -2
  27. package/dist/ui/components/TodoTree.js +1 -1
  28. package/dist/ui/components/ToolConfirmation.d.ts +11 -1
  29. package/dist/ui/components/ToolConfirmation.js +86 -6
  30. package/dist/ui/pages/ChatScreen.js +223 -108
  31. package/dist/ui/pages/SystemPromptConfigScreen.js +25 -12
  32. package/dist/utils/apiConfig.d.ts +6 -1
  33. package/dist/utils/apiConfig.js +24 -0
  34. package/dist/utils/commands/ide.js +18 -1
  35. package/dist/utils/mcpToolsManager.d.ts +1 -1
  36. package/dist/utils/mcpToolsManager.js +45 -36
  37. package/dist/utils/textBuffer.d.ts +5 -0
  38. package/dist/utils/textBuffer.js +23 -2
  39. package/dist/utils/vscodeConnection.js +10 -1
  40. package/package.json +14 -2
  41. package/readme.md +36 -6
@@ -4,7 +4,6 @@ import { spawn } from 'child_process';
4
4
  import { writeFileSync, readFileSync, existsSync, mkdirSync } from 'fs';
5
5
  import { join } from 'path';
6
6
  import { homedir, platform } from 'os';
7
- import { getOpenAiConfig, updateOpenAiConfig, } from '../../utils/apiConfig.js';
8
7
  import { SYSTEM_PROMPT } from '../../api/systemPrompt.js';
9
8
  const CONFIG_DIR = join(homedir(), '.snow');
10
9
  const SYSTEM_PROMPT_FILE = join(CONFIG_DIR, 'system-prompt.txt');
@@ -24,9 +23,17 @@ export default function SystemPromptConfigScreen({ onBack }) {
24
23
  useEffect(() => {
25
24
  const openEditor = async () => {
26
25
  ensureConfigDirectory();
27
- // 读取当前配置的自定义系统提示词,如果为空则使用默认系统提示词
28
- const config = getOpenAiConfig();
29
- const currentPrompt = config.systemPrompt || SYSTEM_PROMPT;
26
+ // 读取系统提示词文件,如果不存在则使用默认系统提示词
27
+ let currentPrompt = SYSTEM_PROMPT;
28
+ if (existsSync(SYSTEM_PROMPT_FILE)) {
29
+ try {
30
+ currentPrompt = readFileSync(SYSTEM_PROMPT_FILE, 'utf8');
31
+ }
32
+ catch {
33
+ // 读取失败,使用默认
34
+ currentPrompt = SYSTEM_PROMPT;
35
+ }
36
+ }
30
37
  // 写入临时文件供编辑
31
38
  writeFileSync(SYSTEM_PROMPT_FILE, currentPrompt, 'utf8');
32
39
  const editor = getSystemEditor();
@@ -39,22 +46,28 @@ export default function SystemPromptConfigScreen({ onBack }) {
39
46
  if (existsSync(SYSTEM_PROMPT_FILE)) {
40
47
  try {
41
48
  const editedContent = readFileSync(SYSTEM_PROMPT_FILE, 'utf8');
42
- // 如果编辑后的内容为空或与默认提示词相同,则保存为空(使用默认)
43
- // 否则保存自定义提示词
44
49
  const trimmedContent = editedContent.trim();
45
50
  if (trimmedContent === '' || trimmedContent === SYSTEM_PROMPT.trim()) {
46
- // 保存为空,表示使用默认提示词
47
- updateOpenAiConfig({ systemPrompt: undefined });
48
- console.log('System prompt reset to default. Please use `snow` to restart!');
51
+ // 内容为空或与默认相同,删除文件,使用默认提示词
52
+ try {
53
+ const fs = require('fs');
54
+ fs.unlinkSync(SYSTEM_PROMPT_FILE);
55
+ console.log('System prompt reset to default. Please use `snow` to restart!');
56
+ }
57
+ catch {
58
+ // 删除失败,保存空内容
59
+ writeFileSync(SYSTEM_PROMPT_FILE, '', 'utf8');
60
+ console.log('System prompt reset to default. Please use `snow` to restart!');
61
+ }
49
62
  }
50
63
  else {
51
- // 保存自定义提示词
52
- updateOpenAiConfig({ systemPrompt: editedContent });
64
+ // 保存自定义提示词到文件
65
+ writeFileSync(SYSTEM_PROMPT_FILE, editedContent, 'utf8');
53
66
  console.log('Custom system prompt saved successfully! Please use `snow` to restart!');
54
67
  }
55
68
  }
56
69
  catch (error) {
57
- console.error('Failed to read edited content:', error instanceof Error ? error.message : 'Unknown error');
70
+ console.error('Failed to save system prompt:', error instanceof Error ? error.message : 'Unknown error');
58
71
  }
59
72
  }
60
73
  process.exit(0);
@@ -14,7 +14,6 @@ export interface ApiConfig {
14
14
  maxTokens?: number;
15
15
  compactModel?: CompactModelConfig;
16
16
  anthropicBeta?: boolean;
17
- systemPrompt?: string;
18
17
  }
19
18
  export interface MCPServer {
20
19
  url?: string;
@@ -37,3 +36,9 @@ export declare function validateApiConfig(config: Partial<ApiConfig>): string[];
37
36
  export declare function updateMCPConfig(mcpConfig: MCPConfig): void;
38
37
  export declare function getMCPConfig(): MCPConfig;
39
38
  export declare function validateMCPConfig(config: Partial<MCPConfig>): string[];
39
+ /**
40
+ * 读取自定义系统提示词
41
+ * 如果 system-prompt.txt 文件存在且不为空,返回其内容
42
+ * 否则返回 undefined (使用默认系统提示词)
43
+ */
44
+ export declare function getCustomSystemPrompt(): string | undefined;
@@ -17,6 +17,7 @@ const DEFAULT_MCP_CONFIG = {
17
17
  mcpServers: {},
18
18
  };
19
19
  const CONFIG_DIR = join(homedir(), '.snow');
20
+ const SYSTEM_PROMPT_FILE = join(CONFIG_DIR, 'system-prompt.txt');
20
21
  function normalizeRequestMethod(method) {
21
22
  if (method === 'chat' || method === 'responses' || method === 'gemini' || method === 'anthropic') {
22
23
  return method;
@@ -192,3 +193,26 @@ export function validateMCPConfig(config) {
192
193
  }
193
194
  return errors;
194
195
  }
196
+ /**
197
+ * 读取自定义系统提示词
198
+ * 如果 system-prompt.txt 文件存在且不为空,返回其内容
199
+ * 否则返回 undefined (使用默认系统提示词)
200
+ */
201
+ export function getCustomSystemPrompt() {
202
+ ensureConfigDirectory();
203
+ if (!existsSync(SYSTEM_PROMPT_FILE)) {
204
+ return undefined;
205
+ }
206
+ try {
207
+ const content = readFileSync(SYSTEM_PROMPT_FILE, 'utf8');
208
+ // 只有当文件完全为空时才返回 undefined
209
+ if (content.length === 0) {
210
+ return undefined;
211
+ }
212
+ // 返回原始内容,不做任何处理
213
+ return content;
214
+ }
215
+ catch {
216
+ return undefined;
217
+ }
218
+ }
@@ -3,6 +3,7 @@ import { vscodeConnection } from '../vscodeConnection.js';
3
3
  // IDE connection command handler
4
4
  registerCommand('ide', {
5
5
  execute: async () => {
6
+ // Check if already connected
6
7
  if (vscodeConnection.isConnected()) {
7
8
  return {
8
9
  success: true,
@@ -10,15 +11,31 @@ registerCommand('ide', {
10
11
  message: 'Already connected to VSCode editor'
11
12
  };
12
13
  }
14
+ // Check if server is already running (but not connected yet)
15
+ if (vscodeConnection.isServerRunning()) {
16
+ return {
17
+ success: true,
18
+ action: 'info',
19
+ message: `VSCode connection server is already running on port ${vscodeConnection.getPort()}\nWaiting for VSCode extension to connect...`
20
+ };
21
+ }
22
+ // Start the server
13
23
  try {
14
24
  await vscodeConnection.start();
15
25
  return {
16
26
  success: true,
17
27
  action: 'info',
18
- message: `VSCode connection server started on port ${vscodeConnection.getPort()}\nPlease connect from the Snow CLI extension in VSCode`
28
+ message: `VSCode connection server started on port ${vscodeConnection.getPort()}\nWaiting for VSCode extension to connect...`
19
29
  };
20
30
  }
21
31
  catch (error) {
32
+ // Handle EADDRINUSE error specifically
33
+ if (error instanceof Error && 'code' in error && error.code === 'EADDRINUSE') {
34
+ return {
35
+ success: false,
36
+ message: `Port ${vscodeConnection.getPort()} is already in use. Please restart Snow CLI to reset the connection.`
37
+ };
38
+ }
22
39
  return {
23
40
  success: false,
24
41
  message: error instanceof Error ? error.message : 'Failed to start IDE connection'
@@ -1,6 +1,6 @@
1
1
  import { TodoService } from '../mcp/todo.js';
2
2
  export interface MCPTool {
3
- type: "function";
3
+ type: 'function';
4
4
  function: {
5
5
  name: string;
6
6
  description: string;
@@ -42,7 +42,7 @@ function isCacheValid() {
42
42
  if (!toolsCache)
43
43
  return false;
44
44
  const now = Date.now();
45
- const isExpired = (now - toolsCache.lastUpdate) > CACHE_DURATION;
45
+ const isExpired = now - toolsCache.lastUpdate > CACHE_DURATION;
46
46
  const configChanged = toolsCache.configHash !== generateConfigHash();
47
47
  return !isExpired && !configChanged;
48
48
  }
@@ -66,44 +66,44 @@ async function refreshToolsCache() {
66
66
  const filesystemServiceTools = filesystemTools.map(tool => ({
67
67
  name: tool.name.replace('filesystem_', ''),
68
68
  description: tool.description,
69
- inputSchema: tool.inputSchema
69
+ inputSchema: tool.inputSchema,
70
70
  }));
71
71
  servicesInfo.push({
72
72
  serviceName: 'filesystem',
73
73
  tools: filesystemServiceTools,
74
74
  isBuiltIn: true,
75
- connected: true
75
+ connected: true,
76
76
  });
77
77
  for (const tool of filesystemTools) {
78
78
  allTools.push({
79
- type: "function",
79
+ type: 'function',
80
80
  function: {
81
81
  name: `filesystem-${tool.name.replace('filesystem_', '')}`,
82
82
  description: tool.description,
83
- parameters: tool.inputSchema
84
- }
83
+ parameters: tool.inputSchema,
84
+ },
85
85
  });
86
86
  }
87
87
  // Add built-in terminal tools (always available)
88
88
  const terminalServiceTools = terminalTools.map(tool => ({
89
89
  name: tool.name.replace('terminal_', ''),
90
90
  description: tool.description,
91
- inputSchema: tool.inputSchema
91
+ inputSchema: tool.inputSchema,
92
92
  }));
93
93
  servicesInfo.push({
94
94
  serviceName: 'terminal',
95
95
  tools: terminalServiceTools,
96
96
  isBuiltIn: true,
97
- connected: true
97
+ connected: true,
98
98
  });
99
99
  for (const tool of terminalTools) {
100
100
  allTools.push({
101
- type: "function",
101
+ type: 'function',
102
102
  function: {
103
103
  name: `terminal-${tool.name.replace('terminal_', '')}`,
104
104
  description: tool.description,
105
- parameters: tool.inputSchema
106
- }
105
+ parameters: tool.inputSchema,
106
+ },
107
107
  });
108
108
  }
109
109
  // Add built-in TODO tools (always available)
@@ -112,22 +112,22 @@ async function refreshToolsCache() {
112
112
  const todoServiceTools = todoTools.map(tool => ({
113
113
  name: tool.name.replace('todo-', ''),
114
114
  description: tool.description || '',
115
- inputSchema: tool.inputSchema
115
+ inputSchema: tool.inputSchema,
116
116
  }));
117
117
  servicesInfo.push({
118
118
  serviceName: 'todo',
119
119
  tools: todoServiceTools,
120
120
  isBuiltIn: true,
121
- connected: true
121
+ connected: true,
122
122
  });
123
123
  for (const tool of todoTools) {
124
124
  allTools.push({
125
- type: "function",
125
+ type: 'function',
126
126
  function: {
127
127
  name: tool.name,
128
128
  description: tool.description || '',
129
- parameters: tool.inputSchema
130
- }
129
+ parameters: tool.inputSchema,
130
+ },
131
131
  });
132
132
  }
133
133
  // Add user-configured MCP server tools (probe for availability but don't maintain connections)
@@ -140,16 +140,16 @@ async function refreshToolsCache() {
140
140
  serviceName,
141
141
  tools: serviceTools,
142
142
  isBuiltIn: false,
143
- connected: true
143
+ connected: true,
144
144
  });
145
145
  for (const tool of serviceTools) {
146
146
  allTools.push({
147
- type: "function",
147
+ type: 'function',
148
148
  function: {
149
149
  name: `${serviceName}-${tool.name}`,
150
150
  description: tool.description,
151
- parameters: tool.inputSchema
152
- }
151
+ parameters: tool.inputSchema,
152
+ },
153
153
  });
154
154
  }
155
155
  }
@@ -159,7 +159,7 @@ async function refreshToolsCache() {
159
159
  tools: [],
160
160
  isBuiltIn: false,
161
161
  connected: false,
162
- error: error instanceof Error ? error.message : 'Unknown error'
162
+ error: error instanceof Error ? error.message : 'Unknown error',
163
163
  });
164
164
  }
165
165
  }
@@ -172,7 +172,7 @@ async function refreshToolsCache() {
172
172
  tools: allTools,
173
173
  servicesInfo,
174
174
  lastUpdate: Date.now(),
175
- configHash: generateConfigHash()
175
+ configHash: generateConfigHash(),
176
176
  };
177
177
  }
178
178
  /**
@@ -226,7 +226,7 @@ async function connectAndGetTools(serviceName, server, timeoutMs = 10000) {
226
226
  name: `snow-cli-${serviceName}`,
227
227
  version: '1.0.0',
228
228
  }, {
229
- capabilities: {}
229
+ capabilities: {},
230
230
  });
231
231
  // Create transport based on server configuration
232
232
  if (server.url) {
@@ -260,11 +260,11 @@ async function connectAndGetTools(serviceName, server, timeoutMs = 10000) {
260
260
  }
261
261
  }
262
262
  transport = new StreamableHTTPClientTransport(url, {
263
- requestInit: { headers }
263
+ requestInit: { headers },
264
264
  });
265
265
  await Promise.race([
266
266
  client.connect(transport),
267
- new Promise((_, reject) => setTimeout(() => reject(new Error('HTTP connection timeout')), timeoutMs))
267
+ new Promise((_, reject) => setTimeout(() => reject(new Error('HTTP connection timeout')), timeoutMs)),
268
268
  ]);
269
269
  }
270
270
  catch (httpError) {
@@ -277,12 +277,12 @@ async function connectAndGetTools(serviceName, server, timeoutMs = 10000) {
277
277
  name: `snow-cli-${serviceName}`,
278
278
  version: '1.0.0',
279
279
  }, {
280
- capabilities: {}
280
+ capabilities: {},
281
281
  });
282
282
  transport = new SSEClientTransport(url);
283
283
  await Promise.race([
284
284
  client.connect(transport),
285
- new Promise((_, reject) => setTimeout(() => reject(new Error('SSE connection timeout')), timeoutMs))
285
+ new Promise((_, reject) => setTimeout(() => reject(new Error('SSE connection timeout')), timeoutMs)),
286
286
  ]);
287
287
  }
288
288
  }
@@ -309,13 +309,13 @@ async function connectAndGetTools(serviceName, server, timeoutMs = 10000) {
309
309
  // Get tools from the service
310
310
  const toolsResult = await Promise.race([
311
311
  client.listTools(),
312
- new Promise((_, reject) => setTimeout(() => reject(new Error('ListTools timeout')), timeoutMs))
312
+ new Promise((_, reject) => setTimeout(() => reject(new Error('ListTools timeout')), timeoutMs)),
313
313
  ]);
314
- return toolsResult.tools?.map(tool => ({
314
+ return (toolsResult.tools?.map(tool => ({
315
315
  name: tool.name,
316
316
  description: tool.description || '',
317
- inputSchema: tool.inputSchema
318
- })) || [];
317
+ inputSchema: tool.inputSchema,
318
+ })) || []);
319
319
  }
320
320
  finally {
321
321
  try {
@@ -391,8 +391,15 @@ export async function executeMCPTool(toolName, args) {
391
391
  return await filesystemService.getFileInfo(args.filePath);
392
392
  case 'edit':
393
393
  return await filesystemService.editFile(args.filePath, args.startLine, args.endLine, args.newContent, args.contextLines);
394
- case 'search':
395
- return await filesystemService.searchCode(args.query, args.dirPath, args.fileExtensions, args.caseSensitive, args.maxResults);
394
+ case 'search': {
395
+ // 兼容性处理:如果 searchMode 不存在或无效,默认使用 'text'
396
+ const validSearchModes = ['text', 'regex', 'ast'];
397
+ let searchMode = 'text';
398
+ if (args.searchMode && validSearchModes.includes(args.searchMode)) {
399
+ searchMode = args.searchMode;
400
+ }
401
+ return await filesystemService.searchCode(args.query, args.dirPath, args.fileExtensions, args.caseSensitive, args.maxResults, searchMode);
402
+ }
396
403
  default:
397
404
  throw new Error(`Unknown filesystem tool: ${actualToolName}`);
398
405
  }
@@ -430,7 +437,7 @@ async function executeOnExternalMCPService(serviceName, server, toolName, args)
430
437
  name: `snow-cli-${serviceName}`,
431
438
  version: '1.0.0',
432
439
  }, {
433
- capabilities: {}
440
+ capabilities: {},
434
441
  });
435
442
  // Setup transport (similar to getServiceTools)
436
443
  let transport;
@@ -450,7 +457,9 @@ async function executeOnExternalMCPService(serviceName, server, toolName, args)
450
457
  transport = new StdioClientTransport({
451
458
  command: server.command,
452
459
  args: server.args || [],
453
- env: server.env ? { ...process.env, ...server.env } : process.env,
460
+ env: server.env
461
+ ? { ...process.env, ...server.env }
462
+ : process.env,
454
463
  });
455
464
  }
456
465
  await client.connect(transport);
@@ -458,7 +467,7 @@ async function executeOnExternalMCPService(serviceName, server, toolName, args)
458
467
  // Execute the tool with the original tool name (not prefixed)
459
468
  const result = await client.callTool({
460
469
  name: toolName,
461
- arguments: args
470
+ arguments: args,
462
471
  });
463
472
  logger.debug(`result from ${serviceName} tool ${toolName}:`, result);
464
473
  return result.content;
@@ -28,11 +28,16 @@ export declare class TextBuffer {
28
28
  private pasteTimer;
29
29
  private pastePlaceholderPosition;
30
30
  private onUpdateCallback?;
31
+ private isDestroyed;
31
32
  private visualLines;
32
33
  private visualLineStarts;
33
34
  private visualCursorPos;
34
35
  private preferredVisualCol;
35
36
  constructor(viewport: Viewport, onUpdate?: () => void);
37
+ /**
38
+ * Cleanup method to be called when the buffer is no longer needed
39
+ */
40
+ destroy(): void;
36
41
  get text(): string;
37
42
  /**
38
43
  * 获取完整文本,包括替换占位符为原始内容
@@ -79,6 +79,12 @@ export class TextBuffer {
79
79
  writable: true,
80
80
  value: void 0
81
81
  }); // 更新回调函数
82
+ Object.defineProperty(this, "isDestroyed", {
83
+ enumerable: true,
84
+ configurable: true,
85
+ writable: true,
86
+ value: false
87
+ }); // 标记是否已销毁
82
88
  Object.defineProperty(this, "visualLines", {
83
89
  enumerable: true,
84
90
  configurable: true,
@@ -107,6 +113,19 @@ export class TextBuffer {
107
113
  this.onUpdateCallback = onUpdate;
108
114
  this.recalculateVisualState();
109
115
  }
116
+ /**
117
+ * Cleanup method to be called when the buffer is no longer needed
118
+ */
119
+ destroy() {
120
+ this.isDestroyed = true;
121
+ if (this.pasteTimer) {
122
+ clearTimeout(this.pasteTimer);
123
+ this.pasteTimer = null;
124
+ }
125
+ this.pasteStorage.clear();
126
+ this.imageStorage.clear();
127
+ this.onUpdateCallback = undefined;
128
+ }
110
129
  get text() {
111
130
  return this.content;
112
131
  }
@@ -136,7 +155,7 @@ export class TextBuffer {
136
155
  }
137
156
  scheduleUpdate() {
138
157
  // Notify external components of updates
139
- if (this.onUpdateCallback) {
158
+ if (!this.isDestroyed && this.onUpdateCallback) {
140
159
  this.onUpdateCallback();
141
160
  }
142
161
  }
@@ -191,7 +210,9 @@ export class TextBuffer {
191
210
  this.cursorIndex = this.pastePlaceholderPosition + cpLen(tempPlaceholder);
192
211
  // 设置150ms的定时器,如果150ms内没有新数据,则认为粘贴完成
193
212
  this.pasteTimer = setTimeout(() => {
194
- this.finalizePaste();
213
+ if (!this.isDestroyed) {
214
+ this.finalizePaste();
215
+ }
195
216
  }, 150);
196
217
  this.recalculateVisualState();
197
218
  this.scheduleUpdate();
@@ -41,6 +41,10 @@ class VSCodeConnectionManager {
41
41
  try {
42
42
  this.server = new WebSocketServer({ port: this.port });
43
43
  this.server.on('connection', (ws) => {
44
+ // Close old client if exists
45
+ if (this.client && this.client !== ws) {
46
+ this.client.close();
47
+ }
44
48
  this.client = ws;
45
49
  ws.on('message', (message) => {
46
50
  try {
@@ -52,7 +56,12 @@ class VSCodeConnectionManager {
52
56
  }
53
57
  });
54
58
  ws.on('close', () => {
55
- this.client = null;
59
+ if (this.client === ws) {
60
+ this.client = null;
61
+ }
62
+ });
63
+ ws.on('error', () => {
64
+ // Silently handle errors
56
65
  });
57
66
  });
58
67
  this.server.on('listening', () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-ai",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
4
4
  "description": "Intelligent Command Line Assistant powered by AI",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -40,7 +40,7 @@
40
40
  ],
41
41
  "dependencies": {
42
42
  "@anthropic-ai/sdk": "^0.65.0",
43
- "@google/generative-ai": "^0.24.1",
43
+ "@google/genai": "^1.23.0",
44
44
  "@inkjs/ui": "^2.0.0",
45
45
  "@modelcontextprotocol/sdk": "^1.17.3",
46
46
  "chalk-template": "^1.1.2",
@@ -59,6 +59,18 @@
59
59
  "react": "^18.2.0",
60
60
  "string-width": "^7.2.0",
61
61
  "tiktoken": "^1.0.22",
62
+ "tree-sitter": "^0.25.0",
63
+ "tree-sitter-c": "^0.24.1",
64
+ "tree-sitter-c-sharp": "^0.23.1",
65
+ "tree-sitter-cpp": "^0.23.4",
66
+ "tree-sitter-go": "^0.25.0",
67
+ "tree-sitter-java": "^0.23.5",
68
+ "tree-sitter-javascript": "^0.25.0",
69
+ "tree-sitter-php": "^0.24.2",
70
+ "tree-sitter-python": "^0.25.0",
71
+ "tree-sitter-ruby": "^0.23.1",
72
+ "tree-sitter-rust": "^0.24.0",
73
+ "tree-sitter-typescript": "^0.23.2",
62
74
  "ws": "^8.14.2"
63
75
  },
64
76
  "devDependencies": {
package/readme.md CHANGED
@@ -1,6 +1,17 @@
1
+ <div align="center">
2
+
3
+ <img src="logo.png" alt="Snow AI CLI Logo" width="200"/>
4
+
1
5
  # snow-ai
2
6
 
3
- > This readme is automatically generated by [create-ink-app](https://github.com/vadimdemedes/create-ink-app)
7
+ **English** | [中文](readme_zh.md)
8
+
9
+ *An intelligent AI-powered CLI tool for developers*
10
+
11
+ </div>
12
+
13
+ ---
14
+
4
15
 
5
16
  ## Install
6
17
 
@@ -21,15 +32,17 @@ $ snow --update
21
32
  ## Config example `./User/.snow/config.json`
22
33
  ```json
23
34
  {
24
- "openai": {
25
- "baseUrl": "https://api.openai.com/v1",
35
+ "snowcfg": {
36
+ "baseUrl": "https://api.openai.com/v1",//Gemini:https://generativelanguage.googleapis.com Anthropic:https://api.anthropic.com
26
37
  "apiKey": "your-api-key",
27
38
  "requestMethod": "responses",
28
39
  "advancedModel": "gpt-5-codex",
29
40
  "basicModel": "gpt-5-codex",
30
- "maxContextTokens": 200000,
41
+ "maxContextTokens": 32000, //The maximum context length of the model
42
+ "maxTokens": 4096, // The maximum generation length of the model
43
+ "anthropicBeta": false,
31
44
  "compactModel": {
32
- "baseUrl": "https://api.openai.com/v1",
45
+ "baseUrl": "https://api.opeai.com/v1",
33
46
  "apiKey": "your-api-key",
34
47
  "modelName": "gpt-4.1-mini"
35
48
  }
@@ -56,7 +69,24 @@ $ npm uninstall --global snow-ai
56
69
  * **Agent**
57
70
 
58
71
  ![alt text](image-1.png)
72
+ * In the middle of the conversation: click ESC to stop AI generation
73
+
74
+ * When mounting: double-click ESC, view the dialogue recorder, select rollback, including file checkpoints
59
75
 
60
76
  * **Commands**
61
77
 
62
- ![alt text](image-2.png)
78
+ ![alt text](image-2.png)
79
+ - /clear - Create a new session
80
+
81
+ - /resume - The recovery history has
82
+
83
+ - /mcp - Check the status of MCP service
84
+
85
+ - /yolo - Unattended mode, all tools automatically agree to execute
86
+
87
+ - /init - Initialize the project and generate the SNOW.md description document
88
+
89
+ - /ide - Connect to VSCode, you need to install the plug-in
90
+
91
+ - /compact - compress the context into a sentence
92
+