snow-ai 0.3.33 → 0.3.34
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/embedding.js
CHANGED
|
@@ -19,9 +19,10 @@ export async function createEmbeddings(options) {
|
|
|
19
19
|
if (!baseUrl) {
|
|
20
20
|
throw new Error('Embedding base URL is required');
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
// API key is optional for local deployments (e.g., Ollama)
|
|
23
|
+
// if (!apiKey) {
|
|
24
|
+
// throw new Error('Embedding API key is required');
|
|
25
|
+
// }
|
|
25
26
|
if (!input || input.length === 0) {
|
|
26
27
|
throw new Error('Input texts are required');
|
|
27
28
|
}
|
|
@@ -40,12 +41,16 @@ export async function createEmbeddings(options) {
|
|
|
40
41
|
const url = baseUrl.endsWith('/embeddings')
|
|
41
42
|
? baseUrl
|
|
42
43
|
: `${baseUrl.replace(/\/$/, '')}/embeddings`;
|
|
44
|
+
// Build headers - only include Authorization if API key is provided
|
|
45
|
+
const headers = {
|
|
46
|
+
'Content-Type': 'application/json',
|
|
47
|
+
};
|
|
48
|
+
if (apiKey) {
|
|
49
|
+
headers['Authorization'] = `Bearer ${apiKey}`;
|
|
50
|
+
}
|
|
43
51
|
const fetchOptions = addProxyToFetchOptions(url, {
|
|
44
52
|
method: 'POST',
|
|
45
|
-
headers
|
|
46
|
-
'Content-Type': 'application/json',
|
|
47
|
-
Authorization: `Bearer ${apiKey}`,
|
|
48
|
-
},
|
|
53
|
+
headers,
|
|
49
54
|
body: JSON.stringify(requestBody),
|
|
50
55
|
});
|
|
51
56
|
const response = await fetch(url, fetchOptions);
|
package/dist/api/systemPrompt.js
CHANGED
|
@@ -317,10 +317,14 @@ function hasCodebaseSearchTool(tools) {
|
|
|
317
317
|
function getWorkflowSection(hasCodebase) {
|
|
318
318
|
if (hasCodebase) {
|
|
319
319
|
return `**Your workflow:**
|
|
320
|
-
1.
|
|
320
|
+
1. **🚀 START WITH SEMANTIC SEARCH** - Use \\\`codebase-search\\\` as your PRIMARY exploration tool
|
|
321
|
+
- 🎯 ALWAYS try \\\`codebase-search\\\` FIRST for ANY code understanding task
|
|
322
|
+
- 💡 Examples: "authentication logic", "error handling", "user validation", "database queries"
|
|
323
|
+
- ⚡ Dramatically faster than reading multiple files manually
|
|
324
|
+
- 📊 Returns relevant code snippets with context - read results to understand the codebase
|
|
321
325
|
2. Read the primary file(s) mentioned (or files found by codebase search)
|
|
322
326
|
3. Check dependencies/imports that directly impact the change
|
|
323
|
-
4. For precise symbol lookup, use \\\`ace-search-symbols\\\`, \\\`ace-find-definition\\\`, or \\\`ace-find-references\\\`
|
|
327
|
+
4. For precise symbol lookup AFTER understanding context, use \\\`ace-search-symbols\\\`, \\\`ace-find-definition\\\`, or \\\`ace-find-references\\\`
|
|
324
328
|
5. Read related files ONLY if they're critical to understanding the task
|
|
325
329
|
6. Write/modify code with proper context
|
|
326
330
|
7. Verify with build
|
|
@@ -351,16 +355,17 @@ function getCodeSearchSection(hasCodebase) {
|
|
|
351
355
|
|
|
352
356
|
🎯 **Priority Order (use in this sequence):**
|
|
353
357
|
|
|
354
|
-
1. **Codebase Semantic Search** (⚡
|
|
358
|
+
1. **Codebase Semantic Search** (⚡ ALWAYS TRY THIS FIRST!):
|
|
355
359
|
- \\\`codebase-search\\\` - Semantic search using embeddings
|
|
356
360
|
- 🔍 Find code by MEANING, not just keywords
|
|
357
|
-
- 🎯 Best for: "how is authentication handled", "error handling patterns"
|
|
361
|
+
- 🎯 Best for: "how is authentication handled", "error handling patterns", "validation logic"
|
|
358
362
|
- 📊 Returns: Full code content + similarity scores + file locations
|
|
359
|
-
- 💡 **
|
|
360
|
-
- 🚀 **When to use**:
|
|
361
|
-
-
|
|
363
|
+
- 💡 **CRITICAL**: Use this as your PRIMARY tool for understanding codebase
|
|
364
|
+
- 🚀 **When to use**: ANY code understanding task, finding implementations, pattern discovery
|
|
365
|
+
- ⚡ **Example queries**: "user authentication", "database connection", "API error handling"
|
|
366
|
+
- ❌ **When to skip**: ONLY skip if you need exact symbol names or regex patterns
|
|
362
367
|
|
|
363
|
-
2. **ACE Code Search** (
|
|
368
|
+
2. **ACE Code Search** (Use AFTER semantic search for precise lookups):
|
|
364
369
|
- \\\`ace-search-symbols\\\` - Find functions/classes/variables by exact name
|
|
365
370
|
- \\\`ace-find-definition\\\` - Go to definition of a symbol
|
|
366
371
|
- \\\`ace-find-references\\\` - Find all usages of a symbol
|
|
@@ -8,13 +8,42 @@ export function useClipboard(buffer, updateCommandPanelState, updateFilePickerSt
|
|
|
8
8
|
if (process.platform === 'win32') {
|
|
9
9
|
// Windows: Use PowerShell to read image from clipboard
|
|
10
10
|
try {
|
|
11
|
-
|
|
12
|
-
const
|
|
11
|
+
// Optimized PowerShell script with compression for large images
|
|
12
|
+
const psScript = 'Add-Type -AssemblyName System.Windows.Forms; ' +
|
|
13
|
+
'Add-Type -AssemblyName System.Drawing; ' +
|
|
14
|
+
'$clipboard = [System.Windows.Forms.Clipboard]::GetImage(); ' +
|
|
15
|
+
'if ($clipboard -ne $null) { ' +
|
|
16
|
+
'$ms = New-Object System.IO.MemoryStream; ' +
|
|
17
|
+
'$width = $clipboard.Width; ' +
|
|
18
|
+
'$height = $clipboard.Height; ' +
|
|
19
|
+
'$maxSize = 2048; ' +
|
|
20
|
+
'if ($width -gt $maxSize -or $height -gt $maxSize) { ' +
|
|
21
|
+
'$ratio = [Math]::Min($maxSize / $width, $maxSize / $height); ' +
|
|
22
|
+
'$newWidth = [int]($width * $ratio); ' +
|
|
23
|
+
'$newHeight = [int]($height * $ratio); ' +
|
|
24
|
+
'$resized = New-Object System.Drawing.Bitmap($newWidth, $newHeight); ' +
|
|
25
|
+
'$graphics = [System.Drawing.Graphics]::FromImage($resized); ' +
|
|
26
|
+
'$graphics.CompositingQuality = [System.Drawing.Drawing2D.CompositingQuality]::HighQuality; ' +
|
|
27
|
+
'$graphics.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic; ' +
|
|
28
|
+
'$graphics.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality; ' +
|
|
29
|
+
'$graphics.DrawImage($clipboard, 0, 0, $newWidth, $newHeight); ' +
|
|
30
|
+
'$resized.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png); ' +
|
|
31
|
+
'$graphics.Dispose(); ' +
|
|
32
|
+
'$resized.Dispose(); ' +
|
|
33
|
+
'} else { ' +
|
|
34
|
+
'$clipboard.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png); ' +
|
|
35
|
+
'}; ' +
|
|
36
|
+
'$bytes = $ms.ToArray(); ' +
|
|
37
|
+
'$ms.Close(); ' +
|
|
38
|
+
'[Convert]::ToBase64String($bytes); ' +
|
|
39
|
+
'}';
|
|
40
|
+
const base64Raw = execSync(`powershell -NoProfile -Command "${psScript}"`, {
|
|
13
41
|
encoding: 'utf-8',
|
|
14
|
-
timeout:
|
|
42
|
+
timeout: 10000,
|
|
43
|
+
maxBuffer: 50 * 1024 * 1024, // 50MB buffer
|
|
15
44
|
});
|
|
16
|
-
//
|
|
17
|
-
const base64 = base64Raw.replace(/\s
|
|
45
|
+
// 高效清理:一次性移除所有空白字符
|
|
46
|
+
const base64 = base64Raw.replace(/\s/g, '');
|
|
18
47
|
if (base64 && base64.length > 100) {
|
|
19
48
|
// 直接传入 base64 数据,不需要 data URL 前缀
|
|
20
49
|
buffer.insertImage(base64, 'image/png');
|
|
@@ -28,6 +57,7 @@ export function useClipboard(buffer, updateCommandPanelState, updateFilePickerSt
|
|
|
28
57
|
}
|
|
29
58
|
catch (imgError) {
|
|
30
59
|
// No image in clipboard or error, fall through to text
|
|
60
|
+
logger.error('Failed to read image from Windows clipboard:', imgError);
|
|
31
61
|
}
|
|
32
62
|
}
|
|
33
63
|
else if (process.platform === 'darwin') {
|
|
@@ -52,13 +82,34 @@ end try'`;
|
|
|
52
82
|
encoding: 'utf-8',
|
|
53
83
|
timeout: 3000,
|
|
54
84
|
});
|
|
55
|
-
//
|
|
56
|
-
|
|
85
|
+
// Use sips to resize if needed, then convert to base64
|
|
86
|
+
// First check image size
|
|
87
|
+
const sizeCheck = execSync(`sips -g pixelWidth -g pixelHeight "${tmpFile}" | grep -E "pixelWidth|pixelHeight" | awk '{print $2}'`, {
|
|
57
88
|
encoding: 'utf-8',
|
|
58
89
|
timeout: 2000,
|
|
59
90
|
});
|
|
60
|
-
|
|
61
|
-
const
|
|
91
|
+
const [widthStr, heightStr] = sizeCheck.trim().split('\n');
|
|
92
|
+
const width = parseInt(widthStr || '0', 10);
|
|
93
|
+
const height = parseInt(heightStr || '0', 10);
|
|
94
|
+
const maxSize = 2048;
|
|
95
|
+
// Resize if too large
|
|
96
|
+
if (width > maxSize || height > maxSize) {
|
|
97
|
+
const ratio = Math.min(maxSize / width, maxSize / height);
|
|
98
|
+
const newWidth = Math.floor(width * ratio);
|
|
99
|
+
const newHeight = Math.floor(height * ratio);
|
|
100
|
+
execSync(`sips -z ${newHeight} ${newWidth} "${tmpFile}" --out "${tmpFile}"`, {
|
|
101
|
+
encoding: 'utf-8',
|
|
102
|
+
timeout: 5000,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
// Read the file as base64 with optimized buffer
|
|
106
|
+
const base64Raw = execSync(`base64 -i "${tmpFile}"`, {
|
|
107
|
+
encoding: 'utf-8',
|
|
108
|
+
timeout: 5000,
|
|
109
|
+
maxBuffer: 50 * 1024 * 1024, // 50MB buffer
|
|
110
|
+
});
|
|
111
|
+
// 高效清理:一次性移除所有空白字符
|
|
112
|
+
const base64 = base64Raw.replace(/\s/g, '');
|
|
62
113
|
// Clean up temp file
|
|
63
114
|
try {
|
|
64
115
|
execSync(`rm "${tmpFile}"`, { timeout: 1000 });
|
|
@@ -85,9 +85,10 @@ export default function CodeBaseConfigScreen({ onBack, onSave, inlineMode = fals
|
|
|
85
85
|
}
|
|
86
86
|
if (!embeddingBaseUrl.trim()) {
|
|
87
87
|
validationErrors.push('Embedding base URL is required when enabled');
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
validationErrors.push('Embedding API key is required when enabled');
|
|
88
|
+
// Embedding API key is optional (for local deployments like Ollama)
|
|
89
|
+
// if (!embeddingApiKey.trim()) {
|
|
90
|
+
// validationErrors.push('Embedding API key is required when enabled');
|
|
91
|
+
// }
|
|
91
92
|
}
|
|
92
93
|
if (embeddingDimensions <= 0) {
|
|
93
94
|
validationErrors.push('Embedding dimensions must be greater than 0');
|
|
@@ -175,7 +176,7 @@ export default function CodeBaseConfigScreen({ onBack, onSave, inlineMode = fals
|
|
|
175
176
|
return (React.createElement(Box, { key: field, flexDirection: "column" },
|
|
176
177
|
React.createElement(Text, { color: isActive ? 'green' : 'white' },
|
|
177
178
|
isActive ? '❯ ' : ' ',
|
|
178
|
-
"Embedding API Key:"),
|
|
179
|
+
"Embedding API Key (Optional for local):"),
|
|
179
180
|
isCurrentlyEditing && (React.createElement(Box, { marginLeft: 3 },
|
|
180
181
|
React.createElement(Text, { color: "cyan" },
|
|
181
182
|
React.createElement(TextInput, { value: embeddingApiKey, onChange: value => setEmbeddingApiKey(stripFocusArtifacts(value)), onSubmit: () => setIsEditing(false), mask: "*" })))),
|
|
@@ -41,7 +41,7 @@ export default function WelcomeScreen({ version = '1.0.0', onMenuSelect, }) {
|
|
|
41
41
|
{
|
|
42
42
|
label: 'CodeBase Settings',
|
|
43
43
|
value: 'codebase',
|
|
44
|
-
infoText: 'Configure codebase indexing with embedding
|
|
44
|
+
infoText: 'Configure codebase indexing with embedding models',
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
label: 'System Prompt Settings',
|
package/dist/utils/apiConfig.js
CHANGED
|
@@ -260,7 +260,7 @@ function migrateSystemPromptFromTxt() {
|
|
|
260
260
|
writeFileSync(SYSTEM_PROMPT_JSON_FILE, JSON.stringify(config, null, 2), 'utf8');
|
|
261
261
|
// 删除旧文件
|
|
262
262
|
unlinkSync(SYSTEM_PROMPT_FILE);
|
|
263
|
-
console.log('✅ Migrated system prompt from txt to json format.');
|
|
263
|
+
// console.log('✅ Migrated system prompt from txt to json format.');
|
|
264
264
|
}
|
|
265
265
|
catch (error) {
|
|
266
266
|
console.error('Failed to migrate system prompt:', error);
|