@ariso-ai/ivan 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +412 -0
- package/dist/agent.d.ts +11 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +48 -0
- package/dist/agent.js.map +1 -0
- package/dist/config/config.d.ts +20 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +187 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config.d.ts +46 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +414 -0
- package/dist/config.js.map +1 -0
- package/dist/database/database.d.ts +12 -0
- package/dist/database/database.d.ts.map +1 -0
- package/dist/database/database.js +45 -0
- package/dist/database/database.js.map +1 -0
- package/dist/database/migration.d.ts +11 -0
- package/dist/database/migration.d.ts.map +1 -0
- package/dist/database/migration.js +64 -0
- package/dist/database/migration.js.map +1 -0
- package/dist/database/migrations/001_create_jobs_table.d.ts +3 -0
- package/dist/database/migrations/001_create_jobs_table.d.ts.map +1 -0
- package/dist/database/migrations/001_create_jobs_table.js +14 -0
- package/dist/database/migrations/001_create_jobs_table.js.map +1 -0
- package/dist/database/migrations/001_initial_schema.d.ts +3 -0
- package/dist/database/migrations/001_initial_schema.d.ts.map +1 -0
- package/dist/database/migrations/001_initial_schema.js +66 -0
- package/dist/database/migrations/001_initial_schema.js.map +1 -0
- package/dist/database/migrations/002_create_tasks_table.d.ts +3 -0
- package/dist/database/migrations/002_create_tasks_table.d.ts.map +1 -0
- package/dist/database/migrations/002_create_tasks_table.js +16 -0
- package/dist/database/migrations/002_create_tasks_table.js.map +1 -0
- package/dist/database/migrations/003_add_log_to_tasks.d.ts +3 -0
- package/dist/database/migrations/003_add_log_to_tasks.d.ts.map +1 -0
- package/dist/database/migrations/003_add_log_to_tasks.js +11 -0
- package/dist/database/migrations/003_add_log_to_tasks.js.map +1 -0
- package/dist/database/migrations/004_add_branch_to_tasks.d.ts +3 -0
- package/dist/database/migrations/004_add_branch_to_tasks.d.ts.map +1 -0
- package/dist/database/migrations/004_add_branch_to_tasks.js +11 -0
- package/dist/database/migrations/004_add_branch_to_tasks.js.map +1 -0
- package/dist/database/migrations/005_add_type_to_tasks.d.ts +3 -0
- package/dist/database/migrations/005_add_type_to_tasks.d.ts.map +1 -0
- package/dist/database/migrations/005_add_type_to_tasks.js +11 -0
- package/dist/database/migrations/005_add_type_to_tasks.js.map +1 -0
- package/dist/database/migrations/006_add_comment_url_and_commit_to_tasks.d.ts +3 -0
- package/dist/database/migrations/006_add_comment_url_and_commit_to_tasks.d.ts.map +1 -0
- package/dist/database/migrations/006_add_comment_url_and_commit_to_tasks.js +15 -0
- package/dist/database/migrations/006_add_comment_url_and_commit_to_tasks.js.map +1 -0
- package/dist/database/migrations/006_add_comment_url_to_tasks.d.ts +3 -0
- package/dist/database/migrations/006_add_comment_url_to_tasks.d.ts.map +1 -0
- package/dist/database/migrations/006_add_comment_url_to_tasks.js +14 -0
- package/dist/database/migrations/006_add_comment_url_to_tasks.js.map +1 -0
- package/dist/database/migrations/007_add_commit_to_tasks.d.ts +3 -0
- package/dist/database/migrations/007_add_commit_to_tasks.d.ts.map +1 -0
- package/dist/database/migrations/007_add_commit_to_tasks.js +13 -0
- package/dist/database/migrations/007_add_commit_to_tasks.js.map +1 -0
- package/dist/database/migrations/008_add_lint_and_test_task_type.d.ts +3 -0
- package/dist/database/migrations/008_add_lint_and_test_task_type.d.ts.map +1 -0
- package/dist/database/migrations/008_add_lint_and_test_task_type.js +42 -0
- package/dist/database/migrations/008_add_lint_and_test_task_type.js.map +1 -0
- package/dist/database/migrations/index.d.ts +3 -0
- package/dist/database/migrations/index.d.ts.map +1 -0
- package/dist/database/migrations/index.js +19 -0
- package/dist/database/migrations/index.js.map +1 -0
- package/dist/database/types.d.ts +34 -0
- package/dist/database/types.d.ts.map +1 -0
- package/dist/database/types.js +2 -0
- package/dist/database/types.js.map +1 -0
- package/dist/database.d.ts +13 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +32 -0
- package/dist/database.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +285 -0
- package/dist/index.js.map +1 -0
- package/dist/scripts/task-executor.d.ts +3 -0
- package/dist/scripts/task-executor.d.ts.map +1 -0
- package/dist/scripts/task-executor.js +139 -0
- package/dist/scripts/task-executor.js.map +1 -0
- package/dist/scripts/task-planner.d.ts +3 -0
- package/dist/scripts/task-planner.d.ts.map +1 -0
- package/dist/scripts/task-planner.js +81 -0
- package/dist/scripts/task-planner.js.map +1 -0
- package/dist/services/address-executor.d.ts +13 -0
- package/dist/services/address-executor.d.ts.map +1 -0
- package/dist/services/address-executor.js +202 -0
- package/dist/services/address-executor.js.map +1 -0
- package/dist/services/address-task-executor.d.ts +19 -0
- package/dist/services/address-task-executor.d.ts.map +1 -0
- package/dist/services/address-task-executor.js +736 -0
- package/dist/services/address-task-executor.js.map +1 -0
- package/dist/services/claude-cli-executor.d.ts +14 -0
- package/dist/services/claude-cli-executor.d.ts.map +1 -0
- package/dist/services/claude-cli-executor.js +241 -0
- package/dist/services/claude-cli-executor.js.map +1 -0
- package/dist/services/claude-executor.d.ts +14 -0
- package/dist/services/claude-executor.d.ts.map +1 -0
- package/dist/services/claude-executor.js +274 -0
- package/dist/services/claude-executor.js.map +1 -0
- package/dist/services/claude-planner.d.ts +15 -0
- package/dist/services/claude-planner.d.ts.map +1 -0
- package/dist/services/claude-planner.js +107 -0
- package/dist/services/claude-planner.js.map +1 -0
- package/dist/services/docker-orchestrator.d.ts +11 -0
- package/dist/services/docker-orchestrator.d.ts.map +1 -0
- package/dist/services/docker-orchestrator.js +85 -0
- package/dist/services/docker-orchestrator.js.map +1 -0
- package/dist/services/executor-factory.d.ts +14 -0
- package/dist/services/executor-factory.d.ts.map +1 -0
- package/dist/services/executor-factory.js +14 -0
- package/dist/services/executor-factory.js.map +1 -0
- package/dist/services/git-manager.d.ts +36 -0
- package/dist/services/git-manager.d.ts.map +1 -0
- package/dist/services/git-manager.js +728 -0
- package/dist/services/git-manager.js.map +1 -0
- package/dist/services/index.d.ts +9 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +9 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/job-manager.d.ts +30 -0
- package/dist/services/job-manager.d.ts.map +1 -0
- package/dist/services/job-manager.js +337 -0
- package/dist/services/job-manager.js.map +1 -0
- package/dist/services/openai-service.d.ts +14 -0
- package/dist/services/openai-service.d.ts.map +1 -0
- package/dist/services/openai-service.js +186 -0
- package/dist/services/openai-service.js.map +1 -0
- package/dist/services/pr-service.d.ts +31 -0
- package/dist/services/pr-service.d.ts.map +1 -0
- package/dist/services/pr-service.js +291 -0
- package/dist/services/pr-service.js.map +1 -0
- package/dist/services/repository-manager.d.ts +12 -0
- package/dist/services/repository-manager.d.ts.map +1 -0
- package/dist/services/repository-manager.js +101 -0
- package/dist/services/repository-manager.js.map +1 -0
- package/dist/services/task-executor.d.ts +20 -0
- package/dist/services/task-executor.d.ts.map +1 -0
- package/dist/services/task-executor.js +717 -0
- package/dist/services/task-executor.js.map +1 -0
- package/dist/types/non-interactive-config.d.ts +28 -0
- package/dist/types/non-interactive-config.d.ts.map +1 -0
- package/dist/types/non-interactive-config.js +2 -0
- package/dist/types/non-interactive-config.js.map +1 -0
- package/dist/web-server.d.ts +16 -0
- package/dist/web-server.d.ts.map +1 -0
- package/dist/web-server.js +488 -0
- package/dist/web-server.js.map +1 -0
- package/package.json +71 -0
package/README.md
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
# Ivan š¤
|
|
2
|
+
|
|
3
|
+
## Your AI-Powered Development Assistant
|
|
4
|
+
|
|
5
|
+
Ivan is an intelligent CLI tool that automates complex development workflows by breaking down high-level requests into executable tasks, implementing them with AI assistance, and creating pull requests with properly formatted commits and descriptions.
|
|
6
|
+
|
|
7
|
+
## Key Features
|
|
8
|
+
|
|
9
|
+
- **š§ Intelligent Task Breakdown**: Analyzes your request and automatically breaks it down into manageable, PR-ready tasks
|
|
10
|
+
- **š¤ Flexible Claude Execution**: Choose between SDK (API-based) or CLI (Claude Max) execution modes
|
|
11
|
+
- **š Automated Git Workflow**: Creates branches, commits changes, and opens pull requests automatically
|
|
12
|
+
- **š Smart Commit Messages**: Generates conventional commit messages using OpenAI's GPT-4
|
|
13
|
+
- **š¬ PR Comment Handling**: Automatically addresses PR review comments with `ivan address` command
|
|
14
|
+
- **š Smart Review Requests**: Generates context-specific review instructions for each PR using AI
|
|
15
|
+
- **ā° Optional Review Monitoring**: Can wait 30 minutes after task completion to automatically address incoming PR comments
|
|
16
|
+
- **šÆ Repository-Specific Instructions**: Set coding guidelines and patterns that are automatically applied to every task
|
|
17
|
+
- **š Progress Tracking**: SQLite database tracks all jobs, tasks, execution history, and tool calls
|
|
18
|
+
- **š Web Interface**: Built-in web server to view and monitor jobs and tasks in your browser
|
|
19
|
+
- **ā” Interactive Prompting**: Automatically prompts for missing configuration instead of failing
|
|
20
|
+
|
|
21
|
+
## Prerequisites
|
|
22
|
+
|
|
23
|
+
- Node.js 20+
|
|
24
|
+
- Git repository
|
|
25
|
+
- GitHub CLI (`gh`) installed and authenticated
|
|
26
|
+
- OpenAI API key (for commit messages and PR descriptions)
|
|
27
|
+
- **One of the following**:
|
|
28
|
+
- **SDK Mode**: Anthropic API key (for direct API access)
|
|
29
|
+
- **CLI Mode**: Claude Code CLI installed (for Claude Max users)
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Clone the repository
|
|
35
|
+
git clone https://github.com/yourusername/ivan.git
|
|
36
|
+
cd ivan
|
|
37
|
+
|
|
38
|
+
# Install dependencies
|
|
39
|
+
npm install
|
|
40
|
+
|
|
41
|
+
# Build the project
|
|
42
|
+
npm run build
|
|
43
|
+
|
|
44
|
+
# Link globally for system-wide access
|
|
45
|
+
npm link
|
|
46
|
+
|
|
47
|
+
# Or run directly from the project directory
|
|
48
|
+
node dist/index.js
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Configuration
|
|
52
|
+
|
|
53
|
+
Ivan will automatically prompt for configuration on first use. You can also reconfigure at any time:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Reconfigure API keys and settings
|
|
57
|
+
ivan reconfigure
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Configuration includes:
|
|
61
|
+
- **Executor Type**: Choose between SDK (API-based) or CLI (Claude Max) mode
|
|
62
|
+
- **OpenAI API Key**: For generating commit messages and PR descriptions
|
|
63
|
+
- **Anthropic API Key**: For Claude Code execution (SDK mode only)
|
|
64
|
+
- **Repository Instructions**: Optional coding guidelines specific to each repository
|
|
65
|
+
- **Tool Permissions**: Configure which tools Claude Code can use per repository
|
|
66
|
+
- **Model Selection**: Choose which Claude model to use for tasks
|
|
67
|
+
|
|
68
|
+
Configuration is stored in `~/.ivan/config.json` and the database in `~/.ivan/db.sqlite`
|
|
69
|
+
|
|
70
|
+
### Executor Modes
|
|
71
|
+
|
|
72
|
+
Ivan supports two ways to run Claude Code:
|
|
73
|
+
|
|
74
|
+
#### SDK Mode (Default)
|
|
75
|
+
- Uses the Anthropic API directly via TypeScript SDK
|
|
76
|
+
- Requires an Anthropic API key
|
|
77
|
+
- Best for users with API access
|
|
78
|
+
|
|
79
|
+
#### CLI Mode
|
|
80
|
+
- Uses the Claude Code CLI installed on your machine
|
|
81
|
+
- Perfect for Claude Max subscribers (no API key needed)
|
|
82
|
+
- Provides real-time streaming output
|
|
83
|
+
- Requires Claude Code CLI to be installed
|
|
84
|
+
|
|
85
|
+
**Switch between modes at any time:**
|
|
86
|
+
```bash
|
|
87
|
+
# Configure executor type
|
|
88
|
+
ivan configure-executor
|
|
89
|
+
|
|
90
|
+
# View current executor setting
|
|
91
|
+
ivan show-config
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Usage
|
|
95
|
+
|
|
96
|
+
### Running Tasks
|
|
97
|
+
|
|
98
|
+
Simply run `ivan` in any git repository:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
ivan
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Then describe what you want to accomplish. Ivan will:
|
|
105
|
+
1. Break down your request into individual tasks
|
|
106
|
+
2. Ask if you want to wait for PR reviews after completion
|
|
107
|
+
3. Execute each task using Claude Code
|
|
108
|
+
4. Create pull requests with proper commits and AI-generated review instructions
|
|
109
|
+
5. Optionally wait 30 minutes and automatically address any PR comments
|
|
110
|
+
|
|
111
|
+
### CLI Commands
|
|
112
|
+
|
|
113
|
+
#### Main Commands
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Run Ivan to execute tasks (default command)
|
|
117
|
+
ivan
|
|
118
|
+
|
|
119
|
+
# Reconfigure API keys and settings
|
|
120
|
+
ivan reconfigure
|
|
121
|
+
|
|
122
|
+
# Address PR review comments and failing checks
|
|
123
|
+
ivan address
|
|
124
|
+
|
|
125
|
+
# Start the web interface
|
|
126
|
+
ivan web [--port <port>]
|
|
127
|
+
|
|
128
|
+
# Stop the web interface
|
|
129
|
+
ivan web-stop [--port <port>]
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### Repository Configuration
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# Set or update repository-specific instructions
|
|
136
|
+
ivan edit-repo-instructions
|
|
137
|
+
|
|
138
|
+
# Configure allowed tools for Claude Code in current repository
|
|
139
|
+
ivan config-tools
|
|
140
|
+
|
|
141
|
+
# Show current repository configuration
|
|
142
|
+
ivan show-config
|
|
143
|
+
|
|
144
|
+
# Choose which Claude model to use for tasks
|
|
145
|
+
ivan choose-model
|
|
146
|
+
|
|
147
|
+
# Configure executor type (SDK vs CLI)
|
|
148
|
+
ivan configure-executor
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Addressing PR Comments
|
|
152
|
+
|
|
153
|
+
Automatically handle PR review comments:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Scan all open PRs for unaddressed comments and failing checks
|
|
157
|
+
ivan address
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
This will:
|
|
161
|
+
1. Find all open PRs with unaddressed inline code comments
|
|
162
|
+
2. Let you select which PRs to address
|
|
163
|
+
3. Create tasks for each unaddressed comment
|
|
164
|
+
4. Automatically implement fixes using Claude Code
|
|
165
|
+
5. Commit changes with co-author attribution
|
|
166
|
+
6. Reply to each comment with the commit that fixed it
|
|
167
|
+
7. Add a review request with specific instructions
|
|
168
|
+
|
|
169
|
+
### Example Requests
|
|
170
|
+
|
|
171
|
+
- "Add user authentication with JWT tokens"
|
|
172
|
+
- "Refactor the database module to use TypeScript"
|
|
173
|
+
- "Add comprehensive test coverage for the API endpoints"
|
|
174
|
+
- "Implement a caching layer with Redis"
|
|
175
|
+
- "Fix all ESLint warnings and add proper error handling"
|
|
176
|
+
|
|
177
|
+
### Web Interface
|
|
178
|
+
|
|
179
|
+
Start the web server to monitor jobs and tasks:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# Start web server on default port 3000
|
|
183
|
+
ivan web
|
|
184
|
+
|
|
185
|
+
# Or specify a custom port
|
|
186
|
+
ivan web --port 8080
|
|
187
|
+
|
|
188
|
+
# Stop the web server
|
|
189
|
+
ivan web-stop
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Then open http://localhost:3000 in your browser to see:
|
|
193
|
+
- All jobs and their status
|
|
194
|
+
- Individual task progress
|
|
195
|
+
- Execution logs
|
|
196
|
+
- Pull request links
|
|
197
|
+
|
|
198
|
+
### Repository-Specific Instructions
|
|
199
|
+
|
|
200
|
+
Set coding guidelines that will be automatically applied to every task:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
# Set or update repository instructions
|
|
204
|
+
ivan edit-repo-instructions
|
|
205
|
+
|
|
206
|
+
# Instructions can include:
|
|
207
|
+
- Coding style preferences
|
|
208
|
+
- Framework-specific patterns
|
|
209
|
+
- Testing requirements
|
|
210
|
+
- Documentation standards
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**Note**: Ivan will prompt for instructions the first time you use it in a repository. If you decline, it won't ask again, but you can always configure them later using `ivan edit-repo-instructions`.
|
|
214
|
+
|
|
215
|
+
### Tool Configuration
|
|
216
|
+
|
|
217
|
+
Control which tools Claude Code can use in your repository:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
# Configure allowed tools
|
|
221
|
+
ivan config-tools
|
|
222
|
+
|
|
223
|
+
# View current configuration
|
|
224
|
+
ivan show-config
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
By default, all tools are allowed. You can restrict to specific tools like `["Bash", "Read", "Write", "Edit"]` for enhanced security.
|
|
228
|
+
|
|
229
|
+
### Model Selection
|
|
230
|
+
|
|
231
|
+
Choose which Claude model to use for task execution:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
# Select a Claude model
|
|
235
|
+
ivan choose-model
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Available models:
|
|
239
|
+
- **Claude Sonnet 4**: Default, balanced performance
|
|
240
|
+
- **Claude 3.5 Haiku**: Faster, good for simpler tasks
|
|
241
|
+
- **Claude Opus 4.1**: Most capable, but slower
|
|
242
|
+
|
|
243
|
+
## How It Works
|
|
244
|
+
|
|
245
|
+
### Standard Workflow
|
|
246
|
+
1. **Task Analysis**: Claude Code analyzes your request and breaks it into PR-ready tasks
|
|
247
|
+
2. **Review Options**: Asks if you want to wait for PR reviews (optional)
|
|
248
|
+
3. **Branch Creation**: Creates a new branch for each task (`ivan/task-description-timestamp`)
|
|
249
|
+
4. **Code Implementation**: Claude Code implements the changes using your repository context
|
|
250
|
+
5. **Smart Commits**: Generates conventional commit messages based on the actual changes
|
|
251
|
+
6. **Pull Request**: Creates a PR with detailed description and AI-generated review instructions
|
|
252
|
+
7. **Review Monitoring** (optional): Waits 30 minutes for reviews, then automatically addresses comments
|
|
253
|
+
8. **Cleanup**: Returns to main branch and syncs with upstream
|
|
254
|
+
|
|
255
|
+
### Address Workflow
|
|
256
|
+
1. **PR Scanning**: Finds all open PRs with unaddressed comments or failing checks
|
|
257
|
+
2. **Comment Detection**: Uses GitHub GraphQL API to find unresolved inline code comments
|
|
258
|
+
3. **Task Creation**: Creates address tasks for each comment with proper branch tracking
|
|
259
|
+
4. **Automated Fixes**: Implements fixes using Claude Code with repository context
|
|
260
|
+
5. **Smart Replies**: Replies to each comment with the commit that addressed it
|
|
261
|
+
6. **Review Requests**: Adds context-specific review instructions based on changes
|
|
262
|
+
|
|
263
|
+
## Architecture
|
|
264
|
+
|
|
265
|
+
```
|
|
266
|
+
ivan/
|
|
267
|
+
āāā src/
|
|
268
|
+
ā āāā database/ # SQLite schema and migrations
|
|
269
|
+
ā āāā services/ # Core services
|
|
270
|
+
ā ā āāā claude-executor.ts # Claude Code SDK integration
|
|
271
|
+
ā ā āāā claude-cli-executor.ts # Claude Code CLI integration
|
|
272
|
+
ā ā āāā executor-factory.ts # Executor selection logic
|
|
273
|
+
ā ā āāā openai-service.ts # OpenAI API for commits/PRs
|
|
274
|
+
ā ā āāā job-manager.ts # Job and task management
|
|
275
|
+
ā ā āāā git-manager.ts # Git operations and GitHub CLI
|
|
276
|
+
ā ā āāā task-executor.ts # Main workflow orchestration
|
|
277
|
+
ā ā āāā address-executor.ts # PR comment addressing workflow
|
|
278
|
+
ā ā āāā address-task-executor.ts # Individual comment fix execution
|
|
279
|
+
ā ā āāā pr-service.ts # PR comment and check detection
|
|
280
|
+
ā āāā config.ts # Configuration management
|
|
281
|
+
ā āāā web-server.ts # Web interface server
|
|
282
|
+
ā āāā index.ts # CLI entry point
|
|
283
|
+
āāā dist/ # Compiled JavaScript
|
|
284
|
+
āāā ~/.ivan/ # User configuration and database
|
|
285
|
+
āāā config.json # API keys and settings (includes executorType)
|
|
286
|
+
āāā db.sqlite # Jobs and tasks database
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Database Schema
|
|
290
|
+
|
|
291
|
+
Ivan maintains a local SQLite database to track:
|
|
292
|
+
- **Jobs**: High-level user requests with timestamps and status
|
|
293
|
+
- **Tasks**: Individual tasks within a job, including:
|
|
294
|
+
- Task description
|
|
295
|
+
- Task type (build or address)
|
|
296
|
+
- Execution status (not_started, active, completed)
|
|
297
|
+
- Branch name tracking
|
|
298
|
+
- Pull request links
|
|
299
|
+
- Execution logs with tool calls
|
|
300
|
+
- Timestamps
|
|
301
|
+
|
|
302
|
+
## Development
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
# Run in development mode
|
|
306
|
+
npm run dev
|
|
307
|
+
|
|
308
|
+
# Watch mode for development
|
|
309
|
+
npm run watch
|
|
310
|
+
|
|
311
|
+
# Run linter
|
|
312
|
+
npm run lint
|
|
313
|
+
|
|
314
|
+
# Type checking
|
|
315
|
+
npm run typecheck
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## Advanced Features
|
|
319
|
+
|
|
320
|
+
### Execution Logs
|
|
321
|
+
- All Claude Code interactions are logged with tool calls
|
|
322
|
+
- Each response is separated with visual dividers for readability
|
|
323
|
+
- Tool inputs and outputs are captured for debugging
|
|
324
|
+
- Logs are stored in the database for each task
|
|
325
|
+
|
|
326
|
+
### Smart Review Comments
|
|
327
|
+
- PRs are created with AI-generated review instructions
|
|
328
|
+
- Review comments are specific to the changes made
|
|
329
|
+
- Uses GPT-4o-mini to analyze diffs and generate contextual review requests
|
|
330
|
+
- Replies to PR comments include "Ivan:" prefix for clear attribution
|
|
331
|
+
|
|
332
|
+
### Comment Detection
|
|
333
|
+
- Uses GitHub GraphQL API to detect resolved status
|
|
334
|
+
- Only processes unresolved inline code comments
|
|
335
|
+
- Ignores top-level PR comments
|
|
336
|
+
- Skips comments that already have replies
|
|
337
|
+
|
|
338
|
+
## Security Considerations
|
|
339
|
+
|
|
340
|
+
- API keys are stored locally in `~/.ivan/config.json`
|
|
341
|
+
- No credentials are stored in the database
|
|
342
|
+
- Configuration prompts mask API key input
|
|
343
|
+
- Each task runs in the local environment with your git credentials
|
|
344
|
+
- GitHub CLI authentication is used for PR creation
|
|
345
|
+
|
|
346
|
+
## Limitations
|
|
347
|
+
|
|
348
|
+
- Requires GitHub CLI (`gh`) for pull request creation
|
|
349
|
+
- Works with GitHub repositories (GitLab/Bitbucket support planned)
|
|
350
|
+
- Tasks must be completable by Claude Code
|
|
351
|
+
- Requires active internet connection for AI services
|
|
352
|
+
|
|
353
|
+
## Contributing
|
|
354
|
+
|
|
355
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
356
|
+
|
|
357
|
+
## License
|
|
358
|
+
|
|
359
|
+
MIT
|
|
360
|
+
|
|
361
|
+
## Support
|
|
362
|
+
|
|
363
|
+
For issues, questions, or suggestions, please open an issue on GitHub.
|
|
364
|
+
|
|
365
|
+
## Troubleshooting
|
|
366
|
+
|
|
367
|
+
### Common Issues
|
|
368
|
+
|
|
369
|
+
**GitHub CLI not authenticated:**
|
|
370
|
+
```bash
|
|
371
|
+
gh auth login
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
**API keys not working:**
|
|
375
|
+
```bash
|
|
376
|
+
ivan reconfigure
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
**Claude CLI not found (CLI mode):**
|
|
380
|
+
```bash
|
|
381
|
+
# Install Claude Code CLI first
|
|
382
|
+
# See: https://docs.claude.com/en/docs/claude-code/installation
|
|
383
|
+
|
|
384
|
+
# Then configure Ivan to use CLI mode
|
|
385
|
+
ivan configure-executor
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
**Executor hanging or not showing output (CLI mode):**
|
|
389
|
+
- Ensure you're using the latest version of Claude Code CLI
|
|
390
|
+
- Try switching to SDK mode with `ivan configure-executor`
|
|
391
|
+
- Check that `claude --print` works independently
|
|
392
|
+
|
|
393
|
+
**Want to switch between SDK and CLI mode:**
|
|
394
|
+
```bash
|
|
395
|
+
# Switch executor type
|
|
396
|
+
ivan configure-executor
|
|
397
|
+
|
|
398
|
+
# View current configuration
|
|
399
|
+
ivan show-config
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
**Permission denied errors:**
|
|
403
|
+
- Ensure you have write access to the repository
|
|
404
|
+
- Check that your SSH keys are properly configured
|
|
405
|
+
|
|
406
|
+
**Web server issues:**
|
|
407
|
+
- Check if port is already in use
|
|
408
|
+
- Try a different port with `--port` flag
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
Built with ā¤ļø to make AI-powered development workflows more efficient and automated.
|
package/dist/agent.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IvanConfig } from './config/config.js';
|
|
2
|
+
import { DatabaseManager } from './database/database.js';
|
|
3
|
+
export declare class OrchestrationAgent {
|
|
4
|
+
private config;
|
|
5
|
+
private dbManager;
|
|
6
|
+
private claudePlanner;
|
|
7
|
+
private jobManager;
|
|
8
|
+
constructor(config: IvanConfig, dbManager: DatabaseManager);
|
|
9
|
+
executeTask(task: string): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAMzD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,UAAU,CAAa;gBAEnB,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,eAAe;IAO7C,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CA8CtD"}
|
package/dist/agent.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ClaudePlannerService } from './services/claude-planner.js';
|
|
2
|
+
import { JobManager } from './services/job-manager.js';
|
|
3
|
+
import { DockerOrchestrator } from './services/docker-orchestrator.js';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
export class OrchestrationAgent {
|
|
6
|
+
config;
|
|
7
|
+
dbManager;
|
|
8
|
+
claudePlanner;
|
|
9
|
+
jobManager;
|
|
10
|
+
constructor(config, dbManager) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
this.dbManager = dbManager;
|
|
13
|
+
this.claudePlanner = new ClaudePlannerService(config.repository, config.anthropicApiKey);
|
|
14
|
+
this.jobManager = new JobManager(dbManager.getDatabase());
|
|
15
|
+
}
|
|
16
|
+
async executeTask(task) {
|
|
17
|
+
console.log(chalk.gray('\nš Task:'), task);
|
|
18
|
+
console.log(chalk.gray('ā'.repeat(50)));
|
|
19
|
+
try {
|
|
20
|
+
// Step 1: Plan tasks with Claude
|
|
21
|
+
const taskPlan = await this.claudePlanner.planTasks(task);
|
|
22
|
+
// Step 2: Create job and tasks in database
|
|
23
|
+
const jobId = await this.jobManager.createJob(task, `User request: ${task}`, this.config.repository);
|
|
24
|
+
await this.jobManager.createTasks(jobId, taskPlan.tasks);
|
|
25
|
+
// Step 3: Update job status to in_progress
|
|
26
|
+
await this.jobManager.updateJobStatus(jobId, 'in_progress');
|
|
27
|
+
// Step 4: Run tasks in Docker containers
|
|
28
|
+
const orchestrator = new DockerOrchestrator(this.jobManager, this.config.repository, this.config.openAiApiKey);
|
|
29
|
+
await orchestrator.runAllTasks(jobId);
|
|
30
|
+
// Step 5: Update job status to completed
|
|
31
|
+
const tasks = await this.jobManager.getJobTasks(jobId);
|
|
32
|
+
const allCompleted = tasks.every(t => t.status === 'completed');
|
|
33
|
+
if (allCompleted) {
|
|
34
|
+
await this.jobManager.updateJobStatus(jobId, 'completed');
|
|
35
|
+
console.log(chalk.green(`\nā
Job #${jobId} completed successfully!`));
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
await this.jobManager.updateJobStatus(jobId, 'failed');
|
|
39
|
+
console.log(chalk.yellow(`\nā ļø Job #${jobId} completed with some failed tasks`));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
console.error(chalk.red('\nā Task execution failed:'), error);
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,OAAO,kBAAkB;IACrB,MAAM,CAAa;IACnB,SAAS,CAAkB;IAC3B,aAAa,CAAuB;IACpC,UAAU,CAAa;IAE/B,YAAY,MAAkB,EAAE,SAA0B;QACxD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,aAAa,GAAG,IAAI,oBAAoB,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;QACzF,IAAI,CAAC,UAAU,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5D,CAAC;IAEM,KAAK,CAAC,WAAW,CAAC,IAAY;QACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAExC,IAAI,CAAC;YACH,iCAAiC;YACjC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAE1D,2CAA2C;YAC3C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAC3C,IAAI,EACJ,iBAAiB,IAAI,EAAE,EACvB,IAAI,CAAC,MAAM,CAAC,UAAU,CACvB,CAAC;YAEF,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;YAEzD,2CAA2C;YAC3C,MAAM,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;YAE5D,yCAAyC;YACzC,MAAM,YAAY,GAAG,IAAI,kBAAkB,CACzC,IAAI,CAAC,UAAU,EACf,IAAI,CAAC,MAAM,CAAC,UAAU,EACtB,IAAI,CAAC,MAAM,CAAC,YAAY,CACzB,CAAC;YAEF,MAAM,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAEtC,yCAAyC;YACzC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACvD,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;YAEhE,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;gBAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,KAAK,0BAA0B,CAAC,CAAC,CAAC;YACxE,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBACvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,KAAK,mCAAmC,CAAC,CAAC,CAAC;YACpF,CAAC;QAEH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,4BAA4B,CAAC,EAAE,KAAK,CAAC,CAAC;YAC9D,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DatabaseManager } from '../database/database.js';
|
|
2
|
+
export interface IvanConfig {
|
|
3
|
+
openAiApiKey: string;
|
|
4
|
+
anthropicApiKey: string;
|
|
5
|
+
repository: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class ConfigManager {
|
|
8
|
+
private configDir;
|
|
9
|
+
private configPath;
|
|
10
|
+
private dbManager;
|
|
11
|
+
constructor();
|
|
12
|
+
initialize(): Promise<IvanConfig>;
|
|
13
|
+
private loadConfig;
|
|
14
|
+
private saveConfig;
|
|
15
|
+
getConfig(): IvanConfig | null;
|
|
16
|
+
getDatabase(): DatabaseManager;
|
|
17
|
+
forceReconfigure(): Promise<IvanConfig>;
|
|
18
|
+
private checkClaudeCodeInstallation;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAI1D,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAkB;;IAQtB,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC;IA2E9C,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,UAAU;IAQX,SAAS,IAAI,UAAU,GAAG,IAAI;IAI9B,WAAW,IAAI,eAAe;IAIxB,gBAAgB,IAAI,OAAO,CAAC,UAAU,CAAC;YAiEtC,2BAA2B;CAyB1C"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as os from 'os';
|
|
4
|
+
import { exec } from 'child_process';
|
|
5
|
+
import { promisify } from 'util';
|
|
6
|
+
import inquirer from 'inquirer';
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import { DatabaseManager } from '../database/database.js';
|
|
9
|
+
const execAsync = promisify(exec);
|
|
10
|
+
export class ConfigManager {
|
|
11
|
+
configDir;
|
|
12
|
+
configPath;
|
|
13
|
+
dbManager;
|
|
14
|
+
constructor() {
|
|
15
|
+
this.configDir = path.join(os.homedir(), '.ivan');
|
|
16
|
+
this.configPath = path.join(this.configDir, 'config.json');
|
|
17
|
+
this.dbManager = new DatabaseManager();
|
|
18
|
+
}
|
|
19
|
+
async initialize() {
|
|
20
|
+
await this.dbManager.initialize();
|
|
21
|
+
const existingConfig = this.loadConfig();
|
|
22
|
+
if (existingConfig) {
|
|
23
|
+
console.log(chalk.green('ā Configuration found!'));
|
|
24
|
+
return existingConfig;
|
|
25
|
+
}
|
|
26
|
+
console.log(chalk.cyan('\nš¤ Welcome to Ivan - Your Coding Orchestration Agent\n'));
|
|
27
|
+
console.log(chalk.yellow('Let\'s set up your configuration...\n'));
|
|
28
|
+
await this.checkClaudeCodeInstallation();
|
|
29
|
+
await this.dbManager.initialize();
|
|
30
|
+
const answers = await inquirer.prompt([
|
|
31
|
+
{
|
|
32
|
+
type: 'input',
|
|
33
|
+
name: 'repository',
|
|
34
|
+
message: 'Enter the SSH repository URL (e.g., git@github.com:user/repo.git):',
|
|
35
|
+
validate: (input) => {
|
|
36
|
+
if (!input || input.trim() === '') {
|
|
37
|
+
return 'Repository URL is required';
|
|
38
|
+
}
|
|
39
|
+
const trimmed = input.trim();
|
|
40
|
+
const sshUrlPattern = /^git@[\w.-]+:[\w.-]+\/[\w.-]+\.git$/;
|
|
41
|
+
if (!sshUrlPattern.test(trimmed)) {
|
|
42
|
+
return 'Please enter a valid SSH repository URL (e.g., git@github.com:user/repo.git)';
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
},
|
|
46
|
+
filter: (input) => input.trim()
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
type: 'password',
|
|
50
|
+
name: 'openAiApiKey',
|
|
51
|
+
message: 'Enter your OpenAI API key (for commit messages):',
|
|
52
|
+
mask: '*',
|
|
53
|
+
validate: (input) => {
|
|
54
|
+
if (!input || input.trim() === '') {
|
|
55
|
+
return 'OpenAI API key is required';
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
type: 'password',
|
|
62
|
+
name: 'anthropicApiKey',
|
|
63
|
+
message: 'Enter your Anthropic API key (for task planning):',
|
|
64
|
+
mask: '*',
|
|
65
|
+
validate: (input) => {
|
|
66
|
+
if (!input || input.trim() === '') {
|
|
67
|
+
return 'Anthropic API key is required';
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
]);
|
|
73
|
+
const config = {
|
|
74
|
+
repository: answers.repository,
|
|
75
|
+
openAiApiKey: answers.openAiApiKey,
|
|
76
|
+
anthropicApiKey: answers.anthropicApiKey
|
|
77
|
+
};
|
|
78
|
+
this.saveConfig(config);
|
|
79
|
+
console.log(chalk.green('\nā Configuration saved successfully!\n'));
|
|
80
|
+
return config;
|
|
81
|
+
}
|
|
82
|
+
loadConfig() {
|
|
83
|
+
try {
|
|
84
|
+
if (fs.existsSync(this.configPath)) {
|
|
85
|
+
const configData = fs.readFileSync(this.configPath, 'utf-8');
|
|
86
|
+
return JSON.parse(configData);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.error(chalk.red('Error loading configuration:'), error);
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
saveConfig(config) {
|
|
95
|
+
if (!fs.existsSync(this.configDir)) {
|
|
96
|
+
fs.mkdirSync(this.configDir, { recursive: true });
|
|
97
|
+
}
|
|
98
|
+
fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2));
|
|
99
|
+
}
|
|
100
|
+
getConfig() {
|
|
101
|
+
return this.loadConfig();
|
|
102
|
+
}
|
|
103
|
+
getDatabase() {
|
|
104
|
+
return this.dbManager;
|
|
105
|
+
}
|
|
106
|
+
async forceReconfigure() {
|
|
107
|
+
console.log(chalk.cyan('\nš§ Reconfiguring Ivan...\n'));
|
|
108
|
+
await this.dbManager.initialize();
|
|
109
|
+
await this.checkClaudeCodeInstallation();
|
|
110
|
+
const answers = await inquirer.prompt([
|
|
111
|
+
{
|
|
112
|
+
type: 'input',
|
|
113
|
+
name: 'repository',
|
|
114
|
+
message: 'Enter the SSH repository URL (e.g., git@github.com:user/repo.git):',
|
|
115
|
+
validate: (input) => {
|
|
116
|
+
if (!input || input.trim() === '') {
|
|
117
|
+
return 'Repository URL is required';
|
|
118
|
+
}
|
|
119
|
+
const trimmed = input.trim();
|
|
120
|
+
const sshUrlPattern = /^git@[\w.-]+:[\w.-]+\/[\w.-]+\.git$/;
|
|
121
|
+
if (!sshUrlPattern.test(trimmed)) {
|
|
122
|
+
return 'Please enter a valid SSH repository URL (e.g., git@github.com:user/repo.git)';
|
|
123
|
+
}
|
|
124
|
+
return true;
|
|
125
|
+
},
|
|
126
|
+
filter: (input) => input.trim()
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
type: 'password',
|
|
130
|
+
name: 'openAiApiKey',
|
|
131
|
+
message: 'Enter your OpenAI API key (for commit messages):',
|
|
132
|
+
mask: '*',
|
|
133
|
+
validate: (input) => {
|
|
134
|
+
if (!input || input.trim() === '') {
|
|
135
|
+
return 'OpenAI API key is required';
|
|
136
|
+
}
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
type: 'password',
|
|
142
|
+
name: 'anthropicApiKey',
|
|
143
|
+
message: 'Enter your Anthropic API key (for task planning):',
|
|
144
|
+
mask: '*',
|
|
145
|
+
validate: (input) => {
|
|
146
|
+
if (!input || input.trim() === '') {
|
|
147
|
+
return 'Anthropic API key is required';
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
]);
|
|
153
|
+
const config = {
|
|
154
|
+
repository: answers.repository,
|
|
155
|
+
openAiApiKey: answers.openAiApiKey,
|
|
156
|
+
anthropicApiKey: answers.anthropicApiKey
|
|
157
|
+
};
|
|
158
|
+
this.saveConfig(config);
|
|
159
|
+
console.log(chalk.green('\nā Configuration updated successfully!\n'));
|
|
160
|
+
return config;
|
|
161
|
+
}
|
|
162
|
+
async checkClaudeCodeInstallation() {
|
|
163
|
+
try {
|
|
164
|
+
console.log(chalk.gray('š Checking for Claude Code installation...'));
|
|
165
|
+
const { stdout } = await execAsync('claude --version');
|
|
166
|
+
console.log(chalk.green('ā Claude Code is installed'));
|
|
167
|
+
console.log(chalk.gray(` Version: ${stdout.trim()}\n`));
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
console.log(chalk.red('ā Claude Code not found'));
|
|
171
|
+
console.log(chalk.yellow(' Please install Claude Code from: https://docs.anthropic.com/en/docs/claude-code\n'));
|
|
172
|
+
const { continueAnyway } = await inquirer.prompt([
|
|
173
|
+
{
|
|
174
|
+
type: 'confirm',
|
|
175
|
+
name: 'continueAnyway',
|
|
176
|
+
message: 'Continue setup without Claude Code?',
|
|
177
|
+
default: false
|
|
178
|
+
}
|
|
179
|
+
]);
|
|
180
|
+
if (!continueAnyway) {
|
|
181
|
+
console.log(chalk.yellow('\nš Setup cancelled. Install Claude Code and try again.\n'));
|
|
182
|
+
process.exit(0);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=config.js.map
|