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.
- package/README.md +254 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +12067 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.ts +415 -0
- package/dist/index.js +1599 -0
- package/dist/index.js.map +1 -0
- package/docs/superpowers/plans/2026-05-14-deepercode-implementation.md +24 -0
- package/docs/superpowers/plans/2026-05-14-deepercode-plan.md +1248 -0
- package/docs/superpowers/specs/2026-05-14-deepercode-design.md +560 -0
- package/package.json +60 -0
- package/src/cli/bootstrap.ts +69 -0
- package/src/cli/chat-repl.ts +932 -0
- package/src/cli/commands/chat.ts +39 -0
- package/src/cli/commands/chat.tsx +39 -0
- package/src/cli/commands/config.ts +133 -0
- package/src/cli/commands/mcp.ts +172 -0
- package/src/cli/commands/run.ts +147 -0
- package/src/cli/commands/skill.ts +152 -0
- package/src/cli/index.ts +184 -0
- package/src/core/bugscan.ts +145 -0
- package/src/core/config.ts +285 -0
- package/src/core/constants.ts +49 -0
- package/src/core/eventbus.ts +202 -0
- package/src/core/logger.ts +109 -0
- package/src/core/storage.ts +96 -0
- package/src/index.ts +26 -0
- package/src/mcp/ConfigLoader.ts +74 -0
- package/src/mcp/MCPClient.ts +326 -0
- package/src/mcp/ResourceAdapter.ts +58 -0
- package/src/mcp/SSETransport.ts +133 -0
- package/src/mcp/StdioTransport.ts +116 -0
- package/src/mcp/ToolAdapter.ts +71 -0
- package/src/mcp/types.ts +58 -0
- package/src/memory/xmemory.ts +275 -0
- package/src/model/DeepSeekClient.ts +292 -0
- package/src/model/MessageBuilder.ts +155 -0
- package/src/model/RetryManager.ts +82 -0
- package/src/model/StreamHandler.ts +158 -0
- package/src/model/types.ts +86 -0
- package/src/skills/SkillCreator.ts +153 -0
- package/src/skills/SkillEngine.ts +158 -0
- package/src/skills/SkillExecutor.ts +107 -0
- package/src/skills/SkillLoader.ts +182 -0
- package/src/skills/SkillRegistry.ts +73 -0
- package/src/skills/SkillTrigger.ts +82 -0
- package/src/skills/types.ts +28 -0
- package/src/tools/ToolExecutor.ts +103 -0
- package/src/tools/ToolRegistry.ts +71 -0
- package/src/tools/ToolValidator.ts +103 -0
- package/src/tools/builtin/ai/context_summarize.ts +76 -0
- package/src/tools/builtin/ai/memory_store.ts +86 -0
- package/src/tools/builtin/ai/prompt_template.ts +71 -0
- package/src/tools/builtin/ai/skill_create.ts +53 -0
- package/src/tools/builtin/ai/subagent.ts +39 -0
- package/src/tools/builtin/ai/todo_manager.ts +157 -0
- package/src/tools/builtin/ai/token_count.ts +196 -0
- package/src/tools/builtin/ai/tool_create.ts +52 -0
- package/src/tools/builtin/code/analyze_deps.ts +72 -0
- package/src/tools/builtin/code/bug_scan.ts +80 -0
- package/src/tools/builtin/code/code_metrics.ts +111 -0
- package/src/tools/builtin/code/extract_function.ts +86 -0
- package/src/tools/builtin/code/format_code.ts +57 -0
- package/src/tools/builtin/code/generate_code.ts +75 -0
- package/src/tools/builtin/code/import_organizer.ts +82 -0
- package/src/tools/builtin/code/lint_code.ts +48 -0
- package/src/tools/builtin/code/parse_ast.ts +86 -0
- package/src/tools/builtin/code/refactor_code.ts +63 -0
- package/src/tools/builtin/code/type_check.ts +48 -0
- package/src/tools/builtin/data/chart_generate.ts +62 -0
- package/src/tools/builtin/data/csv_parse.ts +56 -0
- package/src/tools/builtin/data/data_diff.ts +79 -0
- package/src/tools/builtin/data/data_transform.ts +74 -0
- package/src/tools/builtin/data/data_validate.ts +75 -0
- package/src/tools/builtin/data/json_parse.ts +71 -0
- package/src/tools/builtin/data/template_render.ts +58 -0
- package/src/tools/builtin/data/toml_parse.ts +42 -0
- package/src/tools/builtin/data/xml_parse.ts +79 -0
- package/src/tools/builtin/data/yaml_parse.ts +42 -0
- package/src/tools/builtin/database/db_backup.ts +53 -0
- package/src/tools/builtin/database/db_restore.ts +51 -0
- package/src/tools/builtin/database/db_schema.ts +66 -0
- package/src/tools/builtin/database/nosql_query.ts +50 -0
- package/src/tools/builtin/database/orm_generate.ts +66 -0
- package/src/tools/builtin/database/redis_command.ts +46 -0
- package/src/tools/builtin/database/sql_migrate.ts +55 -0
- package/src/tools/builtin/database/sql_query.ts +60 -0
- package/src/tools/builtin/filesystem/batch_read.ts +56 -0
- package/src/tools/builtin/filesystem/batch_write.ts +67 -0
- package/src/tools/builtin/filesystem/copy_file.ts +36 -0
- package/src/tools/builtin/filesystem/create_dir.ts +30 -0
- package/src/tools/builtin/filesystem/delete_file.ts +30 -0
- package/src/tools/builtin/filesystem/diff_files.ts +47 -0
- package/src/tools/builtin/filesystem/edit_file.ts +47 -0
- package/src/tools/builtin/filesystem/file_info.ts +52 -0
- package/src/tools/builtin/filesystem/glob_find.ts +44 -0
- package/src/tools/builtin/filesystem/list_dir.ts +51 -0
- package/src/tools/builtin/filesystem/merge_files.ts +44 -0
- package/src/tools/builtin/filesystem/move_file.ts +37 -0
- package/src/tools/builtin/filesystem/read_file.ts +55 -0
- package/src/tools/builtin/filesystem/watch_file.ts +33 -0
- package/src/tools/builtin/filesystem/write_file.ts +45 -0
- package/src/tools/builtin/index.ts +244 -0
- package/src/tools/builtin/network/api_call.ts +79 -0
- package/src/tools/builtin/network/browser_action.ts +54 -0
- package/src/tools/builtin/network/check_url.ts +59 -0
- package/src/tools/builtin/network/download_file.ts +64 -0
- package/src/tools/builtin/network/graphql_query.ts +46 -0
- package/src/tools/builtin/network/http_request.ts +61 -0
- package/src/tools/builtin/network/parse_html.ts +101 -0
- package/src/tools/builtin/network/proxy_request.ts +53 -0
- package/src/tools/builtin/network/screenshot_page.ts +58 -0
- package/src/tools/builtin/network/web_fetch.ts +70 -0
- package/src/tools/builtin/network/web_search.ts +128 -0
- package/src/tools/builtin/network/websocket_connect.ts +70 -0
- package/src/tools/builtin/project/build_project.ts +68 -0
- package/src/tools/builtin/project/config_manage.ts +99 -0
- package/src/tools/builtin/project/coverage_report.ts +59 -0
- package/src/tools/builtin/project/docker_manage.ts +90 -0
- package/src/tools/builtin/project/env_manage.ts +88 -0
- package/src/tools/builtin/project/npm_manage.ts +71 -0
- package/src/tools/builtin/project/project_init.ts +59 -0
- package/src/tools/builtin/project/run_test.ts +74 -0
- package/src/tools/builtin/search/codebase_search.ts +76 -0
- package/src/tools/builtin/search/find_definition.ts +84 -0
- package/src/tools/builtin/search/find_references.ts +75 -0
- package/src/tools/builtin/search/fuzzy_find.ts +75 -0
- package/src/tools/builtin/search/grep_search.ts +90 -0
- package/src/tools/builtin/search/regex_find.ts +91 -0
- package/src/tools/builtin/search/search_docs.ts +51 -0
- package/src/tools/builtin/search/search_package.ts +50 -0
- package/src/tools/builtin/search/symbol_search.ts +82 -0
- package/src/tools/builtin/search/text_search.ts +63 -0
- package/src/tools/builtin/security/decrypt_file.ts +54 -0
- package/src/tools/builtin/security/encrypt_file.ts +52 -0
- package/src/tools/builtin/security/hash_generate.ts +48 -0
- package/src/tools/builtin/security/jwt_decode.ts +53 -0
- package/src/tools/builtin/security/secret_scan.ts +82 -0
- package/src/tools/builtin/security/vulnerability_check.ts +71 -0
- package/src/tools/builtin/shell/background_terminal.ts +38 -0
- package/src/tools/builtin/shell/check_status.ts +48 -0
- package/src/tools/builtin/shell/interactive_terminal.ts +31 -0
- package/src/tools/builtin/shell/kill_terminal.ts +29 -0
- package/src/tools/builtin/shell/list_terminals.ts +61 -0
- package/src/tools/builtin/shell/pipe_commands.ts +55 -0
- package/src/tools/builtin/shell/process-pool.ts +150 -0
- package/src/tools/builtin/shell/run_async.ts +73 -0
- package/src/tools/builtin/shell/run_command.ts +60 -0
- package/src/tools/builtin/shell/send_ctrl_keys.ts +43 -0
- package/src/tools/builtin/shell/send_keys.ts +36 -0
- package/src/tools/builtin/shell/send_text.ts +35 -0
- package/src/tools/builtin/shell/shell_script.ts +65 -0
- package/src/tools/builtin/shell/stop_command.ts +40 -0
- package/src/tools/builtin/shell/terminal_resize.ts +31 -0
- package/src/tools/builtin/shell/terminal_screenshot.ts +28 -0
- package/src/tools/builtin/system/log_viewer.ts +89 -0
- package/src/tools/builtin/system/notify_user.ts +55 -0
- package/src/tools/builtin/system/process_list.ts +66 -0
- package/src/tools/builtin/system/resource_monitor.ts +66 -0
- package/src/tools/builtin/system/system_info.ts +41 -0
- package/src/tools/tool-types.ts +97 -0
- package/src/ui/AgentTree.tsx +98 -0
- package/src/ui/App.tsx +46 -0
- package/src/ui/ChatView.tsx +278 -0
- package/src/ui/ConfirmDialog.tsx +68 -0
- package/src/ui/DiffView.tsx +64 -0
- package/src/ui/FilePreview.tsx +59 -0
- package/src/ui/InputBox.tsx +267 -0
- package/src/ui/MessageBubble.tsx +30 -0
- package/src/ui/Spinner.tsx +35 -0
- package/src/ui/StatusBar.tsx +41 -0
- package/src/ui/ToolCallCard.tsx +73 -0
- package/src/ui/ansi.ts +50 -0
- package/src/ui/markdown.ts +238 -0
- package/src/ui/themes/dark.ts +4 -0
- package/src/ui/themes/default.ts +25 -0
- package/src/ui/themes/light.ts +14 -0
- package/tests/unit/BuiltinTools.test.ts +129 -0
- package/tests/unit/BuiltinToolsIntegration.test.ts +111 -0
- package/tests/unit/FilesystemTools.test.ts +211 -0
- package/tests/unit/SkillLoader.test.ts +141 -0
- package/tests/unit/SkillRegistry.test.ts +113 -0
- package/tests/unit/ToolExecutor.test.ts +160 -0
- package/tests/unit/ToolRegistry.test.ts +103 -0
- package/tests/unit/ToolValidator.test.ts +137 -0
- package/tsconfig.json +28 -0
- package/tsup.config.ts +17 -0
- package/vitest.config.ts +20 -0
package/src/cli/index.ts
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs } from 'node:util';
|
|
3
|
+
import { DEEPER_VERSION } from '../core/constants.ts';
|
|
4
|
+
|
|
5
|
+
async function main() {
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
|
|
8
|
+
if (args.length === 0) {
|
|
9
|
+
return startChat({});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { values, positionals } = parseArgs({
|
|
13
|
+
args,
|
|
14
|
+
options: {
|
|
15
|
+
help: { type: 'boolean', short: 'h' },
|
|
16
|
+
version: { type: 'boolean', short: 'v' },
|
|
17
|
+
model: { type: 'string', short: 'm' },
|
|
18
|
+
'api-key': { type: 'string', short: 'k' },
|
|
19
|
+
verbose: { type: 'boolean' },
|
|
20
|
+
'auto-run': { type: 'string' },
|
|
21
|
+
},
|
|
22
|
+
allowPositionals: true,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
if (values.help) {
|
|
26
|
+
showHelp();
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (values.version) {
|
|
31
|
+
console.log(`DeeperCode v${DEEPER_VERSION}`);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const command = positionals[0];
|
|
36
|
+
const commandArgs = positionals.slice(1);
|
|
37
|
+
|
|
38
|
+
const globalOpts = {
|
|
39
|
+
model: values.model || process.env.DEEPER_MODEL,
|
|
40
|
+
apiKey: values['api-key'] || process.env.DEEPSEEK_API_KEY,
|
|
41
|
+
verbose: values.verbose,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
switch (command) {
|
|
45
|
+
case 'chat':
|
|
46
|
+
case 'repl': {
|
|
47
|
+
await startChat({
|
|
48
|
+
...globalOpts,
|
|
49
|
+
autoRun: values['auto-run'],
|
|
50
|
+
});
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
case 'run':
|
|
55
|
+
case 'exec': {
|
|
56
|
+
const task = commandArgs.join(' ');
|
|
57
|
+
if (!task) {
|
|
58
|
+
console.error('❌ 请提供任务描述');
|
|
59
|
+
console.error(' 用法: deeper run "任务描述"');
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
const { run } = await import('./commands/run.ts');
|
|
63
|
+
await run(task, globalOpts);
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
case 'config': {
|
|
68
|
+
const { configCommand } = await import('./commands/config.ts');
|
|
69
|
+
await configCommand(commandArgs);
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
case 'skill':
|
|
74
|
+
case 'skills': {
|
|
75
|
+
const { skillCommand } = await import('./commands/skill.ts');
|
|
76
|
+
await skillCommand(commandArgs);
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
case 'mcp': {
|
|
81
|
+
const { mcpCommand } = await import('./commands/mcp.ts');
|
|
82
|
+
await mcpCommand(commandArgs);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
case 'version': {
|
|
87
|
+
console.log(`DeeperCode v${DEEPER_VERSION}`);
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
default: {
|
|
92
|
+
const task = positionals.join(' ').trim();
|
|
93
|
+
if (task) {
|
|
94
|
+
const { run } = await import('./commands/run.ts');
|
|
95
|
+
await run(task, globalOpts);
|
|
96
|
+
} else {
|
|
97
|
+
console.error(`未知命令: ${positionals[0] || ''}`);
|
|
98
|
+
console.error('使用 --help 查看帮助');
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function startChat(opts: {
|
|
106
|
+
model?: string;
|
|
107
|
+
apiKey?: string;
|
|
108
|
+
verbose?: boolean;
|
|
109
|
+
autoRun?: string;
|
|
110
|
+
}) {
|
|
111
|
+
const { chat } = await import('./commands/chat.js');
|
|
112
|
+
await chat(opts);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function showHelp() {
|
|
116
|
+
console.log(`
|
|
117
|
+
██████╗ ███████╗███████╗██████╗ ███████╗██████╗
|
|
118
|
+
██╔══██╗██╔════╝██╔════╝██╔══██╗██╔════╝██╔══██╗
|
|
119
|
+
██║ ██║█████╗ █████╗ ██████╔╝█████╗ ██████╔╝
|
|
120
|
+
██║ ██║██╔══╝ ██╔══╝ ██╔═══╝ ██╔══╝ ██╔══██╗
|
|
121
|
+
██████╔╝███████╗███████╗██║ ███████╗██║ ██║
|
|
122
|
+
╚═════╝ ╚══════╝╚══════╝╚═╝ ╚══════╝╚═╝ ╚═╝
|
|
123
|
+
██████╗ ██████╗ ██████╗ ███████╗
|
|
124
|
+
██╔════╝██╔═══██╗██╔══██╗██╔════╝
|
|
125
|
+
██║ ██║ ██║██║ ██║█████╗
|
|
126
|
+
██║ ██║ ██║██║ ██║██╔══╝
|
|
127
|
+
╚██████╗╚██████╔╝██████╔╝███████╗
|
|
128
|
+
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
|
|
129
|
+
|
|
130
|
+
DeeperCode v${DEEPER_VERSION} - 一句话生成完整项目的 AI Agentic CLI 工具
|
|
131
|
+
|
|
132
|
+
用法:
|
|
133
|
+
deeper [options] 启动交互式 REPL
|
|
134
|
+
deeper chat [options] 启动聊天模式
|
|
135
|
+
deeper run "任务描述" [options] 单次执行任务
|
|
136
|
+
deeper config <subcommand> 配置管理
|
|
137
|
+
deeper skill <subcommand> Skill 管理
|
|
138
|
+
deeper mcp <subcommand> MCP 管理
|
|
139
|
+
|
|
140
|
+
选项:
|
|
141
|
+
-h, --help 显示帮助信息
|
|
142
|
+
-v, --version 显示版本号
|
|
143
|
+
-m, --model <model> 指定模型 (默认: deepseek-v4-pro, 可选: v4-flash)
|
|
144
|
+
-k, --api-key <key> 指定 API Key
|
|
145
|
+
--verbose 详细输出模式
|
|
146
|
+
--auto-run <task> 自动运行任务后进入 REPL
|
|
147
|
+
|
|
148
|
+
子命令:
|
|
149
|
+
deeper config list 列出配置
|
|
150
|
+
deeper config set <key> <value> 设置配置
|
|
151
|
+
deeper config get <key> 获取配置
|
|
152
|
+
deeper config reset 重置配置
|
|
153
|
+
|
|
154
|
+
deeper skill list 列出 Skills
|
|
155
|
+
deeper skill create <name> 创建 Skill
|
|
156
|
+
|
|
157
|
+
deeper mcp list 列出 MCP 服务器
|
|
158
|
+
deeper mcp add <name> ... 添加 MCP 服务器
|
|
159
|
+
deeper mcp remove <name> 移除 MCP 服务器
|
|
160
|
+
|
|
161
|
+
环境变量:
|
|
162
|
+
DEEPSEEK_API_KEY DeepSeek API Key
|
|
163
|
+
DEEPER_HOME DeeperCode 数据目录 (默认: ~/.deeper)
|
|
164
|
+
DEEPER_MODEL 默认模型名称
|
|
165
|
+
|
|
166
|
+
内存:
|
|
167
|
+
如遇 OOM,使用 node --max-old-space-size=4096 $(which deeper) 启动
|
|
168
|
+
Windows: set NODE_OPTIONS=--max-old-space-size=4096 && deeper
|
|
169
|
+
|
|
170
|
+
示例:
|
|
171
|
+
deeper 启动交互式 REPL
|
|
172
|
+
deeper run "创建一个 React 应用" 单次执行
|
|
173
|
+
deeper --model deepseek-v4-pro -k sk-xxxx 指定模型和密钥
|
|
174
|
+
deeper --model deepseek-v4-flash 使用快速模型
|
|
175
|
+
deeper config set theme light 切换亮色主题
|
|
176
|
+
|
|
177
|
+
使用 DeepSeek-V4-Pro 驱动 | 105+ 内置工具 | 强大的 Agent 系统
|
|
178
|
+
`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
main().catch((err) => {
|
|
182
|
+
console.error('❌ 启动失败:', err instanceof Error ? err.message : String(err));
|
|
183
|
+
process.exit(1);
|
|
184
|
+
});
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { extname, basename } from 'node:path';
|
|
3
|
+
|
|
4
|
+
const MAX_FILE_SIZE = 500_000;
|
|
5
|
+
|
|
6
|
+
export interface BugReport {
|
|
7
|
+
file: string;
|
|
8
|
+
line?: number;
|
|
9
|
+
severity: 'error' | 'warning' | 'info';
|
|
10
|
+
message: string;
|
|
11
|
+
suggestion?: string;
|
|
12
|
+
category: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const LANG_CONFIGS: Record<string, { name: string; patterns: Array<{ re: RegExp; severity: BugReport['severity']; cat: string; msg: string; hint?: string }> }> = {
|
|
16
|
+
'.ts': { name: 'TypeScript', patterns: [
|
|
17
|
+
{ re: /:\s*any\b/g, severity: 'warning', cat: '类型安全', msg: '使用了 `any` 类型,建议指定具体类型', hint: '将 `any` 替换为具体接口或类型' },
|
|
18
|
+
{ re: /console\.(log|warn|error|debug)\(/g, severity: 'info', cat: '调试代码', msg: '生产代码中留有 console 调用', hint: '移除此调试语句或使用 logger' },
|
|
19
|
+
{ re: /as\s+[A-Z]\w+/g, severity: 'warning', cat: '类型安全', msg: '使用 `as` 类型断言', hint: '优先使用类型守卫替代类型断言' },
|
|
20
|
+
{ re: /@ts-ignore/g, severity: 'warning', cat: '类型安全', msg: '使用 @ts-ignore 忽略类型检查', hint: '修复类型错误而非忽略' },
|
|
21
|
+
{ re: /setTimeout\([^,)]*\)/g, severity: 'info', cat: '可靠性', msg: 'setTimeout 缺少错误处理', hint: '考虑在回调中添加 try-catch' },
|
|
22
|
+
]},
|
|
23
|
+
'.js': { name: 'JavaScript', patterns: [
|
|
24
|
+
{ re: /console\.(log|warn|error|debug)\(/g, severity: 'info', cat: '调试代码', msg: '生产代码中留有 console 调用' },
|
|
25
|
+
{ re: /var\s+/g, severity: 'warning', cat: '代码风格', msg: '使用了 `var`,建议使用 `const`/`let`' },
|
|
26
|
+
{ re: /==(?!=)/g, severity: 'warning', cat: '逻辑错误', msg: '使用了 `==` 而非 `===`', hint: '使用 `===` 进行严格比较' },
|
|
27
|
+
{ re: /eval\(/g, severity: 'error', cat: '安全', msg: '使用 eval() 存在安全风险', hint: '避免使用 eval' },
|
|
28
|
+
{ re: /innerHTML\s*=/g, severity: 'warning', cat: '安全', msg: '直接修改 innerHTML 有 XSS 风险', hint: '使用 textContent 或安全 DOM 方法' },
|
|
29
|
+
]},
|
|
30
|
+
'.py': { name: 'Python', patterns: [
|
|
31
|
+
{ re: /except\s*:/g, severity: 'warning', cat: '错误处理', msg: '使用了裸 except 捕获所有异常' },
|
|
32
|
+
{ re: /except\s+Exception\s*:/g, severity: 'info', cat: '错误处理', msg: '捕获范围过宽', hint: '捕获更具体的异常类型' },
|
|
33
|
+
{ re: /:\s*print\(/g, severity: 'info', cat: '调试代码', msg: '生产代码中留有 print 调用' },
|
|
34
|
+
{ re: /input\(/g, severity: 'info', cat: '安全', msg: '未校验用户输入' },
|
|
35
|
+
{ re: /exec\(/g, severity: 'error', cat: '安全', msg: '使用 exec() 存在安全风险' },
|
|
36
|
+
{ re: /import\s+\*/g, severity: 'info', cat: '代码风格', msg: '通配符导入,建议明确导入' },
|
|
37
|
+
]},
|
|
38
|
+
'.json': { name: 'JSON', patterns: [
|
|
39
|
+
]},
|
|
40
|
+
'.css': { name: 'CSS', patterns: [
|
|
41
|
+
{ re: /!important/g, severity: 'warning', cat: 'CSS 反模式', msg: '使用 !important', hint: '通过提高选择器特异性替代' },
|
|
42
|
+
{ re: /position:\s*absolute/g, severity: 'info', cat: '布局', msg: '大量 absolute 定位可能影响响应式' },
|
|
43
|
+
]},
|
|
44
|
+
'.html': { name: 'HTML', patterns: [
|
|
45
|
+
{ re: /<script[^>]*>/, severity: 'info', cat: '安全', msg: '内联 script 标签' },
|
|
46
|
+
{ re: /on\w+\s*=/, severity: 'warning', cat: '安全', msg: '内联事件处理器 (onclick 等)', hint: '使用 addEventListener 替代' },
|
|
47
|
+
]},
|
|
48
|
+
'.java': { name: 'Java', patterns: [
|
|
49
|
+
{ re: /System\.out\.print/, severity: 'info', cat: '调试代码', msg: '留有 System.out 调用', hint: '使用日志框架替代' },
|
|
50
|
+
{ re: /catch\s*\(\s*Exception\s+/g, severity: 'warning', cat: '错误处理', msg: '捕获范围过宽' },
|
|
51
|
+
]},
|
|
52
|
+
'.go': { name: 'Go', patterns: [
|
|
53
|
+
{ re: /_,\s*_\s*:=/g, severity: 'warning', cat: '错误处理', msg: '忽略了错误返回值', hint: '应处理返回的 error' },
|
|
54
|
+
{ re: /panic\(/g, severity: 'warning', cat: '错误处理', msg: '使用 panic 而非 error 返回', hint: '优先使用 error 返回值' },
|
|
55
|
+
]},
|
|
56
|
+
'.rs': { name: 'Rust', patterns: [
|
|
57
|
+
{ re: /\.unwrap\(\)/g, severity: 'warning', cat: '错误处理', msg: '使用 unwrap() 可能导致 panic', hint: '使用 ? 或 match 处理错误' },
|
|
58
|
+
{ re: /unsafe\s*\{/g, severity: 'warning', cat: '安全', msg: '使用了 unsafe 块' },
|
|
59
|
+
]},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export function analyzeFile(filePath: string): BugReport[] {
|
|
63
|
+
if (!existsSync(filePath)) return [];
|
|
64
|
+
try { if (statSync(filePath).size > MAX_FILE_SIZE) return []; } catch { return []; }
|
|
65
|
+
const reports: BugReport[] = [];
|
|
66
|
+
const ext = extname(filePath).toLowerCase();
|
|
67
|
+
const config = LANG_CONFIGS[ext];
|
|
68
|
+
if (!config) return [];
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
72
|
+
const lines = content.split('\n');
|
|
73
|
+
|
|
74
|
+
for (const pattern of config.patterns) {
|
|
75
|
+
if (!pattern.msg) continue;
|
|
76
|
+
let match;
|
|
77
|
+
pattern.re.lastIndex = 0;
|
|
78
|
+
while ((match = pattern.re.exec(content)) !== null) {
|
|
79
|
+
if (!pattern.msg) continue;
|
|
80
|
+
const lineNum = content.slice(0, match.index).split('\n').length;
|
|
81
|
+
reports.push({
|
|
82
|
+
file: basename(filePath),
|
|
83
|
+
line: lineNum,
|
|
84
|
+
severity: pattern.severity,
|
|
85
|
+
message: pattern.msg,
|
|
86
|
+
suggestion: pattern.hint,
|
|
87
|
+
category: pattern.cat,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 通用检查 (跨语言)
|
|
93
|
+
for (let i = 0; i < lines.length; i++) {
|
|
94
|
+
const line = lines[i];
|
|
95
|
+
const trimmed = line.trim();
|
|
96
|
+
|
|
97
|
+
// 超长行
|
|
98
|
+
if (trimmed.length > 200 && !trimmed.startsWith('//') && !trimmed.startsWith('#')) {
|
|
99
|
+
reports.push({
|
|
100
|
+
file: basename(filePath), line: i + 1, severity: 'info',
|
|
101
|
+
message: `行过长 (${trimmed.length} 字符)`, suggestion: '考虑拆分或格式化',
|
|
102
|
+
category: '代码风格',
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// TODO/FIXME/HACK/BUG 标记
|
|
107
|
+
if (/\/\/\s*(TODO|FIXME|HACK|BUG|XXX)\b/i.test(trimmed) ||
|
|
108
|
+
/#\s*(TODO|FIXME|HACK|BUG|XXX)\b/i.test(trimmed)) {
|
|
109
|
+
const tag = trimmed.match(/(?:TODO|FIXME|HACK|BUG|XXX)/i)?.[0] || '';
|
|
110
|
+
reports.push({
|
|
111
|
+
file: basename(filePath), line: i + 1,
|
|
112
|
+
severity: tag === 'BUG' ? 'error' : tag === 'FIXME' ? 'warning' : 'info',
|
|
113
|
+
message: `标记为 ${tag}`, suggestion: '建议及时处理',
|
|
114
|
+
category: '代码标记',
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
} catch { return []; }
|
|
119
|
+
|
|
120
|
+
return reports;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function summarizeBugs(reports: BugReport[]): string {
|
|
124
|
+
if (reports.length === 0) return '';
|
|
125
|
+
const errs = reports.filter(r => r.severity === 'error').length;
|
|
126
|
+
const warns = reports.filter(r => r.severity === 'warning').length;
|
|
127
|
+
const infos = reports.filter(r => r.severity === 'info').length;
|
|
128
|
+
|
|
129
|
+
let s = `[BugScan] 检查发现 ${reports.length} 个问题`;
|
|
130
|
+
if (errs > 0) s += ` · ${errs} ❌错误`;
|
|
131
|
+
if (warns > 0) s += ` · ${warns} ⚠警告`;
|
|
132
|
+
if (infos > 0) s += ` · ${infos} ℹ提示`;
|
|
133
|
+
s += '\n';
|
|
134
|
+
|
|
135
|
+
const top = reports.slice(0, 8);
|
|
136
|
+
for (const r of top) {
|
|
137
|
+
const sev = r.severity === 'error' ? '❌' : r.severity === 'warning' ? '⚠' : 'ℹ';
|
|
138
|
+
s += `${sev} ${r.file}:${r.line ?? '?'} [${r.category}] ${r.message}`;
|
|
139
|
+
if (r.suggestion) s += ` → ${r.suggestion}`;
|
|
140
|
+
s += '\n';
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (reports.length > 8) s += `... 还有 ${reports.length - 8} 个问题\n`;
|
|
144
|
+
return s;
|
|
145
|
+
}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import process from 'node:process';
|
|
4
|
+
import { DEEPER_CONFIG_FILE, PROJECT_CONFIG_FILE, DEEPSEEK_DEFAULT_MODEL, DEEPSEEK_BASE_URL } from './constants.js';
|
|
5
|
+
|
|
6
|
+
export interface MCPConfigEntry {
|
|
7
|
+
name: string;
|
|
8
|
+
command?: string;
|
|
9
|
+
args?: string[];
|
|
10
|
+
url?: string;
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
autoConnect: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface SkillConfigEntry {
|
|
16
|
+
name: string;
|
|
17
|
+
path: string;
|
|
18
|
+
enabled: boolean;
|
|
19
|
+
autoLoad: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface DeeperConfig {
|
|
23
|
+
model: string;
|
|
24
|
+
apiKey: string;
|
|
25
|
+
baseUrl: string;
|
|
26
|
+
temperature: number;
|
|
27
|
+
maxTokens: number;
|
|
28
|
+
thinkEnabled: boolean;
|
|
29
|
+
thinkBudget: number;
|
|
30
|
+
thinkBudgetTokens: number;
|
|
31
|
+
logLevel: string;
|
|
32
|
+
maxRetries: number;
|
|
33
|
+
timeoutMs: number;
|
|
34
|
+
maxSubAgents: number;
|
|
35
|
+
maxRecursionDepth: number;
|
|
36
|
+
theme: 'dark' | 'light';
|
|
37
|
+
locale: string;
|
|
38
|
+
mcpServers: MCPConfigEntry[];
|
|
39
|
+
skills: SkillConfigEntry[];
|
|
40
|
+
[key: string]: unknown;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const DEFAULT_CONFIG: DeeperConfig = {
|
|
44
|
+
model: DEEPSEEK_DEFAULT_MODEL,
|
|
45
|
+
apiKey: process.env.DEEPSEEK_API_KEY || '',
|
|
46
|
+
baseUrl: DEEPSEEK_BASE_URL,
|
|
47
|
+
temperature: 0.7,
|
|
48
|
+
maxTokens: 8192,
|
|
49
|
+
thinkEnabled: true,
|
|
50
|
+
thinkBudget: 32000,
|
|
51
|
+
thinkBudgetTokens: 32000,
|
|
52
|
+
logLevel: 'info',
|
|
53
|
+
maxRetries: 3,
|
|
54
|
+
timeoutMs: 120000,
|
|
55
|
+
maxSubAgents: 5,
|
|
56
|
+
maxRecursionDepth: 2,
|
|
57
|
+
theme: 'dark',
|
|
58
|
+
locale: 'zh-CN',
|
|
59
|
+
mcpServers: [],
|
|
60
|
+
skills: [],
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const PROJECT_CONFIG_PATH = join(process.cwd(), PROJECT_CONFIG_FILE);
|
|
64
|
+
const USER_CONFIG_PATH = DEEPER_CONFIG_FILE;
|
|
65
|
+
|
|
66
|
+
export class ConfigManager {
|
|
67
|
+
private defaults: DeeperConfig;
|
|
68
|
+
private userConfig: Partial<DeeperConfig>;
|
|
69
|
+
private projectConfig: Partial<DeeperConfig>;
|
|
70
|
+
private envOverrides: Partial<DeeperConfig>;
|
|
71
|
+
private cliOverrides: Partial<DeeperConfig>;
|
|
72
|
+
|
|
73
|
+
constructor() {
|
|
74
|
+
this.defaults = { ...DEFAULT_CONFIG };
|
|
75
|
+
this.userConfig = {};
|
|
76
|
+
this.projectConfig = {};
|
|
77
|
+
this.envOverrides = {};
|
|
78
|
+
this.cliOverrides = {};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
load(): void {
|
|
82
|
+
this.userConfig = this.readJSONFile(USER_CONFIG_PATH);
|
|
83
|
+
this.projectConfig = this.readJSONFile(PROJECT_CONFIG_PATH);
|
|
84
|
+
this.envOverrides = this.readEnvOverrides();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
save(scope: 'user' | 'project'): void {
|
|
88
|
+
const configPath = scope === 'user' ? USER_CONFIG_PATH : PROJECT_CONFIG_PATH;
|
|
89
|
+
const currentConfig = scope === 'user' ? this.userConfig : this.projectConfig;
|
|
90
|
+
const dir = dirname(configPath);
|
|
91
|
+
if (!existsSync(dir)) {
|
|
92
|
+
mkdirSync(dir, { recursive: true });
|
|
93
|
+
}
|
|
94
|
+
writeFileSync(configPath, JSON.stringify(currentConfig, null, 2), 'utf-8');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
get<K extends keyof DeeperConfig>(key: K): DeeperConfig[K] {
|
|
98
|
+
if (key in this.cliOverrides) {
|
|
99
|
+
return this.cliOverrides[key] as DeeperConfig[K];
|
|
100
|
+
}
|
|
101
|
+
if (key in this.envOverrides) {
|
|
102
|
+
return this.envOverrides[key] as DeeperConfig[K];
|
|
103
|
+
}
|
|
104
|
+
if (key in this.projectConfig) {
|
|
105
|
+
return this.projectConfig[key] as DeeperConfig[K];
|
|
106
|
+
}
|
|
107
|
+
if (key in this.userConfig) {
|
|
108
|
+
return this.userConfig[key] as DeeperConfig[K];
|
|
109
|
+
}
|
|
110
|
+
return this.defaults[key];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
set<K extends keyof DeeperConfig>(key: K, value: DeeperConfig[K], scope: 'cli' | 'project' | 'user'): void {
|
|
114
|
+
switch (scope) {
|
|
115
|
+
case 'cli':
|
|
116
|
+
this.cliOverrides[key] = value;
|
|
117
|
+
break;
|
|
118
|
+
case 'project':
|
|
119
|
+
this.projectConfig[key] = value;
|
|
120
|
+
break;
|
|
121
|
+
case 'user':
|
|
122
|
+
this.userConfig[key] = value;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
setCliOverrides(overrides: Partial<DeeperConfig>): void {
|
|
128
|
+
this.cliOverrides = { ...overrides };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
getAll(): DeeperConfig {
|
|
132
|
+
return {
|
|
133
|
+
...this.defaults,
|
|
134
|
+
...this.userConfig,
|
|
135
|
+
...this.projectConfig,
|
|
136
|
+
...this.envOverrides,
|
|
137
|
+
...this.cliOverrides,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private readJSONFile(path: string): Partial<DeeperConfig> {
|
|
142
|
+
try {
|
|
143
|
+
if (existsSync(path)) {
|
|
144
|
+
const content = readFileSync(path, 'utf-8');
|
|
145
|
+
return JSON.parse(content) as Partial<DeeperConfig>;
|
|
146
|
+
}
|
|
147
|
+
} catch {
|
|
148
|
+
}
|
|
149
|
+
return {};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private readEnvOverrides(): Partial<DeeperConfig> {
|
|
153
|
+
const overrides: Partial<DeeperConfig> = {};
|
|
154
|
+
const envMap: Record<string, keyof DeeperConfig> = {
|
|
155
|
+
DEEPER_MODEL: 'model',
|
|
156
|
+
DEEPER_API_KEY: 'apiKey',
|
|
157
|
+
DEEPER_BASE_URL: 'baseUrl',
|
|
158
|
+
DEEPER_TEMPERATURE: 'temperature',
|
|
159
|
+
DEEPER_MAX_TOKENS: 'maxTokens',
|
|
160
|
+
DEEPER_THINK_ENABLED: 'thinkEnabled',
|
|
161
|
+
DEEPER_THINK_BUDGET: 'thinkBudget',
|
|
162
|
+
DEEPER_LOG_LEVEL: 'logLevel',
|
|
163
|
+
DEEPER_MAX_RETRIES: 'maxRetries',
|
|
164
|
+
DEEPER_TIMEOUT: 'timeoutMs',
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
for (const [envKey, configKey] of Object.entries(envMap)) {
|
|
168
|
+
const value = process.env[envKey];
|
|
169
|
+
if (value !== undefined) {
|
|
170
|
+
switch (typeof DEFAULT_CONFIG[configKey]) {
|
|
171
|
+
case 'number':
|
|
172
|
+
(overrides as Record<string, unknown>)[configKey] = Number(value);
|
|
173
|
+
break;
|
|
174
|
+
case 'boolean':
|
|
175
|
+
(overrides as Record<string, unknown>)[configKey] = value.toLowerCase() === 'true' || value === '1';
|
|
176
|
+
break;
|
|
177
|
+
default:
|
|
178
|
+
(overrides as Record<string, unknown>)[configKey] = value;
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return overrides;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let cachedConfig: DeeperConfig | null = null;
|
|
189
|
+
|
|
190
|
+
const KEY_ALIASES: Record<string, keyof DeeperConfig> = {
|
|
191
|
+
api_key: 'apiKey',
|
|
192
|
+
'api-key': 'apiKey',
|
|
193
|
+
base_url: 'baseUrl',
|
|
194
|
+
'base-url': 'baseUrl',
|
|
195
|
+
max_tokens: 'maxTokens',
|
|
196
|
+
'max-tokens': 'maxTokens',
|
|
197
|
+
think_enabled: 'thinkEnabled',
|
|
198
|
+
'think-enabled': 'thinkEnabled',
|
|
199
|
+
think_budget: 'thinkBudget',
|
|
200
|
+
'think-budget': 'thinkBudget',
|
|
201
|
+
log_level: 'logLevel',
|
|
202
|
+
'log-level': 'logLevel',
|
|
203
|
+
max_retries: 'maxRetries',
|
|
204
|
+
'max-retries': 'maxRetries',
|
|
205
|
+
timeout_ms: 'timeoutMs',
|
|
206
|
+
'timeout-ms': 'timeoutMs',
|
|
207
|
+
max_sub_agents: 'maxSubAgents',
|
|
208
|
+
'max-sub-agents': 'maxSubAgents',
|
|
209
|
+
max_recursion_depth: 'maxRecursionDepth',
|
|
210
|
+
'max-recursion-depth': 'maxRecursionDepth',
|
|
211
|
+
mcp_servers: 'mcpServers',
|
|
212
|
+
'mcp-servers': 'mcpServers',
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
function normalizeConfig(raw: Record<string, unknown>): Partial<DeeperConfig> {
|
|
216
|
+
const result: Record<string, unknown> = {};
|
|
217
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
218
|
+
const canonical = KEY_ALIASES[key] || key;
|
|
219
|
+
result[canonical] = value;
|
|
220
|
+
}
|
|
221
|
+
return result as Partial<DeeperConfig>;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export function loadConfig(): DeeperConfig {
|
|
225
|
+
if (cachedConfig) return cachedConfig;
|
|
226
|
+
try {
|
|
227
|
+
if (existsSync(DEEPER_CONFIG_FILE)) {
|
|
228
|
+
const raw = readFileSync(DEEPER_CONFIG_FILE, 'utf-8');
|
|
229
|
+
const parsed = JSON.parse(raw) as Record<string, unknown>;
|
|
230
|
+
cachedConfig = { ...DEFAULT_CONFIG, ...normalizeConfig(parsed) };
|
|
231
|
+
} else {
|
|
232
|
+
cachedConfig = { ...DEFAULT_CONFIG };
|
|
233
|
+
}
|
|
234
|
+
} catch {
|
|
235
|
+
cachedConfig = { ...DEFAULT_CONFIG };
|
|
236
|
+
}
|
|
237
|
+
return cachedConfig;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export function saveConfig(config?: DeeperConfig): void {
|
|
241
|
+
if (config) cachedConfig = { ...config };
|
|
242
|
+
if (!cachedConfig) cachedConfig = { ...DEFAULT_CONFIG };
|
|
243
|
+
const dir = dirname(DEEPER_CONFIG_FILE);
|
|
244
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
245
|
+
writeFileSync(DEEPER_CONFIG_FILE, JSON.stringify(cachedConfig, null, 2), 'utf-8');
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export function getConfig(): DeeperConfig {
|
|
249
|
+
return cachedConfig ?? loadConfig();
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export function updateConfig(partial: Partial<DeeperConfig>): DeeperConfig {
|
|
253
|
+
const current = getConfig();
|
|
254
|
+
cachedConfig = { ...current, ...partial };
|
|
255
|
+
saveConfig();
|
|
256
|
+
return cachedConfig;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export function resetConfig(): DeeperConfig {
|
|
260
|
+
cachedConfig = { ...DEFAULT_CONFIG };
|
|
261
|
+
saveConfig();
|
|
262
|
+
return cachedConfig;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export function getConfigValue<K extends keyof DeeperConfig>(key: K): DeeperConfig[K] {
|
|
266
|
+
return getConfig()[key];
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export function setConfigValue<K extends keyof DeeperConfig>(key: K, value: DeeperConfig[K]): void {
|
|
270
|
+
updateConfig({ [key]: value } as unknown as Partial<DeeperConfig>);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export function getApiKey(): string {
|
|
274
|
+
return getConfig().apiKey || process.env.DEEPSEEK_API_KEY || '';
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export function getModel(): string {
|
|
278
|
+
return getConfig().model;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export function getBaseUrl(): string {
|
|
282
|
+
return getConfig().baseUrl;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export const configManager = { load: () => loadConfig(), save: saveConfig, get: getConfigValue, set: setConfigValue, getAll: getConfig };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import process from 'node:process';
|
|
4
|
+
|
|
5
|
+
export const DEEPER_VERSION = '1.0.0';
|
|
6
|
+
export const DEEPER_NAME = 'DeeperCode';
|
|
7
|
+
export const DEEPER_HOME = join(process.env.DEEPER_HOME || join(homedir(), '.deeper'));
|
|
8
|
+
export const DEEPER_CONFIG_FILE = join(DEEPER_HOME, 'config.json');
|
|
9
|
+
export const DEEPER_MCP_FILE = join(DEEPER_HOME, 'mcp.json');
|
|
10
|
+
export const DEEPER_SKILLS_DIR = join(DEEPER_HOME, 'skills');
|
|
11
|
+
export const DEEPER_SESSIONS_DIR = join(DEEPER_HOME, 'sessions');
|
|
12
|
+
export const DEEPER_LOGS_DIR = join(DEEPER_HOME, 'logs');
|
|
13
|
+
export const DEEPER_MEMORY_FILE = join(DEEPER_HOME, 'memory.json');
|
|
14
|
+
export const PROJECT_CONFIG_DIR = '.deeper';
|
|
15
|
+
export const PROJECT_CONFIG_FILE = join(PROJECT_CONFIG_DIR, 'config.json');
|
|
16
|
+
export const PROJECT_SKILLS_DIR = join(PROJECT_CONFIG_DIR, 'skills');
|
|
17
|
+
|
|
18
|
+
export const DEEPSEEK_BASE_URL = 'https://api.deepseek.com';
|
|
19
|
+
export const DEEPSEEK_DEFAULT_MODEL = 'deepseek-v4-pro';
|
|
20
|
+
export const DEEPSEEK_MODELS = ['deepseek-v4-pro', 'deepseek-v4-flash'] as const;
|
|
21
|
+
export type DeepSeekModel = typeof DEEPSEEK_MODELS[number];
|
|
22
|
+
export const DEEPSEEK_MAX_TOKENS = 1_048_576;
|
|
23
|
+
export const DEEPSEEK_THINK_BUDGET = 16000;
|
|
24
|
+
|
|
25
|
+
export const AGENT_MAX_SUB_AGENTS = 5;
|
|
26
|
+
export const AGENT_MAX_RECURSION_DEPTH = 2;
|
|
27
|
+
export const AGENT_SUB_AGENT_TIMEOUT_MS = 120000;
|
|
28
|
+
export const AGENT_MAX_CONCURRENT_TOOLS = 3;
|
|
29
|
+
|
|
30
|
+
export const CONTEXT_MAX_TOKENS = 1_048_576;
|
|
31
|
+
export const CONTEXT_AUTO_SUMMARIZE_THRESHOLD = 786_432;
|
|
32
|
+
export const CONTEXT_HISTORY_SIZE = 80;
|
|
33
|
+
export const CONTEXT_FILE_LIMIT = 50_000;
|
|
34
|
+
|
|
35
|
+
export const CONTEXT_COMPRESSION_STAGES = [
|
|
36
|
+
{ threshold: 0.7, strategy: 'light' },
|
|
37
|
+
{ threshold: 0.85, strategy: 'aggressive' },
|
|
38
|
+
{ threshold: 0.95, strategy: 'emergency' },
|
|
39
|
+
] as const;
|
|
40
|
+
|
|
41
|
+
export const MCP_CONNECTION_TIMEOUT_MS = 10000;
|
|
42
|
+
|
|
43
|
+
export const TOOL_CATEGORIES = [
|
|
44
|
+
'filesystem', 'search', 'shell', 'network',
|
|
45
|
+
'code', 'database', 'data', 'security',
|
|
46
|
+
'project', 'ai', 'system',
|
|
47
|
+
] as const;
|
|
48
|
+
|
|
49
|
+
export type ToolCategory = typeof TOOL_CATEGORIES[number];
|