@renseiai/agentfactory 0.8.8 → 0.8.9
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/dist/src/config/index.d.ts +1 -1
- package/dist/src/config/index.d.ts.map +1 -1
- package/dist/src/config/index.js +1 -1
- package/dist/src/config/repository-config.d.ts +23 -0
- package/dist/src/config/repository-config.d.ts.map +1 -1
- package/dist/src/config/repository-config.js +27 -0
- package/dist/src/config/repository-config.test.js +140 -1
- package/dist/src/governor/decision-engine.d.ts +3 -0
- package/dist/src/governor/decision-engine.d.ts.map +1 -1
- package/dist/src/governor/decision-engine.js +11 -0
- package/dist/src/governor/decision-engine.test.js +33 -0
- package/dist/src/governor/governor-types.d.ts +1 -1
- package/dist/src/governor/governor-types.d.ts.map +1 -1
- package/dist/src/governor/governor.d.ts +17 -1
- package/dist/src/governor/governor.d.ts.map +1 -1
- package/dist/src/governor/governor.js +112 -1
- package/dist/src/governor/governor.test.js +155 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/orchestrator/issue-tracker-client.d.ts +4 -0
- package/dist/src/orchestrator/issue-tracker-client.d.ts.map +1 -1
- package/dist/src/orchestrator/orchestrator.d.ts.map +1 -1
- package/dist/src/orchestrator/orchestrator.js +24 -0
- package/dist/src/orchestrator/parse-work-result.d.ts.map +1 -1
- package/dist/src/orchestrator/parse-work-result.js +6 -0
- package/dist/src/orchestrator/parse-work-result.test.js +19 -0
- package/dist/src/providers/index.d.ts +64 -1
- package/dist/src/providers/index.d.ts.map +1 -1
- package/dist/src/providers/index.js +132 -1
- package/dist/src/providers/index.test.js +340 -2
- package/dist/src/routing/index.d.ts +7 -0
- package/dist/src/routing/index.d.ts.map +1 -0
- package/dist/src/routing/index.js +6 -0
- package/dist/src/routing/observation-recorder.d.ts +19 -0
- package/dist/src/routing/observation-recorder.d.ts.map +1 -0
- package/dist/src/routing/observation-recorder.js +73 -0
- package/dist/src/routing/observation-recorder.test.d.ts +2 -0
- package/dist/src/routing/observation-recorder.test.d.ts.map +1 -0
- package/dist/src/routing/observation-recorder.test.js +322 -0
- package/dist/src/routing/observation-store.d.ts +40 -0
- package/dist/src/routing/observation-store.d.ts.map +1 -0
- package/dist/src/routing/observation-store.js +1 -0
- package/dist/src/routing/observation-store.test.d.ts +2 -0
- package/dist/src/routing/observation-store.test.d.ts.map +1 -0
- package/dist/src/routing/observation-store.test.js +138 -0
- package/dist/src/routing/posterior-store.d.ts +12 -0
- package/dist/src/routing/posterior-store.d.ts.map +1 -0
- package/dist/src/routing/posterior-store.js +13 -0
- package/dist/src/routing/posterior-store.test.d.ts +2 -0
- package/dist/src/routing/posterior-store.test.d.ts.map +1 -0
- package/dist/src/routing/posterior-store.test.js +37 -0
- package/dist/src/routing/reward.d.ts +16 -0
- package/dist/src/routing/reward.d.ts.map +1 -0
- package/dist/src/routing/reward.js +29 -0
- package/dist/src/routing/reward.test.d.ts +2 -0
- package/dist/src/routing/reward.test.d.ts.map +1 -0
- package/dist/src/routing/reward.test.js +210 -0
- package/dist/src/routing/routing-engine.d.ts +20 -0
- package/dist/src/routing/routing-engine.d.ts.map +1 -0
- package/dist/src/routing/routing-engine.js +113 -0
- package/dist/src/routing/routing-engine.test.d.ts +2 -0
- package/dist/src/routing/routing-engine.test.d.ts.map +1 -0
- package/dist/src/routing/routing-engine.test.js +310 -0
- package/dist/src/routing/types.d.ts +157 -0
- package/dist/src/routing/types.d.ts.map +1 -0
- package/dist/src/routing/types.js +68 -0
- package/dist/src/routing/types.test.d.ts +2 -0
- package/dist/src/routing/types.test.d.ts.map +1 -0
- package/dist/src/routing/types.test.js +184 -0
- package/dist/src/templates/types.d.ts +3 -0
- package/dist/src/templates/types.d.ts.map +1 -1
- package/dist/src/templates/types.js +2 -0
- package/dist/src/workflow/agent-cancellation.d.ts +37 -0
- package/dist/src/workflow/agent-cancellation.d.ts.map +1 -0
- package/dist/src/workflow/agent-cancellation.js +41 -0
- package/dist/src/workflow/agent-cancellation.test.d.ts +2 -0
- package/dist/src/workflow/agent-cancellation.test.d.ts.map +1 -0
- package/dist/src/workflow/agent-cancellation.test.js +86 -0
- package/dist/src/workflow/concurrency-semaphore.d.ts +21 -0
- package/dist/src/workflow/concurrency-semaphore.d.ts.map +1 -0
- package/dist/src/workflow/concurrency-semaphore.js +46 -0
- package/dist/src/workflow/concurrency-semaphore.test.d.ts +2 -0
- package/dist/src/workflow/concurrency-semaphore.test.d.ts.map +1 -0
- package/dist/src/workflow/concurrency-semaphore.test.js +183 -0
- package/dist/src/workflow/gate-state.d.ts +115 -0
- package/dist/src/workflow/gate-state.d.ts.map +1 -0
- package/dist/src/workflow/gate-state.js +185 -0
- package/dist/src/workflow/gate-state.test.d.ts +2 -0
- package/dist/src/workflow/gate-state.test.d.ts.map +1 -0
- package/dist/src/workflow/gate-state.test.js +251 -0
- package/dist/src/workflow/gates/gate-evaluator.d.ts +119 -0
- package/dist/src/workflow/gates/gate-evaluator.d.ts.map +1 -0
- package/dist/src/workflow/gates/gate-evaluator.js +243 -0
- package/dist/src/workflow/gates/gate-evaluator.test.d.ts +2 -0
- package/dist/src/workflow/gates/gate-evaluator.test.d.ts.map +1 -0
- package/dist/src/workflow/gates/gate-evaluator.test.js +240 -0
- package/dist/src/workflow/gates/signal-gate.d.ts +114 -0
- package/dist/src/workflow/gates/signal-gate.d.ts.map +1 -0
- package/dist/src/workflow/gates/signal-gate.js +216 -0
- package/dist/src/workflow/gates/signal-gate.test.d.ts +2 -0
- package/dist/src/workflow/gates/signal-gate.test.d.ts.map +1 -0
- package/dist/src/workflow/gates/signal-gate.test.js +199 -0
- package/dist/src/workflow/gates/timeout-engine.d.ts +96 -0
- package/dist/src/workflow/gates/timeout-engine.d.ts.map +1 -0
- package/dist/src/workflow/gates/timeout-engine.js +162 -0
- package/dist/src/workflow/gates/timeout-engine.test.d.ts +2 -0
- package/dist/src/workflow/gates/timeout-engine.test.d.ts.map +1 -0
- package/dist/src/workflow/gates/timeout-engine.test.js +186 -0
- package/dist/src/workflow/gates/timer-gate.d.ts +125 -0
- package/dist/src/workflow/gates/timer-gate.d.ts.map +1 -0
- package/dist/src/workflow/gates/timer-gate.js +381 -0
- package/dist/src/workflow/gates/timer-gate.test.d.ts +2 -0
- package/dist/src/workflow/gates/timer-gate.test.d.ts.map +1 -0
- package/dist/src/workflow/gates/timer-gate.test.js +211 -0
- package/dist/src/workflow/gates/webhook-gate.d.ts +132 -0
- package/dist/src/workflow/gates/webhook-gate.d.ts.map +1 -0
- package/dist/src/workflow/gates/webhook-gate.js +216 -0
- package/dist/src/workflow/gates/webhook-gate.test.d.ts +2 -0
- package/dist/src/workflow/gates/webhook-gate.test.d.ts.map +1 -0
- package/dist/src/workflow/gates/webhook-gate.test.js +182 -0
- package/dist/src/workflow/index.d.ts +23 -2
- package/dist/src/workflow/index.d.ts.map +1 -1
- package/dist/src/workflow/index.js +15 -1
- package/dist/src/workflow/parallelism-executor.d.ts +25 -0
- package/dist/src/workflow/parallelism-executor.d.ts.map +1 -0
- package/dist/src/workflow/parallelism-executor.js +53 -0
- package/dist/src/workflow/parallelism-executor.test.d.ts +2 -0
- package/dist/src/workflow/parallelism-executor.test.d.ts.map +1 -0
- package/dist/src/workflow/parallelism-executor.test.js +191 -0
- package/dist/src/workflow/parallelism-types.d.ts +80 -0
- package/dist/src/workflow/parallelism-types.d.ts.map +1 -0
- package/dist/src/workflow/parallelism-types.js +8 -0
- package/dist/src/workflow/phase-context-injector.d.ts +29 -0
- package/dist/src/workflow/phase-context-injector.d.ts.map +1 -0
- package/dist/src/workflow/phase-context-injector.js +43 -0
- package/dist/src/workflow/phase-context-injector.test.d.ts +2 -0
- package/dist/src/workflow/phase-context-injector.test.d.ts.map +1 -0
- package/dist/src/workflow/phase-context-injector.test.js +123 -0
- package/dist/src/workflow/phase-output-collector.d.ts +39 -0
- package/dist/src/workflow/phase-output-collector.d.ts.map +1 -0
- package/dist/src/workflow/phase-output-collector.js +141 -0
- package/dist/src/workflow/phase-output-collector.test.d.ts +2 -0
- package/dist/src/workflow/phase-output-collector.test.d.ts.map +1 -0
- package/dist/src/workflow/phase-output-collector.test.js +179 -0
- package/dist/src/workflow/strategies/fan-in-strategy.d.ts +21 -0
- package/dist/src/workflow/strategies/fan-in-strategy.d.ts.map +1 -0
- package/dist/src/workflow/strategies/fan-in-strategy.js +92 -0
- package/dist/src/workflow/strategies/fan-in-strategy.test.d.ts +2 -0
- package/dist/src/workflow/strategies/fan-in-strategy.test.d.ts.map +1 -0
- package/dist/src/workflow/strategies/fan-in-strategy.test.js +182 -0
- package/dist/src/workflow/strategies/fan-out-strategy.d.ts +16 -0
- package/dist/src/workflow/strategies/fan-out-strategy.d.ts.map +1 -0
- package/dist/src/workflow/strategies/fan-out-strategy.js +47 -0
- package/dist/src/workflow/strategies/fan-out-strategy.test.d.ts +2 -0
- package/dist/src/workflow/strategies/fan-out-strategy.test.d.ts.map +1 -0
- package/dist/src/workflow/strategies/fan-out-strategy.test.js +97 -0
- package/dist/src/workflow/strategies/index.d.ts +4 -0
- package/dist/src/workflow/strategies/index.d.ts.map +1 -0
- package/dist/src/workflow/strategies/index.js +3 -0
- package/dist/src/workflow/strategies/race-strategy.d.ts +19 -0
- package/dist/src/workflow/strategies/race-strategy.d.ts.map +1 -0
- package/dist/src/workflow/strategies/race-strategy.js +92 -0
- package/dist/src/workflow/strategies/race-strategy.test.d.ts +2 -0
- package/dist/src/workflow/strategies/race-strategy.test.d.ts.map +1 -0
- package/dist/src/workflow/strategies/race-strategy.test.js +318 -0
- package/dist/src/workflow/transition-engine.d.ts.map +1 -1
- package/dist/src/workflow/transition-engine.js +12 -0
- package/dist/src/workflow/transition-engine.test.js +92 -0
- package/dist/src/workflow/workflow-registry.d.ts +5 -1
- package/dist/src/workflow/workflow-registry.d.ts.map +1 -1
- package/dist/src/workflow/workflow-registry.js +8 -0
- package/dist/src/workflow/workflow-registry.test.js +54 -0
- package/dist/src/workflow/workflow-types.d.ts +151 -6
- package/dist/src/workflow/workflow-types.d.ts.map +1 -1
- package/dist/src/workflow/workflow-types.js +71 -1
- package/dist/src/workflow/workflow-types.test.js +293 -2
- package/package.json +2 -2
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { AgentProviderName } from '../providers/types.js';
|
|
3
|
+
import type { AgentWorkType } from '../orchestrator/work-types.js';
|
|
4
|
+
export interface RoutingObservation {
|
|
5
|
+
id: string;
|
|
6
|
+
provider: AgentProviderName;
|
|
7
|
+
workType: AgentWorkType;
|
|
8
|
+
project?: string;
|
|
9
|
+
issueIdentifier: string;
|
|
10
|
+
sessionId: string;
|
|
11
|
+
reward: number;
|
|
12
|
+
taskCompleted: boolean;
|
|
13
|
+
prCreated: boolean;
|
|
14
|
+
qaResult: 'passed' | 'failed' | 'unknown';
|
|
15
|
+
totalCostUsd: number;
|
|
16
|
+
wallClockMs: number;
|
|
17
|
+
timestamp: number;
|
|
18
|
+
confidence: number;
|
|
19
|
+
explorationReason?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare const RoutingObservationSchema: z.ZodObject<{
|
|
22
|
+
id: z.ZodString;
|
|
23
|
+
provider: z.ZodEnum<{
|
|
24
|
+
claude: "claude";
|
|
25
|
+
codex: "codex";
|
|
26
|
+
amp: "amp";
|
|
27
|
+
"spring-ai": "spring-ai";
|
|
28
|
+
a2a: "a2a";
|
|
29
|
+
}>;
|
|
30
|
+
workType: z.ZodEnum<{
|
|
31
|
+
research: "research";
|
|
32
|
+
"backlog-creation": "backlog-creation";
|
|
33
|
+
development: "development";
|
|
34
|
+
inflight: "inflight";
|
|
35
|
+
"inflight-coordination": "inflight-coordination";
|
|
36
|
+
qa: "qa";
|
|
37
|
+
acceptance: "acceptance";
|
|
38
|
+
refinement: "refinement";
|
|
39
|
+
"refinement-coordination": "refinement-coordination";
|
|
40
|
+
coordination: "coordination";
|
|
41
|
+
"qa-coordination": "qa-coordination";
|
|
42
|
+
"acceptance-coordination": "acceptance-coordination";
|
|
43
|
+
}>;
|
|
44
|
+
project: z.ZodOptional<z.ZodString>;
|
|
45
|
+
issueIdentifier: z.ZodString;
|
|
46
|
+
sessionId: z.ZodString;
|
|
47
|
+
reward: z.ZodNumber;
|
|
48
|
+
taskCompleted: z.ZodBoolean;
|
|
49
|
+
prCreated: z.ZodBoolean;
|
|
50
|
+
qaResult: z.ZodEnum<{
|
|
51
|
+
failed: "failed";
|
|
52
|
+
passed: "passed";
|
|
53
|
+
unknown: "unknown";
|
|
54
|
+
}>;
|
|
55
|
+
totalCostUsd: z.ZodNumber;
|
|
56
|
+
wallClockMs: z.ZodNumber;
|
|
57
|
+
timestamp: z.ZodNumber;
|
|
58
|
+
confidence: z.ZodNumber;
|
|
59
|
+
explorationReason: z.ZodOptional<z.ZodString>;
|
|
60
|
+
}, z.core.$strip>;
|
|
61
|
+
export interface RoutingPosterior {
|
|
62
|
+
provider: AgentProviderName;
|
|
63
|
+
workType: AgentWorkType;
|
|
64
|
+
alpha: number;
|
|
65
|
+
beta: number;
|
|
66
|
+
totalObservations: number;
|
|
67
|
+
avgReward: number;
|
|
68
|
+
avgCostUsd: number;
|
|
69
|
+
lastUpdated: number;
|
|
70
|
+
}
|
|
71
|
+
export declare const RoutingPosteriorSchema: z.ZodObject<{
|
|
72
|
+
provider: z.ZodEnum<{
|
|
73
|
+
claude: "claude";
|
|
74
|
+
codex: "codex";
|
|
75
|
+
amp: "amp";
|
|
76
|
+
"spring-ai": "spring-ai";
|
|
77
|
+
a2a: "a2a";
|
|
78
|
+
}>;
|
|
79
|
+
workType: z.ZodEnum<{
|
|
80
|
+
research: "research";
|
|
81
|
+
"backlog-creation": "backlog-creation";
|
|
82
|
+
development: "development";
|
|
83
|
+
inflight: "inflight";
|
|
84
|
+
"inflight-coordination": "inflight-coordination";
|
|
85
|
+
qa: "qa";
|
|
86
|
+
acceptance: "acceptance";
|
|
87
|
+
refinement: "refinement";
|
|
88
|
+
"refinement-coordination": "refinement-coordination";
|
|
89
|
+
coordination: "coordination";
|
|
90
|
+
"qa-coordination": "qa-coordination";
|
|
91
|
+
"acceptance-coordination": "acceptance-coordination";
|
|
92
|
+
}>;
|
|
93
|
+
alpha: z.ZodNumber;
|
|
94
|
+
beta: z.ZodNumber;
|
|
95
|
+
totalObservations: z.ZodNumber;
|
|
96
|
+
avgReward: z.ZodNumber;
|
|
97
|
+
avgCostUsd: z.ZodNumber;
|
|
98
|
+
lastUpdated: z.ZodNumber;
|
|
99
|
+
}, z.core.$strip>;
|
|
100
|
+
export interface RoutingDecision {
|
|
101
|
+
selectedProvider: AgentProviderName;
|
|
102
|
+
confidence: number;
|
|
103
|
+
expectedReward: number;
|
|
104
|
+
explorationReason?: string;
|
|
105
|
+
source: 'mab-routing';
|
|
106
|
+
alternatives: Array<{
|
|
107
|
+
provider: AgentProviderName;
|
|
108
|
+
expectedReward: number;
|
|
109
|
+
confidence: number;
|
|
110
|
+
}>;
|
|
111
|
+
}
|
|
112
|
+
export declare const RoutingDecisionSchema: z.ZodObject<{
|
|
113
|
+
selectedProvider: z.ZodEnum<{
|
|
114
|
+
claude: "claude";
|
|
115
|
+
codex: "codex";
|
|
116
|
+
amp: "amp";
|
|
117
|
+
"spring-ai": "spring-ai";
|
|
118
|
+
a2a: "a2a";
|
|
119
|
+
}>;
|
|
120
|
+
confidence: z.ZodNumber;
|
|
121
|
+
expectedReward: z.ZodNumber;
|
|
122
|
+
explorationReason: z.ZodOptional<z.ZodString>;
|
|
123
|
+
source: z.ZodLiteral<"mab-routing">;
|
|
124
|
+
alternatives: z.ZodArray<z.ZodObject<{
|
|
125
|
+
provider: z.ZodEnum<{
|
|
126
|
+
claude: "claude";
|
|
127
|
+
codex: "codex";
|
|
128
|
+
amp: "amp";
|
|
129
|
+
"spring-ai": "spring-ai";
|
|
130
|
+
a2a: "a2a";
|
|
131
|
+
}>;
|
|
132
|
+
expectedReward: z.ZodNumber;
|
|
133
|
+
confidence: z.ZodNumber;
|
|
134
|
+
}, z.core.$strip>>;
|
|
135
|
+
}, z.core.$strip>;
|
|
136
|
+
export interface RoutingConfig {
|
|
137
|
+
enabled: boolean;
|
|
138
|
+
explorationRate: number;
|
|
139
|
+
windowSize: number;
|
|
140
|
+
discountFactor: number;
|
|
141
|
+
minObservationsForExploit: number;
|
|
142
|
+
changeDetectionThreshold: number;
|
|
143
|
+
}
|
|
144
|
+
export declare const RoutingConfigSchema: z.ZodObject<{
|
|
145
|
+
enabled: z.ZodBoolean;
|
|
146
|
+
explorationRate: z.ZodNumber;
|
|
147
|
+
windowSize: z.ZodNumber;
|
|
148
|
+
discountFactor: z.ZodNumber;
|
|
149
|
+
minObservationsForExploit: z.ZodNumber;
|
|
150
|
+
changeDetectionThreshold: z.ZodNumber;
|
|
151
|
+
}, z.core.$strip>;
|
|
152
|
+
export declare const ROUTING_KEYS: {
|
|
153
|
+
readonly posteriors: (provider: AgentProviderName, workType: AgentWorkType) => string;
|
|
154
|
+
readonly observations: "routing:observations";
|
|
155
|
+
readonly config: "routing:config";
|
|
156
|
+
};
|
|
157
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/routing/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAmBlE,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,QAAQ,EAAE,aAAa,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,OAAO,CAAA;IACtB,SAAS,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAA;IACzC,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgBnC,CAAA;AAEF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,QAAQ,EAAE,aAAa,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBASjC,CAAA;AAEF,MAAM,WAAW,eAAe;IAC9B,gBAAgB,EAAE,iBAAiB,CAAA;IACnC,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,MAAM,EAAE,aAAa,CAAA;IACrB,YAAY,EAAE,KAAK,CAAC;QAClB,QAAQ,EAAE,iBAAiB,CAAA;QAC3B,cAAc,EAAE,MAAM,CAAA;QACtB,UAAU,EAAE,MAAM,CAAA;KACnB,CAAC,CAAA;CACH;AAED,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;iBAahC,CAAA;AAEF,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;IACvB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,yBAAyB,EAAE,MAAM,CAAA;IACjC,wBAAwB,EAAE,MAAM,CAAA;CACjC;AAED,eAAO,MAAM,mBAAmB;;;;;;;iBAO9B,CAAA;AAEF,eAAO,MAAM,YAAY;oCACA,iBAAiB,YAAY,aAAa;;;CAIzD,CAAA"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const AgentProviderNameSchema = z.enum(['claude', 'codex', 'amp', 'spring-ai', 'a2a']);
|
|
3
|
+
const AgentWorkTypeSchema = z.enum([
|
|
4
|
+
'research',
|
|
5
|
+
'backlog-creation',
|
|
6
|
+
'development',
|
|
7
|
+
'inflight',
|
|
8
|
+
'inflight-coordination',
|
|
9
|
+
'qa',
|
|
10
|
+
'acceptance',
|
|
11
|
+
'refinement',
|
|
12
|
+
'refinement-coordination',
|
|
13
|
+
'coordination',
|
|
14
|
+
'qa-coordination',
|
|
15
|
+
'acceptance-coordination',
|
|
16
|
+
]);
|
|
17
|
+
export const RoutingObservationSchema = z.object({
|
|
18
|
+
id: z.string().uuid(),
|
|
19
|
+
provider: AgentProviderNameSchema,
|
|
20
|
+
workType: AgentWorkTypeSchema,
|
|
21
|
+
project: z.string().optional(),
|
|
22
|
+
issueIdentifier: z.string(),
|
|
23
|
+
sessionId: z.string(),
|
|
24
|
+
reward: z.number().min(0).max(1),
|
|
25
|
+
taskCompleted: z.boolean(),
|
|
26
|
+
prCreated: z.boolean(),
|
|
27
|
+
qaResult: z.enum(['passed', 'failed', 'unknown']),
|
|
28
|
+
totalCostUsd: z.number().min(0),
|
|
29
|
+
wallClockMs: z.number().min(0),
|
|
30
|
+
timestamp: z.number(),
|
|
31
|
+
confidence: z.number().min(0).max(1),
|
|
32
|
+
explorationReason: z.string().optional(),
|
|
33
|
+
});
|
|
34
|
+
export const RoutingPosteriorSchema = z.object({
|
|
35
|
+
provider: AgentProviderNameSchema,
|
|
36
|
+
workType: AgentWorkTypeSchema,
|
|
37
|
+
alpha: z.number().min(1),
|
|
38
|
+
beta: z.number().min(1),
|
|
39
|
+
totalObservations: z.number().int().min(0),
|
|
40
|
+
avgReward: z.number().min(0).max(1),
|
|
41
|
+
avgCostUsd: z.number().min(0),
|
|
42
|
+
lastUpdated: z.number(),
|
|
43
|
+
});
|
|
44
|
+
export const RoutingDecisionSchema = z.object({
|
|
45
|
+
selectedProvider: AgentProviderNameSchema,
|
|
46
|
+
confidence: z.number().min(0).max(1),
|
|
47
|
+
expectedReward: z.number().min(0).max(1),
|
|
48
|
+
explorationReason: z.string().optional(),
|
|
49
|
+
source: z.literal('mab-routing'),
|
|
50
|
+
alternatives: z.array(z.object({
|
|
51
|
+
provider: AgentProviderNameSchema,
|
|
52
|
+
expectedReward: z.number().min(0).max(1),
|
|
53
|
+
confidence: z.number().min(0).max(1),
|
|
54
|
+
})),
|
|
55
|
+
});
|
|
56
|
+
export const RoutingConfigSchema = z.object({
|
|
57
|
+
enabled: z.boolean(),
|
|
58
|
+
explorationRate: z.number().min(0).max(1),
|
|
59
|
+
windowSize: z.number().int().positive(),
|
|
60
|
+
discountFactor: z.number().min(0).max(1),
|
|
61
|
+
minObservationsForExploit: z.number().int().min(0),
|
|
62
|
+
changeDetectionThreshold: z.number().min(0),
|
|
63
|
+
});
|
|
64
|
+
export const ROUTING_KEYS = {
|
|
65
|
+
posteriors: (provider, workType) => `routing:posteriors:${provider}:${workType}`,
|
|
66
|
+
observations: 'routing:observations',
|
|
67
|
+
config: 'routing:config',
|
|
68
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.test.d.ts","sourceRoot":"","sources":["../../../src/routing/types.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { RoutingObservationSchema, RoutingPosteriorSchema, RoutingDecisionSchema, RoutingConfigSchema, ROUTING_KEYS, } from './types.js';
|
|
3
|
+
describe('RoutingObservationSchema', () => {
|
|
4
|
+
const validObservation = {
|
|
5
|
+
id: '550e8400-e29b-41d4-a716-446655440000',
|
|
6
|
+
provider: 'claude',
|
|
7
|
+
workType: 'development',
|
|
8
|
+
project: 'Agent',
|
|
9
|
+
issueIdentifier: 'SUP-100',
|
|
10
|
+
sessionId: 'session-abc-123',
|
|
11
|
+
reward: 0.85,
|
|
12
|
+
taskCompleted: true,
|
|
13
|
+
prCreated: true,
|
|
14
|
+
qaResult: 'passed',
|
|
15
|
+
totalCostUsd: 0.42,
|
|
16
|
+
wallClockMs: 120000,
|
|
17
|
+
timestamp: 1700000000,
|
|
18
|
+
confidence: 0.9,
|
|
19
|
+
explorationReason: 'forced',
|
|
20
|
+
};
|
|
21
|
+
it('parses a valid observation', () => {
|
|
22
|
+
const result = RoutingObservationSchema.parse(validObservation);
|
|
23
|
+
expect(result).toEqual(validObservation);
|
|
24
|
+
});
|
|
25
|
+
it('parses without optional fields', () => {
|
|
26
|
+
const { project, explorationReason, ...required } = validObservation;
|
|
27
|
+
const result = RoutingObservationSchema.parse(required);
|
|
28
|
+
expect(result.project).toBeUndefined();
|
|
29
|
+
expect(result.explorationReason).toBeUndefined();
|
|
30
|
+
});
|
|
31
|
+
it('rejects invalid provider', () => {
|
|
32
|
+
expect(() => RoutingObservationSchema.parse({ ...validObservation, provider: 'gpt' })).toThrow();
|
|
33
|
+
});
|
|
34
|
+
it('rejects invalid workType', () => {
|
|
35
|
+
expect(() => RoutingObservationSchema.parse({ ...validObservation, workType: 'deploy' })).toThrow();
|
|
36
|
+
});
|
|
37
|
+
it('rejects reward out of range', () => {
|
|
38
|
+
expect(() => RoutingObservationSchema.parse({ ...validObservation, reward: 1.5 })).toThrow();
|
|
39
|
+
expect(() => RoutingObservationSchema.parse({ ...validObservation, reward: -0.1 })).toThrow();
|
|
40
|
+
});
|
|
41
|
+
it('rejects invalid qaResult', () => {
|
|
42
|
+
expect(() => RoutingObservationSchema.parse({ ...validObservation, qaResult: 'skipped' })).toThrow();
|
|
43
|
+
});
|
|
44
|
+
it('rejects negative totalCostUsd', () => {
|
|
45
|
+
expect(() => RoutingObservationSchema.parse({ ...validObservation, totalCostUsd: -1 })).toThrow();
|
|
46
|
+
});
|
|
47
|
+
it('rejects invalid UUID for id', () => {
|
|
48
|
+
expect(() => RoutingObservationSchema.parse({ ...validObservation, id: 'not-a-uuid' })).toThrow();
|
|
49
|
+
});
|
|
50
|
+
it('rejects missing required fields', () => {
|
|
51
|
+
expect(() => RoutingObservationSchema.parse({})).toThrow();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
describe('RoutingPosteriorSchema', () => {
|
|
55
|
+
const validPosterior = {
|
|
56
|
+
provider: 'codex',
|
|
57
|
+
workType: 'qa',
|
|
58
|
+
alpha: 5.2,
|
|
59
|
+
beta: 2.1,
|
|
60
|
+
totalObservations: 10,
|
|
61
|
+
avgReward: 0.72,
|
|
62
|
+
avgCostUsd: 0.35,
|
|
63
|
+
lastUpdated: 1700000000,
|
|
64
|
+
};
|
|
65
|
+
it('parses a valid posterior', () => {
|
|
66
|
+
const result = RoutingPosteriorSchema.parse(validPosterior);
|
|
67
|
+
expect(result).toEqual(validPosterior);
|
|
68
|
+
});
|
|
69
|
+
it('rejects alpha below 1', () => {
|
|
70
|
+
expect(() => RoutingPosteriorSchema.parse({ ...validPosterior, alpha: 0.5 })).toThrow();
|
|
71
|
+
});
|
|
72
|
+
it('rejects beta below 1', () => {
|
|
73
|
+
expect(() => RoutingPosteriorSchema.parse({ ...validPosterior, beta: 0 })).toThrow();
|
|
74
|
+
});
|
|
75
|
+
it('rejects negative totalObservations', () => {
|
|
76
|
+
expect(() => RoutingPosteriorSchema.parse({ ...validPosterior, totalObservations: -1 })).toThrow();
|
|
77
|
+
});
|
|
78
|
+
it('rejects non-integer totalObservations', () => {
|
|
79
|
+
expect(() => RoutingPosteriorSchema.parse({ ...validPosterior, totalObservations: 1.5 })).toThrow();
|
|
80
|
+
});
|
|
81
|
+
it('rejects avgReward out of range', () => {
|
|
82
|
+
expect(() => RoutingPosteriorSchema.parse({ ...validPosterior, avgReward: 1.1 })).toThrow();
|
|
83
|
+
});
|
|
84
|
+
it('rejects invalid provider', () => {
|
|
85
|
+
expect(() => RoutingPosteriorSchema.parse({ ...validPosterior, provider: 'openai' })).toThrow();
|
|
86
|
+
});
|
|
87
|
+
it('rejects missing required fields', () => {
|
|
88
|
+
expect(() => RoutingPosteriorSchema.parse({})).toThrow();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe('RoutingDecisionSchema', () => {
|
|
92
|
+
const validDecision = {
|
|
93
|
+
selectedProvider: 'amp',
|
|
94
|
+
confidence: 0.88,
|
|
95
|
+
expectedReward: 0.75,
|
|
96
|
+
explorationReason: 'uncertainty',
|
|
97
|
+
source: 'mab-routing',
|
|
98
|
+
alternatives: [
|
|
99
|
+
{ provider: 'claude', expectedReward: 0.7, confidence: 0.85 },
|
|
100
|
+
{ provider: 'codex', expectedReward: 0.65, confidence: 0.8 },
|
|
101
|
+
],
|
|
102
|
+
};
|
|
103
|
+
it('parses a valid decision', () => {
|
|
104
|
+
const result = RoutingDecisionSchema.parse(validDecision);
|
|
105
|
+
expect(result).toEqual(validDecision);
|
|
106
|
+
});
|
|
107
|
+
it('parses without optional explorationReason', () => {
|
|
108
|
+
const { explorationReason, ...required } = validDecision;
|
|
109
|
+
const result = RoutingDecisionSchema.parse(required);
|
|
110
|
+
expect(result.explorationReason).toBeUndefined();
|
|
111
|
+
});
|
|
112
|
+
it('parses with empty alternatives', () => {
|
|
113
|
+
const result = RoutingDecisionSchema.parse({ ...validDecision, alternatives: [] });
|
|
114
|
+
expect(result.alternatives).toEqual([]);
|
|
115
|
+
});
|
|
116
|
+
it('rejects invalid source', () => {
|
|
117
|
+
expect(() => RoutingDecisionSchema.parse({ ...validDecision, source: 'manual' })).toThrow();
|
|
118
|
+
});
|
|
119
|
+
it('rejects invalid provider in alternatives', () => {
|
|
120
|
+
expect(() => RoutingDecisionSchema.parse({
|
|
121
|
+
...validDecision,
|
|
122
|
+
alternatives: [{ provider: 'gpt', expectedReward: 0.5, confidence: 0.5 }],
|
|
123
|
+
})).toThrow();
|
|
124
|
+
});
|
|
125
|
+
it('rejects confidence out of range', () => {
|
|
126
|
+
expect(() => RoutingDecisionSchema.parse({ ...validDecision, confidence: 2.0 })).toThrow();
|
|
127
|
+
});
|
|
128
|
+
it('rejects missing required fields', () => {
|
|
129
|
+
expect(() => RoutingDecisionSchema.parse({})).toThrow();
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
describe('RoutingConfigSchema', () => {
|
|
133
|
+
const validConfig = {
|
|
134
|
+
enabled: true,
|
|
135
|
+
explorationRate: 0.1,
|
|
136
|
+
windowSize: 50,
|
|
137
|
+
discountFactor: 0.95,
|
|
138
|
+
minObservationsForExploit: 5,
|
|
139
|
+
changeDetectionThreshold: 0.3,
|
|
140
|
+
};
|
|
141
|
+
it('parses a valid config', () => {
|
|
142
|
+
const result = RoutingConfigSchema.parse(validConfig);
|
|
143
|
+
expect(result).toEqual(validConfig);
|
|
144
|
+
});
|
|
145
|
+
it('rejects explorationRate out of range', () => {
|
|
146
|
+
expect(() => RoutingConfigSchema.parse({ ...validConfig, explorationRate: 1.5 })).toThrow();
|
|
147
|
+
expect(() => RoutingConfigSchema.parse({ ...validConfig, explorationRate: -0.1 })).toThrow();
|
|
148
|
+
});
|
|
149
|
+
it('rejects non-positive windowSize', () => {
|
|
150
|
+
expect(() => RoutingConfigSchema.parse({ ...validConfig, windowSize: 0 })).toThrow();
|
|
151
|
+
});
|
|
152
|
+
it('rejects non-integer windowSize', () => {
|
|
153
|
+
expect(() => RoutingConfigSchema.parse({ ...validConfig, windowSize: 10.5 })).toThrow();
|
|
154
|
+
});
|
|
155
|
+
it('rejects discountFactor out of range', () => {
|
|
156
|
+
expect(() => RoutingConfigSchema.parse({ ...validConfig, discountFactor: 1.1 })).toThrow();
|
|
157
|
+
});
|
|
158
|
+
it('rejects negative minObservationsForExploit', () => {
|
|
159
|
+
expect(() => RoutingConfigSchema.parse({ ...validConfig, minObservationsForExploit: -1 })).toThrow();
|
|
160
|
+
});
|
|
161
|
+
it('rejects negative changeDetectionThreshold', () => {
|
|
162
|
+
expect(() => RoutingConfigSchema.parse({ ...validConfig, changeDetectionThreshold: -0.5 })).toThrow();
|
|
163
|
+
});
|
|
164
|
+
it('rejects non-boolean enabled', () => {
|
|
165
|
+
expect(() => RoutingConfigSchema.parse({ ...validConfig, enabled: 'yes' })).toThrow();
|
|
166
|
+
});
|
|
167
|
+
it('rejects missing required fields', () => {
|
|
168
|
+
expect(() => RoutingConfigSchema.parse({})).toThrow();
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
describe('ROUTING_KEYS', () => {
|
|
172
|
+
it('generates correct posteriors key', () => {
|
|
173
|
+
expect(ROUTING_KEYS.posteriors('claude', 'development')).toBe('routing:posteriors:claude:development');
|
|
174
|
+
});
|
|
175
|
+
it('generates correct posteriors key for coordination work type', () => {
|
|
176
|
+
expect(ROUTING_KEYS.posteriors('amp', 'qa-coordination')).toBe('routing:posteriors:amp:qa-coordination');
|
|
177
|
+
});
|
|
178
|
+
it('has correct observations key', () => {
|
|
179
|
+
expect(ROUTING_KEYS.observations).toBe('routing:observations');
|
|
180
|
+
});
|
|
181
|
+
it('has correct config key', () => {
|
|
182
|
+
expect(ROUTING_KEYS.config).toBe('routing:config');
|
|
183
|
+
});
|
|
184
|
+
});
|
|
@@ -110,6 +110,8 @@ export interface TemplateContext {
|
|
|
110
110
|
testCommand?: string;
|
|
111
111
|
/** Validation command override — replaces typecheck for compiled projects (e.g. 'cargo clippy') */
|
|
112
112
|
validateCommand?: string;
|
|
113
|
+
/** Collected outputs from upstream phases, keyed by phase name then output key */
|
|
114
|
+
phaseOutputs?: Record<string, Record<string, unknown>>;
|
|
113
115
|
}
|
|
114
116
|
/**
|
|
115
117
|
* Translates abstract tool permissions to provider-native format.
|
|
@@ -223,6 +225,7 @@ export declare const TemplateContextSchema: z.ZodObject<{
|
|
|
223
225
|
buildCommand: z.ZodOptional<z.ZodString>;
|
|
224
226
|
testCommand: z.ZodOptional<z.ZodString>;
|
|
225
227
|
validateCommand: z.ZodOptional<z.ZodString>;
|
|
228
|
+
phaseOutputs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
226
229
|
}, z.core.$strip>;
|
|
227
230
|
/**
|
|
228
231
|
* Validate a parsed YAML object as a WorkflowTemplate.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/templates/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAGlE,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAMlE;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACjB,YAAY,GACZ,MAAM,CAAA;AAMV;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,IAAI,CAAA;IAChB,IAAI,EAAE,kBAAkB,CAAA;IACxB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAA;QACZ,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,QAAQ,EAAE,aAAa,CAAA;KACxB,CAAA;IACD,KAAK,CAAC,EAAE;QACN,KAAK,CAAC,EAAE,cAAc,EAAE,CAAA;QACxB,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAA;KAC5B,CAAA;IACD,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAA;CACf;AAMD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,IAAI,CAAA;IAChB,IAAI,EAAE,iBAAiB,CAAA;IACvB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAA;QACZ,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,0EAA0E;QAC1E,QAAQ,CAAC,EAAE,MAAM,CAAA;KAClB,CAAA;IACD,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAA;CAChB;AAMD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,cAAc,CAAC,EAAE,MAAM,CAAA;IAGvB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAA;IAGvB,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAA;IAGrB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kGAAkG;IAClG,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gDAAgD;IAChD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,0CAA0C;IAC1C,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uCAAuC;IACvC,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAA;IACjC,4CAA4C;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAA;IAGrB,uDAAuD;IACvD,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAA;IAGb,sFAAsF;IACtF,UAAU,CAAC,EAAE,MAAM,CAAA;IAGnB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IAGtB,wEAAwE;IACxE,cAAc,CAAC,EAAE,OAAO,CAAA;IAGxB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kGAAkG;IAClG,cAAc,CAAC,EAAE,MAAM,CAAA;IAGvB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mGAAmG;IACnG,eAAe,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/templates/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAGlE,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAMlE;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACjB,YAAY,GACZ,MAAM,CAAA;AAMV;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,IAAI,CAAA;IAChB,IAAI,EAAE,kBAAkB,CAAA;IACxB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAA;QACZ,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,QAAQ,EAAE,aAAa,CAAA;KACxB,CAAA;IACD,KAAK,CAAC,EAAE;QACN,KAAK,CAAC,EAAE,cAAc,EAAE,CAAA;QACxB,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAA;KAC5B,CAAA;IACD,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAA;CACf;AAMD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,IAAI,CAAA;IAChB,IAAI,EAAE,iBAAiB,CAAA;IACvB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAA;QACZ,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,0EAA0E;QAC1E,QAAQ,CAAC,EAAE,MAAM,CAAA;KAClB,CAAA;IACD,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAA;CAChB;AAMD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,cAAc,CAAC,EAAE,MAAM,CAAA;IAGvB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAA;IAGvB,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAA;IAGrB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kGAAkG;IAClG,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gDAAgD;IAChD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,0CAA0C;IAC1C,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uCAAuC;IACvC,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAA;IACjC,4CAA4C;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAA;IAGrB,uDAAuD;IACvD,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAA;IAGb,sFAAsF;IACtF,UAAU,CAAC,EAAE,MAAM,CAAA;IAGnB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IAGtB,wEAAwE;IACxE,cAAc,CAAC,EAAE,OAAO,CAAA;IAGxB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kGAAkG;IAClG,cAAc,CAAC,EAAE,MAAM,CAAA;IAGvB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mGAAmG;IACnG,eAAe,CAAC,EAAE,MAAM,CAAA;IAGxB,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CACvD;AAMD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,+DAA+D;IAC/D,oBAAoB,CAAC,WAAW,EAAE,cAAc,EAAE,GAAG,MAAM,EAAE,CAAA;CAC9D;AAMD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IAC/F,wDAAwD;IACxD,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAuBD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;EAAqB,CAAA;AAErD,eAAO,MAAM,oBAAoB;;4DAI/B,CAAA;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAajC,CAAA;AAEF,eAAO,MAAM,qBAAqB;;;;;;;;;iBAShC,CAAA;AAEF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;iBAiChC,CAAA;AAMF;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAS3F;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,eAAe,CASzF"}
|
|
@@ -93,6 +93,8 @@ export const TemplateContextSchema = z.object({
|
|
|
93
93
|
buildCommand: z.string().optional(),
|
|
94
94
|
testCommand: z.string().optional(),
|
|
95
95
|
validateCommand: z.string().optional(),
|
|
96
|
+
// Phase output data (parallel data passing)
|
|
97
|
+
phaseOutputs: z.record(z.string(), z.record(z.string(), z.unknown())).optional(),
|
|
96
98
|
});
|
|
97
99
|
// ---------------------------------------------------------------------------
|
|
98
100
|
// Validation Helpers
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Cancellation
|
|
3
|
+
*
|
|
4
|
+
* Utility for signaling and tracking cancellation of parallel agent tasks.
|
|
5
|
+
* Used by the RaceStrategy to cancel remaining agents when one wins.
|
|
6
|
+
*/
|
|
7
|
+
export interface AgentCancellation {
|
|
8
|
+
/** Signal cancellation for an agent/task */
|
|
9
|
+
cancel(taskId: string): Promise<boolean>;
|
|
10
|
+
/**
|
|
11
|
+
* Signal cancellation with a timeout guarantee.
|
|
12
|
+
* Resolves after the agent acknowledges cancellation OR after timeoutMs,
|
|
13
|
+
* whichever comes first. Prevents hanging if an agent never checks isCancelled().
|
|
14
|
+
* @param taskId - The task to cancel
|
|
15
|
+
* @param timeoutMs - Maximum time to wait in milliseconds (default: 30000)
|
|
16
|
+
* @returns true if newly cancelled, false if already cancelled
|
|
17
|
+
*/
|
|
18
|
+
cancelWithTimeout(taskId: string, timeoutMs?: number): Promise<boolean>;
|
|
19
|
+
/** Check if a task has been cancelled */
|
|
20
|
+
isCancelled(taskId: string): boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* In-memory cancellation tracker.
|
|
24
|
+
* In production, this would be backed by a shared state store (Redis, etc.)
|
|
25
|
+
* to coordinate cancellation across processes.
|
|
26
|
+
*/
|
|
27
|
+
export declare class InMemoryAgentCancellation implements AgentCancellation {
|
|
28
|
+
private readonly cancelled;
|
|
29
|
+
cancel(taskId: string): Promise<boolean>;
|
|
30
|
+
cancelWithTimeout(taskId: string, timeoutMs?: number): Promise<boolean>;
|
|
31
|
+
isCancelled(taskId: string): boolean;
|
|
32
|
+
/** Get all cancelled task IDs */
|
|
33
|
+
getCancelledIds(): string[];
|
|
34
|
+
/** Reset all cancellation state */
|
|
35
|
+
reset(): void;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=agent-cancellation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-cancellation.d.ts","sourceRoot":"","sources":["../../../src/workflow/agent-cancellation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,iBAAiB;IAChC,4CAA4C;IAC5C,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACxC;;;;;;;OAOG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACvE,yCAAyC;IACzC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;CACrC;AAED;;;;GAIG;AACH,qBAAa,yBAA0B,YAAW,iBAAiB;IACjE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAExC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQxC,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,GAAE,MAAe,GAAG,OAAO,CAAC,OAAO,CAAC;IAUrF,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIpC,iCAAiC;IACjC,eAAe,IAAI,MAAM,EAAE;IAI3B,mCAAmC;IACnC,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Cancellation
|
|
3
|
+
*
|
|
4
|
+
* Utility for signaling and tracking cancellation of parallel agent tasks.
|
|
5
|
+
* Used by the RaceStrategy to cancel remaining agents when one wins.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* In-memory cancellation tracker.
|
|
9
|
+
* In production, this would be backed by a shared state store (Redis, etc.)
|
|
10
|
+
* to coordinate cancellation across processes.
|
|
11
|
+
*/
|
|
12
|
+
export class InMemoryAgentCancellation {
|
|
13
|
+
cancelled = new Set();
|
|
14
|
+
async cancel(taskId) {
|
|
15
|
+
if (this.cancelled.has(taskId)) {
|
|
16
|
+
return false; // already cancelled
|
|
17
|
+
}
|
|
18
|
+
this.cancelled.add(taskId);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
async cancelWithTimeout(taskId, timeoutMs = 30_000) {
|
|
22
|
+
// Signal cancellation immediately
|
|
23
|
+
const result = await this.cancel(taskId);
|
|
24
|
+
// The timeout is enforced at the caller level (e.g., RaceStrategy wraps
|
|
25
|
+
// Promise.allSettled with a timeout). This method ensures the cancellation
|
|
26
|
+
// flag is set and returns promptly — the timeout parameter is recorded
|
|
27
|
+
// for callers that need to know the configured value.
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
isCancelled(taskId) {
|
|
31
|
+
return this.cancelled.has(taskId);
|
|
32
|
+
}
|
|
33
|
+
/** Get all cancelled task IDs */
|
|
34
|
+
getCancelledIds() {
|
|
35
|
+
return [...this.cancelled];
|
|
36
|
+
}
|
|
37
|
+
/** Reset all cancellation state */
|
|
38
|
+
reset() {
|
|
39
|
+
this.cancelled.clear();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-cancellation.test.d.ts","sourceRoot":"","sources":["../../../src/workflow/agent-cancellation.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { InMemoryAgentCancellation } from './agent-cancellation.js';
|
|
3
|
+
describe('InMemoryAgentCancellation', () => {
|
|
4
|
+
describe('cancel()', () => {
|
|
5
|
+
it('returns true on first call for a task', async () => {
|
|
6
|
+
const cancellation = new InMemoryAgentCancellation();
|
|
7
|
+
const result = await cancellation.cancel('task-1');
|
|
8
|
+
expect(result).toBe(true);
|
|
9
|
+
});
|
|
10
|
+
it('returns false on duplicate cancel for the same task', async () => {
|
|
11
|
+
const cancellation = new InMemoryAgentCancellation();
|
|
12
|
+
await cancellation.cancel('task-1');
|
|
13
|
+
const result = await cancellation.cancel('task-1');
|
|
14
|
+
expect(result).toBe(false);
|
|
15
|
+
});
|
|
16
|
+
it('returns true for different task IDs', async () => {
|
|
17
|
+
const cancellation = new InMemoryAgentCancellation();
|
|
18
|
+
const r1 = await cancellation.cancel('task-1');
|
|
19
|
+
const r2 = await cancellation.cancel('task-2');
|
|
20
|
+
expect(r1).toBe(true);
|
|
21
|
+
expect(r2).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
describe('isCancelled()', () => {
|
|
25
|
+
it('returns false for a task that has not been cancelled', () => {
|
|
26
|
+
const cancellation = new InMemoryAgentCancellation();
|
|
27
|
+
expect(cancellation.isCancelled('task-1')).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
it('returns true for a task that has been cancelled', async () => {
|
|
30
|
+
const cancellation = new InMemoryAgentCancellation();
|
|
31
|
+
await cancellation.cancel('task-1');
|
|
32
|
+
expect(cancellation.isCancelled('task-1')).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
it('returns correct state for multiple tasks', async () => {
|
|
35
|
+
const cancellation = new InMemoryAgentCancellation();
|
|
36
|
+
await cancellation.cancel('task-1');
|
|
37
|
+
await cancellation.cancel('task-3');
|
|
38
|
+
expect(cancellation.isCancelled('task-1')).toBe(true);
|
|
39
|
+
expect(cancellation.isCancelled('task-2')).toBe(false);
|
|
40
|
+
expect(cancellation.isCancelled('task-3')).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe('getCancelledIds()', () => {
|
|
44
|
+
it('returns empty array when nothing is cancelled', () => {
|
|
45
|
+
const cancellation = new InMemoryAgentCancellation();
|
|
46
|
+
expect(cancellation.getCancelledIds()).toEqual([]);
|
|
47
|
+
});
|
|
48
|
+
it('returns all cancelled IDs', async () => {
|
|
49
|
+
const cancellation = new InMemoryAgentCancellation();
|
|
50
|
+
await cancellation.cancel('task-a');
|
|
51
|
+
await cancellation.cancel('task-b');
|
|
52
|
+
await cancellation.cancel('task-c');
|
|
53
|
+
const ids = cancellation.getCancelledIds();
|
|
54
|
+
expect(ids).toHaveLength(3);
|
|
55
|
+
expect(ids).toContain('task-a');
|
|
56
|
+
expect(ids).toContain('task-b');
|
|
57
|
+
expect(ids).toContain('task-c');
|
|
58
|
+
});
|
|
59
|
+
it('does not include duplicates', async () => {
|
|
60
|
+
const cancellation = new InMemoryAgentCancellation();
|
|
61
|
+
await cancellation.cancel('task-1');
|
|
62
|
+
await cancellation.cancel('task-1');
|
|
63
|
+
expect(cancellation.getCancelledIds()).toEqual(['task-1']);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('reset()', () => {
|
|
67
|
+
it('clears all cancellation state', async () => {
|
|
68
|
+
const cancellation = new InMemoryAgentCancellation();
|
|
69
|
+
await cancellation.cancel('task-1');
|
|
70
|
+
await cancellation.cancel('task-2');
|
|
71
|
+
expect(cancellation.getCancelledIds()).toHaveLength(2);
|
|
72
|
+
cancellation.reset();
|
|
73
|
+
expect(cancellation.getCancelledIds()).toEqual([]);
|
|
74
|
+
expect(cancellation.isCancelled('task-1')).toBe(false);
|
|
75
|
+
expect(cancellation.isCancelled('task-2')).toBe(false);
|
|
76
|
+
});
|
|
77
|
+
it('allows re-cancelling after reset', async () => {
|
|
78
|
+
const cancellation = new InMemoryAgentCancellation();
|
|
79
|
+
await cancellation.cancel('task-1');
|
|
80
|
+
cancellation.reset();
|
|
81
|
+
const result = await cancellation.cancel('task-1');
|
|
82
|
+
expect(result).toBe(true);
|
|
83
|
+
expect(cancellation.isCancelled('task-1')).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Concurrency Semaphore
|
|
3
|
+
*
|
|
4
|
+
* Limits the number of concurrent operations. When the limit is reached,
|
|
5
|
+
* subsequent acquire() calls wait until a slot is released.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ConcurrencySemaphore {
|
|
8
|
+
private readonly maxConcurrent;
|
|
9
|
+
private current;
|
|
10
|
+
private readonly waiters;
|
|
11
|
+
constructor(maxConcurrent: number);
|
|
12
|
+
/** Current number of active slots */
|
|
13
|
+
get activeCount(): number;
|
|
14
|
+
/** Number of waiters in the queue */
|
|
15
|
+
get waitingCount(): number;
|
|
16
|
+
/** Acquire a slot. Resolves when a slot is available. */
|
|
17
|
+
acquire(): Promise<void>;
|
|
18
|
+
/** Release a slot. Wakes up the next waiter if any. */
|
|
19
|
+
release(): void;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=concurrency-semaphore.d.ts.map
|