coding-agent-adapters 0.2.18 → 0.3.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 +144 -0
- package/dist/index.cjs +419 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +75 -9
- package/dist/index.d.ts +75 -9
- package/dist/index.js +408 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -161,6 +161,134 @@ aider.getRecommendedModels({ googleKey: 'AIza...' });
|
|
|
161
161
|
// { powerful: 'gemini/gemini-3-pro', fast: 'gemini/gemini-3-flash' }
|
|
162
162
|
```
|
|
163
163
|
|
|
164
|
+
## Workspace Files & Memory
|
|
165
|
+
|
|
166
|
+
Each coding agent CLI has its own convention for project-level memory files (instructions the agent reads on startup) and config files. Adapters expose this knowledge so orchestration systems can write context to the correct files before spawning an agent.
|
|
167
|
+
|
|
168
|
+
### Discovering Workspace Files
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { ClaudeAdapter, AiderAdapter } from 'coding-agent-adapters';
|
|
172
|
+
|
|
173
|
+
const claude = new ClaudeAdapter();
|
|
174
|
+
claude.getWorkspaceFiles();
|
|
175
|
+
// [
|
|
176
|
+
// { relativePath: 'CLAUDE.md', type: 'memory', autoLoaded: true, format: 'markdown', ... },
|
|
177
|
+
// { relativePath: '.claude/settings.json', type: 'config', autoLoaded: true, format: 'json', ... },
|
|
178
|
+
// { relativePath: '.claude/commands', type: 'config', autoLoaded: false, format: 'markdown', ... },
|
|
179
|
+
// ]
|
|
180
|
+
|
|
181
|
+
claude.memoryFilePath; // 'CLAUDE.md'
|
|
182
|
+
|
|
183
|
+
const aider = new AiderAdapter();
|
|
184
|
+
aider.memoryFilePath; // '.aider.conventions.md'
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Per-Adapter File Mappings
|
|
188
|
+
|
|
189
|
+
| Adapter | Memory File | Config | Other |
|
|
190
|
+
|---------|------------|--------|-------|
|
|
191
|
+
| Claude | `CLAUDE.md` | `.claude/settings.json` | `.claude/commands` |
|
|
192
|
+
| Gemini | `GEMINI.md` | `.gemini/settings.json` | `.gemini/styles` |
|
|
193
|
+
| Codex | `AGENTS.md` | `.codex/config.json` | `codex.md` |
|
|
194
|
+
| Aider | `.aider.conventions.md` | `.aider.conf.yml` | `.aiderignore` |
|
|
195
|
+
|
|
196
|
+
### Writing Memory Files
|
|
197
|
+
|
|
198
|
+
Use `writeMemoryFile()` to write instructions into a workspace before spawning an agent. Parent directories are created automatically.
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
const adapter = new ClaudeAdapter();
|
|
202
|
+
|
|
203
|
+
// Write to the adapter's default memory file (CLAUDE.md)
|
|
204
|
+
await adapter.writeMemoryFile('/path/to/workspace', `# Project Context
|
|
205
|
+
This is a TypeScript monorepo using pnpm workspaces.
|
|
206
|
+
Always run tests before committing.
|
|
207
|
+
`);
|
|
208
|
+
|
|
209
|
+
// Append to an existing memory file
|
|
210
|
+
await adapter.writeMemoryFile('/path/to/workspace', '\n## Additional Rules\nUse snake_case.\n', {
|
|
211
|
+
append: true,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// Write to a custom file (e.g., template-specific context for sub-agents)
|
|
215
|
+
await adapter.writeMemoryFile('/path/to/workspace', '# Task-Specific Context\n...', {
|
|
216
|
+
fileName: 'TASK_CONTEXT.md',
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Approval Presets
|
|
221
|
+
|
|
222
|
+
Each coding agent CLI has its own config format for controlling tool permissions. The approval preset system provides 4 named levels that translate to the correct per-CLI config files and CLI flags.
|
|
223
|
+
|
|
224
|
+
### Preset Levels
|
|
225
|
+
|
|
226
|
+
| Preset | Description | Auto-approve | Require approval | Blocked |
|
|
227
|
+
|--------|-------------|-------------|-----------------|---------|
|
|
228
|
+
| `readonly` | Read-only. Safe for auditing. | file_read, planning, user_interaction | — | file_write, shell, web, agent |
|
|
229
|
+
| `standard` | Standard dev. Reads + web auto, writes/shell prompt. | file_read, planning, user_interaction, web | file_write, shell, agent | — |
|
|
230
|
+
| `permissive` | File ops auto-approved, shell still prompts. | file_read, file_write, planning, user_interaction, web, agent | shell | — |
|
|
231
|
+
| `autonomous` | Everything auto-approved. Use with sandbox. | all categories | — | — |
|
|
232
|
+
|
|
233
|
+
### Generating Configs
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
import { generateApprovalConfig, listPresets, getPresetDefinition } from 'coding-agent-adapters';
|
|
237
|
+
|
|
238
|
+
// List all available presets
|
|
239
|
+
const presets = listPresets();
|
|
240
|
+
|
|
241
|
+
// Generate CLI-specific config for a preset
|
|
242
|
+
const config = generateApprovalConfig('claude', 'permissive');
|
|
243
|
+
// {
|
|
244
|
+
// preset: 'permissive',
|
|
245
|
+
// cliFlags: [],
|
|
246
|
+
// workspaceFiles: [{ relativePath: '.claude/settings.json', content: '...', format: 'json' }],
|
|
247
|
+
// envVars: {},
|
|
248
|
+
// summary: 'Claude Code: File ops auto-approved, shell still prompts.',
|
|
249
|
+
// }
|
|
250
|
+
|
|
251
|
+
// Each CLI gets its own config format
|
|
252
|
+
generateApprovalConfig('gemini', 'readonly'); // → .gemini/settings.json + --approval-mode plan
|
|
253
|
+
generateApprovalConfig('codex', 'autonomous'); // → .codex/config.json + --full-auto
|
|
254
|
+
generateApprovalConfig('aider', 'permissive'); // → .aider.conf.yml + --yes-always
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Using Presets with Adapters
|
|
258
|
+
|
|
259
|
+
When `approvalPreset` is set in `adapterConfig`, the adapter's `getArgs()` automatically appends the correct CLI flags:
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
const session = await manager.spawn({
|
|
263
|
+
name: 'sandboxed-agent',
|
|
264
|
+
type: 'claude',
|
|
265
|
+
workdir: '/path/to/project',
|
|
266
|
+
adapterConfig: {
|
|
267
|
+
anthropicKey: process.env.ANTHROPIC_API_KEY,
|
|
268
|
+
approvalPreset: 'autonomous',
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
You can also write the config files to a workspace manually using `writeApprovalConfig()`:
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
const adapter = new ClaudeAdapter();
|
|
277
|
+
const writtenFiles = await adapter.writeApprovalConfig('/path/to/workspace', {
|
|
278
|
+
adapterConfig: { approvalPreset: 'permissive' },
|
|
279
|
+
});
|
|
280
|
+
// writtenFiles: ['/path/to/workspace/.claude/settings.json']
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Per-CLI Output
|
|
284
|
+
|
|
285
|
+
| CLI | Config File | Key Controls |
|
|
286
|
+
|-----|------------|--------------|
|
|
287
|
+
| Claude Code | `.claude/settings.json` | `permissions.allow`, `permissions.deny`, `sandbox.*` |
|
|
288
|
+
| Gemini CLI | `.gemini/settings.json` | `general.defaultApprovalMode`, `tools.allowed`, `tools.exclude` |
|
|
289
|
+
| Codex | `.codex/config.json` | `approval_policy`, `sandbox_mode`, `tools.web_search` |
|
|
290
|
+
| Aider | `.aider.conf.yml` | `yes-always`, `no-auto-commits` |
|
|
291
|
+
|
|
164
292
|
## Preflight Check
|
|
165
293
|
|
|
166
294
|
Before spawning agents, check if the required CLIs are installed:
|
|
@@ -218,12 +346,18 @@ Extend `BaseCodingAdapter` to create adapters for other coding CLIs:
|
|
|
218
346
|
|
|
219
347
|
```typescript
|
|
220
348
|
import { BaseCodingAdapter } from 'coding-agent-adapters';
|
|
349
|
+
import type { AgentFileDescriptor, InstallationInfo, ModelRecommendations } from 'coding-agent-adapters';
|
|
221
350
|
import type { SpawnConfig, ParsedOutput, LoginDetection, AutoResponseRule } from 'pty-manager';
|
|
222
351
|
|
|
223
352
|
export class CursorAdapter extends BaseCodingAdapter {
|
|
224
353
|
readonly adapterType = 'cursor';
|
|
225
354
|
readonly displayName = 'Cursor';
|
|
226
355
|
|
|
356
|
+
readonly installation: InstallationInfo = {
|
|
357
|
+
command: 'npm install -g cursor-cli',
|
|
358
|
+
docsUrl: 'https://cursor.sh/docs',
|
|
359
|
+
};
|
|
360
|
+
|
|
227
361
|
// Set to false if the CLI uses text prompts instead of TUI menus
|
|
228
362
|
override readonly usesTuiMenus = false;
|
|
229
363
|
|
|
@@ -231,6 +365,16 @@ export class CursorAdapter extends BaseCodingAdapter {
|
|
|
231
365
|
{ pattern: /accept terms/i, type: 'tos', response: 'y', responseType: 'text', description: 'Accept TOS', safe: true, once: true },
|
|
232
366
|
];
|
|
233
367
|
|
|
368
|
+
getWorkspaceFiles(): AgentFileDescriptor[] {
|
|
369
|
+
return [
|
|
370
|
+
{ relativePath: '.cursor/rules', description: 'Project rules', autoLoaded: true, type: 'memory', format: 'markdown' },
|
|
371
|
+
];
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
getRecommendedModels(): ModelRecommendations {
|
|
375
|
+
return { powerful: 'claude-sonnet-4', fast: 'gpt-4o-mini' };
|
|
376
|
+
}
|
|
377
|
+
|
|
234
378
|
getCommand(): string { return 'cursor'; }
|
|
235
379
|
getArgs(config: SpawnConfig): string[] { return ['--cli']; }
|
|
236
380
|
getEnv(config: SpawnConfig): Record<string, string> { return {}; }
|
package/dist/index.cjs
CHANGED
|
@@ -4,6 +4,362 @@ var promises = require('fs/promises');
|
|
|
4
4
|
var path = require('path');
|
|
5
5
|
var ptyManager = require('pty-manager');
|
|
6
6
|
|
|
7
|
+
// src/base-coding-adapter.ts
|
|
8
|
+
|
|
9
|
+
// src/approval-presets.ts
|
|
10
|
+
var TOOL_CATEGORIES = [
|
|
11
|
+
{ category: "file_read", risk: "low", description: "Read files, search, list directories" },
|
|
12
|
+
{ category: "file_write", risk: "medium", description: "Write, edit, and create files" },
|
|
13
|
+
{ category: "shell", risk: "high", description: "Execute shell commands" },
|
|
14
|
+
{ category: "web", risk: "medium", description: "Web search and fetch" },
|
|
15
|
+
{ category: "agent", risk: "medium", description: "Spawn sub-agents, skills, MCP tools" },
|
|
16
|
+
{ category: "planning", risk: "low", description: "Task planning and todo management" },
|
|
17
|
+
{ category: "user_interaction", risk: "low", description: "Ask user questions" }
|
|
18
|
+
];
|
|
19
|
+
var PRESET_DEFINITIONS = [
|
|
20
|
+
{
|
|
21
|
+
preset: "readonly",
|
|
22
|
+
description: "Read-only. Safe for auditing.",
|
|
23
|
+
autoApprove: ["file_read", "planning", "user_interaction"],
|
|
24
|
+
requireApproval: [],
|
|
25
|
+
blocked: ["file_write", "shell", "web", "agent"]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
preset: "standard",
|
|
29
|
+
description: "Standard dev. Reads + web auto, writes/shell prompt.",
|
|
30
|
+
autoApprove: ["file_read", "planning", "user_interaction", "web"],
|
|
31
|
+
requireApproval: ["file_write", "shell", "agent"],
|
|
32
|
+
blocked: []
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
preset: "permissive",
|
|
36
|
+
description: "File ops auto-approved, shell still prompts.",
|
|
37
|
+
autoApprove: ["file_read", "file_write", "planning", "user_interaction", "web", "agent"],
|
|
38
|
+
requireApproval: ["shell"],
|
|
39
|
+
blocked: []
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
preset: "autonomous",
|
|
43
|
+
description: "Everything auto-approved. Use with sandbox.",
|
|
44
|
+
autoApprove: ["file_read", "file_write", "shell", "web", "agent", "planning", "user_interaction"],
|
|
45
|
+
requireApproval: [],
|
|
46
|
+
blocked: []
|
|
47
|
+
}
|
|
48
|
+
];
|
|
49
|
+
var CLAUDE_TOOL_CATEGORIES = {
|
|
50
|
+
// file_read
|
|
51
|
+
Read: "file_read",
|
|
52
|
+
Grep: "file_read",
|
|
53
|
+
Glob: "file_read",
|
|
54
|
+
LS: "file_read",
|
|
55
|
+
NotebookRead: "file_read",
|
|
56
|
+
// file_write
|
|
57
|
+
Write: "file_write",
|
|
58
|
+
Edit: "file_write",
|
|
59
|
+
// shell
|
|
60
|
+
Bash: "shell",
|
|
61
|
+
BashOutput: "shell",
|
|
62
|
+
KillShell: "shell",
|
|
63
|
+
// web
|
|
64
|
+
WebSearch: "web",
|
|
65
|
+
WebFetch: "web",
|
|
66
|
+
// agent
|
|
67
|
+
Task: "agent",
|
|
68
|
+
Skill: "agent",
|
|
69
|
+
// planning
|
|
70
|
+
TodoWrite: "planning",
|
|
71
|
+
// user_interaction
|
|
72
|
+
AskUserQuestion: "user_interaction"
|
|
73
|
+
};
|
|
74
|
+
var GEMINI_TOOL_CATEGORIES = {
|
|
75
|
+
// file_read
|
|
76
|
+
read_file: "file_read",
|
|
77
|
+
read_many_files: "file_read",
|
|
78
|
+
list_directory: "file_read",
|
|
79
|
+
glob: "file_read",
|
|
80
|
+
search_file_content: "file_read",
|
|
81
|
+
// file_write
|
|
82
|
+
write_file: "file_write",
|
|
83
|
+
replace: "file_write",
|
|
84
|
+
// shell
|
|
85
|
+
run_shell_command: "shell",
|
|
86
|
+
// web
|
|
87
|
+
web_fetch: "web",
|
|
88
|
+
google_web_search: "web",
|
|
89
|
+
// agent
|
|
90
|
+
activate_skill: "agent",
|
|
91
|
+
get_internal_docs: "agent",
|
|
92
|
+
// planning
|
|
93
|
+
save_memory: "planning",
|
|
94
|
+
write_todos: "planning",
|
|
95
|
+
// user_interaction
|
|
96
|
+
ask_user: "user_interaction"
|
|
97
|
+
};
|
|
98
|
+
var CODEX_TOOL_CATEGORIES = {
|
|
99
|
+
// shell (codex uses shell for most operations)
|
|
100
|
+
exec_command: "shell",
|
|
101
|
+
write_stdin: "shell",
|
|
102
|
+
shell_command: "shell",
|
|
103
|
+
// file_write
|
|
104
|
+
apply_patch: "file_write",
|
|
105
|
+
// file_read
|
|
106
|
+
grep_files: "file_read",
|
|
107
|
+
read_file: "file_read",
|
|
108
|
+
list_dir: "file_read",
|
|
109
|
+
// web
|
|
110
|
+
web_search: "web",
|
|
111
|
+
view_image: "web",
|
|
112
|
+
// agent
|
|
113
|
+
spawn_agent: "agent",
|
|
114
|
+
send_input: "agent",
|
|
115
|
+
resume_agent: "agent",
|
|
116
|
+
wait: "agent",
|
|
117
|
+
close_agent: "agent",
|
|
118
|
+
// planning
|
|
119
|
+
update_plan: "planning",
|
|
120
|
+
// user_interaction
|
|
121
|
+
request_user_input: "user_interaction"
|
|
122
|
+
};
|
|
123
|
+
var AIDER_COMMAND_CATEGORIES = {
|
|
124
|
+
// file_read
|
|
125
|
+
"/read-only": "file_read",
|
|
126
|
+
"/ls": "file_read",
|
|
127
|
+
"/map": "file_read",
|
|
128
|
+
"/map-refresh": "file_read",
|
|
129
|
+
"/tokens": "file_read",
|
|
130
|
+
"/diff": "file_read",
|
|
131
|
+
"/context": "file_read",
|
|
132
|
+
// file_write
|
|
133
|
+
"/add": "file_write",
|
|
134
|
+
"/drop": "file_write",
|
|
135
|
+
"/edit": "file_write",
|
|
136
|
+
"/code": "file_write",
|
|
137
|
+
"/architect": "file_write",
|
|
138
|
+
"/undo": "file_write",
|
|
139
|
+
// shell
|
|
140
|
+
"/run": "shell",
|
|
141
|
+
"/test": "shell",
|
|
142
|
+
"/lint": "shell",
|
|
143
|
+
"/git": "shell",
|
|
144
|
+
// web
|
|
145
|
+
"/web": "web",
|
|
146
|
+
// planning
|
|
147
|
+
"/ask": "planning",
|
|
148
|
+
// user_interaction
|
|
149
|
+
"/voice": "user_interaction",
|
|
150
|
+
"/help": "user_interaction",
|
|
151
|
+
// config/other
|
|
152
|
+
"/model": "planning",
|
|
153
|
+
"/settings": "planning",
|
|
154
|
+
"/commit": "file_write",
|
|
155
|
+
"/clear": "planning",
|
|
156
|
+
"/reset": "planning"
|
|
157
|
+
};
|
|
158
|
+
function getToolsForCategories(mapping, categories) {
|
|
159
|
+
return Object.entries(mapping).filter(([, cat]) => categories.includes(cat)).map(([tool]) => tool);
|
|
160
|
+
}
|
|
161
|
+
function generateClaudeApprovalConfig(preset) {
|
|
162
|
+
const def = getPresetDefinition(preset);
|
|
163
|
+
const allowTools = getToolsForCategories(CLAUDE_TOOL_CATEGORIES, def.autoApprove);
|
|
164
|
+
const denyTools = getToolsForCategories(CLAUDE_TOOL_CATEGORIES, def.blocked);
|
|
165
|
+
const settings = {
|
|
166
|
+
permissions: {}
|
|
167
|
+
};
|
|
168
|
+
const permissions = settings.permissions;
|
|
169
|
+
if (allowTools.length > 0) {
|
|
170
|
+
permissions.allow = allowTools;
|
|
171
|
+
}
|
|
172
|
+
if (denyTools.length > 0) {
|
|
173
|
+
permissions.deny = denyTools;
|
|
174
|
+
}
|
|
175
|
+
if (preset === "autonomous") {
|
|
176
|
+
settings.sandbox = {
|
|
177
|
+
enabled: true,
|
|
178
|
+
autoAllowBashIfSandboxed: true
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const cliFlags = [];
|
|
182
|
+
if (preset === "autonomous") {
|
|
183
|
+
const allTools = Object.keys(CLAUDE_TOOL_CATEGORIES);
|
|
184
|
+
cliFlags.push("--tools", allTools.join(","));
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
preset,
|
|
188
|
+
cliFlags,
|
|
189
|
+
workspaceFiles: [
|
|
190
|
+
{
|
|
191
|
+
relativePath: ".claude/settings.json",
|
|
192
|
+
content: JSON.stringify(settings, null, 2),
|
|
193
|
+
format: "json"
|
|
194
|
+
}
|
|
195
|
+
],
|
|
196
|
+
envVars: {},
|
|
197
|
+
summary: `Claude Code: ${def.description}`
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function generateGeminiApprovalConfig(preset) {
|
|
201
|
+
const def = getPresetDefinition(preset);
|
|
202
|
+
const cliFlags = [];
|
|
203
|
+
const allowedTools = getToolsForCategories(GEMINI_TOOL_CATEGORIES, def.autoApprove);
|
|
204
|
+
const excludeTools = getToolsForCategories(GEMINI_TOOL_CATEGORIES, def.blocked);
|
|
205
|
+
let approvalMode;
|
|
206
|
+
switch (preset) {
|
|
207
|
+
case "readonly":
|
|
208
|
+
approvalMode = "plan";
|
|
209
|
+
cliFlags.push("--approval-mode", "plan");
|
|
210
|
+
break;
|
|
211
|
+
case "standard":
|
|
212
|
+
approvalMode = "default";
|
|
213
|
+
break;
|
|
214
|
+
case "permissive":
|
|
215
|
+
approvalMode = "auto_edit";
|
|
216
|
+
cliFlags.push("--approval-mode", "auto_edit");
|
|
217
|
+
break;
|
|
218
|
+
case "autonomous":
|
|
219
|
+
approvalMode = "auto_edit";
|
|
220
|
+
cliFlags.push("-y");
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
const settings = {
|
|
224
|
+
general: {
|
|
225
|
+
defaultApprovalMode: approvalMode
|
|
226
|
+
},
|
|
227
|
+
tools: {}
|
|
228
|
+
};
|
|
229
|
+
const tools = settings.tools;
|
|
230
|
+
if (allowedTools.length > 0) {
|
|
231
|
+
tools.allowed = allowedTools;
|
|
232
|
+
}
|
|
233
|
+
if (excludeTools.length > 0) {
|
|
234
|
+
tools.exclude = excludeTools;
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
preset,
|
|
238
|
+
cliFlags,
|
|
239
|
+
workspaceFiles: [
|
|
240
|
+
{
|
|
241
|
+
relativePath: ".gemini/settings.json",
|
|
242
|
+
content: JSON.stringify(settings, null, 2),
|
|
243
|
+
format: "json"
|
|
244
|
+
}
|
|
245
|
+
],
|
|
246
|
+
envVars: {},
|
|
247
|
+
summary: `Gemini CLI: ${def.description}`
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function generateCodexApprovalConfig(preset) {
|
|
251
|
+
const cliFlags = [];
|
|
252
|
+
let approvalPolicy;
|
|
253
|
+
let sandboxMode;
|
|
254
|
+
let webSearch;
|
|
255
|
+
switch (preset) {
|
|
256
|
+
case "readonly":
|
|
257
|
+
approvalPolicy = "untrusted";
|
|
258
|
+
sandboxMode = "workspace-read";
|
|
259
|
+
webSearch = false;
|
|
260
|
+
cliFlags.push("--sandbox", "workspace-read", "-a", "untrusted");
|
|
261
|
+
break;
|
|
262
|
+
case "standard":
|
|
263
|
+
approvalPolicy = "on-failure";
|
|
264
|
+
sandboxMode = "workspace-write";
|
|
265
|
+
webSearch = true;
|
|
266
|
+
cliFlags.push("--sandbox", "workspace-write");
|
|
267
|
+
break;
|
|
268
|
+
case "permissive":
|
|
269
|
+
approvalPolicy = "on-request";
|
|
270
|
+
sandboxMode = "workspace-write";
|
|
271
|
+
webSearch = true;
|
|
272
|
+
cliFlags.push("-a", "on-request");
|
|
273
|
+
break;
|
|
274
|
+
case "autonomous":
|
|
275
|
+
approvalPolicy = "never";
|
|
276
|
+
sandboxMode = "workspace-write";
|
|
277
|
+
webSearch = true;
|
|
278
|
+
cliFlags.push("--full-auto");
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
const config = {
|
|
282
|
+
approval_policy: approvalPolicy,
|
|
283
|
+
sandbox_mode: sandboxMode,
|
|
284
|
+
tools: {
|
|
285
|
+
web_search: webSearch
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
return {
|
|
289
|
+
preset,
|
|
290
|
+
cliFlags,
|
|
291
|
+
workspaceFiles: [
|
|
292
|
+
{
|
|
293
|
+
relativePath: ".codex/config.json",
|
|
294
|
+
content: JSON.stringify(config, null, 2),
|
|
295
|
+
format: "json"
|
|
296
|
+
}
|
|
297
|
+
],
|
|
298
|
+
envVars: {},
|
|
299
|
+
summary: `Codex: ${getPresetDefinition(preset).description}`
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
function generateAiderApprovalConfig(preset) {
|
|
303
|
+
const def = getPresetDefinition(preset);
|
|
304
|
+
const cliFlags = [];
|
|
305
|
+
const lines = [];
|
|
306
|
+
switch (preset) {
|
|
307
|
+
case "readonly":
|
|
308
|
+
lines.push("yes-always: false");
|
|
309
|
+
lines.push("no-auto-commits: true");
|
|
310
|
+
cliFlags.push("--no-auto-commits");
|
|
311
|
+
break;
|
|
312
|
+
case "standard":
|
|
313
|
+
lines.push("yes-always: false");
|
|
314
|
+
break;
|
|
315
|
+
case "permissive":
|
|
316
|
+
lines.push("yes-always: true");
|
|
317
|
+
cliFlags.push("--yes-always");
|
|
318
|
+
break;
|
|
319
|
+
case "autonomous":
|
|
320
|
+
lines.push("yes-always: true");
|
|
321
|
+
cliFlags.push("--yes-always");
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
return {
|
|
325
|
+
preset,
|
|
326
|
+
cliFlags,
|
|
327
|
+
workspaceFiles: [
|
|
328
|
+
{
|
|
329
|
+
relativePath: ".aider.conf.yml",
|
|
330
|
+
content: lines.join("\n") + "\n",
|
|
331
|
+
format: "yaml"
|
|
332
|
+
}
|
|
333
|
+
],
|
|
334
|
+
envVars: {},
|
|
335
|
+
summary: `Aider: ${def.description}`
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
function generateApprovalConfig(adapterType, preset) {
|
|
339
|
+
switch (adapterType) {
|
|
340
|
+
case "claude":
|
|
341
|
+
return generateClaudeApprovalConfig(preset);
|
|
342
|
+
case "gemini":
|
|
343
|
+
return generateGeminiApprovalConfig(preset);
|
|
344
|
+
case "codex":
|
|
345
|
+
return generateCodexApprovalConfig(preset);
|
|
346
|
+
case "aider":
|
|
347
|
+
return generateAiderApprovalConfig(preset);
|
|
348
|
+
default:
|
|
349
|
+
throw new Error(`Unknown adapter type: ${adapterType}`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
function listPresets() {
|
|
353
|
+
return [...PRESET_DEFINITIONS];
|
|
354
|
+
}
|
|
355
|
+
function getPresetDefinition(preset) {
|
|
356
|
+
const def = PRESET_DEFINITIONS.find((d) => d.preset === preset);
|
|
357
|
+
if (!def) {
|
|
358
|
+
throw new Error(`Unknown preset: ${preset}`);
|
|
359
|
+
}
|
|
360
|
+
return def;
|
|
361
|
+
}
|
|
362
|
+
|
|
7
363
|
// src/base-coding-adapter.ts
|
|
8
364
|
var BaseCodingAdapter = class extends ptyManager.BaseCLIAdapter {
|
|
9
365
|
/**
|
|
@@ -114,6 +470,40 @@ Docs: ${this.installation.docsUrl}`
|
|
|
114
470
|
content = content.trim();
|
|
115
471
|
return content;
|
|
116
472
|
}
|
|
473
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
474
|
+
// Approval Presets
|
|
475
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
476
|
+
/**
|
|
477
|
+
* Extract the approval preset from a spawn config, if set.
|
|
478
|
+
*/
|
|
479
|
+
getApprovalPreset(config) {
|
|
480
|
+
const adapterConfig = config.adapterConfig;
|
|
481
|
+
return adapterConfig?.approvalPreset;
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Generate the approval config for this adapter, if a preset is set.
|
|
485
|
+
*/
|
|
486
|
+
getApprovalConfig(config) {
|
|
487
|
+
const preset = this.getApprovalPreset(config);
|
|
488
|
+
if (!preset) return null;
|
|
489
|
+
return generateApprovalConfig(this.adapterType, preset);
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Write approval config files to a workspace directory.
|
|
493
|
+
* Returns the list of files written (absolute paths).
|
|
494
|
+
*/
|
|
495
|
+
async writeApprovalConfig(workspacePath, config) {
|
|
496
|
+
const approvalConfig = this.getApprovalConfig(config);
|
|
497
|
+
if (!approvalConfig) return [];
|
|
498
|
+
const written = [];
|
|
499
|
+
for (const file of approvalConfig.workspaceFiles) {
|
|
500
|
+
const fullPath = path.join(workspacePath, file.relativePath);
|
|
501
|
+
await promises.mkdir(path.dirname(fullPath), { recursive: true });
|
|
502
|
+
await promises.writeFile(fullPath, file.content, "utf-8");
|
|
503
|
+
written.push(fullPath);
|
|
504
|
+
}
|
|
505
|
+
return written;
|
|
506
|
+
}
|
|
117
507
|
/**
|
|
118
508
|
* Write content to this agent's memory file in a workspace.
|
|
119
509
|
* Creates parent directories as needed.
|
|
@@ -248,6 +638,10 @@ var ClaudeAdapter = class extends BaseCodingAdapter {
|
|
|
248
638
|
args.push("--cwd", config.workdir);
|
|
249
639
|
}
|
|
250
640
|
}
|
|
641
|
+
const approvalConfig = this.getApprovalConfig(config);
|
|
642
|
+
if (approvalConfig) {
|
|
643
|
+
args.push(...approvalConfig.cliFlags);
|
|
644
|
+
}
|
|
251
645
|
return args;
|
|
252
646
|
}
|
|
253
647
|
getEnv(config) {
|
|
@@ -480,6 +874,10 @@ var GeminiAdapter = class extends BaseCodingAdapter {
|
|
|
480
874
|
args.push("--cwd", config.workdir);
|
|
481
875
|
}
|
|
482
876
|
}
|
|
877
|
+
const approvalConfig = this.getApprovalConfig(config);
|
|
878
|
+
if (approvalConfig) {
|
|
879
|
+
args.push(...approvalConfig.cliFlags);
|
|
880
|
+
}
|
|
483
881
|
return args;
|
|
484
882
|
}
|
|
485
883
|
getEnv(config) {
|
|
@@ -784,6 +1182,10 @@ var CodexAdapter = class extends BaseCodingAdapter {
|
|
|
784
1182
|
args.push("--cwd", config.workdir);
|
|
785
1183
|
}
|
|
786
1184
|
}
|
|
1185
|
+
const approvalConfig = this.getApprovalConfig(config);
|
|
1186
|
+
if (approvalConfig) {
|
|
1187
|
+
args.push(...approvalConfig.cliFlags);
|
|
1188
|
+
}
|
|
787
1189
|
return args;
|
|
788
1190
|
}
|
|
789
1191
|
getEnv(config) {
|
|
@@ -1219,6 +1621,10 @@ var AiderAdapter = class extends BaseCodingAdapter {
|
|
|
1219
1621
|
if (credentials.anthropicKey) args.push("--api-key", `anthropic=${credentials.anthropicKey}`);
|
|
1220
1622
|
if (credentials.openaiKey) args.push("--api-key", `openai=${credentials.openaiKey}`);
|
|
1221
1623
|
if (credentials.googleKey) args.push("--api-key", `gemini=${credentials.googleKey}`);
|
|
1624
|
+
const approvalConfig = this.getApprovalConfig(config);
|
|
1625
|
+
if (approvalConfig) {
|
|
1626
|
+
args.push(...approvalConfig.cliFlags);
|
|
1627
|
+
}
|
|
1222
1628
|
return args;
|
|
1223
1629
|
}
|
|
1224
1630
|
getEnv(config) {
|
|
@@ -1575,18 +1981,31 @@ async function printMissingAdapters(types) {
|
|
|
1575
1981
|
}
|
|
1576
1982
|
|
|
1577
1983
|
exports.ADAPTER_TYPES = ADAPTER_TYPES;
|
|
1984
|
+
exports.AIDER_COMMAND_CATEGORIES = AIDER_COMMAND_CATEGORIES;
|
|
1578
1985
|
exports.AiderAdapter = AiderAdapter;
|
|
1579
1986
|
exports.BaseCodingAdapter = BaseCodingAdapter;
|
|
1987
|
+
exports.CLAUDE_TOOL_CATEGORIES = CLAUDE_TOOL_CATEGORIES;
|
|
1988
|
+
exports.CODEX_TOOL_CATEGORIES = CODEX_TOOL_CATEGORIES;
|
|
1580
1989
|
exports.ClaudeAdapter = ClaudeAdapter;
|
|
1581
1990
|
exports.CodexAdapter = CodexAdapter;
|
|
1991
|
+
exports.GEMINI_TOOL_CATEGORIES = GEMINI_TOOL_CATEGORIES;
|
|
1582
1992
|
exports.GeminiAdapter = GeminiAdapter;
|
|
1993
|
+
exports.PRESET_DEFINITIONS = PRESET_DEFINITIONS;
|
|
1994
|
+
exports.TOOL_CATEGORIES = TOOL_CATEGORIES;
|
|
1583
1995
|
exports.checkAdapters = checkAdapters;
|
|
1584
1996
|
exports.checkAllAdapters = checkAllAdapters;
|
|
1585
1997
|
exports.clearPatternCache = clearPatternCache;
|
|
1586
1998
|
exports.createAdapter = createAdapter;
|
|
1587
1999
|
exports.createAllAdapters = createAllAdapters;
|
|
2000
|
+
exports.generateAiderApprovalConfig = generateAiderApprovalConfig;
|
|
2001
|
+
exports.generateApprovalConfig = generateApprovalConfig;
|
|
2002
|
+
exports.generateClaudeApprovalConfig = generateClaudeApprovalConfig;
|
|
2003
|
+
exports.generateCodexApprovalConfig = generateCodexApprovalConfig;
|
|
2004
|
+
exports.generateGeminiApprovalConfig = generateGeminiApprovalConfig;
|
|
1588
2005
|
exports.getBaselinePatterns = getBaselinePatterns;
|
|
2006
|
+
exports.getPresetDefinition = getPresetDefinition;
|
|
1589
2007
|
exports.hasDynamicPatterns = hasDynamicPatterns;
|
|
2008
|
+
exports.listPresets = listPresets;
|
|
1590
2009
|
exports.loadPatterns = loadPatterns;
|
|
1591
2010
|
exports.loadPatternsSync = loadPatternsSync;
|
|
1592
2011
|
exports.preloadAllPatterns = preloadAllPatterns;
|