snow-ai 0.3.6 → 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 (127) hide show
  1. package/dist/agents/compactAgent.js +7 -3
  2. package/dist/agents/reviewAgent.d.ts +50 -0
  3. package/dist/agents/reviewAgent.js +264 -0
  4. package/dist/agents/summaryAgent.d.ts +34 -8
  5. package/dist/agents/summaryAgent.js +167 -164
  6. package/dist/api/anthropic.d.ts +1 -0
  7. package/dist/api/anthropic.js +118 -78
  8. package/dist/api/chat.d.ts +2 -1
  9. package/dist/api/chat.js +82 -52
  10. package/dist/api/gemini.d.ts +1 -0
  11. package/dist/api/gemini.js +110 -64
  12. package/dist/api/responses.d.ts +10 -1
  13. package/dist/api/responses.js +127 -79
  14. package/dist/api/systemPrompt.d.ts +1 -1
  15. package/dist/api/systemPrompt.js +36 -7
  16. package/dist/api/types.d.ts +8 -0
  17. package/dist/app.js +15 -2
  18. package/dist/hooks/useCommandHandler.d.ts +1 -0
  19. package/dist/hooks/useCommandHandler.js +102 -1
  20. package/dist/hooks/useCommandPanel.d.ts +2 -1
  21. package/dist/hooks/useCommandPanel.js +19 -1
  22. package/dist/hooks/useConversation.d.ts +4 -1
  23. package/dist/hooks/useConversation.js +91 -29
  24. package/dist/hooks/useKeyboardInput.js +19 -0
  25. package/dist/hooks/useSnapshotState.d.ts +2 -0
  26. package/dist/hooks/useTerminalFocus.js +13 -3
  27. package/dist/mcp/aceCodeSearch.d.ts +2 -76
  28. package/dist/mcp/aceCodeSearch.js +31 -467
  29. package/dist/mcp/bash.d.ts +1 -8
  30. package/dist/mcp/bash.js +20 -40
  31. package/dist/mcp/filesystem.d.ts +131 -111
  32. package/dist/mcp/filesystem.js +212 -375
  33. package/dist/mcp/ideDiagnostics.js +2 -4
  34. package/dist/mcp/todo.d.ts +1 -17
  35. package/dist/mcp/todo.js +11 -15
  36. package/dist/mcp/types/aceCodeSearch.types.d.ts +92 -0
  37. package/dist/mcp/types/aceCodeSearch.types.js +4 -0
  38. package/dist/mcp/types/bash.types.d.ts +13 -0
  39. package/dist/mcp/types/bash.types.js +4 -0
  40. package/dist/mcp/types/filesystem.types.d.ts +135 -0
  41. package/dist/mcp/types/filesystem.types.js +4 -0
  42. package/dist/mcp/types/todo.types.d.ts +27 -0
  43. package/dist/mcp/types/todo.types.js +4 -0
  44. package/dist/mcp/types/websearch.types.d.ts +30 -0
  45. package/dist/mcp/types/websearch.types.js +4 -0
  46. package/dist/mcp/utils/aceCodeSearch/filesystem.utils.d.ts +34 -0
  47. package/dist/mcp/utils/aceCodeSearch/filesystem.utils.js +146 -0
  48. package/dist/mcp/utils/aceCodeSearch/language.utils.d.ts +14 -0
  49. package/dist/mcp/utils/aceCodeSearch/language.utils.js +99 -0
  50. package/dist/mcp/utils/aceCodeSearch/search.utils.d.ts +31 -0
  51. package/dist/mcp/utils/aceCodeSearch/search.utils.js +136 -0
  52. package/dist/mcp/utils/aceCodeSearch/symbol.utils.d.ts +20 -0
  53. package/dist/mcp/utils/aceCodeSearch/symbol.utils.js +141 -0
  54. package/dist/mcp/utils/bash/security.utils.d.ts +20 -0
  55. package/dist/mcp/utils/bash/security.utils.js +34 -0
  56. package/dist/mcp/utils/filesystem/batch-operations.utils.d.ts +39 -0
  57. package/dist/mcp/utils/filesystem/batch-operations.utils.js +182 -0
  58. package/dist/mcp/utils/filesystem/code-analysis.utils.d.ts +18 -0
  59. package/dist/mcp/utils/filesystem/code-analysis.utils.js +165 -0
  60. package/dist/mcp/utils/filesystem/match-finder.utils.d.ts +16 -0
  61. package/dist/mcp/utils/filesystem/match-finder.utils.js +85 -0
  62. package/dist/mcp/utils/filesystem/similarity.utils.d.ts +22 -0
  63. package/dist/mcp/utils/filesystem/similarity.utils.js +75 -0
  64. package/dist/mcp/utils/todo/date.utils.d.ts +9 -0
  65. package/dist/mcp/utils/todo/date.utils.js +14 -0
  66. package/dist/mcp/utils/websearch/browser.utils.d.ts +8 -0
  67. package/dist/mcp/utils/websearch/browser.utils.js +58 -0
  68. package/dist/mcp/utils/websearch/text.utils.d.ts +16 -0
  69. package/dist/mcp/utils/websearch/text.utils.js +39 -0
  70. package/dist/mcp/websearch.d.ts +1 -31
  71. package/dist/mcp/websearch.js +21 -97
  72. package/dist/ui/components/ChatInput.d.ts +3 -1
  73. package/dist/ui/components/ChatInput.js +12 -5
  74. package/dist/ui/components/CommandPanel.d.ts +2 -1
  75. package/dist/ui/components/CommandPanel.js +18 -3
  76. package/dist/ui/components/MarkdownRenderer.d.ts +1 -2
  77. package/dist/ui/components/MarkdownRenderer.js +25 -153
  78. package/dist/ui/components/MessageList.js +5 -5
  79. package/dist/ui/components/PendingMessages.js +1 -1
  80. package/dist/ui/components/PendingToolCalls.d.ts +11 -0
  81. package/dist/ui/components/PendingToolCalls.js +35 -0
  82. package/dist/ui/components/SessionListScreen.js +37 -17
  83. package/dist/ui/components/ToolResultPreview.d.ts +1 -1
  84. package/dist/ui/components/ToolResultPreview.js +119 -155
  85. package/dist/ui/components/UsagePanel.d.ts +2 -0
  86. package/dist/ui/components/UsagePanel.js +360 -0
  87. package/dist/ui/pages/ChatScreen.d.ts +5 -0
  88. package/dist/ui/pages/ChatScreen.js +164 -85
  89. package/dist/ui/pages/ConfigScreen.js +23 -19
  90. package/dist/ui/pages/HeadlessModeScreen.js +2 -4
  91. package/dist/ui/pages/SubAgentConfigScreen.js +17 -17
  92. package/dist/ui/pages/SystemPromptConfigScreen.js +7 -6
  93. package/dist/utils/chatExporter.d.ts +9 -0
  94. package/dist/utils/chatExporter.js +126 -0
  95. package/dist/utils/commandExecutor.d.ts +3 -3
  96. package/dist/utils/commandExecutor.js +4 -4
  97. package/dist/utils/commands/export.d.ts +2 -0
  98. package/dist/utils/commands/export.js +12 -0
  99. package/dist/utils/commands/home.d.ts +2 -0
  100. package/dist/utils/commands/home.js +12 -0
  101. package/dist/utils/commands/init.js +3 -3
  102. package/dist/utils/commands/review.d.ts +2 -0
  103. package/dist/utils/commands/review.js +81 -0
  104. package/dist/utils/commands/role.d.ts +2 -0
  105. package/dist/utils/commands/role.js +37 -0
  106. package/dist/utils/commands/usage.d.ts +2 -0
  107. package/dist/utils/commands/usage.js +12 -0
  108. package/dist/utils/contextCompressor.js +99 -367
  109. package/dist/utils/fileDialog.d.ts +9 -0
  110. package/dist/utils/fileDialog.js +74 -0
  111. package/dist/utils/incrementalSnapshot.d.ts +7 -0
  112. package/dist/utils/incrementalSnapshot.js +35 -0
  113. package/dist/utils/mcpToolsManager.js +12 -12
  114. package/dist/utils/messageFormatter.js +89 -6
  115. package/dist/utils/proxyUtils.d.ts +15 -0
  116. package/dist/utils/proxyUtils.js +50 -0
  117. package/dist/utils/retryUtils.d.ts +27 -0
  118. package/dist/utils/retryUtils.js +114 -2
  119. package/dist/utils/sessionConverter.js +11 -0
  120. package/dist/utils/sessionManager.d.ts +7 -5
  121. package/dist/utils/sessionManager.js +60 -82
  122. package/dist/utils/terminal.js +4 -3
  123. package/dist/utils/toolDisplayConfig.d.ts +16 -0
  124. package/dist/utils/toolDisplayConfig.js +42 -0
  125. package/dist/utils/usageLogger.d.ts +11 -0
  126. package/dist/utils/usageLogger.js +99 -0
  127. package/package.json +3 -7
