deeper-cli 1.0.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.
Files changed (188) hide show
  1. package/README.md +254 -0
  2. package/dist/cli/index.d.ts +1 -0
  3. package/dist/cli/index.js +12067 -0
  4. package/dist/cli/index.js.map +1 -0
  5. package/dist/index.d.ts +415 -0
  6. package/dist/index.js +1599 -0
  7. package/dist/index.js.map +1 -0
  8. package/docs/superpowers/plans/2026-05-14-deepercode-implementation.md +24 -0
  9. package/docs/superpowers/plans/2026-05-14-deepercode-plan.md +1248 -0
  10. package/docs/superpowers/specs/2026-05-14-deepercode-design.md +560 -0
  11. package/package.json +60 -0
  12. package/src/cli/bootstrap.ts +69 -0
  13. package/src/cli/chat-repl.ts +932 -0
  14. package/src/cli/commands/chat.ts +39 -0
  15. package/src/cli/commands/chat.tsx +39 -0
  16. package/src/cli/commands/config.ts +133 -0
  17. package/src/cli/commands/mcp.ts +172 -0
  18. package/src/cli/commands/run.ts +147 -0
  19. package/src/cli/commands/skill.ts +152 -0
  20. package/src/cli/index.ts +184 -0
  21. package/src/core/bugscan.ts +145 -0
  22. package/src/core/config.ts +285 -0
  23. package/src/core/constants.ts +49 -0
  24. package/src/core/eventbus.ts +202 -0
  25. package/src/core/logger.ts +109 -0
  26. package/src/core/storage.ts +96 -0
  27. package/src/index.ts +26 -0
  28. package/src/mcp/ConfigLoader.ts +74 -0
  29. package/src/mcp/MCPClient.ts +326 -0
  30. package/src/mcp/ResourceAdapter.ts +58 -0
  31. package/src/mcp/SSETransport.ts +133 -0
  32. package/src/mcp/StdioTransport.ts +116 -0
  33. package/src/mcp/ToolAdapter.ts +71 -0
  34. package/src/mcp/types.ts +58 -0
  35. package/src/memory/xmemory.ts +275 -0
  36. package/src/model/DeepSeekClient.ts +292 -0
  37. package/src/model/MessageBuilder.ts +155 -0
  38. package/src/model/RetryManager.ts +82 -0
  39. package/src/model/StreamHandler.ts +158 -0
  40. package/src/model/types.ts +86 -0
  41. package/src/skills/SkillCreator.ts +153 -0
  42. package/src/skills/SkillEngine.ts +158 -0
  43. package/src/skills/SkillExecutor.ts +107 -0
  44. package/src/skills/SkillLoader.ts +182 -0
  45. package/src/skills/SkillRegistry.ts +73 -0
  46. package/src/skills/SkillTrigger.ts +82 -0
  47. package/src/skills/types.ts +28 -0
  48. package/src/tools/ToolExecutor.ts +103 -0
  49. package/src/tools/ToolRegistry.ts +71 -0
  50. package/src/tools/ToolValidator.ts +103 -0
  51. package/src/tools/builtin/ai/context_summarize.ts +76 -0
  52. package/src/tools/builtin/ai/memory_store.ts +86 -0
  53. package/src/tools/builtin/ai/prompt_template.ts +71 -0
  54. package/src/tools/builtin/ai/skill_create.ts +53 -0
  55. package/src/tools/builtin/ai/subagent.ts +39 -0
  56. package/src/tools/builtin/ai/todo_manager.ts +157 -0
  57. package/src/tools/builtin/ai/token_count.ts +196 -0
  58. package/src/tools/builtin/ai/tool_create.ts +52 -0
  59. package/src/tools/builtin/code/analyze_deps.ts +72 -0
  60. package/src/tools/builtin/code/bug_scan.ts +80 -0
  61. package/src/tools/builtin/code/code_metrics.ts +111 -0
  62. package/src/tools/builtin/code/extract_function.ts +86 -0
  63. package/src/tools/builtin/code/format_code.ts +57 -0
  64. package/src/tools/builtin/code/generate_code.ts +75 -0
  65. package/src/tools/builtin/code/import_organizer.ts +82 -0
  66. package/src/tools/builtin/code/lint_code.ts +48 -0
  67. package/src/tools/builtin/code/parse_ast.ts +86 -0
  68. package/src/tools/builtin/code/refactor_code.ts +63 -0
  69. package/src/tools/builtin/code/type_check.ts +48 -0
  70. package/src/tools/builtin/data/chart_generate.ts +62 -0
  71. package/src/tools/builtin/data/csv_parse.ts +56 -0
  72. package/src/tools/builtin/data/data_diff.ts +79 -0
  73. package/src/tools/builtin/data/data_transform.ts +74 -0
  74. package/src/tools/builtin/data/data_validate.ts +75 -0
  75. package/src/tools/builtin/data/json_parse.ts +71 -0
  76. package/src/tools/builtin/data/template_render.ts +58 -0
  77. package/src/tools/builtin/data/toml_parse.ts +42 -0
  78. package/src/tools/builtin/data/xml_parse.ts +79 -0
  79. package/src/tools/builtin/data/yaml_parse.ts +42 -0
  80. package/src/tools/builtin/database/db_backup.ts +53 -0
  81. package/src/tools/builtin/database/db_restore.ts +51 -0
  82. package/src/tools/builtin/database/db_schema.ts +66 -0
  83. package/src/tools/builtin/database/nosql_query.ts +50 -0
  84. package/src/tools/builtin/database/orm_generate.ts +66 -0
  85. package/src/tools/builtin/database/redis_command.ts +46 -0
  86. package/src/tools/builtin/database/sql_migrate.ts +55 -0
  87. package/src/tools/builtin/database/sql_query.ts +60 -0
  88. package/src/tools/builtin/filesystem/batch_read.ts +56 -0
  89. package/src/tools/builtin/filesystem/batch_write.ts +67 -0
  90. package/src/tools/builtin/filesystem/copy_file.ts +36 -0
  91. package/src/tools/builtin/filesystem/create_dir.ts +30 -0
  92. package/src/tools/builtin/filesystem/delete_file.ts +30 -0
  93. package/src/tools/builtin/filesystem/diff_files.ts +47 -0
  94. package/src/tools/builtin/filesystem/edit_file.ts +47 -0
  95. package/src/tools/builtin/filesystem/file_info.ts +52 -0
  96. package/src/tools/builtin/filesystem/glob_find.ts +44 -0
  97. package/src/tools/builtin/filesystem/list_dir.ts +51 -0
  98. package/src/tools/builtin/filesystem/merge_files.ts +44 -0
  99. package/src/tools/builtin/filesystem/move_file.ts +37 -0
  100. package/src/tools/builtin/filesystem/read_file.ts +55 -0
  101. package/src/tools/builtin/filesystem/watch_file.ts +33 -0
  102. package/src/tools/builtin/filesystem/write_file.ts +45 -0
  103. package/src/tools/builtin/index.ts +244 -0
  104. package/src/tools/builtin/network/api_call.ts +79 -0
  105. package/src/tools/builtin/network/browser_action.ts +54 -0
  106. package/src/tools/builtin/network/check_url.ts +59 -0
  107. package/src/tools/builtin/network/download_file.ts +64 -0
  108. package/src/tools/builtin/network/graphql_query.ts +46 -0
  109. package/src/tools/builtin/network/http_request.ts +61 -0
  110. package/src/tools/builtin/network/parse_html.ts +101 -0
  111. package/src/tools/builtin/network/proxy_request.ts +53 -0
  112. package/src/tools/builtin/network/screenshot_page.ts +58 -0
  113. package/src/tools/builtin/network/web_fetch.ts +70 -0
  114. package/src/tools/builtin/network/web_search.ts +128 -0
  115. package/src/tools/builtin/network/websocket_connect.ts +70 -0
  116. package/src/tools/builtin/project/build_project.ts +68 -0
  117. package/src/tools/builtin/project/config_manage.ts +99 -0
  118. package/src/tools/builtin/project/coverage_report.ts +59 -0
  119. package/src/tools/builtin/project/docker_manage.ts +90 -0
  120. package/src/tools/builtin/project/env_manage.ts +88 -0
  121. package/src/tools/builtin/project/npm_manage.ts +71 -0
  122. package/src/tools/builtin/project/project_init.ts +59 -0
  123. package/src/tools/builtin/project/run_test.ts +74 -0
  124. package/src/tools/builtin/search/codebase_search.ts +76 -0
  125. package/src/tools/builtin/search/find_definition.ts +84 -0
  126. package/src/tools/builtin/search/find_references.ts +75 -0
  127. package/src/tools/builtin/search/fuzzy_find.ts +75 -0
  128. package/src/tools/builtin/search/grep_search.ts +90 -0
  129. package/src/tools/builtin/search/regex_find.ts +91 -0
  130. package/src/tools/builtin/search/search_docs.ts +51 -0
  131. package/src/tools/builtin/search/search_package.ts +50 -0
  132. package/src/tools/builtin/search/symbol_search.ts +82 -0
  133. package/src/tools/builtin/search/text_search.ts +63 -0
  134. package/src/tools/builtin/security/decrypt_file.ts +54 -0
  135. package/src/tools/builtin/security/encrypt_file.ts +52 -0
  136. package/src/tools/builtin/security/hash_generate.ts +48 -0
  137. package/src/tools/builtin/security/jwt_decode.ts +53 -0
  138. package/src/tools/builtin/security/secret_scan.ts +82 -0
  139. package/src/tools/builtin/security/vulnerability_check.ts +71 -0
  140. package/src/tools/builtin/shell/background_terminal.ts +38 -0
  141. package/src/tools/builtin/shell/check_status.ts +48 -0
  142. package/src/tools/builtin/shell/interactive_terminal.ts +31 -0
  143. package/src/tools/builtin/shell/kill_terminal.ts +29 -0
  144. package/src/tools/builtin/shell/list_terminals.ts +61 -0
  145. package/src/tools/builtin/shell/pipe_commands.ts +55 -0
  146. package/src/tools/builtin/shell/process-pool.ts +150 -0
  147. package/src/tools/builtin/shell/run_async.ts +73 -0
  148. package/src/tools/builtin/shell/run_command.ts +60 -0
  149. package/src/tools/builtin/shell/send_ctrl_keys.ts +43 -0
  150. package/src/tools/builtin/shell/send_keys.ts +36 -0
  151. package/src/tools/builtin/shell/send_text.ts +35 -0
  152. package/src/tools/builtin/shell/shell_script.ts +65 -0
  153. package/src/tools/builtin/shell/stop_command.ts +40 -0
  154. package/src/tools/builtin/shell/terminal_resize.ts +31 -0
  155. package/src/tools/builtin/shell/terminal_screenshot.ts +28 -0
  156. package/src/tools/builtin/system/log_viewer.ts +89 -0
  157. package/src/tools/builtin/system/notify_user.ts +55 -0
  158. package/src/tools/builtin/system/process_list.ts +66 -0
  159. package/src/tools/builtin/system/resource_monitor.ts +66 -0
  160. package/src/tools/builtin/system/system_info.ts +41 -0
  161. package/src/tools/tool-types.ts +97 -0
  162. package/src/ui/AgentTree.tsx +98 -0
  163. package/src/ui/App.tsx +46 -0
  164. package/src/ui/ChatView.tsx +278 -0
  165. package/src/ui/ConfirmDialog.tsx +68 -0
  166. package/src/ui/DiffView.tsx +64 -0
  167. package/src/ui/FilePreview.tsx +59 -0
  168. package/src/ui/InputBox.tsx +267 -0
  169. package/src/ui/MessageBubble.tsx +30 -0
  170. package/src/ui/Spinner.tsx +35 -0
  171. package/src/ui/StatusBar.tsx +41 -0
  172. package/src/ui/ToolCallCard.tsx +73 -0
  173. package/src/ui/ansi.ts +50 -0
  174. package/src/ui/markdown.ts +238 -0
  175. package/src/ui/themes/dark.ts +4 -0
  176. package/src/ui/themes/default.ts +25 -0
  177. package/src/ui/themes/light.ts +14 -0
  178. package/tests/unit/BuiltinTools.test.ts +129 -0
  179. package/tests/unit/BuiltinToolsIntegration.test.ts +111 -0
  180. package/tests/unit/FilesystemTools.test.ts +211 -0
  181. package/tests/unit/SkillLoader.test.ts +141 -0
  182. package/tests/unit/SkillRegistry.test.ts +113 -0
  183. package/tests/unit/ToolExecutor.test.ts +160 -0
  184. package/tests/unit/ToolRegistry.test.ts +103 -0
  185. package/tests/unit/ToolValidator.test.ts +137 -0
  186. package/tsconfig.json +28 -0
  187. package/tsup.config.ts +17 -0
  188. package/vitest.config.ts +20 -0
