agent-pipeline 0.1.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/CLAUDE.md +134 -0
- package/README.md +209 -0
- package/dist/analytics/pipeline-analytics.d.ts +19 -0
- package/dist/analytics/pipeline-analytics.d.ts.map +1 -0
- package/dist/analytics/pipeline-analytics.js +155 -0
- package/dist/analytics/pipeline-analytics.js.map +1 -0
- package/dist/analytics/types.d.ts +31 -0
- package/dist/analytics/types.d.ts.map +1 -0
- package/dist/analytics/types.js +2 -0
- package/dist/analytics/types.js.map +1 -0
- package/dist/cli/commands/agent/info.d.ts +2 -0
- package/dist/cli/commands/agent/info.d.ts.map +1 -0
- package/dist/cli/commands/agent/info.js +62 -0
- package/dist/cli/commands/agent/info.js.map +1 -0
- package/dist/cli/commands/agent/list.d.ts +2 -0
- package/dist/cli/commands/agent/list.d.ts.map +1 -0
- package/dist/cli/commands/agent/list.js +57 -0
- package/dist/cli/commands/agent/list.js.map +1 -0
- package/dist/cli/commands/agent/pull.d.ts +5 -0
- package/dist/cli/commands/agent/pull.d.ts.map +1 -0
- package/dist/cli/commands/agent/pull.js +71 -0
- package/dist/cli/commands/agent/pull.js.map +1 -0
- package/dist/cli/commands/analytics.d.ts +6 -0
- package/dist/cli/commands/analytics.d.ts.map +1 -0
- package/dist/cli/commands/analytics.js +101 -0
- package/dist/cli/commands/analytics.js.map +1 -0
- package/dist/cli/commands/cleanup.d.ts +7 -0
- package/dist/cli/commands/cleanup.d.ts.map +1 -0
- package/dist/cli/commands/cleanup.js +76 -0
- package/dist/cli/commands/cleanup.js.map +1 -0
- package/dist/cli/commands/history.d.ts +7 -0
- package/dist/cli/commands/history.d.ts.map +1 -0
- package/dist/cli/commands/history.js +173 -0
- package/dist/cli/commands/history.js.map +1 -0
- package/dist/cli/commands/init.d.ts +7 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +158 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/install.d.ts +2 -0
- package/dist/cli/commands/install.d.ts.map +1 -0
- package/dist/cli/commands/install.js +15 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/list.d.ts +2 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +13 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/pipeline/clone.d.ts +2 -0
- package/dist/cli/commands/pipeline/clone.d.ts.map +1 -0
- package/dist/cli/commands/pipeline/clone.js +42 -0
- package/dist/cli/commands/pipeline/clone.js.map +1 -0
- package/dist/cli/commands/pipeline/config.d.ts +2 -0
- package/dist/cli/commands/pipeline/config.d.ts.map +1 -0
- package/dist/cli/commands/pipeline/config.js +23 -0
- package/dist/cli/commands/pipeline/config.js.map +1 -0
- package/dist/cli/commands/pipeline/create.d.ts +2 -0
- package/dist/cli/commands/pipeline/create.d.ts.map +1 -0
- package/dist/cli/commands/pipeline/create.js +86 -0
- package/dist/cli/commands/pipeline/create.js.map +1 -0
- package/dist/cli/commands/pipeline/delete.d.ts +6 -0
- package/dist/cli/commands/pipeline/delete.d.ts.map +1 -0
- package/dist/cli/commands/pipeline/delete.js +60 -0
- package/dist/cli/commands/pipeline/delete.js.map +1 -0
- package/dist/cli/commands/pipeline/edit.d.ts +2 -0
- package/dist/cli/commands/pipeline/edit.d.ts.map +1 -0
- package/dist/cli/commands/pipeline/edit.js +50 -0
- package/dist/cli/commands/pipeline/edit.js.map +1 -0
- package/dist/cli/commands/pipeline/export.d.ts +6 -0
- package/dist/cli/commands/pipeline/export.d.ts.map +1 -0
- package/dist/cli/commands/pipeline/export.js +48 -0
- package/dist/cli/commands/pipeline/export.js.map +1 -0
- package/dist/cli/commands/pipeline/import.d.ts +2 -0
- package/dist/cli/commands/pipeline/import.d.ts.map +1 -0
- package/dist/cli/commands/pipeline/import.js +59 -0
- package/dist/cli/commands/pipeline/import.js.map +1 -0
- package/dist/cli/commands/pipeline/validate.d.ts +2 -0
- package/dist/cli/commands/pipeline/validate.d.ts.map +1 -0
- package/dist/cli/commands/pipeline/validate.js +28 -0
- package/dist/cli/commands/pipeline/validate.js.map +1 -0
- package/dist/cli/commands/rollback.d.ts +6 -0
- package/dist/cli/commands/rollback.d.ts.map +1 -0
- package/dist/cli/commands/rollback.js +49 -0
- package/dist/cli/commands/rollback.js.map +1 -0
- package/dist/cli/commands/run.d.ts +15 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +61 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/status.d.ts +2 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +52 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/test.d.ts +5 -0
- package/dist/cli/commands/test.d.ts.map +1 -0
- package/dist/cli/commands/test.js +18 -0
- package/dist/cli/commands/test.js.map +1 -0
- package/dist/cli/commands/uninstall.d.ts +2 -0
- package/dist/cli/commands/uninstall.d.ts.map +1 -0
- package/dist/cli/commands/uninstall.js +6 -0
- package/dist/cli/commands/uninstall.js.map +1 -0
- package/dist/cli/hooks.d.ts +8 -0
- package/dist/cli/hooks.d.ts.map +1 -0
- package/dist/cli/hooks.js +98 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli/templates/agents/cleanup-reporter.md +107 -0
- package/dist/cli/templates/agents/code-reducer.md +51 -0
- package/dist/cli/templates/agents/code-reviewer.md +34 -0
- package/dist/cli/templates/agents/context-reducer.md +94 -0
- package/dist/cli/templates/agents/dependency-auditor.md +127 -0
- package/dist/cli/templates/agents/detective-empath.md +26 -0
- package/dist/cli/templates/agents/detective-linguist.md +26 -0
- package/dist/cli/templates/agents/detective-logician.md +26 -0
- package/dist/cli/templates/agents/detective-skeptic.md +26 -0
- package/dist/cli/templates/agents/detective-statistician.md +26 -0
- package/dist/cli/templates/agents/doc-updater.md +30 -0
- package/dist/cli/templates/agents/judge.md +27 -0
- package/dist/cli/templates/agents/memory-updater.md +72 -0
- package/dist/cli/templates/agents/quality-checker.md +32 -0
- package/dist/cli/templates/agents/security-auditor.md +32 -0
- package/dist/cli/templates/agents/storyteller.md +26 -0
- package/dist/cli/templates/agents/summary.md +32 -0
- package/dist/cli/templates/agents/synthesizer.md +26 -0
- package/dist/cli/templates/pipelines/large-pipeline-example.yml +178 -0
- package/dist/cli/templates/pipelines/post-commit-example.yml +67 -0
- package/dist/cli/templates/pipelines/post-merge-example.yml +78 -0
- package/dist/cli/templates/pipelines/pre-commit-example.yml +41 -0
- package/dist/cli/templates/pipelines/pre-push-example.yml +51 -0
- package/dist/cli/templates/pipelines/test-pipeline.yml +90 -0
- package/dist/cli/utils/agent-importer.d.ts +21 -0
- package/dist/cli/utils/agent-importer.d.ts.map +1 -0
- package/dist/cli/utils/agent-importer.js +150 -0
- package/dist/cli/utils/agent-importer.js.map +1 -0
- package/dist/cli/utils/interactive-prompts.d.ts +10 -0
- package/dist/cli/utils/interactive-prompts.d.ts.map +1 -0
- package/dist/cli/utils/interactive-prompts.js +75 -0
- package/dist/cli/utils/interactive-prompts.js.map +1 -0
- package/dist/config/pipeline-loader.d.ts +14 -0
- package/dist/config/pipeline-loader.d.ts.map +1 -0
- package/dist/config/pipeline-loader.js +71 -0
- package/dist/config/pipeline-loader.js.map +1 -0
- package/dist/config/project-config-loader.d.ts +11 -0
- package/dist/config/project-config-loader.d.ts.map +1 -0
- package/dist/config/project-config-loader.js +100 -0
- package/dist/config/project-config-loader.js.map +1 -0
- package/dist/config/schema.d.ts +165 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +2 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/core/agent-query-runner.d.ts +25 -0
- package/dist/core/agent-query-runner.d.ts.map +1 -0
- package/dist/core/agent-query-runner.js +76 -0
- package/dist/core/agent-query-runner.js.map +1 -0
- package/dist/core/agent-runtime-registry.d.ts +11 -0
- package/dist/core/agent-runtime-registry.d.ts.map +1 -0
- package/dist/core/agent-runtime-registry.js +32 -0
- package/dist/core/agent-runtime-registry.js.map +1 -0
- package/dist/core/agent-runtimes/claude-code-headless-runtime.d.ts +16 -0
- package/dist/core/agent-runtimes/claude-code-headless-runtime.d.ts.map +1 -0
- package/dist/core/agent-runtimes/claude-code-headless-runtime.js +301 -0
- package/dist/core/agent-runtimes/claude-code-headless-runtime.js.map +1 -0
- package/dist/core/agent-runtimes/claude-sdk-runtime.d.ts +15 -0
- package/dist/core/agent-runtimes/claude-sdk-runtime.d.ts.map +1 -0
- package/dist/core/agent-runtimes/claude-sdk-runtime.js +92 -0
- package/dist/core/agent-runtimes/claude-sdk-runtime.js.map +1 -0
- package/dist/core/branch-manager.d.ts +15 -0
- package/dist/core/branch-manager.d.ts.map +1 -0
- package/dist/core/branch-manager.js +90 -0
- package/dist/core/branch-manager.js.map +1 -0
- package/dist/core/condition-evaluator.d.ts +16 -0
- package/dist/core/condition-evaluator.d.ts.map +1 -0
- package/dist/core/condition-evaluator.js +121 -0
- package/dist/core/condition-evaluator.js.map +1 -0
- package/dist/core/context-reducer.d.ts +15 -0
- package/dist/core/context-reducer.d.ts.map +1 -0
- package/dist/core/context-reducer.js +224 -0
- package/dist/core/context-reducer.js.map +1 -0
- package/dist/core/dag-planner.d.ts +13 -0
- package/dist/core/dag-planner.d.ts.map +1 -0
- package/dist/core/dag-planner.js +233 -0
- package/dist/core/dag-planner.js.map +1 -0
- package/dist/core/git-manager.d.ts +14 -0
- package/dist/core/git-manager.d.ts.map +1 -0
- package/dist/core/git-manager.js +70 -0
- package/dist/core/git-manager.js.map +1 -0
- package/dist/core/group-execution-orchestrator.d.ts +34 -0
- package/dist/core/group-execution-orchestrator.d.ts.map +1 -0
- package/dist/core/group-execution-orchestrator.js +238 -0
- package/dist/core/group-execution-orchestrator.js.map +1 -0
- package/dist/core/loop-state-manager.d.ts +29 -0
- package/dist/core/loop-state-manager.d.ts.map +1 -0
- package/dist/core/loop-state-manager.js +78 -0
- package/dist/core/loop-state-manager.js.map +1 -0
- package/dist/core/output-storage-manager.d.ts +14 -0
- package/dist/core/output-storage-manager.d.ts.map +1 -0
- package/dist/core/output-storage-manager.js +68 -0
- package/dist/core/output-storage-manager.js.map +1 -0
- package/dist/core/output-tool-builder.d.ts +6 -0
- package/dist/core/output-tool-builder.d.ts.map +1 -0
- package/dist/core/output-tool-builder.js +50 -0
- package/dist/core/output-tool-builder.js.map +1 -0
- package/dist/core/parallel-executor.d.ts +21 -0
- package/dist/core/parallel-executor.d.ts.map +1 -0
- package/dist/core/parallel-executor.js +93 -0
- package/dist/core/parallel-executor.js.map +1 -0
- package/dist/core/pipeline-finalizer.d.ts +24 -0
- package/dist/core/pipeline-finalizer.d.ts.map +1 -0
- package/dist/core/pipeline-finalizer.js +103 -0
- package/dist/core/pipeline-finalizer.js.map +1 -0
- package/dist/core/pipeline-initializer.d.ts +36 -0
- package/dist/core/pipeline-initializer.d.ts.map +1 -0
- package/dist/core/pipeline-initializer.js +105 -0
- package/dist/core/pipeline-initializer.js.map +1 -0
- package/dist/core/pipeline-runner.d.ts +36 -0
- package/dist/core/pipeline-runner.d.ts.map +1 -0
- package/dist/core/pipeline-runner.js +326 -0
- package/dist/core/pipeline-runner.js.map +1 -0
- package/dist/core/pr-creator.d.ts +23 -0
- package/dist/core/pr-creator.d.ts.map +1 -0
- package/dist/core/pr-creator.js +138 -0
- package/dist/core/pr-creator.js.map +1 -0
- package/dist/core/retry-handler.d.ts +15 -0
- package/dist/core/retry-handler.d.ts.map +1 -0
- package/dist/core/retry-handler.js +95 -0
- package/dist/core/retry-handler.js.map +1 -0
- package/dist/core/stage-executor.d.ts +27 -0
- package/dist/core/stage-executor.d.ts.map +1 -0
- package/dist/core/stage-executor.js +365 -0
- package/dist/core/stage-executor.js.map +1 -0
- package/dist/core/state-manager.d.ts +10 -0
- package/dist/core/state-manager.d.ts.map +1 -0
- package/dist/core/state-manager.js +61 -0
- package/dist/core/state-manager.js.map +1 -0
- package/dist/core/types/agent-runtime.d.ts +51 -0
- package/dist/core/types/agent-runtime.d.ts.map +1 -0
- package/dist/core/types/agent-runtime.js +2 -0
- package/dist/core/types/agent-runtime.js.map +1 -0
- package/dist/core/types/execution-graph.d.ts +29 -0
- package/dist/core/types/execution-graph.d.ts.map +1 -0
- package/dist/core/types/execution-graph.js +2 -0
- package/dist/core/types/execution-graph.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +400 -0
- package/dist/index.js.map +1 -0
- package/dist/notifications/notification-manager.d.ts +12 -0
- package/dist/notifications/notification-manager.d.ts.map +1 -0
- package/dist/notifications/notification-manager.js +74 -0
- package/dist/notifications/notification-manager.js.map +1 -0
- package/dist/notifications/notifiers/base-notifier.d.ts +9 -0
- package/dist/notifications/notifiers/base-notifier.d.ts.map +1 -0
- package/dist/notifications/notifiers/base-notifier.js +27 -0
- package/dist/notifications/notifiers/base-notifier.js.map +1 -0
- package/dist/notifications/notifiers/local-notifier.d.ts +11 -0
- package/dist/notifications/notifiers/local-notifier.d.ts.map +1 -0
- package/dist/notifications/notifiers/local-notifier.js +91 -0
- package/dist/notifications/notifiers/local-notifier.js.map +1 -0
- package/dist/notifications/notifiers/slack-notifier.d.ts +13 -0
- package/dist/notifications/notifiers/slack-notifier.d.ts.map +1 -0
- package/dist/notifications/notifiers/slack-notifier.js +209 -0
- package/dist/notifications/notifiers/slack-notifier.js.map +1 -0
- package/dist/notifications/types.d.ts +34 -0
- package/dist/notifications/types.d.ts.map +1 -0
- package/dist/notifications/types.js +2 -0
- package/dist/notifications/types.js.map +1 -0
- package/dist/ui/components/execution-group.d.ts +10 -0
- package/dist/ui/components/execution-group.d.ts.map +1 -0
- package/dist/ui/components/execution-group.js +19 -0
- package/dist/ui/components/execution-group.js.map +1 -0
- package/dist/ui/components/stage-row.d.ts +10 -0
- package/dist/ui/components/stage-row.d.ts.map +1 -0
- package/dist/ui/components/stage-row.js +69 -0
- package/dist/ui/components/stage-row.js.map +1 -0
- package/dist/ui/components/status-badge.d.ts +7 -0
- package/dist/ui/components/status-badge.d.ts.map +1 -0
- package/dist/ui/components/status-badge.js +18 -0
- package/dist/ui/components/status-badge.js.map +1 -0
- package/dist/ui/components/summary-line.d.ts +9 -0
- package/dist/ui/components/summary-line.d.ts.map +1 -0
- package/dist/ui/components/summary-line.js +13 -0
- package/dist/ui/components/summary-line.js.map +1 -0
- package/dist/ui/pipeline-ui.d.ts +8 -0
- package/dist/ui/pipeline-ui.d.ts.map +1 -0
- package/dist/ui/pipeline-ui.js +82 -0
- package/dist/ui/pipeline-ui.js.map +1 -0
- package/dist/utils/error-factory.d.ts +21 -0
- package/dist/utils/error-factory.d.ts.map +1 -0
- package/dist/utils/error-factory.js +74 -0
- package/dist/utils/error-factory.js.map +1 -0
- package/dist/utils/errors.d.ts +11 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +21 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/gh-cli-checker.d.ts +6 -0
- package/dist/utils/gh-cli-checker.d.ts.map +1 -0
- package/dist/utils/gh-cli-checker.js +42 -0
- package/dist/utils/gh-cli-checker.js.map +1 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +39 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/pipeline-formatter.d.ts +10 -0
- package/dist/utils/pipeline-formatter.d.ts.map +1 -0
- package/dist/utils/pipeline-formatter.js +92 -0
- package/dist/utils/pipeline-formatter.js.map +1 -0
- package/dist/utils/token-estimator.d.ts +15 -0
- package/dist/utils/token-estimator.d.ts.map +1 -0
- package/dist/utils/token-estimator.js +46 -0
- package/dist/utils/token-estimator.js.map +1 -0
- package/dist/validators/pipeline-validator.d.ts +31 -0
- package/dist/validators/pipeline-validator.d.ts.map +1 -0
- package/dist/validators/pipeline-validator.js +540 -0
- package/dist/validators/pipeline-validator.js.map +1 -0
- package/license +21 -0
- package/package.json +90 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { checkGHCLI } from '../utils/gh-cli-checker.js';
|
|
3
|
+
export class PRCreator {
|
|
4
|
+
executeGhCommand(args) {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
const process = spawn('gh', args);
|
|
7
|
+
let stdout = '';
|
|
8
|
+
let stderr = '';
|
|
9
|
+
process.stdout.on('data', (data) => {
|
|
10
|
+
stdout += data.toString();
|
|
11
|
+
});
|
|
12
|
+
process.stderr.on('data', (data) => {
|
|
13
|
+
stderr += data.toString();
|
|
14
|
+
});
|
|
15
|
+
process.on('close', (code) => {
|
|
16
|
+
if (code === 0) {
|
|
17
|
+
resolve(stdout);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
const errorMessage = stderr || stdout || 'Unknown error';
|
|
21
|
+
reject(new Error(`gh command failed with exit code ${code}: ${errorMessage}`));
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
process.on('error', (err) => {
|
|
25
|
+
reject(err);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
async createPR(branchName, baseBranch, config, pipelineState) {
|
|
30
|
+
const ghStatus = await checkGHCLI();
|
|
31
|
+
if (!ghStatus.installed) {
|
|
32
|
+
throw new Error('GitHub CLI (gh) is not installed. Install from: https://cli.github.com/\n\n' +
|
|
33
|
+
'Or disable PR creation:\n' +
|
|
34
|
+
'- Remove git.pullRequest.autoCreate from your pipeline config\n' +
|
|
35
|
+
'- Or run with: agent-pipeline run <pipeline> --no-pr');
|
|
36
|
+
}
|
|
37
|
+
if (!ghStatus.authenticated) {
|
|
38
|
+
throw new Error('GitHub CLI is not authenticated. Run: gh auth login\n\n' +
|
|
39
|
+
'Or disable PR creation:\n' +
|
|
40
|
+
'- Run with: agent-pipeline run <pipeline> --no-pr');
|
|
41
|
+
}
|
|
42
|
+
const title = config.title ||
|
|
43
|
+
`🤖 [Agent Pipeline] ${pipelineState.pipelineConfig.name}`;
|
|
44
|
+
const body = config.body || PRCreator.buildDefaultPRBody(pipelineState);
|
|
45
|
+
const args = [
|
|
46
|
+
'pr', 'create',
|
|
47
|
+
'--base', baseBranch,
|
|
48
|
+
'--head', branchName,
|
|
49
|
+
'--title', title,
|
|
50
|
+
'--body', body
|
|
51
|
+
];
|
|
52
|
+
if (config.draft) {
|
|
53
|
+
args.push('--draft');
|
|
54
|
+
}
|
|
55
|
+
if (config.reviewers && config.reviewers.length > 0) {
|
|
56
|
+
args.push('--reviewer', config.reviewers.join(','));
|
|
57
|
+
}
|
|
58
|
+
if (config.labels && config.labels.length > 0) {
|
|
59
|
+
args.push('--label', config.labels.join(','));
|
|
60
|
+
}
|
|
61
|
+
if (config.assignees && config.assignees.length > 0) {
|
|
62
|
+
args.push('--assignee', config.assignees.join(','));
|
|
63
|
+
}
|
|
64
|
+
if (config.milestone) {
|
|
65
|
+
args.push('--milestone', config.milestone);
|
|
66
|
+
}
|
|
67
|
+
if (config.web) {
|
|
68
|
+
args.push('--web');
|
|
69
|
+
}
|
|
70
|
+
console.log(`\n🚀 Creating pull request...`);
|
|
71
|
+
try {
|
|
72
|
+
const stdout = await this.executeGhCommand(args);
|
|
73
|
+
const urlMatch = stdout.match(/https:\/\/github\.com\/[^\s]+/);
|
|
74
|
+
const url = urlMatch ? urlMatch[0] : '';
|
|
75
|
+
const numberMatch = stdout.match(/#(\d+)/);
|
|
76
|
+
const number = numberMatch ? parseInt(numberMatch[1]) : 0;
|
|
77
|
+
return { url, number };
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
if (error instanceof Error) {
|
|
81
|
+
if (error.message.includes('already exists')) {
|
|
82
|
+
throw new Error(`A pull request already exists for ${branchName}. ` +
|
|
83
|
+
`View it with: gh pr view ${branchName}`);
|
|
84
|
+
}
|
|
85
|
+
throw new Error(`Failed to create PR: ${error.message}`);
|
|
86
|
+
}
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
static buildDefaultPRBody(state) {
|
|
91
|
+
const successCount = state.stages.filter(s => s.status === 'success').length;
|
|
92
|
+
const totalCount = state.stages.length;
|
|
93
|
+
const summary = `
|
|
94
|
+
## 🤖 Agent Pipeline Summary
|
|
95
|
+
|
|
96
|
+
**Pipeline:** ${state.pipelineConfig.name}
|
|
97
|
+
**Run ID:** \`${state.runId}\`
|
|
98
|
+
**Status:** ${state.status === 'completed' ? '✅ Completed' : '⚠️ ' + state.status}
|
|
99
|
+
**Duration:** ${state.artifacts.totalDuration?.toFixed(2)}s
|
|
100
|
+
**Stages:** ${successCount}/${totalCount} successful
|
|
101
|
+
|
|
102
|
+
### Stages Executed
|
|
103
|
+
|
|
104
|
+
${state.stages.map((s, i) => {
|
|
105
|
+
const icon = s.status === 'success' ? '✅' :
|
|
106
|
+
s.status === 'failed' ? '❌' :
|
|
107
|
+
s.status === 'skipped' ? '⏭️' : '⏳';
|
|
108
|
+
const retry = (s.retryAttempt || 0) > 0 ? ` (${s.retryAttempt} retries)` : '';
|
|
109
|
+
return `${i + 1}. ${icon} **${s.stageName}** - ${s.duration?.toFixed(2)}s${retry}`;
|
|
110
|
+
}).join('\n')}
|
|
111
|
+
|
|
112
|
+
### Commits
|
|
113
|
+
|
|
114
|
+
${state.stages
|
|
115
|
+
.filter(s => s.commitSha)
|
|
116
|
+
.map(s => `- \`${s.commitSha?.substring(0, 7)}\` ${s.commitMessage}`)
|
|
117
|
+
.join('\n')}
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
*This PR was automatically generated by Agent Pipeline*
|
|
122
|
+
`.trim();
|
|
123
|
+
return summary;
|
|
124
|
+
}
|
|
125
|
+
async viewPR(branchName) {
|
|
126
|
+
await this.executeGhCommand(['pr', 'view', branchName, '--web']);
|
|
127
|
+
}
|
|
128
|
+
async prExists(branchName) {
|
|
129
|
+
try {
|
|
130
|
+
await this.executeGhCommand(['pr', 'view', branchName]);
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=pr-creator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-creator.js","sourceRoot":"","sources":["../../src/core/pr-creator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { RetryConfig } from '../config/schema.js';
|
|
2
|
+
export interface RetryContext {
|
|
3
|
+
attemptNumber: number;
|
|
4
|
+
maxAttempts: number;
|
|
5
|
+
lastError?: unknown;
|
|
6
|
+
delays: number[];
|
|
7
|
+
}
|
|
8
|
+
export declare class RetryHandler {
|
|
9
|
+
executeWithRetry<T>(fn: () => Promise<T>, retryConfig: RetryConfig | undefined, onRetry?: (context: RetryContext) => void): Promise<T>;
|
|
10
|
+
private calculateDelay;
|
|
11
|
+
private shouldRetry;
|
|
12
|
+
private sleep;
|
|
13
|
+
static formatDelay(ms: number): string;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=retry-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry-handler.d.ts","sourceRoot":"","sources":["../../src/core/retry-handler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,qBAAa,YAAY;IAQjB,gBAAgB,CAAC,CAAC,EACtB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,WAAW,EAAE,WAAW,GAAG,SAAS,EACpC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,GACxC,OAAO,CAAC,CAAC,CAAC;IA0Db,OAAO,CAAC,cAAc;IAgCtB,OAAO,CAAC,WAAW;IA8CnB,OAAO,CAAC,KAAK;IAOb,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;CASvC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
export class RetryHandler {
|
|
2
|
+
async executeWithRetry(fn, retryConfig, onRetry) {
|
|
3
|
+
const maxAttempts = retryConfig ? (retryConfig.maxAttempts ?? 3) : 1;
|
|
4
|
+
const context = {
|
|
5
|
+
attemptNumber: 0,
|
|
6
|
+
maxAttempts,
|
|
7
|
+
delays: []
|
|
8
|
+
};
|
|
9
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
10
|
+
context.attemptNumber = attempt;
|
|
11
|
+
try {
|
|
12
|
+
const result = await fn();
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
context.lastError = error;
|
|
17
|
+
const isLastAttempt = attempt === maxAttempts - 1;
|
|
18
|
+
if (isLastAttempt) {
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
if (!this.shouldRetry(error)) {
|
|
22
|
+
throw error;
|
|
23
|
+
}
|
|
24
|
+
const delay = this.calculateDelay(attempt, retryConfig);
|
|
25
|
+
context.delays.push(delay);
|
|
26
|
+
if (onRetry) {
|
|
27
|
+
onRetry(context);
|
|
28
|
+
}
|
|
29
|
+
await this.sleep(delay);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
throw new Error('Retry logic error: exceeded max attempts without throwing');
|
|
33
|
+
}
|
|
34
|
+
calculateDelay(attempt, config) {
|
|
35
|
+
const initialDelay = config?.initialDelay || 1000;
|
|
36
|
+
const maxDelay = config?.maxDelay || 30000;
|
|
37
|
+
let delay;
|
|
38
|
+
switch (config?.backoff) {
|
|
39
|
+
case 'exponential':
|
|
40
|
+
delay = initialDelay * Math.pow(2, attempt);
|
|
41
|
+
break;
|
|
42
|
+
case 'linear':
|
|
43
|
+
delay = initialDelay * (attempt + 1);
|
|
44
|
+
break;
|
|
45
|
+
case 'fixed':
|
|
46
|
+
default:
|
|
47
|
+
delay = initialDelay;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
return Math.min(delay, maxDelay);
|
|
51
|
+
}
|
|
52
|
+
shouldRetry(error) {
|
|
53
|
+
const message = (error instanceof Error ? error.message : String(error)).toLowerCase();
|
|
54
|
+
if (message.includes('401') || message.includes('403') || message.includes('unauthorized')) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
if (message.includes('enoent') || message.includes('no such file')) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
if (message.includes('yaml') || message.includes('parse error')) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
if (message.includes('invalid') && message.includes('config')) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
if (message.includes('timeout') ||
|
|
67
|
+
message.includes('network') ||
|
|
68
|
+
message.includes('econnrefused') ||
|
|
69
|
+
message.includes('econnreset') ||
|
|
70
|
+
message.includes('etimedout') ||
|
|
71
|
+
message.includes('429') ||
|
|
72
|
+
message.includes('500') ||
|
|
73
|
+
message.includes('502') ||
|
|
74
|
+
message.includes('503') ||
|
|
75
|
+
message.includes('504')) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
sleep(ms) {
|
|
81
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
82
|
+
}
|
|
83
|
+
static formatDelay(ms) {
|
|
84
|
+
if (ms < 1000) {
|
|
85
|
+
return `${ms}ms`;
|
|
86
|
+
}
|
|
87
|
+
else if (ms < 60000) {
|
|
88
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
return `${(ms / 60000).toFixed(1)}m`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=retry-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry-handler.js","sourceRoot":"","sources":["../../src/core/retry-handler.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,YAAY;IAQvB,KAAK,CAAC,gBAAgB,CACpB,EAAoB,EACpB,WAAoC,EACpC,OAAyC;QAIzC,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrE,MAAM,OAAO,GAAiB;YAC5B,aAAa,EAAE,CAAC;YAChB,WAAW;YACX,MAAM,EAAE,EAAE;SACX,CAAC;QAEF,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;YACvD,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC;YAEhC,IAAI,CAAC;gBAEH,MAAM,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC;gBAC1B,OAAO,MAAM,CAAC;YAEhB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,SAAS,GAAG,KAAK,CAAC;gBAG1B,MAAM,aAAa,GAAG,OAAO,KAAK,WAAW,GAAG,CAAC,CAAC;gBAElD,IAAI,aAAa,EAAE,CAAC;oBAElB,MAAM,KAAK,CAAC;gBACd,CAAC;gBAGD,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC7B,MAAM,KAAK,CAAC;gBACd,CAAC;gBAGD,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;gBACxD,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAG3B,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,CAAC,OAAO,CAAC,CAAC;gBACnB,CAAC;gBAGD,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAGD,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC/E,CAAC;IAQO,cAAc,CAAC,OAAe,EAAE,MAAoB;QAC1D,MAAM,YAAY,GAAG,MAAM,EAAE,YAAY,IAAI,IAAI,CAAC;QAClD,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,IAAI,KAAK,CAAC;QAE3C,IAAI,KAAa,CAAC;QAElB,QAAQ,MAAM,EAAE,OAAO,EAAE,CAAC;YACxB,KAAK,aAAa;gBAEhB,KAAK,GAAG,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;gBAC5C,MAAM;YAER,KAAK,QAAQ;gBAEX,KAAK,GAAG,YAAY,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;gBACrC,MAAM;YAER,KAAK,OAAO,CAAC;YACb;gBAEE,KAAK,GAAG,YAAY,CAAC;gBACrB,MAAM;QACV,CAAC;QAGD,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC;IAMO,WAAW,CAAC,KAAc;QAChC,MAAM,OAAO,GAAG,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAGvF,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YAC3F,OAAO,KAAK,CAAC;QACf,CAAC;QAGD,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YACnE,OAAO,KAAK,CAAC;QACf,CAAC;QAGD,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YAChE,OAAO,KAAK,CAAC;QACf,CAAC;QAGD,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9D,OAAO,KAAK,CAAC;QACf,CAAC;QAGD,IACE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;YAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;YAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;YAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;YAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;YAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EACvB,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAGD,OAAO,IAAI,CAAC;IACd,CAAC;IAKO,KAAK,CAAC,EAAU;QACtB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IACzD,CAAC;IAKD,MAAM,CAAC,WAAW,CAAC,EAAU;QAC3B,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC;YACd,OAAO,GAAG,EAAE,IAAI,CAAC;QACnB,CAAC;aAAM,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC;YACtB,OAAO,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;QACtC,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;QACvC,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { GitManager } from './git-manager.js';
|
|
2
|
+
import { AgentRuntime } from './types/agent-runtime.js';
|
|
3
|
+
import { AgentStageConfig, StageExecution, PipelineState, LoopContext } from '../config/schema.js';
|
|
4
|
+
export declare class StageExecutor {
|
|
5
|
+
private gitManager;
|
|
6
|
+
private dryRun;
|
|
7
|
+
private defaultRuntime?;
|
|
8
|
+
private loopContext?;
|
|
9
|
+
private retryHandler;
|
|
10
|
+
private outputStorageManager;
|
|
11
|
+
constructor(gitManager: GitManager, dryRun: boolean, runId: string, repoPath: string, defaultRuntime?: AgentRuntime | undefined, loopContext?: LoopContext | undefined);
|
|
12
|
+
private buildClaudeAgentOptions;
|
|
13
|
+
private resolveStageRuntime;
|
|
14
|
+
private loadSystemPrompt;
|
|
15
|
+
private buildUserPrompt;
|
|
16
|
+
executeStage(stageConfig: AgentStageConfig, pipelineState: PipelineState, onOutputUpdate?: (output: string) => void): Promise<StageExecution>;
|
|
17
|
+
private buildAgentContext;
|
|
18
|
+
private buildRecentStagesContext;
|
|
19
|
+
private buildOlderStagesContext;
|
|
20
|
+
private buildCompressedFilesContext;
|
|
21
|
+
private buildFullFilesContext;
|
|
22
|
+
private buildLoopContextSection;
|
|
23
|
+
private checkContextTokens;
|
|
24
|
+
private runAgentWithTimeout;
|
|
25
|
+
private calculateDuration;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=stage-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage-executor.d.ts","sourceRoot":"","sources":["../../src/core/stage-executor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAyB,MAAM,0BAA0B,CAAC;AAI/E,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAuB,MAAM,qBAAqB,CAAC;AAKxH,qBAAa,aAAa;IAKtB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,MAAM;IAGd,OAAO,CAAC,cAAc,CAAC;IACvB,OAAO,CAAC,WAAW,CAAC;IATtB,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,oBAAoB,CAAuB;gBAGzC,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,OAAO,EACvB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EACR,cAAc,CAAC,EAAE,YAAY,YAAA,EAC7B,WAAW,CAAC,EAAE,WAAW,YAAA;IAWnC,OAAO,CAAC,uBAAuB;IA0C/B,OAAO,CAAC,mBAAmB;YA2Cb,gBAAgB;YAgBhB,eAAe;IAOvB,YAAY,CAChB,WAAW,EAAE,gBAAgB,EAC7B,aAAa,EAAE,aAAa,EAC5B,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GACxC,OAAO,CAAC,cAAc,CAAC;YAmLZ,iBAAiB;IAyE/B,OAAO,CAAC,wBAAwB;IAmChC,OAAO,CAAC,uBAAuB;IAU/B,OAAO,CAAC,2BAA2B;IAUnC,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,uBAAuB;YAuBjB,kBAAkB;YAwBlB,mBAAmB;IA6FjC,OAAO,CAAC,iBAAiB;CAM1B"}
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import { RetryHandler } from './retry-handler.js';
|
|
3
|
+
import { AgentRuntimeRegistry } from './agent-runtime-registry.js';
|
|
4
|
+
import { OutputToolBuilder } from './output-tool-builder.js';
|
|
5
|
+
import { OutputStorageManager } from './output-storage-manager.js';
|
|
6
|
+
import { PipelineFormatter } from '../utils/pipeline-formatter.js';
|
|
7
|
+
import { ErrorFactory } from '../utils/error-factory.js';
|
|
8
|
+
import { TokenEstimator } from '../utils/token-estimator.js';
|
|
9
|
+
export class StageExecutor {
|
|
10
|
+
gitManager;
|
|
11
|
+
dryRun;
|
|
12
|
+
defaultRuntime;
|
|
13
|
+
loopContext;
|
|
14
|
+
retryHandler;
|
|
15
|
+
outputStorageManager;
|
|
16
|
+
constructor(gitManager, dryRun, runId, repoPath, defaultRuntime, loopContext) {
|
|
17
|
+
this.gitManager = gitManager;
|
|
18
|
+
this.dryRun = dryRun;
|
|
19
|
+
this.defaultRuntime = defaultRuntime;
|
|
20
|
+
this.loopContext = loopContext;
|
|
21
|
+
this.retryHandler = new RetryHandler();
|
|
22
|
+
this.outputStorageManager = new OutputStorageManager(repoPath, runId);
|
|
23
|
+
}
|
|
24
|
+
buildClaudeAgentOptions(stageConfig, pipelineState) {
|
|
25
|
+
const stageSettings = stageConfig.runtime?.options;
|
|
26
|
+
const globalSettings = pipelineState.pipelineConfig.runtime?.options;
|
|
27
|
+
const options = {};
|
|
28
|
+
const model = stageSettings?.model || globalSettings?.model;
|
|
29
|
+
if (model)
|
|
30
|
+
options.model = model;
|
|
31
|
+
const maxTurns = stageSettings?.maxTurns ?? globalSettings?.maxTurns;
|
|
32
|
+
if (maxTurns !== undefined)
|
|
33
|
+
options.maxTurns = maxTurns;
|
|
34
|
+
const maxThinkingTokens = stageSettings?.maxThinkingTokens ?? globalSettings?.maxThinkingTokens;
|
|
35
|
+
if (maxThinkingTokens !== undefined)
|
|
36
|
+
options.maxThinkingTokens = maxThinkingTokens;
|
|
37
|
+
return options;
|
|
38
|
+
}
|
|
39
|
+
resolveStageRuntime(stageConfig, pipelineState) {
|
|
40
|
+
try {
|
|
41
|
+
const stageRuntimeType = stageConfig.runtime?.type;
|
|
42
|
+
if (stageRuntimeType) {
|
|
43
|
+
console.log(` Using stage-level runtime: ${stageRuntimeType}`);
|
|
44
|
+
return AgentRuntimeRegistry.getRuntime(stageRuntimeType);
|
|
45
|
+
}
|
|
46
|
+
const pipelineRuntimeType = pipelineState.pipelineConfig.runtime?.type;
|
|
47
|
+
if (pipelineRuntimeType) {
|
|
48
|
+
console.log(` Using pipeline-level runtime: ${pipelineRuntimeType}`);
|
|
49
|
+
return AgentRuntimeRegistry.getRuntime(pipelineRuntimeType);
|
|
50
|
+
}
|
|
51
|
+
if (this.defaultRuntime) {
|
|
52
|
+
console.log(` Using injected default runtime`);
|
|
53
|
+
return this.defaultRuntime;
|
|
54
|
+
}
|
|
55
|
+
console.log(` Using global default runtime: claude-code-headless`);
|
|
56
|
+
return AgentRuntimeRegistry.getRuntime('claude-code-headless');
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
const runtimeType = stageConfig.runtime?.type ||
|
|
60
|
+
pipelineState.pipelineConfig.runtime?.type ||
|
|
61
|
+
'claude-code-headless';
|
|
62
|
+
throw new Error(`Failed to resolve runtime '${runtimeType}': ${error instanceof Error ? error.message : String(error)}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async loadSystemPrompt(agentPath) {
|
|
66
|
+
try {
|
|
67
|
+
return await fs.readFile(agentPath, 'utf-8');
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
throw new Error(`Failed to load agent prompt from '${agentPath}': ${error instanceof Error ? error.message : String(error)}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async buildUserPrompt(stageConfig, pipelineState) {
|
|
74
|
+
return this.buildAgentContext(stageConfig, pipelineState);
|
|
75
|
+
}
|
|
76
|
+
async executeStage(stageConfig, pipelineState, onOutputUpdate) {
|
|
77
|
+
const execution = {
|
|
78
|
+
stageName: stageConfig.name,
|
|
79
|
+
status: 'running',
|
|
80
|
+
startTime: new Date().toISOString(),
|
|
81
|
+
retryAttempt: 0,
|
|
82
|
+
maxRetries: stageConfig.retry?.maxAttempts || 0
|
|
83
|
+
};
|
|
84
|
+
const runtime = this.resolveStageRuntime(stageConfig, pipelineState);
|
|
85
|
+
const executeAttempt = async () => {
|
|
86
|
+
const systemPrompt = await this.loadSystemPrompt(stageConfig.agent);
|
|
87
|
+
const userPrompt = await this.buildUserPrompt(stageConfig, pipelineState);
|
|
88
|
+
const tokenEstimator = new TokenEstimator();
|
|
89
|
+
const estimatedTokens = tokenEstimator.estimateTokens(userPrompt + systemPrompt);
|
|
90
|
+
tokenEstimator.dispose();
|
|
91
|
+
const claudeAgentOptions = this.buildClaudeAgentOptions(stageConfig, pipelineState);
|
|
92
|
+
const retryInfo = PipelineFormatter.formatRetryInfo(execution.retryAttempt, execution.maxRetries);
|
|
93
|
+
console.log(`🤖 Running stage: ${stageConfig.name}${retryInfo}...`);
|
|
94
|
+
console.log(` Estimated input: ~${PipelineFormatter.formatTokenCount(estimatedTokens)} tokens`);
|
|
95
|
+
const result = await this.runAgentWithTimeout(runtime, userPrompt, systemPrompt, stageConfig.timeout, stageConfig.outputs, pipelineState.pipelineConfig.settings?.permissionMode || 'acceptEdits', claudeAgentOptions, onOutputUpdate);
|
|
96
|
+
execution.agentOutput = result.textOutput;
|
|
97
|
+
execution.extractedData = result.extractedData;
|
|
98
|
+
if (result.tokenUsage) {
|
|
99
|
+
execution.tokenUsage = {
|
|
100
|
+
estimated_input: estimatedTokens,
|
|
101
|
+
actual_input: result.tokenUsage.inputTokens,
|
|
102
|
+
output: result.tokenUsage.outputTokens,
|
|
103
|
+
cache_creation: result.tokenUsage.cacheCreationTokens,
|
|
104
|
+
cache_read: result.tokenUsage.cacheReadTokens,
|
|
105
|
+
num_turns: result.numTurns,
|
|
106
|
+
thinking_tokens: result.tokenUsage.thinkingTokens
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
const contextReductionConfig = pipelineState.pipelineConfig.settings?.contextReduction;
|
|
110
|
+
const requireSummary = contextReductionConfig?.requireSummary ?? true;
|
|
111
|
+
if (execution.extractedData) {
|
|
112
|
+
if (requireSummary && !execution.extractedData.summary) {
|
|
113
|
+
console.warn(`⚠️ Stage '${stageConfig.name}' did not provide 'summary' field. ` +
|
|
114
|
+
`Context reduction may be less effective for downstream stages.`);
|
|
115
|
+
}
|
|
116
|
+
if (stageConfig.outputs && stageConfig.outputs.length > 0) {
|
|
117
|
+
const missing = stageConfig.outputs.filter(key => !(key in execution.extractedData));
|
|
118
|
+
if (missing.length > 0) {
|
|
119
|
+
console.warn(`⚠️ Stage '${stageConfig.name}' did not provide expected outputs: ${missing.join(', ')}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else if (stageConfig.outputs && stageConfig.outputs.length > 0) {
|
|
124
|
+
console.warn(`⚠️ Stage '${stageConfig.name}' did not call report_outputs tool. ` +
|
|
125
|
+
`Expected outputs: ${stageConfig.outputs.join(', ')}`);
|
|
126
|
+
}
|
|
127
|
+
if (pipelineState.pipelineConfig.settings?.contextReduction?.saveVerboseOutputs !== false) {
|
|
128
|
+
const outputFiles = await this.outputStorageManager.saveStageOutputs(stageConfig.name, execution.extractedData, execution.agentOutput || '');
|
|
129
|
+
execution.outputFiles = outputFiles;
|
|
130
|
+
}
|
|
131
|
+
const globalAutoCommit = pipelineState.pipelineConfig.settings?.autoCommit;
|
|
132
|
+
const stageAutoCommit = stageConfig.autoCommit ?? globalAutoCommit ?? true;
|
|
133
|
+
const shouldCommit = stageAutoCommit && !this.dryRun;
|
|
134
|
+
if (shouldCommit) {
|
|
135
|
+
const commitSha = await this.gitManager.createPipelineCommit(stageConfig.name, pipelineState.runId, stageConfig.commitMessage);
|
|
136
|
+
if (commitSha) {
|
|
137
|
+
execution.commitSha = commitSha;
|
|
138
|
+
execution.commitMessage = await this.gitManager.getCommitMessage(commitSha);
|
|
139
|
+
console.log(`✅ Committed changes: ${commitSha.substring(0, 7)}`);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
console.log(`ℹ️ No changes to commit`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else if (this.dryRun && await this.gitManager.hasUncommittedChanges()) {
|
|
146
|
+
console.log(`💡 Would commit changes (dry-run mode)`);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
try {
|
|
150
|
+
await this.retryHandler.executeWithRetry(executeAttempt, stageConfig.retry, (context) => {
|
|
151
|
+
execution.retryAttempt = context.attemptNumber + 1;
|
|
152
|
+
const delay = context.delays[context.delays.length - 1];
|
|
153
|
+
const errorMsg = context.lastError instanceof Error
|
|
154
|
+
? context.lastError.message
|
|
155
|
+
: String(context.lastError);
|
|
156
|
+
console.log(`⚠️ Stage failed (attempt ${context.attemptNumber + 1}/${context.maxAttempts}). ` +
|
|
157
|
+
`Retrying in ${RetryHandler.formatDelay(delay)}...`);
|
|
158
|
+
console.log(` Error: ${errorMsg}`);
|
|
159
|
+
});
|
|
160
|
+
execution.status = 'success';
|
|
161
|
+
execution.endTime = new Date().toISOString();
|
|
162
|
+
execution.duration = this.calculateDuration(execution);
|
|
163
|
+
console.log(`✅ Stage completed: ${stageConfig.name}`);
|
|
164
|
+
if (execution.tokenUsage) {
|
|
165
|
+
console.log(` ${PipelineFormatter.formatTokenUsage(execution.tokenUsage)} | Duration: ${execution.duration.toFixed(1)}s`);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
console.log(` Duration: ${execution.duration.toFixed(1)}s`);
|
|
169
|
+
}
|
|
170
|
+
return execution;
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
execution.status = 'failed';
|
|
174
|
+
execution.endTime = new Date().toISOString();
|
|
175
|
+
execution.duration = this.calculateDuration(execution);
|
|
176
|
+
const errorDetails = ErrorFactory.createStageError(error, stageConfig.agent);
|
|
177
|
+
execution.error = errorDetails;
|
|
178
|
+
const retryInfo = execution.retryAttempt && execution.retryAttempt > 0
|
|
179
|
+
? ` (after ${execution.retryAttempt} retries)`
|
|
180
|
+
: '';
|
|
181
|
+
console.error(`❌ Stage failed: ${stageConfig.name}${retryInfo}`);
|
|
182
|
+
console.error(` Error: ${errorDetails.message}`);
|
|
183
|
+
if (errorDetails.agentPath) {
|
|
184
|
+
console.error(` Agent: ${errorDetails.agentPath}`);
|
|
185
|
+
}
|
|
186
|
+
if (errorDetails.suggestion) {
|
|
187
|
+
console.error(` 💡 ${errorDetails.suggestion}`);
|
|
188
|
+
}
|
|
189
|
+
return execution;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async buildAgentContext(stageConfig, pipelineState) {
|
|
193
|
+
const config = pipelineState.pipelineConfig.settings?.contextReduction || {
|
|
194
|
+
enabled: true,
|
|
195
|
+
maxTokens: 50000,
|
|
196
|
+
strategy: 'summary-based',
|
|
197
|
+
contextWindow: 3,
|
|
198
|
+
requireSummary: true,
|
|
199
|
+
saveVerboseOutputs: true,
|
|
200
|
+
compressFileList: true
|
|
201
|
+
};
|
|
202
|
+
const previousStages = pipelineState.stages.filter(s => s.status === 'success');
|
|
203
|
+
const contextWindow = config.contextWindow || 3;
|
|
204
|
+
const recentStages = previousStages.slice(-contextWindow);
|
|
205
|
+
const olderStages = previousStages.slice(0, -contextWindow);
|
|
206
|
+
const recentStagesContext = this.buildRecentStagesContext(recentStages, pipelineState.runId);
|
|
207
|
+
const olderStagesContext = this.buildOlderStagesContext(olderStages, pipelineState.runId);
|
|
208
|
+
const changedFilesContext = config.compressFileList
|
|
209
|
+
? this.buildCompressedFilesContext(pipelineState)
|
|
210
|
+
: this.buildFullFilesContext(pipelineState);
|
|
211
|
+
const outputInstructions = OutputToolBuilder.buildOutputInstructions(stageConfig.outputs);
|
|
212
|
+
const loopContextSection = this.buildLoopContextSection();
|
|
213
|
+
const context = `
|
|
214
|
+
# Pipeline Context
|
|
215
|
+
|
|
216
|
+
**Pipeline Run ID:** ${pipelineState.runId}
|
|
217
|
+
**Current Stage:** ${stageConfig.name}
|
|
218
|
+
**Trigger Commit:** ${pipelineState.trigger.commitSha}
|
|
219
|
+
|
|
220
|
+
${recentStagesContext}
|
|
221
|
+
|
|
222
|
+
${olderStagesContext}
|
|
223
|
+
|
|
224
|
+
${changedFilesContext}
|
|
225
|
+
|
|
226
|
+
${loopContextSection}
|
|
227
|
+
|
|
228
|
+
## Your Task
|
|
229
|
+
${JSON.stringify(stageConfig.inputs || {}, null, 2)}
|
|
230
|
+
|
|
231
|
+
${outputInstructions ? `\n${outputInstructions}\n` : ''}
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
**Note:** Use the Read tool to access full outputs if you need detailed information.
|
|
235
|
+
`.trim();
|
|
236
|
+
if (config.enabled) {
|
|
237
|
+
await this.checkContextTokens(context, config);
|
|
238
|
+
}
|
|
239
|
+
return context;
|
|
240
|
+
}
|
|
241
|
+
buildRecentStagesContext(recentStages, _runId) {
|
|
242
|
+
if (recentStages.length === 0)
|
|
243
|
+
return '';
|
|
244
|
+
const stageContexts = recentStages.map(s => {
|
|
245
|
+
const summary = s.extractedData?.summary
|
|
246
|
+
? String(s.extractedData.summary)
|
|
247
|
+
: 'No summary provided';
|
|
248
|
+
const keyMetrics = Object.entries(s.extractedData || {})
|
|
249
|
+
.filter(([key]) => key !== 'summary')
|
|
250
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
251
|
+
.join(', ');
|
|
252
|
+
const fileReference = s.outputFiles?.structured
|
|
253
|
+
? `- **Full Output:** ${s.outputFiles.structured}`
|
|
254
|
+
: '';
|
|
255
|
+
return `
|
|
256
|
+
### ${s.stageName}
|
|
257
|
+
- **Summary:** ${summary}
|
|
258
|
+
${keyMetrics ? `- **Key Metrics:** ${keyMetrics}` : ''}
|
|
259
|
+
- **Commit:** ${s.commitSha || 'No commit'}
|
|
260
|
+
${fileReference}
|
|
261
|
+
`.trim();
|
|
262
|
+
}).join('\n\n');
|
|
263
|
+
return `## Previous Stages (Last ${recentStages.length} in context window)\n\n${stageContexts}`;
|
|
264
|
+
}
|
|
265
|
+
buildOlderStagesContext(olderStages, runId) {
|
|
266
|
+
if (olderStages.length === 0)
|
|
267
|
+
return '';
|
|
268
|
+
const stageNames = olderStages.map(s => s.stageName).join(', ');
|
|
269
|
+
return `## Earlier Stages\nStages ${stageNames} completed. Full history: .agent-pipeline/outputs/${runId}/pipeline-summary.json\n`;
|
|
270
|
+
}
|
|
271
|
+
buildCompressedFilesContext(pipelineState) {
|
|
272
|
+
const compressed = this.outputStorageManager.compressFileList(pipelineState.artifacts.changedFiles);
|
|
273
|
+
return `## Changed Files Summary
|
|
274
|
+
${compressed}
|
|
275
|
+
Full list: .agent-pipeline/outputs/${pipelineState.runId}/changed-files.txt`;
|
|
276
|
+
}
|
|
277
|
+
buildFullFilesContext(pipelineState) {
|
|
278
|
+
const files = pipelineState.artifacts.changedFiles.join('\n');
|
|
279
|
+
return `## Changed Files\n${files}`;
|
|
280
|
+
}
|
|
281
|
+
buildLoopContextSection() {
|
|
282
|
+
if (!this.loopContext?.enabled) {
|
|
283
|
+
return '';
|
|
284
|
+
}
|
|
285
|
+
return `
|
|
286
|
+
## Pipeline Looping
|
|
287
|
+
|
|
288
|
+
This pipeline is running in LOOP MODE. After completion, the orchestrator will check for the next pipeline to run.
|
|
289
|
+
|
|
290
|
+
**To queue the next pipeline:**
|
|
291
|
+
- Write a valid pipeline YAML file to: \`${this.loopContext.directories.pending}\`
|
|
292
|
+
- The file will be automatically picked up and executed after this pipeline completes
|
|
293
|
+
- Use the same format as regular pipeline definitions in \`.agent-pipeline/pipelines/\`
|
|
294
|
+
|
|
295
|
+
**Current loop status:**
|
|
296
|
+
- Iteration: ${this.loopContext.currentIteration}/${this.loopContext.maxIterations}
|
|
297
|
+
- Pending directory: \`${this.loopContext.directories.pending}\`
|
|
298
|
+
|
|
299
|
+
**Note:** Only create a next pipeline if your analysis determines follow-up work is needed.
|
|
300
|
+
`.trim();
|
|
301
|
+
}
|
|
302
|
+
async checkContextTokens(context, config) {
|
|
303
|
+
const tokenEstimator = new TokenEstimator();
|
|
304
|
+
const { tokens, method } = await tokenEstimator.smartCount(context, config.maxTokens);
|
|
305
|
+
tokenEstimator.dispose();
|
|
306
|
+
const percentage = (tokens / config.maxTokens) * 100;
|
|
307
|
+
if (tokens > config.maxTokens) {
|
|
308
|
+
console.warn(`⚠️ Context size (${PipelineFormatter.formatTokenCount(tokens)} tokens, ${percentage.toFixed(0)}%) ` +
|
|
309
|
+
`exceeds limit (${PipelineFormatter.formatTokenCount(config.maxTokens)}). ` +
|
|
310
|
+
`Consider reducing contextWindow or using agent-based reduction.`);
|
|
311
|
+
}
|
|
312
|
+
else if (tokens > config.maxTokens * 0.8) {
|
|
313
|
+
console.log(`ℹ️ Context size: ${PipelineFormatter.formatTokenCount(tokens)} tokens ` +
|
|
314
|
+
`(${method}, ${percentage.toFixed(0)}% of limit, approaching threshold)`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
async runAgentWithTimeout(runtime, userPrompt, systemPrompt, timeoutSeconds, outputKeys, permissionMode = 'acceptEdits', claudeAgentOptions, onOutputUpdate) {
|
|
318
|
+
const timeout = (timeoutSeconds || 900) * 1000;
|
|
319
|
+
const warningThresholds = [
|
|
320
|
+
{ time: 300 * 1000, label: '5 minutes' },
|
|
321
|
+
{ time: 600 * 1000, label: '10 minutes' },
|
|
322
|
+
{ time: 780 * 1000, label: '13 minutes' }
|
|
323
|
+
];
|
|
324
|
+
const warningTimers = [];
|
|
325
|
+
const runQuery = async () => {
|
|
326
|
+
warningThresholds.forEach(({ time, label }) => {
|
|
327
|
+
if (time < timeout) {
|
|
328
|
+
const timer = setTimeout(() => {
|
|
329
|
+
console.warn(`⚠️ Agent still running after ${label}. Hard timeout at ${(timeout / 1000 / 60).toFixed(0)} minutes.`);
|
|
330
|
+
}, time);
|
|
331
|
+
warningTimers.push(timer);
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
const request = {
|
|
335
|
+
systemPrompt,
|
|
336
|
+
userPrompt,
|
|
337
|
+
options: {
|
|
338
|
+
timeout: timeoutSeconds,
|
|
339
|
+
outputKeys,
|
|
340
|
+
permissionMode,
|
|
341
|
+
model: claudeAgentOptions?.model,
|
|
342
|
+
maxTurns: claudeAgentOptions?.maxTurns,
|
|
343
|
+
maxThinkingTokens: claudeAgentOptions?.maxThinkingTokens,
|
|
344
|
+
onOutputUpdate
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
const result = await runtime.execute(request);
|
|
348
|
+
warningTimers.forEach(timer => clearTimeout(timer));
|
|
349
|
+
return result;
|
|
350
|
+
};
|
|
351
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => {
|
|
352
|
+
warningTimers.forEach(timer => clearTimeout(timer));
|
|
353
|
+
reject(new Error('Agent timeout'));
|
|
354
|
+
}, timeout));
|
|
355
|
+
return Promise.race([runQuery(), timeoutPromise]);
|
|
356
|
+
}
|
|
357
|
+
calculateDuration(execution) {
|
|
358
|
+
if (!execution.endTime)
|
|
359
|
+
return 0;
|
|
360
|
+
const start = new Date(execution.startTime).getTime();
|
|
361
|
+
const end = new Date(execution.endTime).getTime();
|
|
362
|
+
return (end - start) / 1000;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
//# sourceMappingURL=stage-executor.js.map
|