@@ -101,19 +101,22 @@ export class CompactAgent {
101
101
  model: this.modelName,
102
102
  messages,
103
103
  max_tokens: 4096,
104
+ includeBuiltinSystemPrompt: false, // 不需要内置系统提示词
104
105
  }, abortSignal);
105
106
  break;
106
107
  case 'gemini':
107
108
  streamGenerator = createStreamingGeminiCompletion({
108
109
  model: this.modelName,
109
- messages
110
+ messages,
111
+ includeBuiltinSystemPrompt: false, // 不需要内置系统提示词
110
112
  }, abortSignal);
111
113
  break;
112
114
  case 'responses':
113
115
  streamGenerator = createStreamingResponse({
114
116
  model: this.modelName,
115
117
  messages,
116
- stream: true
118
+ stream: true,
119
+ includeBuiltinSystemPrompt: false, // 不需要内置系统提示词
117
120
  }, abortSignal);
118
121
  break;
119
122
  case 'chat':
@@ -121,7 +124,8 @@ export class CompactAgent {
121
124
  streamGenerator = createStreamingChatCompletion({
122
125
  model: this.modelName,
123
126
  messages,
124
- stream: true
127
+ stream: true,
128
+ includeBuiltinSystemPrompt: false, // 不需要内置系统提示词
125
129
  }, abortSignal);
126
130
  break;
127
131
  }
