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,28 @@
1
+ import type { Tool } from '../../tool-types.js';
2
+
3
+ export const terminal_screenshot: Tool = {
4
+ name: 'terminal_screenshot',
5
+ description: '获取终端状态快照(文本形式)',
6
+ category: 'shell',
7
+ parameters: {
8
+ type: 'object',
9
+ properties: {
10
+ terminal_id: { type: 'string', description: '终端标识' },
11
+ },
12
+ required: ['terminal_id'],
13
+ },
14
+ dangerous: false,
15
+ requiresApproval: false,
16
+ async execute(params) {
17
+ try {
18
+ const terminalId = params.terminal_id as string;
19
+ return {
20
+ success: true,
21
+ output: `终端快照: ${terminalId}\n(终端屏幕截图功能在 CLI 环境中以文本输出替代)`,
22
+ metadata: { terminalId, method: 'text-snapshot' },
23
+ };
24
+ } catch (err: unknown) {
25
+ return { success: false, error: (err as Error).message, output: '' };
26
+ }
27
+ },
28
+ };
@@ -0,0 +1,89 @@
1
+ import { readFileSync, existsSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import type { Tool } from '../../tool-types.js';
4
+
5
+ export const log_viewer: Tool = {
6
+ name: 'log_viewer',
7
+ description: '查看和管理日志文件',
8
+ category: 'system',
9
+ parameters: {
10
+ type: 'object',
11
+ properties: {
12
+ action: { type: 'string', description: '操作: read, tail, search, clear', enum: ['read', 'tail', 'search', 'clear'] },
13
+ file_path: { type: 'string', description: '日志文件路径' },
14
+ lines: { type: 'number', description: '读取行数(tail 模式)' },
15
+ query: { type: 'string', description: '搜索关键词' },
16
+ },
17
+ required: ['action'],
18
+ },
19
+ dangerous: false,
20
+ requiresApproval: false,
21
+ async execute(params) {
22
+ try {
23
+ const action = params.action as string;
24
+ const filePath = params.file_path as string | undefined;
25
+ const lineCount = (params.lines as number) ?? 50;
26
+ const query = params.query as string | undefined;
27
+
28
+ if (action !== 'clear' && !filePath) {
29
+ const defaultLogs = ['npm-debug.log', 'yarn-error.log', '.log', 'logs/'];
30
+ const cwd = process.cwd();
31
+ const found = defaultLogs.filter(f => existsSync(resolve(cwd, f)));
32
+ return {
33
+ success: true,
34
+ output: `请指定 file_path。项目目录中的日志文件:\n${found.length > 0 ? found.join('\n') : ' (未找到)'}`,
35
+ };
36
+ }
37
+
38
+ const abs = resolve(filePath!);
39
+
40
+ if (action === 'clear') {
41
+ const { writeFileSync } = await import('node:fs');
42
+ writeFileSync(abs, '', 'utf-8');
43
+ return { success: true, output: `日志已清空: ${abs}` };
44
+ }
45
+
46
+ if (!existsSync(abs)) {
47
+ return { success: false, error: `日志文件不存在: ${abs}`, output: '' };
48
+ }
49
+
50
+ const content = readFileSync(abs, 'utf-8');
51
+ const allLines = content.split('\n');
52
+
53
+ switch (action) {
54
+ case 'read': {
55
+ const sub = allLines.slice(0, lineCount).join('\n');
56
+ return {
57
+ success: true,
58
+ output: sub,
59
+ metadata: { lines: allLines.length, shown: Math.min(lineCount, allLines.length) },
60
+ };
61
+ }
62
+ case 'tail': {
63
+ const sub = allLines.slice(-lineCount).join('\n');
64
+ return {
65
+ success: true,
66
+ output: `最后 ${Math.min(lineCount, allLines.length)} 行:\n${sub}`,
67
+ metadata: { totalLines: allLines.length },
68
+ };
69
+ }
70
+ case 'search': {
71
+ if (!query) return { success: false, error: 'search 需要 query 参数', output: '' };
72
+ const matches = allLines
73
+ .map((line, i) => line.includes(query) ? `${i + 1}:${line.trim()}` : null)
74
+ .filter(Boolean)
75
+ .slice(0, 200);
76
+ return {
77
+ success: true,
78
+ output: matches.join('\n') || '未找到匹配行',
79
+ metadata: { matches: matches.length, totalLines: allLines.length },
80
+ };
81
+ }
82
+ default:
83
+ return { success: false, error: `不支持的操作: ${action}`, output: '' };
84
+ }
85
+ } catch (err: unknown) {
86
+ return { success: false, error: (err as Error).message, output: '' };
87
+ }
88
+ },
89
+ };
@@ -0,0 +1,55 @@
1
+ import type { Tool } from '../../tool-types.js';
2
+
3
+ export const notify_user: Tool = {
4
+ name: 'notify_user',
5
+ description: '发送系统通知给用户',
6
+ category: 'system',
7
+ parameters: {
8
+ type: 'object',
9
+ properties: {
10
+ title: { type: 'string', description: '通知标题' },
11
+ message: { type: 'string', description: '通知详情' },
12
+ level: { type: 'string', description: '通知级别: info, warn, error, success', enum: ['info', 'warn', 'error', 'success'] },
13
+ },
14
+ required: ['message'],
15
+ },
16
+ dangerous: false,
17
+ requiresApproval: false,
18
+ async execute(params) {
19
+ try {
20
+ const title = (params.title as string) ?? 'DeeperCode';
21
+ const message = params.message as string;
22
+ const level = (params.level as string) ?? 'info';
23
+
24
+ const icons: Record<string, string> = {
25
+ info: 'ℹ',
26
+ warn: '⚠',
27
+ error: '✗',
28
+ success: '✓',
29
+ };
30
+
31
+ const output = `${icons[level] || ''} [${level.toUpperCase()}] ${title}: ${message}`;
32
+
33
+ try {
34
+ if (process.platform === 'win32') {
35
+ const { execSync } = await import('node:child_process');
36
+ execSync(`powershell -Command "Add-Type -AssemblyName System.Windows.Forms; $notify = New-Object System.Windows.Forms.NotifyIcon; $notify.Icon = [System.Drawing.SystemIcons]::Information; $notify.Visible = $true; $notify.ShowBalloonTip(5000, '${title}', '${message}', [System.Windows.Forms.ToolTipIcon]::${level === 'error' ? 'Error' : 'Info'}); Start-Sleep -Seconds 6; $notify.Dispose()"`, {
37
+ timeout: 10000,
38
+ stdio: 'ignore',
39
+ });
40
+ } else if (process.platform === 'darwin') {
41
+ const { execSync } = await import('node:child_process');
42
+ execSync(`osascript -e 'display notification "${message}" with title "${title}"'`, { stdio: 'ignore' });
43
+ } else {
44
+ const { execSync } = await import('node:child_process');
45
+ execSync(`notify-send "${title}" "${message}"`, { stdio: 'ignore' });
46
+ }
47
+ return { success: true, output, metadata: { title, level, notified: true } };
48
+ } catch {
49
+ return { success: true, output, metadata: { title, level, notified: false } };
50
+ }
51
+ } catch (err: unknown) {
52
+ return { success: false, error: (err as Error).message, output: '' };
53
+ }
54
+ },
55
+ };
@@ -0,0 +1,66 @@
1
+ import { execSync } from 'node:child_process';
2
+ import type { Tool } from '../../tool-types.js';
3
+
4
+ export const process_list: Tool = {
5
+ name: 'process_list',
6
+ description: '列出当前运行的进程',
7
+ category: 'system',
8
+ parameters: {
9
+ type: 'object',
10
+ properties: {
11
+ filter: { type: 'string', description: '进程名过滤' },
12
+ count: { type: 'number', description: '显示数量' },
13
+ },
14
+ required: [],
15
+ },
16
+ dangerous: false,
17
+ requiresApproval: false,
18
+ async execute(params) {
19
+ try {
20
+ const filter = params.filter as string | undefined;
21
+ const count = (params.count as number) ?? 20;
22
+ const platform = process.platform;
23
+
24
+ let cmd: string;
25
+ if (platform === 'win32') {
26
+ cmd = 'tasklist /FO CSV /NH';
27
+ } else {
28
+ cmd = 'ps aux --sort=-%mem';
29
+ }
30
+
31
+ try {
32
+ let output = execSync(cmd, { encoding: 'utf-8', timeout: 10000, stdio: 'pipe' });
33
+ const lines = output.split('\n');
34
+
35
+ if (filter) {
36
+ const filtered = lines.filter(l => l.toLowerCase().includes(filter.toLowerCase()));
37
+ output = filtered.slice(0, count).join('\n');
38
+ } else {
39
+ output = lines.slice(0, count).join('\n');
40
+ }
41
+
42
+ return {
43
+ success: true,
44
+ output: `进程列表 (${platform}):\n${output}`,
45
+ metadata: { platform, filter, lines: Math.min(lines.length, count) },
46
+ };
47
+ } catch {
48
+ const os = await import('node:os');
49
+ return {
50
+ success: true,
51
+ output: [
52
+ `当前进程信息:`,
53
+ `PID: ${process.pid}`,
54
+ `平台: ${os.platform()}`,
55
+ `架构: ${os.arch()}`,
56
+ `Node.js: ${process.version}`,
57
+ `CPU 数: ${os.cpus().length}`,
58
+ ].join('\n'),
59
+ metadata: { pid: process.pid },
60
+ };
61
+ }
62
+ } catch (err: unknown) {
63
+ return { success: false, error: (err as Error).message, output: '' };
64
+ }
65
+ },
66
+ };
@@ -0,0 +1,66 @@
1
+ import type { Tool } from '../../tool-types.js';
2
+
3
+ export const resource_monitor: Tool = {
4
+ name: 'resource_monitor',
5
+ description: '监控系统资源使用情况',
6
+ category: 'system',
7
+ parameters: {
8
+ type: 'object',
9
+ properties: {
10
+ interval_ms: { type: 'number', description: '采样间隔毫秒' },
11
+ samples: { type: 'number', description: '采样次数' },
12
+ },
13
+ required: [],
14
+ },
15
+ dangerous: false,
16
+ requiresApproval: false,
17
+ async execute(params) {
18
+ try {
19
+ const intervalMs = (params.interval_ms as number) ?? 1000;
20
+ const samples = (params.samples as number) ?? 3;
21
+
22
+ const os = await import('node:os');
23
+ const results: Record<string, unknown>[] = [];
24
+
25
+ for (let i = 0; i < samples; i++) {
26
+ const cpus = os.cpus();
27
+ const totalIdle = cpus.reduce((s, c) => s + c.times.idle, 0);
28
+ const totalTick = cpus.reduce((s, c) => s + c.times.user + c.times.nice + c.times.sys + c.times.idle + c.times.irq, 0);
29
+ const cpuUsage = totalTick > 0 ? ((1 - totalIdle / totalTick) * 100).toFixed(1) : '0';
30
+
31
+ results.push({
32
+ sample: i + 1,
33
+ cpu: `${cpuUsage}%`,
34
+ memory: {
35
+ total: `${(os.totalmem() / 1024 / 1024 / 1024).toFixed(1)} GB`,
36
+ free: `${(os.freemem() / 1024 / 1024 / 1024).toFixed(1)} GB`,
37
+ used: `${((os.totalmem() - os.freemem()) / os.totalmem() * 100).toFixed(1)}%`,
38
+ },
39
+ uptime: `${Math.floor(os.uptime() / 3600)}h ${Math.floor((os.uptime() % 3600) / 60)}m`,
40
+ loadAverage: os.loadavg().map(l => l.toFixed(2)),
41
+ });
42
+
43
+ if (i < samples - 1) {
44
+ await new Promise(r => setTimeout(r, intervalMs));
45
+ }
46
+ }
47
+
48
+ const latest = results[results.length - 1];
49
+ const output = [
50
+ `资源监控 (${samples} 采样,间隔 ${intervalMs}ms):`,
51
+ `CPU 使用率: ${(latest as Record<string, unknown>).cpu}`,
52
+ `内存: ${JSON.stringify((latest as Record<string, unknown>).memory)}`,
53
+ `运行时间: ${(latest as Record<string, unknown>).uptime}`,
54
+ `平均负载: ${JSON.stringify((latest as Record<string, unknown>).loadAverage)}`,
55
+ ].join('\n');
56
+
57
+ return {
58
+ success: true,
59
+ output,
60
+ metadata: { samples, intervalMs, latest },
61
+ };
62
+ } catch (err: unknown) {
63
+ return { success: false, error: (err as Error).message, output: '' };
64
+ }
65
+ },
66
+ };
@@ -0,0 +1,41 @@
1
+ import type { Tool } from '../../tool-types.js';
2
+
3
+ export const system_info: Tool = {
4
+ name: 'system_info',
5
+ description: '获取系统信息',
6
+ category: 'system',
7
+ parameters: {
8
+ type: 'object',
9
+ properties: {},
10
+ required: [],
11
+ },
12
+ dangerous: false,
13
+ requiresApproval: false,
14
+ async execute() {
15
+ try {
16
+ const os = await import('node:os');
17
+
18
+ const info = {
19
+ platform: os.platform(),
20
+ arch: os.arch(),
21
+ hostname: os.hostname(),
22
+ cpus: os.cpus().length,
23
+ totalMemory: `${(os.totalmem() / 1024 / 1024 / 1024).toFixed(1)} GB`,
24
+ freeMemory: `${(os.freemem() / 1024 / 1024 / 1024).toFixed(1)} GB`,
25
+ uptime: `${Math.floor(os.uptime() / 3600)}h ${Math.floor((os.uptime() % 3600) / 60)}m`,
26
+ nodeVersion: process.version,
27
+ homeDir: os.homedir(),
28
+ tmpDir: os.tmpdir(),
29
+ cwd: process.cwd(),
30
+ };
31
+
32
+ const output = Object.entries(info)
33
+ .map(([k, v]) => `${k}: ${v}`)
34
+ .join('\n');
35
+
36
+ return { success: true, output, metadata: info };
37
+ } catch (err: unknown) {
38
+ return { success: false, error: (err as Error).message, output: '' };
39
+ }
40
+ },
41
+ };
@@ -0,0 +1,97 @@
1
+ export interface JSONSchema {
2
+ type: string;
3
+ properties?: Record<string, JSONSchema>;
4
+ required?: string[];
5
+ description?: string;
6
+ enum?: string[];
7
+ items?: JSONSchema;
8
+ additionalProperties?: boolean;
9
+ }
10
+
11
+ export interface ToolParameter {
12
+ name: string;
13
+ type: string;
14
+ description: string;
15
+ required: boolean;
16
+ default?: unknown;
17
+ enum?: string[];
18
+ }
19
+
20
+ export interface ToolDefinition {
21
+ name: string;
22
+ description: string;
23
+ category: string;
24
+ parameters: JSONSchema;
25
+ dangerous?: boolean;
26
+ requiresApproval?: boolean;
27
+ }
28
+
29
+ export interface ToolResult {
30
+ success: boolean;
31
+ output: string;
32
+ error?: string;
33
+ metadata?: Record<string, unknown>;
34
+ }
35
+
36
+ export interface ToolExecutor {
37
+ execute(params: Record<string, unknown>, signal?: AbortSignal): Promise<ToolResult>;
38
+ }
39
+
40
+ export type Tool = ToolDefinition & ToolExecutor;
41
+
42
+ export interface ToolCall {
43
+ id: string;
44
+ name: string;
45
+ arguments: Record<string, unknown>;
46
+ }
47
+
48
+ export interface ToolCallResult {
49
+ callId: string;
50
+ result: ToolResult;
51
+ timestamp: number;
52
+ }
53
+
54
+ export type ToolSafetyLevel = 'safe' | 'confirm' | 'dangerous';
55
+
56
+ export const TOOL_SAFETY_MAP: Record<string, ToolSafetyLevel> = {
57
+ read_file: 'safe', list_dir: 'safe', glob_find: 'safe', file_info: 'safe',
58
+ grep_search: 'safe', text_search: 'safe', fuzzy_find: 'safe', regex_find: 'safe',
59
+ find_references: 'safe', find_definition: 'safe', symbol_search: 'safe',
60
+ search_package: 'safe', search_docs: 'safe', codebase_search: 'safe',
61
+ token_count: 'safe', system_info: 'safe', process_list: 'safe',
62
+ resource_monitor: 'safe', log_viewer: 'safe', bug_scan: 'safe',
63
+ web_fetch: 'safe', web_search: 'safe', check_url: 'safe',
64
+ parse_html: 'safe', http_request: 'safe',
65
+ watch_file: 'safe', batch_read: 'safe', create_dir: 'safe',
66
+ json_parse: 'safe', csv_parse: 'safe', xml_parse: 'safe', yaml_parse: 'safe', toml_parse: 'safe',
67
+ data_validate: 'safe', data_diff: 'safe', hash_generate: 'safe', jwt_decode: 'safe',
68
+ coverage_report: 'safe', config_manage: 'safe', notify_user: 'safe',
69
+ format_code: 'safe', lint_code: 'safe', type_check: 'safe', code_metrics: 'safe',
70
+ analyze_deps: 'safe', import_organizer: 'safe', parse_ast: 'safe',
71
+ db_schema: 'safe',
72
+ context_summarize: 'safe', prompt_template: 'safe',
73
+ skill_create: 'safe', tool_create: 'safe', memory_store: 'safe',
74
+ todo_manager: 'safe', subagent: 'safe',
75
+ background_terminal: 'safe', list_terminals: 'safe', read_terminal: 'safe',
76
+ send_keys: 'safe', send_ctrl_keys: 'safe', send_text: 'safe', kill_terminal: 'safe',
77
+ terminal_screenshot: 'safe', terminal_resize: 'safe', check_status: 'safe', stop_command: 'safe',
78
+ download_file: 'safe', api_call: 'safe', graphql_query: 'safe', websocket_connect: 'safe',
79
+
80
+ write_file: 'safe', edit_file: 'safe',
81
+ delete_file: 'confirm', move_file: 'confirm', copy_file: 'confirm', batch_write: 'safe',
82
+ merge_files: 'confirm', diff_files: 'confirm',
83
+ run_command: 'safe', run_async: 'safe', pipe_commands: 'safe',
84
+ shell_script: 'confirm', npm_manage: 'confirm',
85
+ project_init: 'confirm', build_project: 'confirm', run_test: 'confirm',
86
+ docker_manage: 'confirm', env_manage: 'confirm',
87
+ sql_query: 'confirm', sql_migrate: 'confirm', nosql_query: 'confirm',
88
+ db_backup: 'confirm', db_restore: 'confirm', redis_command: 'confirm',
89
+ encrypt_file: 'confirm', decrypt_file: 'confirm',
90
+ template_render: 'confirm', chart_generate: 'confirm',
91
+ secret_scan: 'confirm', vulnerability_check: 'confirm',
92
+ orm_generate: 'confirm', generate_code: 'confirm', refactor_code: 'confirm',
93
+ extract_function: 'confirm', data_transform: 'confirm', proxy_request: 'confirm',
94
+
95
+ interactive_terminal: 'confirm',
96
+ browser_action: 'confirm', screenshot_page: 'confirm',
97
+ };
@@ -0,0 +1,98 @@
1
+ import { Text, Box } from 'ink';
2
+ import { defaultTheme } from './themes/default.ts';
3
+
4
+ interface AgentNode {
5
+ id: string;
6
+ name: string;
7
+ status: 'idle' | 'running' | 'completed' | 'failed';
8
+ children?: AgentNode[];
9
+ }
10
+
11
+ interface AgentTreeProps {
12
+ agents: AgentNode[];
13
+ }
14
+
15
+ const statusIcon: Record<AgentNode['status'], string> = {
16
+ idle: '⏸',
17
+ running: '🔄',
18
+ completed: '✅',
19
+ failed: '❌',
20
+ };
21
+
22
+ const statusColor: Record<AgentNode['status'], string> = {
23
+ idle: defaultTheme.dimText,
24
+ running: defaultTheme.primary,
25
+ completed: defaultTheme.success,
26
+ failed: defaultTheme.error,
27
+ };
28
+
29
+ function AgentNodeRow({
30
+ node,
31
+ depth,
32
+ isLast,
33
+ }: {
34
+ node: AgentNode;
35
+ depth: number;
36
+ isLast: boolean;
37
+ }) {
38
+ const prefix = depth === 0
39
+ ? ''
40
+ : ' '.repeat(depth - 1) + (isLast ? '└─' : '├─');
41
+
42
+ return (
43
+ <Box flexDirection="column">
44
+ <Box>
45
+ <Text dimColor>{prefix}</Text>
46
+ <Text color={statusColor[node.status]}>{statusIcon[node.status]}</Text>
47
+ <Text bold color={statusColor[node.status]}> {node.name}</Text>
48
+ </Box>
49
+ {node.children?.map((child, i) => (
50
+ <AgentNodeRow
51
+ key={child.id}
52
+ node={child}
53
+ depth={depth + 1}
54
+ isLast={i === (node.children?.length || 0) - 1}
55
+ />
56
+ ))}
57
+ </Box>
58
+ );
59
+ }
60
+
61
+ export function AgentTree({ agents }: AgentTreeProps) {
62
+ const total = agents.length;
63
+ const running = agents.filter((a) => a.status === 'running').length;
64
+ const completed = agents.filter((a) => a.status === 'completed').length;
65
+ const failed = agents.filter((a) => a.status === 'failed').length;
66
+
67
+ const countChildren = (ns: AgentNode[]): number =>
68
+ ns.reduce((sum, n) => sum + 1 + countChildren(n.children || []), 0);
69
+
70
+ const totalWithChildren = countChildren(agents);
71
+
72
+ return (
73
+ <Box flexDirection="column" borderStyle="round" borderColor={defaultTheme.border} paddingX={1}>
74
+ <Box>
75
+ <Text bold>🤖 Agent 树</Text>
76
+ <Text dimColor>
77
+ {' '}
78
+ [{totalWithChildren} 节点:
79
+ {' '}<Text color={defaultTheme.success}>{completed} 完成</Text>
80
+ {running > 0 ? <Text color={defaultTheme.primary}> {running} 运行</Text> : null}
81
+ {failed > 0 ? <Text color={defaultTheme.error}> {failed} 失败</Text> : null}
82
+ ]
83
+ </Text>
84
+ </Box>
85
+
86
+ <Box flexDirection="column" marginTop={0}>
87
+ {agents.map((agent, i) => (
88
+ <AgentNodeRow
89
+ key={agent.id}
90
+ node={agent}
91
+ depth={0}
92
+ isLast={i === total - 1}
93
+ />
94
+ ))}
95
+ </Box>
96
+ </Box>
97
+ );
98
+ }
package/src/ui/App.tsx ADDED
@@ -0,0 +1,46 @@
1
+ import { useEffect, useState, useRef } from 'react';
2
+ import { Text, Box } from 'ink';
3
+ import { ChatView } from './ChatView.tsx';
4
+ import { StatusBar } from './StatusBar.tsx';
5
+ import { eventbus } from '../core/eventbus.ts';
6
+ import type { ChatMessage } from '../model/types.ts';
7
+
8
+ interface AppProps {
9
+ apiKey?: string;
10
+ model?: string;
11
+ verbose?: boolean;
12
+ autoRun?: string;
13
+ }
14
+
15
+ export function App({ apiKey, model, autoRun }: AppProps) {
16
+ const [initialMessages, setInitialMessages] = useState<ChatMessage[]>([]);
17
+ const startTimeRef = useRef(Date.now());
18
+
19
+ useEffect(() => {
20
+ const memTimer = setInterval(() => {
21
+ eventbus.emitStatusUpdate({
22
+ memoryUsage: Math.round(process.memoryUsage().heapUsed / (1024 * 1024)),
23
+ uptime: Date.now() - startTimeRef.current,
24
+ });
25
+ }, 5000);
26
+
27
+ if (autoRun) {
28
+ setInitialMessages([{
29
+ id: `auto-${Date.now()}`, role: 'user', content: autoRun, timestamp: Date.now(),
30
+ }]);
31
+ }
32
+
33
+ return () => { clearInterval(memTimer); eventbus.reset(); };
34
+ }, []);
35
+
36
+ return (
37
+ <Box flexDirection="column" width="100%">
38
+ <ChatView
39
+ initialMessages={initialMessages}
40
+ apiKey={apiKey}
41
+ model={model}
42
+ />
43
+ <StatusBar />
44
+ </Box>
45
+ );
46
+ }