snow-ai 0.2.15 → 0.2.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/anthropic.d.ts +1 -1
- package/dist/api/anthropic.js +52 -76
- package/dist/api/chat.d.ts +4 -4
- package/dist/api/chat.js +32 -17
- package/dist/api/gemini.d.ts +1 -1
- package/dist/api/gemini.js +20 -13
- package/dist/api/responses.d.ts +5 -5
- package/dist/api/responses.js +29 -27
- package/dist/app.js +4 -1
- package/dist/hooks/useClipboard.d.ts +4 -0
- package/dist/hooks/useClipboard.js +120 -0
- package/dist/hooks/useCommandHandler.d.ts +26 -0
- package/dist/hooks/useCommandHandler.js +158 -0
- package/dist/hooks/useCommandPanel.d.ts +16 -0
- package/dist/hooks/useCommandPanel.js +53 -0
- package/dist/hooks/useConversation.d.ts +9 -1
- package/dist/hooks/useConversation.js +152 -58
- package/dist/hooks/useFilePicker.d.ts +17 -0
- package/dist/hooks/useFilePicker.js +91 -0
- package/dist/hooks/useHistoryNavigation.d.ts +21 -0
- package/dist/hooks/useHistoryNavigation.js +50 -0
- package/dist/hooks/useInputBuffer.d.ts +6 -0
- package/dist/hooks/useInputBuffer.js +29 -0
- package/dist/hooks/useKeyboardInput.d.ts +51 -0
- package/dist/hooks/useKeyboardInput.js +272 -0
- package/dist/hooks/useSnapshotState.d.ts +12 -0
- package/dist/hooks/useSnapshotState.js +28 -0
- package/dist/hooks/useStreamingState.d.ts +24 -0
- package/dist/hooks/useStreamingState.js +96 -0
- package/dist/hooks/useVSCodeState.d.ts +8 -0
- package/dist/hooks/useVSCodeState.js +63 -0
- package/dist/mcp/filesystem.d.ts +24 -5
- package/dist/mcp/filesystem.js +52 -17
- package/dist/mcp/todo.js +4 -8
- package/dist/ui/components/ChatInput.js +68 -557
- package/dist/ui/components/DiffViewer.js +57 -30
- package/dist/ui/components/FileList.js +70 -26
- package/dist/ui/components/MessageList.d.ts +6 -0
- package/dist/ui/components/MessageList.js +47 -15
- package/dist/ui/components/ShimmerText.d.ts +9 -0
- package/dist/ui/components/ShimmerText.js +30 -0
- package/dist/ui/components/TodoTree.d.ts +1 -1
- package/dist/ui/components/TodoTree.js +0 -4
- package/dist/ui/components/ToolConfirmation.js +14 -6
- package/dist/ui/pages/ChatScreen.js +159 -359
- package/dist/ui/pages/CustomHeadersScreen.d.ts +6 -0
- package/dist/ui/pages/CustomHeadersScreen.js +104 -0
- package/dist/ui/pages/WelcomeScreen.js +5 -0
- package/dist/utils/apiConfig.d.ts +10 -0
- package/dist/utils/apiConfig.js +51 -0
- package/dist/utils/incrementalSnapshot.d.ts +8 -0
- package/dist/utils/incrementalSnapshot.js +63 -0
- package/dist/utils/mcpToolsManager.js +6 -1
- package/dist/utils/retryUtils.d.ts +22 -0
- package/dist/utils/retryUtils.js +180 -0
- package/dist/utils/sessionConverter.js +80 -17
- package/dist/utils/sessionManager.js +35 -4
- package/dist/utils/textUtils.d.ts +4 -0
- package/dist/utils/textUtils.js +19 -0
- package/dist/utils/todoPreprocessor.d.ts +1 -1
- package/dist/utils/todoPreprocessor.js +0 -1
- package/dist/utils/vscodeConnection.d.ts +8 -0
- package/dist/utils/vscodeConnection.js +44 -0
- package/package.json +1 -1
- package/readme.md +3 -1
|
@@ -101,10 +101,41 @@ class SessionManager {
|
|
|
101
101
|
this.currentSession = await this.createNewSession();
|
|
102
102
|
}
|
|
103
103
|
// Check if this exact message already exists to prevent duplicates
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
// For assistant messages with tool_calls, also compare tool_call_id to ensure uniqueness
|
|
105
|
+
const existingMessage = this.currentSession.messages.find(m => {
|
|
106
|
+
if (m.role !== message.role)
|
|
107
|
+
return false;
|
|
108
|
+
if (m.content !== message.content)
|
|
109
|
+
return false;
|
|
110
|
+
if (Math.abs(m.timestamp - message.timestamp) >= 5000)
|
|
111
|
+
return false;
|
|
112
|
+
// If both messages have tool_calls, compare tool call IDs
|
|
113
|
+
if (m.tool_calls && message.tool_calls) {
|
|
114
|
+
// Create sets of tool call IDs for comparison
|
|
115
|
+
const existingIds = new Set(m.tool_calls.map(tc => tc.id));
|
|
116
|
+
const newIds = new Set(message.tool_calls.map(tc => tc.id));
|
|
117
|
+
// If IDs are different, these are different messages
|
|
118
|
+
if (existingIds.size !== newIds.size)
|
|
119
|
+
return false;
|
|
120
|
+
for (const id of newIds) {
|
|
121
|
+
if (!existingIds.has(id))
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else if (m.tool_calls || message.tool_calls) {
|
|
126
|
+
// One has tool_calls, the other doesn't - different messages
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
// If both have tool_call_id (tool response), compare them
|
|
130
|
+
if (m.tool_call_id && message.tool_call_id) {
|
|
131
|
+
return m.tool_call_id === message.tool_call_id;
|
|
132
|
+
}
|
|
133
|
+
else if (m.tool_call_id || message.tool_call_id) {
|
|
134
|
+
// One has tool_call_id, the other doesn't - different messages
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
return true;
|
|
138
|
+
});
|
|
108
139
|
if (existingMessage) {
|
|
109
140
|
return; // Don't add duplicate message
|
|
110
141
|
}
|
|
@@ -31,3 +31,7 @@ export declare function codePointToVisualPos(str: string, codePointIndex: number
|
|
|
31
31
|
* Convert visual position to code point index.
|
|
32
32
|
*/
|
|
33
33
|
export declare function visualPosToCodePoint(str: string, visualPos: number): number;
|
|
34
|
+
/**
|
|
35
|
+
* Format elapsed time to human readable format.
|
|
36
|
+
*/
|
|
37
|
+
export declare function formatElapsedTime(seconds: number): string;
|
package/dist/utils/textUtils.js
CHANGED
|
@@ -81,3 +81,22 @@ export function visualPosToCodePoint(str, visualPos) {
|
|
|
81
81
|
}
|
|
82
82
|
return codePoints.length;
|
|
83
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Format elapsed time to human readable format.
|
|
86
|
+
*/
|
|
87
|
+
export function formatElapsedTime(seconds) {
|
|
88
|
+
if (seconds < 60) {
|
|
89
|
+
return `${seconds}s`;
|
|
90
|
+
}
|
|
91
|
+
else if (seconds < 3600) {
|
|
92
|
+
const minutes = Math.floor(seconds / 60);
|
|
93
|
+
const remainingSeconds = seconds % 60;
|
|
94
|
+
return `${minutes}m ${remainingSeconds}s`;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const hours = Math.floor(seconds / 3600);
|
|
98
|
+
const remainingMinutes = Math.floor((seconds % 3600) / 60);
|
|
99
|
+
const remainingSeconds = seconds % 60;
|
|
100
|
+
return `${hours}h ${remainingMinutes}m ${remainingSeconds}s`;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -36,6 +36,14 @@ declare class VSCodeConnectionManager {
|
|
|
36
36
|
* @returns Promise that resolves with diagnostics array
|
|
37
37
|
*/
|
|
38
38
|
requestDiagnostics(filePath: string): Promise<Diagnostic[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Request DIFF+APPLY view for file changes in VS Code
|
|
41
|
+
* @param filePath - The file path for the diff
|
|
42
|
+
* @param oldContent - Original content with line numbers
|
|
43
|
+
* @param newContent - Modified content with line numbers
|
|
44
|
+
* @returns Promise that resolves with user's approval response
|
|
45
|
+
*/
|
|
46
|
+
requestDiffApply(filePath: string, oldContent: string, newContent: string): Promise<'approve' | 'approve_always' | 'reject'>;
|
|
39
47
|
}
|
|
40
48
|
export declare const vscodeConnection: VSCodeConnectionManager;
|
|
41
49
|
export type { EditorContext, Diagnostic };
|
|
@@ -160,5 +160,49 @@ class VSCodeConnectionManager {
|
|
|
160
160
|
}));
|
|
161
161
|
});
|
|
162
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* Request DIFF+APPLY view for file changes in VS Code
|
|
165
|
+
* @param filePath - The file path for the diff
|
|
166
|
+
* @param oldContent - Original content with line numbers
|
|
167
|
+
* @param newContent - Modified content with line numbers
|
|
168
|
+
* @returns Promise that resolves with user's approval response
|
|
169
|
+
*/
|
|
170
|
+
async requestDiffApply(filePath, oldContent, newContent) {
|
|
171
|
+
return new Promise((resolve) => {
|
|
172
|
+
if (!this.client || this.client.readyState !== WebSocket.OPEN) {
|
|
173
|
+
resolve('approve'); // If not connected, default to approve (fallback to CLI confirmation)
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const requestId = Math.random().toString(36).substring(7);
|
|
177
|
+
const timeout = setTimeout(() => {
|
|
178
|
+
cleanup();
|
|
179
|
+
resolve('approve'); // Timeout, default to approve
|
|
180
|
+
}, 30000); // 30 second timeout for user decision
|
|
181
|
+
const handler = (message) => {
|
|
182
|
+
try {
|
|
183
|
+
const data = JSON.parse(message.toString());
|
|
184
|
+
if (data.type === 'diffApplyResult' && data.requestId === requestId) {
|
|
185
|
+
cleanup();
|
|
186
|
+
resolve(data.result || 'approve');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
// Ignore invalid JSON
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
const cleanup = () => {
|
|
194
|
+
clearTimeout(timeout);
|
|
195
|
+
this.client?.removeListener('message', handler);
|
|
196
|
+
};
|
|
197
|
+
this.client.on('message', handler);
|
|
198
|
+
this.client.send(JSON.stringify({
|
|
199
|
+
type: 'diffApply',
|
|
200
|
+
requestId,
|
|
201
|
+
filePath,
|
|
202
|
+
oldContent,
|
|
203
|
+
newContent
|
|
204
|
+
}));
|
|
205
|
+
});
|
|
206
|
+
}
|
|
163
207
|
}
|
|
164
208
|
export const vscodeConnection = new VSCodeConnectionManager();
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -73,7 +73,9 @@ $ npm uninstall --global snow-ai
|
|
|
73
73
|
|
|
74
74
|
* When mounting: double-click ESC, view the dialogue recorder, select rollback, including file checkpoints
|
|
75
75
|
|
|
76
|
-
*
|
|
76
|
+
* MacOS:`ctrl + v` Paste image
|
|
77
|
+
* Windows:`alt + v` Paste image
|
|
78
|
+
|
|
77
79
|
|
|
78
80
|
* **Commands**
|
|
79
81
|
|