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
|
@@ -1,379 +0,0 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useRef, useMemo } from 'react';
|
|
2
|
-
import { Box, Text } from 'ink';
|
|
3
|
-
import { cpSlice } from '../../utils/textUtils.js';
|
|
4
|
-
import CommandPanel from './CommandPanel.js';
|
|
5
|
-
import FileList from './FileList.js';
|
|
6
|
-
import AgentPickerPanel from './AgentPickerPanel.js';
|
|
7
|
-
import TodoPickerPanel from './TodoPickerPanel.js';
|
|
8
|
-
import { useInputBuffer } from '../../hooks/useInputBuffer.js';
|
|
9
|
-
import { useCommandPanel } from '../../hooks/useCommandPanel.js';
|
|
10
|
-
import { useFilePicker } from '../../hooks/useFilePicker.js';
|
|
11
|
-
import { useHistoryNavigation } from '../../hooks/useHistoryNavigation.js';
|
|
12
|
-
import { useClipboard } from '../../hooks/useClipboard.js';
|
|
13
|
-
import { useKeyboardInput } from '../../hooks/useKeyboardInput.js';
|
|
14
|
-
import { useTerminalSize } from '../../hooks/useTerminalSize.js';
|
|
15
|
-
import { useTerminalFocus } from '../../hooks/useTerminalFocus.js';
|
|
16
|
-
import { useAgentPicker } from '../../hooks/useAgentPicker.js';
|
|
17
|
-
import { useTodoPicker } from '../../hooks/useTodoPicker.js';
|
|
18
|
-
import { useI18n } from '../../i18n/index.js';
|
|
19
|
-
import { useTheme } from '../contexts/ThemeContext.js';
|
|
20
|
-
/**
|
|
21
|
-
* Calculate context usage percentage
|
|
22
|
-
* This is the same logic used in ChatInput to display usage
|
|
23
|
-
*/
|
|
24
|
-
export function calculateContextPercentage(contextUsage) {
|
|
25
|
-
// Determine which caching system is being used
|
|
26
|
-
const isAnthropic = (contextUsage.cacheCreationTokens || 0) > 0 ||
|
|
27
|
-
(contextUsage.cacheReadTokens || 0) > 0;
|
|
28
|
-
// For Anthropic: Total = inputTokens + cacheCreationTokens + cacheReadTokens
|
|
29
|
-
// For OpenAI: Total = inputTokens (cachedTokens are already included in inputTokens)
|
|
30
|
-
const totalInputTokens = isAnthropic
|
|
31
|
-
? contextUsage.inputTokens +
|
|
32
|
-
(contextUsage.cacheCreationTokens || 0) +
|
|
33
|
-
(contextUsage.cacheReadTokens || 0)
|
|
34
|
-
: contextUsage.inputTokens;
|
|
35
|
-
return Math.min(100, (totalInputTokens / contextUsage.maxContextTokens) * 100);
|
|
36
|
-
}
|
|
37
|
-
export default function ChatInput({ onSubmit, onCommand, placeholder = 'Type your message...', disabled = false, isProcessing = false, chatHistory = [], onHistorySelect, yoloMode = false, contextUsage, initialContent = null, onContextPercentageChange, }) {
|
|
38
|
-
// Use i18n hook for translations
|
|
39
|
-
const { t } = useI18n();
|
|
40
|
-
const { theme } = useTheme();
|
|
41
|
-
// Use terminal size hook to listen for resize events
|
|
42
|
-
const { columns: terminalWidth } = useTerminalSize();
|
|
43
|
-
const prevTerminalWidthRef = useRef(terminalWidth);
|
|
44
|
-
// Use terminal focus hook to detect focus state
|
|
45
|
-
const { hasFocus, ensureFocus } = useTerminalFocus();
|
|
46
|
-
// Recalculate viewport dimensions to ensure proper resizing
|
|
47
|
-
const uiOverhead = 8;
|
|
48
|
-
const viewportWidth = Math.max(40, terminalWidth - uiOverhead);
|
|
49
|
-
const viewport = useMemo(() => ({
|
|
50
|
-
width: viewportWidth,
|
|
51
|
-
height: 1,
|
|
52
|
-
}), [viewportWidth]); // Memoize viewport to prevent unnecessary re-renders
|
|
53
|
-
// Use input buffer hook
|
|
54
|
-
const { buffer, triggerUpdate, forceUpdate } = useInputBuffer(viewport);
|
|
55
|
-
// Use command panel hook
|
|
56
|
-
const { showCommands, setShowCommands, commandSelectedIndex, setCommandSelectedIndex, getFilteredCommands, updateCommandPanelState, isProcessing: commandPanelIsProcessing, } = useCommandPanel(buffer, isProcessing);
|
|
57
|
-
// Use file picker hook
|
|
58
|
-
const { showFilePicker, setShowFilePicker, fileSelectedIndex, setFileSelectedIndex, fileQuery, setFileQuery, atSymbolPosition, setAtSymbolPosition, filteredFileCount, searchMode, updateFilePickerState, handleFileSelect, handleFilteredCountChange, fileListRef, } = useFilePicker(buffer, triggerUpdate);
|
|
59
|
-
// Use history navigation hook
|
|
60
|
-
const { showHistoryMenu, setShowHistoryMenu, historySelectedIndex, setHistorySelectedIndex, escapeKeyCount, setEscapeKeyCount, escapeKeyTimer, getUserMessages, handleHistorySelect, currentHistoryIndex, navigateHistoryUp, navigateHistoryDown, resetHistoryNavigation, saveToHistory, } = useHistoryNavigation(buffer, triggerUpdate, chatHistory, onHistorySelect);
|
|
61
|
-
// Use agent picker hook
|
|
62
|
-
const { showAgentPicker, setShowAgentPicker, agentSelectedIndex, setAgentSelectedIndex, updateAgentPickerState, getFilteredAgents, handleAgentSelect, } = useAgentPicker(buffer, triggerUpdate);
|
|
63
|
-
// Use todo picker hook
|
|
64
|
-
const { showTodoPicker, setShowTodoPicker, todoSelectedIndex, setTodoSelectedIndex, todos, selectedTodos, toggleTodoSelection, confirmTodoSelection, isLoading: todoIsLoading, searchQuery: todoSearchQuery, setSearchQuery: setTodoSearchQuery, totalTodoCount, } = useTodoPicker(buffer, triggerUpdate, process.cwd());
|
|
65
|
-
// Use clipboard hook
|
|
66
|
-
const { pasteFromClipboard } = useClipboard(buffer, updateCommandPanelState, updateFilePickerState, triggerUpdate);
|
|
67
|
-
// Use keyboard input hook
|
|
68
|
-
useKeyboardInput({
|
|
69
|
-
buffer,
|
|
70
|
-
disabled,
|
|
71
|
-
triggerUpdate,
|
|
72
|
-
forceUpdate,
|
|
73
|
-
showCommands,
|
|
74
|
-
setShowCommands,
|
|
75
|
-
commandSelectedIndex,
|
|
76
|
-
setCommandSelectedIndex,
|
|
77
|
-
getFilteredCommands,
|
|
78
|
-
updateCommandPanelState,
|
|
79
|
-
onCommand,
|
|
80
|
-
showFilePicker,
|
|
81
|
-
setShowFilePicker,
|
|
82
|
-
fileSelectedIndex,
|
|
83
|
-
setFileSelectedIndex,
|
|
84
|
-
fileQuery,
|
|
85
|
-
setFileQuery,
|
|
86
|
-
atSymbolPosition,
|
|
87
|
-
setAtSymbolPosition,
|
|
88
|
-
filteredFileCount,
|
|
89
|
-
updateFilePickerState,
|
|
90
|
-
handleFileSelect,
|
|
91
|
-
fileListRef,
|
|
92
|
-
showHistoryMenu,
|
|
93
|
-
setShowHistoryMenu,
|
|
94
|
-
historySelectedIndex,
|
|
95
|
-
setHistorySelectedIndex,
|
|
96
|
-
escapeKeyCount,
|
|
97
|
-
setEscapeKeyCount,
|
|
98
|
-
escapeKeyTimer,
|
|
99
|
-
getUserMessages,
|
|
100
|
-
handleHistorySelect,
|
|
101
|
-
currentHistoryIndex,
|
|
102
|
-
navigateHistoryUp,
|
|
103
|
-
navigateHistoryDown,
|
|
104
|
-
resetHistoryNavigation,
|
|
105
|
-
saveToHistory,
|
|
106
|
-
pasteFromClipboard,
|
|
107
|
-
onSubmit,
|
|
108
|
-
ensureFocus,
|
|
109
|
-
showAgentPicker,
|
|
110
|
-
setShowAgentPicker,
|
|
111
|
-
agentSelectedIndex,
|
|
112
|
-
setAgentSelectedIndex,
|
|
113
|
-
updateAgentPickerState,
|
|
114
|
-
getFilteredAgents,
|
|
115
|
-
handleAgentSelect,
|
|
116
|
-
showTodoPicker,
|
|
117
|
-
setShowTodoPicker,
|
|
118
|
-
todoSelectedIndex,
|
|
119
|
-
setTodoSelectedIndex,
|
|
120
|
-
todos,
|
|
121
|
-
selectedTodos,
|
|
122
|
-
toggleTodoSelection,
|
|
123
|
-
confirmTodoSelection,
|
|
124
|
-
todoSearchQuery,
|
|
125
|
-
setTodoSearchQuery,
|
|
126
|
-
});
|
|
127
|
-
// Set initial content when provided (e.g., when rolling back to first message)
|
|
128
|
-
useEffect(() => {
|
|
129
|
-
if (initialContent) {
|
|
130
|
-
// Always do full restore to avoid duplicate placeholders
|
|
131
|
-
buffer.setText('');
|
|
132
|
-
const text = initialContent.text;
|
|
133
|
-
const images = initialContent.images || [];
|
|
134
|
-
if (images.length === 0) {
|
|
135
|
-
// No images, just set the text
|
|
136
|
-
if (text) {
|
|
137
|
-
buffer.insert(text);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
// Split text by image placeholders and reconstruct with actual images
|
|
142
|
-
// Placeholder format: [image #N]
|
|
143
|
-
const imagePlaceholderPattern = /\[image #\d+\]/g;
|
|
144
|
-
const parts = text.split(imagePlaceholderPattern);
|
|
145
|
-
// Interleave text parts with images
|
|
146
|
-
for (let i = 0; i < parts.length; i++) {
|
|
147
|
-
// Insert text part
|
|
148
|
-
const part = parts[i];
|
|
149
|
-
if (part) {
|
|
150
|
-
buffer.insert(part);
|
|
151
|
-
}
|
|
152
|
-
// Insert image after this text part (if exists)
|
|
153
|
-
if (i < images.length) {
|
|
154
|
-
const img = images[i];
|
|
155
|
-
if (img) {
|
|
156
|
-
// Extract base64 data from data URL if present
|
|
157
|
-
let base64Data = img.data;
|
|
158
|
-
if (base64Data.startsWith('data:')) {
|
|
159
|
-
const base64Index = base64Data.indexOf('base64,');
|
|
160
|
-
if (base64Index !== -1) {
|
|
161
|
-
base64Data = base64Data.substring(base64Index + 7);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
buffer.insertImage(base64Data, img.mimeType);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
triggerUpdate();
|
|
170
|
-
}
|
|
171
|
-
// Only run when initialContent changes
|
|
172
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
173
|
-
}, [initialContent]);
|
|
174
|
-
// Force full re-render when file picker visibility changes to prevent artifacts
|
|
175
|
-
useEffect(() => {
|
|
176
|
-
// Use a small delay to ensure the component tree has updated
|
|
177
|
-
const timer = setTimeout(() => {
|
|
178
|
-
forceUpdate();
|
|
179
|
-
}, 10);
|
|
180
|
-
return () => clearTimeout(timer);
|
|
181
|
-
}, [showFilePicker, forceUpdate]);
|
|
182
|
-
// Handle terminal width changes with debounce (like gemini-cli)
|
|
183
|
-
useEffect(() => {
|
|
184
|
-
// Skip on initial mount
|
|
185
|
-
if (prevTerminalWidthRef.current === terminalWidth) {
|
|
186
|
-
prevTerminalWidthRef.current = terminalWidth;
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
prevTerminalWidthRef.current = terminalWidth;
|
|
190
|
-
// Debounce the re-render to avoid flickering during resize
|
|
191
|
-
const timer = setTimeout(() => {
|
|
192
|
-
forceUpdate();
|
|
193
|
-
}, 100);
|
|
194
|
-
return () => clearTimeout(timer);
|
|
195
|
-
}, [terminalWidth, forceUpdate]);
|
|
196
|
-
// Notify parent of context percentage changes
|
|
197
|
-
const lastPercentageRef = useRef(0);
|
|
198
|
-
useEffect(() => {
|
|
199
|
-
if (contextUsage && onContextPercentageChange) {
|
|
200
|
-
const percentage = calculateContextPercentage(contextUsage);
|
|
201
|
-
// Only call callback if percentage has actually changed
|
|
202
|
-
if (percentage !== lastPercentageRef.current) {
|
|
203
|
-
lastPercentageRef.current = percentage;
|
|
204
|
-
onContextPercentageChange(percentage);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}, [contextUsage, onContextPercentageChange]);
|
|
208
|
-
// Render cursor based on focus state
|
|
209
|
-
const renderCursor = useCallback((char) => {
|
|
210
|
-
if (hasFocus) {
|
|
211
|
-
// Focused: solid block cursor (use inverted colors)
|
|
212
|
-
return (React.createElement(Text, { backgroundColor: theme.colors.menuNormal, color: theme.colors.background }, char));
|
|
213
|
-
}
|
|
214
|
-
else {
|
|
215
|
-
// Unfocused: no cursor, just render the character normally
|
|
216
|
-
return React.createElement(Text, null, char);
|
|
217
|
-
}
|
|
218
|
-
}, [hasFocus, theme]);
|
|
219
|
-
// Render content with cursor (treat all text including placeholders as plain text)
|
|
220
|
-
const renderContent = () => {
|
|
221
|
-
if (buffer.text.length > 0) {
|
|
222
|
-
// Use visual lines for proper wrapping and multi-line support
|
|
223
|
-
const visualLines = buffer.viewportVisualLines;
|
|
224
|
-
const [cursorRow, cursorCol] = buffer.visualCursor;
|
|
225
|
-
const renderedLines = [];
|
|
226
|
-
for (let i = 0; i < visualLines.length; i++) {
|
|
227
|
-
const line = visualLines[i] || '';
|
|
228
|
-
if (i === cursorRow) {
|
|
229
|
-
// This line contains the cursor
|
|
230
|
-
const beforeCursor = cpSlice(line, 0, cursorCol);
|
|
231
|
-
const atCursor = cpSlice(line, cursorCol, cursorCol + 1) || ' ';
|
|
232
|
-
const afterCursor = cpSlice(line, cursorCol + 1);
|
|
233
|
-
renderedLines.push(React.createElement(Box, { key: i, flexDirection: "row" },
|
|
234
|
-
React.createElement(Text, null, beforeCursor),
|
|
235
|
-
renderCursor(atCursor),
|
|
236
|
-
React.createElement(Text, null, afterCursor)));
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
// No cursor in this line
|
|
240
|
-
renderedLines.push(React.createElement(Text, { key: i }, line || ' '));
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
return React.createElement(Box, { flexDirection: "column" }, renderedLines);
|
|
244
|
-
}
|
|
245
|
-
else {
|
|
246
|
-
return (React.createElement(React.Fragment, null,
|
|
247
|
-
renderCursor(' '),
|
|
248
|
-
React.createElement(Text, { color: theme.colors.menuSecondary, dimColor: true }, disabled ? t.chatScreen.waitingForResponse : placeholder)));
|
|
249
|
-
}
|
|
250
|
-
};
|
|
251
|
-
return (React.createElement(Box, { flexDirection: "column", paddingX: 1, width: terminalWidth },
|
|
252
|
-
showHistoryMenu && (React.createElement(Box, { flexDirection: "column", marginBottom: 1, width: terminalWidth - 2 },
|
|
253
|
-
React.createElement(Box, { flexDirection: "column" }, (() => {
|
|
254
|
-
const userMessages = getUserMessages();
|
|
255
|
-
const maxVisibleItems = 5; // Number of message items to show (reduced for small terminals)
|
|
256
|
-
// Calculate scroll window to keep selected index visible
|
|
257
|
-
let startIndex = 0;
|
|
258
|
-
if (userMessages.length > maxVisibleItems) {
|
|
259
|
-
// Keep selected item in the middle of the view when possible
|
|
260
|
-
startIndex = Math.max(0, historySelectedIndex - Math.floor(maxVisibleItems / 2));
|
|
261
|
-
// Adjust if we're near the end
|
|
262
|
-
startIndex = Math.min(startIndex, userMessages.length - maxVisibleItems);
|
|
263
|
-
}
|
|
264
|
-
const endIndex = Math.min(userMessages.length, startIndex + maxVisibleItems);
|
|
265
|
-
const visibleMessages = userMessages.slice(startIndex, endIndex);
|
|
266
|
-
const hasMoreAbove = startIndex > 0;
|
|
267
|
-
const hasMoreBelow = endIndex < userMessages.length;
|
|
268
|
-
return (React.createElement(React.Fragment, null,
|
|
269
|
-
React.createElement(Box, { height: 1 }, hasMoreAbove ? (React.createElement(Text, { color: theme.colors.menuSecondary, dimColor: true }, t.chatScreen.moreAbove.replace('{count}', startIndex.toString()))) : (React.createElement(Text, null, " "))),
|
|
270
|
-
visibleMessages.map((message, displayIndex) => {
|
|
271
|
-
const actualIndex = startIndex + displayIndex;
|
|
272
|
-
// Ensure single line by removing all newlines and control characters
|
|
273
|
-
const singleLineLabel = message.label
|
|
274
|
-
.replace(/[\r\n\t\v\f\u0000-\u001F\u007F-\u009F]+/g, ' ')
|
|
275
|
-
.replace(/\s+/g, ' ')
|
|
276
|
-
.trim();
|
|
277
|
-
// Calculate available width for the message
|
|
278
|
-
const prefixWidth = 3; // "❯ " or " "
|
|
279
|
-
const maxLabelWidth = terminalWidth - 4 - prefixWidth;
|
|
280
|
-
const truncatedLabel = singleLineLabel.length > maxLabelWidth
|
|
281
|
-
? singleLineLabel.slice(0, maxLabelWidth - 3) + '...'
|
|
282
|
-
: singleLineLabel;
|
|
283
|
-
return (React.createElement(Box, { key: message.value, height: 1 },
|
|
284
|
-
React.createElement(Text, { color: actualIndex === historySelectedIndex
|
|
285
|
-
? theme.colors.menuSelected
|
|
286
|
-
: theme.colors.menuNormal, bold: true, wrap: "truncate" },
|
|
287
|
-
actualIndex === historySelectedIndex ? '❯ ' : ' ',
|
|
288
|
-
truncatedLabel)));
|
|
289
|
-
}),
|
|
290
|
-
React.createElement(Box, { height: 1 }, hasMoreBelow ? (React.createElement(Text, { color: theme.colors.menuSecondary, dimColor: true }, t.chatScreen.moreBelow.replace('{count}', (userMessages.length - endIndex).toString()))) : (React.createElement(Text, null, " ")))));
|
|
291
|
-
})()),
|
|
292
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
293
|
-
React.createElement(Text, { color: theme.colors.menuInfo, dimColor: true }, t.chatScreen.historyNavigateHint)))),
|
|
294
|
-
!showHistoryMenu && (React.createElement(React.Fragment, null,
|
|
295
|
-
React.createElement(Box, { flexDirection: "column", width: terminalWidth - 2 },
|
|
296
|
-
React.createElement(Text, { color: theme.colors.menuSecondary }, '─'.repeat(terminalWidth - 2)),
|
|
297
|
-
React.createElement(Box, { flexDirection: "row" },
|
|
298
|
-
React.createElement(Text, { color: theme.colors.menuInfo, bold: true },
|
|
299
|
-
"\u276F",
|
|
300
|
-
' '),
|
|
301
|
-
React.createElement(Box, { flexGrow: 1 }, renderContent())),
|
|
302
|
-
React.createElement(Text, { color: theme.colors.menuSecondary }, '─'.repeat(terminalWidth - 2))),
|
|
303
|
-
(showCommands && getFilteredCommands().length > 0) ||
|
|
304
|
-
showFilePicker ? (React.createElement(Box, { marginTop: 1 },
|
|
305
|
-
React.createElement(Text, null, showCommands && getFilteredCommands().length > 0
|
|
306
|
-
? t.chatScreen.typeToFilterCommands
|
|
307
|
-
: showFilePicker
|
|
308
|
-
? searchMode === 'content'
|
|
309
|
-
? t.chatScreen.contentSearchHint
|
|
310
|
-
: t.chatScreen.fileSearchHint
|
|
311
|
-
: ''))) : null,
|
|
312
|
-
React.createElement(CommandPanel, { commands: getFilteredCommands(), selectedIndex: commandSelectedIndex, query: buffer.getFullText().slice(1), visible: showCommands, isProcessing: commandPanelIsProcessing }),
|
|
313
|
-
React.createElement(Box, null,
|
|
314
|
-
React.createElement(FileList, { ref: fileListRef, query: fileQuery, selectedIndex: fileSelectedIndex, visible: showFilePicker, maxItems: 10, rootPath: process.cwd(), onFilteredCountChange: handleFilteredCountChange, searchMode: searchMode })),
|
|
315
|
-
React.createElement(AgentPickerPanel, { agents: getFilteredAgents(), selectedIndex: agentSelectedIndex, visible: showAgentPicker, maxHeight: 5 }),
|
|
316
|
-
React.createElement(TodoPickerPanel, { todos: todos, selectedIndex: todoSelectedIndex, selectedTodos: selectedTodos, visible: showTodoPicker, maxHeight: 5, isLoading: todoIsLoading, searchQuery: todoSearchQuery, totalCount: totalTodoCount }),
|
|
317
|
-
yoloMode && (React.createElement(Box, { marginTop: 1 },
|
|
318
|
-
React.createElement(Text, { color: theme.colors.warning, dimColor: true }, t.chatScreen.yoloModeActive))),
|
|
319
|
-
contextUsage && (React.createElement(Box, { marginTop: 1 },
|
|
320
|
-
React.createElement(Text, { color: theme.colors.menuSecondary, dimColor: true }, (() => {
|
|
321
|
-
// Determine which caching system is being used
|
|
322
|
-
const isAnthropic = (contextUsage.cacheCreationTokens || 0) > 0 ||
|
|
323
|
-
(contextUsage.cacheReadTokens || 0) > 0;
|
|
324
|
-
const isOpenAI = (contextUsage.cachedTokens || 0) > 0;
|
|
325
|
-
// Use the exported function for consistent calculation
|
|
326
|
-
const percentage = calculateContextPercentage(contextUsage);
|
|
327
|
-
// Calculate total tokens for display
|
|
328
|
-
const totalInputTokens = isAnthropic
|
|
329
|
-
? contextUsage.inputTokens +
|
|
330
|
-
(contextUsage.cacheCreationTokens || 0) +
|
|
331
|
-
(contextUsage.cacheReadTokens || 0)
|
|
332
|
-
: contextUsage.inputTokens;
|
|
333
|
-
let color;
|
|
334
|
-
if (percentage < 50)
|
|
335
|
-
color = theme.colors.success;
|
|
336
|
-
else if (percentage < 75)
|
|
337
|
-
color = theme.colors.warning;
|
|
338
|
-
else if (percentage < 90)
|
|
339
|
-
color = theme.colors.warning;
|
|
340
|
-
else
|
|
341
|
-
color = theme.colors.error;
|
|
342
|
-
const formatNumber = (num) => {
|
|
343
|
-
if (num >= 1000)
|
|
344
|
-
return `${(num / 1000).toFixed(1)}k`;
|
|
345
|
-
return num.toString();
|
|
346
|
-
};
|
|
347
|
-
const hasCacheMetrics = isAnthropic || isOpenAI;
|
|
348
|
-
return (React.createElement(React.Fragment, null,
|
|
349
|
-
React.createElement(Text, { color: color },
|
|
350
|
-
percentage.toFixed(1),
|
|
351
|
-
"%"),
|
|
352
|
-
React.createElement(Text, null, " \u00B7 "),
|
|
353
|
-
React.createElement(Text, { color: color }, formatNumber(totalInputTokens)),
|
|
354
|
-
React.createElement(Text, null, t.chatScreen.tokens),
|
|
355
|
-
hasCacheMetrics && (React.createElement(React.Fragment, null,
|
|
356
|
-
React.createElement(Text, null, " \u00B7 "),
|
|
357
|
-
isAnthropic && (React.createElement(React.Fragment, null,
|
|
358
|
-
(contextUsage.cacheReadTokens || 0) > 0 && (React.createElement(React.Fragment, null,
|
|
359
|
-
React.createElement(Text, { color: theme.colors.menuInfo },
|
|
360
|
-
"\u21AF",
|
|
361
|
-
' ',
|
|
362
|
-
formatNumber(contextUsage.cacheReadTokens || 0),
|
|
363
|
-
' ',
|
|
364
|
-
t.chatScreen.cached))),
|
|
365
|
-
(contextUsage.cacheCreationTokens || 0) > 0 && (React.createElement(React.Fragment, null,
|
|
366
|
-
(contextUsage.cacheReadTokens || 0) > 0 && (React.createElement(Text, null, " \u00B7 ")),
|
|
367
|
-
React.createElement(Text, { color: theme.colors.warning },
|
|
368
|
-
"\u25C6",
|
|
369
|
-
' ',
|
|
370
|
-
formatNumber(contextUsage.cacheCreationTokens || 0),
|
|
371
|
-
' ',
|
|
372
|
-
t.chatScreen.newCache))))),
|
|
373
|
-
isOpenAI && (React.createElement(Text, { color: theme.colors.menuInfo },
|
|
374
|
-
"\u21AF ",
|
|
375
|
-
formatNumber(contextUsage.cachedTokens || 0),
|
|
376
|
-
' ',
|
|
377
|
-
t.chatScreen.cached))))));
|
|
378
|
-
})())))))));
|
|
379
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
interface Command {
|
|
3
|
-
name: string;
|
|
4
|
-
description: string;
|
|
5
|
-
}
|
|
6
|
-
interface Props {
|
|
7
|
-
commands: Command[];
|
|
8
|
-
selectedIndex: number;
|
|
9
|
-
query: string;
|
|
10
|
-
visible: boolean;
|
|
11
|
-
maxHeight?: number;
|
|
12
|
-
isProcessing?: boolean;
|
|
13
|
-
}
|
|
14
|
-
declare const CommandPanel: React.MemoExoticComponent<({ commands, selectedIndex, visible, maxHeight, isProcessing, }: Props) => React.JSX.Element | null>;
|
|
15
|
-
export default CommandPanel;
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import React, { memo, useMemo } from 'react';
|
|
2
|
-
import { Box, Text } from 'ink';
|
|
3
|
-
import { Alert } from '@inkjs/ui';
|
|
4
|
-
import { useI18n } from '../../i18n/index.js';
|
|
5
|
-
import { useTheme } from '../contexts/ThemeContext.js';
|
|
6
|
-
const CommandPanel = memo(({ commands, selectedIndex, visible, maxHeight, isProcessing = false, }) => {
|
|
7
|
-
const { t } = useI18n();
|
|
8
|
-
const { theme } = useTheme();
|
|
9
|
-
// Fixed maximum display items to prevent rendering issues
|
|
10
|
-
const MAX_DISPLAY_ITEMS = 5;
|
|
11
|
-
const effectiveMaxItems = maxHeight
|
|
12
|
-
? Math.min(maxHeight, MAX_DISPLAY_ITEMS)
|
|
13
|
-
: MAX_DISPLAY_ITEMS;
|
|
14
|
-
// Limit displayed commands
|
|
15
|
-
const displayedCommands = useMemo(() => {
|
|
16
|
-
if (commands.length <= effectiveMaxItems) {
|
|
17
|
-
return commands;
|
|
18
|
-
}
|
|
19
|
-
// Show commands around the selected index
|
|
20
|
-
const halfWindow = Math.floor(effectiveMaxItems / 2);
|
|
21
|
-
let startIndex = Math.max(0, selectedIndex - halfWindow);
|
|
22
|
-
let endIndex = Math.min(commands.length, startIndex + effectiveMaxItems);
|
|
23
|
-
// Adjust if we're near the end
|
|
24
|
-
if (endIndex - startIndex < effectiveMaxItems) {
|
|
25
|
-
startIndex = Math.max(0, endIndex - effectiveMaxItems);
|
|
26
|
-
}
|
|
27
|
-
return commands.slice(startIndex, endIndex);
|
|
28
|
-
}, [commands, selectedIndex, effectiveMaxItems]);
|
|
29
|
-
// Calculate actual selected index in the displayed subset
|
|
30
|
-
const displayedSelectedIndex = useMemo(() => {
|
|
31
|
-
return displayedCommands.findIndex(cmd => {
|
|
32
|
-
const originalIndex = commands.indexOf(cmd);
|
|
33
|
-
return originalIndex === selectedIndex;
|
|
34
|
-
});
|
|
35
|
-
}, [displayedCommands, commands, selectedIndex]);
|
|
36
|
-
// Don't show panel if not visible
|
|
37
|
-
if (!visible) {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
// Show processing message if conversation is in progress
|
|
41
|
-
if (isProcessing) {
|
|
42
|
-
return (React.createElement(Box, { flexDirection: "column" },
|
|
43
|
-
React.createElement(Box, { width: "100%" },
|
|
44
|
-
React.createElement(Box, { flexDirection: "column", width: "100%" },
|
|
45
|
-
React.createElement(Box, null,
|
|
46
|
-
React.createElement(Text, { color: theme.colors.warning, bold: true }, t.commandPanel.title)),
|
|
47
|
-
React.createElement(Box, { marginTop: 1 },
|
|
48
|
-
React.createElement(Alert, { variant: "info" }, t.commandPanel.processingMessage))))));
|
|
49
|
-
}
|
|
50
|
-
// Don't show panel if no commands found
|
|
51
|
-
if (commands.length === 0) {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
return (React.createElement(Box, { flexDirection: "column" },
|
|
55
|
-
React.createElement(Box, { width: "100%" },
|
|
56
|
-
React.createElement(Box, { flexDirection: "column", width: "100%" },
|
|
57
|
-
React.createElement(Box, null,
|
|
58
|
-
React.createElement(Text, { color: theme.colors.warning, bold: true },
|
|
59
|
-
t.commandPanel.availableCommands,
|
|
60
|
-
' ',
|
|
61
|
-
commands.length > effectiveMaxItems &&
|
|
62
|
-
`(${selectedIndex + 1}/${commands.length})`)),
|
|
63
|
-
displayedCommands.map((command, index) => (React.createElement(Box, { key: command.name, flexDirection: "column", width: "100%" },
|
|
64
|
-
React.createElement(Text, { color: index === displayedSelectedIndex ? theme.colors.success : theme.colors.menuSecondary, bold: true },
|
|
65
|
-
index === displayedSelectedIndex ? '❯ ' : ' ',
|
|
66
|
-
"/",
|
|
67
|
-
command.name),
|
|
68
|
-
React.createElement(Box, { marginLeft: 3 },
|
|
69
|
-
React.createElement(Text, { color: index === displayedSelectedIndex ? theme.colors.success : theme.colors.menuSecondary, dimColor: true },
|
|
70
|
-
"\u2514\u2500 ",
|
|
71
|
-
command.description))))),
|
|
72
|
-
commands.length > effectiveMaxItems && (React.createElement(Box, { marginTop: 1 },
|
|
73
|
-
React.createElement(Text, { color: theme.colors.menuSecondary, dimColor: true },
|
|
74
|
-
t.commandPanel.scrollHint,
|
|
75
|
-
" \u00B7",
|
|
76
|
-
' ',
|
|
77
|
-
t.commandPanel.moreHidden.replace('{count}', (commands.length - effectiveMaxItems).toString()))))))));
|
|
78
|
-
});
|
|
79
|
-
CommandPanel.displayName = 'CommandPanel';
|
|
80
|
-
export default CommandPanel;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
interface Props {
|
|
3
|
-
oldContent?: string;
|
|
4
|
-
newContent: string;
|
|
5
|
-
filename?: string;
|
|
6
|
-
completeOldContent?: string;
|
|
7
|
-
completeNewContent?: string;
|
|
8
|
-
startLineNumber?: number;
|
|
9
|
-
}
|
|
10
|
-
export default function DiffViewer({ oldContent, newContent, filename, completeOldContent, completeNewContent, startLineNumber, }: Props): React.JSX.Element | null;
|
|
11
|
-
export {};
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import React, { useMemo } from 'react';
|
|
2
|
-
import { Box, Text } from 'ink';
|
|
3
|
-
import * as Diff from 'diff';
|
|
4
|
-
import { useTheme } from '../contexts/ThemeContext.js';
|
|
5
|
-
// Helper function to strip line numbers from content (format: "123→content")
|
|
6
|
-
function stripLineNumbers(content) {
|
|
7
|
-
return content
|
|
8
|
-
.split('\n')
|
|
9
|
-
.map(line => {
|
|
10
|
-
// Match pattern: digits + → + content
|
|
11
|
-
const match = line.match(/^\s*\d+→(.*)$/);
|
|
12
|
-
return match ? match[1] : line;
|
|
13
|
-
})
|
|
14
|
-
.join('\n');
|
|
15
|
-
}
|
|
16
|
-
export default function DiffViewer({ oldContent = '', newContent, filename, completeOldContent, completeNewContent, startLineNumber = 1, }) {
|
|
17
|
-
const { theme } = useTheme();
|
|
18
|
-
// If complete file contents are provided, use them for intelligent diff
|
|
19
|
-
const useCompleteContent = completeOldContent && completeNewContent;
|
|
20
|
-
const diffOldContent = useCompleteContent
|
|
21
|
-
? completeOldContent
|
|
22
|
-
: stripLineNumbers(oldContent);
|
|
23
|
-
const diffNewContent = useCompleteContent
|
|
24
|
-
? completeNewContent
|
|
25
|
-
: stripLineNumbers(newContent);
|
|
26
|
-
// If no old content, show as new file creation
|
|
27
|
-
const isNewFile = !diffOldContent || diffOldContent.trim() === '';
|
|
28
|
-
// Memoize new file rendering to avoid re-splitting lines on every render
|
|
29
|
-
const newFileContent = useMemo(() => {
|
|
30
|
-
if (!isNewFile)
|
|
31
|
-
return null;
|
|
32
|
-
const allLines = diffNewContent.split('\n');
|
|
33
|
-
return (React.createElement(Box, { flexDirection: "column" },
|
|
34
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
35
|
-
React.createElement(Text, { bold: true, color: "green" }, "[New File]"),
|
|
36
|
-
filename && React.createElement(Text, { color: "cyan" },
|
|
37
|
-
" ",
|
|
38
|
-
filename)),
|
|
39
|
-
React.createElement(Box, { flexDirection: "column" }, allLines.map((line, index) => (React.createElement(Text, { key: index, color: "white", backgroundColor: theme.colors.diffAdded },
|
|
40
|
-
"+ ",
|
|
41
|
-
line))))));
|
|
42
|
-
}, [isNewFile, diffNewContent, filename, theme.colors.text, theme.colors.diffAdded]);
|
|
43
|
-
if (isNewFile) {
|
|
44
|
-
return newFileContent;
|
|
45
|
-
}
|
|
46
|
-
// Memoize expensive diff calculation - only recompute when content changes
|
|
47
|
-
const hunks = useMemo(() => {
|
|
48
|
-
// Generate line-by-line diff
|
|
49
|
-
const diffResult = Diff.diffLines(diffOldContent, diffNewContent);
|
|
50
|
-
const allChanges = [];
|
|
51
|
-
let oldLineNum = startLineNumber;
|
|
52
|
-
let newLineNum = startLineNumber;
|
|
53
|
-
diffResult.forEach(part => {
|
|
54
|
-
const lines = part.value.replace(/\n$/, '').split('\n');
|
|
55
|
-
lines.forEach(line => {
|
|
56
|
-
if (part.added) {
|
|
57
|
-
allChanges.push({
|
|
58
|
-
type: 'added',
|
|
59
|
-
content: line,
|
|
60
|
-
oldLineNum: null,
|
|
61
|
-
newLineNum: newLineNum++,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
else if (part.removed) {
|
|
65
|
-
allChanges.push({
|
|
66
|
-
type: 'removed',
|
|
67
|
-
content: line,
|
|
68
|
-
oldLineNum: oldLineNum++,
|
|
69
|
-
newLineNum: null,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
allChanges.push({
|
|
74
|
-
type: 'unchanged',
|
|
75
|
-
content: line,
|
|
76
|
-
oldLineNum: oldLineNum++,
|
|
77
|
-
newLineNum: newLineNum++,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
// Find diff hunks (groups of changes with context)
|
|
83
|
-
const computedHunks = [];
|
|
84
|
-
const contextLines = 3; // Number of context lines before and after changes
|
|
85
|
-
for (let i = 0; i < allChanges.length; i++) {
|
|
86
|
-
const change = allChanges[i];
|
|
87
|
-
if (change?.type !== 'unchanged') {
|
|
88
|
-
// Found a change, create a hunk
|
|
89
|
-
const hunkStart = Math.max(0, i - contextLines);
|
|
90
|
-
let hunkEnd = i;
|
|
91
|
-
// Extend the hunk to include all consecutive changes
|
|
92
|
-
while (hunkEnd < allChanges.length - 1) {
|
|
93
|
-
const nextChange = allChanges[hunkEnd + 1];
|
|
94
|
-
if (!nextChange)
|
|
95
|
-
break;
|
|
96
|
-
// If next line is a change, extend the hunk
|
|
97
|
-
if (nextChange.type !== 'unchanged') {
|
|
98
|
-
hunkEnd++;
|
|
99
|
-
continue;
|
|
100
|
-
}
|
|
101
|
-
// If there are more changes within context distance, extend the hunk
|
|
102
|
-
let hasMoreChanges = false;
|
|
103
|
-
for (let j = hunkEnd + 1; j < Math.min(allChanges.length, hunkEnd + 1 + contextLines * 2); j++) {
|
|
104
|
-
if (allChanges[j]?.type !== 'unchanged') {
|
|
105
|
-
hasMoreChanges = true;
|
|
106
|
-
break;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
if (hasMoreChanges) {
|
|
110
|
-
hunkEnd++;
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
break;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
// Add context lines after the hunk
|
|
117
|
-
hunkEnd = Math.min(allChanges.length - 1, hunkEnd + contextLines);
|
|
118
|
-
// Extract the hunk
|
|
119
|
-
const hunkChanges = allChanges.slice(hunkStart, hunkEnd + 1);
|
|
120
|
-
const firstChange = hunkChanges[0];
|
|
121
|
-
const lastChange = hunkChanges[hunkChanges.length - 1];
|
|
122
|
-
if (firstChange && lastChange) {
|
|
123
|
-
computedHunks.push({
|
|
124
|
-
startLine: firstChange.oldLineNum || firstChange.newLineNum || 1,
|
|
125
|
-
endLine: lastChange.oldLineNum || lastChange.newLineNum || 1,
|
|
126
|
-
changes: hunkChanges,
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
// Skip to the end of this hunk
|
|
130
|
-
i = hunkEnd;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return computedHunks;
|
|
134
|
-
}, [diffOldContent, diffNewContent, startLineNumber]);
|
|
135
|
-
return (React.createElement(Box, { flexDirection: "column" },
|
|
136
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
137
|
-
React.createElement(Text, { bold: true, color: "yellow" }, "[File Modified]"),
|
|
138
|
-
filename && React.createElement(Text, { color: "cyan" },
|
|
139
|
-
" ",
|
|
140
|
-
filename)),
|
|
141
|
-
React.createElement(Box, { flexDirection: "column" },
|
|
142
|
-
hunks.map((hunk, hunkIndex) => (React.createElement(Box, { key: hunkIndex, flexDirection: "column", marginBottom: 1 },
|
|
143
|
-
React.createElement(Text, { color: "cyan", dimColor: true },
|
|
144
|
-
"@@ Lines ",
|
|
145
|
-
hunk.startLine,
|
|
146
|
-
"-",
|
|
147
|
-
hunk.endLine,
|
|
148
|
-
" @@"),
|
|
149
|
-
hunk.changes.map((change, changeIndex) => {
|
|
150
|
-
// Calculate line number to display
|
|
151
|
-
const lineNum = change.type === 'added' ? change.newLineNum : change.oldLineNum;
|
|
152
|
-
const lineNumStr = lineNum
|
|
153
|
-
? String(lineNum).padStart(4, ' ')
|
|
154
|
-
: ' ';
|
|
155
|
-
if (change.type === 'added') {
|
|
156
|
-
return (React.createElement(Text, { key: changeIndex, color: "white", backgroundColor: theme.colors.diffAdded },
|
|
157
|
-
lineNumStr,
|
|
158
|
-
" + ",
|
|
159
|
-
change.content));
|
|
160
|
-
}
|
|
161
|
-
if (change.type === 'removed') {
|
|
162
|
-
return (React.createElement(Text, { key: changeIndex, color: "white", backgroundColor: theme.colors.diffRemoved },
|
|
163
|
-
lineNumStr,
|
|
164
|
-
" - ",
|
|
165
|
-
change.content));
|
|
166
|
-
}
|
|
167
|
-
// Unchanged lines (context)
|
|
168
|
-
return (React.createElement(Text, { key: changeIndex, dimColor: true },
|
|
169
|
-
lineNumStr,
|
|
170
|
-
" ",
|
|
171
|
-
change.content));
|
|
172
|
-
})))),
|
|
173
|
-
hunks.length > 1 && (React.createElement(Box, { marginTop: 1 },
|
|
174
|
-
React.createElement(Text, { color: "gray", dimColor: true },
|
|
175
|
-
"Total: ",
|
|
176
|
-
hunks.length,
|
|
177
|
-
" change region(s)"))))));
|
|
178
|
-
}
|