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,79 @@
1
+ import type { Tool } from '../../tool-types.js';
2
+
3
+ export const data_diff: Tool = {
4
+ name: 'data_diff',
5
+ description: '比较两个数据集的差异',
6
+ category: 'data',
7
+ parameters: {
8
+ type: 'object',
9
+ properties: {
10
+ data_a: { type: 'string', description: '数据集 A (JSON)' },
11
+ data_b: { type: 'string', description: '数据集 B (JSON)' },
12
+ },
13
+ required: ['data_a', 'data_b'],
14
+ },
15
+ dangerous: false,
16
+ requiresApproval: false,
17
+ async execute(params) {
18
+ try {
19
+ const a = JSON.parse(params.data_a as string);
20
+ const b = JSON.parse(params.data_b as string);
21
+
22
+ const diff = computeDiff(a, b, '');
23
+ const output = diff.length > 0 ? diff.join('\n') : '两个数据集完全相同';
24
+
25
+ return { success: true, output, metadata: { differences: diff.length } };
26
+ } catch (err: unknown) {
27
+ return { success: false, error: (err as Error).message, output: '' };
28
+ }
29
+ },
30
+ };
31
+
32
+ function computeDiff(a: unknown, b: unknown, path: string): string[] {
33
+ const results: string[] = [];
34
+
35
+ if (a === b) return results;
36
+
37
+ if (typeof a !== typeof b) {
38
+ results.push(`${path || 'root'}: 类型不同 (${typeof a} vs ${typeof b})`);
39
+ return results;
40
+ }
41
+
42
+ if (a === null || b === null || typeof a !== 'object') {
43
+ if (JSON.stringify(a) !== JSON.stringify(b)) {
44
+ results.push(`${path || 'root'}: ${JSON.stringify(a)} → ${JSON.stringify(b)}`);
45
+ }
46
+ return results;
47
+ }
48
+
49
+ if (Array.isArray(a) && Array.isArray(b)) {
50
+ const maxLen = Math.max(a.length, b.length);
51
+ for (let i = 0; i < maxLen; i++) {
52
+ results.push(...computeDiff(a[i], b[i], `${path}[${i}]`));
53
+ }
54
+ return results;
55
+ }
56
+
57
+ const keysA = Object.keys(a as Record<string, unknown>);
58
+ const keysB = Object.keys(b as Record<string, unknown>);
59
+ const allKeys = new Set([...keysA, ...keysB]);
60
+
61
+ for (const key of allKeys) {
62
+ const valA = (a as Record<string, unknown>)[key];
63
+ const valB = (b as Record<string, unknown>)[key];
64
+
65
+ if (!(key in (a as object))) {
66
+ results.push(`${path}.${key}: 新增 → ${JSON.stringify(valB)}`);
67
+ } else if (!(key in (b as object))) {
68
+ results.push(`${path}.${key}: 已删除 (原值: ${JSON.stringify(valA)})`);
69
+ } else {
70
+ if (typeof valA === 'object' && typeof valB === 'object' && valA !== null && valB !== null) {
71
+ results.push(...computeDiff(valA, valB, `${path}.${key}`));
72
+ } else if (valA !== valB) {
73
+ results.push(`${path}.${key}: ${JSON.stringify(valA)} → ${JSON.stringify(valB)}`);
74
+ }
75
+ }
76
+ }
77
+
78
+ return results;
79
+ }
@@ -0,0 +1,74 @@
1
+ import type { Tool } from '../../tool-types.js';
2
+
3
+ export const data_transform: Tool = {
4
+ name: 'data_transform',
5
+ description: '数据格式转换(JSON/CSV/YAML/XML 互转)',
6
+ category: 'data',
7
+ parameters: {
8
+ type: 'object',
9
+ properties: {
10
+ data: { type: 'string', description: '输入数据' },
11
+ from: { type: 'string', description: '源格式: json, csv, yaml, xml', enum: ['json', 'csv', 'yaml', 'xml'] },
12
+ to: { type: 'string', description: '目标格式: json, csv, yaml, xml', enum: ['json', 'csv', 'yaml', 'xml'] },
13
+ file_path: { type: 'string', description: '文件路径' },
14
+ output: { type: 'string', description: '输出文件路径' },
15
+ },
16
+ required: ['from', 'to'],
17
+ },
18
+ dangerous: false,
19
+ requiresApproval: true,
20
+ async execute(params) {
21
+ try {
22
+ const from = params.from as string;
23
+ const to = params.to as string;
24
+ const data = params.data as string | undefined;
25
+ const filePath = params.file_path as string | undefined;
26
+ const output = params.output as string | undefined;
27
+
28
+ let inputStr = '';
29
+ if (filePath) {
30
+ const { readFileSync, existsSync } = await import('node:fs');
31
+ const { resolve } = await import('node:path');
32
+ const abs = resolve(filePath);
33
+ if (!existsSync(abs)) return { success: false, error: `文件不存在: ${abs}`, output: '' };
34
+ inputStr = readFileSync(abs, 'utf-8');
35
+ } else if (data) {
36
+ inputStr = data;
37
+ } else {
38
+ return { success: false, error: '请提供 data 或 file_path 参数', output: '' };
39
+ }
40
+
41
+ let parsed: unknown;
42
+ switch (from) {
43
+ case 'json': parsed = JSON.parse(inputStr); break;
44
+ case 'yaml': { const yaml = await import('yaml'); parsed = yaml.parse(inputStr); break; }
45
+ case 'csv': {
46
+ const { parse } = await import('csv-parse/sync');
47
+ parsed = parse(inputStr, { columns: true, skip_empty_lines: true });
48
+ break;
49
+ }
50
+ case 'xml': parsed = inputStr; break;
51
+ default: return { success: false, error: `不支持的源格式: ${from}`, output: '' };
52
+ }
53
+
54
+ let outputStr = '';
55
+ switch (to) {
56
+ case 'json': outputStr = JSON.stringify(parsed, null, 2); break;
57
+ case 'yaml': { const yaml = await import('yaml'); outputStr = yaml.stringify(parsed); break; }
58
+ case 'xml': outputStr = typeof parsed === 'string' ? parsed : `<root>${JSON.stringify(parsed)}</root>`; break;
59
+ case 'csv': outputStr = JSON.stringify(parsed); break;
60
+ default: return { success: false, error: `不支持的目标格式: ${to}`, output: '' };
61
+ }
62
+
63
+ if (output) {
64
+ const { writeFileSync } = await import('node:fs');
65
+ writeFileSync(output, outputStr, 'utf-8');
66
+ return { success: true, output: `转换完成并写入: ${output}`, metadata: { from, to } };
67
+ }
68
+
69
+ return { success: true, output: outputStr, metadata: { from, to } };
70
+ } catch (err: unknown) {
71
+ return { success: false, error: (err as Error).message, output: '' };
72
+ }
73
+ },
74
+ };
@@ -0,0 +1,75 @@
1
+ import type { Tool } from '../../tool-types.js';
2
+
3
+ export const data_validate: Tool = {
4
+ name: 'data_validate',
5
+ description: '根据 schema 验证数据',
6
+ category: 'data',
7
+ parameters: {
8
+ type: 'object',
9
+ properties: {
10
+ data: { type: 'string', description: 'JSON 数据' },
11
+ schema: { type: 'string', description: 'JSON Schema 用于验证' },
12
+ },
13
+ required: ['data', 'schema'],
14
+ },
15
+ dangerous: false,
16
+ requiresApproval: false,
17
+ async execute(params) {
18
+ try {
19
+ const data = JSON.parse(params.data as string);
20
+ const schema = JSON.parse(params.schema as string);
21
+
22
+ const errors = validateAgainstSchema(data, schema);
23
+
24
+ if (errors.length === 0) {
25
+ return { success: true, output: '数据验证通过!' };
26
+ }
27
+ return {
28
+ success: false,
29
+ error: `数据验证失败 (${errors.length} 个问题)`,
30
+ output: errors.map((e, i) => ` ${i + 1}. ${e}`).join('\n'),
31
+ };
32
+ } catch (err: unknown) {
33
+ return { success: false, error: (err as Error).message, output: '' };
34
+ }
35
+ },
36
+ };
37
+
38
+ function validateAgainstSchema(data: unknown, schema: Record<string, unknown>, path = '$'): string[] {
39
+ const errors: string[] = [];
40
+
41
+ if (schema.type) {
42
+ const expectedType = schema.type as string;
43
+ const actualType = Array.isArray(data) ? 'array' : typeof data;
44
+ if (expectedType !== actualType) {
45
+ errors.push(`${path}: 期望类型 "${expectedType}",实际类型 "${actualType}"`);
46
+ return errors;
47
+ }
48
+ }
49
+
50
+ if (schema.required && Array.isArray(schema.required) && data && typeof data === 'object') {
51
+ for (const key of schema.required as string[]) {
52
+ if (!(key in (data as Record<string, unknown>))) {
53
+ errors.push(`${path}: 缺少必需字段 "${key}"`);
54
+ }
55
+ }
56
+ }
57
+
58
+ if (schema.properties && data && typeof data === 'object' && !Array.isArray(data)) {
59
+ const props = schema.properties as Record<string, Record<string, unknown>>;
60
+ for (const [key, propSchema] of Object.entries(props)) {
61
+ if (key in data) {
62
+ errors.push(...validateAgainstSchema((data as Record<string, unknown>)[key], propSchema, `${path}.${key}`));
63
+ }
64
+ }
65
+ }
66
+
67
+ if (schema.enum && Array.isArray(schema.enum)) {
68
+ const enumValues = schema.enum;
69
+ if (!enumValues.includes(data)) {
70
+ errors.push(`${path}: 值 "${data}" 不在允许的范围: [${enumValues.join(', ')}]`);
71
+ }
72
+ }
73
+
74
+ return errors;
75
+ }
@@ -0,0 +1,71 @@
1
+ import type { Tool } from '../../tool-types.js';
2
+
3
+ export const json_parse: Tool = {
4
+ name: 'json_parse',
5
+ description: '解析和格式化 JSON 内容',
6
+ category: 'data',
7
+ parameters: {
8
+ type: 'object',
9
+ properties: {
10
+ content: { type: 'string', description: 'JSON 字符串' },
11
+ file_path: { type: 'string', description: 'JSON 文件路径' },
12
+ pretty: { type: 'boolean', description: '是否美化输出' },
13
+ query: { type: 'string', description: 'JSONPath 查询' },
14
+ },
15
+ required: [],
16
+ },
17
+ dangerous: false,
18
+ requiresApproval: false,
19
+ async execute(params) {
20
+ try {
21
+ const content = params.content as string | undefined;
22
+ const filePath = params.file_path as string | undefined;
23
+ const pretty = (params.pretty as boolean) ?? true;
24
+ const query = params.query as string | undefined;
25
+
26
+ let jsonContent = '';
27
+ if (filePath) {
28
+ const { readFileSync, existsSync } = await import('node:fs');
29
+ const { resolve } = await import('node:path');
30
+ const abs = resolve(filePath);
31
+ if (!existsSync(abs)) return { success: false, error: `文件不存在: ${abs}`, output: '' };
32
+ jsonContent = readFileSync(abs, 'utf-8');
33
+ } else if (content) {
34
+ jsonContent = content;
35
+ } else {
36
+ return { success: false, error: '请提供 content 或 file_path 参数', output: '' };
37
+ }
38
+
39
+ const parsed = JSON.parse(jsonContent);
40
+
41
+ if (query) {
42
+ const value = resolveJsonPath(parsed, query);
43
+ return {
44
+ success: true,
45
+ output: JSON.stringify(value, null, pretty ? 2 : 0),
46
+ metadata: { query },
47
+ };
48
+ }
49
+
50
+ return { success: true, output: JSON.stringify(parsed, null, pretty ? 2 : 0) };
51
+ } catch (err: unknown) {
52
+ return { success: false, error: (err as Error).message, output: '' };
53
+ }
54
+ },
55
+ };
56
+
57
+ function resolveJsonPath(obj: unknown, path: string): unknown {
58
+ const parts = path.replace(/^\$\.?/, '').split('.');
59
+ let current: unknown = obj;
60
+ for (const part of parts) {
61
+ if (current === null || typeof current !== 'object') return undefined;
62
+ const bracketMatch = part.match(/^(\w+)\[(\d+)\]$/);
63
+ if (bracketMatch) {
64
+ current = (current as Record<string, unknown>)[bracketMatch[1]];
65
+ current = (current as unknown[])?.[parseInt(bracketMatch[2])];
66
+ } else {
67
+ current = (current as Record<string, unknown>)[part];
68
+ }
69
+ }
70
+ return current;
71
+ }
@@ -0,0 +1,58 @@
1
+ import { readFileSync, existsSync, writeFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import type { Tool } from '../../tool-types.js';
4
+
5
+ export const template_render: Tool = {
6
+ name: 'template_render',
7
+ description: '渲染模板字符串或文件',
8
+ category: 'data',
9
+ parameters: {
10
+ type: 'object',
11
+ properties: {
12
+ template: { type: 'string', description: '模板字符串,使用 {{key}} 占位' },
13
+ file_path: { type: 'string', description: '模板文件路径' },
14
+ values: { type: 'object', description: '模板变量值' },
15
+ output: { type: 'string', description: '输出文件路径' },
16
+ },
17
+ required: ['values'],
18
+ },
19
+ dangerous: false,
20
+ requiresApproval: true,
21
+ async execute(params) {
22
+ try {
23
+ const templateStr = params.template as string | undefined;
24
+ const filePath = params.file_path as string | undefined;
25
+ const values = params.values as Record<string, unknown>;
26
+ const output = params.output as string | undefined;
27
+
28
+ let template = '';
29
+ if (filePath) {
30
+ const abs = resolve(filePath);
31
+ if (!existsSync(abs)) return { success: false, error: `模板文件不存在: ${abs}`, output: '' };
32
+ template = readFileSync(abs, 'utf-8');
33
+ } else if (templateStr) {
34
+ template = templateStr;
35
+ } else {
36
+ return { success: false, error: '请提供 template 或 file_path 参数', output: '' };
37
+ }
38
+
39
+ let rendered = template;
40
+ for (const [key, value] of Object.entries(values)) {
41
+ rendered = rendered.replace(new RegExp(`\\{\\{\\s*${escapeRegex(key)}\\s*\\}\\}`, 'g'), String(value));
42
+ }
43
+
44
+ if (output) {
45
+ writeFileSync(output, rendered, 'utf-8');
46
+ return { success: true, output: `模板已渲染并写入: ${output}`, metadata: { keys: Object.keys(values).length } };
47
+ }
48
+
49
+ return { success: true, output: rendered, metadata: { keys: Object.keys(values).length } };
50
+ } catch (err: unknown) {
51
+ return { success: false, error: (err as Error).message, output: '' };
52
+ }
53
+ },
54
+ };
55
+
56
+ function escapeRegex(s: string): string {
57
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
58
+ }
@@ -0,0 +1,42 @@
1
+ import type { Tool } from '../../tool-types.js';
2
+
3
+ export const toml_parse: Tool = {
4
+ name: 'toml_parse',
5
+ description: '解析 TOML 内容',
6
+ category: 'data',
7
+ parameters: {
8
+ type: 'object',
9
+ properties: {
10
+ content: { type: 'string', description: 'TOML 字符串内容' },
11
+ file_path: { type: 'string', description: 'TOML 文件路径' },
12
+ },
13
+ required: [],
14
+ },
15
+ dangerous: false,
16
+ requiresApproval: false,
17
+ async execute(params) {
18
+ try {
19
+ const content = params.content as string | undefined;
20
+ const filePath = params.file_path as string | undefined;
21
+
22
+ let tomlContent = '';
23
+ if (filePath) {
24
+ const { readFileSync, existsSync } = await import('node:fs');
25
+ const { resolve } = await import('node:path');
26
+ const abs = resolve(filePath);
27
+ if (!existsSync(abs)) return { success: false, error: `文件不存在: ${abs}`, output: '' };
28
+ tomlContent = readFileSync(abs, 'utf-8');
29
+ } else if (content) {
30
+ tomlContent = content;
31
+ } else {
32
+ return { success: false, error: '请提供 content 或 file_path 参数', output: '' };
33
+ }
34
+
35
+ const { parse } = await import('toml');
36
+ const parsed = parse(tomlContent);
37
+ return { success: true, output: JSON.stringify(parsed, null, 2) };
38
+ } catch (err: unknown) {
39
+ return { success: false, error: (err as Error).message, output: '' };
40
+ }
41
+ },
42
+ };
@@ -0,0 +1,79 @@
1
+ import type { Tool } from '../../tool-types.js';
2
+
3
+ export const xml_parse: Tool = {
4
+ name: 'xml_parse',
5
+ description: '解析 XML 内容',
6
+ category: 'data',
7
+ parameters: {
8
+ type: 'object',
9
+ properties: {
10
+ content: { type: 'string', description: 'XML 字符串' },
11
+ file_path: { type: 'string', description: 'XML 文件路径' },
12
+ },
13
+ required: [],
14
+ },
15
+ dangerous: false,
16
+ requiresApproval: false,
17
+ async execute(params) {
18
+ try {
19
+ let xmlContent = '';
20
+ const filePath = params.file_path as string | undefined;
21
+ const content = params.content as string | undefined;
22
+
23
+ if (filePath) {
24
+ const { readFileSync, existsSync } = await import('node:fs');
25
+ const { resolve } = await import('node:path');
26
+ const abs = resolve(filePath);
27
+ if (!existsSync(abs)) return { success: false, error: `文件不存在: ${abs}`, output: '' };
28
+ xmlContent = readFileSync(abs, 'utf-8');
29
+ } else if (content) {
30
+ xmlContent = content;
31
+ } else {
32
+ return { success: false, error: '请提供 content 或 file_path 参数', output: '' };
33
+ }
34
+
35
+ const parsed = parseXml(xmlContent);
36
+ return { success: true, output: JSON.stringify(parsed, null, 2) };
37
+ } catch (err: unknown) {
38
+ return { success: false, error: (err as Error).message, output: '' };
39
+ }
40
+ },
41
+ };
42
+
43
+ function parseXml(xml: string): Record<string, unknown> {
44
+ const result: Record<string, unknown> = {};
45
+ const tagRegex = /<([\w:.-]+)([^>]*)>([\s\S]*?)<\/\1>/g;
46
+ const selfClosingRegex = /<([\w:.-]+)([^>]*)\/>/g;
47
+ let match;
48
+
49
+ while ((match = tagRegex.exec(xml)) !== null) {
50
+ const tagName = match[1];
51
+ const attrs = match[2];
52
+ const inner = match[3];
53
+
54
+ const attrsObj: Record<string, string> = {};
55
+ const attrRegex = /(\w+)=["']([^"']*)["']/g;
56
+ let attrMatch;
57
+ while ((attrMatch = attrRegex.exec(attrs)) !== null) {
58
+ attrsObj[attrMatch[1]] = attrMatch[2];
59
+ }
60
+
61
+ if (/<[\w]/.test(inner)) {
62
+ result[tagName] = { ...attrsObj, ...parseXml(inner) };
63
+ } else {
64
+ result[tagName] = { _text: inner.trim(), ...attrsObj };
65
+ }
66
+ }
67
+
68
+ while ((match = selfClosingRegex.exec(xml)) !== null) {
69
+ const attrsObj: Record<string, string> = {};
70
+ const attrRegex = /(\w+)=["']([^"']*)["']/g;
71
+ let attrMatch;
72
+ while ((attrMatch = attrRegex.exec(match[2])) !== null) {
73
+ attrsObj[attrMatch[1]] = attrMatch[2];
74
+ }
75
+ result[match[1]] = attrsObj;
76
+ }
77
+
78
+ return result;
79
+ }
@@ -0,0 +1,42 @@
1
+ import type { Tool } from '../../tool-types.js';
2
+
3
+ export const yaml_parse: Tool = {
4
+ name: 'yaml_parse',
5
+ description: '解析 YAML 内容',
6
+ category: 'data',
7
+ parameters: {
8
+ type: 'object',
9
+ properties: {
10
+ content: { type: 'string', description: 'YAML 字符串' },
11
+ file_path: { type: 'string', description: 'YAML 文件路径' },
12
+ },
13
+ required: [],
14
+ },
15
+ dangerous: false,
16
+ requiresApproval: false,
17
+ async execute(params) {
18
+ try {
19
+ let yamlContent = '';
20
+ const filePath = params.file_path as string | undefined;
21
+ const content = params.content as string | undefined;
22
+
23
+ if (filePath) {
24
+ const { readFileSync, existsSync } = await import('node:fs');
25
+ const { resolve } = await import('node:path');
26
+ const abs = resolve(filePath);
27
+ if (!existsSync(abs)) return { success: false, error: `文件不存在: ${abs}`, output: '' };
28
+ yamlContent = readFileSync(abs, 'utf-8');
29
+ } else if (content) {
30
+ yamlContent = content;
31
+ } else {
32
+ return { success: false, error: '请提供 content 或 file_path 参数', output: '' };
33
+ }
34
+
35
+ const { parse } = await import('yaml');
36
+ const parsed = parse(yamlContent);
37
+ return { success: true, output: JSON.stringify(parsed, null, 2) };
38
+ } catch (err: unknown) {
39
+ return { success: false, error: (err as Error).message, output: '' };
40
+ }
41
+ },
42
+ };
@@ -0,0 +1,53 @@
1
+ import { execSync } from 'node:child_process';
2
+ import type { Tool } from '../../tool-types.js';
3
+
4
+ export const db_backup: Tool = {
5
+ name: 'db_backup',
6
+ description: '数据库备份',
7
+ category: 'database',
8
+ parameters: {
9
+ type: 'object',
10
+ properties: {
11
+ engine: { type: 'string', description: '数据库引擎', enum: ['mysql', 'postgresql', 'sqlite'] },
12
+ connection: { type: 'string', description: '连接字符串/数据库名称' },
13
+ output_file: { type: 'string', description: '备份输出文件路径' },
14
+ tables: { type: 'array', items: { type: 'string' }, description: '指定表名列表' },
15
+ },
16
+ required: ['engine', 'output_file'],
17
+ },
18
+ dangerous: false,
19
+ requiresApproval: true,
20
+ async execute(params) {
21
+ try {
22
+ const engine = params.engine as string;
23
+ const connection = params.connection as string | undefined;
24
+ const outputFile = params.output_file as string;
25
+ const tables = params.tables as string[] | undefined;
26
+
27
+ let cmd = '';
28
+ switch (engine) {
29
+ case 'sqlite':
30
+ cmd = `sqlite3 "${connection || 'database.db'}" .dump > "${outputFile}"`;
31
+ break;
32
+ case 'mysql':
33
+ cmd = `mysqldump ${connection || ''} ${(tables || []).join(' ')} > "${outputFile}"`;
34
+ break;
35
+ case 'postgresql':
36
+ cmd = `pg_dump ${connection || ''} > "${outputFile}"`;
37
+ break;
38
+ default:
39
+ return { success: false, error: `不支持的数据库引擎: ${engine}`, output: '' };
40
+ }
41
+
42
+ try {
43
+ execSync(cmd, { encoding: 'utf-8', timeout: 120000, stdio: 'pipe' });
44
+ return { success: true, output: `备份完成: ${outputFile}`, metadata: { engine, outputFile } };
45
+ } catch (err: unknown) {
46
+ const e = err as { message?: string };
47
+ return { success: false, error: `备份失败: ${e.message || String(err)}`, output: '' };
48
+ }
49
+ } catch (err: unknown) {
50
+ return { success: false, error: (err as Error).message, output: '' };
51
+ }
52
+ },
53
+ };
@@ -0,0 +1,51 @@
1
+ import { execSync } from 'node:child_process';
2
+ import type { Tool } from '../../tool-types.js';
3
+
4
+ export const db_restore: Tool = {
5
+ name: 'db_restore',
6
+ description: '数据库恢复',
7
+ category: 'database',
8
+ parameters: {
9
+ type: 'object',
10
+ properties: {
11
+ engine: { type: 'string', description: '数据库引擎', enum: ['mysql', 'postgresql', 'sqlite'] },
12
+ connection: { type: 'string', description: '连接字符串' },
13
+ backup_file: { type: 'string', description: '备份文件路径' },
14
+ },
15
+ required: ['engine', 'backup_file'],
16
+ },
17
+ dangerous: false,
18
+ requiresApproval: true,
19
+ async execute(params) {
20
+ try {
21
+ const engine = params.engine as string;
22
+ const connection = params.connection as string | undefined;
23
+ const backupFile = params.backup_file as string;
24
+
25
+ let cmd = '';
26
+ switch (engine) {
27
+ case 'sqlite':
28
+ cmd = `sqlite3 "${connection || 'database.db'}" < "${backupFile}"`;
29
+ break;
30
+ case 'mysql':
31
+ cmd = `mysql ${connection || ''} < "${backupFile}"`;
32
+ break;
33
+ case 'postgresql':
34
+ cmd = `psql ${connection || ''} < "${backupFile}"`;
35
+ break;
36
+ default:
37
+ return { success: false, error: `不支持的数据库引擎: ${engine}`, output: '' };
38
+ }
39
+
40
+ try {
41
+ const output = execSync(cmd, { encoding: 'utf-8', timeout: 120000, stdio: 'pipe' });
42
+ return { success: true, output: `恢复完成: ${backupFile}\n${output || ''}`, metadata: { engine, backupFile } };
43
+ } catch (err: unknown) {
44
+ const e = err as { message?: string };
45
+ return { success: false, error: `恢复失败: ${e.message || String(err)}`, output: '' };
46
+ }
47
+ } catch (err: unknown) {
48
+ return { success: false, error: (err as Error).message, output: '' };
49
+ }
50
+ },
51
+ };