@itz4blitz/agentful 1.2.0 → 1.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 +28 -1
- package/bin/cli.js +11 -1055
- package/bin/hooks/block-file-creation.js +271 -0
- package/bin/hooks/product-spec-watcher.js +151 -0
- package/lib/index.js +0 -11
- package/lib/init.js +2 -21
- package/lib/parallel-execution.js +235 -0
- package/lib/presets.js +26 -4
- package/package.json +4 -7
- package/template/.claude/agents/architect.md +2 -2
- package/template/.claude/agents/backend.md +17 -30
- package/template/.claude/agents/frontend.md +17 -39
- package/template/.claude/agents/orchestrator.md +63 -4
- package/template/.claude/agents/product-analyzer.md +1 -1
- package/template/.claude/agents/tester.md +16 -29
- package/template/.claude/commands/agentful-generate.md +221 -14
- package/template/.claude/commands/agentful-init.md +621 -0
- package/template/.claude/commands/agentful-product.md +1 -1
- package/template/.claude/commands/agentful-start.md +99 -1
- package/template/.claude/product/EXAMPLES.md +2 -2
- package/template/.claude/product/index.md +1 -1
- package/template/.claude/settings.json +22 -0
- package/template/.claude/skills/research/SKILL.md +432 -0
- package/template/CLAUDE.md +5 -6
- package/template/bin/hooks/architect-drift-detector.js +242 -0
- package/template/bin/hooks/product-spec-watcher.js +151 -0
- package/version.json +1 -1
- package/bin/hooks/post-agent.js +0 -101
- package/bin/hooks/post-feature.js +0 -227
- package/bin/hooks/pre-agent.js +0 -118
- package/bin/hooks/pre-feature.js +0 -138
- package/lib/VALIDATION_README.md +0 -455
- package/lib/ci/claude-action-integration.js +0 -641
- package/lib/ci/index.js +0 -10
- package/lib/core/analyzer.js +0 -497
- package/lib/core/cli.js +0 -141
- package/lib/core/detectors/conventions.js +0 -342
- package/lib/core/detectors/framework.js +0 -276
- package/lib/core/detectors/index.js +0 -15
- package/lib/core/detectors/language.js +0 -199
- package/lib/core/detectors/patterns.js +0 -356
- package/lib/core/generator.js +0 -626
- package/lib/core/index.js +0 -9
- package/lib/core/output-parser.js +0 -458
- package/lib/core/storage.js +0 -515
- package/lib/core/templates.js +0 -556
- package/lib/pipeline/cli.js +0 -423
- package/lib/pipeline/engine.js +0 -928
- package/lib/pipeline/executor.js +0 -440
- package/lib/pipeline/index.js +0 -33
- package/lib/pipeline/integrations.js +0 -559
- package/lib/pipeline/schemas.js +0 -288
- package/lib/remote/client.js +0 -361
- package/lib/server/auth.js +0 -270
- package/lib/server/client-example.js +0 -190
- package/lib/server/executor.js +0 -477
- package/lib/server/index.js +0 -494
- package/lib/update-helpers.js +0 -505
- package/lib/validation.js +0 -460
package/lib/pipeline/executor.js
DELETED
|
@@ -1,440 +0,0 @@
|
|
|
1
|
-
import { spawn } from 'child_process';
|
|
2
|
-
import fs from 'fs/promises';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { EventEmitter } from 'events';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Agent Execution Runtime
|
|
8
|
-
*
|
|
9
|
-
* Handles the actual execution of AI agents:
|
|
10
|
-
* - Agent invocation via subprocess or API
|
|
11
|
-
* - Context passing between jobs
|
|
12
|
-
* - Streaming logs and progress
|
|
13
|
-
* - Cancellation and cleanup
|
|
14
|
-
* - Result collection
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Agent Executor
|
|
19
|
-
*
|
|
20
|
-
* Executes agents and manages their lifecycle
|
|
21
|
-
*/
|
|
22
|
-
export class AgentExecutor extends EventEmitter {
|
|
23
|
-
constructor(options = {}) {
|
|
24
|
-
super();
|
|
25
|
-
|
|
26
|
-
this.options = {
|
|
27
|
-
agentsDir: options.agentsDir || '.claude/agents',
|
|
28
|
-
tempDir: options.tempDir || '.agentful/pipelines/temp',
|
|
29
|
-
claudeCommand: options.claudeCommand || 'claude',
|
|
30
|
-
streamLogs: options.streamLogs !== false,
|
|
31
|
-
...options
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
this.activeExecutions = new Map(); // executionId -> ExecutionContext
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Execute an agent
|
|
39
|
-
*
|
|
40
|
-
* @param {Object} jobDef - Job definition from pipeline
|
|
41
|
-
* @param {Object} context - Execution context (inputs, variables)
|
|
42
|
-
* @param {Object} options - Execution options
|
|
43
|
-
* @returns {Promise<Object>} Execution result with output
|
|
44
|
-
*/
|
|
45
|
-
async execute(jobDef, context, options = {}) {
|
|
46
|
-
const executionId = this._generateExecutionId(jobDef.id);
|
|
47
|
-
|
|
48
|
-
// Build execution context
|
|
49
|
-
const execContext = {
|
|
50
|
-
executionId,
|
|
51
|
-
jobId: jobDef.id,
|
|
52
|
-
agent: jobDef.agent,
|
|
53
|
-
startTime: Date.now(),
|
|
54
|
-
cancelled: false,
|
|
55
|
-
process: null,
|
|
56
|
-
output: '',
|
|
57
|
-
error: '',
|
|
58
|
-
exitCode: null
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
this.activeExecutions.set(executionId, execContext);
|
|
62
|
-
|
|
63
|
-
try {
|
|
64
|
-
// Prepare agent invocation
|
|
65
|
-
const agentFile = await this._resolveAgentFile(jobDef.agent);
|
|
66
|
-
const prompt = await this._buildAgentPrompt(jobDef, context);
|
|
67
|
-
|
|
68
|
-
// Determine execution method
|
|
69
|
-
const method = jobDef.execution?.method || 'subprocess';
|
|
70
|
-
|
|
71
|
-
let result;
|
|
72
|
-
if (method === 'subprocess') {
|
|
73
|
-
result = await this._executeViaSubprocess(execContext, agentFile, prompt, context, options);
|
|
74
|
-
} else if (method === 'api') {
|
|
75
|
-
result = await this._executeViaAPI(execContext, jobDef, prompt, context, options);
|
|
76
|
-
} else {
|
|
77
|
-
throw new Error(`Unknown execution method: ${method}`);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return result;
|
|
81
|
-
|
|
82
|
-
} finally {
|
|
83
|
-
this.activeExecutions.delete(executionId);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Cancel an active execution
|
|
89
|
-
*
|
|
90
|
-
* @param {string} executionId - Execution ID to cancel
|
|
91
|
-
* @returns {Promise<boolean>} True if cancelled, false if not found
|
|
92
|
-
*/
|
|
93
|
-
async cancel(executionId) {
|
|
94
|
-
const execContext = this.activeExecutions.get(executionId);
|
|
95
|
-
if (!execContext) return false;
|
|
96
|
-
|
|
97
|
-
execContext.cancelled = true;
|
|
98
|
-
|
|
99
|
-
if (execContext.process) {
|
|
100
|
-
// Kill the subprocess
|
|
101
|
-
execContext.process.kill('SIGTERM');
|
|
102
|
-
|
|
103
|
-
// Force kill after timeout
|
|
104
|
-
setTimeout(() => {
|
|
105
|
-
if (execContext.process && !execContext.process.killed) {
|
|
106
|
-
execContext.process.kill('SIGKILL');
|
|
107
|
-
}
|
|
108
|
-
}, 5000);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return true;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Get execution status
|
|
116
|
-
*
|
|
117
|
-
* @param {string} executionId - Execution ID
|
|
118
|
-
* @returns {Object|null} Execution context or null if not found
|
|
119
|
-
*/
|
|
120
|
-
getExecutionStatus(executionId) {
|
|
121
|
-
return this.activeExecutions.get(executionId) || null;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Internal: Execute via subprocess
|
|
126
|
-
*
|
|
127
|
-
* @private
|
|
128
|
-
*/
|
|
129
|
-
async _executeViaSubprocess(execContext, agentFile, prompt, context, options) {
|
|
130
|
-
// Write context to temp file
|
|
131
|
-
const contextFile = await this._writeContextFile(execContext.executionId, context);
|
|
132
|
-
const outputFile = path.join(this.options.tempDir, `${execContext.executionId}-output.json`);
|
|
133
|
-
|
|
134
|
-
// Prepare agent prompt with context reference
|
|
135
|
-
const fullPrompt = this._injectContextReference(prompt, contextFile, outputFile);
|
|
136
|
-
|
|
137
|
-
// Read agent definition file
|
|
138
|
-
const agentContent = await fs.readFile(agentFile, 'utf-8');
|
|
139
|
-
|
|
140
|
-
// Combine agent definition with prompt
|
|
141
|
-
const combinedPrompt = `${agentContent}\n\n---\n\n${fullPrompt}`;
|
|
142
|
-
|
|
143
|
-
return new Promise((resolve, reject) => {
|
|
144
|
-
// Spawn Claude Code with -p flag
|
|
145
|
-
const args = ['-p', combinedPrompt];
|
|
146
|
-
|
|
147
|
-
if (options.timeout) {
|
|
148
|
-
args.push('--timeout', options.timeout.toString());
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const proc = spawn(this.options.claudeCommand, args, {
|
|
152
|
-
cwd: process.cwd(),
|
|
153
|
-
env: { ...process.env }
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
execContext.process = proc;
|
|
157
|
-
|
|
158
|
-
// Setup timeout
|
|
159
|
-
let timeoutHandle;
|
|
160
|
-
if (options.timeout) {
|
|
161
|
-
timeoutHandle = setTimeout(() => {
|
|
162
|
-
if (!execContext.cancelled) {
|
|
163
|
-
proc.kill('SIGTERM');
|
|
164
|
-
reject(new Error(`Agent execution timed out after ${options.timeout}ms`));
|
|
165
|
-
}
|
|
166
|
-
}, options.timeout);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Capture stdout
|
|
170
|
-
proc.stdout.on('data', (data) => {
|
|
171
|
-
const text = data.toString();
|
|
172
|
-
execContext.output += text;
|
|
173
|
-
|
|
174
|
-
if (this.options.streamLogs && options.onLog) {
|
|
175
|
-
options.onLog(text);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Try to extract progress updates
|
|
179
|
-
this._extractProgress(text, options.onProgress);
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
// Capture stderr
|
|
183
|
-
proc.stderr.on('data', (data) => {
|
|
184
|
-
const text = data.toString();
|
|
185
|
-
execContext.error += text;
|
|
186
|
-
|
|
187
|
-
if (this.options.streamLogs && options.onLog) {
|
|
188
|
-
options.onLog(`[ERROR] ${text}`);
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
// Handle process exit
|
|
193
|
-
proc.on('close', async (code) => {
|
|
194
|
-
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
195
|
-
|
|
196
|
-
execContext.exitCode = code;
|
|
197
|
-
execContext.process = null;
|
|
198
|
-
|
|
199
|
-
try {
|
|
200
|
-
// Read output file if exists
|
|
201
|
-
let output = null;
|
|
202
|
-
try {
|
|
203
|
-
const outputContent = await fs.readFile(outputFile, 'utf-8');
|
|
204
|
-
output = JSON.parse(outputContent);
|
|
205
|
-
} catch (error) {
|
|
206
|
-
// No output file or invalid JSON - use stdout
|
|
207
|
-
output = { stdout: execContext.output };
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Cleanup temp files
|
|
211
|
-
await this._cleanupTempFiles(execContext.executionId);
|
|
212
|
-
|
|
213
|
-
if (execContext.cancelled) {
|
|
214
|
-
reject(new Error('Execution was cancelled'));
|
|
215
|
-
} else if (code === 0) {
|
|
216
|
-
resolve({
|
|
217
|
-
success: true,
|
|
218
|
-
output,
|
|
219
|
-
duration: Date.now() - execContext.startTime
|
|
220
|
-
});
|
|
221
|
-
} else {
|
|
222
|
-
reject(new Error(`Agent failed with exit code ${code}: ${execContext.error}`));
|
|
223
|
-
}
|
|
224
|
-
} catch (error) {
|
|
225
|
-
reject(error);
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
proc.on('error', (error) => {
|
|
230
|
-
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
231
|
-
reject(new Error(`Failed to spawn agent: ${error.message}`));
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Internal: Execute via API
|
|
238
|
-
*
|
|
239
|
-
* @private
|
|
240
|
-
*/
|
|
241
|
-
async _executeViaAPI(execContext, jobDef, prompt, context, options) {
|
|
242
|
-
// This would integrate with Claude API directly
|
|
243
|
-
// For now, throw error indicating this needs to be implemented
|
|
244
|
-
|
|
245
|
-
throw new Error('API execution not yet implemented. Use subprocess method.');
|
|
246
|
-
|
|
247
|
-
// Future implementation would look like:
|
|
248
|
-
// const response = await fetch('https://api.anthropic.com/v1/messages', {
|
|
249
|
-
// method: 'POST',
|
|
250
|
-
// headers: { ... },
|
|
251
|
-
// body: JSON.stringify({ ... })
|
|
252
|
-
// });
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Internal: Resolve agent file path
|
|
257
|
-
*
|
|
258
|
-
* @private
|
|
259
|
-
*/
|
|
260
|
-
async _resolveAgentFile(agentName) {
|
|
261
|
-
// Try with .md extension
|
|
262
|
-
let agentFile = path.join(this.options.agentsDir, `${agentName}.md`);
|
|
263
|
-
|
|
264
|
-
try {
|
|
265
|
-
await fs.access(agentFile);
|
|
266
|
-
return agentFile;
|
|
267
|
-
} catch (error) {
|
|
268
|
-
// Try without extension
|
|
269
|
-
agentFile = path.join(this.options.agentsDir, agentName);
|
|
270
|
-
|
|
271
|
-
try {
|
|
272
|
-
await fs.access(agentFile);
|
|
273
|
-
return agentFile;
|
|
274
|
-
} catch (error) {
|
|
275
|
-
throw new Error(`Agent not found: ${agentName}`);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* Internal: Build agent prompt from job definition
|
|
282
|
-
*
|
|
283
|
-
* @private
|
|
284
|
-
*/
|
|
285
|
-
async _buildAgentPrompt(jobDef, context) {
|
|
286
|
-
let prompt = jobDef.prompt || '';
|
|
287
|
-
|
|
288
|
-
// Replace variables in prompt
|
|
289
|
-
prompt = this._interpolateVariables(prompt, context);
|
|
290
|
-
|
|
291
|
-
// Add task description
|
|
292
|
-
if (jobDef.task) {
|
|
293
|
-
prompt = `${jobDef.task}\n\n${prompt}`;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
return prompt;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Internal: Interpolate variables in text
|
|
301
|
-
*
|
|
302
|
-
* @private
|
|
303
|
-
*/
|
|
304
|
-
_interpolateVariables(text, context) {
|
|
305
|
-
return text.replace(/\{\{(\w+(?:\.\w+)*)\}\}/g, (match, path) => {
|
|
306
|
-
const value = this._getNestedValue(context, path);
|
|
307
|
-
return value !== undefined ? value : match;
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Internal: Get nested value from object
|
|
313
|
-
*
|
|
314
|
-
* @private
|
|
315
|
-
*/
|
|
316
|
-
_getNestedValue(obj, path) {
|
|
317
|
-
return path.split('.').reduce((current, prop) => {
|
|
318
|
-
return current && current[prop] !== undefined ? current[prop] : undefined;
|
|
319
|
-
}, obj);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Internal: Inject context reference into prompt
|
|
324
|
-
*
|
|
325
|
-
* @private
|
|
326
|
-
*/
|
|
327
|
-
_injectContextReference(prompt, contextFile, outputFile) {
|
|
328
|
-
return `
|
|
329
|
-
# Pipeline Job Context
|
|
330
|
-
|
|
331
|
-
Input context is available at: ${contextFile}
|
|
332
|
-
Write your output to: ${outputFile}
|
|
333
|
-
|
|
334
|
-
Output format (JSON):
|
|
335
|
-
\`\`\`json
|
|
336
|
-
{
|
|
337
|
-
"success": true,
|
|
338
|
-
"data": { ... },
|
|
339
|
-
"message": "Job completed successfully"
|
|
340
|
-
}
|
|
341
|
-
\`\`\`
|
|
342
|
-
|
|
343
|
-
---
|
|
344
|
-
|
|
345
|
-
# Task
|
|
346
|
-
|
|
347
|
-
${prompt}
|
|
348
|
-
`;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/**
|
|
352
|
-
* Internal: Write context to temp file
|
|
353
|
-
*
|
|
354
|
-
* @private
|
|
355
|
-
*/
|
|
356
|
-
async _writeContextFile(executionId, context) {
|
|
357
|
-
const contextFile = path.join(this.options.tempDir, `${executionId}-context.json`);
|
|
358
|
-
await fs.mkdir(this.options.tempDir, { recursive: true });
|
|
359
|
-
await fs.writeFile(contextFile, JSON.stringify(context, null, 2));
|
|
360
|
-
return contextFile;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
/**
|
|
364
|
-
* Internal: Write prompt to temp file
|
|
365
|
-
*
|
|
366
|
-
* @private
|
|
367
|
-
*/
|
|
368
|
-
async _writePromptFile(executionId, prompt) {
|
|
369
|
-
const promptFile = path.join(this.options.tempDir, `${executionId}-prompt.txt`);
|
|
370
|
-
await fs.mkdir(this.options.tempDir, { recursive: true });
|
|
371
|
-
await fs.writeFile(promptFile, prompt);
|
|
372
|
-
return promptFile;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
/**
|
|
377
|
-
* Internal: Cleanup temp files
|
|
378
|
-
*
|
|
379
|
-
* @private
|
|
380
|
-
*/
|
|
381
|
-
async _cleanupTempFiles(executionId) {
|
|
382
|
-
const files = [
|
|
383
|
-
path.join(this.options.tempDir, `${executionId}-context.json`),
|
|
384
|
-
path.join(this.options.tempDir, `${executionId}-output.json`),
|
|
385
|
-
path.join(this.options.tempDir, `${executionId}-prompt.txt`)
|
|
386
|
-
];
|
|
387
|
-
|
|
388
|
-
for (const file of files) {
|
|
389
|
-
try {
|
|
390
|
-
await fs.unlink(file);
|
|
391
|
-
} catch (error) {
|
|
392
|
-
// Ignore errors - file might not exist
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* Internal: Extract progress from output
|
|
399
|
-
*
|
|
400
|
-
* @private
|
|
401
|
-
*/
|
|
402
|
-
_extractProgress(text, onProgress) {
|
|
403
|
-
if (!onProgress) return;
|
|
404
|
-
|
|
405
|
-
// Look for progress markers: [PROGRESS: 45%] or similar
|
|
406
|
-
const progressMatch = text.match(/\[PROGRESS:\s*(\d+)%\]/i);
|
|
407
|
-
if (progressMatch) {
|
|
408
|
-
const progress = parseInt(progressMatch[1], 10);
|
|
409
|
-
onProgress(progress);
|
|
410
|
-
return;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// Look for task completion markers
|
|
414
|
-
if (text.includes('Task completed') || text.includes('✓')) {
|
|
415
|
-
onProgress(100);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
/**
|
|
420
|
-
* Internal: Generate execution ID
|
|
421
|
-
*
|
|
422
|
-
* @private
|
|
423
|
-
*/
|
|
424
|
-
_generateExecutionId(jobId) {
|
|
425
|
-
const timestamp = Date.now();
|
|
426
|
-
const random = Math.random().toString(36).substring(2, 9);
|
|
427
|
-
return `${jobId}-${timestamp}-${random}`;
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* Agent Executor Factory
|
|
433
|
-
*
|
|
434
|
-
* Creates agent executor with custom configuration
|
|
435
|
-
*/
|
|
436
|
-
export function createAgentExecutor(options = {}) {
|
|
437
|
-
return new AgentExecutor(options);
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
export default AgentExecutor;
|
package/lib/pipeline/index.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pipeline Orchestration System
|
|
3
|
-
*
|
|
4
|
-
* Entry point for agentful pipeline orchestration
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export { PipelineEngine, JobStatus, PipelineStatus } from './engine.js';
|
|
8
|
-
export { AgentExecutor, createAgentExecutor } from './executor.js';
|
|
9
|
-
export {
|
|
10
|
-
GitHubActionsAdapter,
|
|
11
|
-
GitLabCIAdapter,
|
|
12
|
-
JenkinsAdapter,
|
|
13
|
-
WebhookHandler
|
|
14
|
-
} from './integrations.js';
|
|
15
|
-
export { pipelineSchema, validatePipeline } from './schemas.js';
|
|
16
|
-
|
|
17
|
-
// Re-export for convenience
|
|
18
|
-
export * from './engine.js';
|
|
19
|
-
export * from './executor.js';
|
|
20
|
-
export * from './integrations.js';
|
|
21
|
-
export * from './schemas.js';
|
|
22
|
-
|
|
23
|
-
export default {
|
|
24
|
-
PipelineEngine,
|
|
25
|
-
AgentExecutor,
|
|
26
|
-
createAgentExecutor,
|
|
27
|
-
GitHubActionsAdapter,
|
|
28
|
-
GitLabCIAdapter,
|
|
29
|
-
JenkinsAdapter,
|
|
30
|
-
WebhookHandler,
|
|
31
|
-
pipelineSchema,
|
|
32
|
-
validatePipeline
|
|
33
|
-
};
|