@yasserkhanorg/e2e-agents 1.8.5 → 1.10.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 +95 -8
- package/dist/adapters/cypress.d.ts +10 -0
- package/dist/adapters/cypress.d.ts.map +1 -0
- package/dist/adapters/cypress.js +86 -0
- package/dist/adapters/framework_adapter.d.ts +41 -0
- package/dist/adapters/framework_adapter.d.ts.map +1 -0
- package/dist/adapters/framework_adapter.js +152 -0
- package/dist/adapters/playwright.d.ts +10 -0
- package/dist/adapters/playwright.d.ts.map +1 -0
- package/dist/adapters/playwright.js +86 -0
- package/dist/adapters/pytest.d.ts +10 -0
- package/dist/adapters/pytest.d.ts.map +1 -0
- package/dist/adapters/pytest.js +96 -0
- package/dist/adapters/supertest.d.ts +12 -0
- package/dist/adapters/supertest.d.ts.map +1 -0
- package/dist/adapters/supertest.js +85 -0
- package/dist/agent/config.d.ts +1 -1
- package/dist/agent/config.d.ts.map +1 -1
- package/dist/agent/git.d.ts +1 -0
- package/dist/agent/git.d.ts.map +1 -1
- package/dist/agent/git.js +3 -0
- package/dist/agentic/fix_loop.d.ts.map +1 -1
- package/dist/agentic/fix_loop.js +5 -4
- package/dist/agentic/runner.d.ts +2 -0
- package/dist/agentic/runner.d.ts.map +1 -1
- package/dist/agentic/runner.js +15 -12
- package/dist/agents/cross-impact.d.ts.map +1 -1
- package/dist/agents/cross-impact.js +6 -1
- package/dist/agents/executor.d.ts.map +1 -1
- package/dist/agents/executor.js +6 -1
- package/dist/agents/strategist.d.ts.map +1 -1
- package/dist/agents/strategist.js +6 -1
- package/dist/agents/test-designer.d.ts.map +1 -1
- package/dist/agents/test-designer.js +6 -1
- package/dist/anthropic_provider.d.ts.map +1 -1
- package/dist/anthropic_provider.js +1 -0
- package/dist/base_provider.d.ts +56 -0
- package/dist/base_provider.d.ts.map +1 -1
- package/dist/base_provider.js +123 -1
- package/dist/budget_ledger.d.ts +28 -0
- package/dist/budget_ledger.d.ts.map +1 -0
- package/dist/budget_ledger.js +62 -0
- package/dist/cache/cached_provider.d.ts +45 -0
- package/dist/cache/cached_provider.d.ts.map +1 -0
- package/dist/cache/cached_provider.js +88 -0
- package/dist/cache/response_cache.d.ts +79 -0
- package/dist/cache/response_cache.d.ts.map +1 -0
- package/dist/cache/response_cache.js +177 -0
- package/dist/cli/commands/bootstrap.d.ts +3 -0
- package/dist/cli/commands/bootstrap.d.ts.map +1 -0
- package/dist/cli/commands/bootstrap.js +109 -0
- package/dist/cli/commands/cost_report.d.ts +3 -0
- package/dist/cli/commands/cost_report.d.ts.map +1 -0
- package/dist/cli/commands/cost_report.js +115 -0
- package/dist/cli/commands/crew.d.ts.map +1 -1
- package/dist/cli/commands/crew.js +118 -1
- package/dist/cli/commands/gate.d.ts +3 -0
- package/dist/cli/commands/gate.d.ts.map +1 -0
- package/dist/cli/commands/gate.js +86 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +7 -62
- package/dist/cli/commands/train.d.ts.map +1 -1
- package/dist/cli/commands/train.js +16 -21
- package/dist/cli/defaults.d.ts +35 -0
- package/dist/cli/defaults.d.ts.map +1 -0
- package/dist/cli/defaults.js +125 -0
- package/dist/cli/errors.d.ts +27 -0
- package/dist/cli/errors.d.ts.map +1 -0
- package/dist/cli/errors.js +57 -0
- package/dist/cli/parse_args.d.ts.map +1 -1
- package/dist/cli/parse_args.js +24 -2
- package/dist/cli/types.d.ts +7 -1
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli.js +47 -2
- package/dist/crew/context.d.ts +15 -0
- package/dist/crew/context.d.ts.map +1 -1
- package/dist/crew/orchestrator.d.ts +14 -0
- package/dist/crew/orchestrator.d.ts.map +1 -1
- package/dist/crew/orchestrator.js +162 -4
- package/dist/crew/protocol.d.ts +13 -0
- package/dist/crew/protocol.d.ts.map +1 -1
- package/dist/crew/provider.d.ts +15 -1
- package/dist/crew/provider.d.ts.map +1 -1
- package/dist/crew/provider.js +24 -4
- package/dist/custom_provider.d.ts.map +1 -1
- package/dist/custom_provider.js +1 -0
- package/dist/engine/diff_loader.d.ts.map +1 -1
- package/dist/engine/diff_loader.js +3 -14
- package/dist/engine/impact_engine.d.ts.map +1 -1
- package/dist/engine/impact_engine.js +9 -23
- package/dist/esm/adapters/cypress.js +49 -0
- package/dist/esm/adapters/framework_adapter.js +114 -0
- package/dist/esm/adapters/playwright.js +49 -0
- package/dist/esm/adapters/pytest.js +59 -0
- package/dist/esm/adapters/supertest.js +48 -0
- package/dist/esm/agent/git.js +3 -1
- package/dist/esm/agentic/fix_loop.js +5 -4
- package/dist/esm/agentic/runner.js +15 -12
- package/dist/esm/agents/cross-impact.js +6 -1
- package/dist/esm/agents/executor.js +6 -1
- package/dist/esm/agents/strategist.js +6 -1
- package/dist/esm/agents/test-designer.js +6 -1
- package/dist/esm/anthropic_provider.js +1 -0
- package/dist/esm/base_provider.js +121 -0
- package/dist/esm/budget_ledger.js +58 -0
- package/dist/esm/cache/cached_provider.js +82 -0
- package/dist/esm/cache/response_cache.js +140 -0
- package/dist/esm/cli/commands/bootstrap.js +106 -0
- package/dist/esm/cli/commands/cost_report.js +112 -0
- package/dist/esm/cli/commands/crew.js +118 -1
- package/dist/esm/cli/commands/gate.js +83 -0
- package/dist/esm/cli/commands/init.js +3 -58
- package/dist/esm/cli/commands/train.js +16 -21
- package/dist/esm/cli/defaults.js +118 -0
- package/dist/esm/cli/errors.js +52 -0
- package/dist/esm/cli/parse_args.js +24 -2
- package/dist/esm/cli.js +47 -2
- package/dist/esm/crew/orchestrator.js +162 -4
- package/dist/esm/crew/provider.js +24 -4
- package/dist/esm/custom_provider.js +1 -0
- package/dist/esm/engine/diff_loader.js +1 -12
- package/dist/esm/engine/impact_engine.js +9 -23
- package/dist/esm/index.js +21 -0
- package/dist/esm/knowledge/api_surface.js +265 -34
- package/dist/esm/knowledge/cluster_utils.js +60 -0
- package/dist/esm/knowledge/failure_history.js +121 -0
- package/dist/esm/knowledge/kg_bridge.js +381 -0
- package/dist/esm/knowledge/kg_types.js +3 -0
- package/dist/esm/knowledge/route_families.js +119 -0
- package/dist/esm/mcp-server.js +2 -4
- package/dist/esm/metrics/prometheus.js +149 -0
- package/dist/esm/model_router.js +59 -0
- package/dist/esm/ollama_provider.js +1 -0
- package/dist/esm/openai_provider.js +1 -0
- package/dist/esm/pipeline/orchestrator.js +6 -12
- package/dist/esm/pipeline/stage0_preprocess.js +12 -19
- package/dist/esm/pipeline/stage1_impact.js +19 -3
- package/dist/esm/pipeline/stage2_coverage.js +29 -7
- package/dist/esm/pipeline/stage3_generation.js +21 -1
- package/dist/esm/progress.js +112 -0
- package/dist/esm/prompts/coverage.js +17 -24
- package/dist/esm/prompts/cross-impact.js +3 -21
- package/dist/esm/prompts/generation.js +201 -45
- package/dist/esm/prompts/generation_profile.js +147 -0
- package/dist/esm/prompts/heal.js +33 -15
- package/dist/esm/prompts/impact.js +3 -22
- package/dist/esm/prompts/json_extract.js +36 -0
- package/dist/esm/prompts/strategist.js +2 -20
- package/dist/esm/prompts/test-designer.js +6 -21
- package/dist/esm/provider_factory.js +6 -4
- package/dist/esm/reporters/junit.js +86 -0
- package/dist/esm/reporters/reporter.js +3 -0
- package/dist/esm/reporters/sarif.js +131 -0
- package/dist/esm/resilience/circuit_breaker.js +78 -0
- package/dist/esm/resilience/retry.js +56 -0
- package/dist/esm/sanitize.js +66 -0
- package/dist/esm/training/kg_scanner.js +115 -0
- package/dist/esm/training/scanner.js +27 -34
- package/dist/esm/validation/guardrails.js +5 -0
- package/dist/esm/version.js +33 -0
- package/dist/index.d.ts +21 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +45 -1
- package/dist/knowledge/api_surface.d.ts +12 -0
- package/dist/knowledge/api_surface.d.ts.map +1 -1
- package/dist/knowledge/api_surface.js +268 -34
- package/dist/knowledge/cluster_utils.d.ts +28 -0
- package/dist/knowledge/cluster_utils.d.ts.map +1 -0
- package/dist/knowledge/cluster_utils.js +67 -0
- package/dist/knowledge/failure_history.d.ts +39 -0
- package/dist/knowledge/failure_history.d.ts.map +1 -0
- package/dist/knowledge/failure_history.js +128 -0
- package/dist/knowledge/kg_bridge.d.ts +31 -0
- package/dist/knowledge/kg_bridge.d.ts.map +1 -0
- package/dist/knowledge/kg_bridge.js +388 -0
- package/dist/knowledge/kg_types.d.ts +75 -0
- package/dist/knowledge/kg_types.d.ts.map +1 -0
- package/dist/knowledge/kg_types.js +4 -0
- package/dist/knowledge/route_families.d.ts +29 -0
- package/dist/knowledge/route_families.d.ts.map +1 -1
- package/dist/knowledge/route_families.js +122 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +2 -4
- package/dist/metrics/prometheus.d.ts +37 -0
- package/dist/metrics/prometheus.d.ts.map +1 -0
- package/dist/metrics/prometheus.js +153 -0
- package/dist/model_router.d.ts +28 -0
- package/dist/model_router.d.ts.map +1 -0
- package/dist/model_router.js +63 -0
- package/dist/ollama_provider.d.ts.map +1 -1
- package/dist/ollama_provider.js +1 -0
- package/dist/openai_provider.d.ts.map +1 -1
- package/dist/openai_provider.js +1 -0
- package/dist/pipeline/orchestrator.d.ts +2 -0
- package/dist/pipeline/orchestrator.d.ts.map +1 -1
- package/dist/pipeline/orchestrator.js +6 -12
- package/dist/pipeline/stage0_preprocess.d.ts.map +1 -1
- package/dist/pipeline/stage0_preprocess.js +11 -18
- package/dist/pipeline/stage1_impact.d.ts +1 -1
- package/dist/pipeline/stage1_impact.d.ts.map +1 -1
- package/dist/pipeline/stage1_impact.js +18 -2
- package/dist/pipeline/stage2_coverage.d.ts +2 -0
- package/dist/pipeline/stage2_coverage.d.ts.map +1 -1
- package/dist/pipeline/stage2_coverage.js +29 -7
- package/dist/pipeline/stage3_generation.d.ts +2 -0
- package/dist/pipeline/stage3_generation.d.ts.map +1 -1
- package/dist/pipeline/stage3_generation.js +21 -1
- package/dist/pipeline/stage4_heal.d.ts +2 -0
- package/dist/pipeline/stage4_heal.d.ts.map +1 -1
- package/dist/progress.d.ts +22 -0
- package/dist/progress.d.ts.map +1 -0
- package/dist/progress.js +116 -0
- package/dist/prompts/coverage.d.ts +2 -0
- package/dist/prompts/coverage.d.ts.map +1 -1
- package/dist/prompts/coverage.js +17 -24
- package/dist/prompts/cross-impact.d.ts +1 -0
- package/dist/prompts/cross-impact.d.ts.map +1 -1
- package/dist/prompts/cross-impact.js +3 -21
- package/dist/prompts/generation.d.ts +4 -2
- package/dist/prompts/generation.d.ts.map +1 -1
- package/dist/prompts/generation.js +201 -45
- package/dist/prompts/generation_profile.d.ts +29 -0
- package/dist/prompts/generation_profile.d.ts.map +1 -0
- package/dist/prompts/generation_profile.js +151 -0
- package/dist/prompts/heal.d.ts +3 -1
- package/dist/prompts/heal.d.ts.map +1 -1
- package/dist/prompts/heal.js +33 -15
- package/dist/prompts/impact.d.ts +1 -0
- package/dist/prompts/impact.d.ts.map +1 -1
- package/dist/prompts/impact.js +3 -22
- package/dist/prompts/json_extract.d.ts +14 -0
- package/dist/prompts/json_extract.d.ts.map +1 -0
- package/dist/prompts/json_extract.js +39 -0
- package/dist/prompts/strategist.d.ts.map +1 -1
- package/dist/prompts/strategist.js +2 -20
- package/dist/prompts/test-designer.d.ts +2 -0
- package/dist/prompts/test-designer.d.ts.map +1 -1
- package/dist/prompts/test-designer.js +6 -21
- package/dist/provider_factory.d.ts.map +1 -1
- package/dist/provider_factory.js +6 -4
- package/dist/reporters/junit.d.ts +6 -0
- package/dist/reporters/junit.d.ts.map +1 -0
- package/dist/reporters/junit.js +89 -0
- package/dist/reporters/reporter.d.ts +42 -0
- package/dist/reporters/reporter.d.ts.map +1 -0
- package/dist/reporters/reporter.js +4 -0
- package/dist/reporters/sarif.d.ts +7 -0
- package/dist/reporters/sarif.d.ts.map +1 -0
- package/dist/reporters/sarif.js +134 -0
- package/dist/resilience/circuit_breaker.d.ts +36 -0
- package/dist/resilience/circuit_breaker.d.ts.map +1 -0
- package/dist/resilience/circuit_breaker.js +82 -0
- package/dist/resilience/retry.d.ts +11 -0
- package/dist/resilience/retry.d.ts.map +1 -0
- package/dist/resilience/retry.js +59 -0
- package/dist/sanitize.d.ts +15 -0
- package/dist/sanitize.d.ts.map +1 -0
- package/dist/sanitize.js +71 -0
- package/dist/training/kg_scanner.d.ts +13 -0
- package/dist/training/kg_scanner.d.ts.map +1 -0
- package/dist/training/kg_scanner.js +118 -0
- package/dist/training/scanner.d.ts +7 -2
- package/dist/training/scanner.d.ts.map +1 -1
- package/dist/training/scanner.js +27 -34
- package/dist/validation/guardrails.d.ts +2 -0
- package/dist/validation/guardrails.d.ts.map +1 -1
- package/dist/validation/guardrails.js +5 -0
- package/dist/validation/output_schema.d.ts +3 -0
- package/dist/validation/output_schema.d.ts.map +1 -1
- package/dist/version.d.ts +6 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +36 -0
- package/package.json +7 -2
- package/schemas/route-families.schema.json +31 -1
|
@@ -13,7 +13,10 @@ exports.getCypressSpecDirsForBinding = getCypressSpecDirsForBinding;
|
|
|
13
13
|
exports.getPriorityForBinding = getPriorityForBinding;
|
|
14
14
|
exports.getUserFlowsForBinding = getUserFlowsForBinding;
|
|
15
15
|
exports.getRoutesForBinding = getRoutesForBinding;
|
|
16
|
+
exports.getAssertionPatternsForBinding = getAssertionPatternsForBinding;
|
|
16
17
|
exports.clearManifestCache = clearManifestCache;
|
|
18
|
+
exports.buildHeuristicFamilies = buildHeuristicFamilies;
|
|
19
|
+
exports.serializeManifest = serializeManifest;
|
|
17
20
|
const fs_1 = require("fs");
|
|
18
21
|
const path_1 = require("path");
|
|
19
22
|
const logger_js_1 = require("../logger.js");
|
|
@@ -44,6 +47,17 @@ function matchesGlob(filePath, pattern) {
|
|
|
44
47
|
function matchesAnyPattern(filePath, patterns) {
|
|
45
48
|
return patterns.some((pattern) => matchesGlob(filePath, pattern));
|
|
46
49
|
}
|
|
50
|
+
function validateApiEndpoint(ep) {
|
|
51
|
+
if (!ep || typeof ep !== 'object')
|
|
52
|
+
return null;
|
|
53
|
+
const obj = ep;
|
|
54
|
+
if (typeof obj.method !== 'string' || typeof obj.path !== 'string')
|
|
55
|
+
return null;
|
|
56
|
+
const result = { method: obj.method, path: obj.path };
|
|
57
|
+
if (typeof obj.description === 'string')
|
|
58
|
+
result.description = obj.description;
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
47
61
|
function validateFamily(family) {
|
|
48
62
|
if (!family || typeof family !== 'object') {
|
|
49
63
|
return null;
|
|
@@ -52,6 +66,10 @@ function validateFamily(family) {
|
|
|
52
66
|
if (typeof obj.id !== 'string' || !obj.id.trim()) {
|
|
53
67
|
return null;
|
|
54
68
|
}
|
|
69
|
+
// When testType is 'api', routes may contain API paths like "GET /api/users"
|
|
70
|
+
const testType = (obj.testType === 'ui' || obj.testType === 'api' || obj.testType === 'both')
|
|
71
|
+
? obj.testType
|
|
72
|
+
: undefined;
|
|
55
73
|
if (!Array.isArray(obj.routes) || obj.routes.length === 0) {
|
|
56
74
|
return null;
|
|
57
75
|
}
|
|
@@ -95,8 +113,32 @@ function validateFamily(family) {
|
|
|
95
113
|
.map((f) => validateFeature(f))
|
|
96
114
|
.filter((f) => f !== null);
|
|
97
115
|
}
|
|
116
|
+
if (Array.isArray(obj.apiEndpoints)) {
|
|
117
|
+
const endpoints = obj.apiEndpoints
|
|
118
|
+
.map((ep) => validateApiEndpoint(ep))
|
|
119
|
+
.filter((ep) => ep !== null);
|
|
120
|
+
if (endpoints.length > 0)
|
|
121
|
+
result.apiEndpoints = endpoints;
|
|
122
|
+
}
|
|
123
|
+
if (testType) {
|
|
124
|
+
result.testType = testType;
|
|
125
|
+
}
|
|
126
|
+
if (Array.isArray(obj.assertionPatterns)) {
|
|
127
|
+
result.assertionPatterns = validateAssertionPatterns(obj.assertionPatterns);
|
|
128
|
+
}
|
|
98
129
|
return result;
|
|
99
130
|
}
|
|
131
|
+
const VALID_ASSERTION_TYPES = [
|
|
132
|
+
'state-change', 'cross-user', 'persistence', 'negative',
|
|
133
|
+
'permission', 'data-integrity', 'error-handling',
|
|
134
|
+
];
|
|
135
|
+
function validateAssertionPatterns(patterns) {
|
|
136
|
+
return patterns
|
|
137
|
+
.filter((p) => p != null && typeof p === 'object')
|
|
138
|
+
.filter((p) => typeof p.type === 'string' && typeof p.pattern === 'string')
|
|
139
|
+
.filter((p) => VALID_ASSERTION_TYPES.includes(p.type))
|
|
140
|
+
.map((p) => ({ type: p.type, pattern: p.pattern }));
|
|
141
|
+
}
|
|
100
142
|
function validateFeature(feature) {
|
|
101
143
|
if (!feature || typeof feature !== 'object') {
|
|
102
144
|
return null;
|
|
@@ -130,6 +172,9 @@ function validateFeature(feature) {
|
|
|
130
172
|
if (Array.isArray(obj.userFlows)) {
|
|
131
173
|
result.userFlows = obj.userFlows.filter((v) => typeof v === 'string');
|
|
132
174
|
}
|
|
175
|
+
if (Array.isArray(obj.assertionPatterns)) {
|
|
176
|
+
result.assertionPatterns = validateAssertionPatterns(obj.assertionPatterns);
|
|
177
|
+
}
|
|
133
178
|
return result;
|
|
134
179
|
}
|
|
135
180
|
function loadRouteFamilyManifest(testsRoot, config) {
|
|
@@ -283,6 +328,83 @@ function getRoutesForBinding(manifest, binding) {
|
|
|
283
328
|
}
|
|
284
329
|
return family.routes;
|
|
285
330
|
}
|
|
331
|
+
function getAssertionPatternsForBinding(manifest, binding) {
|
|
332
|
+
const family = getFamilyById(manifest, binding.family);
|
|
333
|
+
if (!family) {
|
|
334
|
+
return [];
|
|
335
|
+
}
|
|
336
|
+
if (binding.feature) {
|
|
337
|
+
const feature = getFeatureById(family, binding.feature);
|
|
338
|
+
if (feature?.assertionPatterns && feature.assertionPatterns.length > 0) {
|
|
339
|
+
return feature.assertionPatterns;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return family.assertionPatterns || [];
|
|
343
|
+
}
|
|
286
344
|
function clearManifestCache() {
|
|
287
345
|
manifestCache.clear();
|
|
288
346
|
}
|
|
347
|
+
/**
|
|
348
|
+
* Build heuristic route families from changed files when no manifest exists.
|
|
349
|
+
* Groups files by their top-level directory to create rough family groupings.
|
|
350
|
+
* Results are lower confidence but allow analysis to proceed without training.
|
|
351
|
+
*/
|
|
352
|
+
function buildHeuristicFamilies(changedFiles, testsRoot) {
|
|
353
|
+
const dirGroups = new Map();
|
|
354
|
+
for (const file of changedFiles) {
|
|
355
|
+
const normalized = file.replace(/\\/g, '/');
|
|
356
|
+
const parts = normalized.split('/');
|
|
357
|
+
// Use the first meaningful directory segment as the family ID
|
|
358
|
+
// Skip common prefixes like 'src/', 'app/', 'lib/'
|
|
359
|
+
const skipDirs = new Set(['src', 'app', 'lib', 'packages', 'components']);
|
|
360
|
+
let familyDir = parts[0] || 'root';
|
|
361
|
+
if (skipDirs.has(familyDir) && parts.length > 1) {
|
|
362
|
+
familyDir = parts[1];
|
|
363
|
+
}
|
|
364
|
+
// Normalize to a clean family name
|
|
365
|
+
familyDir = familyDir.replace(/\.[^.]+$/, ''); // strip file extensions for single files
|
|
366
|
+
if (!dirGroups.has(familyDir)) {
|
|
367
|
+
dirGroups.set(familyDir, []);
|
|
368
|
+
}
|
|
369
|
+
dirGroups.get(familyDir).push(normalized);
|
|
370
|
+
}
|
|
371
|
+
const families = [];
|
|
372
|
+
for (const [dir, files] of dirGroups) {
|
|
373
|
+
families.push({
|
|
374
|
+
id: dir,
|
|
375
|
+
routes: [`/${dir}`],
|
|
376
|
+
webappPaths: files.map((f) => `${f}*`),
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
logger_js_1.logger.info(`Built ${families.length} heuristic families from ${changedFiles.length} changed files (no route-families.json found)`);
|
|
380
|
+
logger_js_1.logger.info('Tip: Run `e2e-ai-agents train` to generate a proper route-families manifest for better accuracy.');
|
|
381
|
+
return {
|
|
382
|
+
families,
|
|
383
|
+
source: 'heuristic',
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Serialize a RouteFamilyManifest to clean JSON, stripping empty optional fields.
|
|
388
|
+
*/
|
|
389
|
+
function serializeManifest(manifest) {
|
|
390
|
+
const output = {
|
|
391
|
+
families: manifest.families.map((f) => {
|
|
392
|
+
const cleaned = { ...f };
|
|
393
|
+
const optionalArrays = [
|
|
394
|
+
'pageObjects', 'components', 'webappPaths', 'serverPaths',
|
|
395
|
+
'specDirs', 'cypressSpecDirs', 'tags', 'userFlows', 'features', 'apiEndpoints', 'assertionPatterns',
|
|
396
|
+
];
|
|
397
|
+
for (const key of optionalArrays) {
|
|
398
|
+
if (!cleaned[key] || (Array.isArray(cleaned[key]) && cleaned[key].length === 0)) {
|
|
399
|
+
delete cleaned[key];
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
if (!cleaned.priority)
|
|
403
|
+
delete cleaned.priority;
|
|
404
|
+
if (!cleaned.testType)
|
|
405
|
+
delete cleaned.testType;
|
|
406
|
+
return cleaned;
|
|
407
|
+
}),
|
|
408
|
+
};
|
|
409
|
+
return JSON.stringify(output, null, 2) + '\n';
|
|
410
|
+
}
|
package/dist/mcp-server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":";AAeA,UAAU,IAAI;IACV,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC;AA4GD;;;GAGG;AACH,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,WAAW,CAAc;gBAErB,QAAQ,GAAE,MAAsB;IAM5C,OAAO,CAAC,WAAW;IAmGnB;;;OAGG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAwB5E,OAAO,CAAC,aAAa;IA6BrB,OAAO,CAAC,QAAQ;IAmBhB,OAAO,CAAC,SAAS;IAwCjB,OAAO,CAAC,QAAQ;IAyDhB,OAAO,CAAC,aAAa;
|
|
1
|
+
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":";AAeA,UAAU,IAAI;IACV,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC;AA4GD;;;GAGG;AACH,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,WAAW,CAAc;gBAErB,QAAQ,GAAE,MAAsB;IAM5C,OAAO,CAAC,WAAW;IAmGnB;;;OAGG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAwB5E,OAAO,CAAC,aAAa;IA6BrB,OAAO,CAAC,QAAQ;IAmBhB,OAAO,CAAC,SAAS;IAwCjB,OAAO,CAAC,QAAQ;IAyDhB,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,oBAAoB;IAqD5B,OAAO,CAAC,eAAe;IAuBvB,OAAO,CAAC,sBAAsB;IAW9B;;OAEG;IACH,QAAQ,IAAI,IAAI,EAAE;CAGrB;AAgBD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAG7E;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAC,QAAQ,EAAE,KAAK,CAAC;QAAC,EAAE,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAC,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;CAAC,CA0BtK;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACtC,MAAM,EAAE,kBAAkB,EAC1B,OAAO,EAAE;IAAC,EAAE,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAC,GAC3E,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAmEzC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,GAAE,MAAsB,GAAG,IAAI,CAmCvE;AAMD,eAAe,kBAAkB,CAAC"}
|
package/dist/mcp-server.js
CHANGED
|
@@ -377,8 +377,7 @@ class E2EAgentsMCPServer {
|
|
|
377
377
|
if (!validateGitRef(since)) {
|
|
378
378
|
return JSON.stringify({ error: 'Invalid git reference format' });
|
|
379
379
|
}
|
|
380
|
-
|
|
381
|
-
const result = (0, child_process_1.spawnSync)('git', ['diff', '--name-only', '--', `${since}..HEAD`], {
|
|
380
|
+
const result = (0, child_process_1.spawnSync)('git', ['diff', '--name-only', `${since}..HEAD`], {
|
|
382
381
|
cwd: this.repoRoot,
|
|
383
382
|
encoding: 'utf-8',
|
|
384
383
|
timeout: 30000,
|
|
@@ -446,8 +445,7 @@ class E2EAgentsMCPServer {
|
|
|
446
445
|
if (!validateGitRef(since)) {
|
|
447
446
|
return [];
|
|
448
447
|
}
|
|
449
|
-
|
|
450
|
-
const result = (0, child_process_1.spawnSync)('git', ['diff', '--name-only', '--', `${since}..HEAD`], {
|
|
448
|
+
const result = (0, child_process_1.spawnSync)('git', ['diff', '--name-only', `${since}..HEAD`], {
|
|
451
449
|
cwd: this.repoRoot,
|
|
452
450
|
encoding: 'utf-8',
|
|
453
451
|
timeout: 30000,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export declare class PrometheusMetrics {
|
|
2
|
+
private counters;
|
|
3
|
+
private gauges;
|
|
4
|
+
private histograms;
|
|
5
|
+
/**
|
|
6
|
+
* Record an LLM request.
|
|
7
|
+
*/
|
|
8
|
+
recordLLMRequest(provider: string, agent: string, durationMs: number, costUSD: number, tokens: number): void;
|
|
9
|
+
/**
|
|
10
|
+
* Record a crew workflow run.
|
|
11
|
+
*/
|
|
12
|
+
recordCrewRun(workflow: string, families: number, durationMs: number, costUSD: number): void;
|
|
13
|
+
/**
|
|
14
|
+
* Record a budget check event.
|
|
15
|
+
*/
|
|
16
|
+
recordBudgetCheck(exceeded: boolean, currentUSD: number, limitUSD: number): void;
|
|
17
|
+
/**
|
|
18
|
+
* Record a circuit breaker state change.
|
|
19
|
+
*/
|
|
20
|
+
recordCircuitBreakerState(state: 'closed' | 'open' | 'half-open'): void;
|
|
21
|
+
/**
|
|
22
|
+
* Record a cache hit or miss.
|
|
23
|
+
*/
|
|
24
|
+
recordCacheResult(hit: boolean, agent: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Export all metrics in Prometheus text exposition format.
|
|
27
|
+
*/
|
|
28
|
+
export(): string;
|
|
29
|
+
/**
|
|
30
|
+
* Reset all metrics to zero.
|
|
31
|
+
*/
|
|
32
|
+
reset(): void;
|
|
33
|
+
private incrementCounter;
|
|
34
|
+
private setGauge;
|
|
35
|
+
private observeHistogram;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=prometheus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prometheus.d.ts","sourceRoot":"","sources":["../../src/metrics/prometheus.ts"],"names":[],"mappings":"AAkCA,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,UAAU,CAAmB;IAErC;;OAEG;IACH,gBAAgB,CACZ,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACf,IAAI;IAOP;;OAEG;IACH,aAAa,CACT,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GAChB,IAAI;IAOP;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAMhF;;OAEG;IACH,yBAAyB,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,IAAI;IAKvE;;OAEG;IACH,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIpD;;OAEG;IACH,MAAM,IAAI,MAAM;IA+ChB;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,gBAAgB;CAc3B"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
|
+
// See LICENSE.txt for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.PrometheusMetrics = void 0;
|
|
6
|
+
const DURATION_BUCKETS = [0.1, 0.5, 1, 2, 5, 10, 30, 60, 120, 300];
|
|
7
|
+
class PrometheusMetrics {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.counters = [];
|
|
10
|
+
this.gauges = [];
|
|
11
|
+
this.histograms = [];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Record an LLM request.
|
|
15
|
+
*/
|
|
16
|
+
recordLLMRequest(provider, agent, durationMs, costUSD, tokens) {
|
|
17
|
+
this.incrementCounter('e2e_agents_llm_requests_total', 'Total LLM requests', { provider, agent });
|
|
18
|
+
this.incrementCounter('e2e_agents_llm_tokens_total', 'Total tokens consumed', { provider, agent }, tokens);
|
|
19
|
+
this.incrementCounter('e2e_agents_llm_cost_usd_total', 'Total LLM cost in USD', { provider, agent }, costUSD);
|
|
20
|
+
this.observeHistogram('e2e_agents_llm_request_duration_seconds', 'LLM request duration', { provider, agent }, durationMs / 1000);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Record a crew workflow run.
|
|
24
|
+
*/
|
|
25
|
+
recordCrewRun(workflow, families, durationMs, costUSD) {
|
|
26
|
+
this.incrementCounter('e2e_agents_crew_runs_total', 'Total crew workflow runs', { workflow });
|
|
27
|
+
this.incrementCounter('e2e_agents_crew_families_processed_total', 'Total families processed', { workflow }, families);
|
|
28
|
+
this.incrementCounter('e2e_agents_crew_cost_usd_total', 'Total crew cost in USD', { workflow }, costUSD);
|
|
29
|
+
this.observeHistogram('e2e_agents_crew_duration_seconds', 'Crew workflow duration', { workflow }, durationMs / 1000);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Record a budget check event.
|
|
33
|
+
*/
|
|
34
|
+
recordBudgetCheck(exceeded, currentUSD, limitUSD) {
|
|
35
|
+
this.incrementCounter('e2e_agents_budget_checks_total', 'Total budget checks', { exceeded: String(exceeded) });
|
|
36
|
+
this.setGauge('e2e_agents_budget_used_usd', 'Current budget usage in USD', {}, currentUSD);
|
|
37
|
+
this.setGauge('e2e_agents_budget_limit_usd', 'Budget limit in USD', {}, limitUSD);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Record a circuit breaker state change.
|
|
41
|
+
*/
|
|
42
|
+
recordCircuitBreakerState(state) {
|
|
43
|
+
this.setGauge('e2e_agents_circuit_breaker_state', 'Circuit breaker state (0=closed, 1=open, 2=half-open)', {}, state === 'closed' ? 0 : state === 'open' ? 1 : 2);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Record a cache hit or miss.
|
|
47
|
+
*/
|
|
48
|
+
recordCacheResult(hit, agent) {
|
|
49
|
+
this.incrementCounter('e2e_agents_cache_lookups_total', 'Total cache lookups', { result: hit ? 'hit' : 'miss', agent });
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Export all metrics in Prometheus text exposition format.
|
|
53
|
+
*/
|
|
54
|
+
export() {
|
|
55
|
+
const lines = [];
|
|
56
|
+
const seenHelp = new Set();
|
|
57
|
+
// Export counters
|
|
58
|
+
for (const counter of this.counters) {
|
|
59
|
+
if (!seenHelp.has(counter.name)) {
|
|
60
|
+
lines.push(`# HELP ${counter.name} ${counter.help}`);
|
|
61
|
+
lines.push(`# TYPE ${counter.name} counter`);
|
|
62
|
+
seenHelp.add(counter.name);
|
|
63
|
+
}
|
|
64
|
+
const labelStr = formatLabels(counter.labels);
|
|
65
|
+
lines.push(`${counter.name}${labelStr} ${counter.value}`);
|
|
66
|
+
}
|
|
67
|
+
// Export gauges
|
|
68
|
+
for (const gauge of this.gauges) {
|
|
69
|
+
if (!seenHelp.has(gauge.name)) {
|
|
70
|
+
lines.push(`# HELP ${gauge.name} ${gauge.help}`);
|
|
71
|
+
lines.push(`# TYPE ${gauge.name} gauge`);
|
|
72
|
+
seenHelp.add(gauge.name);
|
|
73
|
+
}
|
|
74
|
+
const labelStr = formatLabels(gauge.labels);
|
|
75
|
+
lines.push(`${gauge.name}${labelStr} ${gauge.value}`);
|
|
76
|
+
}
|
|
77
|
+
// Export histograms
|
|
78
|
+
for (const hist of this.histograms) {
|
|
79
|
+
if (!seenHelp.has(hist.name)) {
|
|
80
|
+
lines.push(`# HELP ${hist.name} ${hist.help}`);
|
|
81
|
+
lines.push(`# TYPE ${hist.name} histogram`);
|
|
82
|
+
seenHelp.add(hist.name);
|
|
83
|
+
}
|
|
84
|
+
const labelStr = formatLabels(hist.labels);
|
|
85
|
+
let cumulative = 0;
|
|
86
|
+
for (const bucket of DURATION_BUCKETS) {
|
|
87
|
+
cumulative += hist.buckets.get(bucket) || 0;
|
|
88
|
+
lines.push(`${hist.name}_bucket${formatLabels({ ...hist.labels, le: String(bucket) })} ${cumulative}`);
|
|
89
|
+
}
|
|
90
|
+
lines.push(`${hist.name}_bucket${formatLabels({ ...hist.labels, le: '+Inf' })} ${hist.count}`);
|
|
91
|
+
lines.push(`${hist.name}_sum${labelStr} ${hist.sum}`);
|
|
92
|
+
lines.push(`${hist.name}_count${labelStr} ${hist.count}`);
|
|
93
|
+
}
|
|
94
|
+
return lines.join('\n') + '\n';
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Reset all metrics to zero.
|
|
98
|
+
*/
|
|
99
|
+
reset() {
|
|
100
|
+
this.counters = [];
|
|
101
|
+
this.gauges = [];
|
|
102
|
+
this.histograms = [];
|
|
103
|
+
}
|
|
104
|
+
incrementCounter(name, help, labels, value = 1) {
|
|
105
|
+
const existing = this.counters.find((c) => c.name === name && labelsMatch(c.labels, labels));
|
|
106
|
+
if (existing) {
|
|
107
|
+
existing.value += value;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
this.counters.push({ name, help, labels, value });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
setGauge(name, help, labels, value) {
|
|
114
|
+
const existing = this.gauges.find((c) => c.name === name && labelsMatch(c.labels, labels));
|
|
115
|
+
if (existing) {
|
|
116
|
+
existing.value = value;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
this.gauges.push({ name, help, labels, value });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
observeHistogram(name, help, labels, value) {
|
|
123
|
+
let existing = this.histograms.find((h) => h.name === name && labelsMatch(h.labels, labels));
|
|
124
|
+
if (!existing) {
|
|
125
|
+
existing = { name, help, labels, sum: 0, count: 0, buckets: new Map() };
|
|
126
|
+
this.histograms.push(existing);
|
|
127
|
+
}
|
|
128
|
+
existing.sum += value;
|
|
129
|
+
existing.count++;
|
|
130
|
+
for (const bucket of DURATION_BUCKETS) {
|
|
131
|
+
if (value <= bucket) {
|
|
132
|
+
existing.buckets.set(bucket, (existing.buckets.get(bucket) || 0) + 1);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
exports.PrometheusMetrics = PrometheusMetrics;
|
|
138
|
+
function escapeLabel(v) {
|
|
139
|
+
return v.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
|
|
140
|
+
}
|
|
141
|
+
function formatLabels(labels) {
|
|
142
|
+
const entries = Object.entries(labels);
|
|
143
|
+
if (entries.length === 0)
|
|
144
|
+
return '';
|
|
145
|
+
return `{${entries.map(([k, v]) => `${k}="${escapeLabel(v)}"`).join(',')}}`;
|
|
146
|
+
}
|
|
147
|
+
function labelsMatch(a, b) {
|
|
148
|
+
const keysA = Object.keys(a);
|
|
149
|
+
const keysB = Object.keys(b);
|
|
150
|
+
if (keysA.length !== keysB.length)
|
|
151
|
+
return false;
|
|
152
|
+
return keysA.every((k) => a[k] === b[k]);
|
|
153
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model Router — routes agent tasks to appropriate models based on task complexity.
|
|
3
|
+
*
|
|
4
|
+
* Classification/extraction tasks → cheap model (Haiku)
|
|
5
|
+
* Generation/reasoning tasks → capable model (Sonnet)
|
|
6
|
+
*/
|
|
7
|
+
export type TaskComplexity = 'classification' | 'extraction' | 'generation' | 'reasoning';
|
|
8
|
+
export interface ModelRoutingConfig {
|
|
9
|
+
classification?: string;
|
|
10
|
+
extraction?: string;
|
|
11
|
+
generation?: string;
|
|
12
|
+
reasoning?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class ModelRouter {
|
|
15
|
+
private overrides;
|
|
16
|
+
private providerType;
|
|
17
|
+
constructor(providerType: string, overrides?: ModelRoutingConfig);
|
|
18
|
+
/**
|
|
19
|
+
* Get the recommended model for a given agent role.
|
|
20
|
+
* Returns undefined if no routing recommendation (use provider default).
|
|
21
|
+
*/
|
|
22
|
+
getModel(role: string): string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Get the task complexity for an agent role.
|
|
25
|
+
*/
|
|
26
|
+
getComplexity(role: string): TaskComplexity;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=model_router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model_router.d.ts","sourceRoot":"","sources":["../src/model_router.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AAEH,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG,YAAY,GAAG,YAAY,GAAG,WAAW,CAAC;AAE1F,MAAM,WAAW,kBAAkB;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AA8BD,qBAAa,WAAW;IACpB,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,YAAY,CAAS;gBAEjB,YAAY,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,kBAAkB;IAKhE;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAgB1C;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc;CAG9C"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
|
+
// See LICENSE.txt for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.ModelRouter = void 0;
|
|
6
|
+
const AGENT_COMPLEXITY = {
|
|
7
|
+
'impact-analyst': 'classification',
|
|
8
|
+
'coverage-evaluator': 'classification',
|
|
9
|
+
'cross-impact': 'extraction',
|
|
10
|
+
'regression-advisor': 'extraction',
|
|
11
|
+
'strategist': 'classification',
|
|
12
|
+
'test-designer': 'generation',
|
|
13
|
+
'generator': 'generation',
|
|
14
|
+
'executor': 'generation',
|
|
15
|
+
'healer': 'reasoning',
|
|
16
|
+
'explorer': 'reasoning',
|
|
17
|
+
};
|
|
18
|
+
const DEFAULT_MODELS = {
|
|
19
|
+
anthropic: {
|
|
20
|
+
classification: 'claude-haiku-4-5-20251001',
|
|
21
|
+
extraction: 'claude-haiku-4-5-20251001',
|
|
22
|
+
generation: 'claude-sonnet-4-5-20250514',
|
|
23
|
+
reasoning: 'claude-sonnet-4-5-20250514',
|
|
24
|
+
},
|
|
25
|
+
openai: {
|
|
26
|
+
classification: 'gpt-4o-mini',
|
|
27
|
+
extraction: 'gpt-4o-mini',
|
|
28
|
+
generation: 'gpt-4o',
|
|
29
|
+
reasoning: 'gpt-4o',
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
class ModelRouter {
|
|
33
|
+
constructor(providerType, overrides) {
|
|
34
|
+
this.providerType = providerType;
|
|
35
|
+
this.overrides = overrides || {};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get the recommended model for a given agent role.
|
|
39
|
+
* Returns undefined if no routing recommendation (use provider default).
|
|
40
|
+
*/
|
|
41
|
+
getModel(role) {
|
|
42
|
+
const complexity = AGENT_COMPLEXITY[role];
|
|
43
|
+
if (!complexity)
|
|
44
|
+
return undefined;
|
|
45
|
+
// Check user overrides first
|
|
46
|
+
const override = this.overrides[complexity];
|
|
47
|
+
if (override)
|
|
48
|
+
return override;
|
|
49
|
+
// Check provider defaults
|
|
50
|
+
const defaults = DEFAULT_MODELS[this.providerType];
|
|
51
|
+
if (defaults)
|
|
52
|
+
return defaults[complexity];
|
|
53
|
+
// No recommendation — use provider's default model
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get the task complexity for an agent role.
|
|
58
|
+
*/
|
|
59
|
+
getComplexity(role) {
|
|
60
|
+
return AGENT_COMPLEXITY[role] || 'generation';
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.ModelRouter = ModelRouter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ollama_provider.d.ts","sourceRoot":"","sources":["../src/ollama_provider.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACR,eAAe,EACf,UAAU,EACV,WAAW,EACX,YAAY,EACZ,oBAAoB,EACvB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAiEhD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAC5C,IAAI,SAAY;IAChB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAS;IAEtB,YAAY,EAAE,oBAAoB,CAShC;gBAEU,MAAM,EAAE,YAAY;IA8B1B,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"ollama_provider.d.ts","sourceRoot":"","sources":["../src/ollama_provider.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACR,eAAe,EACf,UAAU,EACV,WAAW,EACX,YAAY,EACZ,oBAAoB,EACvB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAiEhD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAC5C,IAAI,SAAY;IAChB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAS;IAEtB,YAAY,EAAE,oBAAoB,CAShC;gBAEU,MAAM,EAAE,YAAY;IA8B1B,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC;IAmEnF;;;OAGG;IAEG,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzG;;OAEG;IACI,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC;IAqDnG;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAC;IAgBjE;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAaxC;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC;IAC9C,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC7B,CAAC,CAoCD"}
|
package/dist/ollama_provider.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai_provider.d.ts","sourceRoot":"","sources":["../src/openai_provider.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACR,eAAe,EACf,UAAU,EACV,WAAW,EACX,YAAY,EACZ,oBAAoB,EACvB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAehD,qBAAa,cAAe,SAAQ,YAAY;IAC5C,IAAI,SAAY;IAChB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAS;IAEtB,YAAY,EAAE,oBAAoB,CAAC;gBAEvB,MAAM,EAAE,YAAY;IAyC1B,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"openai_provider.d.ts","sourceRoot":"","sources":["../src/openai_provider.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACR,eAAe,EACf,UAAU,EACV,WAAW,EACX,YAAY,EACZ,oBAAoB,EACvB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAehD,qBAAa,cAAe,SAAQ,YAAY;IAC5C,IAAI,SAAY;IAChB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAS;IAEtB,YAAY,EAAE,oBAAoB,CAAC;gBAEvB,MAAM,EAAE,YAAY;IAyC1B,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC;IA4D7E,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC;IAgGlG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC;IA8CnG,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,iBAAiB;IAWnB,WAAW,IAAI,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAC;CAuBpE;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5D,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACnB,CAAC,CAsBD"}
|
package/dist/openai_provider.js
CHANGED
|
@@ -5,6 +5,7 @@ import { type HealConfig, type HealResult } from './stage4_heal.js';
|
|
|
5
5
|
import { type FlowDecisionReport } from '../validation/output_schema.js';
|
|
6
6
|
import type { RouteFamilyConfig } from '../knowledge/route_families.js';
|
|
7
7
|
import type { ApiSurfaceConfig } from '../knowledge/api_surface.js';
|
|
8
|
+
import type { GenerationProfile } from '../prompts/generation_profile.js';
|
|
8
9
|
export interface PipelineConfig {
|
|
9
10
|
appPath: string;
|
|
10
11
|
testsRoot: string;
|
|
@@ -12,6 +13,7 @@ export interface PipelineConfig {
|
|
|
12
13
|
gitIncludeUncommitted?: boolean;
|
|
13
14
|
routeFamilies?: RouteFamilyConfig;
|
|
14
15
|
apiSurface?: ApiSurfaceConfig;
|
|
16
|
+
profile?: GenerationProfile;
|
|
15
17
|
impact?: ImpactConfig;
|
|
16
18
|
coverage?: CoverageConfig;
|
|
17
19
|
generation?: GenerationConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/pipeline/orchestrator.ts"],"names":[],"mappings":"AAQA,OAAO,EAAiB,KAAK,YAAY,EAAC,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAmB,KAAK,cAAc,EAAC,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAqB,KAAK,gBAAgB,EAAE,KAAK,aAAa,EAAC,MAAM,wBAAwB,CAAC;AACrG,OAAO,EAAuD,KAAK,UAAU,EAAE,KAAK,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACxH,OAAO,EAAe,KAAK,kBAAkB,EAAoB,MAAM,gCAAgC,CAAC;AAExG,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/pipeline/orchestrator.ts"],"names":[],"mappings":"AAQA,OAAO,EAAiB,KAAK,YAAY,EAAC,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAmB,KAAK,cAAc,EAAC,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAqB,KAAK,gBAAgB,EAAE,KAAK,aAAa,EAAC,MAAM,wBAAwB,CAAC;AACrG,OAAO,EAAuD,KAAK,UAAU,EAAE,KAAK,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACxH,OAAO,EAAe,KAAK,kBAAkB,EAAoB,MAAM,gCAAgC,CAAC;AAExG,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,kCAAkC,CAAC;AAGxE,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,iEAAiE;IACjE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,MAAM,CAAC,EAAE,KAAK,CAAC,YAAY,GAAG,QAAQ,GAAG,UAAU,GAAG,YAAY,GAAG,MAAM,CAAC,CAAC;CAChF;AAED,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,UAAU,CAAC;CAC3B;AAYD,wBAAsB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CA8IjF"}
|
|
@@ -14,6 +14,7 @@ const stage3_generation_js_1 = require("./stage3_generation.js");
|
|
|
14
14
|
const stage4_heal_js_1 = require("./stage4_heal.js");
|
|
15
15
|
const output_schema_js_1 = require("../validation/output_schema.js");
|
|
16
16
|
const guardrails_js_1 = require("../validation/guardrails.js");
|
|
17
|
+
const generation_profile_js_1 = require("../prompts/generation_profile.js");
|
|
17
18
|
function createRunId() {
|
|
18
19
|
const ciRunId = process.env.GITHUB_RUN_ID;
|
|
19
20
|
const entropy = Math.random().toString(36).slice(2, 8);
|
|
@@ -23,19 +24,12 @@ function createRunId() {
|
|
|
23
24
|
}
|
|
24
25
|
return `pipeline-local-${ts}-${entropy}`;
|
|
25
26
|
}
|
|
26
|
-
function isTestFile(file) {
|
|
27
|
-
const normalized = file.replace(/\\/g, '/');
|
|
28
|
-
return /\.(spec|test)\.(ts|tsx|js|jsx)$/.test(normalized) ||
|
|
29
|
-
/_test\.go$/.test(normalized) ||
|
|
30
|
-
normalized.includes('__tests__/') ||
|
|
31
|
-
normalized.includes('/tests/') ||
|
|
32
|
-
normalized.includes('/test/');
|
|
33
|
-
}
|
|
34
27
|
async function runPipeline(config) {
|
|
35
28
|
const runId = createRunId();
|
|
36
29
|
const startedAt = new Date().toISOString();
|
|
37
30
|
const allWarnings = [];
|
|
38
31
|
const stages = config.stages || ['preprocess', 'impact', 'coverage'];
|
|
32
|
+
const profile = config.profile || (0, generation_profile_js_1.resolveGenerationProfile)();
|
|
39
33
|
let generatedSpecs;
|
|
40
34
|
let healResult;
|
|
41
35
|
// Step 1: Get changed files
|
|
@@ -47,7 +41,7 @@ async function runPipeline(config) {
|
|
|
47
41
|
}
|
|
48
42
|
const changedFiles = gitResult.files
|
|
49
43
|
.map((f) => f.replace(/\\/g, '/'))
|
|
50
|
-
.filter((f) => !isTestFile(f));
|
|
44
|
+
.filter((f) => !(0, git_js_1.isTestFile)(f));
|
|
51
45
|
if (changedFiles.length === 0) {
|
|
52
46
|
allWarnings.push('No changed application files detected.');
|
|
53
47
|
const emptyReport = {
|
|
@@ -90,7 +84,7 @@ async function runPipeline(config) {
|
|
|
90
84
|
// Step 4: Coverage stage — AI-powered spec coverage evaluation
|
|
91
85
|
if (stages.includes('coverage') && decisions.length > 0) {
|
|
92
86
|
const coverageTimer = logger_js_1.logger.timer('coverage');
|
|
93
|
-
const coverageResult = await (0, stage2_coverage_js_1.runCoverageStage)(decisions, preprocessResult.specIndex, preprocessResult.context, config.testsRoot, config.coverage || {});
|
|
87
|
+
const coverageResult = await (0, stage2_coverage_js_1.runCoverageStage)(decisions, preprocessResult.specIndex, preprocessResult.context, config.testsRoot, { ...(config.coverage || {}), profile });
|
|
94
88
|
decisions = coverageResult.decisions;
|
|
95
89
|
timings.coverage = coverageTimer.end();
|
|
96
90
|
allWarnings.push(...coverageResult.warnings);
|
|
@@ -98,7 +92,7 @@ async function runPipeline(config) {
|
|
|
98
92
|
// Step 5: Generation stage — AI-powered spec generation for create_spec / add_scenarios
|
|
99
93
|
if (stages.includes('generation') && decisions.length > 0) {
|
|
100
94
|
const generationTimer = logger_js_1.logger.timer('generation');
|
|
101
|
-
const generationResult = await (0, stage3_generation_js_1.runGenerationStage)(decisions, preprocessResult.apiSurface, config.testsRoot, config.generation || {});
|
|
95
|
+
const generationResult = await (0, stage3_generation_js_1.runGenerationStage)(decisions, preprocessResult.apiSurface, config.testsRoot, { ...(config.generation || {}), profile });
|
|
102
96
|
generatedSpecs = generationResult.generated;
|
|
103
97
|
timings.generation = generationTimer.end();
|
|
104
98
|
allWarnings.push(...generationResult.warnings);
|
|
@@ -111,7 +105,7 @@ async function runPipeline(config) {
|
|
|
111
105
|
generatedSpecs,
|
|
112
106
|
}, decisions);
|
|
113
107
|
if (healTargets.length > 0) {
|
|
114
|
-
healResult = await (0, stage4_heal_js_1.runHealStage)(config.testsRoot, healTargets, config.heal || { mcp: true });
|
|
108
|
+
healResult = await (0, stage4_heal_js_1.runHealStage)(config.testsRoot, healTargets, { ...(config.heal || { mcp: true }), profile });
|
|
115
109
|
allWarnings.push(...healResult.warnings);
|
|
116
110
|
}
|
|
117
111
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stage0_preprocess.d.ts","sourceRoot":"","sources":["../../src/pipeline/stage0_preprocess.ts"],"names":[],"mappings":"AAKA,OAAO,
|
|
1
|
+
{"version":3,"file":"stage0_preprocess.d.ts","sourceRoot":"","sources":["../../src/pipeline/stage0_preprocess.ts"],"names":[],"mappings":"AAKA,OAAO,EAIH,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAC3B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAwB,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAC,MAAM,6BAA6B,CAAC;AACjH,OAAO,EAAiB,KAAK,SAAS,EAAC,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAuB,KAAK,aAAa,EAAC,MAAM,gCAAgC,CAAC;AAExF,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,UAAU,CAAC,EAAE,gBAAgB,CAAC;CACjC;AAED,MAAM,WAAW,WAAW;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,gBAAgB;IAC7B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACrC,UAAU,EAAE,iBAAiB,CAAC;IAC9B,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AA0BD,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CAmF7F"}
|