snow-ai 0.4.15 → 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 -379
- 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 -1495
- 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
package/dist/api/chat.js
DELETED
|
@@ -1,386 +0,0 @@
|
|
|
1
|
-
import { getOpenAiConfig, getCustomSystemPrompt, getCustomHeaders, } from '../utils/apiConfig.js';
|
|
2
|
-
import { getSystemPrompt } from './systemPrompt.js';
|
|
3
|
-
import { withRetryGenerator, parseJsonWithFix } from '../utils/retryUtils.js';
|
|
4
|
-
import { addProxyToFetchOptions } from '../utils/proxyUtils.js';
|
|
5
|
-
import { saveUsageToFile } from '../utils/usageLogger.js';
|
|
6
|
-
/**
|
|
7
|
-
* Convert our ChatMessage format to OpenAI's ChatCompletionMessageParam format
|
|
8
|
-
* Automatically prepends system prompt if not present
|
|
9
|
-
* Logic:
|
|
10
|
-
* 1. If custom system prompt exists: use custom as system, prepend default as first user message
|
|
11
|
-
* 2. If no custom system prompt: use default as system
|
|
12
|
-
* @param messages - The messages to convert
|
|
13
|
-
* @param includeBuiltinSystemPrompt - Whether to include builtin system prompt (default true)
|
|
14
|
-
*/
|
|
15
|
-
function convertToOpenAIMessages(messages, includeBuiltinSystemPrompt = true) {
|
|
16
|
-
const customSystemPrompt = getCustomSystemPrompt();
|
|
17
|
-
let result = messages.map(msg => {
|
|
18
|
-
// 如果消息包含图片,使用 content 数组格式
|
|
19
|
-
if (msg.role === 'user' && msg.images && msg.images.length > 0) {
|
|
20
|
-
const contentParts = [];
|
|
21
|
-
// 添加文本内容
|
|
22
|
-
if (msg.content) {
|
|
23
|
-
contentParts.push({
|
|
24
|
-
type: 'text',
|
|
25
|
-
text: msg.content,
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
// 添加图片内容
|
|
29
|
-
for (const image of msg.images) {
|
|
30
|
-
contentParts.push({
|
|
31
|
-
type: 'image_url',
|
|
32
|
-
image_url: {
|
|
33
|
-
url: image.data, // Base64 data URL
|
|
34
|
-
},
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
return {
|
|
38
|
-
role: 'user',
|
|
39
|
-
content: contentParts,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
const baseMessage = {
|
|
43
|
-
role: msg.role,
|
|
44
|
-
content: msg.content,
|
|
45
|
-
};
|
|
46
|
-
if (msg.role === 'assistant' && msg.tool_calls) {
|
|
47
|
-
return {
|
|
48
|
-
...baseMessage,
|
|
49
|
-
tool_calls: msg.tool_calls,
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
if (msg.role === 'tool' && msg.tool_call_id) {
|
|
53
|
-
// Handle multimodal tool results with images
|
|
54
|
-
if (msg.images && msg.images.length > 0) {
|
|
55
|
-
const content = [];
|
|
56
|
-
// Add text content
|
|
57
|
-
if (msg.content) {
|
|
58
|
-
content.push({
|
|
59
|
-
type: 'text',
|
|
60
|
-
text: msg.content,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
// Add images as base64 data URLs
|
|
64
|
-
for (const image of msg.images) {
|
|
65
|
-
content.push({
|
|
66
|
-
type: 'image_url',
|
|
67
|
-
image_url: {
|
|
68
|
-
url: `data:${image.mimeType};base64,${image.data}`,
|
|
69
|
-
},
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
return {
|
|
73
|
-
role: 'tool',
|
|
74
|
-
content,
|
|
75
|
-
tool_call_id: msg.tool_call_id,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
return {
|
|
79
|
-
role: 'tool',
|
|
80
|
-
content: msg.content,
|
|
81
|
-
tool_call_id: msg.tool_call_id,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
return baseMessage;
|
|
85
|
-
});
|
|
86
|
-
// 如果第一条消息已经是 system 消息,跳过
|
|
87
|
-
if (result.length > 0 && result[0]?.role === 'system') {
|
|
88
|
-
return result;
|
|
89
|
-
}
|
|
90
|
-
// 如果配置了自定义系统提示词(最高优先级,始终添加)
|
|
91
|
-
if (customSystemPrompt) {
|
|
92
|
-
if (includeBuiltinSystemPrompt) {
|
|
93
|
-
// 自定义系统提示词作为 system 消息,默认系统提示词作为第一条 user 消息
|
|
94
|
-
result = [
|
|
95
|
-
{
|
|
96
|
-
role: 'system',
|
|
97
|
-
content: customSystemPrompt,
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
role: 'user',
|
|
101
|
-
content: getSystemPrompt(),
|
|
102
|
-
},
|
|
103
|
-
...result,
|
|
104
|
-
];
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
// 只添加自定义系统提示词
|
|
108
|
-
result = [
|
|
109
|
-
{
|
|
110
|
-
role: 'system',
|
|
111
|
-
content: customSystemPrompt,
|
|
112
|
-
},
|
|
113
|
-
...result,
|
|
114
|
-
];
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
else if (includeBuiltinSystemPrompt) {
|
|
118
|
-
// 没有自定义系统提示词,但需要添加默认系统提示词
|
|
119
|
-
result = [
|
|
120
|
-
{
|
|
121
|
-
role: 'system',
|
|
122
|
-
content: getSystemPrompt(),
|
|
123
|
-
},
|
|
124
|
-
...result,
|
|
125
|
-
];
|
|
126
|
-
}
|
|
127
|
-
return result;
|
|
128
|
-
}
|
|
129
|
-
let openaiConfig = null;
|
|
130
|
-
function getOpenAIConfig() {
|
|
131
|
-
if (!openaiConfig) {
|
|
132
|
-
const config = getOpenAiConfig();
|
|
133
|
-
if (!config.apiKey || !config.baseUrl) {
|
|
134
|
-
throw new Error('OpenAI API configuration is incomplete. Please configure API settings first.');
|
|
135
|
-
}
|
|
136
|
-
const customHeaders = getCustomHeaders();
|
|
137
|
-
openaiConfig = {
|
|
138
|
-
apiKey: config.apiKey,
|
|
139
|
-
baseUrl: config.baseUrl,
|
|
140
|
-
customHeaders,
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
return openaiConfig;
|
|
144
|
-
}
|
|
145
|
-
export function resetOpenAIClient() {
|
|
146
|
-
openaiConfig = null;
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Parse Server-Sent Events (SSE) stream
|
|
150
|
-
*/
|
|
151
|
-
async function* parseSSEStream(reader) {
|
|
152
|
-
const decoder = new TextDecoder();
|
|
153
|
-
let buffer = '';
|
|
154
|
-
try {
|
|
155
|
-
while (true) {
|
|
156
|
-
const { done, value } = await reader.read();
|
|
157
|
-
if (done) {
|
|
158
|
-
// ✅ 关键修复:检查buffer是否有残留数据
|
|
159
|
-
if (buffer.trim()) {
|
|
160
|
-
// 连接异常中断,抛出明确错误
|
|
161
|
-
throw new Error(`Stream terminated unexpectedly with incomplete data: ${buffer.substring(0, 100)}...`);
|
|
162
|
-
}
|
|
163
|
-
break; // 正常结束
|
|
164
|
-
}
|
|
165
|
-
buffer += decoder.decode(value, { stream: true });
|
|
166
|
-
const lines = buffer.split('\n');
|
|
167
|
-
buffer = lines.pop() || '';
|
|
168
|
-
for (const line of lines) {
|
|
169
|
-
const trimmed = line.trim();
|
|
170
|
-
if (!trimmed || trimmed.startsWith(':'))
|
|
171
|
-
continue;
|
|
172
|
-
if (trimmed === 'data: [DONE]' || trimmed === 'data:[DONE]') {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
// Handle both "event: " and "event:" formats
|
|
176
|
-
if (trimmed.startsWith('event:')) {
|
|
177
|
-
// Event type, will be followed by data
|
|
178
|
-
continue;
|
|
179
|
-
}
|
|
180
|
-
// Handle both "data: " and "data:" formats
|
|
181
|
-
if (trimmed.startsWith('data:')) {
|
|
182
|
-
const data = trimmed.startsWith('data: ')
|
|
183
|
-
? trimmed.slice(6)
|
|
184
|
-
: trimmed.slice(5);
|
|
185
|
-
const parseResult = parseJsonWithFix(data, {
|
|
186
|
-
toolName: 'SSE stream',
|
|
187
|
-
logWarning: false,
|
|
188
|
-
logError: true,
|
|
189
|
-
});
|
|
190
|
-
if (parseResult.success) {
|
|
191
|
-
yield parseResult.data;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
catch (error) {
|
|
198
|
-
const { logger } = await import('../utils/logger.js');
|
|
199
|
-
logger.error('SSE stream parsing error:', {
|
|
200
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
201
|
-
remainingBuffer: buffer.substring(0, 200),
|
|
202
|
-
});
|
|
203
|
-
throw error;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Simple streaming chat completion - only handles OpenAI interaction
|
|
208
|
-
* Tool execution should be handled by the caller
|
|
209
|
-
*/
|
|
210
|
-
export async function* createStreamingChatCompletion(options, abortSignal, onRetry) {
|
|
211
|
-
const config = getOpenAIConfig();
|
|
212
|
-
// 使用重试包装生成器
|
|
213
|
-
yield* withRetryGenerator(async function* () {
|
|
214
|
-
const requestBody = {
|
|
215
|
-
model: options.model,
|
|
216
|
-
messages: convertToOpenAIMessages(options.messages, options.includeBuiltinSystemPrompt !== false),
|
|
217
|
-
stream: true,
|
|
218
|
-
stream_options: { include_usage: true },
|
|
219
|
-
temperature: options.temperature || 0.7,
|
|
220
|
-
max_tokens: options.max_tokens,
|
|
221
|
-
tools: options.tools,
|
|
222
|
-
tool_choice: options.tool_choice,
|
|
223
|
-
};
|
|
224
|
-
const url = `${config.baseUrl}/chat/completions`;
|
|
225
|
-
const fetchOptions = addProxyToFetchOptions(url, {
|
|
226
|
-
method: 'POST',
|
|
227
|
-
headers: {
|
|
228
|
-
'Content-Type': 'application/json',
|
|
229
|
-
Authorization: `Bearer ${config.apiKey}`,
|
|
230
|
-
'x-snow': 'true',
|
|
231
|
-
...config.customHeaders,
|
|
232
|
-
},
|
|
233
|
-
body: JSON.stringify(requestBody),
|
|
234
|
-
signal: abortSignal,
|
|
235
|
-
});
|
|
236
|
-
const response = await fetch(url, fetchOptions);
|
|
237
|
-
if (!response.ok) {
|
|
238
|
-
const errorText = await response.text();
|
|
239
|
-
throw new Error(`OpenAI API error: ${response.status} ${response.statusText} - ${errorText}`);
|
|
240
|
-
}
|
|
241
|
-
if (!response.body) {
|
|
242
|
-
throw new Error('No response body from OpenAI API');
|
|
243
|
-
}
|
|
244
|
-
let contentBuffer = '';
|
|
245
|
-
let toolCallsBuffer = {};
|
|
246
|
-
let hasToolCalls = false;
|
|
247
|
-
let usageData;
|
|
248
|
-
let reasoningStarted = false; // Track if reasoning has started
|
|
249
|
-
for await (const chunk of parseSSEStream(response.body.getReader())) {
|
|
250
|
-
if (abortSignal?.aborted) {
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
// Capture usage information if available (usually in the last chunk)
|
|
254
|
-
const usageValue = chunk.usage;
|
|
255
|
-
if (usageValue !== null && usageValue !== undefined) {
|
|
256
|
-
usageData = {
|
|
257
|
-
prompt_tokens: usageValue.prompt_tokens || 0,
|
|
258
|
-
completion_tokens: usageValue.completion_tokens || 0,
|
|
259
|
-
total_tokens: usageValue.total_tokens || 0,
|
|
260
|
-
// OpenAI Chat API: cached_tokens in prompt_tokens_details
|
|
261
|
-
cached_tokens: usageValue.prompt_tokens_details?.cached_tokens,
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
// Skip content processing if no choices (but usage is already captured above)
|
|
265
|
-
const choice = chunk.choices[0];
|
|
266
|
-
if (!choice) {
|
|
267
|
-
continue;
|
|
268
|
-
}
|
|
269
|
-
// Stream content chunks
|
|
270
|
-
const content = choice.delta?.content;
|
|
271
|
-
if (content) {
|
|
272
|
-
contentBuffer += content;
|
|
273
|
-
yield {
|
|
274
|
-
type: 'content',
|
|
275
|
-
content,
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
// Stream reasoning content (for o1 models, etc.)
|
|
279
|
-
// Note: reasoning_content is NOT included in the response, only counted for tokens
|
|
280
|
-
const reasoningContent = choice.delta?.reasoning_content;
|
|
281
|
-
if (reasoningContent) {
|
|
282
|
-
// Emit reasoning_started event on first reasoning content
|
|
283
|
-
if (!reasoningStarted) {
|
|
284
|
-
reasoningStarted = true;
|
|
285
|
-
yield {
|
|
286
|
-
type: 'reasoning_started',
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
yield {
|
|
290
|
-
type: 'reasoning_delta',
|
|
291
|
-
delta: reasoningContent,
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
// Accumulate tool calls and stream deltas
|
|
295
|
-
const deltaToolCalls = choice.delta?.tool_calls;
|
|
296
|
-
if (deltaToolCalls) {
|
|
297
|
-
hasToolCalls = true;
|
|
298
|
-
for (const deltaCall of deltaToolCalls) {
|
|
299
|
-
const index = deltaCall.index ?? 0;
|
|
300
|
-
if (!toolCallsBuffer[index]) {
|
|
301
|
-
toolCallsBuffer[index] = {
|
|
302
|
-
id: '',
|
|
303
|
-
type: 'function',
|
|
304
|
-
function: {
|
|
305
|
-
name: '',
|
|
306
|
-
arguments: '',
|
|
307
|
-
},
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
if (deltaCall.id) {
|
|
311
|
-
toolCallsBuffer[index].id = deltaCall.id;
|
|
312
|
-
}
|
|
313
|
-
// Yield tool call deltas for token counting
|
|
314
|
-
let deltaText = '';
|
|
315
|
-
if (deltaCall.function?.name) {
|
|
316
|
-
toolCallsBuffer[index].function.name += deltaCall.function.name;
|
|
317
|
-
deltaText += deltaCall.function.name;
|
|
318
|
-
}
|
|
319
|
-
if (deltaCall.function?.arguments) {
|
|
320
|
-
toolCallsBuffer[index].function.arguments +=
|
|
321
|
-
deltaCall.function.arguments;
|
|
322
|
-
deltaText += deltaCall.function.arguments;
|
|
323
|
-
}
|
|
324
|
-
// Stream the delta to frontend for real-time token counting
|
|
325
|
-
if (deltaText) {
|
|
326
|
-
yield {
|
|
327
|
-
type: 'tool_call_delta',
|
|
328
|
-
delta: deltaText,
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
if (choice.finish_reason) {
|
|
334
|
-
break;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
// If there are tool calls, yield them
|
|
338
|
-
if (hasToolCalls) {
|
|
339
|
-
yield {
|
|
340
|
-
type: 'tool_calls',
|
|
341
|
-
tool_calls: Object.values(toolCallsBuffer),
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
// Yield usage information if available
|
|
345
|
-
if (usageData) {
|
|
346
|
-
// Save usage to file system at API layer
|
|
347
|
-
saveUsageToFile(options.model, usageData);
|
|
348
|
-
yield {
|
|
349
|
-
type: 'usage',
|
|
350
|
-
usage: usageData,
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
// Signal completion
|
|
354
|
-
yield {
|
|
355
|
-
type: 'done',
|
|
356
|
-
};
|
|
357
|
-
}, {
|
|
358
|
-
abortSignal,
|
|
359
|
-
onRetry,
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
export function validateChatOptions(options) {
|
|
363
|
-
const errors = [];
|
|
364
|
-
if (!options.model || options.model.trim().length === 0) {
|
|
365
|
-
errors.push('Model is required');
|
|
366
|
-
}
|
|
367
|
-
if (!options.messages || options.messages.length === 0) {
|
|
368
|
-
errors.push('At least one message is required');
|
|
369
|
-
}
|
|
370
|
-
for (const message of options.messages || []) {
|
|
371
|
-
if (!message.role ||
|
|
372
|
-
!['system', 'user', 'assistant', 'tool'].includes(message.role)) {
|
|
373
|
-
errors.push('Invalid message role');
|
|
374
|
-
}
|
|
375
|
-
// Tool messages must have tool_call_id
|
|
376
|
-
if (message.role === 'tool' && !message.tool_call_id) {
|
|
377
|
-
errors.push('Tool messages must have tool_call_id');
|
|
378
|
-
}
|
|
379
|
-
// Content can be empty for tool calls
|
|
380
|
-
if (message.role !== 'tool' &&
|
|
381
|
-
(!message.content || message.content.trim().length === 0)) {
|
|
382
|
-
errors.push('Message content cannot be empty (except for tool messages)');
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
return errors;
|
|
386
|
-
}
|
package/dist/api/embedding.d.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
export interface EmbeddingOptions {
|
|
2
|
-
model?: string;
|
|
3
|
-
input: string[];
|
|
4
|
-
baseUrl?: string;
|
|
5
|
-
apiKey?: string;
|
|
6
|
-
dimensions?: number;
|
|
7
|
-
task?: string;
|
|
8
|
-
}
|
|
9
|
-
export interface EmbeddingResponse {
|
|
10
|
-
model: string;
|
|
11
|
-
object: string;
|
|
12
|
-
usage: {
|
|
13
|
-
total_tokens: number;
|
|
14
|
-
prompt_tokens: number;
|
|
15
|
-
};
|
|
16
|
-
data: Array<{
|
|
17
|
-
object: string;
|
|
18
|
-
index: number;
|
|
19
|
-
embedding: number[];
|
|
20
|
-
}>;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Create embeddings for text array (single API call)
|
|
24
|
-
* @param options Embedding options
|
|
25
|
-
* @returns Embedding response with vectors
|
|
26
|
-
*/
|
|
27
|
-
export declare function createEmbeddings(options: EmbeddingOptions): Promise<EmbeddingResponse>;
|
|
28
|
-
/**
|
|
29
|
-
* Create embedding for single text
|
|
30
|
-
* @param text Single text to embed
|
|
31
|
-
* @param options Optional embedding options
|
|
32
|
-
* @returns Embedding vector
|
|
33
|
-
*/
|
|
34
|
-
export declare function createEmbedding(text: string, options?: Partial<EmbeddingOptions>): Promise<number[]>;
|
package/dist/api/embedding.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { loadCodebaseConfig } from '../utils/codebaseConfig.js';
|
|
2
|
-
import { addProxyToFetchOptions } from '../utils/proxyUtils.js';
|
|
3
|
-
/**
|
|
4
|
-
* Create embeddings for text array (single API call)
|
|
5
|
-
* @param options Embedding options
|
|
6
|
-
* @returns Embedding response with vectors
|
|
7
|
-
*/
|
|
8
|
-
export async function createEmbeddings(options) {
|
|
9
|
-
const config = loadCodebaseConfig();
|
|
10
|
-
// Use config defaults if not provided
|
|
11
|
-
const model = options.model || config.embedding.modelName;
|
|
12
|
-
const baseUrl = options.baseUrl || config.embedding.baseUrl;
|
|
13
|
-
const apiKey = options.apiKey || config.embedding.apiKey;
|
|
14
|
-
const dimensions = options.dimensions ?? config.embedding.dimensions;
|
|
15
|
-
const { input, task } = options;
|
|
16
|
-
if (!model) {
|
|
17
|
-
throw new Error('Embedding model name is required');
|
|
18
|
-
}
|
|
19
|
-
if (!baseUrl) {
|
|
20
|
-
throw new Error('Embedding base URL is required');
|
|
21
|
-
}
|
|
22
|
-
// API key is optional for local deployments (e.g., Ollama)
|
|
23
|
-
// if (!apiKey) {
|
|
24
|
-
// throw new Error('Embedding API key is required');
|
|
25
|
-
// }
|
|
26
|
-
if (!input || input.length === 0) {
|
|
27
|
-
throw new Error('Input texts are required');
|
|
28
|
-
}
|
|
29
|
-
// Build request body
|
|
30
|
-
const requestBody = {
|
|
31
|
-
model,
|
|
32
|
-
input,
|
|
33
|
-
};
|
|
34
|
-
if (task) {
|
|
35
|
-
requestBody.task = task;
|
|
36
|
-
}
|
|
37
|
-
if (dimensions) {
|
|
38
|
-
requestBody.dimensions = dimensions;
|
|
39
|
-
}
|
|
40
|
-
// Use baseUrl directly, append /embeddings if needed
|
|
41
|
-
const url = baseUrl.endsWith('/embeddings')
|
|
42
|
-
? baseUrl
|
|
43
|
-
: `${baseUrl.replace(/\/$/, '')}/embeddings`;
|
|
44
|
-
// Build headers - only include Authorization if API key is provided
|
|
45
|
-
const headers = {
|
|
46
|
-
'Content-Type': 'application/json',
|
|
47
|
-
'x-snow': 'true',
|
|
48
|
-
};
|
|
49
|
-
if (apiKey) {
|
|
50
|
-
headers['Authorization'] = `Bearer ${apiKey}`;
|
|
51
|
-
}
|
|
52
|
-
const fetchOptions = addProxyToFetchOptions(url, {
|
|
53
|
-
method: 'POST',
|
|
54
|
-
headers,
|
|
55
|
-
body: JSON.stringify(requestBody),
|
|
56
|
-
});
|
|
57
|
-
const response = await fetch(url, fetchOptions);
|
|
58
|
-
if (!response.ok) {
|
|
59
|
-
const errorText = await response.text();
|
|
60
|
-
throw new Error(`Embedding API error (${response.status}): ${errorText}`);
|
|
61
|
-
}
|
|
62
|
-
const data = await response.json();
|
|
63
|
-
return data;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Create embedding for single text
|
|
67
|
-
* @param text Single text to embed
|
|
68
|
-
* @param options Optional embedding options
|
|
69
|
-
* @returns Embedding vector
|
|
70
|
-
*/
|
|
71
|
-
export async function createEmbedding(text, options) {
|
|
72
|
-
const response = await createEmbeddings({
|
|
73
|
-
input: [text],
|
|
74
|
-
...options,
|
|
75
|
-
});
|
|
76
|
-
if (response.data.length === 0) {
|
|
77
|
-
throw new Error('No embedding returned from API');
|
|
78
|
-
}
|
|
79
|
-
return response.data[0].embedding;
|
|
80
|
-
}
|
package/dist/api/gemini.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { ChatMessage, ChatCompletionTool, UsageInfo } from './types.js';
|
|
2
|
-
export interface GeminiOptions {
|
|
3
|
-
model: string;
|
|
4
|
-
messages: ChatMessage[];
|
|
5
|
-
temperature?: number;
|
|
6
|
-
tools?: ChatCompletionTool[];
|
|
7
|
-
includeBuiltinSystemPrompt?: boolean;
|
|
8
|
-
}
|
|
9
|
-
export interface GeminiStreamChunk {
|
|
10
|
-
type: 'content' | 'tool_calls' | 'tool_call_delta' | 'done' | 'usage' | 'reasoning_started' | 'reasoning_delta';
|
|
11
|
-
content?: string;
|
|
12
|
-
tool_calls?: Array<{
|
|
13
|
-
id: string;
|
|
14
|
-
type: 'function';
|
|
15
|
-
function: {
|
|
16
|
-
name: string;
|
|
17
|
-
arguments: string;
|
|
18
|
-
};
|
|
19
|
-
}>;
|
|
20
|
-
delta?: string;
|
|
21
|
-
usage?: UsageInfo;
|
|
22
|
-
thinking?: {
|
|
23
|
-
type: 'thinking';
|
|
24
|
-
thinking: string;
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
export declare function resetGeminiClient(): void;
|
|
28
|
-
/**
|
|
29
|
-
* Create streaming chat completion using Gemini API
|
|
30
|
-
*/
|
|
31
|
-
export declare function createStreamingGeminiCompletion(options: GeminiOptions, abortSignal?: AbortSignal, onRetry?: (error: Error, attempt: number, nextDelay: number) => void): AsyncGenerator<GeminiStreamChunk, void, unknown>;
|