@bradtaylorsf/alpha-loop 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/LICENSE +21 -0
- package/README.md +294 -0
- package/agents/implementer.md +30 -0
- package/agents/reviewer.md +29 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +57 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/auth.d.ts +1 -0
- package/dist/commands/auth.js +89 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/history.d.ts +8 -0
- package/dist/commands/history.js +185 -0
- package/dist/commands/history.js.map +1 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +241 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/run.d.ts +15 -0
- package/dist/commands/run.js +321 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/scan.d.ts +1 -0
- package/dist/commands/scan.js +50 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/sync.d.ts +20 -0
- package/dist/commands/sync.js +149 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/vision.d.ts +1 -0
- package/dist/commands/vision.js +194 -0
- package/dist/commands/vision.js.map +1 -0
- package/dist/engine/agents.d.ts +41 -0
- package/dist/engine/agents.js +90 -0
- package/dist/engine/agents.js.map +1 -0
- package/dist/engine/config.d.ts +71 -0
- package/dist/engine/config.js +73 -0
- package/dist/engine/config.js.map +1 -0
- package/dist/engine/prerequisites.d.ts +34 -0
- package/dist/engine/prerequisites.js +90 -0
- package/dist/engine/prerequisites.js.map +1 -0
- package/dist/lib/agent.d.ts +25 -0
- package/dist/lib/agent.js +97 -0
- package/dist/lib/agent.js.map +1 -0
- package/dist/lib/config.d.ts +35 -0
- package/dist/lib/config.js +179 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/context.d.ts +17 -0
- package/dist/lib/context.js +96 -0
- package/dist/lib/context.js.map +1 -0
- package/dist/lib/github.d.ts +61 -0
- package/dist/lib/github.js +313 -0
- package/dist/lib/github.js.map +1 -0
- package/dist/lib/learning.d.ts +43 -0
- package/dist/lib/learning.js +207 -0
- package/dist/lib/learning.js.map +1 -0
- package/dist/lib/logger.d.ts +9 -0
- package/dist/lib/logger.js +28 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/pipeline.d.ts +18 -0
- package/dist/lib/pipeline.js +456 -0
- package/dist/lib/pipeline.js.map +1 -0
- package/dist/lib/preflight.d.ts +33 -0
- package/dist/lib/preflight.js +123 -0
- package/dist/lib/preflight.js.map +1 -0
- package/dist/lib/prerequisites.d.ts +12 -0
- package/dist/lib/prerequisites.js +54 -0
- package/dist/lib/prerequisites.js.map +1 -0
- package/dist/lib/prompts.d.ts +44 -0
- package/dist/lib/prompts.js +102 -0
- package/dist/lib/prompts.js.map +1 -0
- package/dist/lib/session.d.ts +28 -0
- package/dist/lib/session.js +173 -0
- package/dist/lib/session.js.map +1 -0
- package/dist/lib/shell.d.ts +32 -0
- package/dist/lib/shell.js +95 -0
- package/dist/lib/shell.js.map +1 -0
- package/dist/lib/testing.d.ts +10 -0
- package/dist/lib/testing.js +51 -0
- package/dist/lib/testing.js.map +1 -0
- package/dist/lib/verify.d.ts +18 -0
- package/dist/lib/verify.js +235 -0
- package/dist/lib/verify.js.map +1 -0
- package/dist/lib/vision.d.ts +9 -0
- package/dist/lib/vision.js +21 -0
- package/dist/lib/vision.js.map +1 -0
- package/dist/lib/worktree.d.ts +29 -0
- package/dist/lib/worktree.js +153 -0
- package/dist/lib/worktree.js.map +1 -0
- package/package.json +63 -0
- package/templates/agents/implementer.md +34 -0
- package/templates/agents/reviewer.md +48 -0
- package/templates/skills/code-review/SKILL.md +58 -0
- package/templates/skills/git-workflow/SKILL.md +53 -0
- package/templates/skills/implementation-planning/SKILL.md +64 -0
- package/templates/skills/security-analysis/SKILL.md +560 -0
- package/templates/skills/security-analysis/scripts/security-scanner.sh +227 -0
- package/templates/skills/test-robustness/SKILL.md +897 -0
- package/templates/skills/testing-patterns/SKILL.md +75 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import * as readline from 'node:readline';
|
|
4
|
+
import { exec } from '../lib/shell.js';
|
|
5
|
+
import { assertSafeShellArg, loadConfig } from '../lib/config.js';
|
|
6
|
+
import { log } from '../lib/logger.js';
|
|
7
|
+
function ask(rl, question) {
|
|
8
|
+
return new Promise((resolve) => {
|
|
9
|
+
rl.question(question, (answer) => resolve(answer.trim()));
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
const USER_TYPES = {
|
|
13
|
+
'1': 'Technical users (developers, engineers)',
|
|
14
|
+
'2': 'Semi-technical (power users, admins)',
|
|
15
|
+
'3': 'Non-technical (general consumers, elderly, caregivers) \u2014 UI must be simple, accessible, and forgiving',
|
|
16
|
+
'4': 'Mixed audience \u2014 needs both simple and advanced interfaces',
|
|
17
|
+
};
|
|
18
|
+
const STAGES = {
|
|
19
|
+
'1': 'Brand new / greenfield \u2014 focus on getting core architecture right',
|
|
20
|
+
'2': 'MVP / early development \u2014 focus on core flows working end-to-end',
|
|
21
|
+
'3': 'Working product \u2014 adding features without breaking existing functionality',
|
|
22
|
+
'4': 'Mature product \u2014 maintenance, optimization, and careful changes',
|
|
23
|
+
};
|
|
24
|
+
const PRIORITIES = {
|
|
25
|
+
'1': 'Core functionality \u2014 make it work reliably before making it pretty',
|
|
26
|
+
'2': 'User experience \u2014 the product works, now make it delightful',
|
|
27
|
+
'3': 'Scale and performance \u2014 handle more load, optimize bottlenecks',
|
|
28
|
+
'4': 'Security and compliance \u2014 harden, audit, meet regulatory requirements',
|
|
29
|
+
};
|
|
30
|
+
export async function visionCommand() {
|
|
31
|
+
if (!process.stdin.isTTY) {
|
|
32
|
+
log.info('Not running in an interactive terminal. Skipping vision setup.');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const projectDir = process.cwd();
|
|
36
|
+
const contextDir = path.join(projectDir, '.alpha-loop');
|
|
37
|
+
const visionFile = path.join(contextDir, 'vision.md');
|
|
38
|
+
const config = loadConfig();
|
|
39
|
+
fs.mkdirSync(contextDir, { recursive: true });
|
|
40
|
+
const rl = readline.createInterface({
|
|
41
|
+
input: process.stdin,
|
|
42
|
+
output: process.stdout,
|
|
43
|
+
});
|
|
44
|
+
try {
|
|
45
|
+
// Check if vision exists
|
|
46
|
+
if (fs.existsSync(visionFile)) {
|
|
47
|
+
console.log('');
|
|
48
|
+
console.log('\x1b[1mCurrent project vision:\x1b[0m');
|
|
49
|
+
console.log('');
|
|
50
|
+
console.log(fs.readFileSync(visionFile, 'utf-8'));
|
|
51
|
+
console.log('');
|
|
52
|
+
const updateChoice = await ask(rl, 'Update this vision? [y/N]: ');
|
|
53
|
+
if (updateChoice.toLowerCase() !== 'y') {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
console.log('');
|
|
59
|
+
console.log('\x1b[1m\x1b[36mNo project vision found. Let\'s set one up.\x1b[0m');
|
|
60
|
+
console.log('This helps the agent understand what it\'s building and make better decisions.');
|
|
61
|
+
console.log('');
|
|
62
|
+
}
|
|
63
|
+
// Question 1: What is this project?
|
|
64
|
+
console.log('\x1b[1mWhat is this project?\x1b[0m (1-2 sentences)');
|
|
65
|
+
const projectDescription = await ask(rl, '> ');
|
|
66
|
+
console.log('');
|
|
67
|
+
// Question 2: Target users
|
|
68
|
+
console.log('\x1b[1mWho are the target users?\x1b[0m');
|
|
69
|
+
console.log(' [1] Technical users (developers, engineers)');
|
|
70
|
+
console.log(' [2] Semi-technical (power users, admins)');
|
|
71
|
+
console.log(' [3] Non-technical (general consumers, elderly, caregivers)');
|
|
72
|
+
console.log(' [4] Mixed audience');
|
|
73
|
+
const userTypeChoice = await ask(rl, '> ');
|
|
74
|
+
const userType = USER_TYPES[userTypeChoice] ?? userTypeChoice;
|
|
75
|
+
console.log('');
|
|
76
|
+
// Question 3: Project stage
|
|
77
|
+
console.log('\x1b[1mWhat stage is the project in?\x1b[0m');
|
|
78
|
+
console.log(' [1] Brand new / greenfield');
|
|
79
|
+
console.log(' [2] MVP / early development');
|
|
80
|
+
console.log(' [3] Working product, adding features');
|
|
81
|
+
console.log(' [4] Mature product, maintenance mode');
|
|
82
|
+
const stageChoice = await ask(rl, '> ');
|
|
83
|
+
const projectStage = STAGES[stageChoice] ?? stageChoice;
|
|
84
|
+
console.log('');
|
|
85
|
+
// Question 4: Current priority
|
|
86
|
+
console.log('\x1b[1mWhat matters most right now?\x1b[0m');
|
|
87
|
+
console.log(' [1] Core functionality works reliably');
|
|
88
|
+
console.log(' [2] User experience and polish');
|
|
89
|
+
console.log(' [3] Scale and performance');
|
|
90
|
+
console.log(' [4] Security and compliance');
|
|
91
|
+
console.log(' [5] Something else (type it)');
|
|
92
|
+
const priorityChoice = await ask(rl, '> ');
|
|
93
|
+
const priority = PRIORITIES[priorityChoice] ?? priorityChoice;
|
|
94
|
+
console.log('');
|
|
95
|
+
// Question 5: UX/design guidelines
|
|
96
|
+
console.log('\x1b[1mAny UX or design guidelines?\x1b[0m (press Enter to skip)');
|
|
97
|
+
console.log(" Examples: 'mobile-first', 'dark mode', 'WCAG AA accessible', 'minimal UI'");
|
|
98
|
+
const uxGuidelines = await ask(rl, '> ');
|
|
99
|
+
console.log('');
|
|
100
|
+
// Question 6: North star issue
|
|
101
|
+
console.log('\x1b[1mLink a north star issue or paste additional context?\x1b[0m');
|
|
102
|
+
console.log(' Paste a GitHub issue URL, issue number, or freeform text (Enter to skip)');
|
|
103
|
+
const northStarInput = await ask(rl, '> ');
|
|
104
|
+
console.log('');
|
|
105
|
+
let northStarContent = '';
|
|
106
|
+
if (northStarInput) {
|
|
107
|
+
const issueMatch = northStarInput.match(/^(\d+)$/) ?? northStarInput.match(/issues\/(\d+)/);
|
|
108
|
+
if (issueMatch) {
|
|
109
|
+
const issueNum = issueMatch[1];
|
|
110
|
+
log.info(`Fetching issue #${issueNum}...`);
|
|
111
|
+
const repo = assertSafeShellArg(config.repo, 'repo');
|
|
112
|
+
const result = exec(`gh issue view ${issueNum} --repo ${repo} --json title,body`);
|
|
113
|
+
if (result.exitCode === 0 && result.stdout) {
|
|
114
|
+
const issueData = JSON.parse(result.stdout);
|
|
115
|
+
northStarContent = `### North Star: #${issueNum} \u2014 ${issueData.title}\n\n${issueData.body}`;
|
|
116
|
+
log.success(`Fetched issue #${issueNum}: ${issueData.title}`);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
log.warn(`Could not fetch issue #${issueNum}`);
|
|
120
|
+
northStarContent = northStarInput;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
northStarContent = northStarInput;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Question 7: Anything else?
|
|
128
|
+
console.log('\x1b[1mAnything else the agent should always keep in mind?\x1b[0m (Enter to skip)');
|
|
129
|
+
const additionalContext = await ask(rl, '> ');
|
|
130
|
+
console.log('');
|
|
131
|
+
// Synthesize with Claude
|
|
132
|
+
log.step('Generating project vision...');
|
|
133
|
+
const visionPrompt = `Synthesize the following inputs into a concise project vision document. This will be read by AI agents before every task to guide their decisions.
|
|
134
|
+
|
|
135
|
+
Project description: ${projectDescription}
|
|
136
|
+
Target users: ${userType}
|
|
137
|
+
Project stage: ${projectStage}
|
|
138
|
+
Current priority: ${priority}
|
|
139
|
+
UX guidelines: ${uxGuidelines || 'None specified'}
|
|
140
|
+
Additional context: ${additionalContext || 'None'}
|
|
141
|
+
${northStarContent ? `\nNorth star context:\n${northStarContent}` : ''}
|
|
142
|
+
|
|
143
|
+
Output ONLY this markdown structure. Be specific and actionable. Under 500 words total.
|
|
144
|
+
|
|
145
|
+
## What We're Building
|
|
146
|
+
(2-3 sentences synthesizing the project description and north star)
|
|
147
|
+
|
|
148
|
+
## Who It's For
|
|
149
|
+
(Target users and what that means for UX/design decisions)
|
|
150
|
+
|
|
151
|
+
## Current Stage & Priority
|
|
152
|
+
(Where the project is and what matters most right now)
|
|
153
|
+
|
|
154
|
+
## Decision Guidelines
|
|
155
|
+
(5-7 bullet points the agent should follow when making choices about implementation, UX, what to build vs defer, etc. Derived from all inputs above.)
|
|
156
|
+
|
|
157
|
+
## What Good Looks Like
|
|
158
|
+
(3-4 bullet points describing the quality bar — what a successful implementation looks like for this project)`;
|
|
159
|
+
const model = assertSafeShellArg(config.model ?? 'opus', 'model');
|
|
160
|
+
const visionResult = exec(`echo ${JSON.stringify(visionPrompt)} | claude -p --model ${model} --dangerously-skip-permissions --output-format text 2>/dev/null`, { cwd: projectDir });
|
|
161
|
+
if (visionResult.exitCode === 0 && visionResult.stdout) {
|
|
162
|
+
fs.writeFileSync(visionFile, visionResult.stdout + '\n');
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
// Fallback: write raw inputs
|
|
166
|
+
log.warn('Claude synthesis failed, saving raw inputs');
|
|
167
|
+
const raw = [
|
|
168
|
+
'## What We\'re Building',
|
|
169
|
+
projectDescription,
|
|
170
|
+
'',
|
|
171
|
+
'## Who It\'s For',
|
|
172
|
+
userType,
|
|
173
|
+
'',
|
|
174
|
+
'## Current Stage & Priority',
|
|
175
|
+
projectStage,
|
|
176
|
+
`Priority: ${priority}`,
|
|
177
|
+
'',
|
|
178
|
+
'## UX Guidelines',
|
|
179
|
+
uxGuidelines || 'None specified',
|
|
180
|
+
'',
|
|
181
|
+
...(northStarContent ? ['## North Star', northStarContent, ''] : []),
|
|
182
|
+
...(additionalContext ? ['## Additional Context', additionalContext, ''] : []),
|
|
183
|
+
].join('\n');
|
|
184
|
+
fs.writeFileSync(visionFile, raw + '\n');
|
|
185
|
+
}
|
|
186
|
+
log.success(`Project vision saved to ${visionFile}`);
|
|
187
|
+
console.log('');
|
|
188
|
+
console.log(fs.readFileSync(visionFile, 'utf-8'));
|
|
189
|
+
}
|
|
190
|
+
finally {
|
|
191
|
+
rl.close();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=vision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vision.js","sourceRoot":"","sources":["../../src/commands/vision.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Spawn Module
|
|
3
|
+
* ==================
|
|
4
|
+
*
|
|
5
|
+
* Handles spawning different AI CLI agents (Claude, Codex, OpenCode)
|
|
6
|
+
* with the correct CLI flags per agent type.
|
|
7
|
+
*
|
|
8
|
+
* Adding a new agent: add a case to AGENT_CLI_MAP and buildAgentArgs().
|
|
9
|
+
*/
|
|
10
|
+
import { type ChildProcess } from 'node:child_process';
|
|
11
|
+
import type { AgentConfig } from './config.js';
|
|
12
|
+
/**
|
|
13
|
+
* CLI reference for each supported agent.
|
|
14
|
+
* Extend this map to add new agent types.
|
|
15
|
+
*/
|
|
16
|
+
export declare const AGENT_CLI_MAP: Record<string, {
|
|
17
|
+
command: string;
|
|
18
|
+
promptFlag: string;
|
|
19
|
+
modelFlag: string;
|
|
20
|
+
permissionFlag?: string;
|
|
21
|
+
supportsMaxTurns: boolean;
|
|
22
|
+
maxTurnsFlag?: string;
|
|
23
|
+
}>;
|
|
24
|
+
export interface AgentArgs {
|
|
25
|
+
command: string;
|
|
26
|
+
args: string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Constructs the CLI command and arguments for spawning an agent.
|
|
30
|
+
* Throws if the agent type is not recognized.
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildAgentArgs(config: AgentConfig & {
|
|
33
|
+
model: string;
|
|
34
|
+
}, prompt: string): AgentArgs;
|
|
35
|
+
/**
|
|
36
|
+
* Spawns an agent subprocess with the correct CLI flags.
|
|
37
|
+
* Returns the ChildProcess for the caller to manage (listen to events, pipe stdio, etc.).
|
|
38
|
+
*/
|
|
39
|
+
export declare function spawnAgent(config: AgentConfig & {
|
|
40
|
+
model: string;
|
|
41
|
+
}, prompt: string, cwd: string): ChildProcess;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Spawn Module
|
|
3
|
+
* ==================
|
|
4
|
+
*
|
|
5
|
+
* Handles spawning different AI CLI agents (Claude, Codex, OpenCode)
|
|
6
|
+
* with the correct CLI flags per agent type.
|
|
7
|
+
*
|
|
8
|
+
* Adding a new agent: add a case to AGENT_CLI_MAP and buildAgentArgs().
|
|
9
|
+
*/
|
|
10
|
+
import { spawn } from 'node:child_process';
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Agent CLI Mapping
|
|
13
|
+
// ============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* CLI reference for each supported agent.
|
|
16
|
+
* Extend this map to add new agent types.
|
|
17
|
+
*/
|
|
18
|
+
export const AGENT_CLI_MAP = {
|
|
19
|
+
claude: {
|
|
20
|
+
command: 'claude',
|
|
21
|
+
promptFlag: '-p',
|
|
22
|
+
modelFlag: '--model',
|
|
23
|
+
permissionFlag: '--dangerously-skip-permissions',
|
|
24
|
+
supportsMaxTurns: true,
|
|
25
|
+
maxTurnsFlag: '--max-turns',
|
|
26
|
+
},
|
|
27
|
+
codex: {
|
|
28
|
+
command: 'codex',
|
|
29
|
+
promptFlag: '-q',
|
|
30
|
+
modelFlag: '--model',
|
|
31
|
+
permissionFlag: '--auto-edit',
|
|
32
|
+
supportsMaxTurns: false,
|
|
33
|
+
},
|
|
34
|
+
opencode: {
|
|
35
|
+
command: 'opencode',
|
|
36
|
+
promptFlag: 'run',
|
|
37
|
+
modelFlag: '--model',
|
|
38
|
+
supportsMaxTurns: false,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Constructs the CLI command and arguments for spawning an agent.
|
|
43
|
+
* Throws if the agent type is not recognized.
|
|
44
|
+
*/
|
|
45
|
+
export function buildAgentArgs(config, prompt) {
|
|
46
|
+
const agentDef = AGENT_CLI_MAP[config.agent];
|
|
47
|
+
if (!agentDef) {
|
|
48
|
+
throw new Error(`Unknown agent type: "${config.agent}". Supported agents: ${Object.keys(AGENT_CLI_MAP).join(', ')}`);
|
|
49
|
+
}
|
|
50
|
+
const args = [];
|
|
51
|
+
// For opencode, "run" is a subcommand, not a flag
|
|
52
|
+
if (config.agent === 'opencode') {
|
|
53
|
+
args.push(agentDef.promptFlag); // 'run'
|
|
54
|
+
}
|
|
55
|
+
// Model flag
|
|
56
|
+
args.push(agentDef.modelFlag, config.model);
|
|
57
|
+
// Permission flag (if agent supports it)
|
|
58
|
+
if (agentDef.permissionFlag) {
|
|
59
|
+
args.push(agentDef.permissionFlag);
|
|
60
|
+
}
|
|
61
|
+
// Max turns (only if agent supports it and value is provided)
|
|
62
|
+
if (config.maxTurns != null && agentDef.supportsMaxTurns && agentDef.maxTurnsFlag) {
|
|
63
|
+
args.push(agentDef.maxTurnsFlag, String(config.maxTurns));
|
|
64
|
+
}
|
|
65
|
+
// Prompt flag — for claude/codex it's a flag before the prompt text
|
|
66
|
+
if (config.agent !== 'opencode') {
|
|
67
|
+
args.push(agentDef.promptFlag, prompt);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// opencode takes prompt as a positional arg after 'run'
|
|
71
|
+
args.push(prompt);
|
|
72
|
+
}
|
|
73
|
+
return { command: agentDef.command, args };
|
|
74
|
+
}
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// Spawn Agent
|
|
77
|
+
// ============================================================================
|
|
78
|
+
/**
|
|
79
|
+
* Spawns an agent subprocess with the correct CLI flags.
|
|
80
|
+
* Returns the ChildProcess for the caller to manage (listen to events, pipe stdio, etc.).
|
|
81
|
+
*/
|
|
82
|
+
export function spawnAgent(config, prompt, cwd) {
|
|
83
|
+
const { command, args } = buildAgentArgs(config, prompt);
|
|
84
|
+
return spawn(command, args, {
|
|
85
|
+
cwd,
|
|
86
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
87
|
+
env: { ...process.env },
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/engine/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAG9D,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAOrB;IACH,MAAM,EAAE;QACN,OAAO,EAAE,QAAQ;QACjB,UAAU,EAAE,IAAI;QAChB,SAAS,EAAE,SAAS;QACpB,cAAc,EAAE,gCAAgC;QAChD,gBAAgB,EAAE,IAAI;QACtB,YAAY,EAAE,aAAa;KAC5B;IACD,KAAK,EAAE;QACL,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,IAAI;QAChB,SAAS,EAAE,SAAS;QACpB,cAAc,EAAE,aAAa;QAC7B,gBAAgB,EAAE,KAAK;KACxB;IACD,QAAQ,EAAE;QACR,OAAO,EAAE,UAAU;QACnB,UAAU,EAAE,KAAK;QACjB,SAAS,EAAE,SAAS;QACpB,gBAAgB,EAAE,KAAK;KACxB;CACF,CAAC;AAWF;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAAuC,EAAE,MAAc;IACpF,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,wBAAwB,MAAM,CAAC,KAAK,wBAAwB,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACpG,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAa,EAAE,CAAC;IAE1B,kDAAkD;IAClD,IAAI,MAAM,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ;IAC1C,CAAC;IAED,aAAa;IACb,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAE5C,yCAAyC;IACzC,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IACrC,CAAC;IAED,8DAA8D;IAC9D,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,IAAI,QAAQ,CAAC,gBAAgB,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;QAClF,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,oEAAoE;IACpE,IAAI,MAAM,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC;SAAM,CAAC;QACN,wDAAwD;QACxD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;AAC7C,CAAC;AAED,+EAA+E;AAC/E,cAAc;AACd,+EAA+E;AAE/E;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,MAAuC,EAAE,MAAc,EAAE,GAAW;IAC7F,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEzD,OAAO,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;QAC1B,GAAG;QACH,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;QAC/B,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;KACxB,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Module
|
|
3
|
+
* ====================
|
|
4
|
+
*
|
|
5
|
+
* Loads and validates .alpha-loop.yaml with per-stage agent/model configuration.
|
|
6
|
+
* Uses Zod for schema validation with sensible defaults.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
export declare const STAGE_NAMES: readonly ["implement", "fix", "review", "verify", "learn", "aggregate"];
|
|
10
|
+
export type StageName = (typeof STAGE_NAMES)[number];
|
|
11
|
+
export declare const DEFAULT_AGENT = "claude";
|
|
12
|
+
export declare const DEFAULT_MODEL = "opus";
|
|
13
|
+
export declare const AgentConfigSchema: z.ZodObject<{
|
|
14
|
+
agent: z.ZodDefault<z.ZodString>;
|
|
15
|
+
model: z.ZodOptional<z.ZodString>;
|
|
16
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
17
|
+
}, z.core.$strip>;
|
|
18
|
+
export type AgentConfig = z.infer<typeof AgentConfigSchema>;
|
|
19
|
+
export declare const ConfigSchema: z.ZodObject<{
|
|
20
|
+
repo: z.ZodString;
|
|
21
|
+
project: z.ZodOptional<z.ZodNumber>;
|
|
22
|
+
model: z.ZodDefault<z.ZodString>;
|
|
23
|
+
review_model: z.ZodOptional<z.ZodString>;
|
|
24
|
+
max_turns: z.ZodOptional<z.ZodNumber>;
|
|
25
|
+
label: z.ZodDefault<z.ZodString>;
|
|
26
|
+
base_branch: z.ZodDefault<z.ZodString>;
|
|
27
|
+
test_command: z.ZodDefault<z.ZodString>;
|
|
28
|
+
poll_interval: z.ZodDefault<z.ZodNumber>;
|
|
29
|
+
stages: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
30
|
+
implement: z.ZodOptional<z.ZodObject<{
|
|
31
|
+
agent: z.ZodDefault<z.ZodString>;
|
|
32
|
+
model: z.ZodOptional<z.ZodString>;
|
|
33
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
34
|
+
}, z.core.$strip>>;
|
|
35
|
+
fix: z.ZodOptional<z.ZodObject<{
|
|
36
|
+
agent: z.ZodDefault<z.ZodString>;
|
|
37
|
+
model: z.ZodOptional<z.ZodString>;
|
|
38
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
39
|
+
}, z.core.$strip>>;
|
|
40
|
+
review: z.ZodOptional<z.ZodObject<{
|
|
41
|
+
agent: z.ZodDefault<z.ZodString>;
|
|
42
|
+
model: z.ZodOptional<z.ZodString>;
|
|
43
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
44
|
+
}, z.core.$strip>>;
|
|
45
|
+
verify: z.ZodOptional<z.ZodObject<{
|
|
46
|
+
agent: z.ZodDefault<z.ZodString>;
|
|
47
|
+
model: z.ZodOptional<z.ZodString>;
|
|
48
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
49
|
+
}, z.core.$strip>>;
|
|
50
|
+
learn: z.ZodOptional<z.ZodObject<{
|
|
51
|
+
agent: z.ZodDefault<z.ZodString>;
|
|
52
|
+
model: z.ZodOptional<z.ZodString>;
|
|
53
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
54
|
+
}, z.core.$strip>>;
|
|
55
|
+
aggregate: z.ZodOptional<z.ZodObject<{
|
|
56
|
+
agent: z.ZodDefault<z.ZodString>;
|
|
57
|
+
model: z.ZodOptional<z.ZodString>;
|
|
58
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
59
|
+
}, z.core.$strip>>;
|
|
60
|
+
}, z.core.$strict>>>;
|
|
61
|
+
}, z.core.$strip>;
|
|
62
|
+
export type Config = z.infer<typeof ConfigSchema>;
|
|
63
|
+
export declare function loadConfig(cwd: string): Config;
|
|
64
|
+
/**
|
|
65
|
+
* Resolves the agent configuration for a given pipeline stage.
|
|
66
|
+
* Merges stage-specific config with global defaults:
|
|
67
|
+
* - agent: stage.agent → 'claude'
|
|
68
|
+
* - model: stage.model → config.model → 'opus'
|
|
69
|
+
* - maxTurns: stage.maxTurns → config.max_turns → undefined
|
|
70
|
+
*/
|
|
71
|
+
export declare function resolveStageConfig(config: Config, stage: StageName): Required<Pick<AgentConfig, 'agent' | 'model'>> & Pick<AgentConfig, 'maxTurns'>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Module
|
|
3
|
+
* ====================
|
|
4
|
+
*
|
|
5
|
+
* Loads and validates .alpha-loop.yaml with per-stage agent/model configuration.
|
|
6
|
+
* Uses Zod for schema validation with sensible defaults.
|
|
7
|
+
*/
|
|
8
|
+
import { readFileSync } from 'node:fs';
|
|
9
|
+
import { resolve } from 'node:path';
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { parse as parseYaml } from 'yaml';
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Constants
|
|
14
|
+
// ============================================================================
|
|
15
|
+
export const STAGE_NAMES = ['implement', 'fix', 'review', 'verify', 'learn', 'aggregate'];
|
|
16
|
+
export const DEFAULT_AGENT = 'claude';
|
|
17
|
+
export const DEFAULT_MODEL = 'opus';
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Schemas
|
|
20
|
+
// ============================================================================
|
|
21
|
+
export const AgentConfigSchema = z.object({
|
|
22
|
+
agent: z.string().default(DEFAULT_AGENT),
|
|
23
|
+
model: z.string().optional(),
|
|
24
|
+
maxTurns: z.number().optional(),
|
|
25
|
+
});
|
|
26
|
+
const StagesSchema = z.object({
|
|
27
|
+
implement: AgentConfigSchema.optional(),
|
|
28
|
+
fix: AgentConfigSchema.optional(),
|
|
29
|
+
review: AgentConfigSchema.optional(),
|
|
30
|
+
verify: AgentConfigSchema.optional(),
|
|
31
|
+
learn: AgentConfigSchema.optional(),
|
|
32
|
+
aggregate: AgentConfigSchema.optional(),
|
|
33
|
+
}).strict().optional().default({});
|
|
34
|
+
export const ConfigSchema = z.object({
|
|
35
|
+
repo: z.string(),
|
|
36
|
+
project: z.number().optional(),
|
|
37
|
+
model: z.string().default(DEFAULT_MODEL),
|
|
38
|
+
review_model: z.string().optional(),
|
|
39
|
+
max_turns: z.number().optional(),
|
|
40
|
+
label: z.string().default('ready'),
|
|
41
|
+
base_branch: z.string().default('master'),
|
|
42
|
+
test_command: z.string().default('pnpm test'),
|
|
43
|
+
poll_interval: z.number().default(60),
|
|
44
|
+
stages: StagesSchema,
|
|
45
|
+
});
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// Config Loading
|
|
48
|
+
// ============================================================================
|
|
49
|
+
export function loadConfig(cwd) {
|
|
50
|
+
const configPath = resolve(cwd, '.alpha-loop.yaml');
|
|
51
|
+
const raw = readFileSync(configPath, 'utf-8');
|
|
52
|
+
const parsed = parseYaml(raw);
|
|
53
|
+
return ConfigSchema.parse(parsed);
|
|
54
|
+
}
|
|
55
|
+
// ============================================================================
|
|
56
|
+
// Stage Config Resolution
|
|
57
|
+
// ============================================================================
|
|
58
|
+
/**
|
|
59
|
+
* Resolves the agent configuration for a given pipeline stage.
|
|
60
|
+
* Merges stage-specific config with global defaults:
|
|
61
|
+
* - agent: stage.agent → 'claude'
|
|
62
|
+
* - model: stage.model → config.model → 'opus'
|
|
63
|
+
* - maxTurns: stage.maxTurns → config.max_turns → undefined
|
|
64
|
+
*/
|
|
65
|
+
export function resolveStageConfig(config, stage) {
|
|
66
|
+
const stageConfig = config.stages[stage];
|
|
67
|
+
return {
|
|
68
|
+
agent: stageConfig?.agent ?? DEFAULT_AGENT,
|
|
69
|
+
model: stageConfig?.model ?? config.model ?? DEFAULT_MODEL,
|
|
70
|
+
maxTurns: stageConfig?.maxTurns ?? config.max_turns,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/engine/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prerequisites Module
|
|
3
|
+
* ====================
|
|
4
|
+
*
|
|
5
|
+
* Verifies that all configured AI CLI agents are installed before starting the pipeline.
|
|
6
|
+
* Groups stages by agent for clear diagnostic output.
|
|
7
|
+
*/
|
|
8
|
+
import { type Config, type StageName } from './config.js';
|
|
9
|
+
export interface AgentCheckResult {
|
|
10
|
+
agent: string;
|
|
11
|
+
installed: boolean;
|
|
12
|
+
stages: StageName[];
|
|
13
|
+
}
|
|
14
|
+
export interface PrerequisiteResult {
|
|
15
|
+
ok: boolean;
|
|
16
|
+
results: AgentCheckResult[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Checks whether a CLI command is available on the system PATH.
|
|
20
|
+
*/
|
|
21
|
+
export declare function isCommandAvailable(command: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Checks all agents configured across pipeline stages.
|
|
24
|
+
* Returns structured results showing which agents are installed and which stages they serve.
|
|
25
|
+
*/
|
|
26
|
+
export declare function checkAgents(config: Config): PrerequisiteResult;
|
|
27
|
+
/**
|
|
28
|
+
* Formats the prerequisite check results for console output.
|
|
29
|
+
*/
|
|
30
|
+
export declare function formatCheckResults(result: PrerequisiteResult): string;
|
|
31
|
+
/**
|
|
32
|
+
* Formats the pipeline startup summary showing per-stage configuration.
|
|
33
|
+
*/
|
|
34
|
+
export declare function formatPipelineSummary(config: Config): string;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prerequisites Module
|
|
3
|
+
* ====================
|
|
4
|
+
*
|
|
5
|
+
* Verifies that all configured AI CLI agents are installed before starting the pipeline.
|
|
6
|
+
* Groups stages by agent for clear diagnostic output.
|
|
7
|
+
*/
|
|
8
|
+
import { execSync } from 'node:child_process';
|
|
9
|
+
import { STAGE_NAMES, resolveStageConfig } from './config.js';
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Agent Check
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Checks whether a CLI command is available on the system PATH.
|
|
15
|
+
*/
|
|
16
|
+
export function isCommandAvailable(command) {
|
|
17
|
+
// Validate command name to prevent shell injection from user-controlled config
|
|
18
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(command)) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
execSync(`which ${command}`, { stdio: 'ignore' });
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Checks all agents configured across pipeline stages.
|
|
31
|
+
* Returns structured results showing which agents are installed and which stages they serve.
|
|
32
|
+
*/
|
|
33
|
+
export function checkAgents(config) {
|
|
34
|
+
// Collect stages grouped by agent
|
|
35
|
+
const agentStages = new Map();
|
|
36
|
+
for (const stage of STAGE_NAMES) {
|
|
37
|
+
const { agent } = resolveStageConfig(config, stage);
|
|
38
|
+
const stages = agentStages.get(agent) ?? [];
|
|
39
|
+
stages.push(stage);
|
|
40
|
+
agentStages.set(agent, stages);
|
|
41
|
+
}
|
|
42
|
+
// Check each unique agent
|
|
43
|
+
const results = [];
|
|
44
|
+
for (const [agent, stages] of agentStages) {
|
|
45
|
+
results.push({
|
|
46
|
+
agent,
|
|
47
|
+
installed: isCommandAvailable(agent),
|
|
48
|
+
stages,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
ok: results.every(r => r.installed),
|
|
53
|
+
results,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
// ============================================================================
|
|
57
|
+
// Formatting
|
|
58
|
+
// ============================================================================
|
|
59
|
+
/**
|
|
60
|
+
* Formats the prerequisite check results for console output.
|
|
61
|
+
*/
|
|
62
|
+
export function formatCheckResults(result) {
|
|
63
|
+
const lines = ['Checking agents...'];
|
|
64
|
+
for (const r of result.results) {
|
|
65
|
+
const icon = r.installed ? '\u2713' : '\u2717';
|
|
66
|
+
const stageList = r.stages.join(', ');
|
|
67
|
+
lines.push(` ${icon} ${r.agent} (${stageList})`);
|
|
68
|
+
}
|
|
69
|
+
if (!result.ok) {
|
|
70
|
+
const missing = result.results.filter(r => !r.installed);
|
|
71
|
+
for (const m of missing) {
|
|
72
|
+
lines.push(`\nError: "${m.agent}" is not installed. Affected stages: ${m.stages.join(', ')}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return lines.join('\n');
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Formats the pipeline startup summary showing per-stage configuration.
|
|
79
|
+
*/
|
|
80
|
+
export function formatPipelineSummary(config) {
|
|
81
|
+
const lines = ['Pipeline:'];
|
|
82
|
+
for (const stage of STAGE_NAMES) {
|
|
83
|
+
const sc = resolveStageConfig(config, stage);
|
|
84
|
+
const turns = sc.maxTurns ? ` (${sc.maxTurns} turns)` : '';
|
|
85
|
+
const padded = `${stage}:`.padEnd(14);
|
|
86
|
+
lines.push(` ${padded}${sc.agent}/${sc.model}${turns}`);
|
|
87
|
+
}
|
|
88
|
+
return lines.join('\n');
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=prerequisites.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prerequisites.js","sourceRoot":"","sources":["../../src/engine/prerequisites.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAA+B,WAAW,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAiB3F,+EAA+E;AAC/E,cAAc;AACd,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,+EAA+E;IAC/E,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC;QACH,QAAQ,CAAC,SAAS,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,kCAAkC;IAClC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAuB,CAAC;IAEnD,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;QAChC,MAAM,EAAE,KAAK,EAAE,GAAG,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACjC,CAAC;IAED,0BAA0B;IAC1B,MAAM,OAAO,GAAuB,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC1C,OAAO,CAAC,IAAI,CAAC;YACX,KAAK;YACL,SAAS,EAAE,kBAAkB,CAAC,KAAK,CAAC;YACpC,MAAM;SACP,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACnC,OAAO;KACR,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,aAAa;AACb,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAA0B;IAC3D,MAAM,KAAK,GAAa,CAAC,oBAAoB,CAAC,CAAC;IAE/C,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC/C,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,GAAG,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACzD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,KAAK,wCAAwC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,MAAM,KAAK,GAAa,CAAC,WAAW,CAAC,CAAC;IAEtC,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;QAChC,MAAM,EAAE,GAAG,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,QAAQ,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,MAAM,MAAM,GAAG,GAAG,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,GAAG,KAAK,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type AgentResult = {
|
|
2
|
+
exitCode: number;
|
|
3
|
+
output: string;
|
|
4
|
+
duration: number;
|
|
5
|
+
};
|
|
6
|
+
export type AgentOptions = {
|
|
7
|
+
agent: 'claude' | 'codex' | 'opencode';
|
|
8
|
+
model: string;
|
|
9
|
+
prompt: string;
|
|
10
|
+
cwd: string;
|
|
11
|
+
logFile?: string;
|
|
12
|
+
verbose?: boolean;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Build CLI command and args for a given agent type.
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildAgentArgs(options: AgentOptions): {
|
|
18
|
+
command: string;
|
|
19
|
+
args: string[];
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Spawn an AI agent with a prompt.
|
|
23
|
+
* Streams output to terminal in real-time while capturing it.
|
|
24
|
+
*/
|
|
25
|
+
export declare function spawnAgent(options: AgentOptions): Promise<AgentResult>;
|