snow-ai 0.3.36 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/codebaseIndexAgent.js +1 -0
- package/dist/agents/codebaseReviewAgent.d.ts +61 -0
- package/dist/agents/codebaseReviewAgent.js +301 -0
- package/dist/agents/promptOptimizeAgent.d.ts +54 -0
- package/dist/agents/promptOptimizeAgent.js +268 -0
- package/dist/api/anthropic.js +1 -0
- package/dist/api/chat.js +1 -0
- package/dist/api/embedding.js +1 -0
- package/dist/api/gemini.js +2 -1
- package/dist/api/responses.js +1 -0
- package/dist/api/systemPrompt.d.ts +1 -5
- package/dist/api/systemPrompt.js +168 -100
- package/dist/app.js +14 -6
- package/dist/cli.js +1 -1
- package/dist/hooks/useCommandPanel.js +48 -46
- package/dist/hooks/useConversation.d.ts +2 -1
- package/dist/hooks/useConversation.js +116 -30
- package/dist/hooks/useGlobalExit.js +4 -2
- package/dist/hooks/useStreamingState.d.ts +9 -0
- package/dist/hooks/useStreamingState.js +3 -0
- package/dist/i18n/I18nContext.d.ts +14 -0
- package/dist/i18n/I18nContext.js +24 -0
- package/dist/i18n/index.d.ts +3 -0
- package/dist/i18n/index.js +2 -0
- package/dist/i18n/lang/en.d.ts +2 -0
- package/dist/i18n/lang/en.js +483 -0
- package/dist/i18n/lang/es.d.ts +2 -0
- package/dist/i18n/lang/es.js +483 -0
- package/dist/i18n/lang/ja.d.ts +2 -0
- package/dist/i18n/lang/ja.js +483 -0
- package/dist/i18n/lang/ko.d.ts +2 -0
- package/dist/i18n/lang/ko.js +483 -0
- package/dist/i18n/lang/zh-TW.d.ts +2 -0
- package/dist/i18n/lang/zh-TW.js +483 -0
- package/dist/i18n/lang/zh.d.ts +2 -0
- package/dist/i18n/lang/zh.js +483 -0
- package/dist/i18n/translations.d.ts +2 -0
- package/dist/i18n/translations.js +14 -0
- package/dist/i18n/types.d.ts +459 -0
- package/dist/i18n/types.js +1 -0
- package/dist/mcp/aceCodeSearch.d.ts +17 -48
- package/dist/mcp/aceCodeSearch.js +24 -56
- package/dist/mcp/bash.js +8 -1
- package/dist/mcp/codebaseSearch.d.ts +1 -1
- package/dist/mcp/codebaseSearch.js +159 -30
- package/dist/mcp/filesystem.d.ts +3 -80
- package/dist/mcp/filesystem.js +23 -103
- package/dist/mcp/subagent.d.ts +2 -1
- package/dist/mcp/subagent.js +54 -5
- package/dist/ui/components/ChatInput.js +22 -25
- package/dist/ui/components/CommandPanel.d.ts +1 -1
- package/dist/ui/components/CommandPanel.js +20 -13
- package/dist/ui/components/DiffViewer.d.ts +1 -1
- package/dist/ui/components/DiffViewer.js +101 -91
- package/dist/ui/components/FileList.js +22 -11
- package/dist/ui/components/HelpPanel.js +47 -21
- package/dist/ui/components/Menu.js +6 -2
- package/dist/ui/components/MessageList.d.ts +6 -0
- package/dist/ui/components/MessageList.js +1 -1
- package/dist/ui/components/ToolConfirmation.d.ts +4 -1
- package/dist/ui/components/ToolConfirmation.js +28 -2
- package/dist/ui/components/ToolResultPreview.d.ts +2 -1
- package/dist/ui/components/ToolResultPreview.js +41 -25
- package/dist/ui/pages/ChatScreen.js +177 -56
- package/dist/ui/pages/CodeBaseConfigScreen.js +54 -30
- package/dist/ui/pages/ConfigScreen.js +138 -98
- package/dist/ui/pages/CustomHeadersScreen.js +75 -69
- package/dist/ui/pages/LanguageSettingsScreen.d.ts +7 -0
- package/dist/ui/pages/LanguageSettingsScreen.js +89 -0
- package/dist/ui/pages/ProxyConfigScreen.js +27 -23
- package/dist/ui/pages/SensitiveCommandConfigScreen.js +32 -25
- package/dist/ui/pages/SubAgentConfigScreen.js +88 -75
- package/dist/ui/pages/SystemPromptConfigScreen.js +31 -26
- package/dist/ui/pages/WelcomeScreen.js +40 -26
- package/dist/utils/apiConfig.d.ts +2 -0
- package/dist/utils/codebaseConfig.d.ts +1 -5
- package/dist/utils/codebaseConfig.js +2 -10
- package/dist/utils/codebaseSearchEvents.d.ts +16 -0
- package/dist/utils/codebaseSearchEvents.js +13 -0
- package/dist/utils/commands/agent.js +2 -2
- package/dist/utils/commands/init.js +1 -1
- package/dist/utils/configManager.js +26 -5
- package/dist/utils/contextCompressor.js +1 -1
- package/dist/utils/languageConfig.d.ts +21 -0
- package/dist/utils/languageConfig.js +61 -0
- package/dist/utils/mcpToolsManager.js +0 -9
- package/dist/utils/notebookManager.js +11 -4
- package/dist/utils/sessionConverter.js +13 -3
- package/dist/utils/sessionManager.d.ts +1 -0
- package/dist/utils/subAgentConfig.d.ts +10 -5
- package/dist/utils/subAgentConfig.js +112 -19
- package/dist/utils/subAgentExecutor.d.ts +9 -1
- package/dist/utils/subAgentExecutor.js +122 -9
- package/dist/utils/toolExecutor.d.ts +2 -1
- package/dist/utils/toolExecutor.js +1 -2
- package/dist/utils/usageLogger.js +18 -3
- package/package.json +2 -1
|
@@ -4,6 +4,7 @@ import TextInput from 'ink-text-input';
|
|
|
4
4
|
import { Alert, Spinner } from '@inkjs/ui';
|
|
5
5
|
import { getMCPServicesInfo } from '../../utils/mcpToolsManager.js';
|
|
6
6
|
import { createSubAgent, updateSubAgent, getSubAgent, validateSubAgent, } from '../../utils/subAgentConfig.js';
|
|
7
|
+
import { useI18n } from '../../i18n/index.js';
|
|
7
8
|
// Focus event handling - prevent terminal focus events from appearing as input
|
|
8
9
|
const focusEventTokenRegex = /(?:\x1b)?\[[0-9;]*[IO]/g;
|
|
9
10
|
const isFocusEventInput = (value) => {
|
|
@@ -37,59 +38,8 @@ const stripFocusArtifacts = (value) => {
|
|
|
37
38
|
.replace(/\[[0-9;]*[IO]/g, '')
|
|
38
39
|
.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '');
|
|
39
40
|
};
|
|
40
|
-
const toolCategories = [
|
|
41
|
-
{
|
|
42
|
-
name: 'Filesystem Tools',
|
|
43
|
-
tools: [
|
|
44
|
-
'filesystem-read',
|
|
45
|
-
'filesystem-create',
|
|
46
|
-
'filesystem-edit',
|
|
47
|
-
'filesystem-edit_search',
|
|
48
|
-
'filesystem-delete',
|
|
49
|
-
'filesystem-list',
|
|
50
|
-
],
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
name: 'ACE Code Search Tools',
|
|
54
|
-
tools: [
|
|
55
|
-
'ace-search_symbols',
|
|
56
|
-
'ace-find_definition',
|
|
57
|
-
'ace-find_references',
|
|
58
|
-
'ace-semantic_search',
|
|
59
|
-
'ace-text_search',
|
|
60
|
-
'ace-file_outline',
|
|
61
|
-
'ace-index_stats',
|
|
62
|
-
'ace-clear_cache',
|
|
63
|
-
],
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
name: 'Codebase Search Tools',
|
|
67
|
-
tools: ['codebase-search'],
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
name: 'Terminal Tools',
|
|
71
|
-
tools: ['terminal-execute'],
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
name: 'TODO Management Tools',
|
|
75
|
-
tools: [
|
|
76
|
-
'todo-create',
|
|
77
|
-
'todo-get',
|
|
78
|
-
'todo-update',
|
|
79
|
-
'todo-add',
|
|
80
|
-
'todo-delete',
|
|
81
|
-
],
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
name: 'Web Search Tools',
|
|
85
|
-
tools: ['websearch-search', 'websearch-fetch'],
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
name: 'IDE Diagnostics Tools',
|
|
89
|
-
tools: ['ide-get_diagnostics'],
|
|
90
|
-
},
|
|
91
|
-
];
|
|
92
41
|
export default function SubAgentConfigScreen({ onBack, onSave, inlineMode = false, agentId, }) {
|
|
42
|
+
const { t } = useI18n();
|
|
93
43
|
const [agentName, setAgentName] = useState('');
|
|
94
44
|
const [description, setDescription] = useState('');
|
|
95
45
|
const [role, setRole] = useState('');
|
|
@@ -103,6 +53,56 @@ export default function SubAgentConfigScreen({ onBack, onSave, inlineMode = fals
|
|
|
103
53
|
const [mcpServices, setMcpServices] = useState([]);
|
|
104
54
|
const [loadError, setLoadError] = useState(null);
|
|
105
55
|
const isEditMode = !!agentId;
|
|
56
|
+
// Tool categories with translations
|
|
57
|
+
const toolCategories = [
|
|
58
|
+
{
|
|
59
|
+
name: t.subAgentConfig.filesystemTools,
|
|
60
|
+
tools: [
|
|
61
|
+
'filesystem-read',
|
|
62
|
+
'filesystem-create',
|
|
63
|
+
'filesystem-edit',
|
|
64
|
+
'filesystem-edit_search',
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: t.subAgentConfig.aceTools,
|
|
69
|
+
tools: [
|
|
70
|
+
'ace-find_definition',
|
|
71
|
+
'ace-find_references',
|
|
72
|
+
'ace-semantic_search',
|
|
73
|
+
'ace-text_search',
|
|
74
|
+
'ace-file_outline',
|
|
75
|
+
'ace-index_stats',
|
|
76
|
+
'ace-clear_cache',
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: t.subAgentConfig.codebaseTools,
|
|
81
|
+
tools: ['codebase-search'],
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: t.subAgentConfig.terminalTools,
|
|
85
|
+
tools: ['terminal-execute'],
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: t.subAgentConfig.todoTools,
|
|
89
|
+
tools: [
|
|
90
|
+
'todo-create',
|
|
91
|
+
'todo-get',
|
|
92
|
+
'todo-update',
|
|
93
|
+
'todo-add',
|
|
94
|
+
'todo-delete',
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: t.subAgentConfig.webSearchTools,
|
|
99
|
+
tools: ['websearch-search', 'websearch-fetch'],
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: t.subAgentConfig.ideTools,
|
|
103
|
+
tools: ['ide-get_diagnostics'],
|
|
104
|
+
},
|
|
105
|
+
];
|
|
106
106
|
// Load existing agent data in edit mode
|
|
107
107
|
useEffect(() => {
|
|
108
108
|
if (agentId) {
|
|
@@ -142,13 +142,13 @@ export default function SubAgentConfigScreen({ onBack, onSave, inlineMode = fals
|
|
|
142
142
|
for (const service of mcpServices) {
|
|
143
143
|
if (!service.isBuiltIn && service.connected && service.tools.length > 0) {
|
|
144
144
|
categories.push({
|
|
145
|
-
name: `${service.serviceName}
|
|
145
|
+
name: `${service.serviceName} ${t.subAgentConfig.categoryMCP}`,
|
|
146
146
|
tools: service.tools.map(t => t.name),
|
|
147
147
|
});
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
return categories;
|
|
151
|
-
}, [mcpServices]);
|
|
151
|
+
}, [mcpServices, toolCategories, t]);
|
|
152
152
|
// Get all available tools
|
|
153
153
|
const allTools = useMemo(() => allToolCategories.flatMap(cat => cat.tools), [allToolCategories]);
|
|
154
154
|
const handleToggleTool = useCallback((tool) => {
|
|
@@ -204,7 +204,7 @@ export default function SubAgentConfigScreen({ onBack, onSave, inlineMode = fals
|
|
|
204
204
|
tools: Array.from(selectedTools),
|
|
205
205
|
});
|
|
206
206
|
if (errors.length > 0) {
|
|
207
|
-
setSaveError(errors[0] ||
|
|
207
|
+
setSaveError(errors[0] || t.subAgentConfig.validationFailed);
|
|
208
208
|
return;
|
|
209
209
|
}
|
|
210
210
|
try {
|
|
@@ -228,7 +228,7 @@ export default function SubAgentConfigScreen({ onBack, onSave, inlineMode = fals
|
|
|
228
228
|
}, 1500);
|
|
229
229
|
}
|
|
230
230
|
catch (error) {
|
|
231
|
-
setSaveError(error instanceof Error ? error.message :
|
|
231
|
+
setSaveError(error instanceof Error ? error.message : t.subAgentConfig.saveError);
|
|
232
232
|
}
|
|
233
233
|
}, [
|
|
234
234
|
agentName,
|
|
@@ -238,6 +238,7 @@ export default function SubAgentConfigScreen({ onBack, onSave, inlineMode = fals
|
|
|
238
238
|
onSave,
|
|
239
239
|
isEditMode,
|
|
240
240
|
agentId,
|
|
241
|
+
t,
|
|
241
242
|
]);
|
|
242
243
|
useInput((rawInput, key) => {
|
|
243
244
|
const input = stripFocusArtifacts(rawInput);
|
|
@@ -351,12 +352,13 @@ export default function SubAgentConfigScreen({ onBack, onSave, inlineMode = fals
|
|
|
351
352
|
});
|
|
352
353
|
const renderToolSelection = () => {
|
|
353
354
|
return (React.createElement(Box, { flexDirection: "column" },
|
|
354
|
-
React.createElement(Text, { bold: true, color: "cyan" },
|
|
355
|
+
React.createElement(Text, { bold: true, color: "cyan" }, t.subAgentConfig.toolSelection),
|
|
355
356
|
isLoadingMCP && (React.createElement(Box, null,
|
|
356
|
-
React.createElement(Spinner, { label:
|
|
357
|
+
React.createElement(Spinner, { label: t.subAgentConfig.loadingMCP }))),
|
|
357
358
|
loadError && (React.createElement(Box, null,
|
|
358
359
|
React.createElement(Text, { color: "yellow" },
|
|
359
|
-
|
|
360
|
+
t.subAgentConfig.mcpLoadError,
|
|
361
|
+
" ",
|
|
360
362
|
loadError))),
|
|
361
363
|
allToolCategories.map((category, catIndex) => {
|
|
362
364
|
const isCurrent = catIndex === selectedCategoryIndex;
|
|
@@ -382,39 +384,50 @@ export default function SubAgentConfigScreen({ onBack, onSave, inlineMode = fals
|
|
|
382
384
|
})))));
|
|
383
385
|
}),
|
|
384
386
|
React.createElement(Text, { color: "gray", dimColor: true },
|
|
385
|
-
|
|
387
|
+
t.subAgentConfig.selectedTools,
|
|
388
|
+
" ",
|
|
386
389
|
selectedTools.size,
|
|
387
|
-
" /
|
|
390
|
+
" /",
|
|
391
|
+
' ',
|
|
388
392
|
allTools.length,
|
|
389
|
-
"
|
|
393
|
+
" ",
|
|
394
|
+
t.subAgentConfig.toolsCount)));
|
|
390
395
|
};
|
|
391
396
|
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
392
397
|
!inlineMode && (React.createElement(Box, { marginBottom: 1 },
|
|
393
398
|
React.createElement(Text, { bold: true, color: "cyan" },
|
|
394
|
-
"\u2746
|
|
395
|
-
|
|
396
|
-
|
|
399
|
+
"\u2746",
|
|
400
|
+
' ',
|
|
401
|
+
isEditMode
|
|
402
|
+
? t.subAgentConfig.titleEdit
|
|
403
|
+
: t.subAgentConfig.titleNew,
|
|
404
|
+
' ',
|
|
405
|
+
t.subAgentConfig.title))),
|
|
397
406
|
showSuccess && (React.createElement(Box, { marginBottom: 1 },
|
|
398
407
|
React.createElement(Alert, { variant: "success" },
|
|
399
|
-
"Sub-agent
|
|
400
|
-
|
|
401
|
-
|
|
408
|
+
"Sub-agent",
|
|
409
|
+
' ',
|
|
410
|
+
isEditMode
|
|
411
|
+
? t.subAgentConfig.saveSuccessEdit
|
|
412
|
+
: t.subAgentConfig.saveSuccessCreate,
|
|
413
|
+
' ',
|
|
414
|
+
"successfully!"))),
|
|
402
415
|
saveError && (React.createElement(Box, { marginBottom: 1 },
|
|
403
416
|
React.createElement(Alert, { variant: "error" }, saveError))),
|
|
404
417
|
React.createElement(Box, { flexDirection: "column" },
|
|
405
418
|
React.createElement(Box, { flexDirection: "column" },
|
|
406
|
-
React.createElement(Text, { bold: true, color: currentField === 'name' ? 'green' : 'white' },
|
|
419
|
+
React.createElement(Text, { bold: true, color: currentField === 'name' ? 'green' : 'white' }, t.subAgentConfig.agentName),
|
|
407
420
|
React.createElement(Box, { marginLeft: 2 },
|
|
408
|
-
React.createElement(TextInput, { value: agentName, onChange: value => setAgentName(stripFocusArtifacts(value)), placeholder:
|
|
421
|
+
React.createElement(TextInput, { value: agentName, onChange: value => setAgentName(stripFocusArtifacts(value)), placeholder: t.subAgentConfig.agentNamePlaceholder, focus: currentField === 'name' }))),
|
|
409
422
|
React.createElement(Box, { flexDirection: "column" },
|
|
410
|
-
React.createElement(Text, { bold: true, color: currentField === 'description' ? 'green' : 'white' },
|
|
423
|
+
React.createElement(Text, { bold: true, color: currentField === 'description' ? 'green' : 'white' }, t.subAgentConfig.description),
|
|
411
424
|
React.createElement(Box, { marginLeft: 2 },
|
|
412
|
-
React.createElement(TextInput, { value: description, onChange: value => setDescription(stripFocusArtifacts(value)), placeholder:
|
|
425
|
+
React.createElement(TextInput, { value: description, onChange: value => setDescription(stripFocusArtifacts(value)), placeholder: t.subAgentConfig.descriptionPlaceholder, focus: currentField === 'description' }))),
|
|
413
426
|
React.createElement(Box, { flexDirection: "column" },
|
|
414
|
-
React.createElement(Text, { bold: true, color: currentField === 'role' ? 'green' : 'white' },
|
|
427
|
+
React.createElement(Text, { bold: true, color: currentField === 'role' ? 'green' : 'white' }, t.subAgentConfig.roleOptional),
|
|
415
428
|
React.createElement(Box, { marginLeft: 2 },
|
|
416
|
-
React.createElement(TextInput, { value: role, onChange: value => setRole(stripFocusArtifacts(value)), placeholder:
|
|
429
|
+
React.createElement(TextInput, { value: role, onChange: value => setRole(stripFocusArtifacts(value)), placeholder: t.subAgentConfig.rolePlaceholder, focus: currentField === 'role' }))),
|
|
417
430
|
renderToolSelection(),
|
|
418
431
|
React.createElement(Box, { marginTop: 1 },
|
|
419
|
-
React.createElement(Text, { color: "gray", dimColor: true },
|
|
432
|
+
React.createElement(Text, { color: "gray", dimColor: true }, t.subAgentConfig.navigationHint)))));
|
|
420
433
|
}
|
|
@@ -4,7 +4,9 @@ import Gradient from 'ink-gradient';
|
|
|
4
4
|
import { Alert } from '@inkjs/ui';
|
|
5
5
|
import TextInput from 'ink-text-input';
|
|
6
6
|
import { getSystemPromptConfig, saveSystemPromptConfig, } from '../../utils/apiConfig.js';
|
|
7
|
+
import { useI18n } from '../../i18n/index.js';
|
|
7
8
|
export default function SystemPromptConfigScreen({ onBack }) {
|
|
9
|
+
const { t } = useI18n();
|
|
8
10
|
const [config, setConfig] = useState(() => {
|
|
9
11
|
return (getSystemPromptConfig() || {
|
|
10
12
|
active: '',
|
|
@@ -39,7 +41,7 @@ export default function SystemPromptConfigScreen({ onBack }) {
|
|
|
39
41
|
return true;
|
|
40
42
|
}
|
|
41
43
|
catch (err) {
|
|
42
|
-
setError(err instanceof Error ? err.message :
|
|
44
|
+
setError(err instanceof Error ? err.message : t.systemPromptConfig.saveError);
|
|
43
45
|
return false;
|
|
44
46
|
}
|
|
45
47
|
};
|
|
@@ -231,18 +233,18 @@ export default function SystemPromptConfigScreen({ onBack }) {
|
|
|
231
233
|
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
232
234
|
React.createElement(Box, { marginBottom: 1, borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1 },
|
|
233
235
|
React.createElement(Box, { flexDirection: "column" },
|
|
234
|
-
React.createElement(Gradient, { name: "rainbow" },
|
|
235
|
-
React.createElement(Text, { color: "gray", dimColor: true },
|
|
236
|
+
React.createElement(Gradient, { name: "rainbow" }, t.systemPromptConfig.title),
|
|
237
|
+
React.createElement(Text, { color: "gray", dimColor: true }, t.systemPromptConfig.subtitle))),
|
|
236
238
|
error && (React.createElement(Box, { marginBottom: 1 },
|
|
237
239
|
React.createElement(Alert, { variant: "error" }, error))),
|
|
238
240
|
React.createElement(Box, { marginBottom: 1 },
|
|
239
241
|
React.createElement(Text, { bold: true },
|
|
240
|
-
|
|
242
|
+
t.systemPromptConfig.activePrompt,
|
|
241
243
|
' ',
|
|
242
|
-
React.createElement(Text, { color: "green" }, activePrompt?.name ||
|
|
244
|
+
React.createElement(Text, { color: "green" }, activePrompt?.name || t.systemPromptConfig.none))),
|
|
243
245
|
config.prompts.length === 0 ? (React.createElement(Box, { marginBottom: 1 },
|
|
244
|
-
React.createElement(Text, { color: "yellow" },
|
|
245
|
-
React.createElement(Text, { bold: true, color: "cyan" },
|
|
246
|
+
React.createElement(Text, { color: "yellow" }, t.systemPromptConfig.noPromptsConfigured))) : (React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
|
|
247
|
+
React.createElement(Text, { bold: true, color: "cyan" }, t.systemPromptConfig.availablePrompts),
|
|
246
248
|
config.prompts.map((prompt, index) => (React.createElement(Box, { key: prompt.id, marginLeft: 2 },
|
|
247
249
|
React.createElement(Text, { color: index === selectedIndex
|
|
248
250
|
? 'green'
|
|
@@ -258,23 +260,25 @@ export default function SystemPromptConfigScreen({ onBack }) {
|
|
|
258
260
|
prompt.content.substring(0, 50),
|
|
259
261
|
prompt.content.length > 50 ? '...' : '')))))))),
|
|
260
262
|
React.createElement(Box, { marginBottom: 1 },
|
|
261
|
-
React.createElement(Text, { bold: true, color: "cyan" },
|
|
263
|
+
React.createElement(Text, { bold: true, color: "cyan" }, t.systemPromptConfig.actions)),
|
|
262
264
|
React.createElement(Box, { flexDirection: "column", marginBottom: 1, marginLeft: 2 }, actions.map(action => (React.createElement(Text, { key: action, color: currentAction === action ? 'green' : 'gray', bold: currentAction === action },
|
|
263
265
|
currentAction === action ? '❯ ' : ' ',
|
|
264
|
-
action === 'activate' &&
|
|
265
|
-
action === 'deactivate' &&
|
|
266
|
-
action === 'edit' &&
|
|
267
|
-
action === 'delete' &&
|
|
268
|
-
action === 'add' &&
|
|
269
|
-
action === 'back' &&
|
|
266
|
+
action === 'activate' && t.systemPromptConfig.activate,
|
|
267
|
+
action === 'deactivate' && t.systemPromptConfig.deactivate,
|
|
268
|
+
action === 'edit' && t.systemPromptConfig.edit,
|
|
269
|
+
action === 'delete' && t.systemPromptConfig.delete,
|
|
270
|
+
action === 'add' && t.systemPromptConfig.addNew,
|
|
271
|
+
action === 'back' && t.systemPromptConfig.escBack)))),
|
|
270
272
|
React.createElement(Box, { marginTop: 1 },
|
|
271
|
-
React.createElement(Text, { color: "gray", dimColor: true },
|
|
273
|
+
React.createElement(Text, { color: "gray", dimColor: true }, t.systemPromptConfig.navigationHint))));
|
|
272
274
|
}
|
|
273
275
|
// Render add/edit view
|
|
274
276
|
if (view === 'add' || view === 'edit') {
|
|
275
277
|
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
276
278
|
React.createElement(Box, { marginBottom: 1, borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1 },
|
|
277
|
-
React.createElement(Gradient, { name: "rainbow" }, view === 'add'
|
|
279
|
+
React.createElement(Gradient, { name: "rainbow" }, view === 'add'
|
|
280
|
+
? t.systemPromptConfig.addNewTitle
|
|
281
|
+
: t.systemPromptConfig.editTitle)),
|
|
278
282
|
error && (React.createElement(Box, { marginBottom: 1 },
|
|
279
283
|
React.createElement(Alert, { variant: "error" }, error))),
|
|
280
284
|
React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
|
|
@@ -282,38 +286,39 @@ export default function SystemPromptConfigScreen({ onBack }) {
|
|
|
282
286
|
React.createElement(Box, { flexDirection: "column" },
|
|
283
287
|
React.createElement(Text, { color: editingField === 'name' ? 'green' : 'white' },
|
|
284
288
|
editingField === 'name' ? '❯ ' : ' ',
|
|
285
|
-
|
|
289
|
+
t.systemPromptConfig.nameLabel),
|
|
286
290
|
editingField === 'name' && isEditing && (React.createElement(Box, { marginLeft: 3 },
|
|
287
|
-
React.createElement(TextInput, { value: editName, onChange: setEditName, placeholder:
|
|
291
|
+
React.createElement(TextInput, { value: editName, onChange: setEditName, placeholder: t.systemPromptConfig.enterPromptName }))),
|
|
288
292
|
(!isEditing || editingField !== 'name') && (React.createElement(Box, { marginLeft: 3 },
|
|
289
|
-
React.createElement(Text, { color: "gray" }, editName ||
|
|
293
|
+
React.createElement(Text, { color: "gray" }, editName || t.systemPromptConfig.notSet))))),
|
|
290
294
|
React.createElement(Box, { marginBottom: 1 },
|
|
291
295
|
React.createElement(Box, { flexDirection: "column" },
|
|
292
296
|
React.createElement(Text, { color: editingField === 'content' ? 'green' : 'white' },
|
|
293
297
|
editingField === 'content' ? '❯ ' : ' ',
|
|
294
|
-
|
|
298
|
+
t.systemPromptConfig.contentLabel),
|
|
295
299
|
editingField === 'content' && isEditing && (React.createElement(Box, { marginLeft: 3 },
|
|
296
|
-
React.createElement(TextInput, { value: editContent, onChange: setEditContent, placeholder:
|
|
300
|
+
React.createElement(TextInput, { value: editContent, onChange: setEditContent, placeholder: t.systemPromptConfig.enterPromptContent }))),
|
|
297
301
|
(!isEditing || editingField !== 'content') && (React.createElement(Box, { marginLeft: 3 },
|
|
298
302
|
React.createElement(Text, { color: "gray" }, editContent
|
|
299
303
|
? editContent.substring(0, 100) +
|
|
300
304
|
(editContent.length > 100 ? '...' : '')
|
|
301
|
-
:
|
|
305
|
+
: t.systemPromptConfig.notSet)))))),
|
|
302
306
|
React.createElement(Box, { marginTop: 1 },
|
|
303
|
-
React.createElement(Text, { color: "gray", dimColor: true },
|
|
307
|
+
React.createElement(Text, { color: "gray", dimColor: true }, t.systemPromptConfig.editingHint))));
|
|
304
308
|
}
|
|
305
309
|
// Render delete confirmation
|
|
306
310
|
if (view === 'confirmDelete') {
|
|
307
311
|
const promptToDelete = config.prompts.length > 0 ? config.prompts[selectedIndex] : null;
|
|
308
312
|
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
309
|
-
React.createElement(Alert, { variant: "warning" },
|
|
313
|
+
React.createElement(Alert, { variant: "warning" }, t.systemPromptConfig.confirmDelete),
|
|
310
314
|
React.createElement(Box, { marginBottom: 1 },
|
|
311
315
|
React.createElement(Text, null,
|
|
312
|
-
|
|
316
|
+
t.systemPromptConfig.deleteConfirmMessage,
|
|
317
|
+
" \"",
|
|
313
318
|
React.createElement(Text, { bold: true, color: "yellow" }, promptToDelete?.name),
|
|
314
319
|
"\"?")),
|
|
315
320
|
React.createElement(Box, { marginTop: 1 },
|
|
316
|
-
React.createElement(Text, { color: "gray", dimColor: true },
|
|
321
|
+
React.createElement(Text, { color: "gray", dimColor: true }, t.systemPromptConfig.confirmHint))));
|
|
317
322
|
}
|
|
318
323
|
return null;
|
|
319
324
|
}
|
|
@@ -13,68 +13,76 @@ import SensitiveCommandConfigScreen from './SensitiveCommandConfigScreen.js';
|
|
|
13
13
|
import CodeBaseConfigScreen from './CodeBaseConfigScreen.js';
|
|
14
14
|
import SystemPromptConfigScreen from './SystemPromptConfigScreen.js';
|
|
15
15
|
import CustomHeadersScreen from './CustomHeadersScreen.js';
|
|
16
|
+
import LanguageSettingsScreen from './LanguageSettingsScreen.js';
|
|
17
|
+
import { useI18n } from '../../i18n/index.js';
|
|
16
18
|
export default function WelcomeScreen({ version = '1.0.0', onMenuSelect, }) {
|
|
17
|
-
const
|
|
19
|
+
const { t } = useI18n();
|
|
20
|
+
const [infoText, setInfoText] = useState(t.welcome.startChatInfo);
|
|
18
21
|
const [inlineView, setInlineView] = useState('menu');
|
|
19
22
|
const [editingAgentId, setEditingAgentId] = useState();
|
|
20
23
|
const { columns: terminalWidth } = useTerminalSize();
|
|
21
24
|
const { stdout } = useStdout();
|
|
22
25
|
const isInitialMount = useRef(true);
|
|
23
|
-
const [remountKey, setRemountKey] = useState(0);
|
|
24
26
|
const menuOptions = useMemo(() => [
|
|
25
27
|
{
|
|
26
|
-
label:
|
|
28
|
+
label: t.welcome.startChat,
|
|
27
29
|
value: 'chat',
|
|
28
|
-
infoText:
|
|
30
|
+
infoText: t.welcome.startChatInfo,
|
|
29
31
|
clearTerminal: true,
|
|
30
32
|
},
|
|
31
33
|
{
|
|
32
|
-
label:
|
|
34
|
+
label: t.welcome.apiSettings,
|
|
33
35
|
value: 'config',
|
|
34
|
-
infoText:
|
|
36
|
+
infoText: t.welcome.apiSettingsInfo,
|
|
35
37
|
},
|
|
36
38
|
{
|
|
37
|
-
label:
|
|
39
|
+
label: t.welcome.proxySettings,
|
|
38
40
|
value: 'proxy',
|
|
39
|
-
infoText:
|
|
41
|
+
infoText: t.welcome.proxySettingsInfo,
|
|
40
42
|
},
|
|
41
43
|
{
|
|
42
|
-
label:
|
|
44
|
+
label: t.welcome.codebaseSettings,
|
|
43
45
|
value: 'codebase',
|
|
44
|
-
infoText:
|
|
46
|
+
infoText: t.welcome.codebaseSettingsInfo,
|
|
45
47
|
},
|
|
46
48
|
{
|
|
47
|
-
label:
|
|
49
|
+
label: t.welcome.systemPromptSettings,
|
|
48
50
|
value: 'systemprompt',
|
|
49
|
-
infoText:
|
|
51
|
+
infoText: t.welcome.systemPromptSettingsInfo,
|
|
50
52
|
},
|
|
51
53
|
{
|
|
52
|
-
label:
|
|
54
|
+
label: t.welcome.customHeadersSettings,
|
|
53
55
|
value: 'customheaders',
|
|
54
|
-
infoText:
|
|
56
|
+
infoText: t.welcome.customHeadersSettingsInfo,
|
|
55
57
|
},
|
|
56
58
|
{
|
|
57
|
-
label:
|
|
59
|
+
label: t.welcome.mcpSettings,
|
|
58
60
|
value: 'mcp',
|
|
59
|
-
infoText:
|
|
61
|
+
infoText: t.welcome.mcpSettingsInfo,
|
|
60
62
|
},
|
|
61
63
|
{
|
|
62
|
-
label:
|
|
64
|
+
label: t.welcome.subAgentSettings,
|
|
63
65
|
value: 'subagent',
|
|
64
|
-
infoText:
|
|
66
|
+
infoText: t.welcome.subAgentSettingsInfo,
|
|
65
67
|
},
|
|
66
68
|
{
|
|
67
|
-
label:
|
|
69
|
+
label: t.welcome.sensitiveCommands,
|
|
68
70
|
value: 'sensitive-commands',
|
|
69
|
-
infoText:
|
|
71
|
+
infoText: t.welcome.sensitiveCommandsInfo,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
label: t.welcome.languageSettings,
|
|
75
|
+
value: 'language',
|
|
76
|
+
infoText: t.welcome.languageSettingsInfo,
|
|
70
77
|
},
|
|
71
78
|
{
|
|
72
|
-
label:
|
|
79
|
+
label: t.welcome.exit,
|
|
73
80
|
value: 'exit',
|
|
74
81
|
color: 'rgb(232, 131, 136)',
|
|
75
|
-
infoText:
|
|
82
|
+
infoText: t.welcome.exitInfo,
|
|
76
83
|
},
|
|
77
|
-
], []);
|
|
84
|
+
], [t]);
|
|
85
|
+
const [remountKey, setRemountKey] = useState(0);
|
|
78
86
|
const handleSelectionChange = useCallback((newInfoText) => {
|
|
79
87
|
setInfoText(newInfoText);
|
|
80
88
|
}, []);
|
|
@@ -101,6 +109,9 @@ export default function WelcomeScreen({ version = '1.0.0', onMenuSelect, }) {
|
|
|
101
109
|
else if (value === 'customheaders') {
|
|
102
110
|
setInlineView('customheaders');
|
|
103
111
|
}
|
|
112
|
+
else if (value === 'language') {
|
|
113
|
+
setInlineView('language-settings');
|
|
114
|
+
}
|
|
104
115
|
else {
|
|
105
116
|
// Pass through to parent for other actions (chat, exit, etc.)
|
|
106
117
|
onMenuSelect?.(value);
|
|
@@ -143,11 +154,12 @@ export default function WelcomeScreen({ version = '1.0.0', onMenuSelect, }) {
|
|
|
143
154
|
React.createElement(Box, { key: "welcome-header", flexDirection: "row", paddingLeft: 2, paddingTop: 1, paddingBottom: 0, width: terminalWidth },
|
|
144
155
|
React.createElement(Box, { flexDirection: "column", justifyContent: "center" },
|
|
145
156
|
React.createElement(Text, { bold: true },
|
|
146
|
-
React.createElement(Gradient, { name: "rainbow" },
|
|
157
|
+
React.createElement(Gradient, { name: "rainbow" }, t.welcome.title)),
|
|
147
158
|
React.createElement(Text, { color: "gray", dimColor: true },
|
|
148
159
|
"v",
|
|
149
160
|
version,
|
|
150
|
-
" \u2022
|
|
161
|
+
" \u2022 ",
|
|
162
|
+
t.welcome.subtitle))),
|
|
151
163
|
] }, item => item),
|
|
152
164
|
onMenuSelect && inlineView === 'menu' && (React.createElement(Box, { paddingX: 1 },
|
|
153
165
|
React.createElement(Box, { borderStyle: "round", borderColor: "cyan", paddingX: 1 },
|
|
@@ -171,5 +183,7 @@ export default function WelcomeScreen({ version = '1.0.0', onMenuSelect, }) {
|
|
|
171
183
|
inlineView === 'systemprompt' && (React.createElement(Box, { paddingX: 1 },
|
|
172
184
|
React.createElement(SystemPromptConfigScreen, { onBack: handleBackToMenu }))),
|
|
173
185
|
inlineView === 'customheaders' && (React.createElement(Box, { paddingX: 1 },
|
|
174
|
-
React.createElement(CustomHeadersScreen, { onBack: handleBackToMenu })))
|
|
186
|
+
React.createElement(CustomHeadersScreen, { onBack: handleBackToMenu }))),
|
|
187
|
+
inlineView === 'language-settings' && (React.createElement(Box, { paddingX: 1 },
|
|
188
|
+
React.createElement(LanguageSettingsScreen, { onBack: handleBackToMenu, inlineMode: true })))));
|
|
175
189
|
}
|
|
@@ -27,6 +27,8 @@ export interface ApiConfig {
|
|
|
27
27
|
thinking?: ThinkingConfig;
|
|
28
28
|
geminiThinking?: GeminiThinkingConfig;
|
|
29
29
|
responsesReasoning?: ResponsesReasoningConfig;
|
|
30
|
+
enablePromptOptimization?: boolean;
|
|
31
|
+
enableAutoCompress?: boolean;
|
|
30
32
|
}
|
|
31
33
|
export interface MCPServer {
|
|
32
34
|
url?: string;
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
export interface CodebaseConfig {
|
|
2
2
|
enabled: boolean;
|
|
3
|
+
enableAgentReview: boolean;
|
|
3
4
|
embedding: {
|
|
4
5
|
modelName: string;
|
|
5
6
|
baseUrl: string;
|
|
6
7
|
apiKey: string;
|
|
7
8
|
dimensions: number;
|
|
8
9
|
};
|
|
9
|
-
llm: {
|
|
10
|
-
modelName: string;
|
|
11
|
-
baseUrl: string;
|
|
12
|
-
apiKey: string;
|
|
13
|
-
};
|
|
14
10
|
batch: {
|
|
15
11
|
maxLines: number;
|
|
16
12
|
concurrency: number;
|
|
@@ -3,17 +3,13 @@ import path from 'path';
|
|
|
3
3
|
import os from 'os';
|
|
4
4
|
const DEFAULT_CONFIG = {
|
|
5
5
|
enabled: false,
|
|
6
|
+
enableAgentReview: true,
|
|
6
7
|
embedding: {
|
|
7
8
|
modelName: '',
|
|
8
9
|
baseUrl: '',
|
|
9
10
|
apiKey: '',
|
|
10
11
|
dimensions: 1536,
|
|
11
12
|
},
|
|
12
|
-
llm: {
|
|
13
|
-
modelName: '',
|
|
14
|
-
baseUrl: '',
|
|
15
|
-
apiKey: '',
|
|
16
|
-
},
|
|
17
13
|
batch: {
|
|
18
14
|
maxLines: 10,
|
|
19
15
|
concurrency: 3,
|
|
@@ -41,17 +37,13 @@ export const loadCodebaseConfig = () => {
|
|
|
41
37
|
// Merge with defaults to ensure all fields exist
|
|
42
38
|
return {
|
|
43
39
|
enabled: config.enabled ?? DEFAULT_CONFIG.enabled,
|
|
40
|
+
enableAgentReview: config.enableAgentReview ?? DEFAULT_CONFIG.enableAgentReview,
|
|
44
41
|
embedding: {
|
|
45
42
|
modelName: config.embedding?.modelName ?? DEFAULT_CONFIG.embedding.modelName,
|
|
46
43
|
baseUrl: config.embedding?.baseUrl ?? DEFAULT_CONFIG.embedding.baseUrl,
|
|
47
44
|
apiKey: config.embedding?.apiKey ?? DEFAULT_CONFIG.embedding.apiKey,
|
|
48
45
|
dimensions: config.embedding?.dimensions ?? DEFAULT_CONFIG.embedding.dimensions,
|
|
49
46
|
},
|
|
50
|
-
llm: {
|
|
51
|
-
modelName: config.llm?.modelName ?? DEFAULT_CONFIG.llm.modelName,
|
|
52
|
-
baseUrl: config.llm?.baseUrl ?? DEFAULT_CONFIG.llm.baseUrl,
|
|
53
|
-
apiKey: config.llm?.apiKey ?? DEFAULT_CONFIG.llm.apiKey,
|
|
54
|
-
},
|
|
55
47
|
batch: {
|
|
56
48
|
maxLines: config.batch?.maxLines ?? DEFAULT_CONFIG.batch.maxLines,
|
|
57
49
|
concurrency: config.batch?.concurrency ?? DEFAULT_CONFIG.batch.concurrency,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
export type CodebaseSearchEvent = {
|
|
3
|
+
type: 'search-start' | 'search-retry' | 'search-complete';
|
|
4
|
+
attempt: number;
|
|
5
|
+
maxAttempts: number;
|
|
6
|
+
currentTopN: number;
|
|
7
|
+
message: string;
|
|
8
|
+
query?: string;
|
|
9
|
+
};
|
|
10
|
+
declare class CodebaseSearchEventEmitter extends EventEmitter {
|
|
11
|
+
emitSearchEvent(event: CodebaseSearchEvent): void;
|
|
12
|
+
onSearchEvent(callback: (event: CodebaseSearchEvent) => void): void;
|
|
13
|
+
removeSearchEventListener(callback: (event: CodebaseSearchEvent) => void): void;
|
|
14
|
+
}
|
|
15
|
+
export declare const codebaseSearchEvents: CodebaseSearchEventEmitter;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
class CodebaseSearchEventEmitter extends EventEmitter {
|
|
3
|
+
emitSearchEvent(event) {
|
|
4
|
+
this.emit('codebase-search', event);
|
|
5
|
+
}
|
|
6
|
+
onSearchEvent(callback) {
|
|
7
|
+
this.on('codebase-search', callback);
|
|
8
|
+
}
|
|
9
|
+
removeSearchEventListener(callback) {
|
|
10
|
+
this.off('codebase-search', callback);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export const codebaseSearchEvents = new CodebaseSearchEventEmitter();
|
|
@@ -77,7 +77,7 @@ License information (check package.json or LICENSE file)
|
|
|
77
77
|
---
|
|
78
78
|
|
|
79
79
|
**Important instructions:**
|
|
80
|
-
- Use filesystem-
|
|
80
|
+
- Use filesystem-read to explore directories (it automatically lists contents when path is a directory)
|
|
81
81
|
- Use filesystem-read to read important files
|
|
82
82
|
- Use terminal-execute to run commands like 'npm run' to discover available scripts
|
|
83
83
|
- Be thorough but concise - focus on essential information
|