@yasserkhanorg/e2e-agents 1.7.7 → 1.8.1

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.
Files changed (119) hide show
  1. package/README.md +55 -0
  2. package/dist/agent/git.d.ts +5 -0
  3. package/dist/agent/git.d.ts.map +1 -1
  4. package/dist/agent/git.js +13 -0
  5. package/dist/agents/coverage-evaluator.d.ts +8 -0
  6. package/dist/agents/coverage-evaluator.d.ts.map +1 -0
  7. package/dist/agents/coverage-evaluator.js +41 -0
  8. package/dist/agents/cross-impact.d.ts +13 -0
  9. package/dist/agents/cross-impact.d.ts.map +1 -0
  10. package/dist/agents/cross-impact.js +135 -0
  11. package/dist/agents/executor.d.ts +8 -0
  12. package/dist/agents/executor.d.ts.map +1 -0
  13. package/dist/agents/executor.js +70 -0
  14. package/dist/agents/explorer.d.ts +12 -0
  15. package/dist/agents/explorer.d.ts.map +1 -0
  16. package/dist/agents/explorer.js +43 -0
  17. package/dist/agents/generator.d.ts +8 -0
  18. package/dist/agents/generator.d.ts.map +1 -0
  19. package/dist/agents/generator.js +77 -0
  20. package/dist/agents/healer.d.ts +8 -0
  21. package/dist/agents/healer.d.ts.map +1 -0
  22. package/dist/agents/healer.js +31 -0
  23. package/dist/agents/impact-analyst.d.ts +8 -0
  24. package/dist/agents/impact-analyst.d.ts.map +1 -0
  25. package/dist/agents/impact-analyst.js +38 -0
  26. package/dist/agents/regression-advisor.d.ts +8 -0
  27. package/dist/agents/regression-advisor.d.ts.map +1 -0
  28. package/dist/agents/regression-advisor.js +116 -0
  29. package/dist/agents/strategist.d.ts +9 -0
  30. package/dist/agents/strategist.d.ts.map +1 -0
  31. package/dist/agents/strategist.js +87 -0
  32. package/dist/agents/test-designer.d.ts +8 -0
  33. package/dist/agents/test-designer.d.ts.map +1 -0
  34. package/dist/agents/test-designer.js +106 -0
  35. package/dist/cli/commands/crew.d.ts +3 -0
  36. package/dist/cli/commands/crew.d.ts.map +1 -0
  37. package/dist/cli/commands/crew.js +137 -0
  38. package/dist/cli/parse_args.d.ts.map +1 -1
  39. package/dist/cli/parse_args.js +2 -1
  40. package/dist/cli/types.d.ts +2 -1
  41. package/dist/cli/types.d.ts.map +1 -1
  42. package/dist/cli.js +5 -0
  43. package/dist/crew/context.d.ts +40 -0
  44. package/dist/crew/context.d.ts.map +1 -0
  45. package/dist/crew/context.js +36 -0
  46. package/dist/crew/orchestrator.d.ts +36 -0
  47. package/dist/crew/orchestrator.d.ts.map +1 -0
  48. package/dist/crew/orchestrator.js +171 -0
  49. package/dist/crew/protocol.d.ts +33 -0
  50. package/dist/crew/protocol.d.ts.map +1 -0
  51. package/dist/crew/protocol.js +4 -0
  52. package/dist/crew/provider.d.ts +3 -0
  53. package/dist/crew/provider.d.ts.map +1 -0
  54. package/dist/crew/provider.js +16 -0
  55. package/dist/crew/sanitize.d.ts +3 -0
  56. package/dist/crew/sanitize.d.ts.map +1 -0
  57. package/dist/crew/sanitize.js +31 -0
  58. package/dist/crew/types.d.ts +52 -0
  59. package/dist/crew/types.d.ts.map +1 -0
  60. package/dist/crew/types.js +4 -0
  61. package/dist/crew/workflows.d.ts +52 -0
  62. package/dist/crew/workflows.d.ts.map +1 -0
  63. package/dist/crew/workflows.js +36 -0
  64. package/dist/esm/agent/git.js +12 -0
  65. package/dist/esm/agents/coverage-evaluator.js +37 -0
  66. package/dist/esm/agents/cross-impact.js +131 -0
  67. package/dist/esm/agents/executor.js +66 -0
  68. package/dist/esm/agents/explorer.js +39 -0
  69. package/dist/esm/agents/generator.js +73 -0
  70. package/dist/esm/agents/healer.js +27 -0
  71. package/dist/esm/agents/impact-analyst.js +34 -0
  72. package/dist/esm/agents/regression-advisor.js +112 -0
  73. package/dist/esm/agents/strategist.js +83 -0
  74. package/dist/esm/agents/test-designer.js +102 -0
  75. package/dist/esm/cli/commands/crew.js +134 -0
  76. package/dist/esm/cli/parse_args.js +2 -1
  77. package/dist/esm/cli.js +5 -0
  78. package/dist/esm/crew/context.js +32 -0
  79. package/dist/esm/crew/orchestrator.js +167 -0
  80. package/dist/esm/crew/protocol.js +3 -0
  81. package/dist/esm/crew/provider.js +13 -0
  82. package/dist/esm/crew/sanitize.js +27 -0
  83. package/dist/esm/crew/types.js +3 -0
  84. package/dist/esm/crew/workflows.js +33 -0
  85. package/dist/esm/index.js +14 -0
  86. package/dist/esm/knowledge/route_families.js +2 -2
  87. package/dist/esm/logger.js +1 -2
  88. package/dist/esm/ollama_provider.js +1 -1
  89. package/dist/esm/prompts/cross-impact.js +71 -0
  90. package/dist/esm/prompts/strategist.js +79 -0
  91. package/dist/esm/prompts/test-designer.js +107 -0
  92. package/dist/esm/provider_factory.js +6 -10
  93. package/dist/esm/training/enricher.js +4 -3
  94. package/dist/esm/training/validator.js +2 -1
  95. package/dist/index.d.ts +17 -0
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js +27 -1
  98. package/dist/knowledge/route_families.d.ts.map +1 -1
  99. package/dist/knowledge/route_families.js +2 -2
  100. package/dist/logger.d.ts +1 -2
  101. package/dist/logger.d.ts.map +1 -1
  102. package/dist/logger.js +1 -2
  103. package/dist/ollama_provider.js +1 -1
  104. package/dist/prompts/cross-impact.d.ts +22 -0
  105. package/dist/prompts/cross-impact.d.ts.map +1 -0
  106. package/dist/prompts/cross-impact.js +75 -0
  107. package/dist/prompts/strategist.d.ts +25 -0
  108. package/dist/prompts/strategist.d.ts.map +1 -0
  109. package/dist/prompts/strategist.js +83 -0
  110. package/dist/prompts/test-designer.d.ts +33 -0
  111. package/dist/prompts/test-designer.d.ts.map +1 -0
  112. package/dist/prompts/test-designer.js +111 -0
  113. package/dist/provider_factory.d.ts.map +1 -1
  114. package/dist/provider_factory.js +6 -10
  115. package/dist/training/enricher.d.ts.map +1 -1
  116. package/dist/training/enricher.js +4 -3
  117. package/dist/training/validator.d.ts.map +1 -1
  118. package/dist/training/validator.js +2 -1
  119. package/package.json +1 -1
