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
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
|
|
3
|
+
export interface ContextUpdatedPayload {
|
|
4
|
+
modelName: string;
|
|
5
|
+
tokenCount: number;
|
|
6
|
+
memoryUsage: number;
|
|
7
|
+
uptime: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface MessagePayload {
|
|
11
|
+
id: string;
|
|
12
|
+
role: 'user' | 'assistant' | 'system';
|
|
13
|
+
content: string;
|
|
14
|
+
thinking?: string;
|
|
15
|
+
timestamp: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ToolCallPayload {
|
|
19
|
+
id: string;
|
|
20
|
+
toolName: string;
|
|
21
|
+
args: Record<string, unknown>;
|
|
22
|
+
status: 'pending' | 'running' | 'completed' | 'failed';
|
|
23
|
+
result?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface DiffPayload {
|
|
27
|
+
filePath: string;
|
|
28
|
+
oldContent: string;
|
|
29
|
+
newContent: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface AgentPayload {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
status: 'idle' | 'running' | 'completed' | 'failed';
|
|
36
|
+
parentId?: string;
|
|
37
|
+
task: string;
|
|
38
|
+
children?: AgentPayload[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const Events = {
|
|
42
|
+
CONTEXT_UPDATED: 'context:updated',
|
|
43
|
+
MESSAGE_SEND: 'message:send',
|
|
44
|
+
MESSAGE_RECEIVED: 'message:received',
|
|
45
|
+
MESSAGE_STREAMING: 'message:streaming',
|
|
46
|
+
TOOL_CALL_START: 'tool:call:start',
|
|
47
|
+
TOOL_CALL_END: 'tool:call:end',
|
|
48
|
+
FILE_DIFF: 'file:diff',
|
|
49
|
+
AGENT_TREE_UPDATED: 'agent:tree:updated',
|
|
50
|
+
APP_QUIT: 'app:quit',
|
|
51
|
+
APP_CLEAR: 'app:clear',
|
|
52
|
+
STATUS_UPDATE: 'status:update',
|
|
53
|
+
CONFIG_CHANGED: 'config:changed',
|
|
54
|
+
AGENT_STATUS_CHANGE: 'agent:status:change',
|
|
55
|
+
AGENT_CREATED: 'agent:created',
|
|
56
|
+
AGENT_THINKING: 'agent:thinking',
|
|
57
|
+
AGENT_EXECUTING: 'agent:executing',
|
|
58
|
+
AGENT_WAITING: 'agent:waiting',
|
|
59
|
+
AGENT_COMPLETED: 'agent:completed',
|
|
60
|
+
AGENT_FAILED: 'agent:failed',
|
|
61
|
+
AGENT_CANCELLED: 'agent:cancelled',
|
|
62
|
+
AGENT_LOOP_ITERATION: 'agent:loop:iteration',
|
|
63
|
+
AGENT_LOOP_DETECTED: 'agent:loop:detected',
|
|
64
|
+
AGENT_LOOP_LIMIT: 'agent:loop:limit',
|
|
65
|
+
TOOL_CALL_ERROR: 'tool:call:error',
|
|
66
|
+
ORCHESTRATOR_DECOMPOSE: 'orchestrator:decompose',
|
|
67
|
+
ORCHESTRATOR_DISPATCH: 'orchestrator:dispatch',
|
|
68
|
+
ORCHESTRATOR_AGGREGATE: 'orchestrator:aggregate',
|
|
69
|
+
SUBAGENT_START: 'subagent:start',
|
|
70
|
+
SUBAGENT_TIMEOUT: 'subagent:timeout',
|
|
71
|
+
SUBAGENT_COMPLETE: 'subagent:complete',
|
|
72
|
+
SUBAGENT_ERROR: 'subagent:error',
|
|
73
|
+
POOL_ACQUIRE: 'pool:acquire',
|
|
74
|
+
POOL_RELEASE: 'pool:release',
|
|
75
|
+
POOL_QUEUE: 'pool:queue',
|
|
76
|
+
CONTEXT_SUMMARIZED: 'context:summarized',
|
|
77
|
+
CONTEXT_TOKEN_WARNING: 'context:token:warning',
|
|
78
|
+
MCP_CONNECTED: 'mcp:connected',
|
|
79
|
+
MCP_ERROR: 'mcp:error',
|
|
80
|
+
MCP_DISCONNECTED: 'mcp:disconnected',
|
|
81
|
+
MCP_TOOLS_DISCOVERED: 'mcp:tools:discovered',
|
|
82
|
+
SKILL_LOADED: 'skill:loaded',
|
|
83
|
+
SKILL_EXECUTED: 'skill:executed',
|
|
84
|
+
SKILL_CREATED: 'skill:created',
|
|
85
|
+
SKILL_TRIGGERED: 'skill:triggered',
|
|
86
|
+
} as const;
|
|
87
|
+
|
|
88
|
+
export const EventBusEvents = Events;
|
|
89
|
+
|
|
90
|
+
export class EventBus extends EventEmitter {
|
|
91
|
+
private static instance: EventBus;
|
|
92
|
+
|
|
93
|
+
static getInstance(): EventBus {
|
|
94
|
+
if (!EventBus.instance) {
|
|
95
|
+
EventBus.instance = new EventBus();
|
|
96
|
+
}
|
|
97
|
+
return EventBus.instance;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
onContextUpdated(handler: (payload: ContextUpdatedPayload) => void): void {
|
|
101
|
+
this.on(EventBusEvents.CONTEXT_UPDATED, handler);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
emitContextUpdated(payload: ContextUpdatedPayload): void {
|
|
105
|
+
this.emit(EventBusEvents.CONTEXT_UPDATED, payload);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
onMessageSend(handler: (payload: { content: string }) => void): void {
|
|
109
|
+
this.on(EventBusEvents.MESSAGE_SEND, handler);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
emitMessageSend(payload: { content: string }): void {
|
|
113
|
+
this.emit(EventBusEvents.MESSAGE_SEND, payload);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
onMessageReceived(handler: (payload: MessagePayload) => void): void {
|
|
117
|
+
this.on(EventBusEvents.MESSAGE_RECEIVED, handler);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
emitMessageReceived(payload: MessagePayload): void {
|
|
121
|
+
this.emit(EventBusEvents.MESSAGE_RECEIVED, payload);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
onMessageStreaming(handler: (payload: { id: string; content: string; thinking?: string }) => void): void {
|
|
125
|
+
this.on(EventBusEvents.MESSAGE_STREAMING, handler);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
emitMessageStreaming(payload: { id: string; content: string; thinking?: string }): void {
|
|
129
|
+
this.emit(EventBusEvents.MESSAGE_STREAMING, payload);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
onToolCallStart(handler: (payload: ToolCallPayload) => void): void {
|
|
133
|
+
this.on(EventBusEvents.TOOL_CALL_START, handler);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
emitToolCallStart(payload: ToolCallPayload): void {
|
|
137
|
+
this.emit(EventBusEvents.TOOL_CALL_START, payload);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
onToolCallEnd(handler: (payload: ToolCallPayload) => void): void {
|
|
141
|
+
this.on(EventBusEvents.TOOL_CALL_END, handler);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
emitToolCallEnd(payload: ToolCallPayload): void {
|
|
145
|
+
this.emit(EventBusEvents.TOOL_CALL_END, payload);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
onFileDiff(handler: (payload: DiffPayload) => void): void {
|
|
149
|
+
this.on(EventBusEvents.FILE_DIFF, handler);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
emitFileDiff(payload: DiffPayload): void {
|
|
153
|
+
this.emit(EventBusEvents.FILE_DIFF, payload);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
onAgentTreeUpdated(handler: (payload: { agents: AgentPayload[] }) => void): void {
|
|
157
|
+
this.on(EventBusEvents.AGENT_TREE_UPDATED, handler);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
emitAgentTreeUpdated(payload: { agents: AgentPayload[] }): void {
|
|
161
|
+
this.emit(EventBusEvents.AGENT_TREE_UPDATED, payload);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
onAppQuit(handler: () => void): void {
|
|
165
|
+
this.on(EventBusEvents.APP_QUIT, handler);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
emitAppQuit(): void {
|
|
169
|
+
this.emit(EventBusEvents.APP_QUIT);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
onAppClear(handler: () => void): void {
|
|
173
|
+
this.on(EventBusEvents.APP_CLEAR, handler);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
emitAppClear(): void {
|
|
177
|
+
this.emit(EventBusEvents.APP_CLEAR);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
onStatusUpdate(handler: (payload: Partial<ContextUpdatedPayload>) => void): void {
|
|
181
|
+
this.on(EventBusEvents.STATUS_UPDATE, handler);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
emitStatusUpdate(payload: Partial<ContextUpdatedPayload>): void {
|
|
185
|
+
this.emit(EventBusEvents.STATUS_UPDATE, payload);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
onConfigChanged(handler: (payload: Record<string, unknown>) => void): void {
|
|
189
|
+
this.on(EventBusEvents.CONFIG_CHANGED, handler);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
emitConfigChanged(payload: Record<string, unknown>): void {
|
|
193
|
+
this.emit(EventBusEvents.CONFIG_CHANGED, payload);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
reset(): void {
|
|
197
|
+
this.removeAllListeners();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export const eventbus = EventBus.getInstance();
|
|
202
|
+
export const globalEventBus = eventbus;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { appendFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { DEEPER_LOGS_DIR } from './constants.js';
|
|
4
|
+
|
|
5
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
6
|
+
|
|
7
|
+
const LOG_LEVEL_RANK: Record<LogLevel, number> = {
|
|
8
|
+
debug: 0,
|
|
9
|
+
info: 1,
|
|
10
|
+
warn: 2,
|
|
11
|
+
error: 3,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export class Logger {
|
|
15
|
+
private level: LogLevel;
|
|
16
|
+
private logDir: string;
|
|
17
|
+
private currentLogFile: string;
|
|
18
|
+
|
|
19
|
+
constructor(level: LogLevel = 'info', logDir?: string) {
|
|
20
|
+
this.level = level;
|
|
21
|
+
this.logDir = logDir ?? DEEPER_LOGS_DIR;
|
|
22
|
+
this.currentLogFile = this.generateLogFileName();
|
|
23
|
+
this.ensureLogDir();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
setLevel(level: LogLevel): void {
|
|
27
|
+
this.level = level;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
debug(message: string, data?: unknown): void {
|
|
31
|
+
this.log('debug', message, data);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
info(message: string, data?: unknown): void {
|
|
35
|
+
this.log('info', message, data);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
warn(message: string, data?: unknown): void {
|
|
39
|
+
this.log('warn', message, data);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
error(message: string, data?: unknown): void {
|
|
43
|
+
this.log('error', message, data);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private log(level: LogLevel, message: string, data?: unknown): void {
|
|
47
|
+
if (LOG_LEVEL_RANK[level] < LOG_LEVEL_RANK[this.level]) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const timestamp = new Date().toISOString();
|
|
52
|
+
const formatted = this.formatMessage(level, timestamp, message, data);
|
|
53
|
+
|
|
54
|
+
switch (level) {
|
|
55
|
+
case 'error':
|
|
56
|
+
console.error(formatted);
|
|
57
|
+
break;
|
|
58
|
+
case 'warn':
|
|
59
|
+
console.warn(formatted);
|
|
60
|
+
break;
|
|
61
|
+
default:
|
|
62
|
+
console.log(formatted);
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
appendFileSync(this.currentLogFile, this.stripAnsi(formatted) + '\n', 'utf-8');
|
|
68
|
+
} catch {
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private formatMessage(level: LogLevel, timestamp: string, message: string, data?: unknown): string {
|
|
73
|
+
const levelUpper = level.toUpperCase();
|
|
74
|
+
const base = `[${timestamp}] [${levelUpper}] ${message}`;
|
|
75
|
+
if (data !== undefined) {
|
|
76
|
+
if (typeof data === 'string') {
|
|
77
|
+
return `${base} ${data}`;
|
|
78
|
+
}
|
|
79
|
+
if (data instanceof Error) {
|
|
80
|
+
return `${base} ${data.message}\n${data.stack ?? ''}`;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
return `${base} ${JSON.stringify(data)}`;
|
|
84
|
+
} catch {
|
|
85
|
+
return `${base} [Unserializable data]`;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return base;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private stripAnsi(text: string): string {
|
|
92
|
+
return text.replace(/\x1b\[[0-9;]*m/g, '');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private generateLogFileName(): string {
|
|
96
|
+
const now = new Date();
|
|
97
|
+
const dateStr = now.toISOString().slice(0, 10).replace(/-/g, '');
|
|
98
|
+
return join(this.logDir, `deeper-${dateStr}.log`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private ensureLogDir(): void {
|
|
102
|
+
const dir = dirname(this.currentLogFile);
|
|
103
|
+
if (!existsSync(dir)) {
|
|
104
|
+
mkdirSync(dir, { recursive: true });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export const logger = new Logger();
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { DEEPER_HOME } from './constants.js';
|
|
4
|
+
|
|
5
|
+
export class Storage {
|
|
6
|
+
private baseDir: string;
|
|
7
|
+
|
|
8
|
+
constructor(baseDir?: string) {
|
|
9
|
+
this.baseDir = baseDir ?? join(DEEPER_HOME, 'storage');
|
|
10
|
+
this.ensureDir(this.baseDir);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get<T = unknown>(key: string): T | null {
|
|
14
|
+
const filePath = this.getFilePath(key);
|
|
15
|
+
try {
|
|
16
|
+
if (!existsSync(filePath)) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
20
|
+
return JSON.parse(content) as T;
|
|
21
|
+
} catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
set<T = unknown>(key: string, value: T): void {
|
|
27
|
+
const filePath = this.getFilePath(key);
|
|
28
|
+
this.ensureDir(dirname(filePath));
|
|
29
|
+
writeFileSync(filePath, JSON.stringify(value, null, 2), 'utf-8');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
delete(key: string): boolean {
|
|
33
|
+
const filePath = this.getFilePath(key);
|
|
34
|
+
try {
|
|
35
|
+
if (existsSync(filePath)) {
|
|
36
|
+
unlinkSync(filePath);
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
} catch {
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
has(key: string): boolean {
|
|
45
|
+
return existsSync(this.getFilePath(key));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
keys(): string[] {
|
|
49
|
+
const result: string[] = [];
|
|
50
|
+
try {
|
|
51
|
+
if (existsSync(this.baseDir)) {
|
|
52
|
+
const files = readdirSync(this.baseDir, { recursive: true });
|
|
53
|
+
for (const file of files) {
|
|
54
|
+
const fileName = typeof file === 'string' ? file : file.toString('utf-8');
|
|
55
|
+
if (fileName.endsWith('.json')) {
|
|
56
|
+
result.push(fileName.replace(/\.json$/, '').replace(/\\/g, '/'));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
clear(): void {
|
|
66
|
+
try {
|
|
67
|
+
const files = readdirSync(this.baseDir, { recursive: true });
|
|
68
|
+
for (const file of files) {
|
|
69
|
+
const fullPath = join(this.baseDir, typeof file === 'string' ? file : file.toString('utf-8'));
|
|
70
|
+
try {
|
|
71
|
+
unlinkSync(fullPath);
|
|
72
|
+
} catch {
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
} catch {
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
setBaseDir(dir: string): void {
|
|
80
|
+
this.baseDir = dir;
|
|
81
|
+
this.ensureDir(dir);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private getFilePath(key: string): string {
|
|
85
|
+
const safeKey = key.replace(/[<>:"/\\|?*]/g, '_');
|
|
86
|
+
return join(this.baseDir, `${safeKey}.json`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private ensureDir(dir: string): void {
|
|
90
|
+
if (!existsSync(dir)) {
|
|
91
|
+
mkdirSync(dir, { recursive: true });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const storage = new Storage();
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export { defaultTheme, type Theme } from './ui/themes/default.ts';
|
|
2
|
+
export { darkTheme } from './ui/themes/dark.ts';
|
|
3
|
+
export { lightTheme } from './ui/themes/light.ts';
|
|
4
|
+
|
|
5
|
+
export { Spinner } from './ui/Spinner.tsx';
|
|
6
|
+
export { MessageBubble } from './ui/MessageBubble.tsx';
|
|
7
|
+
export { ToolCallCard } from './ui/ToolCallCard.tsx';
|
|
8
|
+
export { DiffView } from './ui/DiffView.tsx';
|
|
9
|
+
export { FilePreview } from './ui/FilePreview.tsx';
|
|
10
|
+
export { AgentTree } from './ui/AgentTree.tsx';
|
|
11
|
+
export { ConfirmDialog } from './ui/ConfirmDialog.tsx';
|
|
12
|
+
export { StatusBar } from './ui/StatusBar.tsx';
|
|
13
|
+
export { InputBox } from './ui/InputBox.tsx';
|
|
14
|
+
export { ChatView } from './ui/ChatView.tsx';
|
|
15
|
+
export { App } from './ui/App.tsx';
|
|
16
|
+
|
|
17
|
+
export { eventbus, EventBusEvents, type ContextUpdatedPayload, type MessagePayload, type ToolCallPayload, type DiffPayload, type AgentPayload } from './core/eventbus.ts';
|
|
18
|
+
export { loadConfig, saveConfig, getConfig, updateConfig, resetConfig, getConfigValue, setConfigValue, getApiKey, getModel, getBaseUrl, type DeeperConfig, type MCPConfigEntry, type SkillConfigEntry } from './core/config.ts';
|
|
19
|
+
export { DEEPER_VERSION, DEEPER_NAME, DEEPER_HOME, DEEPER_CONFIG_FILE, DEEPSEEK_DEFAULT_MODEL, DEEPSEEK_BASE_URL, TOOL_CATEGORIES, AGENT_MAX_SUB_AGENTS, CONTEXT_MAX_TOKENS, MCP_CONNECTION_TIMEOUT_MS } from './core/constants.ts';
|
|
20
|
+
export type { ToolCategory } from './core/constants.ts';
|
|
21
|
+
export { type JSONSchema, type ToolParameter, type ToolDefinition, type ToolResult, type ToolExecutor, type Tool, type ToolCall, type ToolCallResult, type ToolSafetyLevel, TOOL_SAFETY_MAP } from './tools/tool-types.ts';
|
|
22
|
+
export { type DeepSeekMessage, type DeepSeekToolCall, type DeepSeekToolDefinition, type DeepSeekRequest, type DeepSeekResponse, type DeepSeekStreamChunk, type ChatMessage, type ToolCallRecord, type AgentInfo, type SlashCommand, SLASH_COMMANDS } from './model/types.ts';
|
|
23
|
+
|
|
24
|
+
export { bootstrap, checkNodeVersion, getVersionInfo, type BootstrapResult } from './cli/bootstrap.ts';
|
|
25
|
+
export { chat } from './cli/commands/chat.tsx';
|
|
26
|
+
export { run } from './cli/commands/run.ts';
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { DEEPER_MCP_FILE } from '../core/constants.js';
|
|
4
|
+
import type { MCPServerConfig } from './types.js';
|
|
5
|
+
|
|
6
|
+
export class ConfigLoader {
|
|
7
|
+
private configPath: string;
|
|
8
|
+
|
|
9
|
+
constructor(configPath?: string) {
|
|
10
|
+
this.configPath = configPath || DEEPER_MCP_FILE;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async load(): Promise<MCPServerConfig[]> {
|
|
14
|
+
if (!existsSync(this.configPath)) {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const content = await readFile(this.configPath, 'utf-8');
|
|
20
|
+
const parsed = JSON.parse(content);
|
|
21
|
+
|
|
22
|
+
if (Array.isArray(parsed)) {
|
|
23
|
+
return this.validateConfigs(parsed);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (parsed && parsed.mcpServers) {
|
|
27
|
+
return this.validateConfigs(parsed.mcpServers);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return [];
|
|
31
|
+
} catch {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async loadSingle(name: string): Promise<MCPServerConfig | null> {
|
|
37
|
+
const configs = await this.load();
|
|
38
|
+
return configs.find((c) => c.name === name) || null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private validateConfigs(raw: unknown[]): MCPServerConfig[] {
|
|
42
|
+
const valid: MCPServerConfig[] = [];
|
|
43
|
+
|
|
44
|
+
for (const item of raw) {
|
|
45
|
+
if (!item || typeof item !== 'object') continue;
|
|
46
|
+
|
|
47
|
+
const obj = item as Record<string, unknown>;
|
|
48
|
+
|
|
49
|
+
if (!obj.name || typeof obj.name !== 'string') continue;
|
|
50
|
+
if (!obj.type || (obj.type !== 'stdio' && obj.type !== 'sse')) continue;
|
|
51
|
+
|
|
52
|
+
const config: MCPServerConfig = {
|
|
53
|
+
name: obj.name,
|
|
54
|
+
type: obj.type as 'stdio' | 'sse',
|
|
55
|
+
command: typeof obj.command === 'string' ? obj.command : undefined,
|
|
56
|
+
args: Array.isArray(obj.args) ? obj.args.map(String) : undefined,
|
|
57
|
+
url: typeof obj.url === 'string' ? obj.url : undefined,
|
|
58
|
+
headers: typeof obj.headers === 'object' && obj.headers
|
|
59
|
+
? obj.headers as Record<string, string>
|
|
60
|
+
: undefined,
|
|
61
|
+
env: typeof obj.env === 'object' && obj.env
|
|
62
|
+
? obj.env as Record<string, string>
|
|
63
|
+
: undefined,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
if (config.type === 'stdio' && !config.command) continue;
|
|
67
|
+
if (config.type === 'sse' && !config.url) continue;
|
|
68
|
+
|
|
69
|
+
valid.push(config);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return valid;
|
|
73
|
+
}
|
|
74
|
+
}
|