@@ -0,0 +1,39 @@
1
+ import { getConfig, loadConfig } from '../../core/config.ts';
2
+
3
+ interface ChatOptions {
4
+ model?: string;
5
+ apiKey?: string;
6
+ verbose?: boolean;
7
+ autoRun?: string;
8
+ }
9
+
10
+ export async function chat(opts: ChatOptions = {}): Promise<void> {
11
+ const config = getConfig() || loadConfig();
12
+
13
+ const apiKey = opts.apiKey || config.apiKey || process.env.DEEPSEEK_API_KEY || '';
14
+ if (!apiKey) {
15
+ console.error('❌ 未设置 API Key');
16
+ console.error('');
17
+ console.error(' 请运行以下命令之一:');
18
+ console.error(' deeper config set api_key "sk-你的密钥"');
19
+ console.error(' 或设置环境变量: set DEEPSEEK_API_KEY=sk-你的密钥');
20
+ console.error('');
21
+ console.error(' 获取密钥: https://platform.deepseek.com');
22
+ process.exit(1);
23
+ }
24
+
25
+ const model = opts.model || config.model || 'deepseek-v4-pro';
26
+ const baseUrl = config.baseUrl || 'https://api.deepseek.com';
27
+ const isFlash = model.includes('flash');
28
+
29
+ const { startRepl } = await import('../chat-repl.js');
30
+ await startRepl({
31
+ apiKey,
32
+ model,
33
+ baseUrl,
34
+ maxTokens: 8192,
35
+ temperature: config.temperature ?? (isFlash ? 0.3 : 0.7),
36
+ thinkEnabled: config.thinkEnabled ?? !isFlash,
37
+ thinkBudget: config.thinkBudget ?? (isFlash ? 0 : 16000),
38
+ });
39
+ }
@@ -0,0 +1,39 @@
1
+ import { render } from 'ink';
2
+ import { App } from '../../ui/App.tsx';
3
+ import { bootstrap } from '../bootstrap.ts';
4
+
5
+ interface ChatOptions {
6
+ model?: string;
7
+ apiKey?: string;
8
+ verbose?: boolean;
9
+ autoRun?: string;
10
+ }
11
+
12
+ export async function chat(opts: ChatOptions = {}): Promise<void> {
13
+ const result = await bootstrap();
14
+
15
+ if (!result.success) {
16
+ for (const err of result.errors) {
17
+ console.error(`❌ ${err}`);
18
+ }
19
+ process.exit(1);
20
+ }
21
+
22
+ for (const warn of result.warnings) {
23
+ console.warn(`⚠ ${warn}`);
24
+ }
25
+
26
+ const model = opts.model || result.config.model;
27
+ const apiKey = opts.apiKey || result.config.apiKey;
28
+
29
+ const { waitUntilExit } = render(
30
+ <App
31
+ apiKey={apiKey}
32
+ model={model}
33
+ verbose={opts.verbose}
34
+ autoRun={opts.autoRun}
35
+ />,
36
+ );
37
+
38
+ await waitUntilExit();
39
+ }
@@ -0,0 +1,133 @@
1
+ import { getConfig, updateConfig, resetConfig, type DeeperConfig } from '../../core/config.ts';
2
+ import { loadConfig } from '../../core/config.ts';
3
+ import { DEEPER_CONFIG_FILE } from '../../core/constants.ts';
4
+
5
+ export async function configCommand(args: string[]): Promise<void> {
6
+ loadConfig();
7
+ const subcommand = args[0] || 'list';
8
+
9
+ switch (subcommand) {
10
+ case 'list':
11
+ case 'ls': {
12
+ const config = getConfig();
13
+ console.log('\n📋 DeeperCode 配置:\n');
14
+ const displayKeys: { key: string; value: unknown; mask?: boolean }[] = [
15
+ { key: 'model', value: config.model },
16
+ { key: 'baseUrl', value: config.baseUrl },
17
+ { key: 'apiKey', value: config.apiKey || '', mask: true },
18
+ { key: 'maxTokens', value: config.maxTokens },
19
+ { key: 'thinkBudget', value: config.thinkBudget },
20
+ { key: 'thinkEnabled', value: config.thinkEnabled },
21
+ { key: 'temperature', value: config.temperature },
22
+ { key: 'maxSubAgents', value: config.maxSubAgents },
23
+ { key: 'maxRecursionDepth', value: config.maxRecursionDepth },
24
+ { key: 'timeoutMs', value: config.timeoutMs },
25
+ { key: 'theme', value: config.theme },
26
+ { key: 'locale', value: config.locale },
27
+ ];
28
+ for (const { key, value, mask } of displayKeys) {
29
+ const raw = String(value ?? '');
30
+ const display = mask
31
+ ? (raw ? `${raw.slice(0, 8)}...${raw.slice(-4)}` : '(未设置)')
32
+ : JSON.stringify(value);
33
+ console.log(` ${key.padEnd(20)} ${display}`);
34
+ }
35
+ console.log();
36
+ break;
37
+ }
38
+
39
+ case 'get': {
40
+ const rawKey = args[1];
41
+ if (!rawKey) {
42
+ console.error('❌ 用法: deeper config get <key>');
43
+ process.exit(1);
44
+ }
45
+ const KEY_ALIASES: Record<string, string> = {
46
+ api_key: 'apiKey', 'api-key': 'apiKey', apikey: 'apiKey', key: 'apiKey',
47
+ };
48
+ const key = KEY_ALIASES[rawKey.toLowerCase()] || rawKey;
49
+ const config = getConfig();
50
+ const value = (config as Record<string, unknown>)[key];
51
+ if (value === undefined) {
52
+ console.error(`❌ 未知配置项: ${rawKey}`);
53
+ process.exit(1);
54
+ }
55
+ if (key === 'apiKey') {
56
+ const str = String(value || '');
57
+ console.log(str ? `${str.slice(0, 8)}...${str.slice(-4)}` : '(未设置)');
58
+ } else {
59
+ console.log(JSON.stringify(value, null, 2));
60
+ }
61
+ break;
62
+ }
63
+
64
+ case 'set': {
65
+ const rawKey = args[1];
66
+ const rawValue = args[2];
67
+ if (!rawKey || rawValue === undefined) {
68
+ console.error('❌ 用法: deeper config set <key> <value>');
69
+ process.exit(1);
70
+ }
71
+
72
+ const KEY_ALIASES: Record<string, string> = {
73
+ api_key: 'apiKey', 'api-key': 'apiKey', apikey: 'apiKey', key: 'apiKey',
74
+ base_url: 'baseUrl', 'base-url': 'baseUrl',
75
+ max_tokens: 'maxTokens', 'max-tokens': 'maxTokens',
76
+ think_budget: 'thinkBudget', 'think-budget': 'thinkBudget',
77
+ think_enabled: 'thinkEnabled', 'think-enabled': 'thinkEnabled',
78
+ log_level: 'logLevel', 'log-level': 'logLevel',
79
+ max_retries: 'maxRetries', 'max-retries': 'maxRetries',
80
+ timeout_ms: 'timeoutMs', 'timeout-ms': 'timeoutMs',
81
+ max_sub_agents: 'maxSubAgents', 'max-sub-agents': 'maxSubAgents',
82
+ max_recursion_depth: 'maxRecursionDepth', 'max-recursion-depth': 'maxRecursionDepth',
83
+ };
84
+ const key = KEY_ALIASES[rawKey.toLowerCase()] || rawKey;
85
+
86
+ try {
87
+ let parsedValue: unknown = rawValue;
88
+ if (rawValue === 'true') parsedValue = true;
89
+ else if (rawValue === 'false') parsedValue = false;
90
+ else if (!isNaN(Number(rawValue))) parsedValue = Number(rawValue);
91
+
92
+ updateConfig({ [key]: parsedValue } as Partial<DeeperConfig>);
93
+ console.log(`✅ 已设置 ${key} = ${JSON.stringify(parsedValue)}`);
94
+ } catch (e) {
95
+ const msg = e instanceof Error ? e.message : String(e);
96
+ console.error(`❌ 设置失败: ${msg}`);
97
+ process.exit(1);
98
+ }
99
+ break;
100
+ }
101
+
102
+ case 'reset': {
103
+ const config = resetConfig();
104
+ console.log('✅ 配置已重置为默认值');
105
+ console.log(JSON.stringify(config, null, 2));
106
+ break;
107
+ }
108
+
109
+ case 'path': {
110
+ console.log(`配置文件路径: ${DEEPER_CONFIG_FILE}`);
111
+ break;
112
+ }
113
+
114
+ default: {
115
+ console.log(`
116
+ 📋 DeeperCode 配置管理
117
+
118
+ 用法:
119
+ deeper config list 列出所有配置
120
+ deeper config get <key> 获取配置项
121
+ deeper config set <key> <value> 设置配置项
122
+ deeper config reset 重置配置
123
+ deeper config path 显示配置文件路径
124
+
125
+ 示例:
126
+ deeper config set model deepseek-v4-pro
127
+ deeper config set theme light
128
+ deeper config get apiKey
129
+ `);
130
+ break;
131
+ }
132
+ }
133
+ }
@@ -0,0 +1,172 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { bootstrap } from '../bootstrap.ts';
3
+ import { DEEPER_MCP_FILE } from '../../core/constants.ts';
4
+ import { getConfig, updateConfig, type MCPConfigEntry } from '../../core/config.ts';
5
+
6
+ export async function mcpCommand(args: string[]): Promise<void> {
7
+ const result = await bootstrap();
8
+ if (!result.success) {
9
+ for (const err of result.errors) {
10
+ console.error(`❌ ${err}`);
11
+ }
12
+ process.exit(1);
13
+ }
14
+
15
+ const subcommand = args[0] || 'list';
16
+
17
+ switch (subcommand) {
18
+ case 'list':
19
+ case 'ls': {
20
+ const config = getConfig();
21
+ const servers = config.mcpServers || [];
22
+
23
+ console.log('\n🔌 MCP 服务器:\n');
24
+
25
+ if (servers.length === 0) {
26
+ console.log(' (未配置任何 MCP 服务器)');
27
+ console.log();
28
+ console.log(' 使用 "deeper mcp add" 添加 MCP 服务器');
29
+ } else {
30
+ for (const server of servers) {
31
+ const status = server.enabled ? '✅ 启用' : '⏸ 禁用';
32
+ const type = server.url ? 'SSE/HTTP' : 'Stdio';
33
+ console.log(` 📡 ${server.name.padEnd(20)} ${status} | ${type}`);
34
+ if (server.command) {
35
+ console.log(` 命令: ${server.command} ${(server.args || []).join(' ')}`);
36
+ }
37
+ if (server.url) {
38
+ console.log(` URL: ${server.url}`);
39
+ }
40
+ if (server.autoConnect) {
41
+ console.log(` 🔗 自动连接`);
42
+ }
43
+ }
44
+ }
45
+ console.log();
46
+ break;
47
+ }
48
+
49
+ case 'add': {
50
+ const name = args[1];
51
+ const type = args[2];
52
+
53
+ if (!name) {
54
+ console.error('❌ 用法: deeper mcp add <name> stdio <command> [args...]');
55
+ console.error(' deeper mcp add <name> sse <url>');
56
+ process.exit(1);
57
+ }
58
+
59
+ const config = getConfig();
60
+ const servers = [...(config.mcpServers || [])];
61
+
62
+ if (servers.find((s) => s.name === name)) {
63
+ console.error(`❌ MCP 服务器 "${name}" 已存在`);
64
+ process.exit(1);
65
+ }
66
+
67
+ if (type === 'stdio') {
68
+ const command = args[3];
69
+ if (!command) {
70
+ console.error('❌ 请提供命令');
71
+ process.exit(1);
72
+ }
73
+ const cmdArgs = args.slice(4);
74
+ servers.push({
75
+ name,
76
+ command,
77
+ args: cmdArgs,
78
+ enabled: true,
79
+ autoConnect: true,
80
+ });
81
+ } else if (type === 'sse' || type === 'http') {
82
+ const url = args[3];
83
+ if (!url) {
84
+ console.error('❌ 请提供 URL');
85
+ process.exit(1);
86
+ }
87
+ servers.push({
88
+ name,
89
+ url,
90
+ enabled: true,
91
+ autoConnect: true,
92
+ });
93
+ } else {
94
+ console.error('❌ 未知类型。支持: stdio, sse');
95
+ process.exit(1);
96
+ }
97
+
98
+ updateConfig({ mcpServers: servers } as any);
99
+ console.log(`✅ MCP 服务器 "${name}" 已添加`);
100
+ break;
101
+ }
102
+
103
+ case 'remove':
104
+ case 'rm': {
105
+ const name = args[1];
106
+ if (!name) {
107
+ console.error('❌ 用法: deeper mcp remove <name>');
108
+ process.exit(1);
109
+ }
110
+
111
+ const config = getConfig();
112
+ const servers = (config.mcpServers || []).filter((s) => s.name !== name);
113
+
114
+ if (servers.length === config.mcpServers?.length) {
115
+ console.error(`❌ MCP 服务器 "${name}" 不存在`);
116
+ process.exit(1);
117
+ }
118
+
119
+ updateConfig({ mcpServers: servers } as any);
120
+ console.log(`✅ MCP 服务器 "${name}" 已移除`);
121
+ break;
122
+ }
123
+
124
+ case 'connect': {
125
+ const name = args[1];
126
+ if (!name) {
127
+ console.error('❌ 用法: deeper mcp connect <name>');
128
+ process.exit(1);
129
+ }
130
+ console.log(`🔌 连接 MCP 服务器 "${name}"...`);
131
+ console.log('💡 在 REPL 中使用 /mcp 查看已连接的服务器');
132
+ break;
133
+ }
134
+
135
+ case 'config': {
136
+ const filePath = DEEPER_MCP_FILE;
137
+ if (existsSync(filePath)) {
138
+ try {
139
+ const content = readFileSync(filePath, 'utf-8');
140
+ console.log(`📄 MCP 配置文件: ${filePath}`);
141
+ console.log(content);
142
+ } catch (e) {
143
+ const msg = e instanceof Error ? e.message : String(e);
144
+ console.error(`❌ 读取失败: ${msg}`);
145
+ }
146
+ } else {
147
+ console.log(`MCP 配置文件不存在: ${filePath}`);
148
+ }
149
+ break;
150
+ }
151
+
152
+ default: {
153
+ console.log(`
154
+ 🔌 DeeperCode MCP 管理
155
+
156
+ 用法:
157
+ deeper mcp list 列出所有 MCP 服务器
158
+ deeper mcp add <name> stdio <cmd> [args] 添加 Stdio MCP 服务器
159
+ deeper mcp add <name> sse <url> 添加 SSE/HTTP MCP 服务器
160
+ deeper mcp remove <name> 移除 MCP 服务器
161
+ deeper mcp connect <name> 连接 MCP 服务器
162
+ deeper mcp config 查看 MCP 配置文件
163
+
164
+ 示例:
165
+ deeper mcp add filesystem stdio npx -y @modelcontextprotocol/server-filesystem
166
+ deeper mcp add myserver sse http://localhost:3001
167
+ deeper mcp remove myserver
168
+ `);
169
+ break;
170
+ }
171
+ }
172
+ }
@@ -0,0 +1,147 @@
1
+ import { loadConfig } from '../../core/config.ts';
2
+ import { bootstrap } from '../bootstrap.ts';
3
+ import type { DeeperConfig } from '../../core/config.ts';
4
+
5
+ interface RunOptions {
6
+ task?: string;
7
+ model?: string;
8
+ apiKey?: string;
9
+ files?: string[];
10
+ }
11
+
12
+ export async function run(task: string, opts: RunOptions = {}): Promise<void> {
13
+ const result = await bootstrap();
14
+
15
+ if (!result.success) {
16
+ for (const err of result.errors) {
17
+ console.error(`❌ ${err}`);
18
+ }
19
+ process.exit(1);
20
+ }
21
+
22
+ if (!task) {
23
+ console.error('❌ 请提供任务描述。用法: deeper run "任务描述"');
24
+ process.exit(1);
25
+ }
26
+
27
+ const config = opts.model || opts.apiKey
28
+ ? { ...result.config, ...(opts.model ? { model: opts.model } : {}), ...(opts.apiKey ? { apiKey: opts.apiKey } : {}) }
29
+ : result.config;
30
+
31
+ if (!config.apiKey && !process.env.DEEPSEEK_API_KEY) {
32
+ console.error('❌ 未设置 API Key');
33
+ console.error(' 请设置环境变量 DEEPSEEK_API_KEY 或使用 --api-key 参数');
34
+ process.exit(1);
35
+ }
36
+
37
+ console.log(`\n🚀 DeeperCode 执行任务\n`);
38
+ console.log(`📋 任务: ${task}`);
39
+ console.log(`🤖 模型: ${config.model}`);
40
+ console.log(`🔗 API: ${config.baseUrl}`);
41
+ console.log();
42
+
43
+ console.log('⏳ 正在连接 DeepSeek API...');
44
+ console.log();
45
+
46
+ try {
47
+ const apiKey = config.apiKey || process.env.DEEPSEEK_API_KEY || '';
48
+ const response = await fetch(`${config.baseUrl}/v1/chat/completions`, {
49
+ method: 'POST',
50
+ headers: {
51
+ 'Content-Type': 'application/json',
52
+ 'Authorization': `Bearer ${apiKey}`,
53
+ },
54
+ body: JSON.stringify({
55
+ model: config.model,
56
+ messages: [
57
+ {
58
+ role: 'system',
59
+ content: '你是一个强大的 AI 编程助手。请帮助用户完成任务。',
60
+ },
61
+ {
62
+ role: 'user',
63
+ content: task,
64
+ },
65
+ ],
66
+ stream: true,
67
+ max_tokens: Math.max(1, Math.min(config.maxTokens || 4096, 131072)),
68
+ }),
69
+ });
70
+
71
+ if (!response.ok) {
72
+ const text = await response.text();
73
+ console.error(`❌ API 请求失败 (${response.status}): ${text}`);
74
+ process.exit(1);
75
+ }
76
+
77
+ const reader = response.body?.getReader();
78
+ if (!reader) {
79
+ console.error('❌ 无法读取响应流');
80
+ process.exit(1);
81
+ }
82
+
83
+ const decoder = new TextDecoder();
84
+ let buffer = '';
85
+ let fullContent = '';
86
+ let thinkingContent = '';
87
+
88
+ console.log('📝 AI 响应:\n');
89
+ console.log('─'.repeat(60));
90
+
91
+ while (true) {
92
+ const { done, value } = await reader.read();
93
+ if (done) break;
94
+
95
+ buffer += decoder.decode(value, { stream: true });
96
+ const lines = buffer.split('\n');
97
+ buffer = lines.pop() || '';
98
+
99
+ for (const line of lines) {
100
+ const trimmed = line.trim();
101
+ if (!trimmed.startsWith('data: ')) continue;
102
+
103
+ const data = trimmed.slice(6);
104
+ if (data === '[DONE]') continue;
105
+
106
+ try {
107
+ const parsed = JSON.parse(data);
108
+ const delta = parsed.choices?.[0]?.delta;
109
+
110
+ if (delta?.thinking) {
111
+ thinkingContent += delta.thinking;
112
+ }
113
+
114
+ if (delta?.content) {
115
+ fullContent += delta.content;
116
+ process.stdout.write(delta.content);
117
+ }
118
+ } catch {
119
+ // 跳过无法解析的行
120
+ }
121
+ }
122
+ }
123
+
124
+ console.log('\n' + '─'.repeat(60));
125
+ console.log();
126
+
127
+ if (thinkingContent) {
128
+ console.log('💭 思考过程:');
129
+ console.log('─'.repeat(60));
130
+ console.log(thinkingContent.slice(0, 500));
131
+ if (thinkingContent.length > 500) {
132
+ console.log(`... (还有 ${thinkingContent.length - 500} 字符)`);
133
+ }
134
+ console.log('─'.repeat(60));
135
+ }
136
+
137
+ const usage = `📊 Token: ~${fullContent.length} 输出`;
138
+ console.log(usage);
139
+ console.log();
140
+
141
+ console.log('✅ 任务执行完成!');
142
+ } catch (e) {
143
+ const msg = e instanceof Error ? e.message : String(e);
144
+ console.error(`❌ 请求失败: ${msg}`);
145
+ process.exit(1);
146
+ }
147
+ }
@@ -0,0 +1,152 @@
1
+ import { readdirSync, existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { bootstrap } from '../bootstrap.ts';
4
+ import { DEEPER_SKILLS_DIR, PROJECT_SKILLS_DIR } from '../../core/constants.ts';
5
+
6
+ export async function skillCommand(args: string[]): Promise<void> {
7
+ const result = await bootstrap();
8
+ if (!result.success) {
9
+ for (const err of result.errors) {
10
+ console.error(`❌ ${err}`);
11
+ }
12
+ process.exit(1);
13
+ }
14
+
15
+ const subcommand = args[0] || 'list';
16
+
17
+ switch (subcommand) {
18
+ case 'list':
19
+ case 'ls': {
20
+ console.log('\n🧩 DeeperCode Skills:\n');
21
+
22
+ const homeSkills = listSkills(DEEPER_SKILLS_DIR);
23
+ console.log(`📁 全局 Skills (${DEEPER_SKILLS_DIR}):`);
24
+ if (homeSkills.length === 0) {
25
+ console.log(' (无)');
26
+ } else {
27
+ for (const skill of homeSkills) {
28
+ console.log(` 📦 ${skill.name} - ${skill.description}`);
29
+ }
30
+ }
31
+
32
+ const cwd = process.cwd();
33
+ const projectSkillsDir = join(cwd, PROJECT_SKILLS_DIR);
34
+ if (existsSync(projectSkillsDir)) {
35
+ const projectSkills = listSkills(projectSkillsDir);
36
+ console.log(`\n📁 项目 Skills (${projectSkillsDir}):`);
37
+ if (projectSkills.length === 0) {
38
+ console.log(' (无)');
39
+ } else {
40
+ for (const skill of projectSkills) {
41
+ console.log(` 📦 ${skill.name} - ${skill.description}`);
42
+ }
43
+ }
44
+ }
45
+
46
+ console.log();
47
+ break;
48
+ }
49
+
50
+ case 'create': {
51
+ const name = args[1];
52
+ if (!name) {
53
+ console.error('❌ 用法: deeper skill create <name>');
54
+ process.exit(1);
55
+ }
56
+
57
+ const targetDir = join(DEEPER_SKILLS_DIR, name);
58
+ if (existsSync(targetDir)) {
59
+ console.error(`❌ Skill "${name}" 已存在`);
60
+ process.exit(1);
61
+ }
62
+
63
+ try {
64
+ mkdirSync(targetDir, { recursive: true });
65
+ const skillDef = {
66
+ name,
67
+ version: '1.0.0',
68
+ description: `${name} 技能`,
69
+ triggers: [],
70
+ steps: [],
71
+ };
72
+ writeFileSync(
73
+ join(targetDir, 'skill.json'),
74
+ JSON.stringify(skillDef, null, 2),
75
+ 'utf-8',
76
+ );
77
+ console.log(`✅ Skill "${name}" 已创建: ${targetDir}`);
78
+ } catch (e) {
79
+ const msg = e instanceof Error ? e.message : String(e);
80
+ console.error(`❌ 创建失败: ${msg}`);
81
+ process.exit(1);
82
+ }
83
+ break;
84
+ }
85
+
86
+ case 'info': {
87
+ const name = args[1];
88
+ if (!name) {
89
+ console.error('❌ 用法: deeper skill info <name>');
90
+ process.exit(1);
91
+ }
92
+
93
+ const skillPath = join(DEEPER_SKILLS_DIR, name, 'skill.json');
94
+ if (!existsSync(skillPath)) {
95
+ console.error(`❌ Skill "${name}" 不存在`);
96
+ process.exit(1);
97
+ }
98
+
99
+ try {
100
+ const content = readFileSync(skillPath, 'utf-8');
101
+ const skillDef = JSON.parse(content);
102
+ console.log(JSON.stringify(skillDef, null, 2));
103
+ } catch (e) {
104
+ const msg = e instanceof Error ? e.message : String(e);
105
+ console.error(`❌ 读取失败: ${msg}`);
106
+ process.exit(1);
107
+ }
108
+ break;
109
+ }
110
+
111
+ default: {
112
+ console.log(`
113
+ 🧩 DeeperCode Skill 管理
114
+
115
+ 用法:
116
+ deeper skill list 列出所有 Skills
117
+ deeper skill create <name> 创建新 Skill
118
+ deeper skill info <name> 查看 Skill 详情
119
+
120
+ 示例:
121
+ deeper skill list
122
+ deeper skill create my-skill
123
+ deeper skill info my-skill
124
+ `);
125
+ break;
126
+ }
127
+ }
128
+ }
129
+
130
+ function listSkills(dir: string): { name: string; description: string }[] {
131
+ try {
132
+ if (!existsSync(dir)) return [];
133
+ const entries = readdirSync(dir, { withFileTypes: true });
134
+ return entries
135
+ .filter((e) => e.isDirectory())
136
+ .map((e) => {
137
+ const skillFile = join(dir, e.name, 'skill.json');
138
+ if (existsSync(skillFile)) {
139
+ try {
140
+ const content = readFileSync(skillFile, 'utf-8');
141
+ const def = JSON.parse(content);
142
+ return { name: def.name || e.name, description: def.description || '' };
143
+ } catch {
144
+ return { name: e.name, description: '' };
145
+ }
146
+ }
147
+ return { name: e.name, description: '' };
148
+ });
149
+ } catch {
150
+ return [];
151
+ }
152
+ }