@ddse/acm-aicoder 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.aicoder/index.json +304 -0
- package/AICODER_IMPLEMENTATION_PLAN_PHASE2.md +284 -0
- package/LICENSE +21 -0
- package/README.md +490 -0
- package/bin/interactive.tsx +232 -0
- package/dist/bin/interactive.d.ts +3 -0
- package/dist/bin/interactive.d.ts.map +1 -0
- package/dist/bin/interactive.js +155 -0
- package/dist/bin/interactive.js.map +1 -0
- package/dist/src/config/providers.d.ts +15 -0
- package/dist/src/config/providers.d.ts.map +1 -0
- package/dist/src/config/providers.js +142 -0
- package/dist/src/config/providers.js.map +1 -0
- package/dist/src/config/session.d.ts +25 -0
- package/dist/src/config/session.d.ts.map +1 -0
- package/dist/src/config/session.js +97 -0
- package/dist/src/config/session.js.map +1 -0
- package/dist/src/context/bm25.d.ts +68 -0
- package/dist/src/context/bm25.d.ts.map +1 -0
- package/dist/src/context/bm25.js +131 -0
- package/dist/src/context/bm25.js.map +1 -0
- package/dist/src/context/code-search.d.ts +30 -0
- package/dist/src/context/code-search.d.ts.map +1 -0
- package/dist/src/context/code-search.js +150 -0
- package/dist/src/context/code-search.js.map +1 -0
- package/dist/src/context/context-pack.d.ts +25 -0
- package/dist/src/context/context-pack.d.ts.map +1 -0
- package/dist/src/context/context-pack.js +92 -0
- package/dist/src/context/context-pack.js.map +1 -0
- package/dist/src/context/dependency-mapper.d.ts +10 -0
- package/dist/src/context/dependency-mapper.d.ts.map +1 -0
- package/dist/src/context/dependency-mapper.js +62 -0
- package/dist/src/context/dependency-mapper.js.map +1 -0
- package/dist/src/context/index.d.ts +8 -0
- package/dist/src/context/index.d.ts.map +1 -0
- package/dist/src/context/index.js +9 -0
- package/dist/src/context/index.js.map +1 -0
- package/dist/src/context/symbol-extractor.d.ts +26 -0
- package/dist/src/context/symbol-extractor.d.ts.map +1 -0
- package/dist/src/context/symbol-extractor.js +129 -0
- package/dist/src/context/symbol-extractor.js.map +1 -0
- package/dist/src/context/test-mapper.d.ts +16 -0
- package/dist/src/context/test-mapper.d.ts.map +1 -0
- package/dist/src/context/test-mapper.js +66 -0
- package/dist/src/context/test-mapper.js.map +1 -0
- package/dist/src/context/types.d.ts +61 -0
- package/dist/src/context/types.d.ts.map +1 -0
- package/dist/src/context/types.js +3 -0
- package/dist/src/context/types.js.map +1 -0
- package/dist/src/context/workspace-indexer.d.ts +39 -0
- package/dist/src/context/workspace-indexer.d.ts.map +1 -0
- package/dist/src/context/workspace-indexer.js +222 -0
- package/dist/src/context/workspace-indexer.js.map +1 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/registries.d.ts +34 -0
- package/dist/src/registries.d.ts.map +1 -0
- package/dist/src/registries.js +87 -0
- package/dist/src/registries.js.map +1 -0
- package/dist/src/runtime/budget-manager.d.ts +42 -0
- package/dist/src/runtime/budget-manager.d.ts.map +1 -0
- package/dist/src/runtime/budget-manager.js +82 -0
- package/dist/src/runtime/budget-manager.js.map +1 -0
- package/dist/src/runtime/interactive-runtime.d.ts +39 -0
- package/dist/src/runtime/interactive-runtime.d.ts.map +1 -0
- package/dist/src/runtime/interactive-runtime.js +321 -0
- package/dist/src/runtime/interactive-runtime.js.map +1 -0
- package/dist/src/tasks-v2/analysis-tasks.d.ts +117 -0
- package/dist/src/tasks-v2/analysis-tasks.d.ts.map +1 -0
- package/dist/src/tasks-v2/analysis-tasks.js +209 -0
- package/dist/src/tasks-v2/analysis-tasks.js.map +1 -0
- package/dist/src/tasks-v2/developer-tasks.d.ts +226 -0
- package/dist/src/tasks-v2/developer-tasks.d.ts.map +1 -0
- package/dist/src/tasks-v2/developer-tasks.js +322 -0
- package/dist/src/tasks-v2/developer-tasks.js.map +1 -0
- package/dist/src/tasks-v2/index.d.ts +3 -0
- package/dist/src/tasks-v2/index.d.ts.map +1 -0
- package/dist/src/tasks-v2/index.js +4 -0
- package/dist/src/tasks-v2/index.js.map +1 -0
- package/dist/src/tools-v2/edit-tools.d.ts +67 -0
- package/dist/src/tools-v2/edit-tools.d.ts.map +1 -0
- package/dist/src/tools-v2/edit-tools.js +117 -0
- package/dist/src/tools-v2/edit-tools.js.map +1 -0
- package/dist/src/tools-v2/index.d.ts +6 -0
- package/dist/src/tools-v2/index.d.ts.map +1 -0
- package/dist/src/tools-v2/index.js +7 -0
- package/dist/src/tools-v2/index.js.map +1 -0
- package/dist/src/tools-v2/read-tools.d.ts +129 -0
- package/dist/src/tools-v2/read-tools.d.ts.map +1 -0
- package/dist/src/tools-v2/read-tools.js +216 -0
- package/dist/src/tools-v2/read-tools.js.map +1 -0
- package/dist/src/tools-v2/search-tools.d.ts +73 -0
- package/dist/src/tools-v2/search-tools.d.ts.map +1 -0
- package/dist/src/tools-v2/search-tools.js +132 -0
- package/dist/src/tools-v2/search-tools.js.map +1 -0
- package/dist/src/tools-v2/test-tools.d.ts +59 -0
- package/dist/src/tools-v2/test-tools.d.ts.map +1 -0
- package/dist/src/tools-v2/test-tools.js +111 -0
- package/dist/src/tools-v2/test-tools.js.map +1 -0
- package/dist/src/tools-v2/workspace-context.d.ts +65 -0
- package/dist/src/tools-v2/workspace-context.d.ts.map +1 -0
- package/dist/src/tools-v2/workspace-context.js +336 -0
- package/dist/src/tools-v2/workspace-context.js.map +1 -0
- package/dist/src/ui/App.d.ts +9 -0
- package/dist/src/ui/App.d.ts.map +1 -0
- package/dist/src/ui/App.js +257 -0
- package/dist/src/ui/App.js.map +1 -0
- package/dist/src/ui/components/ChatPane.d.ts +12 -0
- package/dist/src/ui/components/ChatPane.d.ts.map +1 -0
- package/dist/src/ui/components/ChatPane.js +41 -0
- package/dist/src/ui/components/ChatPane.js.map +1 -0
- package/dist/src/ui/components/EventsPane.d.ts +12 -0
- package/dist/src/ui/components/EventsPane.d.ts.map +1 -0
- package/dist/src/ui/components/EventsPane.js +48 -0
- package/dist/src/ui/components/EventsPane.js.map +1 -0
- package/dist/src/ui/components/GoalsTasksPane.d.ts +18 -0
- package/dist/src/ui/components/GoalsTasksPane.d.ts.map +1 -0
- package/dist/src/ui/components/GoalsTasksPane.js +83 -0
- package/dist/src/ui/components/GoalsTasksPane.js.map +1 -0
- package/dist/src/ui/store.d.ts +74 -0
- package/dist/src/ui/store.d.ts.map +1 -0
- package/dist/src/ui/store.js +260 -0
- package/dist/src/ui/store.js.map +1 -0
- package/dist/tests/integration.test.d.ts +2 -0
- package/dist/tests/integration.test.d.ts.map +1 -0
- package/dist/tests/integration.test.js +415 -0
- package/dist/tests/integration.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/docs/AICODER.png +0 -0
- package/docs/INTERACTIVE_CLI_GUIDE.md +201 -0
- package/docs/TUI_MOCKUP.md +180 -0
- package/package.json +52 -0
- package/src/config/providers.ts +174 -0
- package/src/config/session.ts +143 -0
- package/src/context/bm25.ts +173 -0
- package/src/context/code-search.ts +188 -0
- package/src/context/context-pack.ts +133 -0
- package/src/context/dependency-mapper.ts +72 -0
- package/src/context/index.ts +8 -0
- package/src/context/symbol-extractor.ts +149 -0
- package/src/context/test-mapper.ts +77 -0
- package/src/context/types.ts +69 -0
- package/src/context/workspace-indexer.ts +249 -0
- package/src/index.ts +5 -0
- package/src/registries.ts +118 -0
- package/src/runtime/budget-manager.ts +118 -0
- package/src/runtime/interactive-runtime.ts +423 -0
- package/src/tasks-v2/analysis-tasks.ts +311 -0
- package/src/tasks-v2/developer-tasks.ts +437 -0
- package/src/tasks-v2/index.ts +3 -0
- package/src/tools-v2/edit-tools.ts +153 -0
- package/src/tools-v2/index.ts +6 -0
- package/src/tools-v2/read-tools.ts +286 -0
- package/src/tools-v2/search-tools.ts +175 -0
- package/src/tools-v2/test-tools.ts +147 -0
- package/src/tools-v2/workspace-context.ts +428 -0
- package/src/ui/App.tsx +392 -0
- package/src/ui/components/ChatPane.tsx +84 -0
- package/src/ui/components/EventsPane.tsx +81 -0
- package/src/ui/components/GoalsTasksPane.tsx +149 -0
- package/src/ui/store.ts +362 -0
- package/tests/integration.test.ts +537 -0
- package/tsconfig.json +22 -0
package/README.md
ADDED
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
# ACM AI Coder - Phase 2
|
|
2
|
+
|
|
3
|
+
<!-- markdownlint-disable MD024 MD032 -->
|
|
4
|
+
|
|
5
|
+
An advanced AI-powered developer workflow automation tool with an interactive full-screen TUI that showcases the complete ACM (Agentic Contract Model) framework v0.5.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
The ACM AI Coder Phase 2 introduces an **interactive-only experience** with a three-column terminal UI:
|
|
10
|
+
|
|
11
|
+
- **Left Column**: Chat interface with streaming planner and nucleus reasoning
|
|
12
|
+
- **Middle Column**: Current goal, tasks with live status, and budget metrics
|
|
13
|
+
- **Right Column**: Event stream showing ledger entries, tool calls, and context updates
|
|
14
|
+
|
|
15
|
+
### Key Features
|
|
16
|
+
|
|
17
|
+
- ✅ **Interactive-Only TUI**: Full-screen terminal interface with real-time updates
|
|
18
|
+
- ✅ **Mandatory Configuration**: Requires `--provider`, `--model`, and `--workspace` flags with optional `--base-url`
|
|
19
|
+
- ✅ **Budget Governance**: Pre-inference cost checks with live spend tracking
|
|
20
|
+
- ✅ **Streaming Reasoning**: Watch planner and nucleus think in real-time
|
|
21
|
+
- ✅ **File Mentions**: Reference workspace files with `#path/to/file` syntax
|
|
22
|
+
- ✅ **Memory Lifecycle**: Automatic cleanup and replay bundle persistence
|
|
23
|
+
- ✅ **ACM Framework Integration**: Built entirely on ACM primitives (planner, runtime, nucleus, ledger)
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# From the workspace root
|
|
29
|
+
pnpm install
|
|
30
|
+
|
|
31
|
+
# Build the package
|
|
32
|
+
pnpm --filter @ddse/acm-aicoder build
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
### Phase 2 Interactive Mode (Recommended)
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Start the interactive AI Coder
|
|
41
|
+
acm-aicoder \
|
|
42
|
+
--provider vllm \
|
|
43
|
+
--model Qwen/Qwen3-Coder-30B-A3B-Instruct-FP8 \
|
|
44
|
+
--base-url http://localhost:8001/v1 \
|
|
45
|
+
--workspace /path/to/your/project
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Required Parameters:**
|
|
49
|
+
|
|
50
|
+
- `--provider <ollama|vllm>` - LLM provider (default: ollama)
|
|
51
|
+
- `--model <name>` - Model identifier provided by the selected provider
|
|
52
|
+
- `--workspace <path>` - Project workspace root directory (must exist and be a readable directory)
|
|
53
|
+
|
|
54
|
+
**Optional Parameters:**
|
|
55
|
+
|
|
56
|
+
- `--base-url <url>` - Override provider base URL when using a custom endpoint
|
|
57
|
+
- `--temperature <0-2>` - LLM temperature (default: 0.7)
|
|
58
|
+
- `--seed <number>` - Random seed for reproducibility
|
|
59
|
+
- `--plans <1|2>` - Number of alternative plans to generate (default: 1)
|
|
60
|
+
|
|
61
|
+
### Commands in Interactive Mode
|
|
62
|
+
|
|
63
|
+
Once running, you can use these commands:
|
|
64
|
+
|
|
65
|
+
- `/exit`, `/quit` - Exit the application
|
|
66
|
+
- `/help` - Show available commands
|
|
67
|
+
- `/budget` - Display detailed budget information
|
|
68
|
+
- `/context` - Show current context information
|
|
69
|
+
- `/reset` - Reset the session (clear goal and tasks)
|
|
70
|
+
- `#path/to/file` - Mention files from your workspace in chat
|
|
71
|
+
|
|
72
|
+
**Example Session:**
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
> Analyze the src/index.ts file and find potential bugs
|
|
76
|
+
|
|
77
|
+
[Planner will reason about the task, select appropriate capabilities]
|
|
78
|
+
[Tasks will execute with live status updates]
|
|
79
|
+
[Events will stream in the right column]
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## ACM Framework Integration
|
|
83
|
+
|
|
84
|
+
Phase 2 is built strictly on ACM v0.5 components:
|
|
85
|
+
|
|
86
|
+
### Planner & Nucleus
|
|
87
|
+
|
|
88
|
+
- Chat pane visualizes ACM planner tool-call loops and nucleus inferences in real-time
|
|
89
|
+
- Streaming tokens show reasoning as it happens
|
|
90
|
+
- Budget checks run before each inference
|
|
91
|
+
|
|
92
|
+
#### Nucleus configuration requirements
|
|
93
|
+
|
|
94
|
+
- Every runtime invocation now passes a `nucleusFactory` and `nucleusConfig` to `executePlan`. The CLI wires these from the `--llm-provider`, `--llm-model`, `--llm-base-url`, and `--llm-engine` flags to build a shared `DeterministicNucleus` instance.
|
|
95
|
+
- If you embed AI Coder components elsewhere, supply your own factory that returns a `Nucleus` subclass and include at minimum an `llmCall` block with `provider`, `model`, and token limits.
|
|
96
|
+
- Tests and examples provide lightweight stub nuclei; use them as a reference when authoring new scripts or integrations.
|
|
97
|
+
|
|
98
|
+
### Tools & Tasks
|
|
99
|
+
|
|
100
|
+
- All tools extend `Tool<I, O>` from `@ddse/acm-sdk`
|
|
101
|
+
- Tasks extend `Task<I, O>` and leverage context builder
|
|
102
|
+
- Tool call envelopes logged to ledger for determinism
|
|
103
|
+
|
|
104
|
+
### Context Packets
|
|
105
|
+
|
|
106
|
+
- Context orchestration uses Phase 4 `ContextBuilder`
|
|
107
|
+
- Immutable packets with provenance and sources
|
|
108
|
+
- View current context with `/context` command
|
|
109
|
+
|
|
110
|
+
### Ledger & Replay
|
|
111
|
+
|
|
112
|
+
- Event stream pane visualizes ledger entries
|
|
113
|
+
- Replay bundles saved automatically to `.aicoder/replays/`
|
|
114
|
+
- Includes session config, ledger, and budget summary
|
|
115
|
+
|
|
116
|
+
### Budget Enforcement
|
|
117
|
+
|
|
118
|
+
- BudgetManager enforces spending limits before inference
|
|
119
|
+
- Provider metadata for OpenAI, Anthropic, Ollama, and more
|
|
120
|
+
- Real-time budget display in Tasks column
|
|
121
|
+
|
|
122
|
+
## Architecture
|
|
123
|
+
|
|
124
|
+
The ACM AI Coder is built on the ACM framework and showcases all its capabilities:
|
|
125
|
+
|
|
126
|
+
### ACM Framework Integration
|
|
127
|
+
|
|
128
|
+
1. **SDK Layer**: All tools and tasks extend `Tool<I, O>` and `Task<I, O>` from `@ddse/acm-sdk`
|
|
129
|
+
2. **Context Engine**: Intelligent repository understanding feeds into planning
|
|
130
|
+
3. **Planning Phase**: LLM analyzes goal + context, generates Plan-A and Plan-B
|
|
131
|
+
4. **Runtime Execution**: `@ddse/acm-runtime` executes plans with streaming, checkpoints, and verification
|
|
132
|
+
5. **Policy Engine**: Safety guards with path restrictions and action gating
|
|
133
|
+
6. **Replay Bundle**: Complete audit trail via `@ddse/acm-replay`
|
|
134
|
+
|
|
135
|
+
### Workflow
|
|
136
|
+
|
|
137
|
+
1. **Indexing**: Scan workspace, extract symbols, dependencies, and tests
|
|
138
|
+
2. **Context Generation**: Create context pack with relevant files and symbols
|
|
139
|
+
3. **Planning**: Feed context to LLM planner for multi-step plan generation
|
|
140
|
+
4. **Approval**: User approves plan and operations that modify code
|
|
141
|
+
5. **Execution**: ACM runtime executes with streaming progress
|
|
142
|
+
6. **Checkpointing**: Automatic checkpoints after each task
|
|
143
|
+
7. **Verification**: Tasks verify outputs match expectations
|
|
144
|
+
|
|
145
|
+
### Safety Features
|
|
146
|
+
|
|
147
|
+
- **Dry Run Mode**: Preview all changes without modifying files
|
|
148
|
+
- **Approval Workflow**: User approval required for file modifications
|
|
149
|
+
- **Policy Engine**: Path allowlists and action restrictions
|
|
150
|
+
- **Automatic Backups**: `.backup` files created before edits
|
|
151
|
+
- **Checkpointing**: Resume from any point if execution is interrupted
|
|
152
|
+
- **Context Limits**: File size and result count limits prevent overload
|
|
153
|
+
|
|
154
|
+
## How It Showcases ACM
|
|
155
|
+
|
|
156
|
+
This tool demonstrates every aspect of the ACM framework:
|
|
157
|
+
|
|
158
|
+
- **Capability Model**: Tasks are registered as capabilities with clear contracts
|
|
159
|
+
- **Tool Composition**: Tasks compose multiple tools to accomplish goals
|
|
160
|
+
- **Context Packets**: Immutable context with content-addressable refs
|
|
161
|
+
- **Plan Alternatives**: Planner generates Plan-A and Plan-B with rationale
|
|
162
|
+
- **Deterministic Execution**: Runtime executes plans with guards and verification
|
|
163
|
+
- **Policy Integration**: Pre/post hooks for safety enforcement
|
|
164
|
+
- **Memory Ledger**: Complete audit trail of all decisions
|
|
165
|
+
- **Streaming**: Real-time progress via StreamSink
|
|
166
|
+
- **Resumability**: FileCheckpointStore enables resume from crashes
|
|
167
|
+
|
|
168
|
+
## Development
|
|
169
|
+
|
|
170
|
+
### Running Tests
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Run integration tests
|
|
174
|
+
pnpm --filter @ddse/acm-aicoder test
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
<!-- markdownlint-enable MD024 MD032 -->
|
|
178
|
+
|
|
179
|
+
### Building
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# Build TypeScript
|
|
183
|
+
pnpm --filter @ddse/acm-aicoder build
|
|
184
|
+
|
|
185
|
+
# Watch mode for development
|
|
186
|
+
pnpm --filter @ddse/acm-aicoder dev
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Examples
|
|
190
|
+
|
|
191
|
+
### Example 1: Deep Workspace Analysis
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
pnpm --filter @ddse/acm-aicoder exec acm-aicoder --goal analyze --workspace .
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
This will:
|
|
198
|
+
|
|
199
|
+
1. Index all files in the workspace (respecting gitignore)
|
|
200
|
+
2. Extract symbols (functions, classes, interfaces)
|
|
201
|
+
3. Map dependencies from package.json
|
|
202
|
+
4. Identify test files and their targets
|
|
203
|
+
5. Generate a comprehensive report with statistics
|
|
204
|
+
|
|
205
|
+
Output includes:
|
|
206
|
+
|
|
207
|
+
- Total files scanned
|
|
208
|
+
- Code files by language
|
|
209
|
+
- Symbols extracted (functions, classes, etc.)
|
|
210
|
+
- Dependencies found
|
|
211
|
+
- Test file mappings
|
|
212
|
+
|
|
213
|
+
### Example 2: Search for Code Patterns
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
pnpm --filter @ddse/acm-aicoder exec acm-aicoder --goal custom
|
|
217
|
+
# Enter: "Search for all error handling patterns in the codebase"
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
This will:
|
|
221
|
+
|
|
222
|
+
1. Build BM25 index of code files
|
|
223
|
+
2. Search for "error handling try catch" patterns
|
|
224
|
+
3. Return top-k results with context
|
|
225
|
+
4. Show file paths, line numbers, and code snippets
|
|
226
|
+
|
|
227
|
+
### Example 3: Implement a New Function
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
pnpm --filter @ddse/acm-aicoder exec acm-aicoder --goal custom
|
|
231
|
+
# Enter: "Implement a function to validate email addresses in src/utils.ts"
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
This will:
|
|
235
|
+
|
|
236
|
+
1. Read the target file
|
|
237
|
+
2. Analyze existing code patterns
|
|
238
|
+
3. Generate function implementation (with LLM)
|
|
239
|
+
4. Show diff preview
|
|
240
|
+
5. Request approval
|
|
241
|
+
6. Apply changes with automatic backup
|
|
242
|
+
|
|
243
|
+
### Example 4: Refactor Symbol Names
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
pnpm --filter @ddse/acm-aicoder exec acm-aicoder --goal custom
|
|
247
|
+
# Enter: "Rename function getUserData to fetchUserData everywhere"
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
This will:
|
|
251
|
+
|
|
252
|
+
1. Search for all occurrences of the symbol
|
|
253
|
+
2. Generate list of affected files
|
|
254
|
+
3. Show preview of changes
|
|
255
|
+
4. Request approval
|
|
256
|
+
5. Apply rename across all files (with backup)
|
|
257
|
+
|
|
258
|
+
### Example 5: Fix TypeScript Errors
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
pnpm --filter @ddse/acm-aicoder exec acm-aicoder --goal custom
|
|
262
|
+
# Enter: "Fix all TypeScript compilation errors"
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
This will:
|
|
266
|
+
|
|
267
|
+
1. Run build to collect TypeScript errors
|
|
268
|
+
2. Analyze each error with context
|
|
269
|
+
3. Generate fixes (with LLM)
|
|
270
|
+
4. Show diffs for each fix
|
|
271
|
+
5. Request approval
|
|
272
|
+
6. Apply fixes and verify build succeeds
|
|
273
|
+
|
|
274
|
+
### Example 6: Generate Unit Tests
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
pnpm --filter @ddse/acm-aicoder exec acm-aicoder --goal custom
|
|
278
|
+
# Enter: "Generate unit tests for the validateEmail function in src/utils.ts"
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
This will:
|
|
282
|
+
|
|
283
|
+
1. Read and analyze the target function
|
|
284
|
+
2. Generate test cases (with LLM)
|
|
285
|
+
3. Create test file (e.g., `src/utils.test.ts`)
|
|
286
|
+
4. Show preview
|
|
287
|
+
5. Request approval
|
|
288
|
+
6. Apply and run tests to verify
|
|
289
|
+
|
|
290
|
+
### Example 7: Resume from Checkpoint
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
# Start a long operation
|
|
294
|
+
pnpm --filter @ddse/acm-aicoder exec acm-aicoder --goal implementFeature
|
|
295
|
+
|
|
296
|
+
# If interrupted (Ctrl+C), resume later:
|
|
297
|
+
pnpm --filter @ddse/acm-aicoder exec acm-aicoder --resume run-1696348800000
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
The resume will:
|
|
301
|
+
|
|
302
|
+
1. Load checkpoint from disk
|
|
303
|
+
2. Restore plan and completed tasks
|
|
304
|
+
3. Continue from the next task
|
|
305
|
+
4. Maintain all context and state
|
|
306
|
+
|
|
307
|
+
## Key Components
|
|
308
|
+
|
|
309
|
+
### Context Engine
|
|
310
|
+
|
|
311
|
+
Located in `src/context/`:
|
|
312
|
+
|
|
313
|
+
- **WorkspaceIndexer**: Fast file scanning with caching
|
|
314
|
+
- **SymbolExtractor**: Parse TS/JS for symbols
|
|
315
|
+
- **DependencyMapper**: Extract package.json dependencies
|
|
316
|
+
- **TestMapper**: Identify test files
|
|
317
|
+
- **CodeSearch**: BM25-based semantic search
|
|
318
|
+
- **ContextPackGenerator**: Generate planning context
|
|
319
|
+
|
|
320
|
+
### Tools V2
|
|
321
|
+
|
|
322
|
+
Located in `src/tools-v2/`:
|
|
323
|
+
|
|
324
|
+
- **read-tools.ts**: FileStatTool, FileReadToolV2, FileReadLinesTool, DiffTool
|
|
325
|
+
- **search-tools.ts**: CodeSearchTool, GrepTool
|
|
326
|
+
- **edit-tools.ts**: PatchApplyTool, CodeEditToolV2
|
|
327
|
+
- **test-tools.ts**: RunTestsToolV2, BuildTool
|
|
328
|
+
|
|
329
|
+
### Tasks V2
|
|
330
|
+
|
|
331
|
+
Located in `src/tasks-v2/`:
|
|
332
|
+
|
|
333
|
+
- **analysis-tasks.ts**: AnalyzeWorkspaceTask, CollectContextPackTask, SearchCodeTask
|
|
334
|
+
- **developer-tasks.ts**: FindSymbolDefinitionTask, ImplementFunctionTask, RefactorRenameSymbolTask, FixTypeErrorTask, GenerateUnitTestsTask
|
|
335
|
+
|
|
336
|
+
## Contributing
|
|
337
|
+
|
|
338
|
+
See [CONTRIBUTING.md](../../CONTRIBUTING.md) for development guidelines.
|
|
339
|
+
|
|
340
|
+
## License
|
|
341
|
+
|
|
342
|
+
MIT
|
|
343
|
+
|
|
344
|
+
You can also use the AI Coder programmatically:
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
import {
|
|
348
|
+
// Context Engine
|
|
349
|
+
WorkspaceIndexer,
|
|
350
|
+
SymbolExtractor,
|
|
351
|
+
CodeSearch,
|
|
352
|
+
ContextPackGenerator,
|
|
353
|
+
|
|
354
|
+
// Tools V2
|
|
355
|
+
FileStatTool,
|
|
356
|
+
FileReadToolV2,
|
|
357
|
+
CodeSearchTool,
|
|
358
|
+
GrepTool,
|
|
359
|
+
DiffTool,
|
|
360
|
+
PatchApplyTool,
|
|
361
|
+
CodeEditToolV2,
|
|
362
|
+
RunTestsToolV2,
|
|
363
|
+
BuildTool,
|
|
364
|
+
|
|
365
|
+
// Tasks V2
|
|
366
|
+
AnalyzeWorkspaceTask,
|
|
367
|
+
FindSymbolDefinitionTask,
|
|
368
|
+
ImplementFunctionTask,
|
|
369
|
+
RefactorRenameSymbolTask,
|
|
370
|
+
GenerateUnitTestsTask,
|
|
371
|
+
CollectContextPackTask,
|
|
372
|
+
|
|
373
|
+
// Registries
|
|
374
|
+
SimpleCapabilityRegistry,
|
|
375
|
+
SimpleToolRegistry,
|
|
376
|
+
SimplePolicyEngine,
|
|
377
|
+
} from '@ddse/acm-aicoder';
|
|
378
|
+
|
|
379
|
+
import { executeResumablePlan } from '@ddse/acm-runtime';
|
|
380
|
+
import { StructuredLLMPlanner } from '@ddse/acm-planner';
|
|
381
|
+
import { createOllamaClient } from '@ddse/acm-llm';
|
|
382
|
+
|
|
383
|
+
// Setup
|
|
384
|
+
const rootPath = process.cwd();
|
|
385
|
+
|
|
386
|
+
// 1. Build workspace index
|
|
387
|
+
const indexer = new WorkspaceIndexer(rootPath);
|
|
388
|
+
const index = await indexer.buildIndex();
|
|
389
|
+
|
|
390
|
+
// 2. Setup search
|
|
391
|
+
const search = new CodeSearch(rootPath);
|
|
392
|
+
await search.indexFiles(index);
|
|
393
|
+
|
|
394
|
+
// 3. Register tools
|
|
395
|
+
const toolRegistry = new SimpleToolRegistry();
|
|
396
|
+
toolRegistry.register(new FileStatTool());
|
|
397
|
+
toolRegistry.register(new CodeSearchTool(rootPath));
|
|
398
|
+
toolRegistry.register(new GrepTool(rootPath));
|
|
399
|
+
toolRegistry.register(new CodeEditToolV2());
|
|
400
|
+
toolRegistry.register(new RunTestsToolV2());
|
|
401
|
+
toolRegistry.register(new BuildTool());
|
|
402
|
+
|
|
403
|
+
// 4. Register tasks
|
|
404
|
+
const capabilityRegistry = new SimpleCapabilityRegistry();
|
|
405
|
+
capabilityRegistry.register(
|
|
406
|
+
{ name: 'analyze_workspace', sideEffects: false },
|
|
407
|
+
new AnalyzeWorkspaceTask()
|
|
408
|
+
);
|
|
409
|
+
capabilityRegistry.register(
|
|
410
|
+
{ name: 'find_symbol', sideEffects: false },
|
|
411
|
+
new FindSymbolDefinitionTask()
|
|
412
|
+
);
|
|
413
|
+
capabilityRegistry.register(
|
|
414
|
+
{ name: 'implement_function', sideEffects: true },
|
|
415
|
+
new ImplementFunctionTask()
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
// 5. Create context pack
|
|
419
|
+
const symbolExtractor = new SymbolExtractor(rootPath);
|
|
420
|
+
const symbols = await symbolExtractor.extractSymbols(index);
|
|
421
|
+
|
|
422
|
+
const packGenerator = new ContextPackGenerator(search);
|
|
423
|
+
const contextPack = await packGenerator.generate(
|
|
424
|
+
'Find and fix all TypeScript errors',
|
|
425
|
+
index,
|
|
426
|
+
symbols,
|
|
427
|
+
[], // dependencies
|
|
428
|
+
[], // test mappings
|
|
429
|
+
{ maxFiles: 10, maxSymbols: 30 }
|
|
430
|
+
);
|
|
431
|
+
|
|
432
|
+
// 6. Plan with context
|
|
433
|
+
const llm = createOllamaClient('llama3.1');
|
|
434
|
+
const planner = new StructuredLLMPlanner();
|
|
435
|
+
|
|
436
|
+
const goal = {
|
|
437
|
+
id: 'goal-1',
|
|
438
|
+
intent: 'Find and fix all TypeScript errors',
|
|
439
|
+
constraints: {},
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
const context = {
|
|
443
|
+
id: 'ctx-1',
|
|
444
|
+
facts: { contextPack },
|
|
445
|
+
version: '1.0',
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
const plannerResult = await planner.plan({
|
|
449
|
+
goal,
|
|
450
|
+
context,
|
|
451
|
+
capabilities: capabilityRegistry.list(),
|
|
452
|
+
llm,
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
// 7. Execute with runtime
|
|
456
|
+
const policy = new SimplePolicyEngine();
|
|
457
|
+
policy.setAllowedPaths(['src/**']);
|
|
458
|
+
|
|
459
|
+
const result = await executeResumablePlan({
|
|
460
|
+
goal,
|
|
461
|
+
context,
|
|
462
|
+
plan: plannerResult.plans[0],
|
|
463
|
+
capabilityRegistry,
|
|
464
|
+
toolRegistry,
|
|
465
|
+
policy,
|
|
466
|
+
verify: async (taskId, output, expressions) => true,
|
|
467
|
+
runId: `run-${Date.now()}`,
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
console.log('Execution complete:', result);
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
## Reference Pipeline Walkthrough
|
|
474
|
+
|
|
475
|
+
### Build from Source
|
|
476
|
+
|
|
477
|
+
```bash
|
|
478
|
+
# Build TypeScript
|
|
479
|
+
pnpm --filter @ddse/acm-aicoder build
|
|
480
|
+
|
|
481
|
+
# Watch mode for development
|
|
482
|
+
pnpm --filter @ddse/acm-aicoder dev
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
### Test Suite (Preview)
|
|
486
|
+
|
|
487
|
+
```bash
|
|
488
|
+
# Run integration tests (coming soon)
|
|
489
|
+
pnpm --filter @ddse/acm-aicoder test
|
|
490
|
+
```
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// ACM AI Coder - Phase 2 Interactive CLI
|
|
4
|
+
// Full-screen TUI with three-column layout
|
|
5
|
+
// Requires: --provider, --model, and --workspace (optional --base-url)
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { render } from 'ink';
|
|
9
|
+
import { ExternalContextProviderAdapter } from '@ddse/acm-sdk';
|
|
10
|
+
import { createOllamaClient, createVLLMClient } from '@ddse/acm-llm';
|
|
11
|
+
import { App } from '../src/ui/App.js';
|
|
12
|
+
import { AppStore } from '../src/ui/store.js';
|
|
13
|
+
import { InteractiveRuntime } from '../src/runtime/interactive-runtime.js';
|
|
14
|
+
import { parseCliArgs, validateAndNormalizeConfig } from '../src/config/session.js';
|
|
15
|
+
import {
|
|
16
|
+
SimpleCapabilityRegistry,
|
|
17
|
+
SimpleToolRegistry,
|
|
18
|
+
SimplePolicyEngine,
|
|
19
|
+
// V2 Tools
|
|
20
|
+
FileStatTool,
|
|
21
|
+
FileReadToolV2,
|
|
22
|
+
CodeSearchTool,
|
|
23
|
+
GrepTool,
|
|
24
|
+
DiffTool,
|
|
25
|
+
CodeEditToolV2,
|
|
26
|
+
RunTestsToolV2,
|
|
27
|
+
WorkspaceContextRetrievalTool,
|
|
28
|
+
type WorkspaceContextOperation,
|
|
29
|
+
BuildTool,
|
|
30
|
+
// V2 Tasks
|
|
31
|
+
AnalyzeWorkspaceTask,
|
|
32
|
+
CollectContextPackTask,
|
|
33
|
+
SearchCodeTask,
|
|
34
|
+
FindSymbolDefinitionTask,
|
|
35
|
+
ImplementFunctionTask,
|
|
36
|
+
RefactorRenameSymbolTask,
|
|
37
|
+
FixTypeErrorTask,
|
|
38
|
+
GenerateUnitTestsTask,
|
|
39
|
+
} from '../src/index.js';
|
|
40
|
+
|
|
41
|
+
function buildWorkspaceContextInput(
|
|
42
|
+
directive: string,
|
|
43
|
+
goalIntent?: string
|
|
44
|
+
): {
|
|
45
|
+
directive: string;
|
|
46
|
+
goal?: string;
|
|
47
|
+
operations: WorkspaceContextOperation[];
|
|
48
|
+
} {
|
|
49
|
+
const separatorIndex = directive.indexOf(':');
|
|
50
|
+
const payload = separatorIndex >= 0 ? directive.slice(separatorIndex + 1).trim() : '';
|
|
51
|
+
const operations: WorkspaceContextOperation[] = [];
|
|
52
|
+
|
|
53
|
+
if (payload.length > 0) {
|
|
54
|
+
if (payload.startsWith('{')) {
|
|
55
|
+
try {
|
|
56
|
+
const parsed = JSON.parse(payload);
|
|
57
|
+
if (Array.isArray(parsed.operations)) {
|
|
58
|
+
return {
|
|
59
|
+
directive,
|
|
60
|
+
goal: goalIntent,
|
|
61
|
+
operations: parsed.operations as WorkspaceContextOperation[],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (typeof parsed.query === 'string' && parsed.query.length > 0) {
|
|
65
|
+
operations.push({ type: 'search', query: parsed.query, includeContext: true });
|
|
66
|
+
}
|
|
67
|
+
if (typeof parsed.pattern === 'string' && parsed.pattern.length > 0) {
|
|
68
|
+
operations.push({ type: 'grep', pattern: parsed.pattern, maxResults: 20 });
|
|
69
|
+
}
|
|
70
|
+
} catch {
|
|
71
|
+
// Fall through to textual parsing
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (operations.length === 0) {
|
|
76
|
+
operations.push({ type: 'search', query: payload, includeContext: true });
|
|
77
|
+
operations.push({ type: 'grep', pattern: payload, maxResults: 20 });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
directive,
|
|
83
|
+
goal: goalIntent,
|
|
84
|
+
operations,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function main() {
|
|
89
|
+
try {
|
|
90
|
+
// Parse and validate CLI arguments
|
|
91
|
+
const args = parseCliArgs(process.argv.slice(2));
|
|
92
|
+
const config = validateAndNormalizeConfig(args);
|
|
93
|
+
|
|
94
|
+
// Ensure the process operates within the validated workspace
|
|
95
|
+
process.chdir(config.workspace);
|
|
96
|
+
|
|
97
|
+
// Create LLM client based on provider selection
|
|
98
|
+
const llm = config.provider === 'vllm'
|
|
99
|
+
? createVLLMClient(config.model, config.baseUrl)
|
|
100
|
+
: createOllamaClient(config.model, config.baseUrl);
|
|
101
|
+
|
|
102
|
+
// Setup registries
|
|
103
|
+
const toolRegistry = new SimpleToolRegistry();
|
|
104
|
+
const capabilityRegistry = new SimpleCapabilityRegistry();
|
|
105
|
+
const policyEngine = new SimplePolicyEngine();
|
|
106
|
+
const contextProvider = new ExternalContextProviderAdapter();
|
|
107
|
+
|
|
108
|
+
// Register tools
|
|
109
|
+
const fileStatTool = new FileStatTool(config.workspace);
|
|
110
|
+
const fileReadTool = new FileReadToolV2(config.workspace);
|
|
111
|
+
const codeSearchTool = new CodeSearchTool(config.workspace);
|
|
112
|
+
const grepTool = new GrepTool(config.workspace);
|
|
113
|
+
const diffTool = new DiffTool(config.workspace);
|
|
114
|
+
const codeEditTool = new CodeEditToolV2(config.workspace);
|
|
115
|
+
const runTestsTool = new RunTestsToolV2(config.workspace);
|
|
116
|
+
const buildTool = new BuildTool(config.workspace);
|
|
117
|
+
const workspaceContextTool = new WorkspaceContextRetrievalTool(config.workspace);
|
|
118
|
+
|
|
119
|
+
toolRegistry.register(fileStatTool);
|
|
120
|
+
toolRegistry.register(fileReadTool);
|
|
121
|
+
toolRegistry.register(codeSearchTool);
|
|
122
|
+
toolRegistry.register(grepTool);
|
|
123
|
+
toolRegistry.register(diffTool);
|
|
124
|
+
toolRegistry.register(codeEditTool);
|
|
125
|
+
toolRegistry.register(runTestsTool);
|
|
126
|
+
toolRegistry.register(buildTool);
|
|
127
|
+
toolRegistry.register(workspaceContextTool);
|
|
128
|
+
|
|
129
|
+
contextProvider.register(workspaceContextTool, {
|
|
130
|
+
match: directive =>
|
|
131
|
+
directive.startsWith('workspace.context') || directive.startsWith('workspace_context'),
|
|
132
|
+
buildInput: (directive, ctx) =>
|
|
133
|
+
buildWorkspaceContextInput(directive, ctx.runContext?.goal.intent),
|
|
134
|
+
describe:
|
|
135
|
+
'Retrieve relevant workspace snippets, grep matches, and metadata to satisfy context requests.',
|
|
136
|
+
autoPromote: true,
|
|
137
|
+
maxArtifacts: 32,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Register capabilities (tasks)
|
|
141
|
+
capabilityRegistry.register(
|
|
142
|
+
{ name: 'analyze_workspace', sideEffects: false },
|
|
143
|
+
new AnalyzeWorkspaceTask()
|
|
144
|
+
);
|
|
145
|
+
capabilityRegistry.register(
|
|
146
|
+
{ name: 'collect_context_pack', sideEffects: false },
|
|
147
|
+
new CollectContextPackTask()
|
|
148
|
+
);
|
|
149
|
+
capabilityRegistry.register(
|
|
150
|
+
{ name: 'search_code', sideEffects: false },
|
|
151
|
+
new SearchCodeTask()
|
|
152
|
+
);
|
|
153
|
+
capabilityRegistry.register(
|
|
154
|
+
{ name: 'find_symbol_definition', sideEffects: false },
|
|
155
|
+
new FindSymbolDefinitionTask()
|
|
156
|
+
);
|
|
157
|
+
capabilityRegistry.register(
|
|
158
|
+
{ name: 'implement_function', sideEffects: true },
|
|
159
|
+
new ImplementFunctionTask()
|
|
160
|
+
);
|
|
161
|
+
capabilityRegistry.register(
|
|
162
|
+
{ name: 'refactor_rename_symbol', sideEffects: true },
|
|
163
|
+
new RefactorRenameSymbolTask()
|
|
164
|
+
);
|
|
165
|
+
capabilityRegistry.register(
|
|
166
|
+
{ name: 'fix_type_error', sideEffects: true },
|
|
167
|
+
new FixTypeErrorTask()
|
|
168
|
+
);
|
|
169
|
+
capabilityRegistry.register(
|
|
170
|
+
{ name: 'generate_unit_tests', sideEffects: true },
|
|
171
|
+
new GenerateUnitTestsTask()
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
// Allow workspace operations
|
|
175
|
+
policyEngine.setAllowedPaths([config.workspace]);
|
|
176
|
+
|
|
177
|
+
// Create app store and runtime
|
|
178
|
+
const store = new AppStore();
|
|
179
|
+
const runtime = new InteractiveRuntime({
|
|
180
|
+
config,
|
|
181
|
+
llm,
|
|
182
|
+
capabilityRegistry,
|
|
183
|
+
toolRegistry,
|
|
184
|
+
policyEngine,
|
|
185
|
+
store,
|
|
186
|
+
contextProvider,
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const initialBudget = runtime.getBudgetManager().getStatus();
|
|
190
|
+
|
|
191
|
+
// Welcome message
|
|
192
|
+
store.addMessage('system',
|
|
193
|
+
`Welcome to ACM AI Coder (Phase 2)\n\n` +
|
|
194
|
+
`Configuration:\n` +
|
|
195
|
+
` Provider: ${config.provider}\n` +
|
|
196
|
+
` Model: ${config.model}\n` +
|
|
197
|
+
(config.baseUrl ? ` Base URL: ${config.baseUrl}\n` : '') +
|
|
198
|
+
` Workspace: ${config.workspace}\n` +
|
|
199
|
+
(initialBudget.maxTokens !== undefined ? ` Token allowance: ${initialBudget.maxTokens}\n` : '') +
|
|
200
|
+
`\n` +
|
|
201
|
+
`Type your goal to start planning, or /help for commands.`
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
// Update initial budget status
|
|
205
|
+
store.updateBudgetStatus(initialBudget);
|
|
206
|
+
|
|
207
|
+
// Handle commands from UI
|
|
208
|
+
const handleCommand = async (command: string) => {
|
|
209
|
+
if (command.startsWith('/')) {
|
|
210
|
+
// Already handled by UI component
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Process as goal
|
|
215
|
+
await runtime.processGoal(command);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// Render TUI
|
|
219
|
+
render(<App store={store} onCommand={handleCommand} />);
|
|
220
|
+
|
|
221
|
+
} catch (error: any) {
|
|
222
|
+
console.error('Error starting ACM AI Coder:');
|
|
223
|
+
console.error(error.message);
|
|
224
|
+
console.error('\nFor help, run: acm-aicoder --help');
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
main().catch(err => {
|
|
230
|
+
console.error('Fatal error:', err);
|
|
231
|
+
process.exit(1);
|
|
232
|
+
});
|