developer-ai 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 +241 -0
- package/bin/developer-ai.js +2 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +219 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +82 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/schema.d.ts +115 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +29 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/constants.d.ts +8 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +8 -0
- package/dist/constants.js.map +1 -0
- package/dist/core/agent.d.ts +38 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +155 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/system-prompt.d.ts +6 -0
- package/dist/core/system-prompt.d.ts.map +1 -0
- package/dist/core/system-prompt.js +44 -0
- package/dist/core/system-prompt.js.map +1 -0
- package/dist/core/types.d.ts +42 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +6 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/client.d.ts +13 -0
- package/dist/mcp/client.d.ts.map +1 -0
- package/dist/mcp/client.js +202 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/providers/ollama.d.ts +13 -0
- package/dist/providers/ollama.d.ts.map +1 -0
- package/dist/providers/ollama.js +60 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/openai.d.ts +9 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +40 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/skills/loader.d.ts +25 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +93 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/tests/tools.test.d.ts +2 -0
- package/dist/tests/tools.test.d.ts.map +1 -0
- package/dist/tests/tools.test.js +170 -0
- package/dist/tests/tools.test.js.map +1 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +19 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list-files.d.ts +3 -0
- package/dist/tools/list-files.d.ts.map +1 -0
- package/dist/tools/list-files.js +60 -0
- package/dist/tools/list-files.js.map +1 -0
- package/dist/tools/read-file.d.ts +3 -0
- package/dist/tools/read-file.d.ts.map +1 -0
- package/dist/tools/read-file.js +46 -0
- package/dist/tools/read-file.js.map +1 -0
- package/dist/tools/registry.d.ts +24 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +37 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/run-command.d.ts +3 -0
- package/dist/tools/run-command.d.ts.map +1 -0
- package/dist/tools/run-command.js +114 -0
- package/dist/tools/run-command.js.map +1 -0
- package/dist/tools/search-text.d.ts +3 -0
- package/dist/tools/search-text.d.ts.map +1 -0
- package/dist/tools/search-text.js +103 -0
- package/dist/tools/search-text.js.map +1 -0
- package/dist/tools/utils.d.ts +6 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +14 -0
- package/dist/tools/utils.js.map +1 -0
- package/dist/tools/web-search.d.ts +3 -0
- package/dist/tools/web-search.d.ts.map +1 -0
- package/dist/tools/web-search.js +80 -0
- package/dist/tools/web-search.js.map +1 -0
- package/dist/tools/write-file.d.ts +3 -0
- package/dist/tools/write-file.d.ts.map +1 -0
- package/dist/tools/write-file.js +66 -0
- package/dist/tools/write-file.js.map +1 -0
- package/package.json +54 -0
- package/skills/accessibility/SKILL.md +496 -0
- package/skills/api-design/SKILL.md +419 -0
- package/skills/code-review/SKILL.md +267 -0
- package/skills/debugging/SKILL.md +332 -0
- package/skills/documentation/SKILL.md +496 -0
- package/skills/error-handling/SKILL.md +504 -0
- package/skills/git-workflow/SKILL.md +448 -0
- package/skills/human-like-coding/SKILL.md +400 -0
- package/skills/performance-optimization/SKILL.md +412 -0
- package/skills/prompt-engineering/SKILL.md +362 -0
- package/skills/refactoring/SKILL.md +457 -0
- package/skills/security-audit/SKILL.md +453 -0
- package/skills/testing-strategy/SKILL.md +501 -0
- package/skills/webapp-testing/SKILL.md +309 -0
package/README.md
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# Developer-AI
|
|
2
|
+
|
|
3
|
+
A production-grade, terminal-based AI coding assistant. Think of it as GitHub Copilot for your terminal — it reads and writes files, runs commands, searches your codebase, and iterates on tasks using structured tool calls.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Interactive REPL** — chat with the agent in your terminal
|
|
8
|
+
- **One-shot mode** — pass an instruction as an argument
|
|
9
|
+
- **Multi-provider** — OpenAI (cloud) or Ollama (local)
|
|
10
|
+
- **Tool-driven agent** — structured tool calls for file I/O, shell commands, text search
|
|
11
|
+
- **MCP support** — connect Model Context Protocol servers for additional tools
|
|
12
|
+
- **Web search** — Brave Search or Serper integration
|
|
13
|
+
- **Agent Skills** — loads SKILL.md files for domain-specific guidance
|
|
14
|
+
- **Safety first** — path sandboxing, command allowlists, confirmation prompts
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Install globally
|
|
20
|
+
npm install -g developer-ai
|
|
21
|
+
|
|
22
|
+
# First-time setup
|
|
23
|
+
developer-ai onboard
|
|
24
|
+
|
|
25
|
+
# Interactive mode
|
|
26
|
+
developer-ai
|
|
27
|
+
|
|
28
|
+
# One-shot mode
|
|
29
|
+
developer-ai "Create a landing page for an AI startup called Inferencia"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
### From npm
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install -g developer-ai
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### From source
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
git clone https://github.com/your-username/developer-ai.git
|
|
44
|
+
cd developer-ai/coder
|
|
45
|
+
npm install
|
|
46
|
+
npm run build
|
|
47
|
+
npm link # makes `developer-ai` available globally
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Configuration
|
|
51
|
+
|
|
52
|
+
### Onboarding
|
|
53
|
+
|
|
54
|
+
Run `developer-ai onboard` to set up:
|
|
55
|
+
1. **Provider** — choose between Ollama (local) or OpenAI (cloud)
|
|
56
|
+
2. **API key** — for OpenAI (stored in `~/.developer-ai/config.json` with 0600 permissions)
|
|
57
|
+
3. **Web search** — optional Brave Search or Serper API key
|
|
58
|
+
|
|
59
|
+
### Config File
|
|
60
|
+
|
|
61
|
+
Located at `~/.developer-ai/config.json`:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"provider": "openai",
|
|
66
|
+
"openai": {
|
|
67
|
+
"apiKey": "sk-...",
|
|
68
|
+
"model": "gpt-4o"
|
|
69
|
+
},
|
|
70
|
+
"ollama": {
|
|
71
|
+
"model": "llama3.1",
|
|
72
|
+
"baseUrl": "http://localhost:11434"
|
|
73
|
+
},
|
|
74
|
+
"webSearch": {
|
|
75
|
+
"provider": "brave",
|
|
76
|
+
"braveApiKey": "BSA..."
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Environment Variables
|
|
82
|
+
|
|
83
|
+
Environment variables override config file values:
|
|
84
|
+
|
|
85
|
+
| Variable | Description |
|
|
86
|
+
|----------|-------------|
|
|
87
|
+
| `OPENAI_API_KEY` | OpenAI API key (auto-selects OpenAI provider) |
|
|
88
|
+
| `OPENAI_MODEL` | OpenAI model override |
|
|
89
|
+
| `OLLAMA_MODEL` | Ollama model name |
|
|
90
|
+
| `OLLAMA_BASE_URL` | Ollama server URL |
|
|
91
|
+
| `BRAVE_SEARCH_API_KEY` | Brave Search API key |
|
|
92
|
+
| `SERPER_API_KEY` | Serper.dev API key |
|
|
93
|
+
|
|
94
|
+
## Providers
|
|
95
|
+
|
|
96
|
+
### OpenAI
|
|
97
|
+
|
|
98
|
+
Uses the official `openai` Node.js SDK. Requires an API key.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
export OPENAI_API_KEY=sk-...
|
|
102
|
+
developer-ai "Explain this codebase"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Ollama
|
|
106
|
+
|
|
107
|
+
Connects to a local Ollama instance via HTTP. No API key needed.
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Make sure Ollama is running
|
|
111
|
+
ollama serve
|
|
112
|
+
|
|
113
|
+
# Use a specific model
|
|
114
|
+
export OLLAMA_MODEL=qwen2.5:14b
|
|
115
|
+
developer-ai
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Tools
|
|
119
|
+
|
|
120
|
+
The agent has access to these tools:
|
|
121
|
+
|
|
122
|
+
| Tool | Description |
|
|
123
|
+
|------|-------------|
|
|
124
|
+
| `read_file` | Read a file from the workspace |
|
|
125
|
+
| `write_file` | Create or update a file (with overwrite confirmation) |
|
|
126
|
+
| `list_files` | List directory contents with glob filtering |
|
|
127
|
+
| `search_text` | Search across files with string or regex |
|
|
128
|
+
| `run_command` | Execute shell commands (with safety gates) |
|
|
129
|
+
| `web_search` | Search the web via Brave or Serper |
|
|
130
|
+
|
|
131
|
+
### Safety
|
|
132
|
+
|
|
133
|
+
- **Path sandboxing** — all file operations are restricted to the workspace directory
|
|
134
|
+
- **Command allowlist** — safe commands (`ls`, `cat`, `npm`, `git`, etc.) run automatically; others require confirmation
|
|
135
|
+
- **Dangerous command detection** — patterns like `rm -rf`, `curl | sh`, etc. are always flagged
|
|
136
|
+
- **Overwrite protection** — existing files require explicit confirmation
|
|
137
|
+
|
|
138
|
+
## MCP (Model Context Protocol)
|
|
139
|
+
|
|
140
|
+
Developer-AI supports MCP servers, exposing their tools to the agent with namespaced names.
|
|
141
|
+
|
|
142
|
+
### Configuration
|
|
143
|
+
|
|
144
|
+
Create `~/.developer-ai/mcp.json` (global) or `.developer-ai/mcp.json` (per-project):
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"servers": {
|
|
149
|
+
"filesystem": {
|
|
150
|
+
"command": "npx",
|
|
151
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"],
|
|
152
|
+
"env": {}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
MCP tools appear as `mcp_<server>_<tool>` in the agent's tool registry.
|
|
159
|
+
|
|
160
|
+
## Skills
|
|
161
|
+
|
|
162
|
+
Developer-AI loads SKILL.md files to provide domain-specific guidance. Skills are matched to queries using lightweight keyword scoring.
|
|
163
|
+
|
|
164
|
+
### Bundled Skills
|
|
165
|
+
|
|
166
|
+
The package includes skills for: accessibility, API design, code review, debugging, documentation, error handling, git workflow, human-like coding, performance optimization, prompt engineering, refactoring, security audit, testing strategy, and webapp testing.
|
|
167
|
+
|
|
168
|
+
### Skill Locations (priority order)
|
|
169
|
+
|
|
170
|
+
1. Package built-in: `<package>/skills/`
|
|
171
|
+
2. Workspace: `.github/skills/`
|
|
172
|
+
3. Workspace: `skills/`
|
|
173
|
+
|
|
174
|
+
## CLI Reference
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
Usage: developer-ai [options] [command] [instruction...]
|
|
178
|
+
|
|
179
|
+
Terminal-based AI coding assistant.
|
|
180
|
+
|
|
181
|
+
Arguments:
|
|
182
|
+
instruction One-shot instruction (non-interactive)
|
|
183
|
+
|
|
184
|
+
Options:
|
|
185
|
+
-V, --version output the version number
|
|
186
|
+
--yes Auto-confirm all prompts (non-interactive)
|
|
187
|
+
--allow-dangerous Allow dangerous commands without confirmation
|
|
188
|
+
-h, --help display help for command
|
|
189
|
+
|
|
190
|
+
Commands:
|
|
191
|
+
onboard Configure provider, API keys, and web search
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Development
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
cd coder
|
|
198
|
+
npm install
|
|
199
|
+
npm run build # Compile TypeScript → dist/
|
|
200
|
+
npm run lint # Type-check without emitting
|
|
201
|
+
npm test # Run test suite
|
|
202
|
+
npm run dev # Watch mode
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Example Session
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
$ developer-ai "Create a website named inferencia, which is AI service providing agency"
|
|
209
|
+
|
|
210
|
+
Processing...
|
|
211
|
+
|
|
212
|
+
✓ [write_file] index.html
|
|
213
|
+
✓ [write_file] styles.css
|
|
214
|
+
✓ [write_file] script.js
|
|
215
|
+
|
|
216
|
+
I've created a complete website for Inferencia with 3 files:
|
|
217
|
+
|
|
218
|
+
1. **index.html** — Main page with hero, services, about, team, and contact sections
|
|
219
|
+
2. **styles.css** — Modern responsive styling with dark theme
|
|
220
|
+
3. **script.js** — Smooth scrolling, animations, mobile menu, and contact form
|
|
221
|
+
|
|
222
|
+
Open `index.html` in your browser to preview.
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Troubleshooting
|
|
226
|
+
|
|
227
|
+
### "OpenAI API key not configured"
|
|
228
|
+
Run `developer-ai onboard` or set `OPENAI_API_KEY` environment variable.
|
|
229
|
+
|
|
230
|
+
### "Ollama API error"
|
|
231
|
+
Make sure Ollama is running (`ollama serve`) and the model is pulled (`ollama pull llama3.1`).
|
|
232
|
+
|
|
233
|
+
### "Web search not configured"
|
|
234
|
+
Web search is optional. Set `BRAVE_SEARCH_API_KEY` or `SERPER_API_KEY` to enable it.
|
|
235
|
+
|
|
236
|
+
### MCP server fails to connect
|
|
237
|
+
Check that the command in your MCP config is correct and the server binary is installed.
|
|
238
|
+
|
|
239
|
+
## License
|
|
240
|
+
|
|
241
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import readline from 'node:readline';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { Agent } from './core/agent.js';
|
|
9
|
+
import { loadConfig, saveConfig, loadMcpConfig } from './config/index.js';
|
|
10
|
+
import { createToolRegistry } from './tools/index.js';
|
|
11
|
+
import { McpManager } from './mcp/client.js';
|
|
12
|
+
import { SkillsLoader } from './skills/loader.js';
|
|
13
|
+
import { OpenAIProvider } from './providers/openai.js';
|
|
14
|
+
import { OllamaProvider } from './providers/ollama.js';
|
|
15
|
+
import { VERSION } from './constants.js';
|
|
16
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
// ---- Helpers ----
|
|
18
|
+
function getSkillsDirs() {
|
|
19
|
+
const dirs = [];
|
|
20
|
+
// Skills bundled with the package
|
|
21
|
+
const pkgSkills = path.resolve(__dirname, '..', 'skills');
|
|
22
|
+
if (fs.existsSync(pkgSkills))
|
|
23
|
+
dirs.push(pkgSkills);
|
|
24
|
+
// Local workspace skills (.github/skills)
|
|
25
|
+
const ghSkills = path.join(process.cwd(), '.github', 'skills');
|
|
26
|
+
if (fs.existsSync(ghSkills))
|
|
27
|
+
dirs.push(ghSkills);
|
|
28
|
+
// Local workspace skills (top-level)
|
|
29
|
+
const topSkills = path.join(process.cwd(), 'skills');
|
|
30
|
+
if (fs.existsSync(topSkills) && topSkills !== pkgSkills)
|
|
31
|
+
dirs.push(topSkills);
|
|
32
|
+
return dirs;
|
|
33
|
+
}
|
|
34
|
+
function createProvider() {
|
|
35
|
+
const config = loadConfig();
|
|
36
|
+
if (config.provider === 'openai') {
|
|
37
|
+
const apiKey = config.openai.apiKey ?? process.env['OPENAI_API_KEY'];
|
|
38
|
+
if (!apiKey) {
|
|
39
|
+
console.error(chalk.red('Error: OpenAI API key not configured.\n') +
|
|
40
|
+
chalk.dim('Run: developer-ai onboard'));
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
return new OpenAIProvider(apiKey, config.openai.model);
|
|
44
|
+
}
|
|
45
|
+
return new OllamaProvider(config.ollama.model, config.ollama.baseUrl);
|
|
46
|
+
}
|
|
47
|
+
async function createAgent(opts, confirmFn) {
|
|
48
|
+
const config = loadConfig();
|
|
49
|
+
const mcpConfig = loadMcpConfig();
|
|
50
|
+
const provider = createProvider();
|
|
51
|
+
const toolRegistry = createToolRegistry();
|
|
52
|
+
const mcpManager = new McpManager();
|
|
53
|
+
const skillsLoader = new SkillsLoader(getSkillsDirs());
|
|
54
|
+
// MCP init (non-fatal)
|
|
55
|
+
if (Object.keys(mcpConfig.servers).length > 0) {
|
|
56
|
+
await mcpManager.initialize(mcpConfig);
|
|
57
|
+
}
|
|
58
|
+
const agent = new Agent({
|
|
59
|
+
provider,
|
|
60
|
+
toolRegistry,
|
|
61
|
+
mcpManager,
|
|
62
|
+
skillsLoader,
|
|
63
|
+
workspaceDir: process.cwd(),
|
|
64
|
+
autoYes: opts.yes ?? false,
|
|
65
|
+
allowDangerous: opts.allowDangerous ?? false,
|
|
66
|
+
maxIterations: 30,
|
|
67
|
+
confirmFn,
|
|
68
|
+
});
|
|
69
|
+
await agent.initialize();
|
|
70
|
+
return agent;
|
|
71
|
+
}
|
|
72
|
+
// ---- REPL ----
|
|
73
|
+
async function runRepl(opts) {
|
|
74
|
+
const rl = readline.createInterface({
|
|
75
|
+
input: process.stdin,
|
|
76
|
+
output: process.stdout,
|
|
77
|
+
prompt: chalk.green('you › '),
|
|
78
|
+
});
|
|
79
|
+
// Confirmation via the same readline interface
|
|
80
|
+
const confirmFn = (message) => new Promise((resolve) => {
|
|
81
|
+
rl.question(chalk.yellow(`\n${message} (y/N) `), (answer) => {
|
|
82
|
+
resolve(answer.trim().toLowerCase().startsWith('y'));
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
console.log(chalk.bold.cyan('\n Developer-AI') +
|
|
86
|
+
chalk.dim(` v${VERSION}`) +
|
|
87
|
+
chalk.dim(` · provider: ${loadConfig().provider}`));
|
|
88
|
+
console.log(chalk.dim(` Workspace: ${process.cwd()}`));
|
|
89
|
+
console.log(chalk.dim(' Type "exit" to quit, "clear" to reset context.\n'));
|
|
90
|
+
const agent = await createAgent(opts, confirmFn);
|
|
91
|
+
rl.prompt();
|
|
92
|
+
rl.on('line', async (line) => {
|
|
93
|
+
const input = line.trim();
|
|
94
|
+
if (!input) {
|
|
95
|
+
rl.prompt();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (input === 'exit' || input === 'quit' || input === '.exit') {
|
|
99
|
+
console.log(chalk.dim('Goodbye!'));
|
|
100
|
+
rl.close();
|
|
101
|
+
process.exit(0);
|
|
102
|
+
}
|
|
103
|
+
if (input === 'clear') {
|
|
104
|
+
agent.resetHistory();
|
|
105
|
+
console.log(chalk.dim('Context cleared.\n'));
|
|
106
|
+
rl.prompt();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// Pause readline while the agent is working
|
|
110
|
+
rl.pause();
|
|
111
|
+
try {
|
|
112
|
+
process.stderr.write(chalk.dim('\nThinking...\n\n'));
|
|
113
|
+
const response = await agent.chat(input);
|
|
114
|
+
console.log('\n' + response + '\n');
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
console.error(chalk.red(`\nError: ${err.message}\n`));
|
|
118
|
+
}
|
|
119
|
+
rl.resume();
|
|
120
|
+
rl.prompt();
|
|
121
|
+
});
|
|
122
|
+
rl.on('close', () => process.exit(0));
|
|
123
|
+
}
|
|
124
|
+
// ---- One-shot mode ----
|
|
125
|
+
async function runOneShot(instruction, opts) {
|
|
126
|
+
// In one-shot mode, stdin confirm uses a temporary readline
|
|
127
|
+
const confirmFn = (message) => new Promise((resolve) => {
|
|
128
|
+
const tmpRl = readline.createInterface({
|
|
129
|
+
input: process.stdin,
|
|
130
|
+
output: process.stderr,
|
|
131
|
+
});
|
|
132
|
+
tmpRl.question(chalk.yellow(`${message} (y/N) `), (answer) => {
|
|
133
|
+
tmpRl.close();
|
|
134
|
+
resolve(answer.trim().toLowerCase().startsWith('y'));
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
try {
|
|
138
|
+
const agent = await createAgent(opts, confirmFn);
|
|
139
|
+
process.stderr.write(chalk.dim('Processing...\n\n'));
|
|
140
|
+
const response = await agent.chat(instruction);
|
|
141
|
+
console.log(response);
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// ---- Onboard command ----
|
|
149
|
+
async function runOnboard() {
|
|
150
|
+
console.log(chalk.bold.cyan('\n Developer-AI Setup\n'));
|
|
151
|
+
const rl = readline.createInterface({
|
|
152
|
+
input: process.stdin,
|
|
153
|
+
output: process.stdout,
|
|
154
|
+
});
|
|
155
|
+
const ask = (q) => new Promise((resolve) => rl.question(q, resolve));
|
|
156
|
+
const config = loadConfig();
|
|
157
|
+
// Provider
|
|
158
|
+
const providerChoice = await ask(chalk.white(' Choose provider (1 = Ollama, 2 = OpenAI) [1]: '));
|
|
159
|
+
if (providerChoice.trim() === '2') {
|
|
160
|
+
config.provider = 'openai';
|
|
161
|
+
const apiKey = await ask(chalk.white(' OpenAI API key: '));
|
|
162
|
+
if (apiKey.trim())
|
|
163
|
+
config.openai.apiKey = apiKey.trim();
|
|
164
|
+
const model = await ask(chalk.white(` Model [${config.openai.model}]: `));
|
|
165
|
+
if (model.trim())
|
|
166
|
+
config.openai.model = model.trim();
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
config.provider = 'ollama';
|
|
170
|
+
const model = await ask(chalk.white(` Ollama model [${config.ollama.model}]: `));
|
|
171
|
+
if (model.trim())
|
|
172
|
+
config.ollama.model = model.trim();
|
|
173
|
+
const baseUrl = await ask(chalk.white(` Ollama URL [${config.ollama.baseUrl}]: `));
|
|
174
|
+
if (baseUrl.trim())
|
|
175
|
+
config.ollama.baseUrl = baseUrl.trim();
|
|
176
|
+
}
|
|
177
|
+
// Web search
|
|
178
|
+
const searchChoice = await ask(chalk.white(' Web search (1 = none, 2 = Brave, 3 = Serper) [1]: '));
|
|
179
|
+
if (searchChoice.trim() === '2') {
|
|
180
|
+
config.webSearch.provider = 'brave';
|
|
181
|
+
const key = await ask(chalk.white(' Brave Search API key: '));
|
|
182
|
+
if (key.trim())
|
|
183
|
+
config.webSearch.braveApiKey = key.trim();
|
|
184
|
+
}
|
|
185
|
+
else if (searchChoice.trim() === '3') {
|
|
186
|
+
config.webSearch.provider = 'serper';
|
|
187
|
+
const key = await ask(chalk.white(' Serper API key: '));
|
|
188
|
+
if (key.trim())
|
|
189
|
+
config.webSearch.serperApiKey = key.trim();
|
|
190
|
+
}
|
|
191
|
+
saveConfig(config);
|
|
192
|
+
console.log(chalk.green('\n ✓ Configuration saved to ~/.developer-ai/config.json'));
|
|
193
|
+
console.log(chalk.dim(' ⚠ File permissions set to owner-only (0600).\n'));
|
|
194
|
+
rl.close();
|
|
195
|
+
}
|
|
196
|
+
// ---- Program definition ----
|
|
197
|
+
const program = new Command();
|
|
198
|
+
program
|
|
199
|
+
.name('developer-ai')
|
|
200
|
+
.description('Terminal-based AI coding assistant. Run interactively or provide a one-shot instruction.')
|
|
201
|
+
.version(VERSION)
|
|
202
|
+
.option('--yes', 'Auto-confirm all prompts (non-interactive)', false)
|
|
203
|
+
.option('--allow-dangerous', 'Allow dangerous commands without confirmation', false)
|
|
204
|
+
.argument('[instruction...]', 'One-shot instruction (non-interactive)')
|
|
205
|
+
.action(async (instructionParts, options) => {
|
|
206
|
+
const instruction = instructionParts.join(' ').trim();
|
|
207
|
+
if (instruction) {
|
|
208
|
+
await runOneShot(instruction, options);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
await runRepl(options);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
program
|
|
215
|
+
.command('onboard')
|
|
216
|
+
.description('Configure provider, API keys, and web search')
|
|
217
|
+
.action(runOnboard);
|
|
218
|
+
program.parse();
|
|
219
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type Config, type McpConfig } from './schema.js';
|
|
2
|
+
export declare function ensureConfigDir(): void;
|
|
3
|
+
export declare function loadConfig(): Config;
|
|
4
|
+
export declare function saveConfig(config: Config): void;
|
|
5
|
+
export declare function loadMcpConfig(): McpConfig;
|
|
6
|
+
export declare function getConfigDir(): string;
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiC,KAAK,MAAM,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAMzF,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAED,wBAAgB,UAAU,IAAI,MAAM,CAwCnC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAG/C;AAED,wBAAgB,aAAa,IAAI,SAAS,CAuBzC;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import { ConfigSchema, McpConfigSchema } from './schema.js';
|
|
5
|
+
const CONFIG_DIR = path.join(os.homedir(), '.developer-ai');
|
|
6
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
7
|
+
const MCP_FILE = path.join(CONFIG_DIR, 'mcp.json');
|
|
8
|
+
export function ensureConfigDir() {
|
|
9
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
10
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function loadConfig() {
|
|
14
|
+
ensureConfigDir();
|
|
15
|
+
let config;
|
|
16
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
17
|
+
try {
|
|
18
|
+
const raw = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8'));
|
|
19
|
+
config = ConfigSchema.parse(raw);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
config = ConfigSchema.parse({});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
config = ConfigSchema.parse({});
|
|
27
|
+
}
|
|
28
|
+
// Environment variable overrides — higher priority than config file
|
|
29
|
+
if (process.env['OPENAI_API_KEY']) {
|
|
30
|
+
config.provider = 'openai';
|
|
31
|
+
config.openai.apiKey = process.env['OPENAI_API_KEY'];
|
|
32
|
+
}
|
|
33
|
+
if (process.env['OPENAI_MODEL']) {
|
|
34
|
+
config.openai.model = process.env['OPENAI_MODEL'];
|
|
35
|
+
}
|
|
36
|
+
if (process.env['OLLAMA_MODEL']) {
|
|
37
|
+
config.ollama.model = process.env['OLLAMA_MODEL'];
|
|
38
|
+
}
|
|
39
|
+
if (process.env['OLLAMA_BASE_URL']) {
|
|
40
|
+
config.ollama.baseUrl = process.env['OLLAMA_BASE_URL'];
|
|
41
|
+
}
|
|
42
|
+
if (process.env['BRAVE_SEARCH_API_KEY']) {
|
|
43
|
+
config.webSearch.provider = 'brave';
|
|
44
|
+
config.webSearch.braveApiKey = process.env['BRAVE_SEARCH_API_KEY'];
|
|
45
|
+
}
|
|
46
|
+
if (process.env['SERPER_API_KEY']) {
|
|
47
|
+
config.webSearch.provider = 'serper';
|
|
48
|
+
config.webSearch.serperApiKey = process.env['SERPER_API_KEY'];
|
|
49
|
+
}
|
|
50
|
+
return config;
|
|
51
|
+
}
|
|
52
|
+
export function saveConfig(config) {
|
|
53
|
+
ensureConfigDir();
|
|
54
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 0o600 });
|
|
55
|
+
}
|
|
56
|
+
export function loadMcpConfig() {
|
|
57
|
+
const merged = { servers: {} };
|
|
58
|
+
// Global MCP config
|
|
59
|
+
if (fs.existsSync(MCP_FILE)) {
|
|
60
|
+
try {
|
|
61
|
+
const raw = JSON.parse(fs.readFileSync(MCP_FILE, 'utf-8'));
|
|
62
|
+
const parsed = McpConfigSchema.parse(raw);
|
|
63
|
+
Object.assign(merged.servers, parsed.servers);
|
|
64
|
+
}
|
|
65
|
+
catch { /* ignore malformed config */ }
|
|
66
|
+
}
|
|
67
|
+
// Local MCP config (workspace-level)
|
|
68
|
+
const localMcp = path.join(process.cwd(), '.developer-ai', 'mcp.json');
|
|
69
|
+
if (fs.existsSync(localMcp)) {
|
|
70
|
+
try {
|
|
71
|
+
const raw = JSON.parse(fs.readFileSync(localMcp, 'utf-8'));
|
|
72
|
+
const parsed = McpConfigSchema.parse(raw);
|
|
73
|
+
Object.assign(merged.servers, parsed.servers);
|
|
74
|
+
}
|
|
75
|
+
catch { /* ignore malformed config */ }
|
|
76
|
+
}
|
|
77
|
+
return merged;
|
|
78
|
+
}
|
|
79
|
+
export function getConfigDir() {
|
|
80
|
+
return CONFIG_DIR;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,YAAY,EAAE,eAAe,EAA+B,MAAM,aAAa,CAAC;AAEzF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,eAAe,CAAC,CAAC;AAC5D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AAEnD,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,eAAe,EAAE,CAAC;IAElB,IAAI,MAAc,CAAC;IAEnB,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;YAC9D,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,oEAAoE;IACpE,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAClC,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC3B,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;QAChC,MAAM,CAAC,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;QAChC,MAAM,CAAC,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAAE,CAAC;QACxC,MAAM,CAAC,SAAS,CAAC,QAAQ,GAAG,OAAO,CAAC;QACpC,MAAM,CAAC,SAAS,CAAC,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAClC,MAAM,CAAC,SAAS,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACrC,MAAM,CAAC,SAAS,CAAC,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,eAAe,EAAE,CAAC;IAClB,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAClF,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,MAAM,GAAc,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAE1C,oBAAoB;IACpB,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;YAC3D,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC,CAAC,6BAA6B,CAAC,CAAC;IAC3C,CAAC;IAED,qCAAqC;IACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;IACvE,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;YAC3D,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC,CAAC,6BAA6B,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,UAAU,CAAC;AACpB,CAAC"}
|