aiexecode 1.0.66 → 1.0.68
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.
Potentially problematic release.
This version of aiexecode might be problematic. Click here for more details.
- package/config_template/settings.json +1 -3
- package/index.js +46 -71
- package/package.json +1 -12
- package/payload_viewer/out/404/index.html +1 -1
- package/payload_viewer/out/404.html +1 -1
- package/payload_viewer/out/index.html +1 -1
- package/payload_viewer/out/index.txt +1 -1
- package/payload_viewer/web_server.js +0 -163
- package/src/ai_based/completion_judge.js +96 -5
- package/src/ai_based/orchestrator.js +71 -3
- package/src/ai_based/pip_package_installer.js +14 -12
- package/src/ai_based/pip_package_lookup.js +13 -10
- package/src/commands/apikey.js +8 -34
- package/src/commands/help.js +3 -4
- package/src/commands/model.js +17 -74
- package/src/commands/reasoning_effort.js +1 -1
- package/src/config/feature_flags.js +0 -12
- package/src/{ui → frontend}/App.js +23 -25
- package/src/frontend/README.md +81 -0
- package/src/{ui/components/SuggestionsDisplay.js → frontend/components/AutocompleteMenu.js} +3 -3
- package/src/{ui/components/HistoryItemDisplay.js → frontend/components/ConversationItem.js} +37 -89
- package/src/{ui → frontend}/components/CurrentModelView.js +3 -5
- package/src/{ui → frontend}/components/Footer.js +4 -6
- package/src/{ui → frontend}/components/Header.js +2 -5
- package/src/{ui/components/InputPrompt.js → frontend/components/Input.js} +16 -54
- package/src/frontend/components/ModelListView.js +106 -0
- package/src/{ui → frontend}/components/ModelUpdatedView.js +3 -5
- package/src/{ui → frontend}/components/SessionSpinner.js +3 -3
- package/src/{ui → frontend}/components/SetupWizard.js +8 -101
- package/src/{ui → frontend}/components/ToolApprovalPrompt.js +16 -14
- package/src/frontend/design/themeColors.js +42 -0
- package/src/{ui → frontend}/index.js +7 -7
- package/src/frontend/utils/inputBuffer.js +441 -0
- package/src/{ui/utils/markdownRenderer.js → frontend/utils/markdownParser.js} +3 -3
- package/src/{ui/utils/ConsolePatcher.js → frontend/utils/outputRedirector.js} +9 -9
- package/src/{ui/utils/codeColorizer.js → frontend/utils/syntaxHighlighter.js} +2 -3
- package/src/system/ai_request.js +145 -595
- package/src/system/code_executer.js +111 -16
- package/src/system/file_integrity.js +5 -7
- package/src/system/log.js +3 -3
- package/src/system/mcp_integration.js +15 -13
- package/src/system/output_helper.js +0 -20
- package/src/system/session.js +97 -23
- package/src/system/session_memory.js +2 -82
- package/src/system/system_info.js +1 -1
- package/src/system/ui_events.js +0 -43
- package/src/tools/code_editor.js +17 -2
- package/src/tools/file_reader.js +17 -2
- package/src/tools/glob.js +9 -1
- package/src/tools/response_message.js +0 -2
- package/src/tools/ripgrep.js +9 -1
- package/src/tools/web_downloader.js +9 -1
- package/src/util/config.js +3 -8
- package/src/util/debug_log.js +4 -11
- package/src/util/mcp_config_manager.js +3 -5
- package/src/util/output_formatter.js +0 -47
- package/src/util/prompt_loader.js +3 -4
- package/src/util/safe_fs.js +60 -0
- package/src/util/setup_wizard.js +1 -3
- package/src/util/text_formatter.js +0 -86
- package/src/config/claude_models.js +0 -195
- package/src/ui/README.md +0 -208
- package/src/ui/api.js +0 -167
- package/src/ui/components/AgenticProgressDisplay.js +0 -126
- package/src/ui/components/Composer.js +0 -55
- package/src/ui/components/LoadingIndicator.js +0 -54
- package/src/ui/components/ModelListView.js +0 -214
- package/src/ui/components/Notifications.js +0 -55
- package/src/ui/components/StreamingIndicator.js +0 -36
- package/src/ui/contexts/AppContext.js +0 -25
- package/src/ui/contexts/StreamingContext.js +0 -20
- package/src/ui/contexts/UIStateContext.js +0 -117
- package/src/ui/example-usage.js +0 -180
- package/src/ui/hooks/useTerminalResize.js +0 -39
- package/src/ui/themes/semantic-tokens.js +0 -73
- package/src/ui/utils/text-buffer.js +0 -975
- /package/payload_viewer/out/_next/static/{t0WTsjXST7ISD1Boa6ifx → Z3AZSKhutj-kS4L8VpcOl}/_buildManifest.js +0 -0
- /package/payload_viewer/out/_next/static/{t0WTsjXST7ISD1Boa6ifx → Z3AZSKhutj-kS4L8VpcOl}/_clientMiddlewareManifest.json +0 -0
- /package/payload_viewer/out/_next/static/{t0WTsjXST7ISD1Boa6ifx → Z3AZSKhutj-kS4L8VpcOl}/_ssgManifest.js +0 -0
- /package/src/{ui → frontend}/components/BlankLine.js +0 -0
- /package/src/{ui → frontend}/components/FileDiffViewer.js +0 -0
- /package/src/{ui → frontend}/components/HelpView.js +0 -0
- /package/src/{ui → frontend}/hooks/useCompletion.js +0 -0
- /package/src/{ui → frontend}/hooks/useKeypress.js +0 -0
- /package/src/{ui → frontend}/utils/diffUtils.js +0 -0
- /package/src/{ui → frontend}/utils/renderInkComponent.js +0 -0
|
@@ -4,24 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
import React, { useState, useRef } from 'react';
|
|
6
6
|
import { Box, Text, useInput } from 'ink';
|
|
7
|
-
import { theme } from '../
|
|
8
|
-
import { CLAUDE_MODELS, getClaude4Models, getClaude3Models, DEFAULT_CLAUDE_MODEL } from '../../config/claude_models.js';
|
|
7
|
+
import { theme } from '../design/themeColors.js';
|
|
9
8
|
import { OPENAI_MODELS, getGPT5Models, DEFAULT_OPENAI_MODEL } from '../../config/openai_models.js';
|
|
10
|
-
import { ENABLE_ANTHROPIC_PROVIDER } from '../../config/feature_flags.js';
|
|
11
9
|
|
|
12
10
|
const STEPS = {
|
|
13
|
-
PROVIDER: 'provider',
|
|
14
11
|
OPENAI_KEY: 'openai_key',
|
|
15
12
|
OPENAI_MODEL: 'openai_model',
|
|
16
|
-
OPENAI_EFFORT: 'openai_effort'
|
|
17
|
-
ANTHROPIC_KEY: 'anthropic_key',
|
|
18
|
-
ANTHROPIC_MODEL: 'anthropic_model'
|
|
13
|
+
OPENAI_EFFORT: 'openai_effort'
|
|
19
14
|
};
|
|
20
15
|
|
|
21
16
|
export function SetupWizard({ onComplete, onCancel }) {
|
|
22
|
-
|
|
23
|
-
const initialStep = ENABLE_ANTHROPIC_PROVIDER ? STEPS.PROVIDER : STEPS.OPENAI_KEY;
|
|
24
|
-
const [step, setStep] = useState(initialStep);
|
|
17
|
+
const [step, setStep] = useState(STEPS.OPENAI_KEY);
|
|
25
18
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
26
19
|
const [textInput, setTextInput] = useState('');
|
|
27
20
|
|
|
@@ -30,13 +23,11 @@ export function SetupWizard({ onComplete, onCancel }) {
|
|
|
30
23
|
AI_PROVIDER: 'openai',
|
|
31
24
|
OPENAI_API_KEY: '',
|
|
32
25
|
OPENAI_MODEL: DEFAULT_OPENAI_MODEL,
|
|
33
|
-
OPENAI_REASONING_EFFORT: 'medium'
|
|
34
|
-
ANTHROPIC_API_KEY: '',
|
|
35
|
-
ANTHROPIC_MODEL: DEFAULT_CLAUDE_MODEL
|
|
26
|
+
OPENAI_REASONING_EFFORT: 'medium'
|
|
36
27
|
});
|
|
37
28
|
|
|
38
29
|
// 현재 스텝이 텍스트 입력인지 선택지인지 판단
|
|
39
|
-
const isTextInputStep = step === STEPS.OPENAI_KEY
|
|
30
|
+
const isTextInputStep = step === STEPS.OPENAI_KEY;
|
|
40
31
|
|
|
41
32
|
const completeSetup = () => {
|
|
42
33
|
if (onComplete) {
|
|
@@ -47,17 +38,6 @@ export function SetupWizard({ onComplete, onCancel }) {
|
|
|
47
38
|
|
|
48
39
|
const handleStepComplete = () => {
|
|
49
40
|
switch (step) {
|
|
50
|
-
case STEPS.PROVIDER:
|
|
51
|
-
if (selectedIndex === 0) {
|
|
52
|
-
settingsRef.current.AI_PROVIDER = 'openai';
|
|
53
|
-
setStep(STEPS.OPENAI_KEY);
|
|
54
|
-
} else {
|
|
55
|
-
settingsRef.current.AI_PROVIDER = 'anthropic';
|
|
56
|
-
setStep(STEPS.ANTHROPIC_KEY);
|
|
57
|
-
}
|
|
58
|
-
setSelectedIndex(0);
|
|
59
|
-
break;
|
|
60
|
-
|
|
61
41
|
case STEPS.OPENAI_KEY:
|
|
62
42
|
if (!textInput.trim()) {
|
|
63
43
|
return;
|
|
@@ -84,24 +64,6 @@ export function SetupWizard({ onComplete, onCancel }) {
|
|
|
84
64
|
// 완료
|
|
85
65
|
completeSetup();
|
|
86
66
|
break;
|
|
87
|
-
|
|
88
|
-
case STEPS.ANTHROPIC_KEY:
|
|
89
|
-
if (!textInput.trim()) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
settingsRef.current.ANTHROPIC_API_KEY = textInput.trim();
|
|
93
|
-
setStep(STEPS.ANTHROPIC_MODEL);
|
|
94
|
-
setTextInput('');
|
|
95
|
-
setSelectedIndex(0);
|
|
96
|
-
break;
|
|
97
|
-
|
|
98
|
-
case STEPS.ANTHROPIC_MODEL:
|
|
99
|
-
// 중앙 설정에서 모든 Claude 모델 목록 가져오기
|
|
100
|
-
const anthropicModels = [...getClaude4Models(), ...getClaude3Models()];
|
|
101
|
-
settingsRef.current.ANTHROPIC_MODEL = anthropicModels[selectedIndex];
|
|
102
|
-
// 완료
|
|
103
|
-
completeSetup();
|
|
104
|
-
break;
|
|
105
67
|
}
|
|
106
68
|
};
|
|
107
69
|
|
|
@@ -150,14 +112,10 @@ export function SetupWizard({ onComplete, onCancel }) {
|
|
|
150
112
|
|
|
151
113
|
const getMaxIndexForStep = (currentStep) => {
|
|
152
114
|
switch (currentStep) {
|
|
153
|
-
case STEPS.PROVIDER:
|
|
154
|
-
return ENABLE_ANTHROPIC_PROVIDER ? 1 : 0; // 2 options if enabled, 1 if disabled
|
|
155
115
|
case STEPS.OPENAI_MODEL:
|
|
156
116
|
return getGPT5Models().length - 1;
|
|
157
117
|
case STEPS.OPENAI_EFFORT:
|
|
158
118
|
return 3; // 4 options
|
|
159
|
-
case STEPS.ANTHROPIC_MODEL:
|
|
160
|
-
return [...getClaude4Models(), ...getClaude3Models()].length - 1;
|
|
161
119
|
default:
|
|
162
120
|
return 0;
|
|
163
121
|
}
|
|
@@ -179,28 +137,9 @@ export function SetupWizard({ onComplete, onCancel }) {
|
|
|
179
137
|
|
|
180
138
|
const renderStep = () => {
|
|
181
139
|
switch (step) {
|
|
182
|
-
case STEPS.PROVIDER:
|
|
183
|
-
const providerOptions = ENABLE_ANTHROPIC_PROVIDER
|
|
184
|
-
? [
|
|
185
|
-
'OpenAI (GPT-5, GPT-4, o1 series)',
|
|
186
|
-
'Anthropic (Claude series)'
|
|
187
|
-
]
|
|
188
|
-
: [
|
|
189
|
-
'OpenAI (GPT-5, GPT-4, o1 series)'
|
|
190
|
-
];
|
|
191
|
-
|
|
192
|
-
return React.createElement(Box, { flexDirection: 'column' },
|
|
193
|
-
React.createElement(Text, { bold: true, color: theme.text.accent }, '1. Choose AI Provider:'),
|
|
194
|
-
React.createElement(Text, null),
|
|
195
|
-
renderOptions(providerOptions),
|
|
196
|
-
React.createElement(Text, null),
|
|
197
|
-
React.createElement(Text, { dimColor: true }, '↑↓: Navigate Enter: Confirm')
|
|
198
|
-
);
|
|
199
|
-
|
|
200
140
|
case STEPS.OPENAI_KEY:
|
|
201
|
-
const openaiKeyStep = ENABLE_ANTHROPIC_PROVIDER ? '2' : '1';
|
|
202
141
|
return React.createElement(Box, { flexDirection: 'column' },
|
|
203
|
-
React.createElement(Text, { bold: true, color: theme.text.accent },
|
|
142
|
+
React.createElement(Text, { bold: true, color: theme.text.accent }, '1. OpenAI API Key:'),
|
|
204
143
|
React.createElement(Text, { color: theme.text.secondary }, ' Get your API key from: https://platform.openai.com/account/api-keys'),
|
|
205
144
|
React.createElement(Text, null),
|
|
206
145
|
React.createElement(Box, {
|
|
@@ -215,9 +154,8 @@ export function SetupWizard({ onComplete, onCancel }) {
|
|
|
215
154
|
);
|
|
216
155
|
|
|
217
156
|
case STEPS.OPENAI_MODEL:
|
|
218
|
-
const openaiModelStep = ENABLE_ANTHROPIC_PROVIDER ? '3' : '2';
|
|
219
157
|
return React.createElement(Box, { flexDirection: 'column' },
|
|
220
|
-
React.createElement(Text, { bold: true, color: theme.text.accent },
|
|
158
|
+
React.createElement(Text, { bold: true, color: theme.text.accent }, '2. Choose Model:'),
|
|
221
159
|
React.createElement(Text, null),
|
|
222
160
|
renderOptions(
|
|
223
161
|
getGPT5Models().map(modelId => {
|
|
@@ -230,9 +168,8 @@ export function SetupWizard({ onComplete, onCancel }) {
|
|
|
230
168
|
);
|
|
231
169
|
|
|
232
170
|
case STEPS.OPENAI_EFFORT:
|
|
233
|
-
const openaiEffortStep = ENABLE_ANTHROPIC_PROVIDER ? '4' : '3';
|
|
234
171
|
return React.createElement(Box, { flexDirection: 'column' },
|
|
235
|
-
React.createElement(Text, { bold: true, color: theme.text.accent },
|
|
172
|
+
React.createElement(Text, { bold: true, color: theme.text.accent }, '3. Reasoning Effort:'),
|
|
236
173
|
React.createElement(Text, null),
|
|
237
174
|
renderOptions([
|
|
238
175
|
'minimal (Fastest)',
|
|
@@ -244,36 +181,6 @@ export function SetupWizard({ onComplete, onCancel }) {
|
|
|
244
181
|
React.createElement(Text, { dimColor: true }, '↑↓: Navigate Enter: Confirm')
|
|
245
182
|
);
|
|
246
183
|
|
|
247
|
-
case STEPS.ANTHROPIC_KEY:
|
|
248
|
-
return React.createElement(Box, { flexDirection: 'column' },
|
|
249
|
-
React.createElement(Text, { bold: true, color: theme.text.accent }, '2. Anthropic API Key:'),
|
|
250
|
-
React.createElement(Text, { color: theme.text.secondary }, ' Get your API key from: https://console.anthropic.com/settings/keys'),
|
|
251
|
-
React.createElement(Text, null),
|
|
252
|
-
React.createElement(Box, {
|
|
253
|
-
borderStyle: 'round',
|
|
254
|
-
borderColor: theme.border.focused,
|
|
255
|
-
paddingX: 1
|
|
256
|
-
},
|
|
257
|
-
React.createElement(Text, null, textInput ? '*'.repeat(textInput.length) : ' ')
|
|
258
|
-
),
|
|
259
|
-
React.createElement(Text, null),
|
|
260
|
-
React.createElement(Text, { dimColor: true }, 'Type your API key and press Enter')
|
|
261
|
-
);
|
|
262
|
-
|
|
263
|
-
case STEPS.ANTHROPIC_MODEL:
|
|
264
|
-
return React.createElement(Box, { flexDirection: 'column' },
|
|
265
|
-
React.createElement(Text, { bold: true, color: theme.text.accent }, '3. Choose Model:'),
|
|
266
|
-
React.createElement(Text, null),
|
|
267
|
-
renderOptions(
|
|
268
|
-
[...getClaude4Models(), ...getClaude3Models()].map(modelId => {
|
|
269
|
-
const model = CLAUDE_MODELS[modelId];
|
|
270
|
-
return `${modelId} (${model.name})`;
|
|
271
|
-
})
|
|
272
|
-
),
|
|
273
|
-
React.createElement(Text, null),
|
|
274
|
-
React.createElement(Text, { dimColor: true }, '↑↓: Navigate Enter: Confirm')
|
|
275
|
-
);
|
|
276
|
-
|
|
277
184
|
default:
|
|
278
185
|
return null;
|
|
279
186
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import React, { useState, useEffect } from 'react';
|
|
6
6
|
import { Box, Text, useInput } from 'ink';
|
|
7
|
-
import { theme } from '../
|
|
7
|
+
import { theme } from '../design/themeColors.js';
|
|
8
8
|
import { FileDiffViewer } from './FileDiffViewer.js';
|
|
9
9
|
import { common, createLowlight } from 'lowlight';
|
|
10
10
|
import { getToolDisplayName } from '../../system/tool_registry.js';
|
|
@@ -42,14 +42,14 @@ export function ToolApprovalPrompt({ toolName, args, onDecision, mcpToolInfo = n
|
|
|
42
42
|
return React.createElement(Box, {
|
|
43
43
|
flexDirection: 'column',
|
|
44
44
|
borderStyle: 'round',
|
|
45
|
-
borderColor:
|
|
45
|
+
borderColor: theme.brand.dark,
|
|
46
46
|
paddingX: 1,
|
|
47
47
|
flexGrow: 1
|
|
48
48
|
},
|
|
49
49
|
// Tool info
|
|
50
50
|
React.createElement(Box, { flexDirection: 'column', marginBottom: 0, marginTop: 0 },
|
|
51
51
|
React.createElement(Box, { marginBottom: 0 },
|
|
52
|
-
React.createElement(Text, { bold: true, color:
|
|
52
|
+
React.createElement(Text, { bold: true, color: theme.brand.light }, 'Tool '),
|
|
53
53
|
React.createElement(Text, { color: 'white' }, displayName)
|
|
54
54
|
),
|
|
55
55
|
renderToolArgs(toolName, args, mcpToolInfo)
|
|
@@ -61,11 +61,11 @@ export function ToolApprovalPrompt({ toolName, args, onDecision, mcpToolInfo = n
|
|
|
61
61
|
...choices.map((choice, index) =>
|
|
62
62
|
React.createElement(Box, { key: index, marginLeft: 1 },
|
|
63
63
|
React.createElement(Text, {
|
|
64
|
-
color: index === selectedIndex ?
|
|
64
|
+
color: index === selectedIndex ? theme.brand.light : 'white',
|
|
65
65
|
bold: index === selectedIndex
|
|
66
66
|
}, index === selectedIndex ? '› ' : ' '),
|
|
67
67
|
React.createElement(Text, {
|
|
68
|
-
color: index === selectedIndex ?
|
|
68
|
+
color: index === selectedIndex ? theme.brand.light : 'white'
|
|
69
69
|
}, choice.label)
|
|
70
70
|
)
|
|
71
71
|
)
|
|
@@ -196,12 +196,12 @@ function renderToolArgs(toolName, args, mcpToolInfo = null) {
|
|
|
196
196
|
return React.createElement(Box, { flexDirection: 'column', marginTop: 0 },
|
|
197
197
|
// Server info
|
|
198
198
|
React.createElement(Box, { marginBottom: 0 },
|
|
199
|
-
React.createElement(Text, { bold: true, color:
|
|
199
|
+
React.createElement(Text, { bold: true, color: theme.brand.light }, 'Server '),
|
|
200
200
|
React.createElement(Text, { color: 'white' }, mcpToolInfo.server)
|
|
201
201
|
),
|
|
202
202
|
// Description (박스 안에 담기)
|
|
203
203
|
mcpToolInfo.description && React.createElement(Box, { flexDirection: 'column', marginTop: 0 },
|
|
204
|
-
React.createElement(Text, { bold: true, color:
|
|
204
|
+
React.createElement(Text, { bold: true, color: theme.brand.light }, 'Description'),
|
|
205
205
|
React.createElement(Box, {
|
|
206
206
|
borderStyle: 'single',
|
|
207
207
|
borderColor: '#444444',
|
|
@@ -213,7 +213,7 @@ function renderToolArgs(toolName, args, mcpToolInfo = null) {
|
|
|
213
213
|
),
|
|
214
214
|
// Arguments (JSON 하이라이팅)
|
|
215
215
|
React.createElement(Box, { flexDirection: 'column', marginTop: 0 },
|
|
216
|
-
React.createElement(Text, { bold: true, color:
|
|
216
|
+
React.createElement(Text, { bold: true, color: theme.brand.light }, 'Arguments'),
|
|
217
217
|
React.createElement(Box, {
|
|
218
218
|
borderStyle: 'single',
|
|
219
219
|
borderColor: '#444444',
|
|
@@ -292,7 +292,7 @@ function renderToolArgs(toolName, args, mcpToolInfo = null) {
|
|
|
292
292
|
|
|
293
293
|
return React.createElement(Box, { flexDirection: 'column', marginTop: 0 },
|
|
294
294
|
React.createElement(Box, {},
|
|
295
|
-
React.createElement(Text, { bold: true, color:
|
|
295
|
+
React.createElement(Text, { bold: true, color: theme.brand.light }, 'File '),
|
|
296
296
|
React.createElement(Text, { color: 'white' }, toDisplayPath(args.file_path))
|
|
297
297
|
),
|
|
298
298
|
React.createElement(Box, {
|
|
@@ -372,7 +372,7 @@ function renderToolArgs(toolName, args, mcpToolInfo = null) {
|
|
|
372
372
|
|
|
373
373
|
return React.createElement(Box, { flexDirection: 'column', marginTop: 0 },
|
|
374
374
|
React.createElement(Box, { marginBottom: 0 },
|
|
375
|
-
React.createElement(Text, { bold: true, color:
|
|
375
|
+
React.createElement(Text, { bold: true, color: theme.brand.light }, 'File '),
|
|
376
376
|
React.createElement(Text, { color: 'white' }, toDisplayPath(args.file_path))
|
|
377
377
|
),
|
|
378
378
|
oldContent !== null ? React.createElement(FileDiffViewer, {
|
|
@@ -383,7 +383,8 @@ function renderToolArgs(toolName, args, mcpToolInfo = null) {
|
|
|
383
383
|
newContent: args.new_content || '',
|
|
384
384
|
contextBefore: contextBefore,
|
|
385
385
|
contextAfter: contextAfter,
|
|
386
|
-
contextStartLine: contextStartLine
|
|
386
|
+
contextStartLine: contextStartLine,
|
|
387
|
+
showHeader: false
|
|
387
388
|
}) : React.createElement(Text, { color: 'gray' }, 'Loading...')
|
|
388
389
|
);
|
|
389
390
|
}
|
|
@@ -414,7 +415,7 @@ function renderToolArgs(toolName, args, mcpToolInfo = null) {
|
|
|
414
415
|
|
|
415
416
|
return React.createElement(Box, { flexDirection: 'column', marginTop: 0 },
|
|
416
417
|
React.createElement(Box, { marginBottom: 0 },
|
|
417
|
-
React.createElement(Text, { bold: true, color:
|
|
418
|
+
React.createElement(Text, { bold: true, color: theme.brand.light }, 'File '),
|
|
418
419
|
React.createElement(Text, { color: 'white' }, toDisplayPath(args.file_path))
|
|
419
420
|
),
|
|
420
421
|
diffData ? (
|
|
@@ -429,7 +430,8 @@ function renderToolArgs(toolName, args, mcpToolInfo = null) {
|
|
|
429
430
|
contextBefore: diffData.contextBefore,
|
|
430
431
|
contextAfter: diffData.contextAfter,
|
|
431
432
|
contextStartLine: diffData.contextStartLine,
|
|
432
|
-
isReplaceMode: true
|
|
433
|
+
isReplaceMode: true,
|
|
434
|
+
showHeader: false
|
|
433
435
|
})
|
|
434
436
|
) : React.createElement(Text, { color: 'gray' }, 'Loading...')
|
|
435
437
|
);
|
|
@@ -437,7 +439,7 @@ function renderToolArgs(toolName, args, mcpToolInfo = null) {
|
|
|
437
439
|
|
|
438
440
|
// 기타 도구
|
|
439
441
|
return React.createElement(Box, { flexDirection: 'column', marginTop: 0 },
|
|
440
|
-
React.createElement(Text, { bold: true, color:
|
|
442
|
+
React.createElement(Text, { bold: true, color: theme.brand.light }, 'Arguments'),
|
|
441
443
|
React.createElement(Box, {
|
|
442
444
|
borderStyle: 'single',
|
|
443
445
|
borderColor: 'gray',
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Colors - Color definitions for theming
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const defaultTheme = {
|
|
6
|
+
text: {
|
|
7
|
+
primary: '#E0E0E0',
|
|
8
|
+
secondary: '#888888',
|
|
9
|
+
accent: '#3fbe96',
|
|
10
|
+
link: '#3fbe96',
|
|
11
|
+
},
|
|
12
|
+
background: {
|
|
13
|
+
default: '#1E1E1E',
|
|
14
|
+
highlight: '#2D2D2D',
|
|
15
|
+
},
|
|
16
|
+
border: {
|
|
17
|
+
default: '#333333',
|
|
18
|
+
focused: '#333333',
|
|
19
|
+
},
|
|
20
|
+
ui: {
|
|
21
|
+
symbol: '#666666',
|
|
22
|
+
gradient: ['#00D9FF', '#7B68EE'],
|
|
23
|
+
},
|
|
24
|
+
status: {
|
|
25
|
+
error: '#FF0055',
|
|
26
|
+
warning: '#FFAA00',
|
|
27
|
+
success: '#00FF88',
|
|
28
|
+
info: '#00A8FF',
|
|
29
|
+
},
|
|
30
|
+
brand: {
|
|
31
|
+
dark: '#418972',
|
|
32
|
+
light: '#3fbe96',
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const currentTheme = defaultTheme;
|
|
37
|
+
|
|
38
|
+
export const theme = new Proxy({}, {
|
|
39
|
+
get(target, prop) {
|
|
40
|
+
return currentTheme[prop];
|
|
41
|
+
}
|
|
42
|
+
});
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import { render } from 'ink';
|
|
7
7
|
import { App } from './App.js';
|
|
8
|
-
import {
|
|
8
|
+
import { OutputRedirector } from './utils/outputRedirector.js';
|
|
9
9
|
import { createDebugLogger } from '../util/debug_log.js';
|
|
10
10
|
|
|
11
11
|
const debugLog = createDebugLogger('ui.log', 'index');
|
|
@@ -14,9 +14,9 @@ export function startUI({ onSubmit, onClearScreen, onExit, commands = [], model
|
|
|
14
14
|
debugLog(`startUI called - model: ${model}, version: ${version}, commands: ${commands.length}, initialHistory: ${initialHistory.length}`);
|
|
15
15
|
|
|
16
16
|
// Patch console methods to prevent interference with Ink rendering
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
debugLog('
|
|
17
|
+
const outputRedirector = new OutputRedirector();
|
|
18
|
+
outputRedirector.patch();
|
|
19
|
+
debugLog('OutputRedirector patched');
|
|
20
20
|
|
|
21
21
|
// Disable terminal line wrapping to reduce rendering artifacts
|
|
22
22
|
// This prevents the terminal from wrapping lines itself, letting Ink handle all wrapping
|
|
@@ -36,7 +36,7 @@ export function startUI({ onSubmit, onClearScreen, onExit, commands = [], model
|
|
|
36
36
|
}),
|
|
37
37
|
{
|
|
38
38
|
// Use patchConsole option to prevent console output from interfering
|
|
39
|
-
patchConsole: false, // We're handling this manually with
|
|
39
|
+
patchConsole: false, // We're handling this manually with OutputRedirector
|
|
40
40
|
// Don't exit on Ctrl+C - let the app handle it
|
|
41
41
|
exitOnCtrlC: false,
|
|
42
42
|
// Debug mode ON - prevents clearing terminal and preserves previous content
|
|
@@ -52,8 +52,8 @@ export function startUI({ onSubmit, onClearScreen, onExit, commands = [], model
|
|
|
52
52
|
debugLog('wrappedUnmount called - cleaning up UI');
|
|
53
53
|
// Re-enable line wrapping
|
|
54
54
|
process.stdout.write('\x1b[?7h');
|
|
55
|
-
|
|
56
|
-
debugLog('
|
|
55
|
+
outputRedirector.cleanup();
|
|
56
|
+
debugLog('OutputRedirector cleanup completed');
|
|
57
57
|
originalUnmount();
|
|
58
58
|
debugLog('UI unmounted');
|
|
59
59
|
};
|