snow-ai 0.4.16 → 0.4.17
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/bundle/cli.mjs +477445 -0
- package/bundle/sql-wasm.wasm +0 -0
- package/package.json +31 -26
- package/dist/agents/codebaseIndexAgent.d.ts +0 -102
- package/dist/agents/codebaseIndexAgent.js +0 -641
- package/dist/agents/codebaseReviewAgent.d.ts +0 -61
- package/dist/agents/codebaseReviewAgent.js +0 -301
- package/dist/agents/compactAgent.d.ts +0 -55
- package/dist/agents/compactAgent.js +0 -306
- package/dist/agents/promptOptimizeAgent.d.ts +0 -54
- package/dist/agents/promptOptimizeAgent.js +0 -268
- package/dist/agents/reviewAgent.d.ts +0 -50
- package/dist/agents/reviewAgent.js +0 -265
- package/dist/agents/summaryAgent.d.ts +0 -57
- package/dist/agents/summaryAgent.js +0 -260
- package/dist/api/anthropic.d.ts +0 -44
- package/dist/api/anthropic.js +0 -598
- package/dist/api/chat.d.ts +0 -73
- package/dist/api/chat.js +0 -386
- package/dist/api/embedding.d.ts +0 -34
- package/dist/api/embedding.js +0 -80
- package/dist/api/gemini.d.ts +0 -31
- package/dist/api/gemini.js +0 -445
- package/dist/api/models.d.ts +0 -15
- package/dist/api/models.js +0 -139
- package/dist/api/responses.d.ts +0 -38
- package/dist/api/responses.js +0 -515
- package/dist/api/systemPrompt.d.ts +0 -4
- package/dist/api/systemPrompt.js +0 -408
- package/dist/api/types.d.ts +0 -53
- package/dist/api/types.js +0 -4
- package/dist/app.d.ts +0 -8
- package/dist/app.js +0 -112
- package/dist/cli.d.ts +0 -2
- package/dist/cli.js +0 -199
- package/dist/hooks/useAgentPicker.d.ts +0 -14
- package/dist/hooks/useAgentPicker.js +0 -119
- package/dist/hooks/useClipboard.d.ts +0 -4
- package/dist/hooks/useClipboard.js +0 -175
- package/dist/hooks/useCommandHandler.d.ts +0 -35
- package/dist/hooks/useCommandHandler.js +0 -346
- package/dist/hooks/useCommandPanel.d.ts +0 -17
- package/dist/hooks/useCommandPanel.js +0 -114
- package/dist/hooks/useConversation.d.ts +0 -49
- package/dist/hooks/useConversation.js +0 -1052
- package/dist/hooks/useFilePicker.d.ts +0 -18
- package/dist/hooks/useFilePicker.js +0 -224
- package/dist/hooks/useGlobalExit.d.ts +0 -5
- package/dist/hooks/useGlobalExit.js +0 -34
- package/dist/hooks/useGlobalNavigation.d.ts +0 -6
- package/dist/hooks/useGlobalNavigation.js +0 -17
- package/dist/hooks/useHistoryNavigation.d.ts +0 -35
- package/dist/hooks/useHistoryNavigation.js +0 -133
- package/dist/hooks/useInputBuffer.d.ts +0 -6
- package/dist/hooks/useInputBuffer.js +0 -45
- package/dist/hooks/useKeyboardInput.d.ts +0 -80
- package/dist/hooks/useKeyboardInput.js +0 -608
- package/dist/hooks/useSessionManagement.d.ts +0 -10
- package/dist/hooks/useSessionManagement.js +0 -43
- package/dist/hooks/useSessionSave.d.ts +0 -8
- package/dist/hooks/useSessionSave.js +0 -63
- package/dist/hooks/useSnapshotState.d.ts +0 -26
- package/dist/hooks/useSnapshotState.js +0 -28
- package/dist/hooks/useStreamingState.d.ts +0 -33
- package/dist/hooks/useStreamingState.js +0 -105
- package/dist/hooks/useTerminalFocus.d.ts +0 -28
- package/dist/hooks/useTerminalFocus.js +0 -87
- package/dist/hooks/useTerminalSize.d.ts +0 -4
- package/dist/hooks/useTerminalSize.js +0 -20
- package/dist/hooks/useTodoPicker.d.ts +0 -16
- package/dist/hooks/useTodoPicker.js +0 -94
- package/dist/hooks/useToolConfirmation.d.ts +0 -19
- package/dist/hooks/useToolConfirmation.js +0 -61
- package/dist/hooks/useVSCodeState.d.ts +0 -8
- package/dist/hooks/useVSCodeState.js +0 -81
- package/dist/i18n/I18nContext.d.ts +0 -14
- package/dist/i18n/I18nContext.js +0 -24
- package/dist/i18n/index.d.ts +0 -3
- package/dist/i18n/index.js +0 -2
- package/dist/i18n/lang/en.d.ts +0 -2
- package/dist/i18n/lang/en.js +0 -502
- package/dist/i18n/lang/es.d.ts +0 -2
- package/dist/i18n/lang/es.js +0 -502
- package/dist/i18n/lang/ja.d.ts +0 -2
- package/dist/i18n/lang/ja.js +0 -502
- package/dist/i18n/lang/ko.d.ts +0 -2
- package/dist/i18n/lang/ko.js +0 -502
- package/dist/i18n/lang/zh-TW.d.ts +0 -2
- package/dist/i18n/lang/zh-TW.js +0 -502
- package/dist/i18n/lang/zh.d.ts +0 -2
- package/dist/i18n/lang/zh.js +0 -502
- package/dist/i18n/translations.d.ts +0 -2
- package/dist/i18n/translations.js +0 -14
- package/dist/i18n/types.d.ts +0 -478
- package/dist/i18n/types.js +0 -1
- package/dist/mcp/aceCodeSearch.d.ts +0 -247
- package/dist/mcp/aceCodeSearch.js +0 -1058
- package/dist/mcp/bash.d.ts +0 -50
- package/dist/mcp/bash.js +0 -153
- package/dist/mcp/codebaseSearch.d.ts +0 -44
- package/dist/mcp/codebaseSearch.js +0 -275
- package/dist/mcp/filesystem.d.ts +0 -392
- package/dist/mcp/filesystem.js +0 -1445
- package/dist/mcp/ideDiagnostics.d.ts +0 -36
- package/dist/mcp/ideDiagnostics.js +0 -90
- package/dist/mcp/notebook.d.ts +0 -10
- package/dist/mcp/notebook.js +0 -367
- package/dist/mcp/subagent.d.ts +0 -37
- package/dist/mcp/subagent.js +0 -113
- package/dist/mcp/todo.d.ts +0 -46
- package/dist/mcp/todo.js +0 -511
- package/dist/mcp/types/aceCodeSearch.types.d.ts +0 -92
- package/dist/mcp/types/aceCodeSearch.types.js +0 -4
- package/dist/mcp/types/bash.types.d.ts +0 -13
- package/dist/mcp/types/bash.types.js +0 -4
- package/dist/mcp/types/filesystem.types.d.ts +0 -210
- package/dist/mcp/types/filesystem.types.js +0 -27
- package/dist/mcp/types/todo.types.d.ts +0 -27
- package/dist/mcp/types/todo.types.js +0 -4
- package/dist/mcp/types/websearch.types.d.ts +0 -30
- package/dist/mcp/types/websearch.types.js +0 -4
- package/dist/mcp/utils/aceCodeSearch/filesystem.utils.d.ts +0 -34
- package/dist/mcp/utils/aceCodeSearch/filesystem.utils.js +0 -146
- package/dist/mcp/utils/aceCodeSearch/language.utils.d.ts +0 -14
- package/dist/mcp/utils/aceCodeSearch/language.utils.js +0 -418
- package/dist/mcp/utils/aceCodeSearch/search.utils.d.ts +0 -31
- package/dist/mcp/utils/aceCodeSearch/search.utils.js +0 -136
- package/dist/mcp/utils/aceCodeSearch/symbol.utils.d.ts +0 -20
- package/dist/mcp/utils/aceCodeSearch/symbol.utils.js +0 -141
- package/dist/mcp/utils/bash/security.utils.d.ts +0 -20
- package/dist/mcp/utils/bash/security.utils.js +0 -34
- package/dist/mcp/utils/filesystem/batch-operations.utils.d.ts +0 -39
- package/dist/mcp/utils/filesystem/batch-operations.utils.js +0 -182
- package/dist/mcp/utils/filesystem/code-analysis.utils.d.ts +0 -18
- package/dist/mcp/utils/filesystem/code-analysis.utils.js +0 -165
- package/dist/mcp/utils/filesystem/match-finder.utils.d.ts +0 -16
- package/dist/mcp/utils/filesystem/match-finder.utils.js +0 -85
- package/dist/mcp/utils/filesystem/office-parser.utils.d.ts +0 -43
- package/dist/mcp/utils/filesystem/office-parser.utils.js +0 -163
- package/dist/mcp/utils/filesystem/path-fixer.utils.d.ts +0 -7
- package/dist/mcp/utils/filesystem/path-fixer.utils.js +0 -60
- package/dist/mcp/utils/filesystem/similarity.utils.d.ts +0 -22
- package/dist/mcp/utils/filesystem/similarity.utils.js +0 -75
- package/dist/mcp/utils/todo/date.utils.d.ts +0 -9
- package/dist/mcp/utils/todo/date.utils.js +0 -14
- package/dist/mcp/utils/websearch/browser.utils.d.ts +0 -8
- package/dist/mcp/utils/websearch/browser.utils.js +0 -58
- package/dist/mcp/utils/websearch/text.utils.d.ts +0 -16
- package/dist/mcp/utils/websearch/text.utils.js +0 -39
- package/dist/mcp/websearch.d.ts +0 -88
- package/dist/mcp/websearch.js +0 -375
- package/dist/test/logger-test.d.ts +0 -1
- package/dist/test/logger-test.js +0 -7
- package/dist/types/index.d.ts +0 -15
- package/dist/types/index.js +0 -1
- package/dist/ui/components/AgentPickerPanel.d.ts +0 -10
- package/dist/ui/components/AgentPickerPanel.js +0 -74
- package/dist/ui/components/ChatInput.d.ts +0 -46
- package/dist/ui/components/ChatInput.js +0 -384
- package/dist/ui/components/CommandPanel.d.ts +0 -15
- package/dist/ui/components/CommandPanel.js +0 -80
- package/dist/ui/components/DiffViewer.d.ts +0 -11
- package/dist/ui/components/DiffViewer.js +0 -178
- package/dist/ui/components/FileList.d.ts +0 -15
- package/dist/ui/components/FileList.js +0 -360
- package/dist/ui/components/FileRollbackConfirmation.d.ts +0 -8
- package/dist/ui/components/FileRollbackConfirmation.js +0 -108
- package/dist/ui/components/HelpPanel.d.ts +0 -2
- package/dist/ui/components/HelpPanel.js +0 -67
- package/dist/ui/components/MCPInfoPanel.d.ts +0 -2
- package/dist/ui/components/MCPInfoPanel.js +0 -108
- package/dist/ui/components/MCPInfoScreen.d.ts +0 -7
- package/dist/ui/components/MCPInfoScreen.js +0 -115
- package/dist/ui/components/MarkdownRenderer.d.ts +0 -6
- package/dist/ui/components/MarkdownRenderer.js +0 -70
- package/dist/ui/components/Menu.d.ts +0 -17
- package/dist/ui/components/Menu.js +0 -88
- package/dist/ui/components/MessageList.d.ts +0 -56
- package/dist/ui/components/MessageList.js +0 -97
- package/dist/ui/components/PendingMessages.d.ts +0 -13
- package/dist/ui/components/PendingMessages.js +0 -29
- package/dist/ui/components/PendingToolCalls.d.ts +0 -11
- package/dist/ui/components/PendingToolCalls.js +0 -35
- package/dist/ui/components/ScrollableSelectInput.d.ts +0 -29
- package/dist/ui/components/ScrollableSelectInput.js +0 -157
- package/dist/ui/components/SessionListPanel.d.ts +0 -7
- package/dist/ui/components/SessionListPanel.js +0 -175
- package/dist/ui/components/SessionListScreen.d.ts +0 -7
- package/dist/ui/components/SessionListScreen.js +0 -217
- package/dist/ui/components/SessionListScreenWrapper.d.ts +0 -7
- package/dist/ui/components/SessionListScreenWrapper.js +0 -14
- package/dist/ui/components/ShimmerText.d.ts +0 -9
- package/dist/ui/components/ShimmerText.js +0 -30
- package/dist/ui/components/TodoPickerPanel.d.ts +0 -14
- package/dist/ui/components/TodoPickerPanel.js +0 -119
- package/dist/ui/components/TodoTree.d.ts +0 -15
- package/dist/ui/components/TodoTree.js +0 -60
- package/dist/ui/components/ToolConfirmation.d.ts +0 -21
- package/dist/ui/components/ToolConfirmation.js +0 -204
- package/dist/ui/components/ToolResultPreview.d.ts +0 -13
- package/dist/ui/components/ToolResultPreview.js +0 -337
- package/dist/ui/components/UsagePanel.d.ts +0 -2
- package/dist/ui/components/UsagePanel.js +0 -394
- package/dist/ui/contexts/ThemeContext.d.ts +0 -13
- package/dist/ui/contexts/ThemeContext.js +0 -28
- package/dist/ui/pages/ChatScreen.d.ts +0 -6
- package/dist/ui/pages/ChatScreen.js +0 -1519
- package/dist/ui/pages/CodeBaseConfigScreen.d.ts +0 -8
- package/dist/ui/pages/CodeBaseConfigScreen.js +0 -350
- package/dist/ui/pages/ConfigScreen.d.ts +0 -8
- package/dist/ui/pages/ConfigScreen.js +0 -1101
- package/dist/ui/pages/CustomHeadersScreen.d.ts +0 -6
- package/dist/ui/pages/CustomHeadersScreen.js +0 -502
- package/dist/ui/pages/HeadlessModeScreen.d.ts +0 -7
- package/dist/ui/pages/HeadlessModeScreen.js +0 -381
- package/dist/ui/pages/LanguageSettingsScreen.d.ts +0 -7
- package/dist/ui/pages/LanguageSettingsScreen.js +0 -91
- package/dist/ui/pages/MCPConfigScreen.d.ts +0 -6
- package/dist/ui/pages/MCPConfigScreen.js +0 -55
- package/dist/ui/pages/ProxyConfigScreen.d.ts +0 -8
- package/dist/ui/pages/ProxyConfigScreen.js +0 -149
- package/dist/ui/pages/SensitiveCommandConfigScreen.d.ts +0 -7
- package/dist/ui/pages/SensitiveCommandConfigScreen.js +0 -271
- package/dist/ui/pages/SubAgentConfigScreen.d.ts +0 -9
- package/dist/ui/pages/SubAgentConfigScreen.js +0 -435
- package/dist/ui/pages/SubAgentListScreen.d.ts +0 -9
- package/dist/ui/pages/SubAgentListScreen.js +0 -131
- package/dist/ui/pages/SystemPromptConfigScreen.d.ts +0 -6
- package/dist/ui/pages/SystemPromptConfigScreen.js +0 -326
- package/dist/ui/pages/ThemeSettingsScreen.d.ts +0 -7
- package/dist/ui/pages/ThemeSettingsScreen.js +0 -106
- package/dist/ui/pages/WelcomeScreen.d.ts +0 -7
- package/dist/ui/pages/WelcomeScreen.js +0 -217
- package/dist/ui/themes/index.d.ts +0 -23
- package/dist/ui/themes/index.js +0 -140
- package/dist/utils/apiConfig.d.ts +0 -126
- package/dist/utils/apiConfig.js +0 -423
- package/dist/utils/autoCompress.d.ts +0 -15
- package/dist/utils/autoCompress.js +0 -24
- package/dist/utils/chatExporter.d.ts +0 -9
- package/dist/utils/chatExporter.js +0 -118
- package/dist/utils/checkpointManager.d.ts +0 -74
- package/dist/utils/checkpointManager.js +0 -181
- package/dist/utils/codebaseConfig.d.ts +0 -16
- package/dist/utils/codebaseConfig.js +0 -67
- package/dist/utils/codebaseDatabase.d.ts +0 -102
- package/dist/utils/codebaseDatabase.js +0 -333
- package/dist/utils/codebaseSearchEvents.d.ts +0 -16
- package/dist/utils/codebaseSearchEvents.js +0 -13
- package/dist/utils/commandExecutor.d.ts +0 -13
- package/dist/utils/commandExecutor.js +0 -26
- package/dist/utils/commands/agent.d.ts +0 -2
- package/dist/utils/commands/agent.js +0 -12
- package/dist/utils/commands/clear.d.ts +0 -2
- package/dist/utils/commands/clear.js +0 -12
- package/dist/utils/commands/compact.d.ts +0 -2
- package/dist/utils/commands/compact.js +0 -12
- package/dist/utils/commands/export.d.ts +0 -2
- package/dist/utils/commands/export.js +0 -12
- package/dist/utils/commands/help.d.ts +0 -2
- package/dist/utils/commands/help.js +0 -11
- package/dist/utils/commands/home.d.ts +0 -2
- package/dist/utils/commands/home.js +0 -34
- package/dist/utils/commands/ide.d.ts +0 -2
- package/dist/utils/commands/ide.js +0 -32
- package/dist/utils/commands/init.d.ts +0 -2
- package/dist/utils/commands/init.js +0 -93
- package/dist/utils/commands/mcp.d.ts +0 -2
- package/dist/utils/commands/mcp.js +0 -12
- package/dist/utils/commands/resume.d.ts +0 -2
- package/dist/utils/commands/resume.js +0 -12
- package/dist/utils/commands/review.d.ts +0 -2
- package/dist/utils/commands/review.js +0 -81
- package/dist/utils/commands/role.d.ts +0 -2
- package/dist/utils/commands/role.js +0 -37
- package/dist/utils/commands/todoPicker.d.ts +0 -2
- package/dist/utils/commands/todoPicker.js +0 -12
- package/dist/utils/commands/usage.d.ts +0 -2
- package/dist/utils/commands/usage.js +0 -12
- package/dist/utils/commands/yolo.d.ts +0 -2
- package/dist/utils/commands/yolo.js +0 -12
- package/dist/utils/configManager.d.ts +0 -45
- package/dist/utils/configManager.js +0 -303
- package/dist/utils/contextCompressor.d.ts +0 -16
- package/dist/utils/contextCompressor.js +0 -334
- package/dist/utils/devMode.d.ts +0 -13
- package/dist/utils/devMode.js +0 -54
- package/dist/utils/escapeHandler.d.ts +0 -79
- package/dist/utils/escapeHandler.js +0 -153
- package/dist/utils/fileDialog.d.ts +0 -9
- package/dist/utils/fileDialog.js +0 -74
- package/dist/utils/fileUtils.d.ts +0 -40
- package/dist/utils/fileUtils.js +0 -185
- package/dist/utils/historyManager.d.ts +0 -45
- package/dist/utils/historyManager.js +0 -159
- package/dist/utils/incrementalSnapshot.d.ts +0 -109
- package/dist/utils/incrementalSnapshot.js +0 -383
- package/dist/utils/index.d.ts +0 -11
- package/dist/utils/index.js +0 -18
- package/dist/utils/languageConfig.d.ts +0 -21
- package/dist/utils/languageConfig.js +0 -61
- package/dist/utils/logger.d.ts +0 -37
- package/dist/utils/logger.js +0 -122
- package/dist/utils/mcpToolsManager.d.ts +0 -52
- package/dist/utils/mcpToolsManager.js +0 -878
- package/dist/utils/messageFormatter.d.ts +0 -12
- package/dist/utils/messageFormatter.js +0 -115
- package/dist/utils/notebookManager.d.ts +0 -59
- package/dist/utils/notebookManager.js +0 -213
- package/dist/utils/patch-highlight.d.ts +0 -5
- package/dist/utils/patch-highlight.js +0 -23
- package/dist/utils/processManager.d.ts +0 -27
- package/dist/utils/processManager.js +0 -75
- package/dist/utils/proxyUtils.d.ts +0 -15
- package/dist/utils/proxyUtils.js +0 -50
- package/dist/utils/resourceMonitor.d.ts +0 -65
- package/dist/utils/resourceMonitor.js +0 -175
- package/dist/utils/retryUtils.d.ts +0 -49
- package/dist/utils/retryUtils.js +0 -303
- package/dist/utils/sensitiveCommandManager.d.ts +0 -53
- package/dist/utils/sensitiveCommandManager.js +0 -308
- package/dist/utils/sessionConverter.d.ts +0 -7
- package/dist/utils/sessionConverter.js +0 -306
- package/dist/utils/sessionManager.d.ts +0 -53
- package/dist/utils/sessionManager.js +0 -371
- package/dist/utils/subAgentConfig.d.ts +0 -50
- package/dist/utils/subAgentConfig.js +0 -221
- package/dist/utils/subAgentExecutor.d.ts +0 -40
- package/dist/utils/subAgentExecutor.js +0 -434
- package/dist/utils/terminal.d.ts +0 -5
- package/dist/utils/terminal.js +0 -13
- package/dist/utils/textBuffer.d.ts +0 -99
- package/dist/utils/textBuffer.js +0 -547
- package/dist/utils/textUtils.d.ts +0 -37
- package/dist/utils/textUtils.js +0 -102
- package/dist/utils/themeConfig.d.ts +0 -21
- package/dist/utils/themeConfig.js +0 -61
- package/dist/utils/todoPreprocessor.d.ts +0 -5
- package/dist/utils/todoPreprocessor.js +0 -18
- package/dist/utils/todoScanner.d.ts +0 -8
- package/dist/utils/todoScanner.js +0 -148
- package/dist/utils/toolDisplayConfig.d.ts +0 -16
- package/dist/utils/toolDisplayConfig.js +0 -47
- package/dist/utils/toolExecutor.d.ts +0 -37
- package/dist/utils/toolExecutor.js +0 -224
- package/dist/utils/usageLogger.d.ts +0 -11
- package/dist/utils/usageLogger.js +0 -114
- package/dist/utils/vscodeConnection.d.ts +0 -76
- package/dist/utils/vscodeConnection.js +0 -430
- package/dist/utils/workspaceSnapshot.d.ts +0 -63
- package/dist/utils/workspaceSnapshot.js +0 -300
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
import { getOpenAiConfig, getCustomSystemPrompt } from './apiConfig.js';
|
|
2
|
-
import { getSystemPrompt } from '../api/systemPrompt.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
|
-
/**
|
|
8
|
-
* Compression request prompt - asks AI to create a detailed, structured summary
|
|
9
|
-
* that preserves critical information for task continuity
|
|
10
|
-
*/
|
|
11
|
-
const COMPRESSION_PROMPT = `You are compressing a conversation history to save context space while preserving all critical information. Create a comprehensive summary following this structure:
|
|
12
|
-
|
|
13
|
-
## 📋 Current Task & Goals
|
|
14
|
-
- What is the main task or project being worked on?
|
|
15
|
-
- What are the specific objectives and desired outcomes?
|
|
16
|
-
- What is the current progress status?
|
|
17
|
-
|
|
18
|
-
## 🔧 Technical Context
|
|
19
|
-
- Key technologies, frameworks, libraries, and tools being used
|
|
20
|
-
- Important file paths, function names, and code locations mentioned
|
|
21
|
-
- Architecture decisions and design patterns chosen
|
|
22
|
-
- Configuration settings and environment details
|
|
23
|
-
|
|
24
|
-
## 💡 Key Decisions & Approaches
|
|
25
|
-
- Important decisions made and their rationale
|
|
26
|
-
- Chosen approaches and methodologies
|
|
27
|
-
- Solutions to problems encountered
|
|
28
|
-
- Best practices or patterns agreed upon
|
|
29
|
-
|
|
30
|
-
## ✅ Completed Work
|
|
31
|
-
- What has been successfully implemented or resolved?
|
|
32
|
-
- Important code changes, fixes, or features added
|
|
33
|
-
- Test results or validation performed
|
|
34
|
-
|
|
35
|
-
## 🚧 Pending & In-Progress Work
|
|
36
|
-
- What tasks are currently unfinished?
|
|
37
|
-
- Known issues or blockers that need addressing
|
|
38
|
-
- Next steps planned or discussed
|
|
39
|
-
- Open questions or areas needing clarification
|
|
40
|
-
|
|
41
|
-
## 🔑 Critical Information
|
|
42
|
-
- Important data, values, IDs, or credentials referenced (sanitized)
|
|
43
|
-
- Error messages, warnings, or diagnostic information
|
|
44
|
-
- User preferences, requirements, or constraints
|
|
45
|
-
- Any other context essential for seamless continuation
|
|
46
|
-
|
|
47
|
-
**Guidelines:**
|
|
48
|
-
- Be specific with names, paths, and technical details
|
|
49
|
-
- Preserve exact terminology and technical vocabulary
|
|
50
|
-
- Include enough detail to continue work without confusion
|
|
51
|
-
- Use code snippets or examples where helpful
|
|
52
|
-
- Prioritize actionable information over general descriptions`;
|
|
53
|
-
/**
|
|
54
|
-
* 找到需要保留的消息(最近的工具调用链)
|
|
55
|
-
*
|
|
56
|
-
* 保留策略:
|
|
57
|
-
* - 如果最后有未完成的工具调用(assistant with tool_calls 或 tool),保留这个链
|
|
58
|
-
* - 如果最后是普通 assistant 或 user,不需要保留(压缩全部)
|
|
59
|
-
*
|
|
60
|
-
* 注意:不保留 user 消息,因为:
|
|
61
|
-
* 1. 压缩摘要已包含历史上下文
|
|
62
|
-
* 2. 下一轮对话会有新的 user 消息
|
|
63
|
-
*
|
|
64
|
-
* @returns 保留消息的起始索引,如果全部压缩则返回 messages.length
|
|
65
|
-
*/
|
|
66
|
-
function findPreserveStartIndex(messages) {
|
|
67
|
-
if (messages.length === 0) {
|
|
68
|
-
return 0;
|
|
69
|
-
}
|
|
70
|
-
const lastMsg = messages[messages.length - 1];
|
|
71
|
-
// Case 1: 最后是 tool 消息 → 保留 assistant(tool_calls) → tool
|
|
72
|
-
if (lastMsg?.role === 'tool') {
|
|
73
|
-
// 向前找对应的 assistant with tool_calls
|
|
74
|
-
for (let i = messages.length - 2; i >= 0; i--) {
|
|
75
|
-
const msg = messages[i];
|
|
76
|
-
if (msg?.role === 'assistant' &&
|
|
77
|
-
msg.tool_calls &&
|
|
78
|
-
msg.tool_calls.length > 0) {
|
|
79
|
-
// 找到了,从这个 assistant 开始保留
|
|
80
|
-
return i;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
// 如果找不到对应的 assistant,保留最后的 tool(虽然不太可能)
|
|
84
|
-
return messages.length - 1;
|
|
85
|
-
}
|
|
86
|
-
// Case 2: 最后是 assistant with tool_calls → 保留 assistant(tool_calls)
|
|
87
|
-
if (lastMsg?.role === 'assistant' &&
|
|
88
|
-
lastMsg.tool_calls &&
|
|
89
|
-
lastMsg.tool_calls.length > 0) {
|
|
90
|
-
// 保留这个待处理的 tool_calls
|
|
91
|
-
return messages.length - 1;
|
|
92
|
-
}
|
|
93
|
-
// Case 3: 最后是普通 assistant 或 user → 全部压缩
|
|
94
|
-
// 因为没有未完成的工具调用链
|
|
95
|
-
return messages.length;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Prepare messages for compression by adding system prompt and compression request
|
|
99
|
-
* Note: Only filters out system messages and tool messages, preserving user and assistant messages
|
|
100
|
-
*/
|
|
101
|
-
function prepareMessagesForCompression(conversationMessages, customSystemPrompt) {
|
|
102
|
-
const messages = [];
|
|
103
|
-
// Add system prompt (handled by API modules)
|
|
104
|
-
if (customSystemPrompt) {
|
|
105
|
-
// If custom system prompt exists: custom as system, default as first user message
|
|
106
|
-
messages.push({ role: 'system', content: customSystemPrompt });
|
|
107
|
-
// messages.push({role: 'user', content: getSystemPrompt()});
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
// No custom system prompt: default as system
|
|
111
|
-
messages.push({ role: 'system', content: getSystemPrompt() });
|
|
112
|
-
}
|
|
113
|
-
// Add all conversation history for compression
|
|
114
|
-
// Filter out system messages (already added above) and tool messages (only needed for API, not for summary)
|
|
115
|
-
for (const msg of conversationMessages) {
|
|
116
|
-
if (msg.role !== 'system' && msg.role !== 'tool') {
|
|
117
|
-
// Only include user and assistant messages for compression
|
|
118
|
-
messages.push({
|
|
119
|
-
role: msg.role,
|
|
120
|
-
content: msg.content,
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
// Add compression request as final user message
|
|
125
|
-
messages.push({
|
|
126
|
-
role: 'user',
|
|
127
|
-
content: COMPRESSION_PROMPT,
|
|
128
|
-
});
|
|
129
|
-
return messages;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Compress context using OpenAI Chat Completions API (reuses chat.ts)
|
|
133
|
-
*/
|
|
134
|
-
async function compressWithChatCompletions(modelName, conversationMessages, customSystemPrompt) {
|
|
135
|
-
const messages = prepareMessagesForCompression(conversationMessages, customSystemPrompt);
|
|
136
|
-
let summary = '';
|
|
137
|
-
let usage = {
|
|
138
|
-
prompt_tokens: 0,
|
|
139
|
-
completion_tokens: 0,
|
|
140
|
-
total_tokens: 0,
|
|
141
|
-
};
|
|
142
|
-
// Use the existing streaming API from chat.ts (includes proxy support)
|
|
143
|
-
for await (const chunk of createStreamingChatCompletion({
|
|
144
|
-
model: modelName,
|
|
145
|
-
messages,
|
|
146
|
-
stream: true,
|
|
147
|
-
})) {
|
|
148
|
-
// Collect content
|
|
149
|
-
if (chunk.type === 'content' && chunk.content) {
|
|
150
|
-
summary += chunk.content;
|
|
151
|
-
}
|
|
152
|
-
// Collect usage info
|
|
153
|
-
if (chunk.type === 'usage' && chunk.usage) {
|
|
154
|
-
usage = {
|
|
155
|
-
prompt_tokens: chunk.usage.prompt_tokens || 0,
|
|
156
|
-
completion_tokens: chunk.usage.completion_tokens || 0,
|
|
157
|
-
total_tokens: chunk.usage.total_tokens || 0,
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
if (!summary) {
|
|
162
|
-
throw new Error('Failed to generate summary from compact model');
|
|
163
|
-
}
|
|
164
|
-
return { summary, usage };
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Compress context using OpenAI Responses API (reuses responses.ts)
|
|
168
|
-
*/
|
|
169
|
-
async function compressWithResponses(modelName, conversationMessages, customSystemPrompt) {
|
|
170
|
-
const messages = prepareMessagesForCompression(conversationMessages, customSystemPrompt);
|
|
171
|
-
let summary = '';
|
|
172
|
-
let usage = {
|
|
173
|
-
prompt_tokens: 0,
|
|
174
|
-
completion_tokens: 0,
|
|
175
|
-
total_tokens: 0,
|
|
176
|
-
};
|
|
177
|
-
// Use the existing streaming API from responses.ts (includes proxy support)
|
|
178
|
-
for await (const chunk of createStreamingResponse({
|
|
179
|
-
model: modelName,
|
|
180
|
-
messages,
|
|
181
|
-
stream: true,
|
|
182
|
-
})) {
|
|
183
|
-
// Collect content
|
|
184
|
-
if (chunk.type === 'content' && chunk.content) {
|
|
185
|
-
summary += chunk.content;
|
|
186
|
-
}
|
|
187
|
-
// Collect usage info
|
|
188
|
-
if (chunk.type === 'usage' && chunk.usage) {
|
|
189
|
-
usage = {
|
|
190
|
-
prompt_tokens: chunk.usage.prompt_tokens || 0,
|
|
191
|
-
completion_tokens: chunk.usage.completion_tokens || 0,
|
|
192
|
-
total_tokens: chunk.usage.total_tokens || 0,
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
if (!summary) {
|
|
197
|
-
throw new Error('Failed to generate summary from compact model (Responses API)');
|
|
198
|
-
}
|
|
199
|
-
return { summary, usage };
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Compress context using Gemini API (reuses gemini.ts)
|
|
203
|
-
*/
|
|
204
|
-
async function compressWithGemini(modelName, conversationMessages, customSystemPrompt) {
|
|
205
|
-
const messages = prepareMessagesForCompression(conversationMessages, customSystemPrompt);
|
|
206
|
-
let summary = '';
|
|
207
|
-
let usage = {
|
|
208
|
-
prompt_tokens: 0,
|
|
209
|
-
completion_tokens: 0,
|
|
210
|
-
total_tokens: 0,
|
|
211
|
-
};
|
|
212
|
-
// Use the existing streaming API from gemini.ts (includes proxy support)
|
|
213
|
-
for await (const chunk of createStreamingGeminiCompletion({
|
|
214
|
-
model: modelName,
|
|
215
|
-
messages,
|
|
216
|
-
})) {
|
|
217
|
-
// Collect content
|
|
218
|
-
if (chunk.type === 'content' && chunk.content) {
|
|
219
|
-
summary += chunk.content;
|
|
220
|
-
}
|
|
221
|
-
// Collect usage info
|
|
222
|
-
if (chunk.type === 'usage' && chunk.usage) {
|
|
223
|
-
usage = {
|
|
224
|
-
prompt_tokens: chunk.usage.prompt_tokens || 0,
|
|
225
|
-
completion_tokens: chunk.usage.completion_tokens || 0,
|
|
226
|
-
total_tokens: chunk.usage.total_tokens || 0,
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
if (!summary) {
|
|
231
|
-
throw new Error('Failed to generate summary from Gemini model');
|
|
232
|
-
}
|
|
233
|
-
return { summary, usage };
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* Compress context using Anthropic API (reuses anthropic.ts)
|
|
237
|
-
*/
|
|
238
|
-
async function compressWithAnthropic(modelName, conversationMessages, customSystemPrompt) {
|
|
239
|
-
const messages = prepareMessagesForCompression(conversationMessages, customSystemPrompt);
|
|
240
|
-
let summary = '';
|
|
241
|
-
let usage = {
|
|
242
|
-
prompt_tokens: 0,
|
|
243
|
-
completion_tokens: 0,
|
|
244
|
-
total_tokens: 0,
|
|
245
|
-
};
|
|
246
|
-
// Use the existing streaming API from anthropic.ts (includes proxy support)
|
|
247
|
-
for await (const chunk of createStreamingAnthropicCompletion({
|
|
248
|
-
model: modelName,
|
|
249
|
-
messages,
|
|
250
|
-
max_tokens: 4096,
|
|
251
|
-
disableThinking: true, // Context compression 不使用 Extended Thinking
|
|
252
|
-
})) {
|
|
253
|
-
// Collect content
|
|
254
|
-
if (chunk.type === 'content' && chunk.content) {
|
|
255
|
-
summary += chunk.content;
|
|
256
|
-
}
|
|
257
|
-
// Collect usage info
|
|
258
|
-
if (chunk.type === 'usage' && chunk.usage) {
|
|
259
|
-
usage = {
|
|
260
|
-
prompt_tokens: chunk.usage.prompt_tokens || 0,
|
|
261
|
-
completion_tokens: chunk.usage.completion_tokens || 0,
|
|
262
|
-
total_tokens: chunk.usage.total_tokens || 0,
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
if (!summary) {
|
|
267
|
-
throw new Error('Failed to generate summary from Anthropic model');
|
|
268
|
-
}
|
|
269
|
-
return { summary, usage };
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Compress conversation history using the compact model
|
|
273
|
-
* @param messages - Array of messages to compress
|
|
274
|
-
* @returns Compressed summary and token usage information, or null if compression should be skipped
|
|
275
|
-
*/
|
|
276
|
-
export async function compressContext(messages) {
|
|
277
|
-
const config = getOpenAiConfig();
|
|
278
|
-
// Check if compact model is configured
|
|
279
|
-
if (!config.compactModel || !config.compactModel.modelName) {
|
|
280
|
-
throw new Error('Compact model not configured. Please configure it in API & Model Settings.');
|
|
281
|
-
}
|
|
282
|
-
if (messages.length === 0) {
|
|
283
|
-
console.warn('No messages to compress');
|
|
284
|
-
return null;
|
|
285
|
-
}
|
|
286
|
-
const modelName = config.compactModel.modelName;
|
|
287
|
-
const requestMethod = config.requestMethod;
|
|
288
|
-
// Get custom system prompt if configured
|
|
289
|
-
const customSystemPrompt = getCustomSystemPrompt();
|
|
290
|
-
// 找到需要保留的消息起始位置
|
|
291
|
-
const preserveStartIndex = findPreserveStartIndex(messages);
|
|
292
|
-
// 如果 preserveStartIndex 为 0,说明所有消息都需要保留(没有历史可压缩)
|
|
293
|
-
// 例如:整个对话只有一条 user→assistant(tool_calls),无法压缩
|
|
294
|
-
if (preserveStartIndex === 0) {
|
|
295
|
-
console.warn('Cannot compress: all messages need to be preserved (no history)');
|
|
296
|
-
return null;
|
|
297
|
-
}
|
|
298
|
-
// 分离待压缩和待保留的消息
|
|
299
|
-
const messagesToCompress = messages.slice(0, preserveStartIndex);
|
|
300
|
-
const preservedMessages = messages.slice(preserveStartIndex);
|
|
301
|
-
try {
|
|
302
|
-
// Choose compression method based on request method
|
|
303
|
-
// All methods now reuse existing API modules which include proxy support
|
|
304
|
-
let result;
|
|
305
|
-
switch (requestMethod) {
|
|
306
|
-
case 'gemini':
|
|
307
|
-
result = await compressWithGemini(modelName, messagesToCompress, customSystemPrompt || null);
|
|
308
|
-
break;
|
|
309
|
-
case 'anthropic':
|
|
310
|
-
result = await compressWithAnthropic(modelName, messagesToCompress, customSystemPrompt || null);
|
|
311
|
-
break;
|
|
312
|
-
case 'responses':
|
|
313
|
-
// OpenAI Responses API
|
|
314
|
-
result = await compressWithResponses(modelName, messagesToCompress, customSystemPrompt || null);
|
|
315
|
-
break;
|
|
316
|
-
case 'chat':
|
|
317
|
-
default:
|
|
318
|
-
// OpenAI Chat Completions API
|
|
319
|
-
result = await compressWithChatCompletions(modelName, messagesToCompress, customSystemPrompt || null);
|
|
320
|
-
break;
|
|
321
|
-
}
|
|
322
|
-
// 添加保留的消息到结果中
|
|
323
|
-
if (preservedMessages.length > 0) {
|
|
324
|
-
result.preservedMessages = preservedMessages;
|
|
325
|
-
}
|
|
326
|
-
return result;
|
|
327
|
-
}
|
|
328
|
-
catch (error) {
|
|
329
|
-
if (error instanceof Error) {
|
|
330
|
-
throw new Error(`Context compression failed: ${error.message}`);
|
|
331
|
-
}
|
|
332
|
-
throw new Error('Unknown error occurred during context compression');
|
|
333
|
-
}
|
|
334
|
-
}
|
package/dist/utils/devMode.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Get or create persistent dev userId
|
|
3
|
-
* The userId is stored in ~/.snow/dev-user-id and persists across sessions
|
|
4
|
-
*/
|
|
5
|
-
export declare function getDevUserId(): string;
|
|
6
|
-
/**
|
|
7
|
-
* Check if dev mode is enabled
|
|
8
|
-
*/
|
|
9
|
-
export declare function isDevMode(): boolean;
|
|
10
|
-
/**
|
|
11
|
-
* Enable dev mode by setting environment variable
|
|
12
|
-
*/
|
|
13
|
-
export declare function enableDevMode(): void;
|
package/dist/utils/devMode.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { createHash, randomUUID } from 'crypto';
|
|
2
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
3
|
-
import { homedir } from 'os';
|
|
4
|
-
import { join } from 'path';
|
|
5
|
-
const SNOW_DIR = join(homedir(), '.snow');
|
|
6
|
-
const DEV_USER_ID_FILE = join(SNOW_DIR, 'dev-user-id');
|
|
7
|
-
/**
|
|
8
|
-
* Ensure .snow directory exists
|
|
9
|
-
*/
|
|
10
|
-
function ensureSnowDir() {
|
|
11
|
-
if (!existsSync(SNOW_DIR)) {
|
|
12
|
-
mkdirSync(SNOW_DIR, { recursive: true });
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Generate a persistent dev userId following Anthropic's format
|
|
17
|
-
* Format: user_<hash>_account__session_<uuid>
|
|
18
|
-
*/
|
|
19
|
-
function generateDevUserId() {
|
|
20
|
-
const sessionId = randomUUID();
|
|
21
|
-
const hash = createHash('sha256')
|
|
22
|
-
.update(`anthropic_dev_user_${sessionId}`)
|
|
23
|
-
.digest('hex');
|
|
24
|
-
return `user_${hash}_account__session_${sessionId}`;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Get or create persistent dev userId
|
|
28
|
-
* The userId is stored in ~/.snow/dev-user-id and persists across sessions
|
|
29
|
-
*/
|
|
30
|
-
export function getDevUserId() {
|
|
31
|
-
ensureSnowDir();
|
|
32
|
-
if (existsSync(DEV_USER_ID_FILE)) {
|
|
33
|
-
const userId = readFileSync(DEV_USER_ID_FILE, 'utf-8').trim();
|
|
34
|
-
if (userId) {
|
|
35
|
-
return userId;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
// Generate new userId if file doesn't exist or is empty
|
|
39
|
-
const userId = generateDevUserId();
|
|
40
|
-
writeFileSync(DEV_USER_ID_FILE, userId, 'utf-8');
|
|
41
|
-
return userId;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Check if dev mode is enabled
|
|
45
|
-
*/
|
|
46
|
-
export function isDevMode() {
|
|
47
|
-
return process.env['SNOW_DEV_MODE'] === 'true';
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Enable dev mode by setting environment variable
|
|
51
|
-
*/
|
|
52
|
-
export function enableDevMode() {
|
|
53
|
-
process.env['SNOW_DEV_MODE'] = 'true';
|
|
54
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Escape Handler Utility
|
|
3
|
-
* Handles escape sequence issues in AI-generated content
|
|
4
|
-
* Based on Gemini CLI's approach to handle common LLM escaping bugs
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Unescapes a string that might have been overly escaped by an LLM.
|
|
8
|
-
* Common issues:
|
|
9
|
-
* - "\\n" should be "\n" (newline)
|
|
10
|
-
* - "\\t" should be "\t" (tab)
|
|
11
|
-
* - "\\`" should be "`" (backtick)
|
|
12
|
-
* - "\\\\" should be "\\" (single backslash)
|
|
13
|
-
* - "\\"Hello\\"" should be "\"Hello\"" (quotes)
|
|
14
|
-
*
|
|
15
|
-
* @param inputString - The potentially over-escaped string from AI
|
|
16
|
-
* @returns The unescaped string
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* unescapeString("console.log(\\"Hello\\\\n\\")")
|
|
20
|
-
* // Returns: console.log("Hello\n")
|
|
21
|
-
*
|
|
22
|
-
* unescapeString("const msg = \`Hello \\`\${name}\\`\`")
|
|
23
|
-
* // Returns: const msg = `Hello `${name}``
|
|
24
|
-
*/
|
|
25
|
-
export declare function unescapeString(inputString: string): string;
|
|
26
|
-
/**
|
|
27
|
-
* Checks if a string appears to be over-escaped by comparing it with its unescaped version
|
|
28
|
-
*
|
|
29
|
-
* @param inputString - The string to check
|
|
30
|
-
* @returns True if the string contains escape sequences that would be modified by unescapeString
|
|
31
|
-
*
|
|
32
|
-
* @example
|
|
33
|
-
* isOverEscaped("console.log(\\"Hello\\")") // Returns: true
|
|
34
|
-
* isOverEscaped("console.log(\"Hello\")") // Returns: false
|
|
35
|
-
*/
|
|
36
|
-
export declare function isOverEscaped(inputString: string): boolean;
|
|
37
|
-
/**
|
|
38
|
-
* Counts occurrences of a substring in a string
|
|
39
|
-
* Used to verify if unescaping helps find the correct match
|
|
40
|
-
*
|
|
41
|
-
* @param str - The string to search in
|
|
42
|
-
* @param substr - The substring to search for
|
|
43
|
-
* @returns Number of occurrences found
|
|
44
|
-
*/
|
|
45
|
-
export declare function countOccurrences(str: string, substr: string): number;
|
|
46
|
-
/**
|
|
47
|
-
* Attempts to fix a search string that doesn't match by trying unescaping
|
|
48
|
-
* This is a lightweight, non-LLM approach to handle common escaping issues
|
|
49
|
-
*
|
|
50
|
-
* @param fileContent - The content of the file to search in
|
|
51
|
-
* @param searchString - The search string that failed to match
|
|
52
|
-
* @param expectedOccurrences - Expected number of matches (default: 1)
|
|
53
|
-
* @returns Object with corrected string and match count, or null if correction didn't help
|
|
54
|
-
*
|
|
55
|
-
* @example
|
|
56
|
-
* const fixed = tryUnescapeFix(fileContent, "console.log(\\"Hello\\")", 1);
|
|
57
|
-
* if (fixed) {
|
|
58
|
-
* // Use fixed.correctedString for the search
|
|
59
|
-
* }
|
|
60
|
-
*/
|
|
61
|
-
export declare function tryUnescapeFix(fileContent: string, searchString: string, expectedOccurrences?: number): {
|
|
62
|
-
correctedString: string;
|
|
63
|
-
occurrences: number;
|
|
64
|
-
} | null;
|
|
65
|
-
/**
|
|
66
|
-
* Smart trimming that preserves the relationship between paired strings
|
|
67
|
-
* If trimming the target string results in the expected number of matches,
|
|
68
|
-
* also trim the paired string to maintain consistency
|
|
69
|
-
*
|
|
70
|
-
* @param targetString - The string to potentially trim
|
|
71
|
-
* @param pairedString - The paired string (e.g., replacement content)
|
|
72
|
-
* @param fileContent - The file content to search in
|
|
73
|
-
* @param expectedOccurrences - Expected number of matches
|
|
74
|
-
* @returns Object with potentially trimmed strings
|
|
75
|
-
*/
|
|
76
|
-
export declare function trimPairIfPossible(targetString: string, pairedString: string, fileContent: string, expectedOccurrences?: number): {
|
|
77
|
-
target: string;
|
|
78
|
-
paired: string;
|
|
79
|
-
};
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Escape Handler Utility
|
|
3
|
-
* Handles escape sequence issues in AI-generated content
|
|
4
|
-
* Based on Gemini CLI's approach to handle common LLM escaping bugs
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Unescapes a string that might have been overly escaped by an LLM.
|
|
8
|
-
* Common issues:
|
|
9
|
-
* - "\\n" should be "\n" (newline)
|
|
10
|
-
* - "\\t" should be "\t" (tab)
|
|
11
|
-
* - "\\`" should be "`" (backtick)
|
|
12
|
-
* - "\\\\" should be "\\" (single backslash)
|
|
13
|
-
* - "\\"Hello\\"" should be "\"Hello\"" (quotes)
|
|
14
|
-
*
|
|
15
|
-
* @param inputString - The potentially over-escaped string from AI
|
|
16
|
-
* @returns The unescaped string
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* unescapeString("console.log(\\"Hello\\\\n\\")")
|
|
20
|
-
* // Returns: console.log("Hello\n")
|
|
21
|
-
*
|
|
22
|
-
* unescapeString("const msg = \`Hello \\`\${name}\\`\`")
|
|
23
|
-
* // Returns: const msg = `Hello `${name}``
|
|
24
|
-
*/
|
|
25
|
-
export function unescapeString(inputString) {
|
|
26
|
-
// Regex explanation:
|
|
27
|
-
// \\+ : Matches one or more literal backslash characters
|
|
28
|
-
// (n|t|r|'|"|`|\\|\n) : Capturing group that matches:
|
|
29
|
-
// n, t, r : Literal characters for escape sequences
|
|
30
|
-
// ', ", ` : Quote characters
|
|
31
|
-
// \\ : Literal backslash
|
|
32
|
-
// \n : Actual newline character
|
|
33
|
-
// g : Global flag to replace all occurrences
|
|
34
|
-
return inputString.replace(/\\+(n|t|r|'|"|`|\\|\n)/g, (match, capturedChar) => {
|
|
35
|
-
// 'match' is the entire erroneous sequence, e.g., "\\n" or "\\\\`"
|
|
36
|
-
// 'capturedChar' is the character that determines the true meaning
|
|
37
|
-
switch (capturedChar) {
|
|
38
|
-
case 'n':
|
|
39
|
-
return '\n'; // Newline character
|
|
40
|
-
case 't':
|
|
41
|
-
return '\t'; // Tab character
|
|
42
|
-
case 'r':
|
|
43
|
-
return '\r'; // Carriage return
|
|
44
|
-
case "'":
|
|
45
|
-
return "'"; // Single quote
|
|
46
|
-
case '"':
|
|
47
|
-
return '"'; // Double quote
|
|
48
|
-
case '`':
|
|
49
|
-
return '`'; // Backtick
|
|
50
|
-
case '\\':
|
|
51
|
-
return '\\'; // Single backslash
|
|
52
|
-
case '\n':
|
|
53
|
-
return '\n'; // Clean newline (handles "\\\n" cases)
|
|
54
|
-
default:
|
|
55
|
-
// Fallback: return original match if unexpected character
|
|
56
|
-
return match;
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Checks if a string appears to be over-escaped by comparing it with its unescaped version
|
|
62
|
-
*
|
|
63
|
-
* @param inputString - The string to check
|
|
64
|
-
* @returns True if the string contains escape sequences that would be modified by unescapeString
|
|
65
|
-
*
|
|
66
|
-
* @example
|
|
67
|
-
* isOverEscaped("console.log(\\"Hello\\")") // Returns: true
|
|
68
|
-
* isOverEscaped("console.log(\"Hello\")") // Returns: false
|
|
69
|
-
*/
|
|
70
|
-
export function isOverEscaped(inputString) {
|
|
71
|
-
return unescapeString(inputString) !== inputString;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Counts occurrences of a substring in a string
|
|
75
|
-
* Used to verify if unescaping helps find the correct match
|
|
76
|
-
*
|
|
77
|
-
* @param str - The string to search in
|
|
78
|
-
* @param substr - The substring to search for
|
|
79
|
-
* @returns Number of occurrences found
|
|
80
|
-
*/
|
|
81
|
-
export function countOccurrences(str, substr) {
|
|
82
|
-
if (substr === '') {
|
|
83
|
-
return 0;
|
|
84
|
-
}
|
|
85
|
-
let count = 0;
|
|
86
|
-
let pos = str.indexOf(substr);
|
|
87
|
-
while (pos !== -1) {
|
|
88
|
-
count++;
|
|
89
|
-
pos = str.indexOf(substr, pos + substr.length);
|
|
90
|
-
}
|
|
91
|
-
return count;
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Attempts to fix a search string that doesn't match by trying unescaping
|
|
95
|
-
* This is a lightweight, non-LLM approach to handle common escaping issues
|
|
96
|
-
*
|
|
97
|
-
* @param fileContent - The content of the file to search in
|
|
98
|
-
* @param searchString - The search string that failed to match
|
|
99
|
-
* @param expectedOccurrences - Expected number of matches (default: 1)
|
|
100
|
-
* @returns Object with corrected string and match count, or null if correction didn't help
|
|
101
|
-
*
|
|
102
|
-
* @example
|
|
103
|
-
* const fixed = tryUnescapeFix(fileContent, "console.log(\\"Hello\\")", 1);
|
|
104
|
-
* if (fixed) {
|
|
105
|
-
* // Use fixed.correctedString for the search
|
|
106
|
-
* }
|
|
107
|
-
*/
|
|
108
|
-
export function tryUnescapeFix(fileContent, searchString, expectedOccurrences = 1) {
|
|
109
|
-
// Check if the string appears to be over-escaped
|
|
110
|
-
if (!isOverEscaped(searchString)) {
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
// Try unescaping
|
|
114
|
-
const unescaped = unescapeString(searchString);
|
|
115
|
-
// Count occurrences with unescaped version
|
|
116
|
-
const occurrences = countOccurrences(fileContent, unescaped);
|
|
117
|
-
// Return result if it matches expected occurrences
|
|
118
|
-
if (occurrences === expectedOccurrences) {
|
|
119
|
-
return {
|
|
120
|
-
correctedString: unescaped,
|
|
121
|
-
occurrences,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Smart trimming that preserves the relationship between paired strings
|
|
128
|
-
* If trimming the target string results in the expected number of matches,
|
|
129
|
-
* also trim the paired string to maintain consistency
|
|
130
|
-
*
|
|
131
|
-
* @param targetString - The string to potentially trim
|
|
132
|
-
* @param pairedString - The paired string (e.g., replacement content)
|
|
133
|
-
* @param fileContent - The file content to search in
|
|
134
|
-
* @param expectedOccurrences - Expected number of matches
|
|
135
|
-
* @returns Object with potentially trimmed strings
|
|
136
|
-
*/
|
|
137
|
-
export function trimPairIfPossible(targetString, pairedString, fileContent, expectedOccurrences = 1) {
|
|
138
|
-
const trimmedTarget = targetString.trim();
|
|
139
|
-
// If trimming doesn't change the string, return as-is
|
|
140
|
-
if (targetString.length === trimmedTarget.length) {
|
|
141
|
-
return { target: targetString, paired: pairedString };
|
|
142
|
-
}
|
|
143
|
-
// Check if trimmed version matches expected occurrences
|
|
144
|
-
const trimmedOccurrences = countOccurrences(fileContent, trimmedTarget);
|
|
145
|
-
if (trimmedOccurrences === expectedOccurrences) {
|
|
146
|
-
return {
|
|
147
|
-
target: trimmedTarget,
|
|
148
|
-
paired: pairedString.trim(),
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
// Trimming didn't help, return original
|
|
152
|
-
return { target: targetString, paired: pairedString };
|
|
153
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cross-platform file save dialog
|
|
3
|
-
* Opens a native file save dialog and returns the selected path
|
|
4
|
-
*/
|
|
5
|
-
export declare function showSaveDialog(defaultFilename?: string, title?: string): Promise<string | null>;
|
|
6
|
-
/**
|
|
7
|
-
* Check if native file dialogs are available on this platform
|
|
8
|
-
*/
|
|
9
|
-
export declare function isFileDialogSupported(): boolean;
|