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,155 @@
1
+ import process from 'node:process';
2
+ import type { ChatMessage } from './types.js';
3
+ import type { ToolDefinition } from '../tools/tool-types.js';
4
+ import { DEEPER_NAME, DEEPER_VERSION } from '../core/constants.js';
5
+
6
+ const SYSTEM_PROMPT_TEMPLATE = `You are ${DEEPER_NAME} v${DEEPER_VERSION}, an advanced AI coding assistant powered by DeepSeek with Autonomous Execution capability.
7
+
8
+ ## Core Identity
9
+ - Name: ${DEEPER_NAME}
10
+ - Role: Expert software engineer and architect
11
+ - Capabilities: File operations, code search, shell execution, web research, database operations, multi-agent orchestration
12
+
13
+ ## Available Capabilities
14
+ You have access to a comprehensive tool suite organized into categories:
15
+ - **Filesystem**: read, write, edit, delete, move, copy files; list directories; batch operations
16
+ - **Search**: grep, text search, fuzzy find, symbol search, codebase search, definition/reference finding
17
+ - **Shell**: execute commands, manage processes, run tests, build projects
18
+ - **Network**: HTTP requests, web search, web fetch, API calls
19
+ - **Code**: diff, merge, format, analyze, generate charts
20
+ - **Database**: SQL/NoSQL queries, migrations, backups
21
+ - **Security**: secret scanning, vulnerability checking, encryption/decryption
22
+ - **Project**: project initialization, dependency management, environment management
23
+
24
+ ## Autonomous Execution
25
+ You operate in SOLO mode, meaning you independently plan and execute complex multi-step tasks:
26
+ - Break down large tasks into manageable steps
27
+ - Execute tools proactively without waiting for confirmation on safe operations
28
+ - Handle errors gracefully and adapt your approach
29
+ - Complete tasks fully before reporting results
30
+
31
+ ## Response Guidelines
32
+ - Provide clear, educational explanations alongside code
33
+ - Reference code locations using file paths
34
+ - Follow existing code conventions and patterns
35
+ - Never expose or log secrets or keys
36
+ - Always use proper error handling
37
+ - Balance educational content with task completion
38
+
39
+ ## Tool Usage
40
+ - Use multiple tools in parallel when operations are independent
41
+ - Check for existing implementations before creating new ones
42
+ - Follow security best practices at all times
43
+ - Confirm before executing dangerous operations
44
+
45
+ ## Context Awareness
46
+ - Current working directory: {cwd}
47
+ - Platform: {platform}
48
+ - Node.js version: {nodeVersion}
49
+
50
+ You are a powerful code assistant. Execute tasks thoroughly and precisely.`;
51
+
52
+ export class MessageBuilder {
53
+ private systemPrompt: string;
54
+
55
+ constructor(customPrompt?: string) {
56
+ this.systemPrompt = customPrompt ?? this.buildDefaultSystemPrompt();
57
+ }
58
+
59
+ build(messages: ChatMessage[], tools?: ToolDefinition[]): ChatMessage[] {
60
+ const result: ChatMessage[] = [];
61
+
62
+ const systemMsg: ChatMessage = {
63
+ role: 'system',
64
+ content: this.systemPrompt,
65
+ };
66
+ result.push(systemMsg);
67
+
68
+ for (const msg of messages) {
69
+ result.push(this.normalizeMessage(msg));
70
+ }
71
+
72
+ return result;
73
+ }
74
+
75
+ buildSystemMessage(): ChatMessage {
76
+ return {
77
+ role: 'system',
78
+ content: this.systemPrompt,
79
+ };
80
+ }
81
+
82
+ buildUserMessage(content: string): ChatMessage {
83
+ return {
84
+ role: 'user',
85
+ content,
86
+ };
87
+ }
88
+
89
+ buildAssistantMessage(content: string | null, toolCalls?: ChatMessage['tool_calls']): ChatMessage {
90
+ return {
91
+ role: 'assistant',
92
+ content,
93
+ tool_calls: toolCalls,
94
+ };
95
+ }
96
+
97
+ buildToolResultMessage(toolCallId: string, content: string, toolName?: string): ChatMessage {
98
+ return {
99
+ role: 'tool',
100
+ tool_call_id: toolCallId,
101
+ content,
102
+ name: toolName,
103
+ };
104
+ }
105
+
106
+ formatToolsForPrompt(tools: ToolDefinition[]): string {
107
+ return tools
108
+ .map((tool) => {
109
+ const required = tool.parameters.required ?? [];
110
+ const props = tool.parameters.properties ?? {};
111
+ const params = Object.entries(props)
112
+ .map(([name, schema]) => {
113
+ const isRequired = required.includes(name) ? ' (required)' : '';
114
+ return ` - ${name}: ${schema.type ?? 'any'}${isRequired} - ${schema.description ?? ''}`;
115
+ })
116
+ .join('\n');
117
+
118
+ return `### ${tool.name}\n${tool.description}\nParameters:\n${params}`;
119
+ })
120
+ .join('\n\n');
121
+ }
122
+
123
+ private normalizeMessage(msg: ChatMessage): ChatMessage {
124
+ const normalized: ChatMessage = {
125
+ role: msg.role,
126
+ content: msg.content,
127
+ };
128
+
129
+ if (msg.tool_calls) {
130
+ normalized.tool_calls = msg.tool_calls;
131
+ }
132
+ if (msg.tool_call_id) {
133
+ normalized.tool_call_id = msg.tool_call_id;
134
+ }
135
+ if (msg.name) {
136
+ normalized.name = msg.name;
137
+ }
138
+ if (msg.thinking) {
139
+ normalized.thinking = msg.thinking;
140
+ }
141
+
142
+ return normalized;
143
+ }
144
+
145
+ private buildDefaultSystemPrompt(): string {
146
+ const cwd = process.cwd();
147
+ const platform = `${process.platform} ${process.arch}`;
148
+ const nodeVersion = process.version;
149
+
150
+ return SYSTEM_PROMPT_TEMPLATE
151
+ .replace('{cwd}', cwd)
152
+ .replace('{platform}', platform)
153
+ .replace('{nodeVersion}', nodeVersion);
154
+ }
155
+ }
@@ -0,0 +1,82 @@
1
+ export class RetryManager {
2
+ private maxRetries: number;
3
+ private baseDelayMs: number;
4
+ private maxDelayMs: number;
5
+
6
+ constructor(maxRetries: number = 3, baseDelayMs: number = 1000, maxDelayMs: number = 30000) {
7
+ this.maxRetries = maxRetries;
8
+ this.baseDelayMs = baseDelayMs;
9
+ this.maxDelayMs = maxDelayMs;
10
+ }
11
+
12
+ async execute<T>(fn: () => Promise<T>, shouldRetry?: (error: Error, attempt: number) => boolean): Promise<T> {
13
+ let lastError: Error | undefined;
14
+
15
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
16
+ try {
17
+ return await fn();
18
+ } catch (error) {
19
+ lastError = error instanceof Error ? error : new Error(String(error));
20
+
21
+ if (attempt === this.maxRetries) {
22
+ break;
23
+ }
24
+
25
+ if (shouldRetry && !shouldRetry(lastError, attempt)) {
26
+ break;
27
+ }
28
+
29
+ const delay = Math.min(
30
+ this.baseDelayMs * Math.pow(2, attempt) + Math.random() * 1000,
31
+ this.maxDelayMs,
32
+ );
33
+
34
+ await this.sleep(delay);
35
+ }
36
+ }
37
+
38
+ throw lastError ?? new Error('Max retries exceeded');
39
+ }
40
+
41
+ withTimeout<T>(fn: () => Promise<T>, timeoutMs: number, signal?: AbortSignal): Promise<T> {
42
+ return new Promise<T>((resolve, reject) => {
43
+ const timer = setTimeout(() => {
44
+ reject(new Error(`Request timed out after ${timeoutMs}ms`));
45
+ }, timeoutMs);
46
+
47
+ const onAbort = (): void => {
48
+ clearTimeout(timer);
49
+ reject(new Error('Request was aborted'));
50
+ };
51
+
52
+ if (signal) {
53
+ if (signal.aborted) {
54
+ clearTimeout(timer);
55
+ reject(new Error('Request was aborted'));
56
+ return;
57
+ }
58
+ signal.addEventListener('abort', onAbort, { once: true });
59
+ }
60
+
61
+ fn()
62
+ .then((result) => {
63
+ clearTimeout(timer);
64
+ if (signal) {
65
+ signal.removeEventListener('abort', onAbort);
66
+ }
67
+ resolve(result);
68
+ })
69
+ .catch((error) => {
70
+ clearTimeout(timer);
71
+ if (signal) {
72
+ signal.removeEventListener('abort', onAbort);
73
+ }
74
+ reject(error);
75
+ });
76
+ });
77
+ }
78
+
79
+ private sleep(ms: number): Promise<void> {
80
+ return new Promise((resolve) => setTimeout(resolve, ms));
81
+ }
82
+ }
@@ -0,0 +1,158 @@
1
+ import type { ToolCall } from '../tools/tool-types.js';
2
+ import type { StreamChunk } from './types.js';
3
+
4
+ interface ParsedSSEEvent {
5
+ data: string;
6
+ event?: string;
7
+ id?: string;
8
+ }
9
+
10
+ export class StreamHandler {
11
+ private textBuffer: string;
12
+ private thinkingBuffer: string;
13
+ private toolCallBuffer: Map<number, ToolCall>;
14
+ private finished: boolean;
15
+
16
+ constructor() {
17
+ this.textBuffer = '';
18
+ this.thinkingBuffer = '';
19
+ this.toolCallBuffer = new Map();
20
+ this.finished = false;
21
+ }
22
+
23
+ reset(): void {
24
+ this.textBuffer = '';
25
+ this.thinkingBuffer = '';
26
+ this.toolCallBuffer.clear();
27
+ this.finished = false;
28
+ }
29
+
30
+ handleEvent(event: string, data: string): StreamChunk | null {
31
+ if (event === '[DONE]' || data === '[DONE]') {
32
+ this.finished = true;
33
+ return { type: 'done' };
34
+ }
35
+
36
+ if (!data) {
37
+ return null;
38
+ }
39
+
40
+ try {
41
+ const parsed = JSON.parse(data) as Record<string, unknown>;
42
+ const choices = parsed.choices as Array<Record<string, unknown>> | undefined;
43
+
44
+ if (!choices || choices.length === 0) {
45
+ return null;
46
+ }
47
+
48
+ const choice = choices[0];
49
+ const delta = choice.delta as Record<string, unknown> | undefined;
50
+
51
+ if (!delta) {
52
+ return null;
53
+ }
54
+
55
+ if (delta.reasoning_content) {
56
+ const thinkingChunk = delta.reasoning_content as string;
57
+ this.thinkingBuffer += thinkingChunk;
58
+ return {
59
+ type: 'thinking',
60
+ content: thinkingChunk,
61
+ };
62
+ }
63
+
64
+ if (delta.tool_calls) {
65
+ return this.handleToolCallsDelta(delta.tool_calls as Array<Record<string, unknown>>);
66
+ }
67
+
68
+ if (delta.content) {
69
+ const textChunk = delta.content as string;
70
+ this.textBuffer += textChunk;
71
+ return {
72
+ type: 'text',
73
+ content: textChunk,
74
+ };
75
+ }
76
+
77
+ const finishReason = choice.finish_reason as string | undefined;
78
+ if (finishReason === 'stop' || finishReason === 'length' || finishReason === 'tool_calls') {
79
+ this.finished = true;
80
+ return { type: 'done' };
81
+ }
82
+ } catch {
83
+ return {
84
+ type: 'error',
85
+ error: `Failed to parse SSE data: ${data.slice(0, 200)}`,
86
+ };
87
+ }
88
+
89
+ return null;
90
+ }
91
+
92
+ getAccumulatedText(): string {
93
+ return this.textBuffer;
94
+ }
95
+
96
+ getAccumulatedThinking(): string {
97
+ return this.thinkingBuffer;
98
+ }
99
+
100
+ getToolCalls(): ToolCall[] {
101
+ const result: ToolCall[] = [];
102
+ for (let i = 0; i < this.toolCallBuffer.size; i++) {
103
+ const tc = this.toolCallBuffer.get(i);
104
+ if (tc) {
105
+ result.push(tc);
106
+ }
107
+ }
108
+ return result;
109
+ }
110
+
111
+ isFinished(): boolean {
112
+ return this.finished;
113
+ }
114
+
115
+ private handleToolCallsDelta(toolCalls: Array<Record<string, unknown>>): StreamChunk | null {
116
+ for (const tc of toolCalls) {
117
+ const index = tc.index as number;
118
+ const id = tc.id as string | undefined;
119
+ const fn = tc.function as Record<string, unknown> | undefined;
120
+
121
+ if (!this.toolCallBuffer.has(index)) {
122
+ this.toolCallBuffer.set(index, {
123
+ id: id ?? '',
124
+ name: fn?.name as string ?? '',
125
+ arguments: {},
126
+ });
127
+ }
128
+
129
+ const existing = this.toolCallBuffer.get(index)!;
130
+
131
+ if (id) {
132
+ existing.id = id;
133
+ }
134
+ if (fn?.name) {
135
+ existing.name = fn.name as string;
136
+ }
137
+ if (fn?.arguments) {
138
+ try {
139
+ const argsStr = fn.arguments as string;
140
+ const parsed = JSON.parse(argsStr) as Record<string, unknown>;
141
+ existing.arguments = { ...existing.arguments, ...parsed };
142
+ } catch {
143
+ existing.arguments = existing.arguments || {};
144
+ }
145
+ }
146
+ }
147
+
148
+ const currentCall = this.toolCallBuffer.get(toolCalls[0].index as number);
149
+ if (currentCall) {
150
+ return {
151
+ type: 'tool_call',
152
+ tool_call: { ...currentCall, arguments: { ...currentCall.arguments } },
153
+ };
154
+ }
155
+
156
+ return null;
157
+ }
158
+ }
@@ -0,0 +1,86 @@
1
+ import type { ToolCall, ToolDefinition } from '../tools/tool-types.js';
2
+
3
+ export interface ChatMessage {
4
+ id?: string;
5
+ role: 'system' | 'user' | 'assistant' | 'tool';
6
+ content: string | null;
7
+ tool_calls?: ToolCall[];
8
+ toolCalls?: ToolCallRecord[];
9
+ tool_call_id?: string;
10
+ name?: string;
11
+ thinking?: string;
12
+ timestamp?: number;
13
+ }
14
+
15
+ export interface StreamChunk {
16
+ type: 'text' | 'thinking' | 'tool_call' | 'done' | 'error';
17
+ content?: string;
18
+ tool_call?: ToolCall;
19
+ error?: string;
20
+ }
21
+
22
+ export interface DeepSeekConfig {
23
+ apiKey: string;
24
+ model: string;
25
+ baseUrl: string;
26
+ temperature: number;
27
+ maxTokens: number;
28
+ think: {
29
+ enabled: boolean;
30
+ budgetTokens: number;
31
+ };
32
+ }
33
+
34
+ export interface ToolCallRecord {
35
+ id: string;
36
+ name: string;
37
+ arguments: Record<string, unknown>;
38
+ status: 'pending' | 'running' | 'completed' | 'failed';
39
+ result?: string;
40
+ }
41
+
42
+ export interface AgentInfo {
43
+ id: string;
44
+ name: string;
45
+ status: 'idle' | 'running' | 'completed' | 'failed';
46
+ task: string;
47
+ children?: AgentInfo[];
48
+ }
49
+
50
+ export interface SlashCommand {
51
+ command: string;
52
+ description: string;
53
+ }
54
+
55
+ export const SLASH_COMMANDS: SlashCommand[] = [
56
+ { command: '/help', description: '显示帮助信息' },
57
+ { command: '/clear', description: '清空对话' },
58
+ { command: '/quit', description: '退出 DeeperCode' },
59
+ { command: '/model', description: '查看/切换模型' },
60
+ { command: '/config', description: '查看/修改配置' },
61
+ { command: '/tools', description: '列出可用工具' },
62
+ { command: '/skills', description: '列出已加载技能' },
63
+ { command: '/mcp', description: '管理 MCP 连接' },
64
+ { command: '/save', description: '保存当前会话' },
65
+ { command: '/load', description: '加载历史会话' },
66
+ ];
67
+
68
+ export type DeepSeekMessage = ChatMessage;
69
+ export type DeepSeekToolCall = ToolCall;
70
+ export type DeepSeekToolDefinition = ToolDefinition;
71
+ export type DeepSeekRequest = {
72
+ model: string;
73
+ messages: ChatMessage[];
74
+ temperature?: number;
75
+ max_tokens?: number;
76
+ stream?: boolean;
77
+ tools?: DeepSeekToolDefinition[];
78
+ };
79
+ export type DeepSeekResponse = {
80
+ id: string;
81
+ choices: Array<{
82
+ message: ChatMessage;
83
+ finish_reason: string;
84
+ }>;
85
+ };
86
+ export type DeepSeekStreamChunk = StreamChunk;
@@ -0,0 +1,153 @@
1
+ import { mkdir, writeFile } from 'node:fs/promises';
2
+ import { existsSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { DEEPER_SKILLS_DIR } from '../core/constants.js';
5
+ import type { Skill, SkillMeta } from './types.js';
6
+
7
+ function parseSimpleYaml(s: string): Record<string, unknown> {
8
+ const result: Record<string, unknown> = {};
9
+ const lines = s.split('\n');
10
+ let listKey = '';
11
+ for (const line of lines) {
12
+ const trimmed = line.trim();
13
+ if (!trimmed || trimmed.startsWith('#')) continue;
14
+ const listMatch = trimmed.match(/^\s*-\s+(.+)/);
15
+ if (listMatch && listKey) {
16
+ const arr = (result[listKey] as string[]) || [];
17
+ arr.push(listMatch[1]);
18
+ result[listKey] = arr;
19
+ continue;
20
+ }
21
+ const kv = trimmed.match(/^([^:]+):\s*(.*)/);
22
+ if (kv) {
23
+ listKey = kv[2] === '' ? kv[1].trim() : '';
24
+ if (!listKey) result[kv[1].trim()] = kv[2].trim();
25
+ }
26
+ }
27
+ return result;
28
+ }
29
+
30
+ export interface CreateSkillInput {
31
+ meta: SkillMeta;
32
+ content: string;
33
+ code?: string;
34
+ }
35
+
36
+ export class SkillCreator {
37
+ private outputDir: string;
38
+
39
+ constructor(outputDir?: string) {
40
+ this.outputDir = outputDir || DEEPER_SKILLS_DIR;
41
+ }
42
+
43
+ async create(input: CreateSkillInput): Promise<Skill> {
44
+ const skillDir = join(this.outputDir, input.meta.name);
45
+
46
+ await mkdir(skillDir, { recursive: true });
47
+
48
+ const yamlFrontmatter = this.buildYamlFrontmatter(input.meta);
49
+ const mdContent = `---\n${yamlFrontmatter}---\n\n${input.content}`;
50
+
51
+ const mdPath = join(skillDir, 'skill.md');
52
+ await writeFile(mdPath, mdContent, 'utf-8');
53
+
54
+ if (input.code) {
55
+ const jsPath = join(skillDir, 'skill.js');
56
+ await writeFile(jsPath, input.code, 'utf-8');
57
+ }
58
+
59
+ return {
60
+ meta: input.meta,
61
+ content: input.content,
62
+ code: input.code,
63
+ };
64
+ }
65
+
66
+ async update(name: string, updates: Partial<CreateSkillInput>): Promise<Skill | null> {
67
+ const skillDir = join(this.outputDir, name);
68
+ const mdPath = join(skillDir, 'skill.md');
69
+
70
+ if (!existsSync(mdPath)) {
71
+ return null;
72
+ }
73
+
74
+ const { readFile } = await import('node:fs/promises');
75
+ const existingMd = await readFile(mdPath, 'utf-8');
76
+
77
+ let existingMeta: SkillMeta = {
78
+ name,
79
+ description: '',
80
+ version: '1.0.0',
81
+ author: 'unknown',
82
+ triggers: [],
83
+ tools: [],
84
+ dependencies: [],
85
+ };
86
+
87
+ let existingBody = existingMd;
88
+
89
+ const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
90
+ const match = existingMd.match(frontmatterRegex);
91
+ if (match) {
92
+ try {
93
+ const parsed = parseSimpleYaml(match[1]) as Record<string, unknown>;
94
+ existingMeta = {
95
+ name: (parsed.name as string) || name,
96
+ description: (parsed.description as string) || '',
97
+ version: (parsed.version as string) || '1.0.0',
98
+ author: (parsed.author as string) || 'unknown',
99
+ triggers: Array.isArray(parsed.triggers) ? parsed.triggers.map(String) : [],
100
+ tools: Array.isArray(parsed.tools) ? parsed.tools.map(String) : [],
101
+ dependencies: Array.isArray(parsed.dependencies) ? parsed.dependencies.map(String) : [],
102
+ };
103
+ } catch {
104
+ // Use defaults
105
+ }
106
+ existingBody = match[2];
107
+ }
108
+
109
+ const newMeta: SkillMeta = {
110
+ ...existingMeta,
111
+ ...updates.meta,
112
+ };
113
+
114
+ const newContent = updates.content || existingBody;
115
+
116
+ return this.create({
117
+ meta: newMeta,
118
+ content: newContent,
119
+ code: updates.code,
120
+ });
121
+ }
122
+
123
+ private buildYamlFrontmatter(meta: SkillMeta): string {
124
+ const lines: string[] = [];
125
+ lines.push(`name: ${meta.name}`);
126
+ lines.push(`description: ${meta.description}`);
127
+ lines.push(`version: ${meta.version}`);
128
+ lines.push(`author: ${meta.author}`);
129
+
130
+ if (meta.triggers.length > 0) {
131
+ lines.push('triggers:');
132
+ for (const t of meta.triggers) {
133
+ lines.push(` - ${t}`);
134
+ }
135
+ }
136
+
137
+ if (meta.tools.length > 0) {
138
+ lines.push('tools:');
139
+ for (const t of meta.tools) {
140
+ lines.push(` - ${t}`);
141
+ }
142
+ }
143
+
144
+ if (meta.dependencies.length > 0) {
145
+ lines.push('dependencies:');
146
+ for (const d of meta.dependencies) {
147
+ lines.push(` - ${d}`);
148
+ }
149
+ }
150
+
151
+ return lines.join('\n') + '\n';
152
+ }
153
+ }