@@ -0,0 +1,83 @@
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.buildStrategistPrompt = buildStrategistPrompt;
6
+ exports.parseStrategistResponse = parseStrategistResponse;
7
+ const sanitize_js_1 = require("../crew/sanitize.js");
8
+ function buildStrategistPrompt(ctx) {
9
+ const flowsBlock = ctx.impactedFlows
10
+ .map((f) => {
11
+ const specs = f.existingSpecs.map((s) => `${s.path} (${s.coverageLevel})`).join(', ') || 'none';
12
+ return [
13
+ `- ${f.flowId} (${f.priority}): ${f.flowName}`,
14
+ ` Route Family: ${f.routeFamily}`,
15
+ ` Action: ${f.action}`,
16
+ ` Confidence: ${f.confidence}%`,
17
+ ` Existing Coverage: ${specs}`,
18
+ ` User Actions: ${(0, sanitize_js_1.sanitizeForPrompt)(f.userActions.join('; ') || 'unknown')}`,
19
+ ` Changed Files: ${f.changedFiles.join(', ')}`,
20
+ ].join('\n');
21
+ })
22
+ .join('\n\n');
23
+ const crossImpactBlock = ctx.crossImpacts.length > 0
24
+ ? ctx.crossImpacts.map((ci) => `- ${ci.sourceFamily} → ${ci.affectedFamily} (${ci.riskLevel}): ${ci.sharedDependency} — ${ci.evidence}`).join('\n')
25
+ : 'No cross-family impacts detected.';
26
+ const regressionBlock = ctx.regressionRisks.length > 0
27
+ ? ctx.regressionRisks.map((r) => `- ${r.familyId} (risk=${r.riskScore}): ${r.reason}`).join('\n')
28
+ : 'No regression risk data available.';
29
+ return [
30
+ 'You are a senior QA strategist designing the overall test strategy for a code change.',
31
+ '',
32
+ `IMPACTED FLOWS (${ctx.impactedFlows.length}):`,
33
+ flowsBlock,
34
+ '',
35
+ 'CROSS-FAMILY IMPACTS:',
36
+ crossImpactBlock,
37
+ '',
38
+ 'REGRESSION RISK:',
39
+ regressionBlock,
40
+ '',
41
+ 'TASK: Design a prioritized test strategy for each impacted flow.',
42
+ '',
43
+ 'For each flow, decide:',
44
+ '1. Approach: full-test (comprehensive), smoke-test (critical path only), skip, or manual-review',
45
+ '2. Priority: P0 (critical path), P1 (important), P2 (nice to have)',
46
+ '3. Test categories to cover (from: happy-path, edge-case, boundary, negative, state-transition, race-condition, permission, accessibility, performance)',
47
+ '4. Cross-impact risk level based on shared dependencies',
48
+ '',
49
+ 'Return strict JSON only with this shape:',
50
+ '{"strategy":[{"flowId":"<id>","flowName":"<name>","priority":"P0|P1|P2","approach":"full-test|smoke-test|skip|manual-review","rationale":"<why this approach>","testCategories":["happy-path","edge-case",...],"crossImpactRisk":"high|medium|low|none"}]}',
51
+ '',
52
+ 'Rules:',
53
+ '- P0 flows with create_spec or add_scenarios action should always get full-test.',
54
+ '- Flows with high cross-impact risk should be promoted to at least P1.',
55
+ '- Flows with high regression risk should include edge-case and boundary categories.',
56
+ '- Skip flows only if confidence < 30 AND no cross-impact risk.',
57
+ '- Include accessibility category for any flow involving interactive UI elements.',
58
+ '- Include permission category for any flow involving role-based features.',
59
+ '- Keep rationale concise (1-2 sentences) explaining why this approach was chosen.',
60
+ ].join('\n');
61
+ }
62
+ function parseStrategistResponse(text) {
63
+ const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
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;
83
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Test Designer prompt — designs structured test cases across 9 categories.
3
+ * Replaces flat scenariosToAdd with rich TestCase[] that feed the Generator.
4
+ */
5
+ import type { FlowDecision } from '../validation/output_schema.js';
6
+ import { type ApiSurfaceCatalog } from '../knowledge/api_surface.js';
7
+ import type { SpecEntry } from '../knowledge/spec_index.js';
8
+ import type { StrategyEntry, CrossImpact } from '../crew/types.js';
9
+ export interface TestDesignerPromptContext {
10
+ flow: FlowDecision;
11
+ strategy: StrategyEntry;
12
+ apiSurface: ApiSurfaceCatalog;
13
+ existingSpecs: SpecEntry[];
14
+ crossImpacts: CrossImpact[];
15
+ }
16
+ export declare function buildTestDesignerPrompt(ctx: TestDesignerPromptContext): string;
17
+ export interface TestDesignerAgentResponse {
18
+ testDesign: {
19
+ flowId: string;
20
+ flowName: string;
21
+ testCases: Array<{
22
+ name: string;
23
+ type: 'happy-path' | 'edge-case' | 'boundary' | 'negative' | 'state-transition' | 'race-condition' | 'permission' | 'accessibility' | 'performance' | string;
24
+ preconditions: string[];
25
+ steps: string[];
26
+ expectedOutcome: string;
27
+ priority: 'P0' | 'P1' | 'P2' | string;
28
+ rationale: string;
29
+ }>;
30
+ };
31
+ }
32
+ export declare function parseTestDesignerResponse(text: string): TestDesignerAgentResponse | null;
33
+ //# sourceMappingURL=test-designer.d.ts.map
@@ -0,0 +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;AACjE,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;AAG7E,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;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,CAqBxF"}
@@ -0,0 +1,111 @@
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.buildTestDesignerPrompt = buildTestDesignerPrompt;
6
+ exports.parseTestDesignerResponse = parseTestDesignerResponse;
7
+ const api_surface_js_1 = require("../knowledge/api_surface.js");
8
+ const sanitize_js_1 = require("../crew/sanitize.js");
9
+ function buildTestDesignerPrompt(ctx) {
10
+ const relevantClasses = ctx.apiSurface.pageObjects
11
+ .map((po) => po.className)
12
+ .filter((name) => {
13
+ const lower = name.toLowerCase();
14
+ const hints = [ctx.flow.routeFamily, ctx.flow.featureId, ...ctx.flow.userActions.join(' ').split(/\s+/)]
15
+ .filter(Boolean)
16
+ .map((s) => s.toLowerCase().replace(/[^a-z]/g, ''));
17
+ return lower.includes('page') || hints.some((h) => h.length > 3 && lower.includes(h));
18
+ })
19
+ .slice(0, 10);
20
+ const apiBlock = relevantClasses.length > 0
21
+ ? (0, api_surface_js_1.formatApiSurfaceForPrompt)(ctx.apiSurface, relevantClasses)
22
+ : 'No page objects available.';
23
+ const existingSpecsBlock = ctx.existingSpecs.length > 0
24
+ ? ctx.existingSpecs.map((s) => `- ${s.relativePath}: ${s.testTitles.join(', ')}`).join('\n')
25
+ : 'No existing specs.';
26
+ const crossImpactBlock = ctx.crossImpacts.length > 0
27
+ ? ctx.crossImpacts.map((ci) => `- ${ci.sourceFamily} → ${ci.affectedFamily}: ${ci.sharedDependency} (${ci.riskLevel})`).join('\n')
28
+ : 'None detected.';
29
+ const categories = ctx.strategy.testCategories.join(', ');
30
+ return [
31
+ 'You are a senior QA engineer designing comprehensive test cases for a Mattermost user flow.',
32
+ '',
33
+ `FLOW: ${ctx.flow.flowName}`,
34
+ `Flow ID: ${ctx.flow.flowId}`,
35
+ `Route Family: ${ctx.flow.routeFamily}${ctx.flow.featureId ? ` / ${ctx.flow.featureId}` : ''}`,
36
+ `Route: ${ctx.flow.specificRoute || '(not specified)'}`,
37
+ `Priority: ${ctx.strategy.priority}`,
38
+ `Approach: ${ctx.strategy.approach}`,
39
+ `User Actions: ${(0, sanitize_js_1.sanitizeForPrompt)(ctx.flow.userActions.join('; ') || 'unknown')}`,
40
+ `Evidence: ${(0, sanitize_js_1.sanitizeForPrompt)(ctx.flow.evidence)}`,
41
+ '',
42
+ `REQUIRED TEST CATEGORIES: ${categories}`,
43
+ '',
44
+ 'AVAILABLE PAGE OBJECTS:',
45
+ apiBlock,
46
+ '',
47
+ 'EXISTING SPECS (avoid duplicating these):',
48
+ existingSpecsBlock,
49
+ '',
50
+ 'CROSS-FAMILY IMPACTS:',
51
+ crossImpactBlock,
52
+ '',
53
+ 'TASK: Design structured test cases for this flow.',
54
+ '',
55
+ 'Return strict JSON only with this shape:',
56
+ '{"testDesign":{"flowId":"<id>","flowName":"<name>","testCases":[{"name":"<descriptive name>","type":"<category>","preconditions":["<state required>"],"steps":["<user action>"],"expectedOutcome":"<what should happen>","priority":"P0|P1|P2","rationale":"<why this test matters>"}]}}',
57
+ '',
58
+ 'TYPE VALUES: happy-path, edge-case, boundary, negative, state-transition, race-condition, permission, accessibility, performance',
59
+ '',
60
+ 'Rules:',
61
+ '- Every test must describe a specific USER ACTION, not an implementation detail.',
62
+ '- Steps must be concrete: "click Create Channel button" not "test channel creation".',
63
+ '- Include preconditions (logged-in role, existing data state, etc.).',
64
+ '- Reference only page objects and methods listed above.',
65
+ '- Include a mandatory rationale explaining why this specific test case matters.',
66
+ '- Do NOT duplicate tests already covered by existing specs.',
67
+ '- Maximum 15 test cases per flow.',
68
+ '- For accessibility: test keyboard navigation, screen reader support, ARIA labels.',
69
+ '- For performance: test with realistic data volumes, measure load times.',
70
+ '- For edge cases: test unicode input, max-length fields, empty states, concurrent edits.',
71
+ '',
72
+ 'FEW-SHOT EXAMPLES:',
73
+ '',
74
+ 'Edge case example:',
75
+ '```json',
76
+ '{"name":"channel creation with unicode characters and max-length name","type":"edge-case","preconditions":["logged in as team member","team has < 1000 channels"],"steps":["open create channel dialog","enter 64-character name with emoji and CJK characters","click Create"],"expectedOutcome":"channel created successfully, name renders correctly in sidebar and header","priority":"P1","rationale":"catches encoding issues in channel name storage and rendering"}',
77
+ '```',
78
+ '',
79
+ 'Permission example:',
80
+ '```json',
81
+ '{"name":"guest user cannot archive a public channel","type":"permission","preconditions":["logged in as guest user","guest has access to public channel"],"steps":["open channel header menu","look for Archive Channel option"],"expectedOutcome":"Archive Channel option is not visible in the menu","priority":"P0","rationale":"permission escalation bug — guests archiving channels could disrupt entire teams"}',
82
+ '```',
83
+ '',
84
+ 'Accessibility example:',
85
+ '```json',
86
+ '{"name":"keyboard navigation through channel switcher results","type":"accessibility","preconditions":["logged in","channel switcher open via Ctrl+K"],"steps":["type partial channel name","press ArrowDown to navigate results","press Enter to select"],"expectedOutcome":"focus moves visually and via aria-activedescendant, selected channel opens","priority":"P1","rationale":"screen reader users rely on keyboard navigation — broken focus management makes the app unusable"}',
87
+ '```',
88
+ ].join('\n');
89
+ }
90
+ function parseTestDesignerResponse(text) {
91
+ const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
92
+ const candidates = fenced ? [fenced[1], text] : [text];
93
+ for (const candidate of candidates) {
94
+ const start = candidate.indexOf('{');
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;
111
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"provider_factory.d.ts","sourceRoot":"","sources":["../src/provider_factory.ts"],"names":[],"mappings":"AAOA,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;IA0ElD;;;;;;;;;;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;AAqJD;;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"}
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;;;;;;;;;;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;AA+ID;;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"}
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.LLMProviderFactory = void 0;
6
6
  exports.validateProviderSetup = validateProviderSetup;
7
7
  const anthropic_provider_js_1 = require("./anthropic_provider.js");
8
+ const logger_js_1 = require("./logger.js");
8
9
  const custom_provider_js_1 = require("./custom_provider.js");
9
10
  const ollama_provider_js_1 = require("./ollama_provider.js");
10
11
  const openai_provider_js_1 = require("./openai_provider.js");
@@ -135,8 +136,7 @@ class LLMProviderFactory {
135
136
  const ollama = new ollama_provider_js_1.OllamaProvider({});
136
137
  const health = await ollama.checkHealth();
137
138
  if (health.healthy) {
138
- // eslint-disable-next-line no-console
139
- console.log('Auto-detected Ollama provider (free, local)');
139
+ logger_js_1.logger.info('Auto-detected Ollama provider (free, local)');
140
140
  return ollama;
141
141
  }
142
142
  throw new Error('No LLM provider available. Please either:\n' +
@@ -223,8 +223,7 @@ class HybridProvider {
223
223
  }
224
224
  async generateText(prompt, options) {
225
225
  // Use primary for text generation (free)
226
- // eslint-disable-next-line no-console
227
- console.log(`[Hybrid] Using ${this.primary.name} for text generation`);
226
+ logger_js_1.logger.debug(`[Hybrid] Using ${this.primary.name} for text generation`);
228
227
  return await this.primary.generateText(prompt, options);
229
228
  }
230
229
  async analyzeImage(images, prompt, options) {
@@ -232,8 +231,7 @@ class HybridProvider {
232
231
  if (this.useFallbackFor.has('vision')) {
233
232
  // Use fallback if primary doesn't support vision
234
233
  if (!this.primary.capabilities.vision) {
235
- // eslint-disable-next-line no-console
236
- console.log(`[Hybrid] Using ${this.fallback.name} for vision analysis (primary doesn't support vision)`);
234
+ logger_js_1.logger.debug(`[Hybrid] Using ${this.fallback.name} for vision analysis (primary doesn't support vision)`);
237
235
  if (!this.fallback.analyzeImage) {
238
236
  throw new provider_interface_js_1.UnsupportedCapabilityError(this.name, 'vision');
239
237
  }
@@ -242,8 +240,7 @@ class HybridProvider {
242
240
  }
243
241
  // Try primary first
244
242
  if (this.primary.analyzeImage) {
245
- // eslint-disable-next-line no-console
246
- console.log(`[Hybrid] Using ${this.primary.name} for vision analysis`);
243
+ logger_js_1.logger.debug(`[Hybrid] Using ${this.primary.name} for vision analysis`);
247
244
  return await this.primary.analyzeImage(images, prompt, options);
248
245
  }
249
246
  throw new provider_interface_js_1.UnsupportedCapabilityError(this.name, 'vision');
@@ -253,8 +250,7 @@ class HybridProvider {
253
250
  if (!this.primary.streamText) {
254
251
  throw new provider_interface_js_1.UnsupportedCapabilityError(this.primary.name, 'streaming');
255
252
  }
256
- // eslint-disable-next-line no-console
257
- console.log(`[Hybrid] Using ${this.primary.name} for streaming`);
253
+ logger_js_1.logger.debug(`[Hybrid] Using ${this.primary.name} for streaming`);
258
254
  yield* this.primary.streamText(prompt, options);
259
255
  }
260
256
  getUsageStats() {
@@ -1 +1 @@
1
- {"version":3,"file":"enricher.d.ts","sourceRoot":"","sources":["../../src/training/enricher.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gCAAgC,CAAC;AAGhE,OAAO,KAAK,EAAC,gBAAgB,EAAE,aAAa,EAAC,MAAM,YAAY,CAAC;AAkLhE,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAmBlE;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAwBrE;AAkCD,wBAAsB,cAAc,CAChC,QAAQ,EAAE,WAAW,EAAE,EACvB,OAAO,EAAE,aAAa,EAAE,EACxB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,gBAAgB,CAAC,CAuF3B"}
1
+ {"version":3,"file":"enricher.d.ts","sourceRoot":"","sources":["../../src/training/enricher.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gCAAgC,CAAC;AAGhE,OAAO,KAAK,EAAC,gBAAgB,EAAE,aAAa,EAAC,MAAM,YAAY,CAAC;AAkLhE,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAmBlE;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAwBrE;AAkCD,wBAAsB,cAAc,CAChC,QAAQ,EAAE,WAAW,EAAE,EACvB,OAAO,EAAE,aAAa,EAAE,EACxB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,gBAAgB,CAAC,CAuF3B"}
@@ -7,6 +7,7 @@ exports.parseEnrichResponse = parseEnrichResponse;
7
7
  exports.enrichFamilies = enrichFamilies;
8
8
  const fs_1 = require("fs");
9
9
  const path_1 = require("path");
10
+ const logger_js_1 = require("../logger.js");
10
11
  const types_js_1 = require("./types.js");
11
12
  const MAX_FILES_PER_FAMILY = 20;
12
13
  const MAX_LINES_PER_FILE = 50;
@@ -294,11 +295,11 @@ async function enrichFamilies(families, scanned, projectRoot, provider, budgetUS
294
295
  // Truncate at the last complete section boundary to avoid malformed input
295
296
  const lastSectionEnd = prompt.lastIndexOf('\n---\n', MAX_PROMPT_CHARS);
296
297
  if (lastSectionEnd > 0) {
297
- console.warn(`[train] Prompt truncated from ${prompt.length} chars at section boundary`);
298
+ logger_js_1.logger.warn(`[train] Prompt truncated from ${prompt.length} chars at section boundary`);
298
299
  prompt = prompt.slice(0, lastSectionEnd);
299
300
  }
300
301
  else {
301
- console.warn(`[train] Prompt truncated from ${prompt.length} to ${MAX_PROMPT_CHARS} chars`);
302
+ logger_js_1.logger.warn(`[train] Prompt truncated from ${prompt.length} to ${MAX_PROMPT_CHARS} chars`);
302
303
  prompt = prompt.slice(0, MAX_PROMPT_CHARS);
303
304
  }
304
305
  }
@@ -330,7 +331,7 @@ async function enrichFamilies(families, scanned, projectRoot, provider, budgetUS
330
331
  }
331
332
  catch (error) {
332
333
  // On LLM failure, keep families unchanged
333
- console.warn(`[train] LLM enrichment failed for chunk: ${error instanceof Error ? error.message : String(error)}`);
334
+ logger_js_1.logger.warn(`[train] LLM enrichment failed for chunk: ${error instanceof Error ? error.message : String(error)}`);
334
335
  enriched.push(...chunk);
335
336
  }
336
337
  finally {
@@ -1 +1 @@
1
- {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/training/validator.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AAExE,OAAO,KAAK,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,YAAY,CAAC;AAoBnE;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CA6BrD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAC,CAAC,CA6BhG;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAC,CAAC,CAgB1H;AA+CD,wBAAgB,cAAc,CAC1B,QAAQ,EAAE,mBAAmB,EAC7B,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,MAAM,EAAE,GACxB,gBAAgB,CA+BlB;AAED,wBAAgB,qBAAqB,CACjC,OAAO,EAAE,gBAAgB,EAAE,EAC3B,QAAQ,EAAE,mBAAmB,GAC9B,gBAAgB,CAkDlB;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAgCvE"}
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/training/validator.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AAExE,OAAO,KAAK,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,YAAY,CAAC;AAoBnE;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CA6BrD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAC,CAAC,CA6BhG;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAC,CAAC,CAgB1H;AA+CD,wBAAgB,cAAc,CAC1B,QAAQ,EAAE,mBAAmB,EAC7B,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,MAAM,EAAE,GACxB,gBAAgB,CA+BlB;AAED,wBAAgB,qBAAqB,CACjC,OAAO,EAAE,gBAAgB,EAAE,EAC3B,QAAQ,EAAE,mBAAmB,GAC9B,gBAAgB,CAkDlB;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAgCvE"}
@@ -10,6 +10,7 @@ exports.buildValidationReport = buildValidationReport;
10
10
  exports.formatValidationReport = formatValidationReport;
11
11
  const child_process_1 = require("child_process");
12
12
  const path_1 = require("path");
13
+ const logger_js_1 = require("../logger.js");
13
14
  const route_families_js_1 = require("../knowledge/route_families.js");
14
15
  /**
15
16
  * Glob-style patterns for infrastructure / cross-cutting files that will never
@@ -111,7 +112,7 @@ function getCommitFiles(projectRoot, since) {
111
112
  });
112
113
  }
113
114
  catch (error) {
114
- console.warn(`[train] git log failed: ${error instanceof Error ? error.message : String(error)}`);
115
+ logger_js_1.logger.warn(`[train] git log failed: ${error instanceof Error ? error.message : String(error)}`);
115
116
  return [];
116
117
  }
117
118
  return parseGitLog(log);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yasserkhanorg/e2e-agents",
3
- "version": "1.7.7",
3
+ "version": "1.8.1",
4
4
  "description": "AI-powered E2E test impact analysis, generation, and healing. Analyzes code changes to identify affected Playwright tests, detects coverage gaps, and generates or repairs specs using pluggable LLM providers (Claude, OpenAI, Ollama). Includes MCP server, traceability, and CI/CD integration.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/esm/index.js",