@uluops/core 0.5.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 +543 -0
- package/definitions/starter/code-validator.agent.yaml +134 -0
- package/definitions/starter/docs-validator.agent.yaml +142 -0
- package/definitions/starter/public-interface-validator.agent.yaml +138 -0
- package/definitions/starter/security-analyst.agent.yaml +144 -0
- package/definitions/starter/test-architect.agent.yaml +137 -0
- package/dist/ai/AIProvider.d.ts +198 -0
- package/dist/ai/AIProvider.d.ts.map +1 -0
- package/dist/ai/AIProvider.js +557 -0
- package/dist/ai/AIProvider.js.map +1 -0
- package/dist/ai/ModelCatalog.d.ts +78 -0
- package/dist/ai/ModelCatalog.d.ts.map +1 -0
- package/dist/ai/ModelCatalog.js +193 -0
- package/dist/ai/ModelCatalog.js.map +1 -0
- package/dist/ai/ShellExecutor.d.ts +42 -0
- package/dist/ai/ShellExecutor.d.ts.map +1 -0
- package/dist/ai/ShellExecutor.js +62 -0
- package/dist/ai/ShellExecutor.js.map +1 -0
- package/dist/ai/TokenBudgetTracker.d.ts +49 -0
- package/dist/ai/TokenBudgetTracker.d.ts.map +1 -0
- package/dist/ai/TokenBudgetTracker.js +61 -0
- package/dist/ai/TokenBudgetTracker.js.map +1 -0
- package/dist/ai/ToolAdapter.d.ts +25 -0
- package/dist/ai/ToolAdapter.d.ts.map +1 -0
- package/dist/ai/ToolAdapter.js +135 -0
- package/dist/ai/ToolAdapter.js.map +1 -0
- package/dist/ai/index.d.ts +6 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +4 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/client/UluOpsClient.d.ts +111 -0
- package/dist/client/UluOpsClient.d.ts.map +1 -0
- package/dist/client/UluOpsClient.js +329 -0
- package/dist/client/UluOpsClient.js.map +1 -0
- package/dist/constants.d.ts +6 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +9 -0
- package/dist/constants.js.map +1 -0
- package/dist/errors/UluOpsError.d.ts +10 -0
- package/dist/errors/UluOpsError.d.ts.map +1 -0
- package/dist/errors/UluOpsError.js +13 -0
- package/dist/errors/UluOpsError.js.map +1 -0
- package/dist/errors/index.d.ts +64 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +93 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/executor/AgentExecutor.d.ts +57 -0
- package/dist/executor/AgentExecutor.d.ts.map +1 -0
- package/dist/executor/AgentExecutor.js +331 -0
- package/dist/executor/AgentExecutor.js.map +1 -0
- package/dist/executor/CommandExecutor.d.ts +33 -0
- package/dist/executor/CommandExecutor.d.ts.map +1 -0
- package/dist/executor/CommandExecutor.js +183 -0
- package/dist/executor/CommandExecutor.js.map +1 -0
- package/dist/executor/PipelineExecutor.d.ts +55 -0
- package/dist/executor/PipelineExecutor.d.ts.map +1 -0
- package/dist/executor/PipelineExecutor.js +273 -0
- package/dist/executor/PipelineExecutor.js.map +1 -0
- package/dist/executor/ToolHandler.d.ts +47 -0
- package/dist/executor/ToolHandler.d.ts.map +1 -0
- package/dist/executor/ToolHandler.js +615 -0
- package/dist/executor/ToolHandler.js.map +1 -0
- package/dist/executor/WorkflowExecutor.d.ts +55 -0
- package/dist/executor/WorkflowExecutor.d.ts.map +1 -0
- package/dist/executor/WorkflowExecutor.js +368 -0
- package/dist/executor/WorkflowExecutor.js.map +1 -0
- package/dist/executor/preflight.d.ts +8 -0
- package/dist/executor/preflight.d.ts.map +1 -0
- package/dist/executor/preflight.js +102 -0
- package/dist/executor/preflight.js.map +1 -0
- package/dist/executor/symbols.d.ts +13 -0
- package/dist/executor/symbols.d.ts.map +1 -0
- package/dist/executor/symbols.js +102 -0
- package/dist/executor/symbols.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/OutputExtractor.d.ts +52 -0
- package/dist/parser/OutputExtractor.d.ts.map +1 -0
- package/dist/parser/OutputExtractor.js +818 -0
- package/dist/parser/OutputExtractor.js.map +1 -0
- package/dist/parser/outputSchemas.d.ts +223 -0
- package/dist/parser/outputSchemas.d.ts.map +1 -0
- package/dist/parser/outputSchemas.js +73 -0
- package/dist/parser/outputSchemas.js.map +1 -0
- package/dist/registry/RegistryClient.d.ts +75 -0
- package/dist/registry/RegistryClient.d.ts.map +1 -0
- package/dist/registry/RegistryClient.js +419 -0
- package/dist/registry/RegistryClient.js.map +1 -0
- package/dist/registry/index.d.ts +2 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +2 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/types/agent.d.ts +406 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +2 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/ai.d.ts +14 -0
- package/dist/types/ai.d.ts.map +1 -0
- package/dist/types/ai.js +2 -0
- package/dist/types/ai.js.map +1 -0
- package/dist/types/command.d.ts +153 -0
- package/dist/types/command.d.ts.map +1 -0
- package/dist/types/command.js +2 -0
- package/dist/types/command.js.map +1 -0
- package/dist/types/config.d.ts +136 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +2 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/execution.d.ts +172 -0
- package/dist/types/execution.d.ts.map +1 -0
- package/dist/types/execution.js +2 -0
- package/dist/types/execution.js.map +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/parser.d.ts +75 -0
- package/dist/types/parser.d.ts.map +1 -0
- package/dist/types/parser.js +2 -0
- package/dist/types/parser.js.map +1 -0
- package/dist/types/pipeline.d.ts +155 -0
- package/dist/types/pipeline.d.ts.map +1 -0
- package/dist/types/pipeline.js +2 -0
- package/dist/types/pipeline.js.map +1 -0
- package/dist/types/registry.d.ts +232 -0
- package/dist/types/registry.d.ts.map +1 -0
- package/dist/types/registry.js +2 -0
- package/dist/types/registry.js.map +1 -0
- package/dist/types/tools.d.ts +29 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +2 -0
- package/dist/types/tools.js.map +1 -0
- package/dist/types/validation.d.ts +237 -0
- package/dist/types/validation.d.ts.map +1 -0
- package/dist/types/validation.js +2 -0
- package/dist/types/validation.js.map +1 -0
- package/dist/types/workflow.d.ts +131 -0
- package/dist/types/workflow.d.ts.map +1 -0
- package/dist/types/workflow.js +2 -0
- package/dist/types/workflow.js.map +1 -0
- package/dist/utils/formatError.d.ts +6 -0
- package/dist/utils/formatError.d.ts.map +1 -0
- package/dist/utils/formatError.js +10 -0
- package/dist/utils/formatError.js.map +1 -0
- package/dist/utils/parseRef.d.ts +11 -0
- package/dist/utils/parseRef.d.ts.map +1 -0
- package/dist/utils/parseRef.js +16 -0
- package/dist/utils/parseRef.js.map +1 -0
- package/dist/utils/sumTokenMetrics.d.ts +9 -0
- package/dist/utils/sumTokenMetrics.d.ts.map +1 -0
- package/dist/utils/sumTokenMetrics.js +20 -0
- package/dist/utils/sumTokenMetrics.js.map +1 -0
- package/dist/utils/topoSort.d.ts +24 -0
- package/dist/utils/topoSort.d.ts.map +1 -0
- package/dist/utils/topoSort.js +60 -0
- package/dist/utils/topoSort.js.map +1 -0
- package/dist/validation/ValidationClient.d.ts +51 -0
- package/dist/validation/ValidationClient.d.ts.map +1 -0
- package/dist/validation/ValidationClient.js +179 -0
- package/dist/validation/ValidationClient.js.map +1 -0
- package/dist/validation/index.d.ts +2 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +2 -0
- package/dist/validation/index.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { CommandExecutor } from './CommandExecutor.js';
|
|
2
|
+
import type { RegistryClient } from '../registry/RegistryClient.js';
|
|
3
|
+
import type { ResolvedDefinition } from '../types/registry.js';
|
|
4
|
+
import type { WorkflowResult } from '../types/workflow.js';
|
|
5
|
+
import type { ExecutionInput } from '../types/execution.js';
|
|
6
|
+
/**
|
|
7
|
+
* Executes workflows as quality-gated directed acyclic graphs.
|
|
8
|
+
*
|
|
9
|
+
* Phases are topologically sorted into execution levels based on declared
|
|
10
|
+
* dependencies. Independent phases (those in the same topological level)
|
|
11
|
+
* execute in parallel. Quality gates evaluate continuous AI judgment scores
|
|
12
|
+
* against declared thresholds, with four distinct failure behaviors:
|
|
13
|
+
*
|
|
14
|
+
* - stop: do not start subsequent levels; let running phases finish
|
|
15
|
+
* - abort: cancel running phases immediately; skip all remaining
|
|
16
|
+
* - continue: proceed past failure; dependent phases still check deps
|
|
17
|
+
* - warn: proceed with warning annotation; no blocking
|
|
18
|
+
*/
|
|
19
|
+
export declare class WorkflowExecutor {
|
|
20
|
+
private commandExecutor;
|
|
21
|
+
private registry;
|
|
22
|
+
constructor(commandExecutor: CommandExecutor, registry: RegistryClient);
|
|
23
|
+
/**
|
|
24
|
+
* Execute a workflow with DAG-based phase orchestration.
|
|
25
|
+
*
|
|
26
|
+
* Phases are grouped into topological levels. All phases in a level
|
|
27
|
+
* whose dependencies are satisfied execute in parallel. Gate evaluation
|
|
28
|
+
* occurs after each phase completes, and failure behavior determines
|
|
29
|
+
* whether subsequent levels proceed.
|
|
30
|
+
*/
|
|
31
|
+
execute(resolved: ResolvedDefinition, input: ExecutionInput): Promise<WorkflowResult>;
|
|
32
|
+
/**
|
|
33
|
+
* Execute a set of independent phases in parallel.
|
|
34
|
+
*
|
|
35
|
+
* Respects max_parallel concurrency limit if set. Uses Promise.allSettled
|
|
36
|
+
* to ensure partial failures don't reject the entire level.
|
|
37
|
+
*/
|
|
38
|
+
private executePhasesParallel;
|
|
39
|
+
/**
|
|
40
|
+
* Execute phases with a concurrency semaphore.
|
|
41
|
+
*/
|
|
42
|
+
private executePhasesWithLimit;
|
|
43
|
+
private executePhase;
|
|
44
|
+
private executeCommand;
|
|
45
|
+
private aggregatePhaseScore;
|
|
46
|
+
private evaluateGate;
|
|
47
|
+
private aggregate;
|
|
48
|
+
private createBlockedPhase;
|
|
49
|
+
private createSkippedPhase;
|
|
50
|
+
private checkDependencies;
|
|
51
|
+
private evaluateCondition;
|
|
52
|
+
private deduplicateRecommendations;
|
|
53
|
+
private buildPartialResult;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=WorkflowExecutor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowExecutor.d.ts","sourceRoot":"","sources":["../../src/executor/WorkflowExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAsB,cAAc,EAAgC,MAAM,sBAAsB,CAAC;AAE7G,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,uBAAuB,CAAC;AAM5E;;;;;;;;;;;;GAYG;AACH,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,QAAQ;gBADR,eAAe,EAAE,eAAe,EAChC,QAAQ,EAAE,cAAc;IAGlC;;;;;;;OAOG;IACG,OAAO,CAAC,QAAQ,EAAE,kBAAkB,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IA2I3F;;;;;OAKG;YACW,qBAAqB;IAiCnC;;OAEG;YACW,sBAAsB;YAyBtB,YAAY;YA4DZ,cAAc;IAK5B,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,SAAS;IAiCjB,OAAO,CAAC,kBAAkB;IAa1B,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,kBAAkB;CAgB3B"}
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { WorkflowError } from '../errors/index.js';
|
|
2
|
+
import { formatErrorMessage } from '../utils/formatError.js';
|
|
3
|
+
import { sumTokenMetrics } from '../utils/sumTokenMetrics.js';
|
|
4
|
+
import { topoGroupLevels } from '../utils/topoSort.js';
|
|
5
|
+
/**
|
|
6
|
+
* Executes workflows as quality-gated directed acyclic graphs.
|
|
7
|
+
*
|
|
8
|
+
* Phases are topologically sorted into execution levels based on declared
|
|
9
|
+
* dependencies. Independent phases (those in the same topological level)
|
|
10
|
+
* execute in parallel. Quality gates evaluate continuous AI judgment scores
|
|
11
|
+
* against declared thresholds, with four distinct failure behaviors:
|
|
12
|
+
*
|
|
13
|
+
* - stop: do not start subsequent levels; let running phases finish
|
|
14
|
+
* - abort: cancel running phases immediately; skip all remaining
|
|
15
|
+
* - continue: proceed past failure; dependent phases still check deps
|
|
16
|
+
* - warn: proceed with warning annotation; no blocking
|
|
17
|
+
*/
|
|
18
|
+
export class WorkflowExecutor {
|
|
19
|
+
commandExecutor;
|
|
20
|
+
registry;
|
|
21
|
+
constructor(commandExecutor, registry) {
|
|
22
|
+
this.commandExecutor = commandExecutor;
|
|
23
|
+
this.registry = registry;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Execute a workflow with DAG-based phase orchestration.
|
|
27
|
+
*
|
|
28
|
+
* Phases are grouped into topological levels. All phases in a level
|
|
29
|
+
* whose dependencies are satisfied execute in parallel. Gate evaluation
|
|
30
|
+
* occurs after each phase completes, and failure behavior determines
|
|
31
|
+
* whether subsequent levels proceed.
|
|
32
|
+
*/
|
|
33
|
+
async execute(resolved, input) {
|
|
34
|
+
const startTime = Date.now();
|
|
35
|
+
if (resolved.type !== 'workflow') {
|
|
36
|
+
throw new WorkflowError(`WorkflowExecutor received a '${resolved.type}' definition (expected 'workflow')`, { partialResult: undefined });
|
|
37
|
+
}
|
|
38
|
+
const def = resolved.definition;
|
|
39
|
+
const phaseResults = [];
|
|
40
|
+
const allRecommendations = [];
|
|
41
|
+
const completedPhases = new Map();
|
|
42
|
+
try {
|
|
43
|
+
const levels = topoGroupLevels(def.workflow.orchestration.phases);
|
|
44
|
+
const onFailure = def.workflow.orchestration.on_failure;
|
|
45
|
+
const maxParallel = def.workflow.orchestration.max_parallel;
|
|
46
|
+
let stopped = false;
|
|
47
|
+
let aborted = false;
|
|
48
|
+
for (const level of levels) {
|
|
49
|
+
if (stopped || aborted) {
|
|
50
|
+
// Mark remaining phases as skipped
|
|
51
|
+
for (const phase of level) {
|
|
52
|
+
const skipped = this.createSkippedPhase(phase);
|
|
53
|
+
phaseResults.push(skipped);
|
|
54
|
+
completedPhases.set(phase.id, skipped);
|
|
55
|
+
}
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
// Filter level to phases whose dependencies are satisfied and skip_if is not met
|
|
59
|
+
const eligible = [];
|
|
60
|
+
for (const phase of level) {
|
|
61
|
+
if (phase.skip_if && this.evaluateCondition(phase.skip_if, input, phaseResults)) {
|
|
62
|
+
const skipped = this.createSkippedPhase(phase);
|
|
63
|
+
phaseResults.push(skipped);
|
|
64
|
+
completedPhases.set(phase.id, skipped);
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (!this.checkDependencies(phase.depends_on, completedPhases)) {
|
|
68
|
+
const skipped = this.createSkippedPhase(phase);
|
|
69
|
+
phaseResults.push(skipped);
|
|
70
|
+
completedPhases.set(phase.id, skipped);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
eligible.push(phase);
|
|
74
|
+
}
|
|
75
|
+
if (eligible.length === 0)
|
|
76
|
+
continue;
|
|
77
|
+
// Execute eligible phases in parallel (with optional concurrency limit)
|
|
78
|
+
const levelResults = await this.executePhasesParallel(eligible, input, maxParallel);
|
|
79
|
+
// Process results and evaluate gates
|
|
80
|
+
for (const phaseResult of levelResults) {
|
|
81
|
+
phaseResults.push(phaseResult);
|
|
82
|
+
completedPhases.set(phaseResult.id, phaseResult);
|
|
83
|
+
// Accumulate recommendations
|
|
84
|
+
for (const cmd of phaseResult.commands) {
|
|
85
|
+
allRecommendations.push(...cmd.recommendations);
|
|
86
|
+
}
|
|
87
|
+
// Apply failure behavior based on gate result
|
|
88
|
+
if (phaseResult.decision === 'blocked') {
|
|
89
|
+
switch (onFailure) {
|
|
90
|
+
case 'stop':
|
|
91
|
+
stopped = true;
|
|
92
|
+
break;
|
|
93
|
+
case 'abort':
|
|
94
|
+
aborted = true;
|
|
95
|
+
break;
|
|
96
|
+
case 'warn':
|
|
97
|
+
// Downgrade to warned — proceed without blocking
|
|
98
|
+
phaseResult.decision = 'warned';
|
|
99
|
+
break;
|
|
100
|
+
case 'continue':
|
|
101
|
+
default:
|
|
102
|
+
// Continue — dependent phases will check deps naturally
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// For abort: mark any phases from this level that haven't completed
|
|
108
|
+
// (in practice all completed since we awaited, but semantically distinct
|
|
109
|
+
// from stop in that we don't start the next level either)
|
|
110
|
+
if (aborted) {
|
|
111
|
+
// Remaining levels will be skipped in the next iteration
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
throw new WorkflowError(`Workflow failed: ${formatErrorMessage(error)}`, { partialResult: this.buildPartialResult(def, phaseResults, allRecommendations, startTime, resolved.hash) });
|
|
118
|
+
}
|
|
119
|
+
const aggregated = this.aggregate(def.workflow.aggregation, phaseResults);
|
|
120
|
+
const durationMs = Date.now() - startTime;
|
|
121
|
+
const tokenTotals = sumTokenMetrics(phaseResults.flatMap(p => p.commands.map(c => c.metrics)));
|
|
122
|
+
return {
|
|
123
|
+
type: 'workflow',
|
|
124
|
+
name: def.workflow.interface.name,
|
|
125
|
+
version: def.workflow.interface.version,
|
|
126
|
+
definitionHash: resolved.hash,
|
|
127
|
+
decision: aggregated.decision,
|
|
128
|
+
score: aggregated.score,
|
|
129
|
+
phases: phaseResults,
|
|
130
|
+
recommendations: this.deduplicateRecommendations(allRecommendations),
|
|
131
|
+
durationMs,
|
|
132
|
+
metrics: {
|
|
133
|
+
...tokenTotals,
|
|
134
|
+
durationMs,
|
|
135
|
+
model: 'mixed',
|
|
136
|
+
phasesExecuted: phaseResults.filter(p => p.decision !== 'skipped' && p.decision !== 'aborted').length,
|
|
137
|
+
phasesPassed: phaseResults.filter(p => p.decision === 'passed').length,
|
|
138
|
+
phasesWarned: phaseResults.filter(p => p.decision === 'warned').length,
|
|
139
|
+
phasesBlocked: phaseResults.filter(p => p.decision === 'blocked').length,
|
|
140
|
+
phasesSkipped: phaseResults.filter(p => p.decision === 'skipped').length,
|
|
141
|
+
phasesAborted: phaseResults.filter(p => p.decision === 'aborted').length,
|
|
142
|
+
commands: phaseResults.flatMap(p => p.commands.map(c => ({
|
|
143
|
+
name: c.name,
|
|
144
|
+
score: c.score ?? 0,
|
|
145
|
+
decision: c.decision,
|
|
146
|
+
inputTokens: c.metrics.inputTokens,
|
|
147
|
+
outputTokens: c.metrics.outputTokens,
|
|
148
|
+
durationMs: c.metrics.durationMs,
|
|
149
|
+
costUsd: c.metrics.costUsd,
|
|
150
|
+
}))),
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Execute a set of independent phases in parallel.
|
|
156
|
+
*
|
|
157
|
+
* Respects max_parallel concurrency limit if set. Uses Promise.allSettled
|
|
158
|
+
* to ensure partial failures don't reject the entire level.
|
|
159
|
+
*/
|
|
160
|
+
async executePhasesParallel(phases, input, maxParallel) {
|
|
161
|
+
if (phases.length === 1) {
|
|
162
|
+
// Single phase — no need for concurrency machinery
|
|
163
|
+
return [await this.executePhase(phases[0], input)];
|
|
164
|
+
}
|
|
165
|
+
if (maxParallel && maxParallel > 0 && maxParallel < phases.length) {
|
|
166
|
+
// Semaphore-limited concurrency
|
|
167
|
+
return this.executePhasesWithLimit(phases, input, maxParallel);
|
|
168
|
+
}
|
|
169
|
+
// Unlimited parallel — all phases in this level run concurrently
|
|
170
|
+
const settled = await Promise.allSettled(phases.map(phase => this.executePhase(phase, input)));
|
|
171
|
+
const results = [];
|
|
172
|
+
for (let i = 0; i < settled.length; i++) {
|
|
173
|
+
const outcome = settled[i];
|
|
174
|
+
if (outcome.status === 'fulfilled') {
|
|
175
|
+
results.push(outcome.value);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// Phase threw — create a blocked result preserving error context
|
|
179
|
+
results.push(this.createBlockedPhase(phases[i], outcome.reason));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return results;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Execute phases with a concurrency semaphore.
|
|
186
|
+
*/
|
|
187
|
+
async executePhasesWithLimit(phases, input, limit) {
|
|
188
|
+
const results = new Array(phases.length);
|
|
189
|
+
let nextIndex = 0;
|
|
190
|
+
async function runNext(executor) {
|
|
191
|
+
while (nextIndex < phases.length) {
|
|
192
|
+
const idx = nextIndex++;
|
|
193
|
+
const phase = phases[idx];
|
|
194
|
+
try {
|
|
195
|
+
results[idx] = await executor.executePhase(phase, input);
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
results[idx] = executor.createBlockedPhase(phase, error);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const workers = Array.from({ length: Math.min(limit, phases.length) }, () => runNext(this));
|
|
203
|
+
await Promise.all(workers);
|
|
204
|
+
return results;
|
|
205
|
+
}
|
|
206
|
+
async executePhase(phase, input) {
|
|
207
|
+
const phaseStart = Date.now();
|
|
208
|
+
const commandResults = [];
|
|
209
|
+
if (phase.parallel) {
|
|
210
|
+
const settled = await Promise.allSettled(phase.commands.map(cmdName => this.executeCommand(cmdName, input)));
|
|
211
|
+
const errors = [];
|
|
212
|
+
for (let j = 0; j < settled.length; j++) {
|
|
213
|
+
const outcome = settled[j];
|
|
214
|
+
if (outcome.status === 'fulfilled') {
|
|
215
|
+
commandResults.push(outcome.value);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
const errorMsg = outcome.reason instanceof Error ? outcome.reason.message : String(outcome.reason);
|
|
219
|
+
errors.push(errorMsg);
|
|
220
|
+
// Failed commands contribute a zero-score result so they penalize the aggregate
|
|
221
|
+
commandResults.push({
|
|
222
|
+
type: 'command',
|
|
223
|
+
name: phase.commands[j],
|
|
224
|
+
version: '',
|
|
225
|
+
definitionHash: '',
|
|
226
|
+
agentType: 'validator',
|
|
227
|
+
decision: 'FAIL',
|
|
228
|
+
score: 0,
|
|
229
|
+
maxScore: 100,
|
|
230
|
+
recommendations: [],
|
|
231
|
+
durationMs: 0,
|
|
232
|
+
metrics: { inputTokens: 0, outputTokens: 0, totalEffectiveTokens: 0, durationMs: 0, model: 'unknown', toolCalls: 0 },
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (errors.length > 0 && commandResults.length === errors.length) {
|
|
237
|
+
throw new Error(`All parallel commands in phase "${phase.name}" failed: ${errors.join('; ')}`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
for (const cmdName of phase.commands) {
|
|
242
|
+
const result = await this.executeCommand(cmdName, input);
|
|
243
|
+
commandResults.push(result);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
const aggregateScore = this.aggregatePhaseScore(commandResults, phase.gate?.aggregate ?? 'average');
|
|
247
|
+
const decision = this.evaluateGate(aggregateScore, phase.gate);
|
|
248
|
+
return {
|
|
249
|
+
id: phase.id,
|
|
250
|
+
name: phase.name,
|
|
251
|
+
decision,
|
|
252
|
+
commands: commandResults,
|
|
253
|
+
gateThreshold: phase.gate?.threshold ?? 70,
|
|
254
|
+
score: aggregateScore,
|
|
255
|
+
durationMs: Date.now() - phaseStart,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
async executeCommand(cmdName, input) {
|
|
259
|
+
const resolved = await this.registry.resolve(cmdName);
|
|
260
|
+
return this.commandExecutor.execute(resolved, input);
|
|
261
|
+
}
|
|
262
|
+
aggregatePhaseScore(results, method) {
|
|
263
|
+
if (results.length === 0)
|
|
264
|
+
return 0;
|
|
265
|
+
const scores = results.map(r => r.score ?? 0);
|
|
266
|
+
switch (method) {
|
|
267
|
+
case 'min': return Math.min(...scores);
|
|
268
|
+
case 'max': return Math.max(...scores);
|
|
269
|
+
case 'average':
|
|
270
|
+
default:
|
|
271
|
+
return scores.reduce((a, b) => a + b, 0) / scores.length;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
evaluateGate(score, gate) {
|
|
275
|
+
if (!gate)
|
|
276
|
+
return 'passed';
|
|
277
|
+
if (score >= gate.threshold)
|
|
278
|
+
return 'passed';
|
|
279
|
+
if (gate.on_fail === 'warn')
|
|
280
|
+
return 'warned';
|
|
281
|
+
return 'blocked';
|
|
282
|
+
}
|
|
283
|
+
aggregate(config, phases) {
|
|
284
|
+
const weights = config?.score?.weights ?? {};
|
|
285
|
+
let totalWeight = 0;
|
|
286
|
+
let weightedScore = 0;
|
|
287
|
+
for (const phase of phases) {
|
|
288
|
+
if (phase.decision === 'skipped' || phase.decision === 'aborted')
|
|
289
|
+
continue;
|
|
290
|
+
const weight = weights[phase.id] ?? 1;
|
|
291
|
+
totalWeight += weight;
|
|
292
|
+
weightedScore += phase.score * weight;
|
|
293
|
+
}
|
|
294
|
+
const score = totalWeight > 0 ? Math.round(weightedScore / totalWeight) : 0;
|
|
295
|
+
const hasBlocked = phases.some(p => p.decision === 'blocked');
|
|
296
|
+
const hasWarned = phases.some(p => p.decision === 'warned');
|
|
297
|
+
const hasAborted = phases.some(p => p.decision === 'aborted');
|
|
298
|
+
let decision;
|
|
299
|
+
if (hasBlocked || hasAborted) {
|
|
300
|
+
decision = config?.decision?.BLOCK ?? 'BLOCK';
|
|
301
|
+
}
|
|
302
|
+
else if (hasWarned) {
|
|
303
|
+
decision = config?.decision?.HOLD ?? 'HOLD';
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
decision = config?.decision?.SHIP ?? 'SHIP';
|
|
307
|
+
}
|
|
308
|
+
return { decision, score };
|
|
309
|
+
}
|
|
310
|
+
createBlockedPhase(phase, error) {
|
|
311
|
+
return {
|
|
312
|
+
id: phase.id,
|
|
313
|
+
name: phase.name,
|
|
314
|
+
decision: 'blocked',
|
|
315
|
+
commands: [],
|
|
316
|
+
gateThreshold: phase.gate?.threshold ?? 70,
|
|
317
|
+
score: 0,
|
|
318
|
+
durationMs: 0,
|
|
319
|
+
...(error ? { error: formatErrorMessage(error) } : {}),
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
createSkippedPhase(phase) {
|
|
323
|
+
return {
|
|
324
|
+
id: phase.id,
|
|
325
|
+
name: phase.name,
|
|
326
|
+
decision: 'skipped',
|
|
327
|
+
commands: [],
|
|
328
|
+
gateThreshold: phase.gate?.threshold ?? 70,
|
|
329
|
+
score: 0,
|
|
330
|
+
durationMs: 0,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
checkDependencies(dependsOn, completedPhases) {
|
|
334
|
+
if (!dependsOn || dependsOn.length === 0)
|
|
335
|
+
return true;
|
|
336
|
+
return dependsOn.every(depId => {
|
|
337
|
+
const dep = completedPhases.get(depId);
|
|
338
|
+
return dep && dep.decision !== 'blocked' && dep.decision !== 'aborted';
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
evaluateCondition(condition, input, _phases) {
|
|
342
|
+
const match = condition.match(/\{\{\s*input\.(\w+)\s*\}\}/);
|
|
343
|
+
if (match?.[1])
|
|
344
|
+
return Boolean(input.options?.[match[1]]);
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
347
|
+
deduplicateRecommendations(recommendations) {
|
|
348
|
+
const seen = new Set();
|
|
349
|
+
return recommendations.filter(r => {
|
|
350
|
+
const key = `${r.title}|${r.filePath ?? ''}|${r.lineNumber ?? ''}`;
|
|
351
|
+
if (seen.has(key))
|
|
352
|
+
return false;
|
|
353
|
+
seen.add(key);
|
|
354
|
+
return true;
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
buildPartialResult(def, phases, recommendations, startTime, hash) {
|
|
358
|
+
return {
|
|
359
|
+
type: 'workflow',
|
|
360
|
+
name: def.workflow.interface.name,
|
|
361
|
+
definitionHash: hash,
|
|
362
|
+
phases,
|
|
363
|
+
recommendations,
|
|
364
|
+
durationMs: Date.now() - startTime,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
//# sourceMappingURL=WorkflowExecutor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowExecutor.js","sourceRoot":"","sources":["../../src/executor/WorkflowExecutor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PreflightCheck } from '../types/command.js';
|
|
2
|
+
import type { ExecutionInput } from '../types/execution.js';
|
|
3
|
+
/**
|
|
4
|
+
* Run a set of preflight checks before command execution.
|
|
5
|
+
* Throws PreflightError on first failure.
|
|
6
|
+
*/
|
|
7
|
+
export declare function runPreflightChecks(checks: PreflightCheck[], input: ExecutionInput): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=preflight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../../src/executor/preflight.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAK5D;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,cAAc,EAAE,EACxB,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,IAAI,CAAC,CAIf"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { execFile } from 'node:child_process';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
import { PreflightError } from '../errors/index.js';
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
/**
|
|
8
|
+
* Run a set of preflight checks before command execution.
|
|
9
|
+
* Throws PreflightError on first failure.
|
|
10
|
+
*/
|
|
11
|
+
export async function runPreflightChecks(checks, input) {
|
|
12
|
+
for (const check of checks) {
|
|
13
|
+
await runSingleCheck(check, input);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
async function runSingleCheck(check, input) {
|
|
17
|
+
switch (check.check) {
|
|
18
|
+
case 'file_exists':
|
|
19
|
+
return checkFileExists(check, input);
|
|
20
|
+
case 'command':
|
|
21
|
+
return checkCommand(check);
|
|
22
|
+
case 'env_var':
|
|
23
|
+
return checkEnvVar(check);
|
|
24
|
+
case 'git_clean':
|
|
25
|
+
return checkGitClean(input);
|
|
26
|
+
default:
|
|
27
|
+
throw new PreflightError(`Unknown preflight check type: ${check.check}`, check.check);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function checkFileExists(check, input) {
|
|
31
|
+
if (!check.path) {
|
|
32
|
+
throw new PreflightError('file_exists check requires a path', 'file_exists');
|
|
33
|
+
}
|
|
34
|
+
const targetRoot = path.resolve(input.target);
|
|
35
|
+
const fullPath = path.resolve(input.target, check.path);
|
|
36
|
+
if (!fullPath.startsWith(targetRoot + path.sep) && fullPath !== targetRoot) {
|
|
37
|
+
throw new PreflightError(`file_exists path escapes target directory: ${check.path}`, 'file_exists', { path: check.path });
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
await fs.access(fullPath);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
throw new PreflightError(check.message ?? `Required file not found: ${check.path}`, 'file_exists', { path: check.path });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Run a shell command from a CDL preflight definition.
|
|
48
|
+
*
|
|
49
|
+
* SECURITY: The command string comes from the definition YAML file, which is
|
|
50
|
+
* authored by the SDK user (not end-user input). It's passed to `sh -c` via
|
|
51
|
+
* execFile's argv array (not shell-expanded), but the inner command IS
|
|
52
|
+
* interpreted by sh. We reject commands that contain obvious injection
|
|
53
|
+
* patterns from untrusted YAML.
|
|
54
|
+
*/
|
|
55
|
+
async function checkCommand(check) {
|
|
56
|
+
if (!check.command) {
|
|
57
|
+
throw new PreflightError('command check requires a command', 'command');
|
|
58
|
+
}
|
|
59
|
+
// Reject commands with shell metacharacters that could be used for injection:
|
|
60
|
+
// backtick/process substitution (`cmd`, $(cmd)), chaining (; && || newlines),
|
|
61
|
+
// pipes (|), and redirections (>, <) which could exfiltrate data or chain commands.
|
|
62
|
+
if (/`|\$\(|;|&&|\|\||\|[^|]|(?<![|])>|<|\n|\r/.test(check.command)) {
|
|
63
|
+
throw new PreflightError(`Preflight command contains disallowed shell metacharacter: ${check.command}`, 'command', { command: check.command });
|
|
64
|
+
}
|
|
65
|
+
// Reject interpreter-based code execution that bypasses the metacharacter filter.
|
|
66
|
+
// Commands like `node -e "..."` or `python3 -c "..."` can execute arbitrary code
|
|
67
|
+
// without using any blocked metacharacters.
|
|
68
|
+
if (/\b(node|python[23]?|ruby|perl|php|lua|deno|bun)\s+(-e|--eval|-c)\b/.test(check.command)) {
|
|
69
|
+
throw new PreflightError(`Preflight command contains disallowed interpreter eval: ${check.command}`, 'command', { command: check.command });
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
await execFileAsync('sh', ['-c', check.command], { timeout: 10_000 });
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
throw new PreflightError(check.message ?? `Command check failed: ${check.command}`, 'command', { command: check.command });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function checkEnvVar(check) {
|
|
79
|
+
if (!check.var) {
|
|
80
|
+
throw new PreflightError('env_var check requires a var name', 'env_var');
|
|
81
|
+
}
|
|
82
|
+
if (process.env[check.var] === undefined) {
|
|
83
|
+
throw new PreflightError(check.message ?? `Required environment variable not set: ${check.var}`, 'env_var', { var: check.var });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function checkGitClean(input) {
|
|
87
|
+
try {
|
|
88
|
+
const { stdout } = await execFileAsync('git', ['status', '--porcelain'], {
|
|
89
|
+
cwd: input.target,
|
|
90
|
+
timeout: 10_000,
|
|
91
|
+
});
|
|
92
|
+
if (stdout.trim().length > 0) {
|
|
93
|
+
throw new PreflightError('Git working directory is not clean', 'git_clean');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (error instanceof PreflightError)
|
|
98
|
+
throw error;
|
|
99
|
+
throw new PreflightError(`Failed to check git status: ${error instanceof Error ? error.message : 'is this a git repository?'}`, 'git_clean');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=preflight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../src/executor/preflight.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Symbol extraction from source files.
|
|
3
|
+
* Extracts exported/private functions, classes, interfaces, types, constants.
|
|
4
|
+
*/
|
|
5
|
+
export interface SymbolInfo {
|
|
6
|
+
type: string;
|
|
7
|
+
name: string;
|
|
8
|
+
line: number;
|
|
9
|
+
exported: boolean;
|
|
10
|
+
signature?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function extractSymbols(lines: string[], ext: string, includePrivate: boolean): SymbolInfo[];
|
|
13
|
+
//# sourceMappingURL=symbols.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbols.d.ts","sourceRoot":"","sources":["../../src/executor/symbols.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,GAAG,UAAU,EAAE,CAelG"}
|