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
package/dist/index.js ADDED
@@ -0,0 +1,1599 @@
1
+ // src/ui/themes/default.ts
2
+ var defaultTheme = {
3
+ primary: "#00BFA5",
4
+ secondary: "#7C4DFF",
5
+ success: "#00E676",
6
+ warning: "#FFAB40",
7
+ error: "#FF5252",
8
+ text: "#E0E0E0",
9
+ dimText: "#757575",
10
+ border: "#424242",
11
+ background: "#121212",
12
+ cardBackground: "#1E1E1E"
13
+ };
14
+
15
+ // src/ui/themes/dark.ts
16
+ var darkTheme = { ...defaultTheme };
17
+
18
+ // src/ui/themes/light.ts
19
+ var lightTheme = {
20
+ primary: "#00897B",
21
+ secondary: "#6200EA",
22
+ success: "#00C853",
23
+ warning: "#FF6D00",
24
+ error: "#D50000",
25
+ text: "#212121",
26
+ dimText: "#9E9E9E",
27
+ border: "#E0E0E0",
28
+ background: "#FAFAFA",
29
+ cardBackground: "#FFFFFF"
30
+ };
31
+
32
+ // src/ui/Spinner.tsx
33
+ import { useState, useEffect } from "react";
34
+ import { Text, Box } from "ink";
35
+ import { jsx, jsxs } from "react/jsx-runtime";
36
+ var spinnerFrames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
37
+ function Spinner({ label, type = "braille" }) {
38
+ const [frame, setFrame] = useState(0);
39
+ useEffect(() => {
40
+ const timer = setInterval(() => {
41
+ setFrame((prev) => (prev + 1) % spinnerFrames.length);
42
+ }, 80);
43
+ return () => clearInterval(timer);
44
+ }, []);
45
+ const dotsFrames = [" ", ". ", ".. ", "..."];
46
+ const frameChar = type === "dots" ? dotsFrames[frame % dotsFrames.length] : type === "line" ? ["|", "/", "-", "\\"][frame % 4] : spinnerFrames[frame];
47
+ return /* @__PURE__ */ jsxs(Box, { children: [
48
+ /* @__PURE__ */ jsx(Text, { color: defaultTheme.primary, children: frameChar }),
49
+ label ? /* @__PURE__ */ jsxs(Text, { children: [
50
+ " ",
51
+ label
52
+ ] }) : null
53
+ ] });
54
+ }
55
+
56
+ // src/ui/MessageBubble.tsx
57
+ import { Text as Text2, Box as Box2 } from "ink";
58
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
59
+ function MessageBubble({ role, content }) {
60
+ const display = content ?? "";
61
+ const lines = display.split("\n");
62
+ const color = role === "user" ? defaultTheme.secondary : defaultTheme.text;
63
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
64
+ /* @__PURE__ */ jsx2(Box2, { children: /* @__PURE__ */ jsx2(Text2, { color: role === "user" ? defaultTheme.secondary : defaultTheme.primary, bold: true, children: role === "user" ? "> " : role === "system" ? "\u2699 " : "\u25CF " }) }),
65
+ lines.map((line, i) => /* @__PURE__ */ jsx2(Box2, { paddingLeft: 1, children: /* @__PURE__ */ jsx2(Text2, { color, children: line || " " }) }, i))
66
+ ] });
67
+ }
68
+
69
+ // src/ui/ToolCallCard.tsx
70
+ import { Text as Text3, Box as Box3 } from "ink";
71
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
72
+ var statusConfig = {
73
+ pending: { icon: "\u23F3", color: defaultTheme.dimText, label: "\u7B49\u5F85\u4E2D" },
74
+ running: { icon: "\u{1F504}", color: defaultTheme.primary, label: "\u6267\u884C\u4E2D" },
75
+ completed: { icon: "\u2705", color: defaultTheme.success, label: "\u5DF2\u5B8C\u6210" },
76
+ failed: { icon: "\u274C", color: defaultTheme.error, label: "\u5931\u8D25" }
77
+ };
78
+ function summarizeArgs(args) {
79
+ const entries = Object.entries(args);
80
+ if (entries.length === 0) return "\u65E0\u53C2\u6570";
81
+ const maxLen = 60;
82
+ const summary = entries.map(([k, v]) => {
83
+ const strVal = typeof v === "string" ? v : JSON.stringify(v);
84
+ return `${k}: ${strVal.length > 40 ? strVal.slice(0, 40) + "..." : strVal}`;
85
+ }).join(", ");
86
+ return summary.length > maxLen ? summary.slice(0, maxLen) + "..." : summary;
87
+ }
88
+ function ToolCallCard({ toolName, args, result, status }) {
89
+ const cfg = statusConfig[status];
90
+ return /* @__PURE__ */ jsxs3(
91
+ Box3,
92
+ {
93
+ flexDirection: "column",
94
+ borderStyle: "round",
95
+ borderColor: cfg.color,
96
+ paddingX: 1,
97
+ marginY: 0,
98
+ children: [
99
+ /* @__PURE__ */ jsxs3(Box3, { children: [
100
+ /* @__PURE__ */ jsx3(Text3, { color: cfg.color, children: cfg.icon }),
101
+ /* @__PURE__ */ jsxs3(Text3, { bold: true, color: cfg.color, children: [
102
+ " ",
103
+ toolName
104
+ ] }),
105
+ /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
106
+ " - ",
107
+ cfg.label
108
+ ] })
109
+ ] }),
110
+ /* @__PURE__ */ jsxs3(Box3, { marginTop: 0, children: [
111
+ /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "\u53C2\u6570: " }),
112
+ /* @__PURE__ */ jsx3(Text3, { children: summarizeArgs(args) })
113
+ ] }),
114
+ result && status === "completed" ? /* @__PURE__ */ jsxs3(Box3, { marginTop: 0, flexDirection: "column", children: [
115
+ /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "\u7ED3\u679C: " }),
116
+ /* @__PURE__ */ jsx3(Box3, { borderStyle: "single", borderColor: defaultTheme.border, paddingX: 1, children: /* @__PURE__ */ jsx3(Text3, { children: result.length > 200 ? result.slice(0, 200) + "..." : result }) })
117
+ ] }) : null,
118
+ result && status === "failed" ? /* @__PURE__ */ jsx3(Box3, { marginTop: 0, children: /* @__PURE__ */ jsxs3(Text3, { color: defaultTheme.error, children: [
119
+ "\u9519\u8BEF: ",
120
+ result
121
+ ] }) }) : null
122
+ ]
123
+ }
124
+ );
125
+ }
126
+
127
+ // src/ui/DiffView.tsx
128
+ import { useMemo } from "react";
129
+ import { Text as Text4, Box as Box4 } from "ink";
130
+ import { diffLines } from "diff";
131
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
132
+ function DiffView({ filePath, oldContent, newContent }) {
133
+ const changes = useMemo(() => {
134
+ return diffLines(oldContent || "", newContent || "", {
135
+ ignoreWhitespace: false
136
+ });
137
+ }, [oldContent, newContent]);
138
+ const addedCount = changes.filter((c) => c.added).length;
139
+ const removedCount = changes.filter((c) => c.removed).length;
140
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", borderStyle: "round", borderColor: defaultTheme.border, paddingX: 1, children: [
141
+ /* @__PURE__ */ jsxs4(Box4, { children: [
142
+ /* @__PURE__ */ jsx4(Text4, { bold: true, children: "\u{1F4C4} " }),
143
+ /* @__PURE__ */ jsx4(Text4, { bold: true, color: defaultTheme.primary, children: filePath }),
144
+ /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
145
+ " ",
146
+ /* @__PURE__ */ jsxs4(Text4, { color: defaultTheme.success, children: [
147
+ "+",
148
+ addedCount
149
+ ] }),
150
+ " / ",
151
+ /* @__PURE__ */ jsxs4(Text4, { color: defaultTheme.error, children: [
152
+ "-",
153
+ removedCount
154
+ ] })
155
+ ] })
156
+ ] }),
157
+ /* @__PURE__ */ jsx4(Box4, { flexDirection: "column", marginTop: 0, children: changes.slice(0, 50).map((change, i) => {
158
+ if (change.added) {
159
+ return /* @__PURE__ */ jsx4(Box4, { children: /* @__PURE__ */ jsxs4(Text4, { color: defaultTheme.success, children: [
160
+ "+ ",
161
+ change.value.trimEnd()
162
+ ] }) }, i);
163
+ }
164
+ if (change.removed) {
165
+ return /* @__PURE__ */ jsx4(Box4, { children: /* @__PURE__ */ jsxs4(Text4, { color: defaultTheme.error, children: [
166
+ "- ",
167
+ change.value.trimEnd()
168
+ ] }) }, i);
169
+ }
170
+ return /* @__PURE__ */ jsx4(Box4, { children: /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
171
+ " ",
172
+ change.value.trimEnd()
173
+ ] }) }, i);
174
+ }) }),
175
+ changes.length > 50 ? /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
176
+ "... \u8FD8\u6709 ",
177
+ changes.length - 50,
178
+ " \u5904\u53D8\u66F4\u672A\u663E\u793A"
179
+ ] }) : null
180
+ ] });
181
+ }
182
+
183
+ // src/ui/FilePreview.tsx
184
+ import { Text as Text5, Box as Box5 } from "ink";
185
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
186
+ function formatSize(bytes) {
187
+ if (bytes < 1024) return `${bytes} B`;
188
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
189
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
190
+ }
191
+ function detectLang(path) {
192
+ const ext = path.split(".").pop()?.toLowerCase();
193
+ const map = {
194
+ ts: "TypeScript",
195
+ tsx: "TSX",
196
+ js: "JavaScript",
197
+ jsx: "JSX",
198
+ py: "Python",
199
+ rs: "Rust",
200
+ go: "Go",
201
+ java: "Java",
202
+ json: "JSON",
203
+ yaml: "YAML",
204
+ yml: "YAML",
205
+ toml: "TOML",
206
+ md: "Markdown",
207
+ html: "HTML",
208
+ css: "CSS",
209
+ scss: "SCSS",
210
+ sql: "SQL",
211
+ sh: "Shell",
212
+ bat: "Batch",
213
+ ps1: "PowerShell"
214
+ };
215
+ return map[ext || ""] || ext?.toUpperCase() || "text";
216
+ }
217
+ function FilePreview({ filePath, content, language, lineCount, size }) {
218
+ const lang = language || detectLang(filePath);
219
+ const lines = content ? content.split("\n").slice(0, 10) : [];
220
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "round", borderColor: defaultTheme.border, paddingX: 1, children: [
221
+ /* @__PURE__ */ jsxs5(Box5, { children: [
222
+ /* @__PURE__ */ jsx5(Text5, { bold: true, children: "\u{1F4C4} " }),
223
+ /* @__PURE__ */ jsx5(Text5, { bold: true, color: defaultTheme.primary, children: filePath }),
224
+ /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
225
+ " (",
226
+ lang,
227
+ ")"
228
+ ] }),
229
+ size !== void 0 ? /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
230
+ " - ",
231
+ formatSize(size)
232
+ ] }) : null,
233
+ lineCount !== void 0 ? /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
234
+ " - ",
235
+ lineCount,
236
+ " \u884C"
237
+ ] }) : null
238
+ ] }),
239
+ content ? /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "single", borderColor: defaultTheme.border, paddingX: 1, marginTop: 0, children: [
240
+ lines.map((line, i) => /* @__PURE__ */ jsxs5(Box5, { children: [
241
+ /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
242
+ (i + 1).toString().padStart(3, " "),
243
+ " \u2502 "
244
+ ] }),
245
+ /* @__PURE__ */ jsx5(Text5, { children: line.length > 100 ? line.slice(0, 100) + "..." : line })
246
+ ] }, i)),
247
+ content.split("\n").length > 10 ? /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
248
+ "... \u8FD8\u6709 ",
249
+ content.split("\n").length - 10,
250
+ " \u884C"
251
+ ] }) : null
252
+ ] }) : null
253
+ ] });
254
+ }
255
+
256
+ // src/ui/AgentTree.tsx
257
+ import { Text as Text6, Box as Box6 } from "ink";
258
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
259
+ var statusIcon = {
260
+ idle: "\u23F8",
261
+ running: "\u{1F504}",
262
+ completed: "\u2705",
263
+ failed: "\u274C"
264
+ };
265
+ var statusColor = {
266
+ idle: defaultTheme.dimText,
267
+ running: defaultTheme.primary,
268
+ completed: defaultTheme.success,
269
+ failed: defaultTheme.error
270
+ };
271
+ function AgentNodeRow({
272
+ node,
273
+ depth,
274
+ isLast
275
+ }) {
276
+ const prefix = depth === 0 ? "" : " ".repeat(depth - 1) + (isLast ? "\u2514\u2500" : "\u251C\u2500");
277
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
278
+ /* @__PURE__ */ jsxs6(Box6, { children: [
279
+ /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: prefix }),
280
+ /* @__PURE__ */ jsx6(Text6, { color: statusColor[node.status], children: statusIcon[node.status] }),
281
+ /* @__PURE__ */ jsxs6(Text6, { bold: true, color: statusColor[node.status], children: [
282
+ " ",
283
+ node.name
284
+ ] })
285
+ ] }),
286
+ node.children?.map((child, i) => /* @__PURE__ */ jsx6(
287
+ AgentNodeRow,
288
+ {
289
+ node: child,
290
+ depth: depth + 1,
291
+ isLast: i === (node.children?.length || 0) - 1
292
+ },
293
+ child.id
294
+ ))
295
+ ] });
296
+ }
297
+ function AgentTree({ agents }) {
298
+ const total = agents.length;
299
+ const running = agents.filter((a) => a.status === "running").length;
300
+ const completed = agents.filter((a) => a.status === "completed").length;
301
+ const failed = agents.filter((a) => a.status === "failed").length;
302
+ const countChildren = (ns) => ns.reduce((sum, n) => sum + 1 + countChildren(n.children || []), 0);
303
+ const totalWithChildren = countChildren(agents);
304
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", borderStyle: "round", borderColor: defaultTheme.border, paddingX: 1, children: [
305
+ /* @__PURE__ */ jsxs6(Box6, { children: [
306
+ /* @__PURE__ */ jsx6(Text6, { bold: true, children: "\u{1F916} Agent \u6811" }),
307
+ /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
308
+ " ",
309
+ "[",
310
+ totalWithChildren,
311
+ " \u8282\u70B9:",
312
+ " ",
313
+ /* @__PURE__ */ jsxs6(Text6, { color: defaultTheme.success, children: [
314
+ completed,
315
+ " \u5B8C\u6210"
316
+ ] }),
317
+ running > 0 ? /* @__PURE__ */ jsxs6(Text6, { color: defaultTheme.primary, children: [
318
+ " ",
319
+ running,
320
+ " \u8FD0\u884C"
321
+ ] }) : null,
322
+ failed > 0 ? /* @__PURE__ */ jsxs6(Text6, { color: defaultTheme.error, children: [
323
+ " ",
324
+ failed,
325
+ " \u5931\u8D25"
326
+ ] }) : null,
327
+ "]"
328
+ ] })
329
+ ] }),
330
+ /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", marginTop: 0, children: agents.map((agent, i) => /* @__PURE__ */ jsx6(
331
+ AgentNodeRow,
332
+ {
333
+ node: agent,
334
+ depth: 0,
335
+ isLast: i === total - 1
336
+ },
337
+ agent.id
338
+ )) })
339
+ ] });
340
+ }
341
+
342
+ // src/ui/ConfirmDialog.tsx
343
+ import { useState as useState2, useEffect as useEffect2 } from "react";
344
+ import { Text as Text7, Box as Box7, useInput } from "ink";
345
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
346
+ function ConfirmDialog({ message, detail, onConfirm, onReject }) {
347
+ const [selected, setSelected] = useState2("reject");
348
+ useInput((input, key) => {
349
+ if (key.leftArrow || key.rightArrow) {
350
+ setSelected((prev) => prev === "confirm" ? "reject" : "confirm");
351
+ }
352
+ if (key.return) {
353
+ if (selected === "confirm") {
354
+ onConfirm();
355
+ } else {
356
+ onReject();
357
+ }
358
+ }
359
+ if (input === "y" || input === "Y") {
360
+ onConfirm();
361
+ }
362
+ if (input === "n" || input === "N") {
363
+ onReject();
364
+ }
365
+ });
366
+ useEffect2(() => {
367
+ setSelected("reject");
368
+ }, [message]);
369
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", borderStyle: "double", borderColor: defaultTheme.warning, paddingX: 2, paddingY: 1, children: [
370
+ /* @__PURE__ */ jsx7(Box7, { children: /* @__PURE__ */ jsxs7(Text7, { bold: true, color: defaultTheme.warning, children: [
371
+ "\u26A0 ",
372
+ message
373
+ ] }) }),
374
+ detail ? /* @__PURE__ */ jsx7(Box7, { marginTop: 0, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: detail }) }) : null,
375
+ /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, children: [
376
+ /* @__PURE__ */ jsx7(Box7, { marginRight: 2, children: /* @__PURE__ */ jsxs7(
377
+ Text7,
378
+ {
379
+ color: selected === "confirm" ? defaultTheme.success : defaultTheme.dimText,
380
+ bold: selected === "confirm",
381
+ children: [
382
+ selected === "confirm" ? "\u25B6 " : " ",
383
+ "[Y] \u786E\u8BA4"
384
+ ]
385
+ }
386
+ ) }),
387
+ /* @__PURE__ */ jsx7(Box7, { children: /* @__PURE__ */ jsxs7(
388
+ Text7,
389
+ {
390
+ color: selected === "reject" ? defaultTheme.error : defaultTheme.dimText,
391
+ bold: selected === "reject",
392
+ children: [
393
+ selected === "reject" ? "\u25B6 " : " ",
394
+ "[N] \u53D6\u6D88"
395
+ ]
396
+ }
397
+ ) })
398
+ ] })
399
+ ] });
400
+ }
401
+
402
+ // src/ui/StatusBar.tsx
403
+ import { useState as useState3, useEffect as useEffect3 } from "react";
404
+ import { Text as Text8, Box as Box8 } from "ink";
405
+
406
+ // src/core/eventbus.ts
407
+ import { EventEmitter } from "events";
408
+ var Events = {
409
+ CONTEXT_UPDATED: "context:updated",
410
+ MESSAGE_SEND: "message:send",
411
+ MESSAGE_RECEIVED: "message:received",
412
+ MESSAGE_STREAMING: "message:streaming",
413
+ TOOL_CALL_START: "tool:call:start",
414
+ TOOL_CALL_END: "tool:call:end",
415
+ FILE_DIFF: "file:diff",
416
+ AGENT_TREE_UPDATED: "agent:tree:updated",
417
+ APP_QUIT: "app:quit",
418
+ APP_CLEAR: "app:clear",
419
+ STATUS_UPDATE: "status:update",
420
+ CONFIG_CHANGED: "config:changed",
421
+ AGENT_STATUS_CHANGE: "agent:status:change",
422
+ AGENT_CREATED: "agent:created",
423
+ AGENT_THINKING: "agent:thinking",
424
+ AGENT_EXECUTING: "agent:executing",
425
+ AGENT_WAITING: "agent:waiting",
426
+ AGENT_COMPLETED: "agent:completed",
427
+ AGENT_FAILED: "agent:failed",
428
+ AGENT_CANCELLED: "agent:cancelled",
429
+ AGENT_LOOP_ITERATION: "agent:loop:iteration",
430
+ AGENT_LOOP_DETECTED: "agent:loop:detected",
431
+ AGENT_LOOP_LIMIT: "agent:loop:limit",
432
+ TOOL_CALL_ERROR: "tool:call:error",
433
+ ORCHESTRATOR_DECOMPOSE: "orchestrator:decompose",
434
+ ORCHESTRATOR_DISPATCH: "orchestrator:dispatch",
435
+ ORCHESTRATOR_AGGREGATE: "orchestrator:aggregate",
436
+ SUBAGENT_START: "subagent:start",
437
+ SUBAGENT_TIMEOUT: "subagent:timeout",
438
+ SUBAGENT_COMPLETE: "subagent:complete",
439
+ SUBAGENT_ERROR: "subagent:error",
440
+ POOL_ACQUIRE: "pool:acquire",
441
+ POOL_RELEASE: "pool:release",
442
+ POOL_QUEUE: "pool:queue",
443
+ CONTEXT_SUMMARIZED: "context:summarized",
444
+ CONTEXT_TOKEN_WARNING: "context:token:warning",
445
+ MCP_CONNECTED: "mcp:connected",
446
+ MCP_ERROR: "mcp:error",
447
+ MCP_DISCONNECTED: "mcp:disconnected",
448
+ MCP_TOOLS_DISCOVERED: "mcp:tools:discovered",
449
+ SKILL_LOADED: "skill:loaded",
450
+ SKILL_EXECUTED: "skill:executed",
451
+ SKILL_CREATED: "skill:created",
452
+ SKILL_TRIGGERED: "skill:triggered"
453
+ };
454
+ var EventBusEvents = Events;
455
+ var EventBus = class _EventBus extends EventEmitter {
456
+ static instance;
457
+ static getInstance() {
458
+ if (!_EventBus.instance) {
459
+ _EventBus.instance = new _EventBus();
460
+ }
461
+ return _EventBus.instance;
462
+ }
463
+ onContextUpdated(handler) {
464
+ this.on(EventBusEvents.CONTEXT_UPDATED, handler);
465
+ }
466
+ emitContextUpdated(payload) {
467
+ this.emit(EventBusEvents.CONTEXT_UPDATED, payload);
468
+ }
469
+ onMessageSend(handler) {
470
+ this.on(EventBusEvents.MESSAGE_SEND, handler);
471
+ }
472
+ emitMessageSend(payload) {
473
+ this.emit(EventBusEvents.MESSAGE_SEND, payload);
474
+ }
475
+ onMessageReceived(handler) {
476
+ this.on(EventBusEvents.MESSAGE_RECEIVED, handler);
477
+ }
478
+ emitMessageReceived(payload) {
479
+ this.emit(EventBusEvents.MESSAGE_RECEIVED, payload);
480
+ }
481
+ onMessageStreaming(handler) {
482
+ this.on(EventBusEvents.MESSAGE_STREAMING, handler);
483
+ }
484
+ emitMessageStreaming(payload) {
485
+ this.emit(EventBusEvents.MESSAGE_STREAMING, payload);
486
+ }
487
+ onToolCallStart(handler) {
488
+ this.on(EventBusEvents.TOOL_CALL_START, handler);
489
+ }
490
+ emitToolCallStart(payload) {
491
+ this.emit(EventBusEvents.TOOL_CALL_START, payload);
492
+ }
493
+ onToolCallEnd(handler) {
494
+ this.on(EventBusEvents.TOOL_CALL_END, handler);
495
+ }
496
+ emitToolCallEnd(payload) {
497
+ this.emit(EventBusEvents.TOOL_CALL_END, payload);
498
+ }
499
+ onFileDiff(handler) {
500
+ this.on(EventBusEvents.FILE_DIFF, handler);
501
+ }
502
+ emitFileDiff(payload) {
503
+ this.emit(EventBusEvents.FILE_DIFF, payload);
504
+ }
505
+ onAgentTreeUpdated(handler) {
506
+ this.on(EventBusEvents.AGENT_TREE_UPDATED, handler);
507
+ }
508
+ emitAgentTreeUpdated(payload) {
509
+ this.emit(EventBusEvents.AGENT_TREE_UPDATED, payload);
510
+ }
511
+ onAppQuit(handler) {
512
+ this.on(EventBusEvents.APP_QUIT, handler);
513
+ }
514
+ emitAppQuit() {
515
+ this.emit(EventBusEvents.APP_QUIT);
516
+ }
517
+ onAppClear(handler) {
518
+ this.on(EventBusEvents.APP_CLEAR, handler);
519
+ }
520
+ emitAppClear() {
521
+ this.emit(EventBusEvents.APP_CLEAR);
522
+ }
523
+ onStatusUpdate(handler) {
524
+ this.on(EventBusEvents.STATUS_UPDATE, handler);
525
+ }
526
+ emitStatusUpdate(payload) {
527
+ this.emit(EventBusEvents.STATUS_UPDATE, payload);
528
+ }
529
+ onConfigChanged(handler) {
530
+ this.on(EventBusEvents.CONFIG_CHANGED, handler);
531
+ }
532
+ emitConfigChanged(payload) {
533
+ this.emit(EventBusEvents.CONFIG_CHANGED, payload);
534
+ }
535
+ reset() {
536
+ this.removeAllListeners();
537
+ }
538
+ };
539
+ var eventbus = EventBus.getInstance();
540
+
541
+ // src/ui/StatusBar.tsx
542
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
543
+ function fmtTokens(n) {
544
+ return n > 1e3 ? `${(n / 1e3).toFixed(1)}K` : `${n}`;
545
+ }
546
+ function fmtUptime(ms) {
547
+ const s = Math.floor(ms / 1e3);
548
+ if (s < 60) return `${s}s`;
549
+ const m = Math.floor(s / 60);
550
+ return `${m}m ${s % 60}s`;
551
+ }
552
+ function StatusBar() {
553
+ const [st, setSt] = useState3({
554
+ modelName: "deepseek-v4-pro",
555
+ tokenCount: 0,
556
+ memoryUsage: 0,
557
+ uptime: 0
558
+ });
559
+ useEffect3(() => {
560
+ const h = (p) => setSt((prev) => ({ ...prev, ...p }));
561
+ eventbus.onStatusUpdate(h);
562
+ eventbus.onContextUpdated(h);
563
+ return () => {
564
+ eventbus.removeAllListeners();
565
+ };
566
+ }, []);
567
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "row", paddingX: 1, children: [
568
+ /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: st.modelName }),
569
+ /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
570
+ " | Tok: ",
571
+ fmtTokens(st.tokenCount)
572
+ ] }),
573
+ /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
574
+ " | Mem: ",
575
+ st.memoryUsage,
576
+ "MB"
577
+ ] }),
578
+ /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
579
+ " | ",
580
+ fmtUptime(st.uptime)
581
+ ] }),
582
+ /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: " | Ctrl+C \u9000\u51FA" })
583
+ ] });
584
+ }
585
+
586
+ // src/ui/InputBox.tsx
587
+ import { useState as useState4, useCallback, useRef } from "react";
588
+ import { Text as Text9, Box as Box9, useInput as useInput2 } from "ink";
589
+
590
+ // src/model/types.ts
591
+ var SLASH_COMMANDS = [
592
+ { command: "/help", description: "\u663E\u793A\u5E2E\u52A9\u4FE1\u606F" },
593
+ { command: "/clear", description: "\u6E05\u7A7A\u5BF9\u8BDD" },
594
+ { command: "/quit", description: "\u9000\u51FA DeeperCode" },
595
+ { command: "/model", description: "\u67E5\u770B/\u5207\u6362\u6A21\u578B" },
596
+ { command: "/config", description: "\u67E5\u770B/\u4FEE\u6539\u914D\u7F6E" },
597
+ { command: "/tools", description: "\u5217\u51FA\u53EF\u7528\u5DE5\u5177" },
598
+ { command: "/skills", description: "\u5217\u51FA\u5DF2\u52A0\u8F7D\u6280\u80FD" },
599
+ { command: "/mcp", description: "\u7BA1\u7406 MCP \u8FDE\u63A5" },
600
+ { command: "/save", description: "\u4FDD\u5B58\u5F53\u524D\u4F1A\u8BDD" },
601
+ { command: "/load", description: "\u52A0\u8F7D\u5386\u53F2\u4F1A\u8BDD" }
602
+ ];
603
+
604
+ // src/ui/InputBox.tsx
605
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
606
+ var MAX_HISTORY = 100;
607
+ var history = [];
608
+ function addHistory(content) {
609
+ if (content.trim() && history[history.length - 1] !== content) {
610
+ history.push(content);
611
+ if (history.length > MAX_HISTORY) {
612
+ history.shift();
613
+ }
614
+ }
615
+ }
616
+ function InputBox({ onSubmit, placeholder = "\u8F93\u5165\u6D88\u606F..." }) {
617
+ const [value, setValue] = useState4("");
618
+ const [cursorPos, setCursorPos] = useState4(0);
619
+ const [historyIndex, setHistoryIndex] = useState4(-1);
620
+ const [showConfirmExit, setShowConfirmExit] = useState4(false);
621
+ const [tabSuggestions, setTabSuggestions] = useState4([]);
622
+ const [showSuggestions, setShowSuggestions] = useState4(false);
623
+ const valueRef = useRef(value);
624
+ valueRef.current = value;
625
+ const handleSubmit = useCallback(() => {
626
+ const trimmed = value.trim();
627
+ if (!trimmed) return;
628
+ if (trimmed.startsWith("/")) {
629
+ const cmd = SLASH_COMMANDS.find((c) => trimmed.startsWith(c.command));
630
+ if (cmd) {
631
+ eventbus.emitMessageSend({ content: trimmed });
632
+ addHistory(trimmed);
633
+ setValue("");
634
+ setCursorPos(0);
635
+ setHistoryIndex(-1);
636
+ return;
637
+ }
638
+ }
639
+ onSubmit(trimmed);
640
+ eventbus.emitMessageSend({ content: trimmed });
641
+ addHistory(trimmed);
642
+ setValue("");
643
+ setCursorPos(0);
644
+ setHistoryIndex(-1);
645
+ }, [value, onSubmit]);
646
+ const handleTabComplete = useCallback(() => {
647
+ if (value.startsWith("/")) {
648
+ const matching = SLASH_COMMANDS.filter((c) => c.command.startsWith(value)).map((c) => c.command);
649
+ if (matching.length === 1) {
650
+ setValue(matching[0] + " ");
651
+ setCursorPos(matching[0].length + 1);
652
+ setShowSuggestions(false);
653
+ } else if (matching.length > 1) {
654
+ setTabSuggestions(matching);
655
+ setShowSuggestions(true);
656
+ }
657
+ }
658
+ }, [value]);
659
+ useInput2((input, key) => {
660
+ if (showConfirmExit) {
661
+ if (input === "y" || input === "Y") {
662
+ eventbus.emitAppQuit();
663
+ return;
664
+ }
665
+ if (input === "n" || input === "N" || key.escape) {
666
+ setShowConfirmExit(false);
667
+ return;
668
+ }
669
+ return;
670
+ }
671
+ if (input === "") {
672
+ setShowConfirmExit(true);
673
+ return;
674
+ }
675
+ if (key.return) {
676
+ if (key.ctrl) {
677
+ handleSubmit();
678
+ return;
679
+ }
680
+ if (showSuggestions) {
681
+ setShowSuggestions(false);
682
+ return;
683
+ }
684
+ handleSubmit();
685
+ return;
686
+ }
687
+ if (key.tab) {
688
+ handleTabComplete();
689
+ return;
690
+ }
691
+ if (key.upArrow) {
692
+ if (showSuggestions) {
693
+ setShowSuggestions(false);
694
+ return;
695
+ }
696
+ if (history.length === 0) return;
697
+ const newIndex = historyIndex === -1 ? history.length - 1 : Math.max(0, historyIndex - 1);
698
+ setHistoryIndex(newIndex);
699
+ setValue(history[newIndex]);
700
+ setCursorPos(history[newIndex].length);
701
+ return;
702
+ }
703
+ if (key.downArrow) {
704
+ if (showSuggestions) {
705
+ setShowSuggestions(false);
706
+ return;
707
+ }
708
+ if (historyIndex === -1) return;
709
+ const newIndex = historyIndex + 1;
710
+ if (newIndex >= history.length) {
711
+ setHistoryIndex(-1);
712
+ setValue("");
713
+ setCursorPos(0);
714
+ } else {
715
+ setHistoryIndex(newIndex);
716
+ setValue(history[newIndex]);
717
+ setCursorPos(history[newIndex].length);
718
+ }
719
+ return;
720
+ }
721
+ if (key.escape) {
722
+ setShowSuggestions(false);
723
+ return;
724
+ }
725
+ if (key.backspace || key.delete) {
726
+ setShowSuggestions(false);
727
+ if (key.backspace) {
728
+ if (cursorPos > 0) {
729
+ const newVal = value.slice(0, cursorPos - 1) + value.slice(cursorPos);
730
+ setValue(newVal);
731
+ setCursorPos(Math.max(0, cursorPos - 1));
732
+ }
733
+ }
734
+ if (key.delete) {
735
+ if (cursorPos < value.length) {
736
+ const newVal = value.slice(0, cursorPos) + value.slice(cursorPos + 1);
737
+ setValue(newVal);
738
+ }
739
+ }
740
+ return;
741
+ }
742
+ if (key.leftArrow) {
743
+ setCursorPos(Math.max(0, cursorPos - 1));
744
+ return;
745
+ }
746
+ if (key.rightArrow) {
747
+ setCursorPos(Math.min(value.length, cursorPos + 1));
748
+ return;
749
+ }
750
+ if (key.home) {
751
+ setCursorPos(0);
752
+ return;
753
+ }
754
+ if (key.end) {
755
+ setCursorPos(value.length);
756
+ return;
757
+ }
758
+ if (input && input.length === 1 && !key.ctrl && !key.meta) {
759
+ const newVal = value.slice(0, cursorPos) + input + value.slice(cursorPos);
760
+ setValue(newVal);
761
+ setCursorPos(cursorPos + 1);
762
+ if (newVal.startsWith("/") && newVal.length > 1) {
763
+ const matching = SLASH_COMMANDS.filter((c) => c.command.startsWith(newVal)).map((c) => c.command);
764
+ if (matching.length > 0) {
765
+ setTabSuggestions(matching);
766
+ setShowSuggestions(true);
767
+ } else {
768
+ setShowSuggestions(false);
769
+ }
770
+ } else {
771
+ setShowSuggestions(false);
772
+ }
773
+ return;
774
+ }
775
+ });
776
+ if (showConfirmExit) {
777
+ return /* @__PURE__ */ jsxs9(
778
+ Box9,
779
+ {
780
+ flexDirection: "column",
781
+ borderStyle: "double",
782
+ borderColor: defaultTheme.error,
783
+ paddingX: 2,
784
+ paddingY: 0,
785
+ children: [
786
+ /* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsx9(Text9, { bold: true, color: defaultTheme.error, children: "\u26A0 \u786E\u8BA4\u9000\u51FA DeeperCode?" }) }),
787
+ /* @__PURE__ */ jsx9(Box9, { marginTop: 0, children: /* @__PURE__ */ jsx9(Text9, { children: "\u6309 [Y] \u9000\u51FA [N/ESC] \u53D6\u6D88" }) })
788
+ ]
789
+ }
790
+ );
791
+ }
792
+ const cursorChar = "\u2588";
793
+ const beforeCursor = value.slice(0, cursorPos);
794
+ const atCursor = value[cursorPos] || " ";
795
+ const afterCursor = value.slice(cursorPos + 1);
796
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
797
+ showSuggestions && tabSuggestions.length > 0 ? /* @__PURE__ */ jsx9(Box9, { flexDirection: "column", borderStyle: "single", borderColor: defaultTheme.border, paddingX: 1, children: tabSuggestions.map((s) => /* @__PURE__ */ jsx9(Text9, { color: defaultTheme.primary, children: s }, s)) }) : null,
798
+ /* @__PURE__ */ jsxs9(
799
+ Box9,
800
+ {
801
+ flexDirection: "row",
802
+ borderStyle: "round",
803
+ borderColor: defaultTheme.primary,
804
+ paddingX: 1,
805
+ children: [
806
+ /* @__PURE__ */ jsx9(Text9, { color: defaultTheme.primary, bold: true, children: "\u276F " }),
807
+ /* @__PURE__ */ jsxs9(Box9, { children: [
808
+ /* @__PURE__ */ jsx9(Text9, { children: beforeCursor }),
809
+ /* @__PURE__ */ jsx9(Text9, { backgroundColor: defaultTheme.primary, color: defaultTheme.background, children: atCursor }),
810
+ /* @__PURE__ */ jsx9(Text9, { children: afterCursor }),
811
+ value.length === 0 ? /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: placeholder }) : null
812
+ ] }),
813
+ /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: " Ctrl+Enter \u53D1\u9001" })
814
+ ]
815
+ }
816
+ )
817
+ ] });
818
+ }
819
+
820
+ // src/ui/ChatView.tsx
821
+ import { useEffect as useEffect4, useState as useState5, useRef as useRef2 } from "react";
822
+ import { Text as Text10, Box as Box10, useStdin } from "ink";
823
+ import readline from "readline";
824
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
825
+ var HISTORY_MAX = 100;
826
+ var history2 = [];
827
+ var SLASH_RESULTS = {
828
+ "/help": "\u547D\u4EE4: /help /clear /quit /config /model /tools /export /theme",
829
+ "/clear": "__CLEAR__",
830
+ "/quit": "__QUIT__",
831
+ "/config": "\u6253\u5F00\u914D\u7F6E: deeper config list | deeper config set <key> <value>",
832
+ "/model": "\u6A21\u578B: deepseek-v4-pro / v4-flash",
833
+ "/tools": "105 \u4E2A\u5185\u7F6E\u5DE5\u5177\u5DF2\u5C31\u7EEA",
834
+ "/export": "\u5BF9\u8BDD\u5BFC\u51FA\u529F\u80FD\u5F00\u53D1\u4E2D",
835
+ "/theme": "\u4E3B\u9898: dark | \u5207\u6362: deeper config set theme light"
836
+ };
837
+ function ChatView({ initialMessages = [], apiKey, model }) {
838
+ const [messages, setMessages] = useState5(initialMessages);
839
+ const [thinking, setThinking] = useState5(false);
840
+ const keyRef = useRef2(apiKey);
841
+ const modelRef = useRef2(model || "deepseek-v4-pro");
842
+ keyRef.current = apiKey;
843
+ useEffect4(() => {
844
+ const onMsg = (p) => {
845
+ setMessages((prev) => [...prev, { ...p }]);
846
+ };
847
+ const onClear = () => {
848
+ setMessages([]);
849
+ setThinking(false);
850
+ };
851
+ eventbus.onMessageReceived(onMsg);
852
+ eventbus.onAppClear(onClear);
853
+ return () => {
854
+ eventbus.removeAllListeners();
855
+ };
856
+ }, []);
857
+ const handleSubmit = (content) => {
858
+ const trimmed = content.trim();
859
+ if (!trimmed) return;
860
+ if (SLASH_RESULTS[trimmed]) {
861
+ const r = SLASH_RESULTS[trimmed];
862
+ if (r === "__QUIT__") {
863
+ eventbus.emitAppQuit();
864
+ return;
865
+ }
866
+ if (r === "__CLEAR__") {
867
+ setMessages([]);
868
+ return;
869
+ }
870
+ setMessages((prev) => [...prev, { id: `s-${Date.now()}`, role: "system", content: r, timestamp: Date.now() }]);
871
+ return;
872
+ }
873
+ history2.push(trimmed);
874
+ if (history2.length > HISTORY_MAX) history2.shift();
875
+ const um = { id: `u-${Date.now()}`, role: "user", content: trimmed, timestamp: Date.now() };
876
+ setMessages((prev) => [...prev, um]);
877
+ eventbus.emitMessageSend({ content: trimmed });
878
+ const currentKey = keyRef.current || "";
879
+ if (!currentKey) {
880
+ setMessages((prev) => [...prev, {
881
+ id: `a-${Date.now()}`,
882
+ role: "system",
883
+ content: '\u26A0 \u672A\u914D\u7F6E API Key\u3002\n\n\u8BF7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u914D\u7F6E:\n deeper config set apiKey "sk-\u4F60\u7684DeepSeek\u5BC6\u94A5"\n\n\u83B7\u53D6\u5BC6\u94A5: https://platform.deepseek.com',
884
+ timestamp: Date.now()
885
+ }]);
886
+ return;
887
+ }
888
+ setThinking(true);
889
+ callDeepSeek(trimmed, currentKey, modelRef.current, messages).then((responseText) => {
890
+ setThinking(false);
891
+ setMessages((prev) => [...prev, {
892
+ id: `a-${Date.now()}`,
893
+ role: "assistant",
894
+ content: responseText,
895
+ timestamp: Date.now()
896
+ }]);
897
+ }).catch((err) => {
898
+ setThinking(false);
899
+ setMessages((prev) => [...prev, {
900
+ id: `a-${Date.now()}`,
901
+ role: "system",
902
+ content: `\u274C API \u8BF7\u6C42\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`,
903
+ timestamp: Date.now()
904
+ }]);
905
+ });
906
+ };
907
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
908
+ /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingX: 1, children: [
909
+ messages.length === 0 && !thinking ? /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingY: 1, children: [
910
+ /* @__PURE__ */ jsxs10(Box10, { children: [
911
+ /* @__PURE__ */ jsx10(Text10, { bold: true, color: defaultTheme.primary, children: "DeeperCode" }),
912
+ /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: " \u2014 \u4E00\u53E5\u8BDD\u751F\u6210\u5B8C\u6574\u9879\u76EE" })
913
+ ] }),
914
+ /* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "\u8F93\u5165\u4F60\u7684\u4EFB\u52A1\u6216 /help \u67E5\u770B\u547D\u4EE4" }) })
915
+ ] }) : null,
916
+ messages.map((m) => /* @__PURE__ */ jsx10(MessageBubble, { role: m.role, content: m.content, timestamp: m.timestamp }, m.id)),
917
+ thinking ? /* @__PURE__ */ jsx10(Box10, { marginY: 1, children: /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "\u601D\u8003\u4E2D..." }) }) : null
918
+ ] }),
919
+ /* @__PURE__ */ jsx10(InputLine, { onSubmit: handleSubmit })
920
+ ] });
921
+ }
922
+ async function callDeepSeek(prompt, apiKey, model, history3) {
923
+ const systemMsg = {
924
+ role: "system",
925
+ content: "\u4F60\u662F DeeperCode AI \u7F16\u7A0B\u52A9\u624B\uFF0C\u57FA\u4E8E DeepSeek-V4-Pro\u3002\u4F60\u64C5\u957F\u7F16\u5199\u4EE3\u7801\u3001\u8C03\u8BD5\u3001\u9879\u76EE\u6784\u5EFA\u548C\u6280\u672F\u95EE\u9898\u89E3\u7B54\u3002\u8BF7\u7528\u4E2D\u6587\u56DE\u590D\uFF0C\u4EE3\u7801\u4FDD\u6301\u539F\u6837\u3002"
926
+ };
927
+ const recentHistory = history3.slice(-20).map((m) => ({
928
+ role: m.role === "system" ? "system" : m.role,
929
+ content: m.content || ""
930
+ }));
931
+ const messages = [systemMsg, ...recentHistory, { role: "user", content: prompt }];
932
+ const response = await fetch("https://api.deepseek.com/v1/chat/completions", {
933
+ method: "POST",
934
+ headers: {
935
+ "Content-Type": "application/json",
936
+ "Authorization": `Bearer ${apiKey}`
937
+ },
938
+ body: JSON.stringify({
939
+ model,
940
+ messages,
941
+ stream: false,
942
+ max_tokens: 4096,
943
+ temperature: 0.7
944
+ })
945
+ });
946
+ if (!response.ok) {
947
+ const errText = await response.text().catch(() => "");
948
+ if (response.status === 401) throw new Error("API Key \u65E0\u6548\u6216\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u68C0\u67E5\u914D\u7F6E");
949
+ throw new Error(`HTTP ${response.status}: ${errText.slice(0, 200)}`);
950
+ }
951
+ const data = await response.json();
952
+ return data.choices?.[0]?.message?.content || "(\u7A7A\u54CD\u5E94)";
953
+ }
954
+ function InputLine({ onSubmit }) {
955
+ const { stdin } = useStdin();
956
+ const [buf, setBuf] = useState5("");
957
+ const bufRef = useRef2("");
958
+ bufRef.current = buf;
959
+ const histIdx = useRef2(-1);
960
+ const cursorRef = useRef2(0);
961
+ useEffect4(() => {
962
+ if (!stdin) return;
963
+ readline.emitKeypressEvents(stdin);
964
+ const onKP = (str, key) => {
965
+ if (key.ctrl && key.name === "c") {
966
+ eventbus.emitAppQuit();
967
+ return;
968
+ }
969
+ if (key.name === "return" || key.name === "enter") {
970
+ if (bufRef.current.trim()) {
971
+ onSubmit(bufRef.current);
972
+ }
973
+ bufRef.current = "";
974
+ cursorRef.current = 0;
975
+ setBuf("");
976
+ histIdx.current = -1;
977
+ return;
978
+ }
979
+ if (key.name === "backspace") {
980
+ if (cursorRef.current > 0) {
981
+ const prev = bufRef.current;
982
+ bufRef.current = prev.slice(0, cursorRef.current - 1) + prev.slice(cursorRef.current);
983
+ cursorRef.current = Math.max(0, cursorRef.current - 1);
984
+ setBuf(bufRef.current);
985
+ }
986
+ return;
987
+ }
988
+ if (key.name === "delete") {
989
+ if (cursorRef.current < bufRef.current.length) {
990
+ const prev = bufRef.current;
991
+ bufRef.current = prev.slice(0, cursorRef.current) + prev.slice(cursorRef.current + 1);
992
+ setBuf(bufRef.current);
993
+ }
994
+ return;
995
+ }
996
+ if (key.name === "left") {
997
+ cursorRef.current = Math.max(0, cursorRef.current - 1);
998
+ return;
999
+ }
1000
+ if (key.name === "right") {
1001
+ cursorRef.current = Math.min(bufRef.current.length, cursorRef.current + 1);
1002
+ return;
1003
+ }
1004
+ if (key.name === "home") {
1005
+ cursorRef.current = 0;
1006
+ return;
1007
+ }
1008
+ if (key.name === "end") {
1009
+ cursorRef.current = bufRef.current.length;
1010
+ return;
1011
+ }
1012
+ if (key.name === "up") {
1013
+ if (history2.length === 0) return;
1014
+ const idx = histIdx.current === -1 ? history2.length - 1 : Math.max(0, histIdx.current - 1);
1015
+ histIdx.current = idx;
1016
+ bufRef.current = history2[idx];
1017
+ cursorRef.current = bufRef.current.length;
1018
+ setBuf(bufRef.current);
1019
+ return;
1020
+ }
1021
+ if (key.name === "down") {
1022
+ if (histIdx.current === -1) return;
1023
+ const idx = histIdx.current + 1;
1024
+ if (idx >= history2.length) {
1025
+ histIdx.current = -1;
1026
+ bufRef.current = "";
1027
+ cursorRef.current = 0;
1028
+ } else {
1029
+ histIdx.current = idx;
1030
+ bufRef.current = history2[idx];
1031
+ cursorRef.current = bufRef.current.length;
1032
+ }
1033
+ setBuf(bufRef.current);
1034
+ return;
1035
+ }
1036
+ if (str) {
1037
+ const prev = bufRef.current;
1038
+ bufRef.current = prev.slice(0, cursorRef.current) + str + prev.slice(cursorRef.current);
1039
+ cursorRef.current += str.length;
1040
+ setBuf(bufRef.current);
1041
+ histIdx.current = -1;
1042
+ }
1043
+ };
1044
+ stdin.on("keypress", onKP);
1045
+ return () => {
1046
+ stdin.removeListener("keypress", onKP);
1047
+ };
1048
+ }, []);
1049
+ const before = buf.slice(0, cursorRef.current);
1050
+ const at = buf[cursorRef.current] || " ";
1051
+ const after = buf.slice(cursorRef.current + 1);
1052
+ return /* @__PURE__ */ jsxs10(Box10, { paddingX: 1, children: [
1053
+ /* @__PURE__ */ jsx10(Text10, { color: defaultTheme.primary, bold: true, children: "\u276F " }),
1054
+ /* @__PURE__ */ jsx10(Text10, { children: before }),
1055
+ /* @__PURE__ */ jsx10(Text10, { inverse: true, children: at }),
1056
+ /* @__PURE__ */ jsx10(Text10, { children: after })
1057
+ ] });
1058
+ }
1059
+
1060
+ // src/ui/App.tsx
1061
+ import { useEffect as useEffect5, useState as useState6, useRef as useRef3 } from "react";
1062
+ import { Box as Box11 } from "ink";
1063
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1064
+ function App({ apiKey, model, autoRun }) {
1065
+ const [initialMessages, setInitialMessages] = useState6([]);
1066
+ const startTimeRef = useRef3(Date.now());
1067
+ useEffect5(() => {
1068
+ const memTimer = setInterval(() => {
1069
+ eventbus.emitStatusUpdate({
1070
+ memoryUsage: Math.round(process.memoryUsage().heapUsed / (1024 * 1024)),
1071
+ uptime: Date.now() - startTimeRef.current
1072
+ });
1073
+ }, 5e3);
1074
+ if (autoRun) {
1075
+ setInitialMessages([{
1076
+ id: `auto-${Date.now()}`,
1077
+ role: "user",
1078
+ content: autoRun,
1079
+ timestamp: Date.now()
1080
+ }]);
1081
+ }
1082
+ return () => {
1083
+ clearInterval(memTimer);
1084
+ eventbus.reset();
1085
+ };
1086
+ }, []);
1087
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", width: "100%", children: [
1088
+ /* @__PURE__ */ jsx11(
1089
+ ChatView,
1090
+ {
1091
+ initialMessages,
1092
+ apiKey,
1093
+ model
1094
+ }
1095
+ ),
1096
+ /* @__PURE__ */ jsx11(StatusBar, {})
1097
+ ] });
1098
+ }
1099
+
1100
+ // src/core/config.ts
1101
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
1102
+ import { dirname, join as join2 } from "path";
1103
+ import process3 from "process";
1104
+
1105
+ // src/core/constants.ts
1106
+ import { homedir } from "os";
1107
+ import { join } from "path";
1108
+ import process2 from "process";
1109
+ var DEEPER_VERSION = "1.0.0";
1110
+ var DEEPER_NAME = "DeeperCode";
1111
+ var DEEPER_HOME = join(process2.env.DEEPER_HOME || join(homedir(), ".deeper"));
1112
+ var DEEPER_CONFIG_FILE = join(DEEPER_HOME, "config.json");
1113
+ var DEEPER_MCP_FILE = join(DEEPER_HOME, "mcp.json");
1114
+ var DEEPER_SKILLS_DIR = join(DEEPER_HOME, "skills");
1115
+ var DEEPER_SESSIONS_DIR = join(DEEPER_HOME, "sessions");
1116
+ var DEEPER_LOGS_DIR = join(DEEPER_HOME, "logs");
1117
+ var DEEPER_MEMORY_FILE = join(DEEPER_HOME, "memory.json");
1118
+ var PROJECT_CONFIG_DIR = ".deeper";
1119
+ var PROJECT_CONFIG_FILE = join(PROJECT_CONFIG_DIR, "config.json");
1120
+ var PROJECT_SKILLS_DIR = join(PROJECT_CONFIG_DIR, "skills");
1121
+ var DEEPSEEK_BASE_URL = "https://api.deepseek.com";
1122
+ var DEEPSEEK_DEFAULT_MODEL = "deepseek-v4-pro";
1123
+ var AGENT_MAX_SUB_AGENTS = 5;
1124
+ var CONTEXT_MAX_TOKENS = 1048576;
1125
+ var MCP_CONNECTION_TIMEOUT_MS = 1e4;
1126
+ var TOOL_CATEGORIES = [
1127
+ "filesystem",
1128
+ "search",
1129
+ "shell",
1130
+ "network",
1131
+ "code",
1132
+ "database",
1133
+ "data",
1134
+ "security",
1135
+ "project",
1136
+ "ai",
1137
+ "system"
1138
+ ];
1139
+
1140
+ // src/core/config.ts
1141
+ var DEFAULT_CONFIG = {
1142
+ model: DEEPSEEK_DEFAULT_MODEL,
1143
+ apiKey: process3.env.DEEPSEEK_API_KEY || "",
1144
+ baseUrl: DEEPSEEK_BASE_URL,
1145
+ temperature: 0.7,
1146
+ maxTokens: 8192,
1147
+ thinkEnabled: true,
1148
+ thinkBudget: 32e3,
1149
+ thinkBudgetTokens: 32e3,
1150
+ logLevel: "info",
1151
+ maxRetries: 3,
1152
+ timeoutMs: 12e4,
1153
+ maxSubAgents: 5,
1154
+ maxRecursionDepth: 2,
1155
+ theme: "dark",
1156
+ locale: "zh-CN",
1157
+ mcpServers: [],
1158
+ skills: []
1159
+ };
1160
+ var PROJECT_CONFIG_PATH = join2(process3.cwd(), PROJECT_CONFIG_FILE);
1161
+ var cachedConfig = null;
1162
+ var KEY_ALIASES = {
1163
+ api_key: "apiKey",
1164
+ "api-key": "apiKey",
1165
+ base_url: "baseUrl",
1166
+ "base-url": "baseUrl",
1167
+ max_tokens: "maxTokens",
1168
+ "max-tokens": "maxTokens",
1169
+ think_enabled: "thinkEnabled",
1170
+ "think-enabled": "thinkEnabled",
1171
+ think_budget: "thinkBudget",
1172
+ "think-budget": "thinkBudget",
1173
+ log_level: "logLevel",
1174
+ "log-level": "logLevel",
1175
+ max_retries: "maxRetries",
1176
+ "max-retries": "maxRetries",
1177
+ timeout_ms: "timeoutMs",
1178
+ "timeout-ms": "timeoutMs",
1179
+ max_sub_agents: "maxSubAgents",
1180
+ "max-sub-agents": "maxSubAgents",
1181
+ max_recursion_depth: "maxRecursionDepth",
1182
+ "max-recursion-depth": "maxRecursionDepth",
1183
+ mcp_servers: "mcpServers",
1184
+ "mcp-servers": "mcpServers"
1185
+ };
1186
+ function normalizeConfig(raw) {
1187
+ const result = {};
1188
+ for (const [key, value] of Object.entries(raw)) {
1189
+ const canonical = KEY_ALIASES[key] || key;
1190
+ result[canonical] = value;
1191
+ }
1192
+ return result;
1193
+ }
1194
+ function loadConfig() {
1195
+ if (cachedConfig) return cachedConfig;
1196
+ try {
1197
+ if (existsSync(DEEPER_CONFIG_FILE)) {
1198
+ const raw = readFileSync(DEEPER_CONFIG_FILE, "utf-8");
1199
+ const parsed = JSON.parse(raw);
1200
+ cachedConfig = { ...DEFAULT_CONFIG, ...normalizeConfig(parsed) };
1201
+ } else {
1202
+ cachedConfig = { ...DEFAULT_CONFIG };
1203
+ }
1204
+ } catch {
1205
+ cachedConfig = { ...DEFAULT_CONFIG };
1206
+ }
1207
+ return cachedConfig;
1208
+ }
1209
+ function saveConfig(config) {
1210
+ if (config) cachedConfig = { ...config };
1211
+ if (!cachedConfig) cachedConfig = { ...DEFAULT_CONFIG };
1212
+ const dir = dirname(DEEPER_CONFIG_FILE);
1213
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
1214
+ writeFileSync(DEEPER_CONFIG_FILE, JSON.stringify(cachedConfig, null, 2), "utf-8");
1215
+ }
1216
+ function getConfig() {
1217
+ return cachedConfig ?? loadConfig();
1218
+ }
1219
+ function updateConfig(partial) {
1220
+ const current = getConfig();
1221
+ cachedConfig = { ...current, ...partial };
1222
+ saveConfig();
1223
+ return cachedConfig;
1224
+ }
1225
+ function resetConfig() {
1226
+ cachedConfig = { ...DEFAULT_CONFIG };
1227
+ saveConfig();
1228
+ return cachedConfig;
1229
+ }
1230
+ function getConfigValue(key) {
1231
+ return getConfig()[key];
1232
+ }
1233
+ function setConfigValue(key, value) {
1234
+ updateConfig({ [key]: value });
1235
+ }
1236
+ function getApiKey() {
1237
+ return getConfig().apiKey || process3.env.DEEPSEEK_API_KEY || "";
1238
+ }
1239
+ function getModel() {
1240
+ return getConfig().model;
1241
+ }
1242
+ function getBaseUrl() {
1243
+ return getConfig().baseUrl;
1244
+ }
1245
+
1246
+ // src/tools/tool-types.ts
1247
+ var TOOL_SAFETY_MAP = {
1248
+ read_file: "safe",
1249
+ list_dir: "safe",
1250
+ glob_find: "safe",
1251
+ file_info: "safe",
1252
+ grep_search: "safe",
1253
+ text_search: "safe",
1254
+ fuzzy_find: "safe",
1255
+ regex_find: "safe",
1256
+ find_references: "safe",
1257
+ find_definition: "safe",
1258
+ symbol_search: "safe",
1259
+ search_package: "safe",
1260
+ search_docs: "safe",
1261
+ codebase_search: "safe",
1262
+ token_count: "safe",
1263
+ system_info: "safe",
1264
+ process_list: "safe",
1265
+ resource_monitor: "safe",
1266
+ log_viewer: "safe",
1267
+ bug_scan: "safe",
1268
+ web_fetch: "safe",
1269
+ web_search: "safe",
1270
+ check_url: "safe",
1271
+ parse_html: "safe",
1272
+ http_request: "safe",
1273
+ watch_file: "safe",
1274
+ batch_read: "safe",
1275
+ create_dir: "safe",
1276
+ json_parse: "safe",
1277
+ csv_parse: "safe",
1278
+ xml_parse: "safe",
1279
+ yaml_parse: "safe",
1280
+ toml_parse: "safe",
1281
+ data_validate: "safe",
1282
+ data_diff: "safe",
1283
+ hash_generate: "safe",
1284
+ jwt_decode: "safe",
1285
+ coverage_report: "safe",
1286
+ config_manage: "safe",
1287
+ notify_user: "safe",
1288
+ format_code: "safe",
1289
+ lint_code: "safe",
1290
+ type_check: "safe",
1291
+ code_metrics: "safe",
1292
+ analyze_deps: "safe",
1293
+ import_organizer: "safe",
1294
+ parse_ast: "safe",
1295
+ db_schema: "safe",
1296
+ context_summarize: "safe",
1297
+ prompt_template: "safe",
1298
+ skill_create: "safe",
1299
+ tool_create: "safe",
1300
+ memory_store: "safe",
1301
+ todo_manager: "safe",
1302
+ subagent: "safe",
1303
+ background_terminal: "safe",
1304
+ list_terminals: "safe",
1305
+ read_terminal: "safe",
1306
+ send_keys: "safe",
1307
+ send_ctrl_keys: "safe",
1308
+ send_text: "safe",
1309
+ kill_terminal: "safe",
1310
+ terminal_screenshot: "safe",
1311
+ terminal_resize: "safe",
1312
+ check_status: "safe",
1313
+ stop_command: "safe",
1314
+ download_file: "safe",
1315
+ api_call: "safe",
1316
+ graphql_query: "safe",
1317
+ websocket_connect: "safe",
1318
+ write_file: "safe",
1319
+ edit_file: "safe",
1320
+ delete_file: "confirm",
1321
+ move_file: "confirm",
1322
+ copy_file: "confirm",
1323
+ batch_write: "safe",
1324
+ merge_files: "confirm",
1325
+ diff_files: "confirm",
1326
+ run_command: "safe",
1327
+ run_async: "safe",
1328
+ pipe_commands: "safe",
1329
+ shell_script: "confirm",
1330
+ npm_manage: "confirm",
1331
+ project_init: "confirm",
1332
+ build_project: "confirm",
1333
+ run_test: "confirm",
1334
+ docker_manage: "confirm",
1335
+ env_manage: "confirm",
1336
+ sql_query: "confirm",
1337
+ sql_migrate: "confirm",
1338
+ nosql_query: "confirm",
1339
+ db_backup: "confirm",
1340
+ db_restore: "confirm",
1341
+ redis_command: "confirm",
1342
+ encrypt_file: "confirm",
1343
+ decrypt_file: "confirm",
1344
+ template_render: "confirm",
1345
+ chart_generate: "confirm",
1346
+ secret_scan: "confirm",
1347
+ vulnerability_check: "confirm",
1348
+ orm_generate: "confirm",
1349
+ generate_code: "confirm",
1350
+ refactor_code: "confirm",
1351
+ extract_function: "confirm",
1352
+ data_transform: "confirm",
1353
+ proxy_request: "confirm",
1354
+ interactive_terminal: "confirm",
1355
+ browser_action: "confirm",
1356
+ screenshot_page: "confirm"
1357
+ };
1358
+
1359
+ // src/cli/bootstrap.ts
1360
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2 } from "fs";
1361
+ async function bootstrap() {
1362
+ const errors = [];
1363
+ const warnings = [];
1364
+ const nodeVersion = process.versions.node;
1365
+ const majorVersion = parseInt(nodeVersion.split(".")[0], 10);
1366
+ if (majorVersion < 20) {
1367
+ errors.push(`Node.js \u7248\u672C\u8FC7\u4F4E: ${nodeVersion}\uFF0C\u9700\u8981 >= 20.0.0`);
1368
+ return { success: false, errors, warnings, config: loadConfig() };
1369
+ }
1370
+ const dirs = [
1371
+ DEEPER_HOME,
1372
+ DEEPER_SKILLS_DIR,
1373
+ DEEPER_SESSIONS_DIR,
1374
+ DEEPER_LOGS_DIR
1375
+ ];
1376
+ for (const dir of dirs) {
1377
+ try {
1378
+ if (!existsSync2(dir)) {
1379
+ mkdirSync2(dir, { recursive: true });
1380
+ }
1381
+ } catch {
1382
+ errors.push(`\u65E0\u6CD5\u521B\u5EFA\u76EE\u5F55: ${dir}`);
1383
+ }
1384
+ }
1385
+ let config;
1386
+ try {
1387
+ config = loadConfig();
1388
+ } catch (e) {
1389
+ const msg = e instanceof Error ? e.message : String(e);
1390
+ errors.push(`\u914D\u7F6E\u52A0\u8F7D\u5931\u8D25: ${msg}`);
1391
+ config = loadConfig();
1392
+ }
1393
+ if (!config.apiKey && !process.env.DEEPSEEK_API_KEY) {
1394
+ warnings.push('\u672A\u8BBE\u7F6E API Key\u3002\u8BF7\u8FD0\u884C: deeper config set api_key "sk-\u4F60\u7684\u5BC6\u94A5"');
1395
+ }
1396
+ if (errors.length > 0) {
1397
+ return { success: false, errors, warnings, config };
1398
+ }
1399
+ return { success: true, errors, warnings, config };
1400
+ }
1401
+ function checkNodeVersion() {
1402
+ const nodeVersion = process.versions.node;
1403
+ const majorVersion = parseInt(nodeVersion.split(".")[0], 10);
1404
+ return majorVersion >= 20;
1405
+ }
1406
+ function getVersionInfo() {
1407
+ return `DeeperCode v${DEEPER_VERSION} | Node.js ${process.versions.node} | ${process.platform} ${process.arch}`;
1408
+ }
1409
+
1410
+ // src/cli/commands/chat.tsx
1411
+ import { render } from "ink";
1412
+ import { jsx as jsx12 } from "react/jsx-runtime";
1413
+ async function chat(opts = {}) {
1414
+ const result = await bootstrap();
1415
+ if (!result.success) {
1416
+ for (const err of result.errors) {
1417
+ console.error(`\u274C ${err}`);
1418
+ }
1419
+ process.exit(1);
1420
+ }
1421
+ for (const warn of result.warnings) {
1422
+ console.warn(`\u26A0 ${warn}`);
1423
+ }
1424
+ const model = opts.model || result.config.model;
1425
+ const apiKey = opts.apiKey || result.config.apiKey;
1426
+ const { waitUntilExit } = render(
1427
+ /* @__PURE__ */ jsx12(
1428
+ App,
1429
+ {
1430
+ apiKey,
1431
+ model,
1432
+ verbose: opts.verbose,
1433
+ autoRun: opts.autoRun
1434
+ }
1435
+ )
1436
+ );
1437
+ await waitUntilExit();
1438
+ }
1439
+
1440
+ // src/cli/commands/run.ts
1441
+ async function run(task, opts = {}) {
1442
+ const result = await bootstrap();
1443
+ if (!result.success) {
1444
+ for (const err of result.errors) {
1445
+ console.error(`\u274C ${err}`);
1446
+ }
1447
+ process.exit(1);
1448
+ }
1449
+ if (!task) {
1450
+ console.error('\u274C \u8BF7\u63D0\u4F9B\u4EFB\u52A1\u63CF\u8FF0\u3002\u7528\u6CD5: deeper run "\u4EFB\u52A1\u63CF\u8FF0"');
1451
+ process.exit(1);
1452
+ }
1453
+ const config = opts.model || opts.apiKey ? { ...result.config, ...opts.model ? { model: opts.model } : {}, ...opts.apiKey ? { apiKey: opts.apiKey } : {} } : result.config;
1454
+ if (!config.apiKey && !process.env.DEEPSEEK_API_KEY) {
1455
+ console.error("\u274C \u672A\u8BBE\u7F6E API Key");
1456
+ console.error(" \u8BF7\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF DEEPSEEK_API_KEY \u6216\u4F7F\u7528 --api-key \u53C2\u6570");
1457
+ process.exit(1);
1458
+ }
1459
+ console.log(`
1460
+ \u{1F680} DeeperCode \u6267\u884C\u4EFB\u52A1
1461
+ `);
1462
+ console.log(`\u{1F4CB} \u4EFB\u52A1: ${task}`);
1463
+ console.log(`\u{1F916} \u6A21\u578B: ${config.model}`);
1464
+ console.log(`\u{1F517} API: ${config.baseUrl}`);
1465
+ console.log();
1466
+ console.log("\u23F3 \u6B63\u5728\u8FDE\u63A5 DeepSeek API...");
1467
+ console.log();
1468
+ try {
1469
+ const apiKey = config.apiKey || process.env.DEEPSEEK_API_KEY || "";
1470
+ const response = await fetch(`${config.baseUrl}/v1/chat/completions`, {
1471
+ method: "POST",
1472
+ headers: {
1473
+ "Content-Type": "application/json",
1474
+ "Authorization": `Bearer ${apiKey}`
1475
+ },
1476
+ body: JSON.stringify({
1477
+ model: config.model,
1478
+ messages: [
1479
+ {
1480
+ role: "system",
1481
+ content: "\u4F60\u662F\u4E00\u4E2A\u5F3A\u5927\u7684 AI \u7F16\u7A0B\u52A9\u624B\u3002\u8BF7\u5E2E\u52A9\u7528\u6237\u5B8C\u6210\u4EFB\u52A1\u3002"
1482
+ },
1483
+ {
1484
+ role: "user",
1485
+ content: task
1486
+ }
1487
+ ],
1488
+ stream: true,
1489
+ max_tokens: Math.max(1, Math.min(config.maxTokens || 4096, 131072))
1490
+ })
1491
+ });
1492
+ if (!response.ok) {
1493
+ const text = await response.text();
1494
+ console.error(`\u274C API \u8BF7\u6C42\u5931\u8D25 (${response.status}): ${text}`);
1495
+ process.exit(1);
1496
+ }
1497
+ const reader = response.body?.getReader();
1498
+ if (!reader) {
1499
+ console.error("\u274C \u65E0\u6CD5\u8BFB\u53D6\u54CD\u5E94\u6D41");
1500
+ process.exit(1);
1501
+ }
1502
+ const decoder = new TextDecoder();
1503
+ let buffer = "";
1504
+ let fullContent = "";
1505
+ let thinkingContent = "";
1506
+ console.log("\u{1F4DD} AI \u54CD\u5E94:\n");
1507
+ console.log("\u2500".repeat(60));
1508
+ while (true) {
1509
+ const { done, value } = await reader.read();
1510
+ if (done) break;
1511
+ buffer += decoder.decode(value, { stream: true });
1512
+ const lines = buffer.split("\n");
1513
+ buffer = lines.pop() || "";
1514
+ for (const line of lines) {
1515
+ const trimmed = line.trim();
1516
+ if (!trimmed.startsWith("data: ")) continue;
1517
+ const data = trimmed.slice(6);
1518
+ if (data === "[DONE]") continue;
1519
+ try {
1520
+ const parsed = JSON.parse(data);
1521
+ const delta = parsed.choices?.[0]?.delta;
1522
+ if (delta?.thinking) {
1523
+ thinkingContent += delta.thinking;
1524
+ }
1525
+ if (delta?.content) {
1526
+ fullContent += delta.content;
1527
+ process.stdout.write(delta.content);
1528
+ }
1529
+ } catch {
1530
+ }
1531
+ }
1532
+ }
1533
+ console.log("\n" + "\u2500".repeat(60));
1534
+ console.log();
1535
+ if (thinkingContent) {
1536
+ console.log("\u{1F4AD} \u601D\u8003\u8FC7\u7A0B:");
1537
+ console.log("\u2500".repeat(60));
1538
+ console.log(thinkingContent.slice(0, 500));
1539
+ if (thinkingContent.length > 500) {
1540
+ console.log(`... (\u8FD8\u6709 ${thinkingContent.length - 500} \u5B57\u7B26)`);
1541
+ }
1542
+ console.log("\u2500".repeat(60));
1543
+ }
1544
+ const usage = `\u{1F4CA} Token: ~${fullContent.length} \u8F93\u51FA`;
1545
+ console.log(usage);
1546
+ console.log();
1547
+ console.log("\u2705 \u4EFB\u52A1\u6267\u884C\u5B8C\u6210\uFF01");
1548
+ } catch (e) {
1549
+ const msg = e instanceof Error ? e.message : String(e);
1550
+ console.error(`\u274C \u8BF7\u6C42\u5931\u8D25: ${msg}`);
1551
+ process.exit(1);
1552
+ }
1553
+ }
1554
+ export {
1555
+ AGENT_MAX_SUB_AGENTS,
1556
+ AgentTree,
1557
+ App,
1558
+ CONTEXT_MAX_TOKENS,
1559
+ ChatView,
1560
+ ConfirmDialog,
1561
+ DEEPER_CONFIG_FILE,
1562
+ DEEPER_HOME,
1563
+ DEEPER_NAME,
1564
+ DEEPER_VERSION,
1565
+ DEEPSEEK_BASE_URL,
1566
+ DEEPSEEK_DEFAULT_MODEL,
1567
+ DiffView,
1568
+ EventBusEvents,
1569
+ FilePreview,
1570
+ InputBox,
1571
+ MCP_CONNECTION_TIMEOUT_MS,
1572
+ MessageBubble,
1573
+ SLASH_COMMANDS,
1574
+ Spinner,
1575
+ StatusBar,
1576
+ TOOL_CATEGORIES,
1577
+ TOOL_SAFETY_MAP,
1578
+ ToolCallCard,
1579
+ bootstrap,
1580
+ chat,
1581
+ checkNodeVersion,
1582
+ darkTheme,
1583
+ defaultTheme,
1584
+ eventbus,
1585
+ getApiKey,
1586
+ getBaseUrl,
1587
+ getConfig,
1588
+ getConfigValue,
1589
+ getModel,
1590
+ getVersionInfo,
1591
+ lightTheme,
1592
+ loadConfig,
1593
+ resetConfig,
1594
+ run,
1595
+ saveConfig,
1596
+ setConfigValue,
1597
+ updateConfig
1598
+ };
1599
+ //# sourceMappingURL=index.js.map