aiexecode 1.0.157
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/LICENSE +68 -0
- package/README.md +347 -0
- package/config_template/mcp_config.json +3 -0
- package/config_template/package_name_store.json +5 -0
- package/config_template/settings.json +5 -0
- package/index.js +879 -0
- package/mcp-agent-lib/example/01-basic-usage.js +82 -0
- package/mcp-agent-lib/example/02-quick-start.js +52 -0
- package/mcp-agent-lib/example/03-http-server.js +76 -0
- package/mcp-agent-lib/example/04-multiple-servers.js +117 -0
- package/mcp-agent-lib/example/05-error-handling.js +116 -0
- package/mcp-agent-lib/example/06-resources-and-prompts.js +174 -0
- package/mcp-agent-lib/example/07-advanced-configuration.js +191 -0
- package/mcp-agent-lib/example/08-real-world-chatbot.js +331 -0
- package/mcp-agent-lib/example/README.md +346 -0
- package/mcp-agent-lib/index.js +19 -0
- package/mcp-agent-lib/init.sh +3 -0
- package/mcp-agent-lib/package-lock.json +1216 -0
- package/mcp-agent-lib/package.json +53 -0
- package/mcp-agent-lib/sampleFastMCPClient/client.py +25 -0
- package/mcp-agent-lib/sampleFastMCPClient/run.sh +3 -0
- package/mcp-agent-lib/sampleFastMCPServer/run.sh +3 -0
- package/mcp-agent-lib/sampleFastMCPServer/server.py +12 -0
- package/mcp-agent-lib/sampleFastMCPServerElicitationRequest/run.sh +3 -0
- package/mcp-agent-lib/sampleFastMCPServerElicitationRequest/server.py +43 -0
- package/mcp-agent-lib/sampleFastMCPServerRootsRequest/server.py +63 -0
- package/mcp-agent-lib/sampleMCPHost/index.js +386 -0
- package/mcp-agent-lib/sampleMCPHost/mcp_config.json +24 -0
- package/mcp-agent-lib/sampleMCPHostFeatures/elicitation.js +151 -0
- package/mcp-agent-lib/sampleMCPHostFeatures/index.js +166 -0
- package/mcp-agent-lib/sampleMCPHostFeatures/roots.js +197 -0
- package/mcp-agent-lib/src/mcp_client.js +1860 -0
- package/mcp-agent-lib/src/mcp_message_logger.js +517 -0
- package/package.json +72 -0
- package/payload_viewer/out/404/index.html +1 -0
- package/payload_viewer/out/404.html +1 -0
- package/payload_viewer/out/_next/static/chunks/060f9a97930f3d04.js +1 -0
- package/payload_viewer/out/_next/static/chunks/103c802c8f4a5ea1.js +1 -0
- package/payload_viewer/out/_next/static/chunks/16474fd6c6910c45.js +1 -0
- package/payload_viewer/out/_next/static/chunks/17722e3ac4e00587.js +1 -0
- package/payload_viewer/out/_next/static/chunks/305b077a9873cf54.js +1 -0
- package/payload_viewer/out/_next/static/chunks/4c1d05c6741c2bdd.js +5 -0
- package/payload_viewer/out/_next/static/chunks/538cc02e54714b23.js +1 -0
- package/payload_viewer/out/_next/static/chunks/6251fa5907d2b226.js +5 -0
- package/payload_viewer/out/_next/static/chunks/a6dad97d9634a72d.js +1 -0
- package/payload_viewer/out/_next/static/chunks/b6c0459f3789d25c.js +1 -0
- package/payload_viewer/out/_next/static/chunks/b75131b58f8ca46a.css +3 -0
- package/payload_viewer/out/_next/static/chunks/bd2dcf98c9b362f6.js +1 -0
- package/payload_viewer/out/_next/static/chunks/c8a542ae21335479.js +1 -0
- package/payload_viewer/out/_next/static/chunks/cdd12d5c1a5a6064.js +1 -0
- package/payload_viewer/out/_next/static/chunks/e411019f55d87c42.js +1 -0
- package/payload_viewer/out/_next/static/chunks/e60ef129113f6e24.js +1 -0
- package/payload_viewer/out/_next/static/chunks/f1ac9047ac4a3fde.js +1 -0
- package/payload_viewer/out/_next/static/chunks/turbopack-0ac29803ce3c3c7a.js +3 -0
- package/payload_viewer/out/_next/static/chunks/turbopack-89db4c64206a73e4.js +3 -0
- package/payload_viewer/out/_next/static/chunks/turbopack-a5b8235fa59d7119.js +3 -0
- package/payload_viewer/out/_next/static/media/4fa387ec64143e14-s.c1fdd6c2.woff2 +0 -0
- package/payload_viewer/out/_next/static/media/7178b3e590c64307-s.b97b3418.woff2 +0 -0
- package/payload_viewer/out/_next/static/media/797e433ab948586e-s.p.dbea232f.woff2 +0 -0
- package/payload_viewer/out/_next/static/media/8a480f0b521d4e75-s.8e0177b5.woff2 +0 -0
- package/payload_viewer/out/_next/static/media/bbc41e54d2fcbd21-s.799d8ef8.woff2 +0 -0
- package/payload_viewer/out/_next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2 +0 -0
- package/payload_viewer/out/_next/static/media/favicon.0b3bf435.ico +0 -0
- package/payload_viewer/out/_next/static/uqQYtKpKV7kCSkUbLgdfJ/_buildManifest.js +14 -0
- package/payload_viewer/out/_next/static/uqQYtKpKV7kCSkUbLgdfJ/_clientMiddlewareManifest.json +1 -0
- package/payload_viewer/out/_next/static/uqQYtKpKV7kCSkUbLgdfJ/_ssgManifest.js +1 -0
- package/payload_viewer/out/favicon.ico +0 -0
- package/payload_viewer/out/file.svg +1 -0
- package/payload_viewer/out/globe.svg +1 -0
- package/payload_viewer/out/index.html +1 -0
- package/payload_viewer/out/index.txt +23 -0
- package/payload_viewer/out/next.svg +1 -0
- package/payload_viewer/out/vercel.svg +1 -0
- package/payload_viewer/out/window.svg +1 -0
- package/payload_viewer/web_server.js +861 -0
- package/prompts/completion_judge.txt +128 -0
- package/prompts/orchestrator.txt +1213 -0
- package/src/LLMClient/client.js +1375 -0
- package/src/LLMClient/converters/input-normalizer.js +238 -0
- package/src/LLMClient/converters/responses-to-claude.js +503 -0
- package/src/LLMClient/converters/responses-to-gemini.js +648 -0
- package/src/LLMClient/converters/responses-to-ollama.js +348 -0
- package/src/LLMClient/converters/responses-to-zai.js +667 -0
- package/src/LLMClient/errors.js +398 -0
- package/src/LLMClient/index.js +36 -0
- package/src/ai_based/completion_judge.js +421 -0
- package/src/ai_based/orchestrator.js +527 -0
- package/src/ai_based/pip_package_installer.js +173 -0
- package/src/ai_based/pip_package_lookup.js +197 -0
- package/src/cli/mcp_cli.js +70 -0
- package/src/cli/mcp_commands.js +255 -0
- package/src/commands/agents.js +18 -0
- package/src/commands/apikey.js +55 -0
- package/src/commands/bg.js +140 -0
- package/src/commands/commands.js +56 -0
- package/src/commands/debug.js +54 -0
- package/src/commands/exit.js +19 -0
- package/src/commands/help.js +35 -0
- package/src/commands/mcp.js +128 -0
- package/src/commands/model.js +176 -0
- package/src/commands/setup.js +13 -0
- package/src/commands/skills.js +51 -0
- package/src/commands/tools.js +165 -0
- package/src/commands/viewer.js +147 -0
- package/src/config/ai_models.js +312 -0
- package/src/config/config.js +10 -0
- package/src/config/constants.js +71 -0
- package/src/config/feature_flags.js +15 -0
- package/src/frontend/App.js +1263 -0
- package/src/frontend/README.md +81 -0
- package/src/frontend/components/AutocompleteMenu.js +47 -0
- package/src/frontend/components/BackgroundProcessList.js +175 -0
- package/src/frontend/components/BlankLine.js +62 -0
- package/src/frontend/components/ConversationItem.js +893 -0
- package/src/frontend/components/CurrentModelView.js +43 -0
- package/src/frontend/components/FileDiffViewer.js +616 -0
- package/src/frontend/components/Footer.js +25 -0
- package/src/frontend/components/Header.js +42 -0
- package/src/frontend/components/HelpView.js +154 -0
- package/src/frontend/components/Input.js +344 -0
- package/src/frontend/components/LoadingIndicator.js +31 -0
- package/src/frontend/components/ModelListView.js +49 -0
- package/src/frontend/components/ModelUpdatedView.js +22 -0
- package/src/frontend/components/SessionSpinner.js +66 -0
- package/src/frontend/components/SetupWizard.js +242 -0
- package/src/frontend/components/StreamOutput.js +34 -0
- package/src/frontend/components/TodoList.js +56 -0
- package/src/frontend/components/ToolApprovalPrompt.js +452 -0
- package/src/frontend/design/themeColors.js +42 -0
- package/src/frontend/hooks/useCompletion.js +84 -0
- package/src/frontend/hooks/useFileCompletion.js +467 -0
- package/src/frontend/hooks/useKeypress.js +145 -0
- package/src/frontend/index.js +65 -0
- package/src/frontend/utils/GridRenderer.js +140 -0
- package/src/frontend/utils/InlineFormatter.js +156 -0
- package/src/frontend/utils/diffUtils.js +235 -0
- package/src/frontend/utils/inputBuffer.js +441 -0
- package/src/frontend/utils/markdownParser.js +377 -0
- package/src/frontend/utils/outputRedirector.js +47 -0
- package/src/frontend/utils/renderInkComponent.js +42 -0
- package/src/frontend/utils/syntaxHighlighter.js +149 -0
- package/src/frontend/utils/toolUIFormatter.js +261 -0
- package/src/system/agents_loader.js +170 -0
- package/src/system/ai_request.js +737 -0
- package/src/system/background_process.js +317 -0
- package/src/system/code_executer.js +1233 -0
- package/src/system/command_loader.js +40 -0
- package/src/system/command_parser.js +133 -0
- package/src/system/conversation_state.js +265 -0
- package/src/system/conversation_trimmer.js +265 -0
- package/src/system/custom_command_loader.js +395 -0
- package/src/system/file_integrity.js +466 -0
- package/src/system/import_analyzer.py +174 -0
- package/src/system/log.js +82 -0
- package/src/system/mcp_integration.js +304 -0
- package/src/system/output_helper.js +89 -0
- package/src/system/session.js +1393 -0
- package/src/system/session_memory.js +481 -0
- package/src/system/skill_loader.js +324 -0
- package/src/system/system_info.js +483 -0
- package/src/system/tool_approval.js +160 -0
- package/src/system/tool_registry.js +184 -0
- package/src/system/ui_events.js +279 -0
- package/src/tools/code_editor.js +792 -0
- package/src/tools/file_reader.js +385 -0
- package/src/tools/glob.js +263 -0
- package/src/tools/response_message.js +30 -0
- package/src/tools/ripgrep.js +554 -0
- package/src/tools/skill_tool.js +122 -0
- package/src/tools/todo_write.js +182 -0
- package/src/tools/web_download.py +74 -0
- package/src/tools/web_downloader.js +83 -0
- package/src/util/clone.js +174 -0
- package/src/util/config.js +203 -0
- package/src/util/config_migration.js +174 -0
- package/src/util/debug_log.js +49 -0
- package/src/util/exit_handler.js +53 -0
- package/src/util/file_reference_parser.js +132 -0
- package/src/util/mcp_config_manager.js +159 -0
- package/src/util/output_formatter.js +50 -0
- package/src/util/path_helper.js +27 -0
- package/src/util/path_validator.js +178 -0
- package/src/util/prompt_loader.js +184 -0
- package/src/util/rag_helper.js +101 -0
- package/src/util/safe_fs.js +645 -0
- package/src/util/setup_wizard.js +62 -0
- package/src/util/text_formatter.js +33 -0
- package/src/util/version_check.js +116 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { uiEvents } from '../system/ui_events.js';
|
|
2
|
+
import { formatAgentsMdSummary } from '../system/agents_loader.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* /agents 커맨드 - AGENTS.md 파일 조회
|
|
6
|
+
*
|
|
7
|
+
* 사용법:
|
|
8
|
+
* /agents - 작업 디렉토리 루트의 AGENTS.md 내용 표시
|
|
9
|
+
*/
|
|
10
|
+
export default {
|
|
11
|
+
name: 'agents',
|
|
12
|
+
description: 'Show AGENTS.md file content',
|
|
13
|
+
usage: '/agents',
|
|
14
|
+
handler: async (args, context) => {
|
|
15
|
+
const summary = await formatAgentsMdSummary();
|
|
16
|
+
uiEvents.addSystemMessage(summary);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { uiEvents } from '../system/ui_events.js';
|
|
2
|
+
import { loadSettings, saveSettings, SETTINGS_FILE } from '../util/config.js';
|
|
3
|
+
import { resetAIClients } from '../system/ai_request.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* /apikey 커맨드 - API 키 설정
|
|
7
|
+
*/
|
|
8
|
+
export default {
|
|
9
|
+
name: 'apikey',
|
|
10
|
+
description: 'Set API key',
|
|
11
|
+
usage: '/apikey <api-key>',
|
|
12
|
+
handler: async (args, context) => {
|
|
13
|
+
// 인자 확인
|
|
14
|
+
if (!args || args.length < 1) {
|
|
15
|
+
uiEvents.addSystemMessage(
|
|
16
|
+
`Please enter API key.\n\n` +
|
|
17
|
+
`Usage:\n` +
|
|
18
|
+
` /apikey <your-zai-api-key>`
|
|
19
|
+
);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
// 현재 설정 로드
|
|
25
|
+
const settings = await loadSettings();
|
|
26
|
+
|
|
27
|
+
const apiKey = args[0];
|
|
28
|
+
|
|
29
|
+
// API 키 업데이트
|
|
30
|
+
settings.API_KEY = apiKey;
|
|
31
|
+
process.env.API_KEY = apiKey;
|
|
32
|
+
|
|
33
|
+
// 설정 저장
|
|
34
|
+
await saveSettings(settings);
|
|
35
|
+
|
|
36
|
+
// AI 클라이언트 캐시 초기화 (다음 요청 시 새 설정 적용)
|
|
37
|
+
resetAIClients();
|
|
38
|
+
|
|
39
|
+
// 성공 메시지
|
|
40
|
+
const maskedKey = apiKey.length > 20
|
|
41
|
+
? `${apiKey.slice(0, 10)}...${apiKey.slice(-4)}`
|
|
42
|
+
: `${apiKey.slice(0, 6)}...`;
|
|
43
|
+
|
|
44
|
+
uiEvents.addSystemMessage(
|
|
45
|
+
`API configuration complete\n\n` +
|
|
46
|
+
`API Key: ${maskedKey}\n` +
|
|
47
|
+
`Saved to: ${SETTINGS_FILE}`
|
|
48
|
+
);
|
|
49
|
+
} catch (error) {
|
|
50
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
51
|
+
uiEvents.addErrorMessage(`API key configuration failed: ${errorMessage}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { listBackgroundProcesses, killBackgroundProcess, getBackgroundProcess } from '../system/background_process.js';
|
|
2
|
+
import { uiEvents } from '../system/ui_events.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* /bg 커맨드 - 백그라운드 프로세스 관리
|
|
6
|
+
*
|
|
7
|
+
* 사용법:
|
|
8
|
+
* /bg - 프로세스 목록 표시
|
|
9
|
+
* /bg list - 프로세스 목록 표시
|
|
10
|
+
* /bg kill <id> - 프로세스 종료
|
|
11
|
+
* /bg killall - 모든 실행 중인 프로세스 종료
|
|
12
|
+
*/
|
|
13
|
+
export default {
|
|
14
|
+
name: 'bg',
|
|
15
|
+
description: 'Manage background processes',
|
|
16
|
+
usage: '/bg [list|kill <id>|killall]',
|
|
17
|
+
handler: async (args, context) => {
|
|
18
|
+
const subcommand = args[0]?.toLowerCase() || 'list';
|
|
19
|
+
|
|
20
|
+
switch (subcommand) {
|
|
21
|
+
case 'list':
|
|
22
|
+
case 'ls': {
|
|
23
|
+
const processes = listBackgroundProcesses({ running: true });
|
|
24
|
+
if (processes.length === 0) {
|
|
25
|
+
uiEvents.addSystemMessage('No running background processes');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const lines = [
|
|
30
|
+
'**Background Processes**',
|
|
31
|
+
'| Status | ID | PID | Duration | Command |',
|
|
32
|
+
'|--------|-----|-----|----------|---------|'
|
|
33
|
+
];
|
|
34
|
+
for (const proc of processes) {
|
|
35
|
+
const status = proc.status === 'running' ? 'running' :
|
|
36
|
+
proc.status === 'completed' ? 'completed' :
|
|
37
|
+
proc.status === 'failed' ? 'failed' : 'cancelled';
|
|
38
|
+
const duration = formatDuration(proc.startedAt, proc.endedAt);
|
|
39
|
+
const cmd = proc.command.substring(0, 40) + (proc.command.length > 40 ? '...' : '');
|
|
40
|
+
lines.push(`| ${status} | ${proc.id} | ${proc.pid} | ${duration} | \`${cmd}\` |`);
|
|
41
|
+
}
|
|
42
|
+
const hasRunning = processes.some(p => p.status === 'running');
|
|
43
|
+
if (hasRunning) {
|
|
44
|
+
lines.push('To stop: `/bg kill <id>` or `/bg killall`');
|
|
45
|
+
}
|
|
46
|
+
uiEvents.addSystemMessage(lines.join('\n'));
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
case 'kill': {
|
|
51
|
+
const id = args[1];
|
|
52
|
+
if (!id) {
|
|
53
|
+
uiEvents.addErrorMessage('**Usage:** `/bg kill <process_id>`');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const proc = getBackgroundProcess(id);
|
|
58
|
+
if (!proc) {
|
|
59
|
+
uiEvents.addErrorMessage(`Process not found: \`${id}\``);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (proc.status !== 'running') {
|
|
64
|
+
uiEvents.addSystemMessage(`Process \`${id}\` is already ${proc.status}`);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const killed = killBackgroundProcess(id);
|
|
69
|
+
if (killed) {
|
|
70
|
+
uiEvents.addSystemMessage(`Killed process: \`${id}\` (pid: ${proc.pid})`);
|
|
71
|
+
} else {
|
|
72
|
+
uiEvents.addErrorMessage(`Failed to kill process: \`${id}\``);
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
case 'killall': {
|
|
78
|
+
const processes = listBackgroundProcesses({ running: true });
|
|
79
|
+
if (processes.length === 0) {
|
|
80
|
+
uiEvents.addSystemMessage('No running background processes');
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let killedCount = 0;
|
|
85
|
+
for (const proc of processes) {
|
|
86
|
+
if (killBackgroundProcess(proc.id)) {
|
|
87
|
+
killedCount++;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
uiEvents.addSystemMessage(`Killed **${killedCount}** background process(es)`);
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
case 'show': {
|
|
95
|
+
const id = args[1];
|
|
96
|
+
if (!id) {
|
|
97
|
+
uiEvents.addErrorMessage('**Usage:** `/bg show <process_id>`');
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const proc = getBackgroundProcess(id);
|
|
102
|
+
if (!proc) {
|
|
103
|
+
uiEvents.addErrorMessage(`Process not found: \`${id}\``);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const lines = [
|
|
108
|
+
`## Process: \`${proc.id}\``,
|
|
109
|
+
'',
|
|
110
|
+
`- **PID:** ${proc.pid}`,
|
|
111
|
+
`- **Status:** ${proc.status}`,
|
|
112
|
+
`- **Command:** \`${proc.command}\``,
|
|
113
|
+
`- **Started:** ${proc.startedAt.toISOString()}`,
|
|
114
|
+
proc.endedAt ? `- **Ended:** ${proc.endedAt.toISOString()}` : null,
|
|
115
|
+
proc.exitCode !== null ? `- **Exit Code:** ${proc.exitCode}` : null,
|
|
116
|
+
'',
|
|
117
|
+
proc.stdout ? `**Stdout (last 200 chars):**\n\`\`\`\n${proc.stdout.slice(-200)}\n\`\`\`` : null,
|
|
118
|
+
proc.stderr ? `**Stderr (last 200 chars):**\n\`\`\`\n${proc.stderr.slice(-200)}\n\`\`\`` : null,
|
|
119
|
+
].filter(Boolean);
|
|
120
|
+
|
|
121
|
+
uiEvents.addSystemMessage(lines.join('\n'));
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
default:
|
|
126
|
+
uiEvents.addErrorMessage(`Unknown subcommand: \`${subcommand}\`\n\n**Usage:** \`/bg [list|kill <id>|killall|show <id>]\``);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
function formatDuration(startedAt, endedAt) {
|
|
132
|
+
const end = endedAt ? new Date(endedAt) : new Date();
|
|
133
|
+
const start = new Date(startedAt);
|
|
134
|
+
const diffMs = end - start;
|
|
135
|
+
|
|
136
|
+
if (diffMs < 1000) return `${diffMs}ms`;
|
|
137
|
+
if (diffMs < 60000) return `${Math.round(diffMs / 1000)}s`;
|
|
138
|
+
if (diffMs < 3600000) return `${Math.round(diffMs / 60000)}m`;
|
|
139
|
+
return `${Math.round(diffMs / 3600000)}h`;
|
|
140
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { uiEvents } from '../system/ui_events.js';
|
|
2
|
+
import {
|
|
3
|
+
formatCustomCommandList,
|
|
4
|
+
findCustomCommandByName
|
|
5
|
+
} from '../system/custom_command_loader.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* /commands 커맨드 - 커스텀 커맨드 목록 조회 및 정보 확인
|
|
9
|
+
*
|
|
10
|
+
* 사용법:
|
|
11
|
+
* /commands - 모든 커스텀 커맨드 목록 표시
|
|
12
|
+
* /commands <name> - 특정 커맨드 상세 정보 표시
|
|
13
|
+
*/
|
|
14
|
+
export default {
|
|
15
|
+
name: 'commands',
|
|
16
|
+
description: 'List custom commands or show command details',
|
|
17
|
+
usage: '/commands [command-name]',
|
|
18
|
+
handler: async (args, context) => {
|
|
19
|
+
if (!args || args.length === 0) {
|
|
20
|
+
// 커맨드 목록 표시
|
|
21
|
+
const commandList = await formatCustomCommandList();
|
|
22
|
+
uiEvents.addSystemMessage(commandList);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 특정 커맨드 정보 표시
|
|
27
|
+
const commandName = args[0];
|
|
28
|
+
const command = await findCustomCommandByName(commandName);
|
|
29
|
+
|
|
30
|
+
if (!command) {
|
|
31
|
+
uiEvents.addSystemMessage(`Custom command not found: \`${commandName}\`\n\nUse \`/commands\` to see available commands.`);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const info = [
|
|
36
|
+
`## Command: \`${command.name}\``,
|
|
37
|
+
'',
|
|
38
|
+
`- **Source:** ${command.source}`,
|
|
39
|
+
`- **Path:** \`${command.path}\``,
|
|
40
|
+
command.argumentHint ? `- **Argument Hint:** ${command.argumentHint}` : null,
|
|
41
|
+
command.disableModelInvocation ? '- **Model Invocation:** Disabled (manual only)' : null,
|
|
42
|
+
'',
|
|
43
|
+
'### Frontmatter',
|
|
44
|
+
'```json',
|
|
45
|
+
JSON.stringify(command.frontmatter, null, 2),
|
|
46
|
+
'```',
|
|
47
|
+
'',
|
|
48
|
+
'### Content Preview',
|
|
49
|
+
'```',
|
|
50
|
+
command.content.substring(0, 500) + (command.content.length > 500 ? '...' : ''),
|
|
51
|
+
'```'
|
|
52
|
+
].filter(Boolean).join('\n');
|
|
53
|
+
|
|
54
|
+
uiEvents.addSystemMessage(info);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { uiEvents } from '../system/ui_events.js';
|
|
2
|
+
import { loadSettings, saveSettings, SETTINGS_FILE } from '../util/config.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* /debug 커맨드 - API 요청/응답 내용 표시 설정
|
|
6
|
+
*
|
|
7
|
+
* 사용법:
|
|
8
|
+
* /debug - 현재 설정 상태 표시
|
|
9
|
+
* /debug on - API payload 표시 켜기
|
|
10
|
+
* /debug off - API payload 표시 끄기
|
|
11
|
+
*/
|
|
12
|
+
export default {
|
|
13
|
+
name: 'debug',
|
|
14
|
+
description: 'Toggle API request/response payload display',
|
|
15
|
+
usage: '/debug [on|off]',
|
|
16
|
+
handler: async (args, context) => {
|
|
17
|
+
const settings = await loadSettings();
|
|
18
|
+
const currentValue = settings?.SHOW_API_PAYLOAD === true;
|
|
19
|
+
|
|
20
|
+
if (!args || args.length === 0) {
|
|
21
|
+
// 현재 상태 표시
|
|
22
|
+
const status = currentValue ? '**ON**' : '**OFF**';
|
|
23
|
+
const message = [
|
|
24
|
+
'## API Payload Display',
|
|
25
|
+
'',
|
|
26
|
+
`**Status:** ${status}`,
|
|
27
|
+
'',
|
|
28
|
+
'### Usage',
|
|
29
|
+
'- `/debug` - Show current status',
|
|
30
|
+
'- `/debug on` - Enable API payload display',
|
|
31
|
+
'- `/debug off` - Disable API payload display',
|
|
32
|
+
'',
|
|
33
|
+
`**Settings file:** \`${SETTINGS_FILE}\``
|
|
34
|
+
].join('\n');
|
|
35
|
+
|
|
36
|
+
uiEvents.addSystemMessage(message);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const action = args[0]?.toLowerCase();
|
|
41
|
+
|
|
42
|
+
if (action === 'on' || action === 'true' || action === '1') {
|
|
43
|
+
settings.SHOW_API_PAYLOAD = true;
|
|
44
|
+
await saveSettings(settings);
|
|
45
|
+
uiEvents.addSystemMessage('API Payload Display: **ON**\n\nAI request/response content will now be displayed.');
|
|
46
|
+
} else if (action === 'off' || action === 'false' || action === '0') {
|
|
47
|
+
settings.SHOW_API_PAYLOAD = false;
|
|
48
|
+
await saveSettings(settings);
|
|
49
|
+
uiEvents.addSystemMessage('API Payload Display: **OFF**\n\nAI request/response content will be hidden.');
|
|
50
|
+
} else {
|
|
51
|
+
uiEvents.addSystemMessage(`Unknown option: \`${action}\`\n\n**Usage:** \`/debug [on|off]\``);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { performExit } from '../util/exit_handler.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* /exit 커맨드 - 프로그램 종료
|
|
5
|
+
*/
|
|
6
|
+
export default {
|
|
7
|
+
name: 'exit',
|
|
8
|
+
description: 'Exit the program',
|
|
9
|
+
usage: '/exit',
|
|
10
|
+
handler: async (args, context) => {
|
|
11
|
+
const { mcpIntegration, uiInstance } = context;
|
|
12
|
+
|
|
13
|
+
await performExit({
|
|
14
|
+
mcpIntegration,
|
|
15
|
+
uiInstance,
|
|
16
|
+
showMessages: true
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { uiEvents } from '../system/ui_events.js';
|
|
3
|
+
import { renderInkComponent } from '../frontend/utils/renderInkComponent.js';
|
|
4
|
+
import { HelpView } from '../frontend/components/HelpView.js';
|
|
5
|
+
import { discoverAllCustomCommands } from '../system/custom_command_loader.js';
|
|
6
|
+
import { discoverAllSkills } from '../system/skill_loader.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* /help 커맨드 - 사용 가능한 커맨드 목록 표시
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'help',
|
|
13
|
+
description: 'Show available commands',
|
|
14
|
+
usage: '/help',
|
|
15
|
+
handler: async (args, context) => {
|
|
16
|
+
const { commandRegistry } = context;
|
|
17
|
+
|
|
18
|
+
const commands = commandRegistry.getCommands();
|
|
19
|
+
|
|
20
|
+
// 커스텀 커맨드 로드
|
|
21
|
+
const customCommands = await discoverAllCustomCommands();
|
|
22
|
+
|
|
23
|
+
// 스킬 로드
|
|
24
|
+
const skills = await discoverAllSkills();
|
|
25
|
+
|
|
26
|
+
const component = React.createElement(HelpView, {
|
|
27
|
+
commands,
|
|
28
|
+
customCommands,
|
|
29
|
+
skills
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const output = await renderInkComponent(component);
|
|
33
|
+
uiEvents.addSystemMessage(output);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { uiEvents } from '../system/ui_events.js';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* /mcp 커맨드 - AI Agent 세션 내에서 MCP 서버 상태 조회
|
|
6
|
+
*
|
|
7
|
+
* AI Agent 실행 중 사용자가 입력하는 대화형 명령어
|
|
8
|
+
* 현재 연결된 MCP 서버 목록과 사용 가능한 도구들을 표시
|
|
9
|
+
*
|
|
10
|
+
* 사용법:
|
|
11
|
+
* /mcp - 모든 MCP 서버 목록 표시
|
|
12
|
+
* /mcp <서버이름> - 특정 서버의 도구 목록 상세 표시
|
|
13
|
+
*/
|
|
14
|
+
export default {
|
|
15
|
+
name: 'mcp',
|
|
16
|
+
description: 'Show connected MCP servers, tools, and configuration',
|
|
17
|
+
usage: '/mcp [server-name]',
|
|
18
|
+
handler: async (args, context) => {
|
|
19
|
+
const { mcpIntegration } = context;
|
|
20
|
+
|
|
21
|
+
// MCP Integration이 초기화되지 않은 경우 (설정된 서버가 없거나 초기화 실패)
|
|
22
|
+
if (!mcpIntegration) {
|
|
23
|
+
uiEvents.addSystemMessage('MCP Integration not available');
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 현재 연결된 MCP 서버 목록 조회
|
|
28
|
+
const servers = mcpIntegration.getConnectedServers();
|
|
29
|
+
|
|
30
|
+
if (servers.length === 0) {
|
|
31
|
+
uiEvents.addSystemMessage('No MCP servers configured');
|
|
32
|
+
uiEvents.addSystemMessage('Use CLI: aiexecode mcp add --transport stdio <name> -- <cmd>');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 인자로 특정 서버 이름이 전달된 경우 해당 서버 상세 정보 표시
|
|
37
|
+
const serverName = args[0];
|
|
38
|
+
if (serverName) {
|
|
39
|
+
showServerDetail(mcpIntegration, servers, serverName);
|
|
40
|
+
} else {
|
|
41
|
+
// 인자 없이 /mcp만 입력한 경우 전체 서버 목록 표시
|
|
42
|
+
showServerList(servers);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 연결된 모든 MCP 서버 목록을 간략하게 표시
|
|
49
|
+
*/
|
|
50
|
+
function showServerList(servers) {
|
|
51
|
+
let output = '# MCP Servers\n\n';
|
|
52
|
+
|
|
53
|
+
servers.forEach(server => {
|
|
54
|
+
const statusIcon = server.status === 'connected' ? '✓' : '✗';
|
|
55
|
+
const statusText = server.status === 'connected' ? 'Connected' : 'Disconnected';
|
|
56
|
+
output += `- **${server.name}** ${statusIcon} ${statusText} • ${server.toolCount} tools\n`;
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
output += '\n> Use `/mcp <server-name>` to see tools';
|
|
60
|
+
|
|
61
|
+
uiEvents.addSystemMessage(output);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 특정 MCP 서버의 상세 정보 및 도구 목록 표시
|
|
66
|
+
* 각 도구의 이름, 설명, 필수/선택 파라미터 정보 포함
|
|
67
|
+
*/
|
|
68
|
+
function showServerDetail(mcpIntegration, servers, serverName) {
|
|
69
|
+
const server = servers.find(s => s.name === serverName);
|
|
70
|
+
|
|
71
|
+
if (!server) {
|
|
72
|
+
uiEvents.addSystemMessage(`Server '${serverName}' not found`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// 전체 도구 스키마 조회
|
|
77
|
+
const toolSchemas = mcpIntegration.getToolSchemas();
|
|
78
|
+
|
|
79
|
+
// 설명 문자열에서 서버 이름을 추출하여 해당 서버의 도구만 필터링
|
|
80
|
+
// 형식: "[서버이름 MCP] - 설명"
|
|
81
|
+
const serverTools = toolSchemas.filter(tool => {
|
|
82
|
+
const match = tool.description?.match(/^\[(.+?) MCP\]/);
|
|
83
|
+
return match && match[1] === serverName;
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const statusIcon = server.status === 'connected' ? '✓' : '✗';
|
|
87
|
+
const statusText = server.status === 'connected' ? 'Connected' : 'Disconnected';
|
|
88
|
+
|
|
89
|
+
let output = `# ${server.name}\n\n`;
|
|
90
|
+
output += `**Status:** ${statusIcon} ${statusText}\n`;
|
|
91
|
+
output += `**Tools:** ${serverTools.length}\n\n`;
|
|
92
|
+
|
|
93
|
+
if (serverTools.length > 0) {
|
|
94
|
+
output += '## Available Tools\n\n';
|
|
95
|
+
|
|
96
|
+
serverTools.forEach((tool, idx) => {
|
|
97
|
+
// 도구 설명에서 "[서버이름 MCP] - " 접두사 제거
|
|
98
|
+
const desc = tool.description?.replace(/^\[.+?\] - /, '') || '';
|
|
99
|
+
output += `### ${idx + 1}. \`${tool.name}\`\n\n`;
|
|
100
|
+
|
|
101
|
+
if (desc) {
|
|
102
|
+
output += `${desc}\n\n`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 도구의 파라미터 정보 표시
|
|
106
|
+
const params = tool.parameters?.properties || {};
|
|
107
|
+
const required = tool.parameters?.required || [];
|
|
108
|
+
const paramNames = Object.keys(params);
|
|
109
|
+
|
|
110
|
+
if (paramNames.length > 0) {
|
|
111
|
+
const requiredParams = paramNames.filter(p => required.includes(p));
|
|
112
|
+
const optionalParams = paramNames.filter(p => !required.includes(p));
|
|
113
|
+
|
|
114
|
+
if (requiredParams.length > 0) {
|
|
115
|
+
output += `**Required:** \`${requiredParams.join('`, `')}\`\n`;
|
|
116
|
+
}
|
|
117
|
+
if (optionalParams.length > 0) {
|
|
118
|
+
output += `**Optional:** \`${optionalParams.join('`, `')}\`\n`;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
output += '\n';
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// UI 시스템에 메시지 전달하여 사용자에게 표시
|
|
127
|
+
uiEvents.addSystemMessage(output);
|
|
128
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { uiEvents } from '../system/ui_events.js';
|
|
3
|
+
import { loadSettings, saveSettings, SETTINGS_FILE, getDefaultBaseUrlForProvider } from '../util/config.js';
|
|
4
|
+
import { resetAIClients } from '../system/ai_request.js';
|
|
5
|
+
import { AI_MODELS, getModelsByProvider, DEFAULT_MODEL, ENABLED_PROVIDERS, isModelEnabled } from '../config/ai_models.js';
|
|
6
|
+
import { renderInkComponent } from '../frontend/utils/renderInkComponent.js';
|
|
7
|
+
import { ModelListView } from '../frontend/components/ModelListView.js';
|
|
8
|
+
import { CurrentModelView } from '../frontend/components/CurrentModelView.js';
|
|
9
|
+
import { ModelUpdatedView } from '../frontend/components/ModelUpdatedView.js';
|
|
10
|
+
|
|
11
|
+
// 모델 ID로 provider 찾기
|
|
12
|
+
function getProviderForModel(modelId) {
|
|
13
|
+
const modelInfo = AI_MODELS[modelId];
|
|
14
|
+
return modelInfo ? modelInfo.provider : null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// 모든 모델 목록 표시 (공식 지원 provider만)
|
|
18
|
+
async function listAllModels() {
|
|
19
|
+
// 공식 지원 provider만 사용
|
|
20
|
+
const providers = ENABLED_PROVIDERS;
|
|
21
|
+
|
|
22
|
+
// provider별로 모델 그룹화
|
|
23
|
+
const modelsByProvider = {};
|
|
24
|
+
providers.forEach(provider => {
|
|
25
|
+
const modelIds = getModelsByProvider(provider);
|
|
26
|
+
modelsByProvider[provider] = modelIds.map(id => ({
|
|
27
|
+
id,
|
|
28
|
+
...AI_MODELS[id]
|
|
29
|
+
}));
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const component = React.createElement(ModelListView, {
|
|
33
|
+
modelsByProvider
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const output = await renderInkComponent(component);
|
|
37
|
+
return output;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 현재 설정된 모델 표시
|
|
41
|
+
async function showCurrentModel() {
|
|
42
|
+
try {
|
|
43
|
+
const settings = await loadSettings();
|
|
44
|
+
const currentModel = settings?.MODEL || DEFAULT_MODEL;
|
|
45
|
+
const modelInfo = AI_MODELS[currentModel];
|
|
46
|
+
const provider = modelInfo?.provider || 'unknown';
|
|
47
|
+
|
|
48
|
+
const component = React.createElement(CurrentModelView, {
|
|
49
|
+
provider,
|
|
50
|
+
modelId: currentModel,
|
|
51
|
+
modelInfo
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const output = await renderInkComponent(component);
|
|
55
|
+
return output;
|
|
56
|
+
} catch (error) {
|
|
57
|
+
return `Failed to retrieve current model information: ${error.message}`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* /model 커맨드 - AI 모델 선택
|
|
63
|
+
*/
|
|
64
|
+
export default {
|
|
65
|
+
name: 'model',
|
|
66
|
+
description: 'Select AI model',
|
|
67
|
+
usage: '/model [model-id] or /model list',
|
|
68
|
+
handler: async (args, context) => {
|
|
69
|
+
// 인자가 없으면 현재 모델 표시
|
|
70
|
+
if (!args || args.length === 0) {
|
|
71
|
+
const message = await showCurrentModel();
|
|
72
|
+
uiEvents.addSystemMessage(message);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const command = args[0].toLowerCase();
|
|
77
|
+
|
|
78
|
+
// list 명령어
|
|
79
|
+
if (command === 'list' || command === 'ls') {
|
|
80
|
+
const message = await listAllModels();
|
|
81
|
+
uiEvents.addSystemMessage(message);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 모델 선택
|
|
86
|
+
const modelId = args[0];
|
|
87
|
+
const provider = getProviderForModel(modelId);
|
|
88
|
+
|
|
89
|
+
if (!provider) {
|
|
90
|
+
uiEvents.addSystemMessage(
|
|
91
|
+
`Unsupported model: ${modelId}\n\n` +
|
|
92
|
+
`Use \`/model list\` to see available models.`
|
|
93
|
+
);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 공식 지원 provider 확인
|
|
98
|
+
if (!isModelEnabled(modelId)) {
|
|
99
|
+
uiEvents.addSystemMessage(
|
|
100
|
+
`Model not available: ${modelId}\n\n` +
|
|
101
|
+
`This model is not officially supported.\n` +
|
|
102
|
+
`Use \`/model list\` to see available models.`
|
|
103
|
+
);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
// 현재 설정 로드
|
|
109
|
+
const settings = await loadSettings();
|
|
110
|
+
|
|
111
|
+
// 모델 업데이트
|
|
112
|
+
settings.MODEL = modelId;
|
|
113
|
+
process.env.MODEL = modelId;
|
|
114
|
+
|
|
115
|
+
// Provider별 BASE_URL 자동 설정
|
|
116
|
+
const defaultBaseUrl = getDefaultBaseUrlForProvider(provider);
|
|
117
|
+
if (defaultBaseUrl) {
|
|
118
|
+
// Z.AI 등 특정 provider는 BASE_URL 자동 설정
|
|
119
|
+
settings.BASE_URL = defaultBaseUrl;
|
|
120
|
+
process.env.BASE_URL = defaultBaseUrl;
|
|
121
|
+
} else if (provider !== 'zai') {
|
|
122
|
+
// 다른 provider로 변경 시 BASE_URL 초기화 (Z.AI에서 다른 모델로 변경)
|
|
123
|
+
if (settings.BASE_URL === 'https://api.z.ai/api/anthropic') {
|
|
124
|
+
settings.BASE_URL = '';
|
|
125
|
+
delete process.env.BASE_URL;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// 설정 저장
|
|
130
|
+
await saveSettings(settings);
|
|
131
|
+
|
|
132
|
+
// AI 클라이언트 캐시 초기화 (다음 요청 시 새 설정 적용)
|
|
133
|
+
resetAIClients();
|
|
134
|
+
|
|
135
|
+
// UI 모델 표시 업데이트
|
|
136
|
+
uiEvents.emit('model:changed', { model: modelId });
|
|
137
|
+
|
|
138
|
+
// 성공 메시지
|
|
139
|
+
const modelInfo = AI_MODELS[modelId];
|
|
140
|
+
|
|
141
|
+
// Provider별 경고 메시지 구성
|
|
142
|
+
let warning = null;
|
|
143
|
+
if (!settings.API_KEY) {
|
|
144
|
+
// Provider별 API 키 안내 (공식 지원 provider만)
|
|
145
|
+
const apiKeyHints = {
|
|
146
|
+
'zai': 'Set your Z.AI API key with: `/apikey <your-key>`'
|
|
147
|
+
};
|
|
148
|
+
warning = {
|
|
149
|
+
message: 'API key is not configured.',
|
|
150
|
+
hint: apiKeyHints[provider] || 'Set your API key with: `/apikey <your-key>`'
|
|
151
|
+
};
|
|
152
|
+
} else if (provider === 'zai') {
|
|
153
|
+
// Z.AI 모델 선택 시 추가 안내
|
|
154
|
+
warning = {
|
|
155
|
+
message: `BASE_URL automatically set to: ${defaultBaseUrl}`,
|
|
156
|
+
hint: 'Ensure your API key is valid for Z.AI service.'
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const component = React.createElement(ModelUpdatedView, {
|
|
161
|
+
provider,
|
|
162
|
+
modelId,
|
|
163
|
+
modelInfo,
|
|
164
|
+
settingsFile: SETTINGS_FILE,
|
|
165
|
+
warning
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const message = await renderInkComponent(component);
|
|
169
|
+
uiEvents.addSystemMessage(message);
|
|
170
|
+
} catch (error) {
|
|
171
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
172
|
+
uiEvents.addErrorMessage(`Failed to update model: ${errorMessage}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|