@@ -0,0 +1,50 @@
1
+ export declare class ReviewAgent {
2
+ private modelName;
3
+ private requestMethod;
4
+ private initialized;
5
+ /**
6
+ * Initialize the review agent with current configuration
7
+ * Uses advanced model (same as main flow)
8
+ */
9
+ private initialize;
10
+ /**
11
+ * Check if review agent is available
12
+ */
13
+ isAvailable(): Promise<boolean>;
14
+ /**
15
+ * Check if current directory or any parent directory is a git repository
16
+ * @param startDir - Starting directory to check
17
+ * @returns Path to git root directory, or null if not found
18
+ */
19
+ private findGitRoot;
20
+ /**
21
+ * Check if git is available and current directory is in a git repository
22
+ * @returns Object with isGitRepo flag and optional error message
23
+ */
24
+ checkGitRepository(): {
25
+ isGitRepo: boolean;
26
+ gitRoot?: string;
27
+ error?: string;
28
+ };
29
+ /**
30
+ * Get git diff for uncommitted changes
31
+ * @param gitRoot - Git repository root directory
32
+ * @returns Git diff output
33
+ */
34
+ getGitDiff(gitRoot: string): string;
35
+ /**
36
+ * Generate code review prompt
37
+ */
38
+ private generateReviewPrompt;
39
+ /**
40
+ * Call the advanced model with streaming (same routing as main flow)
41
+ */
42
+ private callAdvancedModel;
43
+ /**
44
+ * Review git changes and return streaming generator
45
+ * @param abortSignal - Optional abort signal
46
+ * @returns Async generator for streaming response
47
+ */
48
+ reviewChanges(abortSignal?: AbortSignal): AsyncGenerator<any, void, unknown>;
49
+ }
50
+ export declare const reviewAgent: ReviewAgent;
@@ -0,0 +1,264 @@
1
+ import { getOpenAiConfig, getCustomSystemPrompt } from '../utils/apiConfig.js';
2
+ import { logger } from '../utils/logger.js';
3
+ import { createStreamingChatCompletion } from '../api/chat.js';
4
+ import { createStreamingResponse } from '../api/responses.js';
5
+ import { createStreamingGeminiCompletion } from '../api/gemini.js';
6
+ import { createStreamingAnthropicCompletion } from '../api/anthropic.js';
7
+ import { execSync } from 'child_process';
8
+ import * as path from 'path';
9
+ import * as fs from 'fs';
10
+ export class ReviewAgent {
11
+ constructor() {
12
+ Object.defineProperty(this, "modelName", {
13
+ enumerable: true,
14
+ configurable: true,
15
+ writable: true,
16
+ value: ''
17
+ });
18
+ Object.defineProperty(this, "requestMethod", {
19
+ enumerable: true,
20
+ configurable: true,
21
+ writable: true,
22
+ value: 'chat'
23
+ });
24
+ Object.defineProperty(this, "initialized", {
25
+ enumerable: true,
26
+ configurable: true,
27
+ writable: true,
28
+ value: false
29
+ });
30
+ }
31
+ /**
32
+ * Initialize the review agent with current configuration
33
+ * Uses advanced model (same as main flow)
34
+ */
35
+ async initialize() {
36
+ try {
37
+ const config = getOpenAiConfig();
38
+ if (!config.advancedModel) {
39
+ return false;
40
+ }
41
+ this.modelName = config.advancedModel;
42
+ this.requestMethod = config.requestMethod;
43
+ this.initialized = true;
44
+ return true;
45
+ }
46
+ catch (error) {
47
+ logger.warn('Failed to initialize review agent:', error);
48
+ return false;
49
+ }
50
+ }
51
+ /**
52
+ * Check if review agent is available
53
+ */
54
+ async isAvailable() {
55
+ if (!this.initialized) {
56
+ return await this.initialize();
57
+ }
58
+ return true;
59
+ }
60
+ /**
61
+ * Check if current directory or any parent directory is a git repository
62
+ * @param startDir - Starting directory to check
63
+ * @returns Path to git root directory, or null if not found
64
+ */
65
+ findGitRoot(startDir) {
66
+ let currentDir = path.resolve(startDir);
67
+ const root = path.parse(currentDir).root;
68
+ while (currentDir !== root) {
69
+ const gitDir = path.join(currentDir, '.git');
70
+ if (fs.existsSync(gitDir)) {
71
+ return currentDir;
72
+ }
73
+ currentDir = path.dirname(currentDir);
74
+ }
75
+ return null;
76
+ }
77
+ /**
78
+ * Check if git is available and current directory is in a git repository
79
+ * @returns Object with isGitRepo flag and optional error message
80
+ */
81
+ checkGitRepository() {
82
+ try {
83
+ // Check if git command is available
84
+ try {
85
+ execSync('git --version', { stdio: 'ignore' });
86
+ }
87
+ catch {
88
+ return {
89
+ isGitRepo: false,
90
+ error: 'Git is not installed or not available in PATH',
91
+ };
92
+ }
93
+ // Find git root directory (check current and parent directories)
94
+ const gitRoot = this.findGitRoot(process.cwd());
95
+ if (!gitRoot) {
96
+ return {
97
+ isGitRepo: false,
98
+ error: 'Current directory is not in a git repository. Please run this command from within a git repository.',
99
+ };
100
+ }
101
+ return { isGitRepo: true, gitRoot };
102
+ }
103
+ catch (error) {
104
+ return {
105
+ isGitRepo: false,
106
+ error: error instanceof Error
107
+ ? error.message
108
+ : 'Failed to check git repository',
109
+ };
110
+ }
111
+ }
112
+ /**
113
+ * Get git diff for uncommitted changes
114
+ * @param gitRoot - Git repository root directory
115
+ * @returns Git diff output
116
+ */
117
+ getGitDiff(gitRoot) {
118
+ try {
119
+ // Get staged changes
120
+ const stagedDiff = execSync('git diff --cached', {
121
+ cwd: gitRoot,
122
+ encoding: 'utf-8',
123
+ maxBuffer: 10 * 1024 * 1024, // 10MB buffer
124
+ });
125
+ // Get unstaged changes
126
+ const unstagedDiff = execSync('git diff', {
127
+ cwd: gitRoot,
128
+ encoding: 'utf-8',
129
+ maxBuffer: 10 * 1024 * 1024,
130
+ });
131
+ // Combine both diffs
132
+ let combinedDiff = '';
133
+ if (stagedDiff) {
134
+ combinedDiff += '# Staged Changes\n\n' + stagedDiff + '\n\n';
135
+ }
136
+ if (unstagedDiff) {
137
+ combinedDiff += '# Unstaged Changes\n\n' + unstagedDiff;
138
+ }
139
+ if (!combinedDiff) {
140
+ return 'No changes detected in the repository.';
141
+ }
142
+ return combinedDiff;
143
+ }
144
+ catch (error) {
145
+ logger.error('Failed to get git diff:', error);
146
+ throw new Error('Failed to get git changes: ' +
147
+ (error instanceof Error ? error.message : 'Unknown error'));
148
+ }
149
+ }
150
+ /**
151
+ * Generate code review prompt
152
+ */
153
+ generateReviewPrompt(gitDiff) {
154
+ return `You are a senior code reviewer. Please review the following git changes and provide feedback.
155
+
156
+ **Your task:**
157
+ 1. Identify potential bugs, security issues, or logic errors
158
+ 2. Suggest performance optimizations
159
+ 3. Point out code quality issues (readability, maintainability)
160
+ 4. Check for best practices violations
161
+ 5. Highlight any breaking changes or compatibility issues
162
+
163
+ **Important:**
164
+ - DO NOT modify the code yourself
165
+ - Focus on finding issues and suggesting improvements
166
+ - Ask the user if they want to fix any issues you find
167
+ - Be constructive and specific in your feedback
168
+ - Prioritize critical issues over minor style preferences
169
+
170
+ **Git Changes:**
171
+
172
+ \`\`\`diff
173
+ ${gitDiff}
174
+ \`\`\`
175
+
176
+ Please provide your review in a clear, structured format.`;
177
+ }
178
+ /**
179
+ * Call the advanced model with streaming (same routing as main flow)
180
+ */
181
+ async *callAdvancedModel(messages, abortSignal) {
182
+ const config = getOpenAiConfig();
183
+ if (!config.advancedModel) {
184
+ throw new Error('Advanced model not configured');
185
+ }
186
+ // Get custom system prompt if configured
187
+ const customSystemPrompt = getCustomSystemPrompt();
188
+ // If custom system prompt exists, prepend it to messages
189
+ let processedMessages = messages;
190
+ if (customSystemPrompt) {
191
+ processedMessages = [
192
+ {
193
+ role: 'system',
194
+ content: customSystemPrompt,
195
+ },
196
+ ...messages,
197
+ ];
198
+ }
199
+ // Route to appropriate streaming API based on request method
200
+ switch (this.requestMethod) {
201
+ case 'anthropic':
202
+ yield* createStreamingAnthropicCompletion({
203
+ model: this.modelName,
204
+ messages: processedMessages,
205
+ max_tokens: 4096,
206
+ }, abortSignal);
207
+ break;
208
+ case 'gemini':
209
+ yield* createStreamingGeminiCompletion({
210
+ model: this.modelName,
211
+ messages: processedMessages,
212
+ }, abortSignal);
213
+ break;
214
+ case 'responses':
215
+ yield* createStreamingResponse({
216
+ model: this.modelName,
217
+ messages: processedMessages,
218
+ stream: true,
219
+ }, abortSignal);
220
+ break;
221
+ case 'chat':
222
+ default:
223
+ yield* createStreamingChatCompletion({
224
+ model: this.modelName,
225
+ messages: processedMessages,
226
+ stream: true,
227
+ }, abortSignal);
228
+ break;
229
+ }
230
+ }
231
+ /**
232
+ * Review git changes and return streaming generator
233
+ * @param abortSignal - Optional abort signal
234
+ * @returns Async generator for streaming response
235
+ */
236
+ async *reviewChanges(abortSignal) {
237
+ const available = await this.isAvailable();
238
+ if (!available) {
239
+ throw new Error('Review agent is not available');
240
+ }
241
+ // Check git repository
242
+ const gitCheck = this.checkGitRepository();
243
+ if (!gitCheck.isGitRepo) {
244
+ throw new Error(gitCheck.error || 'Not a git repository');
245
+ }
246
+ // Get git diff
247
+ const gitDiff = this.getGitDiff(gitCheck.gitRoot);
248
+ if (gitDiff === 'No changes detected in the repository.') {
249
+ throw new Error('No changes detected. Please make some changes before running code review.');
250
+ }
251
+ // Generate review prompt
252
+ const reviewPrompt = this.generateReviewPrompt(gitDiff);
253
+ const messages = [
254
+ {
255
+ role: 'user',
256
+ content: reviewPrompt,
257
+ },
258
+ ];
259
+ // Stream the response
260
+ yield* this.callAdvancedModel(messages, abortSignal);
261
+ }
262
+ }
263
+ // Export singleton instance
264
+ export const reviewAgent = new ReviewAgent();
@@ -1,3 +1,16 @@
1
+ /**
2
+ * Summary Agent Service
3
+ *
4
+ * Generates concise summaries for conversations after the first user-assistant exchange.
5
+ * This service operates in the background without blocking the main conversation flow.
6
+ *
7
+ * Features:
8
+ * - Uses basicModel for efficient, low-cost summarization
9
+ * - Follows the same API routing as main flow (chat, responses, gemini, anthropic)
10
+ * - Generates title (max 50 chars) and summary (max 150 chars)
11
+ * - Only runs once after the first complete conversation exchange
12
+ * - Silent execution with error handling to prevent main flow disruption
13
+ */
1
14
  export declare class SummaryAgent {
2
15
  private modelName;
3
16
  private requestMethod;
@@ -12,20 +25,33 @@ export declare class SummaryAgent {
12
25
  */
13
26
  isAvailable(): Promise<boolean>;
14
27
  /**
15
- * Call the basic model with the same routing as main flow
16
- * Uses streaming APIs and intercepts to assemble complete response
17
- * This ensures 100% consistency with main flow routing
28
+ * Call the model with streaming API and assemble complete response
29
+ * Uses the same routing logic as main flow for consistency
30
+ *
18
31
  * @param messages - Chat messages
19
32
  * @param abortSignal - Optional abort signal to cancel the request
20
33
  */
21
- private callBasicModel;
34
+ private callModel;
22
35
  /**
23
- * Generate a concise summary from the first user message
36
+ * Generate title and summary for a conversation
24
37
  *
25
- * @param userMessage - The first user message in the conversation
38
+ * @param userMessage - User's first message content
39
+ * @param assistantMessage - Assistant's first response content
26
40
  * @param abortSignal - Optional abort signal to cancel generation
27
- * @returns A concise summary (10-20 words) suitable for session title
41
+ * @returns Object containing title and summary, or null if generation fails
42
+ */
43
+ generateSummary(userMessage: string, assistantMessage: string, abortSignal?: AbortSignal): Promise<{
44
+ title: string;
45
+ summary: string;
46
+ } | null>;
47
+ /**
48
+ * Generate fallback summary when AI generation fails
49
+ * Simply truncates the user message for title and summary
50
+ */
51
+ private generateFallbackSummary;
52
+ /**
53
+ * Truncate string to specified length, adding ellipsis if truncated
28
54
  */
29
- generateSummary(userMessage: string, abortSignal?: AbortSignal): Promise<string>;
55
+ private truncateString;
30
56
  }
31
57
  export declare const summaryAgent: SummaryAgent;