gencode-ai 0.1.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 (274) hide show
  1. package/.env.example +11 -0
  2. package/CLAUDE.md +70 -0
  3. package/LICENSE +21 -0
  4. package/README.md +117 -0
  5. package/dist/agent/agent.d.ts +84 -0
  6. package/dist/agent/agent.d.ts.map +1 -0
  7. package/dist/agent/agent.js +233 -0
  8. package/dist/agent/agent.js.map +1 -0
  9. package/dist/agent/index.d.ts +6 -0
  10. package/dist/agent/index.d.ts.map +1 -0
  11. package/dist/agent/index.js +6 -0
  12. package/dist/agent/index.js.map +1 -0
  13. package/dist/agent/types.d.ts +47 -0
  14. package/dist/agent/types.d.ts.map +1 -0
  15. package/dist/agent/types.js +5 -0
  16. package/dist/agent/types.js.map +1 -0
  17. package/dist/cli/components/App.d.ts +14 -0
  18. package/dist/cli/components/App.d.ts.map +1 -0
  19. package/dist/cli/components/App.js +395 -0
  20. package/dist/cli/components/App.js.map +1 -0
  21. package/dist/cli/components/CommandSuggestions.d.ts +13 -0
  22. package/dist/cli/components/CommandSuggestions.d.ts.map +1 -0
  23. package/dist/cli/components/CommandSuggestions.js +32 -0
  24. package/dist/cli/components/CommandSuggestions.js.map +1 -0
  25. package/dist/cli/components/Header.d.ts +9 -0
  26. package/dist/cli/components/Header.d.ts.map +1 -0
  27. package/dist/cli/components/Header.js +13 -0
  28. package/dist/cli/components/Header.js.map +1 -0
  29. package/dist/cli/components/Input.d.ts +13 -0
  30. package/dist/cli/components/Input.d.ts.map +1 -0
  31. package/dist/cli/components/Input.js +27 -0
  32. package/dist/cli/components/Input.js.map +1 -0
  33. package/dist/cli/components/Logo.d.ts +2 -0
  34. package/dist/cli/components/Logo.d.ts.map +1 -0
  35. package/dist/cli/components/Logo.js +8 -0
  36. package/dist/cli/components/Logo.js.map +1 -0
  37. package/dist/cli/components/Messages.d.ts +37 -0
  38. package/dist/cli/components/Messages.d.ts.map +1 -0
  39. package/dist/cli/components/Messages.js +106 -0
  40. package/dist/cli/components/Messages.js.map +1 -0
  41. package/dist/cli/components/ModelSelector.d.ts +13 -0
  42. package/dist/cli/components/ModelSelector.d.ts.map +1 -0
  43. package/dist/cli/components/ModelSelector.js +72 -0
  44. package/dist/cli/components/ModelSelector.js.map +1 -0
  45. package/dist/cli/components/Spinner.d.ts +12 -0
  46. package/dist/cli/components/Spinner.d.ts.map +1 -0
  47. package/dist/cli/components/Spinner.js +45 -0
  48. package/dist/cli/components/Spinner.js.map +1 -0
  49. package/dist/cli/components/index.d.ts +12 -0
  50. package/dist/cli/components/index.d.ts.map +1 -0
  51. package/dist/cli/components/index.js +12 -0
  52. package/dist/cli/components/index.js.map +1 -0
  53. package/dist/cli/components/theme.d.ts +31 -0
  54. package/dist/cli/components/theme.d.ts.map +1 -0
  55. package/dist/cli/components/theme.js +36 -0
  56. package/dist/cli/components/theme.js.map +1 -0
  57. package/dist/cli/index-legacy.d.ts +7 -0
  58. package/dist/cli/index-legacy.d.ts.map +1 -0
  59. package/dist/cli/index-legacy.js +431 -0
  60. package/dist/cli/index-legacy.js.map +1 -0
  61. package/dist/cli/index.d.ts +7 -0
  62. package/dist/cli/index.d.ts.map +1 -0
  63. package/dist/cli/index.js +116 -0
  64. package/dist/cli/index.js.map +1 -0
  65. package/dist/cli/ink-cli.d.ts +7 -0
  66. package/dist/cli/ink-cli.d.ts.map +1 -0
  67. package/dist/cli/ink-cli.js +105 -0
  68. package/dist/cli/ink-cli.js.map +1 -0
  69. package/dist/cli/session-picker.d.ts +16 -0
  70. package/dist/cli/session-picker.d.ts.map +1 -0
  71. package/dist/cli/session-picker.js +280 -0
  72. package/dist/cli/session-picker.js.map +1 -0
  73. package/dist/cli/ui.d.ts +61 -0
  74. package/dist/cli/ui.d.ts.map +1 -0
  75. package/dist/cli/ui.js +364 -0
  76. package/dist/cli/ui.js.map +1 -0
  77. package/dist/config/index.d.ts +7 -0
  78. package/dist/config/index.d.ts.map +1 -0
  79. package/dist/config/index.js +6 -0
  80. package/dist/config/index.js.map +1 -0
  81. package/dist/config/manager.d.ts +31 -0
  82. package/dist/config/manager.d.ts.map +1 -0
  83. package/dist/config/manager.js +65 -0
  84. package/dist/config/manager.js.map +1 -0
  85. package/dist/config/types.d.ts +22 -0
  86. package/dist/config/types.d.ts.map +1 -0
  87. package/dist/config/types.js +6 -0
  88. package/dist/config/types.js.map +1 -0
  89. package/dist/index.d.ts +12 -0
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +21 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/memory/index.d.ts +10 -0
  94. package/dist/memory/index.d.ts.map +1 -0
  95. package/dist/memory/index.js +9 -0
  96. package/dist/memory/index.js.map +1 -0
  97. package/dist/memory/init.d.ts +20 -0
  98. package/dist/memory/init.d.ts.map +1 -0
  99. package/dist/memory/init.js +332 -0
  100. package/dist/memory/init.js.map +1 -0
  101. package/dist/memory/manager.d.ts +85 -0
  102. package/dist/memory/manager.d.ts.map +1 -0
  103. package/dist/memory/manager.js +234 -0
  104. package/dist/memory/manager.js.map +1 -0
  105. package/dist/memory/types.d.ts +74 -0
  106. package/dist/memory/types.d.ts.map +1 -0
  107. package/dist/memory/types.js +6 -0
  108. package/dist/memory/types.js.map +1 -0
  109. package/dist/permissions/index.d.ts +7 -0
  110. package/dist/permissions/index.d.ts.map +1 -0
  111. package/dist/permissions/index.js +6 -0
  112. package/dist/permissions/index.js.map +1 -0
  113. package/dist/permissions/manager.d.ts +32 -0
  114. package/dist/permissions/manager.d.ts.map +1 -0
  115. package/dist/permissions/manager.js +79 -0
  116. package/dist/permissions/manager.js.map +1 -0
  117. package/dist/permissions/types.d.ts +14 -0
  118. package/dist/permissions/types.d.ts.map +1 -0
  119. package/dist/permissions/types.js +17 -0
  120. package/dist/permissions/types.js.map +1 -0
  121. package/dist/providers/anthropic.d.ts +20 -0
  122. package/dist/providers/anthropic.d.ts.map +1 -0
  123. package/dist/providers/anthropic.js +185 -0
  124. package/dist/providers/anthropic.js.map +1 -0
  125. package/dist/providers/gemini.d.ts +21 -0
  126. package/dist/providers/gemini.d.ts.map +1 -0
  127. package/dist/providers/gemini.js +241 -0
  128. package/dist/providers/gemini.js.map +1 -0
  129. package/dist/providers/index.d.ts +34 -0
  130. package/dist/providers/index.d.ts.map +1 -0
  131. package/dist/providers/index.js +72 -0
  132. package/dist/providers/index.js.map +1 -0
  133. package/dist/providers/openai.d.ts +19 -0
  134. package/dist/providers/openai.d.ts.map +1 -0
  135. package/dist/providers/openai.js +221 -0
  136. package/dist/providers/openai.js.map +1 -0
  137. package/dist/providers/types.d.ts +125 -0
  138. package/dist/providers/types.d.ts.map +1 -0
  139. package/dist/providers/types.js +6 -0
  140. package/dist/providers/types.js.map +1 -0
  141. package/dist/session/index.d.ts +6 -0
  142. package/dist/session/index.d.ts.map +1 -0
  143. package/dist/session/index.js +6 -0
  144. package/dist/session/index.js.map +1 -0
  145. package/dist/session/manager.d.ts +101 -0
  146. package/dist/session/manager.d.ts.map +1 -0
  147. package/dist/session/manager.js +295 -0
  148. package/dist/session/manager.js.map +1 -0
  149. package/dist/session/types.d.ts +39 -0
  150. package/dist/session/types.d.ts.map +1 -0
  151. package/dist/session/types.js +10 -0
  152. package/dist/session/types.js.map +1 -0
  153. package/dist/tools/builtin/bash.d.ts +7 -0
  154. package/dist/tools/builtin/bash.d.ts.map +1 -0
  155. package/dist/tools/builtin/bash.js +80 -0
  156. package/dist/tools/builtin/bash.js.map +1 -0
  157. package/dist/tools/builtin/edit.d.ts +7 -0
  158. package/dist/tools/builtin/edit.d.ts.map +1 -0
  159. package/dist/tools/builtin/edit.js +32 -0
  160. package/dist/tools/builtin/edit.js.map +1 -0
  161. package/dist/tools/builtin/glob.d.ts +7 -0
  162. package/dist/tools/builtin/glob.d.ts.map +1 -0
  163. package/dist/tools/builtin/glob.js +36 -0
  164. package/dist/tools/builtin/glob.js.map +1 -0
  165. package/dist/tools/builtin/grep.d.ts +7 -0
  166. package/dist/tools/builtin/grep.d.ts.map +1 -0
  167. package/dist/tools/builtin/grep.js +59 -0
  168. package/dist/tools/builtin/grep.js.map +1 -0
  169. package/dist/tools/builtin/read.d.ts +7 -0
  170. package/dist/tools/builtin/read.d.ts.map +1 -0
  171. package/dist/tools/builtin/read.js +29 -0
  172. package/dist/tools/builtin/read.js.map +1 -0
  173. package/dist/tools/builtin/write.d.ts +7 -0
  174. package/dist/tools/builtin/write.d.ts.map +1 -0
  175. package/dist/tools/builtin/write.js +24 -0
  176. package/dist/tools/builtin/write.js.map +1 -0
  177. package/dist/tools/index.d.ts +38 -0
  178. package/dist/tools/index.d.ts.map +1 -0
  179. package/dist/tools/index.js +32 -0
  180. package/dist/tools/index.js.map +1 -0
  181. package/dist/tools/registry.d.ts +22 -0
  182. package/dist/tools/registry.d.ts.map +1 -0
  183. package/dist/tools/registry.js +71 -0
  184. package/dist/tools/registry.js.map +1 -0
  185. package/dist/tools/types.d.ts +62 -0
  186. package/dist/tools/types.d.ts.map +1 -0
  187. package/dist/tools/types.js +126 -0
  188. package/dist/tools/types.js.map +1 -0
  189. package/docs/README.md +16 -0
  190. package/docs/proposals/0001-web-fetch-tool.md +293 -0
  191. package/docs/proposals/0002-web-search-tool.md +306 -0
  192. package/docs/proposals/0003-task-subagents.md +333 -0
  193. package/docs/proposals/0004-plan-mode.md +338 -0
  194. package/docs/proposals/0005-todo-system.md +299 -0
  195. package/docs/proposals/0006-memory-system.md +539 -0
  196. package/docs/proposals/0007-context-management.md +429 -0
  197. package/docs/proposals/0008-checkpointing.md +327 -0
  198. package/docs/proposals/0009-hooks-system.md +343 -0
  199. package/docs/proposals/0010-mcp-integration.md +382 -0
  200. package/docs/proposals/0011-custom-commands.md +374 -0
  201. package/docs/proposals/0012-ask-user-question.md +317 -0
  202. package/docs/proposals/0013-multi-edit-tool.md +345 -0
  203. package/docs/proposals/0014-lsp-tool.md +478 -0
  204. package/docs/proposals/0015-ls-tool.md +407 -0
  205. package/docs/proposals/0016-kill-shell-tool.md +455 -0
  206. package/docs/proposals/0017-background-tasks.md +489 -0
  207. package/docs/proposals/0018-parallel-tool-execution.md +415 -0
  208. package/docs/proposals/0019-session-enhancements.md +462 -0
  209. package/docs/proposals/0020-session-summarization.md +447 -0
  210. package/docs/proposals/0021-skills-system.md +409 -0
  211. package/docs/proposals/0022-plugin-system.md +467 -0
  212. package/docs/proposals/0023-permission-enhancements.md +470 -0
  213. package/docs/proposals/0024-keyboard-shortcuts.md +443 -0
  214. package/docs/proposals/0025-cost-tracking.md +447 -0
  215. package/docs/proposals/0026-git-integration.md +475 -0
  216. package/docs/proposals/0027-enhanced-read-tool.md +514 -0
  217. package/docs/proposals/0028-enhanced-bash-tool.md +511 -0
  218. package/docs/proposals/0029-notebook-edit-tool.md +413 -0
  219. package/docs/proposals/0030-plugin-marketplace.md +360 -0
  220. package/docs/proposals/0031-command-suggestions.md +295 -0
  221. package/docs/proposals/0032-ide-integrations.md +328 -0
  222. package/docs/proposals/0033-enterprise-deployment.md +221 -0
  223. package/docs/proposals/0034-sandboxing.md +273 -0
  224. package/docs/proposals/0035-auto-updater.md +311 -0
  225. package/docs/proposals/0036-enhanced-glob-tool.md +267 -0
  226. package/docs/proposals/0037-enhanced-grep-tool.md +360 -0
  227. package/docs/proposals/0038-interactive-cli-ui.md +373 -0
  228. package/docs/proposals/0039-streaming-enhancements.md +359 -0
  229. package/docs/proposals/0040-multi-provider-enhancements.md +369 -0
  230. package/docs/proposals/README.md +84 -0
  231. package/docs/proposals/TEMPLATE.md +57 -0
  232. package/docs/proposals/research/claude-code-research.md +307 -0
  233. package/examples/agent-demo.ts +115 -0
  234. package/examples/basic.ts +166 -0
  235. package/package.json +50 -0
  236. package/src/agent/agent.ts +276 -0
  237. package/src/agent/index.ts +6 -0
  238. package/src/agent/types.ts +62 -0
  239. package/src/cli/components/App.tsx +565 -0
  240. package/src/cli/components/CommandSuggestions.tsx +58 -0
  241. package/src/cli/components/Header.tsx +36 -0
  242. package/src/cli/components/Input.tsx +60 -0
  243. package/src/cli/components/Logo.tsx +16 -0
  244. package/src/cli/components/Messages.tsx +210 -0
  245. package/src/cli/components/ModelSelector.tsx +135 -0
  246. package/src/cli/components/Spinner.tsx +72 -0
  247. package/src/cli/components/index.ts +21 -0
  248. package/src/cli/components/theme.ts +36 -0
  249. package/src/cli/index.tsx +136 -0
  250. package/src/config/index.ts +7 -0
  251. package/src/config/manager.ts +77 -0
  252. package/src/config/types.ts +25 -0
  253. package/src/index.ts +86 -0
  254. package/src/permissions/index.ts +7 -0
  255. package/src/permissions/manager.ts +97 -0
  256. package/src/permissions/types.ts +29 -0
  257. package/src/providers/anthropic.ts +224 -0
  258. package/src/providers/gemini.ts +295 -0
  259. package/src/providers/index.ts +97 -0
  260. package/src/providers/openai.ts +261 -0
  261. package/src/providers/types.ts +181 -0
  262. package/src/session/index.ts +6 -0
  263. package/src/session/manager.ts +354 -0
  264. package/src/session/types.ts +49 -0
  265. package/src/tools/builtin/bash.ts +92 -0
  266. package/src/tools/builtin/edit.ts +37 -0
  267. package/src/tools/builtin/glob.ts +42 -0
  268. package/src/tools/builtin/grep.ts +67 -0
  269. package/src/tools/builtin/read.ts +34 -0
  270. package/src/tools/builtin/write.ts +27 -0
  271. package/src/tools/index.ts +36 -0
  272. package/src/tools/registry.ts +83 -0
  273. package/src/tools/types.ts +172 -0
  274. package/tsconfig.json +21 -0
