@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
package/dist/prompts/impact.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.buildImpactPrompt = buildImpactPrompt;
|
|
6
6
|
exports.parseImpactResponse = parseImpactResponse;
|
|
7
|
+
const json_extract_js_1 = require("./json_extract.js");
|
|
7
8
|
const spec_index_js_1 = require("../knowledge/spec_index.js");
|
|
8
9
|
const api_surface_js_1 = require("../knowledge/api_surface.js");
|
|
9
10
|
function buildImpactPrompt(ctx) {
|
|
@@ -27,7 +28,7 @@ function buildImpactPrompt(ctx) {
|
|
|
27
28
|
})
|
|
28
29
|
.join('\n\n');
|
|
29
30
|
return [
|
|
30
|
-
|
|
31
|
+
`You are analyzing code changes in ${ctx.projectName || 'Mattermost'} to identify impacted user-facing flows.`,
|
|
31
32
|
'',
|
|
32
33
|
`ROUTE FAMILY: ${ctx.family.id}`,
|
|
33
34
|
`ROUTES: ${familyRoutes}`,
|
|
@@ -62,25 +63,5 @@ function buildImpactPrompt(ctx) {
|
|
|
62
63
|
].filter(Boolean).join('\n');
|
|
63
64
|
}
|
|
64
65
|
function parseImpactResponse(text) {
|
|
65
|
-
|
|
66
|
-
const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
67
|
-
const candidates = fenced ? [fenced[1], text] : [text];
|
|
68
|
-
for (const candidate of candidates) {
|
|
69
|
-
const start = candidate.indexOf('{');
|
|
70
|
-
const end = candidate.lastIndexOf('}');
|
|
71
|
-
if (start < 0 || end <= start) {
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
const raw = candidate.slice(start, end + 1);
|
|
75
|
-
try {
|
|
76
|
-
const parsed = JSON.parse(raw);
|
|
77
|
-
if (parsed && Array.isArray(parsed.flows)) {
|
|
78
|
-
return parsed;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
catch {
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return null;
|
|
66
|
+
return (0, json_extract_js_1.extractJsonFromResponse)(text, (obj) => obj != null && typeof obj === 'object' && Array.isArray(obj.flows));
|
|
86
67
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared JSON extraction from LLM text responses.
|
|
3
|
+
* Handles fenced code blocks, bare JSON, and partial text.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Extract and parse JSON from LLM response text.
|
|
7
|
+
* Tries fenced code blocks first, then raw text.
|
|
8
|
+
* Returns null if no valid JSON found.
|
|
9
|
+
*
|
|
10
|
+
* @param text - Raw LLM response text
|
|
11
|
+
* @param validate - Predicate to check if parsed object has the expected shape
|
|
12
|
+
*/
|
|
13
|
+
export declare function extractJsonFromResponse<T>(text: string, validate: (obj: unknown) => obj is T): T | null;
|
|
14
|
+
//# sourceMappingURL=json_extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json_extract.d.ts","sourceRoot":"","sources":["../../src/prompts/json_extract.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAqBvG"}
|
|
@@ -0,0 +1,39 @@
|
|
|
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.extractJsonFromResponse = extractJsonFromResponse;
|
|
6
|
+
/**
|
|
7
|
+
* Shared JSON extraction from LLM text responses.
|
|
8
|
+
* Handles fenced code blocks, bare JSON, and partial text.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Extract and parse JSON from LLM response text.
|
|
12
|
+
* Tries fenced code blocks first, then raw text.
|
|
13
|
+
* Returns null if no valid JSON found.
|
|
14
|
+
*
|
|
15
|
+
* @param text - Raw LLM response text
|
|
16
|
+
* @param validate - Predicate to check if parsed object has the expected shape
|
|
17
|
+
*/
|
|
18
|
+
function extractJsonFromResponse(text, validate) {
|
|
19
|
+
const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
20
|
+
const candidates = fenced ? [fenced[1], text] : [text];
|
|
21
|
+
for (const candidate of candidates) {
|
|
22
|
+
const start = candidate.indexOf('{');
|
|
23
|
+
const end = candidate.lastIndexOf('}');
|
|
24
|
+
if (start < 0 || end <= start) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const raw = candidate.slice(start, end + 1);
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(raw);
|
|
30
|
+
if (validate(parsed)) {
|
|
31
|
+
return parsed;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strategist.d.ts","sourceRoot":"","sources":["../../src/prompts/strategist.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAC,WAAW,EAAE,cAAc,EAAgB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"strategist.d.ts","sourceRoot":"","sources":["../../src/prompts/strategist.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAC,WAAW,EAAE,cAAc,EAAgB,MAAM,kBAAkB,CAAC;AAIjF,MAAM,WAAW,uBAAuB;IACpC,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,eAAe,EAAE,cAAc,EAAE,CAAC;CACrC;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,uBAAuB,GAAG,MAAM,CA4D1E;AAED,MAAM,WAAW,uBAAuB;IACpC,QAAQ,EAAE,KAAK,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;QACtC,QAAQ,EAAE,WAAW,GAAG,YAAY,GAAG,MAAM,GAAG,eAAe,GAAG,MAAM,CAAC;QACzE,SAAS,EAAE,MAAM,CAAC;QAClB,cAAc,EAAE,MAAM,EAAE,CAAC;QACzB,eAAe,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;KAChE,CAAC,CAAC;CACN;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,uBAAuB,GAAG,IAAI,CAMpF"}
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
5
5
|
exports.buildStrategistPrompt = buildStrategistPrompt;
|
|
6
6
|
exports.parseStrategistResponse = parseStrategistResponse;
|
|
7
7
|
const sanitize_js_1 = require("../crew/sanitize.js");
|
|
8
|
+
const json_extract_js_1 = require("./json_extract.js");
|
|
8
9
|
function buildStrategistPrompt(ctx) {
|
|
9
10
|
const flowsBlock = ctx.impactedFlows
|
|
10
11
|
.map((f) => {
|
|
@@ -60,24 +61,5 @@ function buildStrategistPrompt(ctx) {
|
|
|
60
61
|
].join('\n');
|
|
61
62
|
}
|
|
62
63
|
function parseStrategistResponse(text) {
|
|
63
|
-
|
|
64
|
-
const candidates = fenced ? [fenced[1], text] : [text];
|
|
65
|
-
for (const candidate of candidates) {
|
|
66
|
-
const start = candidate.indexOf('{');
|
|
67
|
-
const end = candidate.lastIndexOf('}');
|
|
68
|
-
if (start < 0 || end <= start) {
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
const raw = candidate.slice(start, end + 1);
|
|
72
|
-
try {
|
|
73
|
-
const parsed = JSON.parse(raw);
|
|
74
|
-
if (parsed && Array.isArray(parsed.strategy)) {
|
|
75
|
-
return parsed;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return null;
|
|
64
|
+
return (0, json_extract_js_1.extractJsonFromResponse)(text, (obj) => obj != null && typeof obj === 'object' && Array.isArray(obj.strategy));
|
|
83
65
|
}
|
|
@@ -6,12 +6,14 @@ import type { FlowDecision } from '../validation/output_schema.js';
|
|
|
6
6
|
import { type ApiSurfaceCatalog } from '../knowledge/api_surface.js';
|
|
7
7
|
import type { SpecEntry } from '../knowledge/spec_index.js';
|
|
8
8
|
import type { StrategyEntry, CrossImpact } from '../crew/types.js';
|
|
9
|
+
import type { GenerationProfile } from './generation_profile.js';
|
|
9
10
|
export interface TestDesignerPromptContext {
|
|
10
11
|
flow: FlowDecision;
|
|
11
12
|
strategy: StrategyEntry;
|
|
12
13
|
apiSurface: ApiSurfaceCatalog;
|
|
13
14
|
existingSpecs: SpecEntry[];
|
|
14
15
|
crossImpacts: CrossImpact[];
|
|
16
|
+
profile?: GenerationProfile;
|
|
15
17
|
}
|
|
16
18
|
export declare function buildTestDesignerPrompt(ctx: TestDesignerPromptContext): string;
|
|
17
19
|
export interface TestDesignerAgentResponse {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-designer.d.ts","sourceRoot":"","sources":["../../src/prompts/test-designer.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"test-designer.d.ts","sourceRoot":"","sources":["../../src/prompts/test-designer.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AAEjE,OAAO,EAA4B,KAAK,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AAC9F,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,4BAA4B,CAAC;AAC1D,OAAO,KAAK,EAAC,aAAa,EAAE,WAAW,EAAa,MAAM,kBAAkB,CAAC;AAE7E,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,yBAAyB,CAAC;AAE/D,MAAM,WAAW,yBAAyB;IACtC,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,aAAa,CAAC;IACxB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,aAAa,EAAE,SAAS,EAAE,CAAC;IAC3B,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,yBAAyB,GAAG,MAAM,CAuF9E;AAED,MAAM,WAAW,yBAAyB;IACtC,UAAU,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,KAAK,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;YACb,IAAI,EAAE,YAAY,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,GAAG,kBAAkB,GAAG,gBAAgB,GAAG,YAAY,GAAG,eAAe,GAAG,aAAa,GAAG,MAAM,CAAC;YAC7J,aAAa,EAAE,MAAM,EAAE,CAAC;YACxB,KAAK,EAAE,MAAM,EAAE,CAAC;YAChB,eAAe,EAAE,MAAM,CAAC;YACxB,QAAQ,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;YACtC,SAAS,EAAE,MAAM,CAAC;SACrB,CAAC,CAAC;KACN,CAAC;CACL;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,yBAAyB,GAAG,IAAI,CAQxF"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.buildTestDesignerPrompt = buildTestDesignerPrompt;
|
|
6
6
|
exports.parseTestDesignerResponse = parseTestDesignerResponse;
|
|
7
|
+
const json_extract_js_1 = require("./json_extract.js");
|
|
7
8
|
const api_surface_js_1 = require("../knowledge/api_surface.js");
|
|
8
9
|
const sanitize_js_1 = require("../crew/sanitize.js");
|
|
9
10
|
function buildTestDesignerPrompt(ctx) {
|
|
@@ -28,7 +29,7 @@ function buildTestDesignerPrompt(ctx) {
|
|
|
28
29
|
: 'None detected.';
|
|
29
30
|
const categories = ctx.strategy.testCategories.join(', ');
|
|
30
31
|
return [
|
|
31
|
-
|
|
32
|
+
`You are a senior QA engineer designing comprehensive test cases for a ${ctx.profile?.projectName || 'Mattermost'} user flow.`,
|
|
32
33
|
'',
|
|
33
34
|
`FLOW: ${ctx.flow.flowName}`,
|
|
34
35
|
`Flow ID: ${ctx.flow.flowId}`,
|
|
@@ -88,24 +89,8 @@ function buildTestDesignerPrompt(ctx) {
|
|
|
88
89
|
].join('\n');
|
|
89
90
|
}
|
|
90
91
|
function parseTestDesignerResponse(text) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const end = candidate.lastIndexOf('}');
|
|
96
|
-
if (start < 0 || end <= start) {
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
const raw = candidate.slice(start, end + 1);
|
|
100
|
-
try {
|
|
101
|
-
const parsed = JSON.parse(raw);
|
|
102
|
-
if (parsed?.testDesign?.testCases && Array.isArray(parsed.testDesign.testCases)) {
|
|
103
|
-
return parsed;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return null;
|
|
92
|
+
return (0, json_extract_js_1.extractJsonFromResponse)(text, (obj) => {
|
|
93
|
+
const r = obj;
|
|
94
|
+
return r?.testDesign?.testCases != null && Array.isArray(r.testDesign.testCases);
|
|
95
|
+
});
|
|
111
96
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider_factory.d.ts","sourceRoot":"","sources":["../src/provider_factory.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAKR,WAAW,EAIX,cAAc,EAEjB,MAAM,yBAAyB,CAAC;AAGjC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,kBAAkB;IAC3B;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW;IAmBlD;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW;IAWtD;;;;;;;;;OASG;WACU,aAAa,IAAI,OAAO,CAAC,WAAW,CAAC;IAyElD;;;OAGG;WACU,oBAAoB,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IASpF;;;;;;;;;;OAUG;IACH,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW;CAkC/D;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IACzB;;;OAGG;IACH,OAAO,EAAE,cAAc,CAAC;IAExB;;;OAGG;IACH,QAAQ,EAAE,cAAc,CAAC;IAEzB;;;OAGG;IACH,cAAc,CAAC,EAAE,KAAK,CAAC,QAAQ,GAAG,mBAAmB,GAAG,wBAAwB,CAAC,CAAC;CACrF;
|
|
1
|
+
{"version":3,"file":"provider_factory.d.ts","sourceRoot":"","sources":["../src/provider_factory.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAKR,WAAW,EAIX,cAAc,EAEjB,MAAM,yBAAyB,CAAC;AAGjC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,kBAAkB;IAC3B;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW;IAmBlD;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW;IAWtD;;;;;;;;;OASG;WACU,aAAa,IAAI,OAAO,CAAC,WAAW,CAAC;IAyElD;;;OAGG;WACU,oBAAoB,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IASpF;;;;;;;;;;OAUG;IACH,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW;CAkC/D;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IACzB;;;OAGG;IACH,OAAO,EAAE,cAAc,CAAC;IAExB;;;OAGG;IACH,QAAQ,EAAE,cAAc,CAAC;IAEzB;;;OAGG;IACH,cAAc,CAAC,EAAE,KAAK,CAAC,QAAQ,GAAG,mBAAmB,GAAG,wBAAwB,CAAC,CAAC;CACrF;AAgJD;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC;IACxE,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC,CAsCD"}
|
package/dist/provider_factory.js
CHANGED
|
@@ -268,15 +268,17 @@ class HybridProvider {
|
|
|
268
268
|
const primaryStats = this.primary.getUsageStats();
|
|
269
269
|
const fallbackStats = this.fallback.getUsageStats();
|
|
270
270
|
// Combine stats
|
|
271
|
+
const totalRequests = primaryStats.requestCount + fallbackStats.requestCount;
|
|
271
272
|
return {
|
|
272
|
-
requestCount:
|
|
273
|
+
requestCount: totalRequests,
|
|
273
274
|
totalInputTokens: primaryStats.totalInputTokens + fallbackStats.totalInputTokens,
|
|
274
275
|
totalOutputTokens: primaryStats.totalOutputTokens + fallbackStats.totalOutputTokens,
|
|
275
276
|
totalTokens: primaryStats.totalTokens + fallbackStats.totalTokens,
|
|
276
277
|
totalCost: primaryStats.totalCost + fallbackStats.totalCost,
|
|
277
|
-
averageResponseTimeMs:
|
|
278
|
-
|
|
279
|
-
|
|
278
|
+
averageResponseTimeMs: totalRequests > 0
|
|
279
|
+
? (primaryStats.averageResponseTimeMs * primaryStats.requestCount +
|
|
280
|
+
fallbackStats.averageResponseTimeMs * fallbackStats.requestCount) / totalRequests
|
|
281
|
+
: 0,
|
|
280
282
|
failedRequests: primaryStats.failedRequests + fallbackStats.failedRequests,
|
|
281
283
|
startTime: new Date(Math.min(primaryStats.startTime.getTime(), fallbackStats.startTime.getTime())),
|
|
282
284
|
lastUpdated: new Date(Math.max(primaryStats.lastUpdated.getTime(), fallbackStats.lastUpdated.getTime())),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"junit.d.ts","sourceRoot":"","sources":["../../src/reporters/junit.ts"],"names":[],"mappings":"AAGA;;GAEG;AAEH,OAAO,KAAK,EAAc,QAAQ,EAAC,MAAM,eAAe,CAAC;AA6BzD,eAAO,MAAM,aAAa,EAAE,QAyE3B,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
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.junitReporter = void 0;
|
|
6
|
+
function escapeXml(str) {
|
|
7
|
+
return str
|
|
8
|
+
.replace(/&/g, '&')
|
|
9
|
+
.replace(/</g, '<')
|
|
10
|
+
.replace(/>/g, '>')
|
|
11
|
+
.replace(/"/g, '"')
|
|
12
|
+
.replace(/'/g, ''');
|
|
13
|
+
}
|
|
14
|
+
function buildTestCase(tc, flowName) {
|
|
15
|
+
const className = escapeXml(flowName.replace(/\s+/g, '.'));
|
|
16
|
+
const testName = escapeXml(tc.name);
|
|
17
|
+
return ` <testcase classname="${className}" name="${testName}" status="${escapeXml(tc.priority)}">\n` +
|
|
18
|
+
` <properties>\n` +
|
|
19
|
+
` <property name="type" value="${escapeXml(tc.type)}" />\n` +
|
|
20
|
+
` <property name="priority" value="${escapeXml(tc.priority)}" />\n` +
|
|
21
|
+
` </properties>\n` +
|
|
22
|
+
` </testcase>`;
|
|
23
|
+
}
|
|
24
|
+
function buildFailureCase(finding) {
|
|
25
|
+
const name = escapeXml(finding.title);
|
|
26
|
+
return ` <testcase classname="findings" name="${name}">\n` +
|
|
27
|
+
` <failure message="${escapeXml(finding.title)}" type="${escapeXml(finding.severity)}">${escapeXml(finding.description)}</failure>\n` +
|
|
28
|
+
` </testcase>`;
|
|
29
|
+
}
|
|
30
|
+
exports.junitReporter = {
|
|
31
|
+
name: 'junit',
|
|
32
|
+
extension: '.xml',
|
|
33
|
+
format(results) {
|
|
34
|
+
const suites = [];
|
|
35
|
+
// Build a lookup from flowName -> test cases
|
|
36
|
+
const designsByFlow = new Map();
|
|
37
|
+
for (const design of results.testDesigns) {
|
|
38
|
+
designsByFlow.set(design.flowName, design.testCases);
|
|
39
|
+
}
|
|
40
|
+
// High-severity findings as failure cases
|
|
41
|
+
const highFindings = results.findings.filter((f) => f.severity === 'high');
|
|
42
|
+
// Each strategy entry becomes a test suite
|
|
43
|
+
for (const entry of results.strategyEntries) {
|
|
44
|
+
const testCases = designsByFlow.get(entry.flowName) ?? [];
|
|
45
|
+
const failures = highFindings.filter((f) => f.title.includes(entry.flowName));
|
|
46
|
+
const totalTests = testCases.length + failures.length;
|
|
47
|
+
const casesXml = testCases.map((tc) => buildTestCase(tc, entry.flowName)).join('\n');
|
|
48
|
+
const failuresXml = failures.map((f) => buildFailureCase(f)).join('\n');
|
|
49
|
+
const allCases = [casesXml, failuresXml].filter(Boolean).join('\n');
|
|
50
|
+
// Warnings as system-out
|
|
51
|
+
const warningsText = results.warnings.length > 0
|
|
52
|
+
? ` <system-out>${escapeXml(results.warnings.join('\n'))}</system-out>`
|
|
53
|
+
: '';
|
|
54
|
+
suites.push(` <testsuite name="${escapeXml(entry.flowName)}" tests="${totalTests}" failures="${failures.length}" ` +
|
|
55
|
+
`id="${escapeXml(entry.flowId)}">\n` +
|
|
56
|
+
` <properties>\n` +
|
|
57
|
+
` <property name="priority" value="${escapeXml(entry.priority)}" />\n` +
|
|
58
|
+
` <property name="approach" value="${escapeXml(entry.approach)}" />\n` +
|
|
59
|
+
` <property name="rationale" value="${escapeXml(entry.rationale)}" />\n` +
|
|
60
|
+
` </properties>\n` +
|
|
61
|
+
(allCases ? allCases + '\n' : '') +
|
|
62
|
+
(warningsText ? warningsText + '\n' : '') +
|
|
63
|
+
` </testsuite>`);
|
|
64
|
+
}
|
|
65
|
+
// Remaining high findings not tied to a strategy entry
|
|
66
|
+
const coveredFlowNames = new Set(results.strategyEntries.map((e) => e.flowName));
|
|
67
|
+
const uncoveredFindings = highFindings.filter((f) => !Array.from(coveredFlowNames).some((name) => f.title.includes(name)));
|
|
68
|
+
if (uncoveredFindings.length > 0) {
|
|
69
|
+
const failureCases = uncoveredFindings.map((f) => buildFailureCase(f)).join('\n');
|
|
70
|
+
suites.push(` <testsuite name="findings" tests="${uncoveredFindings.length}" failures="${uncoveredFindings.length}">\n` +
|
|
71
|
+
failureCases + '\n' +
|
|
72
|
+
` </testsuite>`);
|
|
73
|
+
}
|
|
74
|
+
const totalTests = results.testDesigns.reduce((sum, d) => sum + d.testCases.length, 0) + highFindings.length;
|
|
75
|
+
const totalFailures = highFindings.length;
|
|
76
|
+
return `<?xml version="1.0" encoding="UTF-8"?>\n` +
|
|
77
|
+
`<testsuites name="e2e-agents: ${escapeXml(results.workflow)}" ` +
|
|
78
|
+
`tests="${totalTests}" failures="${totalFailures}" ` +
|
|
79
|
+
`time="0">\n` +
|
|
80
|
+
` <properties>\n` +
|
|
81
|
+
` <property name="changedFiles" value="${results.changedFiles}" />\n` +
|
|
82
|
+
` <property name="impactedFlows" value="${results.impactedFlows}" />\n` +
|
|
83
|
+
` <property name="cost" value="${results.cost}" />\n` +
|
|
84
|
+
` <property name="tokens" value="${results.tokens}" />\n` +
|
|
85
|
+
` </properties>\n` +
|
|
86
|
+
suites.join('\n') + '\n' +
|
|
87
|
+
`</testsuites>\n`;
|
|
88
|
+
},
|
|
89
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reporter interface and shared types for output format plugins.
|
|
3
|
+
*/
|
|
4
|
+
export interface CrewResults {
|
|
5
|
+
workflow: string;
|
|
6
|
+
changedFiles: number;
|
|
7
|
+
impactedFlows: number;
|
|
8
|
+
strategyEntries: Array<{
|
|
9
|
+
flowId: string;
|
|
10
|
+
flowName: string;
|
|
11
|
+
priority: string;
|
|
12
|
+
approach: string;
|
|
13
|
+
rationale: string;
|
|
14
|
+
}>;
|
|
15
|
+
testDesigns: Array<{
|
|
16
|
+
flowName: string;
|
|
17
|
+
testCases: Array<{
|
|
18
|
+
name: string;
|
|
19
|
+
type: string;
|
|
20
|
+
priority: string;
|
|
21
|
+
}>;
|
|
22
|
+
}>;
|
|
23
|
+
crossImpacts: Array<{
|
|
24
|
+
sourceFamily: string;
|
|
25
|
+
affectedFamily: string;
|
|
26
|
+
riskLevel: string;
|
|
27
|
+
}>;
|
|
28
|
+
findings: Array<{
|
|
29
|
+
title: string;
|
|
30
|
+
severity: string;
|
|
31
|
+
description: string;
|
|
32
|
+
}>;
|
|
33
|
+
warnings: string[];
|
|
34
|
+
cost: number;
|
|
35
|
+
tokens: number;
|
|
36
|
+
}
|
|
37
|
+
export interface Reporter {
|
|
38
|
+
name: string;
|
|
39
|
+
extension: string;
|
|
40
|
+
format(results: CrewResults): string;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../../src/reporters/reporter.ts"],"names":[],"mappings":"AAGA;;GAEG;AAEH,MAAM,WAAW,WAAW;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,KAAK,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;IACH,WAAW,EAAE,KAAK,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,KAAK,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;YACb,QAAQ,EAAE,MAAM,CAAC;SACpB,CAAC,CAAC;KACN,CAAC,CAAC;IACH,YAAY,EAAE,KAAK,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,SAAS,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;IACH,QAAQ,EAAE,KAAK,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAAC;CACxC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SARIF v2.1.0 reporter — maps crew results to Static Analysis Results
|
|
3
|
+
* Interchange Format for GitHub Advanced Security / Azure DevOps.
|
|
4
|
+
*/
|
|
5
|
+
import type { Reporter } from './reporter.js';
|
|
6
|
+
export declare const sarifReporter: Reporter;
|
|
7
|
+
//# sourceMappingURL=sarif.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sarif.d.ts","sourceRoot":"","sources":["../../src/reporters/sarif.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,KAAK,EAAc,QAAQ,EAAC,MAAM,eAAe,CAAC;AAyDzD,eAAO,MAAM,aAAa,EAAE,QAoH3B,CAAC"}
|
|
@@ -0,0 +1,134 @@
|
|
|
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.sarifReporter = void 0;
|
|
6
|
+
function severityToLevel(severity) {
|
|
7
|
+
switch (severity.toLowerCase()) {
|
|
8
|
+
case 'high':
|
|
9
|
+
case 'critical':
|
|
10
|
+
return 'error';
|
|
11
|
+
case 'medium':
|
|
12
|
+
return 'warning';
|
|
13
|
+
case 'low':
|
|
14
|
+
case 'info':
|
|
15
|
+
return 'note';
|
|
16
|
+
default:
|
|
17
|
+
return 'note';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function riskToLevel(risk) {
|
|
21
|
+
switch (risk.toLowerCase()) {
|
|
22
|
+
case 'high':
|
|
23
|
+
return 'warning';
|
|
24
|
+
case 'medium':
|
|
25
|
+
return 'note';
|
|
26
|
+
default:
|
|
27
|
+
return 'none';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.sarifReporter = {
|
|
31
|
+
name: 'sarif',
|
|
32
|
+
extension: '.sarif',
|
|
33
|
+
format(results) {
|
|
34
|
+
const rules = [];
|
|
35
|
+
const sarifResults = [];
|
|
36
|
+
const ruleIds = new Set();
|
|
37
|
+
function ensureRule(id, description, level) {
|
|
38
|
+
if (!ruleIds.has(id)) {
|
|
39
|
+
ruleIds.add(id);
|
|
40
|
+
rules.push({
|
|
41
|
+
id,
|
|
42
|
+
shortDescription: { text: description },
|
|
43
|
+
defaultConfiguration: { level },
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Findings -> results
|
|
48
|
+
for (const finding of results.findings) {
|
|
49
|
+
const level = severityToLevel(finding.severity);
|
|
50
|
+
const ruleId = `finding/${finding.severity}`;
|
|
51
|
+
ensureRule(ruleId, `Finding (${finding.severity})`, level);
|
|
52
|
+
sarifResults.push({
|
|
53
|
+
ruleId,
|
|
54
|
+
level,
|
|
55
|
+
message: { text: `${finding.title}: ${finding.description}` },
|
|
56
|
+
properties: {
|
|
57
|
+
severity: finding.severity,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// Strategy entries without matching test designs -> coverage gap results
|
|
62
|
+
const designedFlows = new Set(results.testDesigns.map((d) => d.flowName));
|
|
63
|
+
for (const entry of results.strategyEntries) {
|
|
64
|
+
if (!designedFlows.has(entry.flowName)) {
|
|
65
|
+
const ruleId = 'coverage/gap';
|
|
66
|
+
ensureRule(ruleId, 'Missing test coverage for impacted flow', 'warning');
|
|
67
|
+
sarifResults.push({
|
|
68
|
+
ruleId,
|
|
69
|
+
level: 'warning',
|
|
70
|
+
message: {
|
|
71
|
+
text: `Flow "${entry.flowName}" (${entry.flowId}) has strategy but no test design. ` +
|
|
72
|
+
`Priority: ${entry.priority}, approach: ${entry.approach}.`,
|
|
73
|
+
},
|
|
74
|
+
properties: {
|
|
75
|
+
flowId: entry.flowId,
|
|
76
|
+
priority: entry.priority,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// High-risk cross-impacts -> warning results
|
|
82
|
+
for (const impact of results.crossImpacts) {
|
|
83
|
+
const level = riskToLevel(impact.riskLevel);
|
|
84
|
+
if (level === 'none') {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const ruleId = `cross-impact/${impact.riskLevel}`;
|
|
88
|
+
ensureRule(ruleId, `Cross-impact (${impact.riskLevel} risk)`, level);
|
|
89
|
+
sarifResults.push({
|
|
90
|
+
ruleId,
|
|
91
|
+
level,
|
|
92
|
+
message: {
|
|
93
|
+
text: `Cross-impact: "${impact.sourceFamily}" affects "${impact.affectedFamily}" ` +
|
|
94
|
+
`with ${impact.riskLevel} risk.`,
|
|
95
|
+
},
|
|
96
|
+
properties: {
|
|
97
|
+
sourceFamily: impact.sourceFamily,
|
|
98
|
+
affectedFamily: impact.affectedFamily,
|
|
99
|
+
riskLevel: impact.riskLevel,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const run = {
|
|
104
|
+
tool: {
|
|
105
|
+
driver: {
|
|
106
|
+
name: 'e2e-agents',
|
|
107
|
+
version: '1.8.5',
|
|
108
|
+
informationUri: 'https://github.com/mattermost/e2e-agents',
|
|
109
|
+
rules,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
results: sarifResults,
|
|
113
|
+
invocations: [
|
|
114
|
+
{
|
|
115
|
+
executionSuccessful: true,
|
|
116
|
+
properties: {
|
|
117
|
+
workflow: results.workflow,
|
|
118
|
+
changedFiles: results.changedFiles,
|
|
119
|
+
impactedFlows: results.impactedFlows,
|
|
120
|
+
cost: results.cost,
|
|
121
|
+
tokens: results.tokens,
|
|
122
|
+
warnings: results.warnings,
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
};
|
|
127
|
+
const sarif = {
|
|
128
|
+
$schema: 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/sarif-2.1/schema/sarif-schema-2.1.0.json',
|
|
129
|
+
version: '2.1.0',
|
|
130
|
+
runs: [run],
|
|
131
|
+
};
|
|
132
|
+
return JSON.stringify(sarif, null, 2) + '\n';
|
|
133
|
+
},
|
|
134
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Circuit Breaker — protects against cascading failures from unavailable LLM providers.
|
|
3
|
+
*
|
|
4
|
+
* States:
|
|
5
|
+
* - CLOSED: normal operation, requests pass through
|
|
6
|
+
* - OPEN: provider is down, all requests short-circuit to fallback
|
|
7
|
+
* - HALF_OPEN: after cooldown, allows one test request through
|
|
8
|
+
*/
|
|
9
|
+
export interface CircuitBreakerConfig {
|
|
10
|
+
failureThreshold: number;
|
|
11
|
+
cooldownMs: number;
|
|
12
|
+
/** Optional predicate: only count errors where this returns true. Defaults to counting all errors. */
|
|
13
|
+
shouldCount?: (error: unknown) => boolean;
|
|
14
|
+
}
|
|
15
|
+
type CircuitState = 'closed' | 'open' | 'half-open';
|
|
16
|
+
export declare class CircuitBreaker {
|
|
17
|
+
private state;
|
|
18
|
+
private failures;
|
|
19
|
+
private lastFailureTime;
|
|
20
|
+
private config;
|
|
21
|
+
constructor(config?: Partial<CircuitBreakerConfig>);
|
|
22
|
+
/** Returns the derived state without mutating internal state. */
|
|
23
|
+
get currentState(): CircuitState;
|
|
24
|
+
get isOpen(): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Execute a function with circuit breaker protection.
|
|
27
|
+
* If the circuit is open, the fallback is called instead.
|
|
28
|
+
*/
|
|
29
|
+
call<T>(fn: () => Promise<T>, fallback: () => T): Promise<T>;
|
|
30
|
+
private onSuccess;
|
|
31
|
+
private onFailure;
|
|
32
|
+
/** Reset the circuit breaker to closed state */
|
|
33
|
+
reset(): void;
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=circuit_breaker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circuit_breaker.d.ts","sourceRoot":"","sources":["../../src/resilience/circuit_breaker.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAEH,MAAM,WAAW,oBAAoB;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,sGAAsG;IACtG,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CAC7C;AAOD,KAAK,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAEpD,qBAAa,cAAc;IACvB,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,MAAM,CAAuB;gBAEzB,MAAM,GAAE,OAAO,CAAC,oBAAoB,CAAM;IAItD,iEAAiE;IACjE,IAAI,YAAY,IAAI,YAAY,CAK/B;IAED,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED;;;OAGG;IACG,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAiClE,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,SAAS;IAQjB,gDAAgD;IAChD,KAAK,IAAI,IAAI;CAKhB"}
|