@@ -0,0 +1,415 @@
1
+ # Proposal: Parallel Tool Execution
2
+
3
+ - **Proposal ID**: 0018
4
+ - **Author**: mycode team
5
+ - **Status**: Draft
6
+ - **Created**: 2025-01-15
7
+ - **Updated**: 2025-01-15
8
+
9
+ ## Summary
10
+
11
+ Implement parallel tool execution to allow multiple independent tool calls to run concurrently within a single agent turn. This reduces latency and improves efficiency when the agent needs to perform multiple non-dependent operations.
12
+
13
+ ## Motivation
14
+
15
+ Currently, mycode executes tools sequentially, one after another:
16
+
17
+ 1. **High latency**: 3 file reads take 3x the time
18
+ 2. **Wasted time**: Network requests wait for each other
19
+ 3. **Poor utilization**: CPU/IO idle between calls
20
+ 4. **Slow exploration**: Searching multiple directories is slow
21
+ 5. **Suboptimal UX**: User waits longer than necessary
22
+
23
+ Parallel execution enables concurrent tool operations for faster results.
24
+
25
+ ## Claude Code Reference
26
+
27
+ Claude Code supports parallel tool calls natively:
28
+
29
+ ### From System Prompt
30
+ ```
31
+ You can call multiple tools in a single response. When multiple independent
32
+ pieces of information are requested and all commands are likely to succeed,
33
+ run multiple tool calls in parallel for optimal performance.
34
+
35
+ However, if some tool calls depend on previous calls to inform dependent
36
+ values, do NOT call these tools in parallel and instead call them sequentially.
37
+ ```
38
+
39
+ ### Parallel Call Example
40
+ Multiple tool calls in single response:
41
+ ```
42
+ Agent: I'll read both configuration files to understand the setup.
43
+ [Read: src/config.ts]
44
+ [Read: src/settings.json]
45
+ [Glob: **/*.test.ts]
46
+ ```
47
+
48
+ All three execute concurrently, results return together.
49
+
50
+ ### Key Rules
51
+ - Independent calls: Run in parallel
52
+ - Dependent calls: Run sequentially
53
+ - Never use placeholders for dependent values
54
+ - Agent decides based on data dependencies
55
+
56
+ ## Detailed Design
57
+
58
+ ### API Design
59
+
60
+ ```typescript
61
+ // src/agent/parallel-executor.ts
62
+ interface ToolCall {
63
+ id: string;
64
+ name: string;
65
+ input: unknown;
66
+ }
67
+
68
+ interface ToolResult {
69
+ id: string;
70
+ name: string;
71
+ success: boolean;
72
+ output: string;
73
+ error?: string;
74
+ duration_ms: number;
75
+ }
76
+
77
+ interface ParallelExecutionConfig {
78
+ max_concurrent: number; // Max concurrent executions
79
+ timeout_per_tool: number; // Per-tool timeout
80
+ fail_fast: boolean; // Stop on first error
81
+ retry_failed: boolean; // Retry failed tools once
82
+ }
83
+
84
+ const DEFAULT_CONFIG: ParallelExecutionConfig = {
85
+ max_concurrent: 10,
86
+ timeout_per_tool: 30000,
87
+ fail_fast: false,
88
+ retry_failed: false
89
+ };
90
+ ```
91
+
92
+ ### Implementation Approach
93
+
94
+ ```typescript
95
+ // src/agent/parallel-executor.ts
96
+ class ParallelToolExecutor {
97
+ private registry: ToolRegistry;
98
+ private config: ParallelExecutionConfig;
99
+ private semaphore: Semaphore;
100
+
101
+ constructor(registry: ToolRegistry, config?: Partial<ParallelExecutionConfig>) {
102
+ this.registry = registry;
103
+ this.config = { ...DEFAULT_CONFIG, ...config };
104
+ this.semaphore = new Semaphore(this.config.max_concurrent);
105
+ }
106
+
107
+ async executeParallel(
108
+ calls: ToolCall[],
109
+ context: ToolContext
110
+ ): Promise<ToolResult[]> {
111
+ const results: ToolResult[] = [];
112
+
113
+ // Execute all calls concurrently with semaphore
114
+ const promises = calls.map(call =>
115
+ this.executeWithSemaphore(call, context)
116
+ );
117
+
118
+ // Wait for all (unless fail_fast)
119
+ if (this.config.fail_fast) {
120
+ const settled = await Promise.allSettled(promises);
121
+ for (const result of settled) {
122
+ if (result.status === 'fulfilled') {
123
+ results.push(result.value);
124
+ if (!result.value.success) break;
125
+ }
126
+ }
127
+ } else {
128
+ const allResults = await Promise.all(promises);
129
+ results.push(...allResults);
130
+ }
131
+
132
+ return results;
133
+ }
134
+
135
+ private async executeWithSemaphore(
136
+ call: ToolCall,
137
+ context: ToolContext
138
+ ): Promise<ToolResult> {
139
+ await this.semaphore.acquire();
140
+
141
+ try {
142
+ return await this.executeSingle(call, context);
143
+ } finally {
144
+ this.semaphore.release();
145
+ }
146
+ }
147
+
148
+ private async executeSingle(
149
+ call: ToolCall,
150
+ context: ToolContext
151
+ ): Promise<ToolResult> {
152
+ const start = Date.now();
153
+
154
+ try {
155
+ // Wrap with timeout
156
+ const result = await Promise.race([
157
+ this.registry.execute(call.name, call.input, context),
158
+ this.timeout(this.config.timeout_per_tool)
159
+ ]);
160
+
161
+ return {
162
+ id: call.id,
163
+ name: call.name,
164
+ success: result.success,
165
+ output: result.output || '',
166
+ error: result.error,
167
+ duration_ms: Date.now() - start
168
+ };
169
+ } catch (error) {
170
+ return {
171
+ id: call.id,
172
+ name: call.name,
173
+ success: false,
174
+ output: '',
175
+ error: error instanceof Error ? error.message : 'Unknown error',
176
+ duration_ms: Date.now() - start
177
+ };
178
+ }
179
+ }
180
+
181
+ private timeout(ms: number): Promise<never> {
182
+ return new Promise((_, reject) =>
183
+ setTimeout(() => reject(new Error('Tool execution timeout')), ms)
184
+ );
185
+ }
186
+ }
187
+ ```
188
+
189
+ ### Agent Loop Integration
190
+
191
+ ```typescript
192
+ // Updated src/agent/agent.ts
193
+ class Agent {
194
+ private parallelExecutor: ParallelToolExecutor;
195
+
196
+ async *run(messages: Message[]): AsyncGenerator<AgentEvent> {
197
+ while (true) {
198
+ const response = await this.provider.complete({
199
+ messages,
200
+ tools: this.registry.getToolDefinitions()
201
+ });
202
+
203
+ // Yield text content
204
+ for (const block of response.content) {
205
+ if (block.type === 'text') {
206
+ yield { type: 'text', content: block.text };
207
+ }
208
+ }
209
+
210
+ // Check for tool calls
211
+ const toolCalls = response.content.filter(b => b.type === 'tool_use');
212
+
213
+ if (toolCalls.length === 0) {
214
+ yield { type: 'done', reason: response.stopReason };
215
+ return;
216
+ }
217
+
218
+ // Execute tools in parallel
219
+ yield { type: 'tools_start', count: toolCalls.length };
220
+
221
+ const results = await this.parallelExecutor.executeParallel(
222
+ toolCalls.map(tc => ({
223
+ id: tc.id,
224
+ name: tc.name,
225
+ input: tc.input
226
+ })),
227
+ { cwd: this.cwd, signal: this.signal }
228
+ );
229
+
230
+ // Yield individual results
231
+ for (const result of results) {
232
+ yield {
233
+ type: 'tool_result',
234
+ id: result.id,
235
+ name: result.name,
236
+ success: result.success,
237
+ output: result.output,
238
+ duration_ms: result.duration_ms
239
+ };
240
+ }
241
+
242
+ // Add results to messages
243
+ messages.push({
244
+ role: 'assistant',
245
+ content: response.content
246
+ });
247
+ messages.push({
248
+ role: 'user',
249
+ content: results.map(r => ({
250
+ type: 'tool_result',
251
+ tool_use_id: r.id,
252
+ content: r.success ? r.output : `Error: ${r.error}`
253
+ }))
254
+ });
255
+ }
256
+ }
257
+ }
258
+ ```
259
+
260
+ ### Semaphore Implementation
261
+
262
+ ```typescript
263
+ // src/utils/semaphore.ts
264
+ class Semaphore {
265
+ private permits: number;
266
+ private waiting: (() => void)[] = [];
267
+
268
+ constructor(permits: number) {
269
+ this.permits = permits;
270
+ }
271
+
272
+ async acquire(): Promise<void> {
273
+ if (this.permits > 0) {
274
+ this.permits--;
275
+ return;
276
+ }
277
+
278
+ return new Promise(resolve => {
279
+ this.waiting.push(resolve);
280
+ });
281
+ }
282
+
283
+ release(): void {
284
+ if (this.waiting.length > 0) {
285
+ const next = this.waiting.shift()!;
286
+ next();
287
+ } else {
288
+ this.permits++;
289
+ }
290
+ }
291
+ }
292
+ ```
293
+
294
+ ### File Changes
295
+
296
+ | File | Action | Description |
297
+ |------|--------|-------------|
298
+ | `src/agent/parallel-executor.ts` | Create | Parallel execution engine |
299
+ | `src/agent/agent.ts` | Modify | Integrate parallel execution |
300
+ | `src/utils/semaphore.ts` | Create | Concurrency control |
301
+ | `src/agent/types.ts` | Modify | Add parallel-related events |
302
+
303
+ ## User Experience
304
+
305
+ ### Parallel Execution Display
306
+ ```
307
+ Agent: I'll check multiple files to understand the project structure.
308
+
309
+ ┌─ Parallel Tool Execution (4 calls) ───────────────┐
310
+ │ [1/4] Read: src/index.ts ✓ (45ms) │
311
+ │ [2/4] Read: package.json ✓ (32ms) │
312
+ │ [3/4] Glob: src/**/*.ts ✓ (78ms) │
313
+ │ [4/4] Grep: "TODO" ✓ (156ms) │
314
+ ├───────────────────────────────────────────────────┤
315
+ │ Total: 4/4 succeeded in 156ms (parallel) │
316
+ │ Sequential would have taken: 311ms │
317
+ └───────────────────────────────────────────────────┘
318
+ ```
319
+
320
+ ### Mixed Results
321
+ ```
322
+ ┌─ Parallel Tool Execution (3 calls) ───────────────┐
323
+ │ [1/3] Read: src/config.ts ✓ (38ms) │
324
+ │ [2/3] Read: missing.ts ✗ (12ms) │
325
+ │ Error: File not found │
326
+ │ [3/3] Bash: npm --version ✓ (234ms) │
327
+ ├───────────────────────────────────────────────────┤
328
+ │ Total: 2/3 succeeded, 1 failed │
329
+ └───────────────────────────────────────────────────┘
330
+ ```
331
+
332
+ ### Sequential Fallback
333
+ ```
334
+ Agent: These operations depend on each other, so I'll run them sequentially.
335
+
336
+ [Read: package.json]
337
+ → Found dependencies list
338
+
339
+ [Bash: npm install lodash]
340
+ → Using package info from previous read
341
+ ```
342
+
343
+ ## Alternatives Considered
344
+
345
+ ### Alternative 1: Always Sequential
346
+ Keep current sequential behavior.
347
+
348
+ **Pros**: Simpler, predictable
349
+ **Cons**: Slow, wastes time
350
+ **Decision**: Rejected - Performance is important
351
+
352
+ ### Alternative 2: Unlimited Parallelism
353
+ No concurrency limits.
354
+
355
+ **Pros**: Maximum speed
356
+ **Cons**: Resource exhaustion, rate limiting
357
+ **Decision**: Rejected - Need semaphore control
358
+
359
+ ### Alternative 3: Provider-Side Parallelism
360
+ Let LLM provider handle parallel calls.
361
+
362
+ **Pros**: Simpler client
363
+ **Cons**: Not all providers support it
364
+ **Decision**: Rejected - Need client-side control
365
+
366
+ ## Security Considerations
367
+
368
+ 1. **Resource Limits**: Cap concurrent operations
369
+ 2. **Timeout Enforcement**: Per-tool and total timeouts
370
+ 3. **Memory Management**: Stream large outputs
371
+ 4. **Rate Limiting**: Respect external API limits
372
+ 5. **Cancellation**: Support AbortSignal propagation
373
+
374
+ ```typescript
375
+ const SAFETY_LIMITS = {
376
+ maxConcurrent: 10,
377
+ maxTotalCalls: 50,
378
+ perToolTimeout: 30000,
379
+ totalTimeout: 120000
380
+ };
381
+ ```
382
+
383
+ ## Testing Strategy
384
+
385
+ 1. **Unit Tests**:
386
+ - Semaphore behavior
387
+ - Parallel vs sequential timing
388
+ - Error handling
389
+ - Timeout enforcement
390
+
391
+ 2. **Integration Tests**:
392
+ - Multiple tool types
393
+ - Mixed success/failure
394
+ - Resource cleanup
395
+
396
+ 3. **Performance Tests**:
397
+ - Speedup measurement
398
+ - Memory usage
399
+ - Concurrent limits
400
+
401
+ ## Migration Path
402
+
403
+ 1. **Phase 1**: ParallelToolExecutor with semaphore
404
+ 2. **Phase 2**: Agent loop integration
405
+ 3. **Phase 3**: CLI display updates
406
+ 4. **Phase 4**: Configuration options
407
+ 5. **Phase 5**: Performance telemetry
408
+
409
+ No breaking changes - sequential behavior preserved as default.
410
+
411
+ ## References
412
+
413
+ - [Promise.all() - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all)
414
+ - [Semaphore Pattern](https://en.wikipedia.org/wiki/Semaphore_(programming))
415
+ - [Claude Code Tool Calling](https://code.claude.com/docs/en/tools)