@yasserkhanorg/e2e-agents 0.3.2

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 (221) hide show
  1. package/LICENSE +168 -0
  2. package/README.md +620 -0
  3. package/dist/agent/analysis.d.ts +62 -0
  4. package/dist/agent/analysis.d.ts.map +1 -0
  5. package/dist/agent/analysis.js +292 -0
  6. package/dist/agent/blast_radius.d.ts +4 -0
  7. package/dist/agent/blast_radius.d.ts.map +1 -0
  8. package/dist/agent/blast_radius.js +37 -0
  9. package/dist/agent/cache_utils.d.ts +38 -0
  10. package/dist/agent/cache_utils.d.ts.map +1 -0
  11. package/dist/agent/cache_utils.js +67 -0
  12. package/dist/agent/config.d.ts +148 -0
  13. package/dist/agent/config.d.ts.map +1 -0
  14. package/dist/agent/config.js +640 -0
  15. package/dist/agent/dependency_graph.d.ts +14 -0
  16. package/dist/agent/dependency_graph.d.ts.map +1 -0
  17. package/dist/agent/dependency_graph.js +227 -0
  18. package/dist/agent/feedback.d.ts +55 -0
  19. package/dist/agent/feedback.d.ts.map +1 -0
  20. package/dist/agent/feedback.js +257 -0
  21. package/dist/agent/flags.d.ts +23 -0
  22. package/dist/agent/flags.d.ts.map +1 -0
  23. package/dist/agent/flags.js +171 -0
  24. package/dist/agent/flow_catalog.d.ts +25 -0
  25. package/dist/agent/flow_catalog.d.ts.map +1 -0
  26. package/dist/agent/flow_catalog.js +106 -0
  27. package/dist/agent/flow_mapping.d.ts +10 -0
  28. package/dist/agent/flow_mapping.d.ts.map +1 -0
  29. package/dist/agent/flow_mapping.js +84 -0
  30. package/dist/agent/framework.d.ts +13 -0
  31. package/dist/agent/framework.d.ts.map +1 -0
  32. package/dist/agent/framework.js +149 -0
  33. package/dist/agent/gap_suggestions.d.ts +14 -0
  34. package/dist/agent/gap_suggestions.d.ts.map +1 -0
  35. package/dist/agent/gap_suggestions.js +101 -0
  36. package/dist/agent/generator.d.ts +10 -0
  37. package/dist/agent/generator.d.ts.map +1 -0
  38. package/dist/agent/generator.js +115 -0
  39. package/dist/agent/git.d.ts +11 -0
  40. package/dist/agent/git.d.ts.map +1 -0
  41. package/dist/agent/git.js +90 -0
  42. package/dist/agent/handoff.d.ts +22 -0
  43. package/dist/agent/handoff.d.ts.map +1 -0
  44. package/dist/agent/handoff.js +180 -0
  45. package/dist/agent/impact-analyzer.d.ts +114 -0
  46. package/dist/agent/impact-analyzer.d.ts.map +1 -0
  47. package/dist/agent/impact-analyzer.js +557 -0
  48. package/dist/agent/index.d.ts +21 -0
  49. package/dist/agent/index.d.ts.map +1 -0
  50. package/dist/agent/index.js +38 -0
  51. package/dist/agent/model-router.d.ts +57 -0
  52. package/dist/agent/model-router.d.ts.map +1 -0
  53. package/dist/agent/model-router.js +154 -0
  54. package/dist/agent/operational_insights.d.ts +41 -0
  55. package/dist/agent/operational_insights.d.ts.map +1 -0
  56. package/dist/agent/operational_insights.js +126 -0
  57. package/dist/agent/pipeline.d.ts +23 -0
  58. package/dist/agent/pipeline.d.ts.map +1 -0
  59. package/dist/agent/pipeline.js +609 -0
  60. package/dist/agent/plan.d.ts +91 -0
  61. package/dist/agent/plan.d.ts.map +1 -0
  62. package/dist/agent/plan.js +331 -0
  63. package/dist/agent/playwright_report.d.ts +8 -0
  64. package/dist/agent/playwright_report.d.ts.map +1 -0
  65. package/dist/agent/playwright_report.js +126 -0
  66. package/dist/agent/report-generator.d.ts +24 -0
  67. package/dist/agent/report-generator.d.ts.map +1 -0
  68. package/dist/agent/report-generator.js +250 -0
  69. package/dist/agent/report.d.ts +81 -0
  70. package/dist/agent/report.d.ts.map +1 -0
  71. package/dist/agent/report.js +147 -0
  72. package/dist/agent/runner.d.ts +7 -0
  73. package/dist/agent/runner.d.ts.map +1 -0
  74. package/dist/agent/runner.js +576 -0
  75. package/dist/agent/selectors.d.ts +10 -0
  76. package/dist/agent/selectors.d.ts.map +1 -0
  77. package/dist/agent/selectors.js +75 -0
  78. package/dist/agent/spec-bridge.d.ts +101 -0
  79. package/dist/agent/spec-bridge.d.ts.map +1 -0
  80. package/dist/agent/spec-bridge.js +273 -0
  81. package/dist/agent/spec-builder.d.ts +102 -0
  82. package/dist/agent/spec-builder.d.ts.map +1 -0
  83. package/dist/agent/spec-builder.js +273 -0
  84. package/dist/agent/subsystem_risk.d.ts +23 -0
  85. package/dist/agent/subsystem_risk.d.ts.map +1 -0
  86. package/dist/agent/subsystem_risk.js +207 -0
  87. package/dist/agent/telemetry.d.ts +84 -0
  88. package/dist/agent/telemetry.d.ts.map +1 -0
  89. package/dist/agent/telemetry.js +220 -0
  90. package/dist/agent/test_path.d.ts +2 -0
  91. package/dist/agent/test_path.d.ts.map +1 -0
  92. package/dist/agent/test_path.js +23 -0
  93. package/dist/agent/tests.d.ts +18 -0
  94. package/dist/agent/tests.d.ts.map +1 -0
  95. package/dist/agent/tests.js +106 -0
  96. package/dist/agent/traceability.d.ts +22 -0
  97. package/dist/agent/traceability.d.ts.map +1 -0
  98. package/dist/agent/traceability.js +183 -0
  99. package/dist/agent/traceability_capture.d.ts +18 -0
  100. package/dist/agent/traceability_capture.d.ts.map +1 -0
  101. package/dist/agent/traceability_capture.js +313 -0
  102. package/dist/agent/traceability_ingest.d.ts +21 -0
  103. package/dist/agent/traceability_ingest.d.ts.map +1 -0
  104. package/dist/agent/traceability_ingest.js +237 -0
  105. package/dist/agent/utils.d.ts +13 -0
  106. package/dist/agent/utils.d.ts.map +1 -0
  107. package/dist/agent/utils.js +152 -0
  108. package/dist/agent/validators/selector-validator.d.ts +74 -0
  109. package/dist/agent/validators/selector-validator.d.ts.map +1 -0
  110. package/dist/agent/validators/selector-validator.js +165 -0
  111. package/dist/anthropic_provider.d.ts +65 -0
  112. package/dist/anthropic_provider.d.ts.map +1 -0
  113. package/dist/anthropic_provider.js +332 -0
  114. package/dist/api.d.ts +48 -0
  115. package/dist/api.d.ts.map +1 -0
  116. package/dist/api.js +113 -0
  117. package/dist/base_provider.d.ts +53 -0
  118. package/dist/base_provider.d.ts.map +1 -0
  119. package/dist/base_provider.js +81 -0
  120. package/dist/cli.d.ts +3 -0
  121. package/dist/cli.d.ts.map +1 -0
  122. package/dist/cli.js +843 -0
  123. package/dist/custom_provider.d.ts +20 -0
  124. package/dist/custom_provider.d.ts.map +1 -0
  125. package/dist/custom_provider.js +276 -0
  126. package/dist/e2e-test-gen/index.d.ts +51 -0
  127. package/dist/e2e-test-gen/index.d.ts.map +1 -0
  128. package/dist/e2e-test-gen/index.js +57 -0
  129. package/dist/e2e-test-gen/spec_parser.d.ts +142 -0
  130. package/dist/e2e-test-gen/spec_parser.d.ts.map +1 -0
  131. package/dist/e2e-test-gen/spec_parser.js +786 -0
  132. package/dist/e2e-test-gen/types.d.ts +185 -0
  133. package/dist/e2e-test-gen/types.d.ts.map +1 -0
  134. package/dist/e2e-test-gen/types.js +4 -0
  135. package/dist/esm/agent/analysis.js +287 -0
  136. package/dist/esm/agent/blast_radius.js +34 -0
  137. package/dist/esm/agent/cache_utils.js +63 -0
  138. package/dist/esm/agent/config.js +637 -0
  139. package/dist/esm/agent/dependency_graph.js +224 -0
  140. package/dist/esm/agent/feedback.js +253 -0
  141. package/dist/esm/agent/flags.js +160 -0
  142. package/dist/esm/agent/flow_catalog.js +103 -0
  143. package/dist/esm/agent/flow_mapping.js +81 -0
  144. package/dist/esm/agent/framework.js +145 -0
  145. package/dist/esm/agent/gap_suggestions.js +98 -0
  146. package/dist/esm/agent/generator.js +112 -0
  147. package/dist/esm/agent/git.js +87 -0
  148. package/dist/esm/agent/handoff.js +177 -0
  149. package/dist/esm/agent/impact-analyzer.js +548 -0
  150. package/dist/esm/agent/index.js +22 -0
  151. package/dist/esm/agent/model-router.js +150 -0
  152. package/dist/esm/agent/operational_insights.js +123 -0
  153. package/dist/esm/agent/pipeline.js +605 -0
  154. package/dist/esm/agent/plan.js +324 -0
  155. package/dist/esm/agent/playwright_report.js +123 -0
  156. package/dist/esm/agent/report-generator.js +247 -0
  157. package/dist/esm/agent/report.js +144 -0
  158. package/dist/esm/agent/runner.js +572 -0
  159. package/dist/esm/agent/selectors.js +71 -0
  160. package/dist/esm/agent/spec-bridge.js +267 -0
  161. package/dist/esm/agent/spec-builder.js +267 -0
  162. package/dist/esm/agent/subsystem_risk.js +204 -0
  163. package/dist/esm/agent/telemetry.js +216 -0
  164. package/dist/esm/agent/test_path.js +20 -0
  165. package/dist/esm/agent/tests.js +101 -0
  166. package/dist/esm/agent/traceability.js +180 -0
  167. package/dist/esm/agent/traceability_capture.js +310 -0
  168. package/dist/esm/agent/traceability_ingest.js +234 -0
  169. package/dist/esm/agent/utils.js +138 -0
  170. package/dist/esm/agent/validators/selector-validator.js +160 -0
  171. package/dist/esm/anthropic_provider.js +324 -0
  172. package/dist/esm/api.js +105 -0
  173. package/dist/esm/base_provider.js +77 -0
  174. package/dist/esm/cli.js +841 -0
  175. package/dist/esm/custom_provider.js +272 -0
  176. package/dist/esm/e2e-test-gen/index.js +50 -0
  177. package/dist/esm/e2e-test-gen/spec_parser.js +782 -0
  178. package/dist/esm/e2e-test-gen/types.js +3 -0
  179. package/dist/esm/index.js +16 -0
  180. package/dist/esm/logger.js +89 -0
  181. package/dist/esm/mcp-server.js +465 -0
  182. package/dist/esm/ollama_provider.js +300 -0
  183. package/dist/esm/openai_provider.js +242 -0
  184. package/dist/esm/package.json +3 -0
  185. package/dist/esm/plan-and-test-constants.js +126 -0
  186. package/dist/esm/provider_factory.js +336 -0
  187. package/dist/esm/provider_interface.js +23 -0
  188. package/dist/esm/provider_utils.js +96 -0
  189. package/dist/index.d.ts +31 -0
  190. package/dist/index.d.ts.map +1 -0
  191. package/dist/index.js +41 -0
  192. package/dist/logger.d.ts +23 -0
  193. package/dist/logger.d.ts.map +1 -0
  194. package/dist/logger.js +93 -0
  195. package/dist/mcp-server.d.ts +35 -0
  196. package/dist/mcp-server.d.ts.map +1 -0
  197. package/dist/mcp-server.js +469 -0
  198. package/dist/ollama_provider.d.ts +65 -0
  199. package/dist/ollama_provider.d.ts.map +1 -0
  200. package/dist/ollama_provider.js +308 -0
  201. package/dist/openai_provider.d.ts +23 -0
  202. package/dist/openai_provider.d.ts.map +1 -0
  203. package/dist/openai_provider.js +250 -0
  204. package/dist/plan-and-test-constants.d.ts +110 -0
  205. package/dist/plan-and-test-constants.d.ts.map +1 -0
  206. package/dist/plan-and-test-constants.js +132 -0
  207. package/dist/provider_factory.d.ts +99 -0
  208. package/dist/provider_factory.d.ts.map +1 -0
  209. package/dist/provider_factory.js +341 -0
  210. package/dist/provider_interface.d.ts +358 -0
  211. package/dist/provider_interface.d.ts.map +1 -0
  212. package/dist/provider_interface.js +28 -0
  213. package/dist/provider_utils.d.ts +39 -0
  214. package/dist/provider_utils.d.ts.map +1 -0
  215. package/dist/provider_utils.js +103 -0
  216. package/package.json +101 -0
  217. package/schemas/gap.schema.json +18 -0
  218. package/schemas/impact.schema.json +418 -0
  219. package/schemas/plan.schema.json +285 -0
  220. package/schemas/subsystem-risk-map.schema.json +62 -0
  221. package/schemas/traceability-input.schema.json +122 -0
@@ -0,0 +1,332 @@
1
+ "use strict";
2
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
3
+ // See LICENSE.txt for license information.
4
+ var __importDefault = (this && this.__importDefault) || function (mod) {
5
+ return (mod && mod.__esModule) ? mod : { "default": mod };
6
+ };
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.AnthropicProvider = void 0;
9
+ exports.checkAnthropicSetup = checkAnthropicSetup;
10
+ const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
11
+ const provider_interface_js_1 = require("./provider_interface.js");
12
+ const provider_utils_js_1 = require("./provider_utils.js");
13
+ const base_provider_js_1 = require("./base_provider.js");
14
+ const logger_js_1 = require("./logger.js");
15
+ /**
16
+ * Anthropic Provider - Claude AI models
17
+ *
18
+ * Features:
19
+ * - Highest quality AI (98% accuracy in testing)
20
+ * - Vision support (analyze screenshots, compare UI)
21
+ * - Fast response times (<1 second)
22
+ * - 200K token context window
23
+ * - Prompt caching (reduces costs by 90% on repeated prompts)
24
+ *
25
+ * Costs (Claude Sonnet 4.5):
26
+ * - Input: $3 per 1M tokens
27
+ * - Output: $15 per 1M tokens
28
+ * - Cached input: $0.30 per 1M tokens
29
+ * - Estimated: ~$30-80/month for autonomous testing
30
+ *
31
+ * Use cases:
32
+ * - Vision tasks (screenshot comparison)
33
+ * - Complex failure diagnosis
34
+ * - High-stakes production testing
35
+ * - When quality is paramount
36
+ *
37
+ * Models:
38
+ * - claude-sonnet-4-5-20250929 (recommended - best balance)
39
+ * - claude-opus-4-5-20251101 (highest quality, slower, more expensive)
40
+ * - claude-haiku-4-0-20250430 (fastest, cheapest, lower quality)
41
+ */
42
+ class AnthropicProvider extends base_provider_js_1.BaseProvider {
43
+ constructor(config) {
44
+ super();
45
+ this.name = 'anthropic';
46
+ this.capabilities = {
47
+ vision: true, // Full vision support
48
+ streaming: true,
49
+ maxTokens: 200000, // 200K context window
50
+ costPer1MInputTokens: 3, // $3 per 1M input tokens
51
+ costPer1MOutputTokens: 15, // $15 per 1M output tokens
52
+ supportsTools: true, // Function calling support
53
+ supportsPromptCaching: true, // Reduces costs by 90%
54
+ typicalResponseTimeMs: 800, // ~0.8 seconds
55
+ };
56
+ // SECURITY: Validate API key format
57
+ if (!provider_utils_js_1.API_KEY_PATTERNS.anthropic.test(config.apiKey)) {
58
+ throw new Error('Invalid API key format. Expected sk-ant-* format.');
59
+ }
60
+ // SECURITY: Validate and enforce HTTPS for remote connections
61
+ if (config.baseUrl) {
62
+ const validation = (0, provider_utils_js_1.validateAndSanitizeUrl)(config.baseUrl);
63
+ if (!validation.valid) {
64
+ throw new Error(`Invalid base URL: ${validation.warning}`);
65
+ }
66
+ if (validation.warning) {
67
+ logger_js_1.logger.warn(`HTTPS required for remote URLs: ${validation.warning}`);
68
+ }
69
+ }
70
+ this.client = new sdk_1.default({
71
+ apiKey: config.apiKey,
72
+ baseURL: config.baseUrl,
73
+ });
74
+ this.model = config.model || 'claude-sonnet-4-5-20250929';
75
+ }
76
+ async generateText(prompt, options) {
77
+ const startTime = Date.now();
78
+ try {
79
+ // SECURITY: Validate prompt length to prevent resource exhaustion
80
+ if (prompt.length > 10 * 1024 * 1024) {
81
+ throw new Error('Prompt exceeds maximum size (10MB)');
82
+ }
83
+ const response = await (0, provider_utils_js_1.withTimeout)(this.client.messages.create({
84
+ model: this.model,
85
+ max_tokens: options?.maxTokens || 4000,
86
+ temperature: options?.temperature,
87
+ top_p: options?.topP,
88
+ stop_sequences: options?.stopSequences,
89
+ system: options?.systemPrompt,
90
+ messages: [
91
+ {
92
+ role: 'user',
93
+ content: prompt,
94
+ },
95
+ ],
96
+ }), options?.timeout, 'generateText');
97
+ const responseTime = Date.now() - startTime;
98
+ const text = this.extractTextFromResponse(response);
99
+ // SECURITY: Type-safe usage extraction
100
+ const usage = this.extractUsageFromResponse(response.usage);
101
+ const cost = this.calculateCost(usage, this.capabilities.costPer1MInputTokens, this.capabilities.costPer1MOutputTokens);
102
+ // Update stats
103
+ this.updateStats(usage, responseTime, cost);
104
+ return {
105
+ text,
106
+ usage,
107
+ cost,
108
+ metadata: {
109
+ model: this.model,
110
+ responseTimeMs: responseTime,
111
+ stopReason: response.stop_reason,
112
+ stopSequence: response.stop_sequence,
113
+ },
114
+ };
115
+ }
116
+ catch (error) {
117
+ this.stats.failedRequests++;
118
+ throw new provider_interface_js_1.LLMProviderError((0, provider_utils_js_1.sanitizeErrorMessage)(error, 'generateText'), this.name, this.extractStatusCode(error), error);
119
+ }
120
+ }
121
+ async analyzeImage(images, prompt, options) {
122
+ const startTime = Date.now();
123
+ try {
124
+ // SECURITY: Validate image array size
125
+ if (images.length === 0 || images.length > 20) {
126
+ throw new Error('Image count must be between 1 and 20');
127
+ }
128
+ // SECURITY: Validate prompt length
129
+ if (prompt.length > 10 * 1024 * 1024) {
130
+ throw new Error('Prompt exceeds maximum size (10MB)');
131
+ }
132
+ // Build content array with text and images
133
+ const content = [];
134
+ // Add prompt text first
135
+ content.push({
136
+ type: 'text',
137
+ text: prompt,
138
+ });
139
+ // Add each image
140
+ for (const image of images) {
141
+ // Validate media type
142
+ const mediaType = (image.mimeType || image.mediaType || 'image/png');
143
+ if (!['image/png', 'image/jpeg', 'image/webp', 'image/gif'].includes(mediaType)) {
144
+ throw new Error(`Unsupported image type: ${mediaType}`);
145
+ }
146
+ const data = image.data || image.base64 || '';
147
+ // SECURITY: Validate base64 data size (limit to 20MB per image)
148
+ if (data.length > 20 * 1024 * 1024) {
149
+ throw new Error('Image data exceeds maximum size (20MB)');
150
+ }
151
+ content.push({
152
+ type: 'image',
153
+ source: {
154
+ type: 'base64',
155
+ media_type: mediaType,
156
+ data: data,
157
+ },
158
+ });
159
+ // Add description if provided
160
+ if (image.description) {
161
+ content.push({
162
+ type: 'text',
163
+ text: `[Image: ${image.description}]`,
164
+ });
165
+ }
166
+ }
167
+ const response = await (0, provider_utils_js_1.withTimeout)(this.client.messages.create({
168
+ model: this.model,
169
+ max_tokens: options?.maxTokens || 4000,
170
+ temperature: options?.temperature,
171
+ top_p: options?.topP,
172
+ stop_sequences: options?.stopSequences,
173
+ system: options?.systemPrompt,
174
+ messages: [
175
+ {
176
+ role: 'user',
177
+ content,
178
+ },
179
+ ],
180
+ }), options?.timeout, 'analyzeImage');
181
+ const responseTime = Date.now() - startTime;
182
+ const text = this.extractTextFromResponse(response);
183
+ // SECURITY: Type-safe usage extraction
184
+ const usage = this.extractUsageFromResponse(response.usage);
185
+ const cost = this.calculateCost(usage, this.capabilities.costPer1MInputTokens, this.capabilities.costPer1MOutputTokens);
186
+ // Update stats
187
+ this.updateStats(usage, responseTime, cost);
188
+ return {
189
+ text,
190
+ usage,
191
+ cost,
192
+ metadata: {
193
+ model: this.model,
194
+ responseTimeMs: responseTime,
195
+ stopReason: response.stop_reason,
196
+ imageCount: images.length,
197
+ },
198
+ };
199
+ }
200
+ catch (error) {
201
+ this.stats.failedRequests++;
202
+ throw new provider_interface_js_1.LLMProviderError((0, provider_utils_js_1.sanitizeErrorMessage)(error, 'analyzeImage'), this.name, this.extractStatusCode(error), error);
203
+ }
204
+ }
205
+ async *streamText(prompt, options) {
206
+ try {
207
+ // SECURITY: Validate prompt length
208
+ if (prompt.length > 10 * 1024 * 1024) {
209
+ throw new Error('Prompt exceeds maximum size (10MB)');
210
+ }
211
+ const stream = await (0, provider_utils_js_1.withTimeout)(this.client.messages.create({
212
+ model: this.model,
213
+ max_tokens: options?.maxTokens || 4000,
214
+ temperature: options?.temperature,
215
+ top_p: options?.topP,
216
+ stop_sequences: options?.stopSequences,
217
+ system: options?.systemPrompt,
218
+ messages: [
219
+ {
220
+ role: 'user',
221
+ content: prompt,
222
+ },
223
+ ],
224
+ stream: true,
225
+ }), options?.timeout, 'streamText');
226
+ for await (const event of stream) {
227
+ if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {
228
+ yield event.delta.text;
229
+ }
230
+ }
231
+ // Note: Streaming doesn't provide detailed usage stats
232
+ // We increment request count but can't track exact tokens/cost
233
+ this.stats.requestCount++;
234
+ this.stats.lastUpdated = new Date();
235
+ }
236
+ catch (error) {
237
+ this.stats.failedRequests++;
238
+ throw new provider_interface_js_1.LLMProviderError((0, provider_utils_js_1.sanitizeErrorMessage)(error, 'streamText'), this.name, this.extractStatusCode(error), error);
239
+ }
240
+ }
241
+ extractTextFromResponse(response) {
242
+ const textBlocks = response.content.filter((block) => block.type === 'text');
243
+ return textBlocks.map((block) => {
244
+ if (block.type === 'text') {
245
+ return block.text;
246
+ }
247
+ return '';
248
+ }).join('\n');
249
+ }
250
+ /**
251
+ * SECURITY: Type-safe usage extraction
252
+ * Avoids unsafe `as any` casts
253
+ */
254
+ extractUsageFromResponse(usage) {
255
+ return {
256
+ inputTokens: usage.input_tokens || 0,
257
+ outputTokens: usage.output_tokens || 0,
258
+ totalTokens: (usage.input_tokens || 0) + (usage.output_tokens || 0),
259
+ cachedTokens: usage.cache_read_input_tokens ?? undefined,
260
+ };
261
+ }
262
+ /**
263
+ * SECURITY: Extract status code safely
264
+ */
265
+ extractStatusCode(error) {
266
+ if (error && typeof error === 'object') {
267
+ const err = error;
268
+ const status = err.status;
269
+ if (typeof status === 'number') {
270
+ return status;
271
+ }
272
+ }
273
+ return undefined;
274
+ }
275
+ /**
276
+ * Check if API key is valid and service is accessible
277
+ */
278
+ async checkHealth() {
279
+ try {
280
+ // Try a minimal request to verify API key
281
+ await (0, provider_utils_js_1.withTimeout)(this.client.messages.create({
282
+ model: this.model,
283
+ max_tokens: 10,
284
+ messages: [
285
+ {
286
+ role: 'user',
287
+ content: 'Hi',
288
+ },
289
+ ],
290
+ }), 5000, 'health check');
291
+ return {
292
+ healthy: true,
293
+ message: `Anthropic API is accessible`,
294
+ };
295
+ }
296
+ catch (error) {
297
+ return {
298
+ healthy: false,
299
+ message: `Anthropic API error: ${(0, provider_utils_js_1.sanitizeErrorMessage)(error, 'health check')}`,
300
+ };
301
+ }
302
+ }
303
+ }
304
+ exports.AnthropicProvider = AnthropicProvider;
305
+ /**
306
+ * Helper to check Anthropic setup
307
+ */
308
+ async function checkAnthropicSetup(apiKey) {
309
+ if (!apiKey) {
310
+ return {
311
+ valid: false,
312
+ message: 'No API key provided',
313
+ estimatedMonthlyCost: 'N/A',
314
+ };
315
+ }
316
+ try {
317
+ const provider = new AnthropicProvider({ apiKey });
318
+ const health = await provider.checkHealth();
319
+ return {
320
+ valid: health.healthy,
321
+ message: health.message,
322
+ estimatedMonthlyCost: '$30-80 for autonomous testing (24 cycles/day)',
323
+ };
324
+ }
325
+ catch (error) {
326
+ return {
327
+ valid: false,
328
+ message: `Setup check failed: ${(0, provider_utils_js_1.sanitizeErrorMessage)(error, 'setup check')}`,
329
+ estimatedMonthlyCost: 'N/A',
330
+ };
331
+ }
332
+ }
package/dist/api.d.ts ADDED
@@ -0,0 +1,48 @@
1
+ import { type ConfigOverrides } from './agent/config.js';
2
+ import { type PlanReport } from './agent/plan.js';
3
+ import type { ReportData } from './agent/report.js';
4
+ import { type FinalizeGeneratedTestsOptions, type FinalizeGeneratedTestsResult } from './agent/handoff.js';
5
+ import { type TraceabilityIngestOptions, type TraceabilityIngestResult } from './agent/traceability_ingest.js';
6
+ import { type TraceabilityCaptureResult } from './agent/traceability_capture.js';
7
+ export interface AgentApiOptions extends Omit<ConfigOverrides, 'mode'> {
8
+ cwd?: string;
9
+ configPath?: string;
10
+ apply?: boolean;
11
+ allowFallback?: boolean;
12
+ }
13
+ export interface AnalyzeResult {
14
+ report: ReportData;
15
+ reportPath: string;
16
+ }
17
+ export interface RecommendTestsResult extends AnalyzeResult {
18
+ plan: PlanReport;
19
+ planPath: string;
20
+ ciSummaryMarkdown: string;
21
+ ciSummaryPath: string;
22
+ }
23
+ export interface TraceabilityIngestApiOptions {
24
+ cwd?: string;
25
+ configPath?: string;
26
+ path?: string;
27
+ testsRoot?: string;
28
+ payload: unknown;
29
+ options?: TraceabilityIngestOptions;
30
+ }
31
+ export interface TraceabilityCaptureApiOptions {
32
+ cwd?: string;
33
+ configPath?: string;
34
+ path?: string;
35
+ testsRoot?: string;
36
+ reportPath: string;
37
+ sinceRef?: string;
38
+ outputPath?: string;
39
+ coverageMapPath?: string;
40
+ changedFilesPath?: string;
41
+ }
42
+ export declare function analyzeImpact(options?: AgentApiOptions): Promise<AnalyzeResult>;
43
+ export declare function findGaps(options?: AgentApiOptions): Promise<AnalyzeResult>;
44
+ export declare function recommendTests(options?: AgentApiOptions): Promise<RecommendTestsResult>;
45
+ export declare function handoffGeneratedTests(options: FinalizeGeneratedTestsOptions): FinalizeGeneratedTestsResult;
46
+ export declare function ingestTraceability(options: TraceabilityIngestApiOptions): TraceabilityIngestResult;
47
+ export declare function captureTraceability(options: TraceabilityCaptureApiOptions): TraceabilityCaptureResult;
48
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAKA,OAAO,EAAgB,KAAK,eAAe,EAAC,MAAM,mBAAmB,CAAC;AAEtE,OAAO,EAMH,KAAK,UAAU,EAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,mBAAmB,CAAC;AAElD,OAAO,EAAyB,KAAK,6BAA6B,EAAE,KAAK,4BAA4B,EAAC,MAAM,oBAAoB,CAAC;AACjI,OAAO,EAEH,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAChC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAGH,KAAK,yBAAyB,EACjC,MAAM,iCAAiC,CAAC;AAEzC,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAqB,SAAQ,aAAa;IACvD,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,4BAA4B;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,yBAAyB,CAAC;CACvC;AAED,MAAM,WAAW,6BAA6B;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AA0BD,wBAAsB,aAAa,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CAOzF;AAED,wBAAsB,QAAQ,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CAOpF;AAED,wBAAsB,cAAc,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAwBjG;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,6BAA6B,GAAG,4BAA4B,CAE1G;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,4BAA4B,GAAG,wBAAwB,CASlG;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,6BAA6B,GAAG,yBAAyB,CAkBrG"}
package/dist/api.js ADDED
@@ -0,0 +1,113 @@
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.analyzeImpact = analyzeImpact;
6
+ exports.findGaps = findGaps;
7
+ exports.recommendTests = recommendTests;
8
+ exports.handoffGeneratedTests = handoffGeneratedTests;
9
+ exports.ingestTraceability = ingestTraceability;
10
+ exports.captureTraceability = captureTraceability;
11
+ const fs_1 = require("fs");
12
+ const path_1 = require("path");
13
+ const config_js_1 = require("./agent/config.js");
14
+ const runner_js_1 = require("./agent/runner.js");
15
+ const plan_js_1 = require("./agent/plan.js");
16
+ const operational_insights_js_1 = require("./agent/operational_insights.js");
17
+ const handoff_js_1 = require("./agent/handoff.js");
18
+ const traceability_ingest_js_1 = require("./agent/traceability_ingest.js");
19
+ const traceability_capture_js_1 = require("./agent/traceability_capture.js");
20
+ function readReportJson(reportPath) {
21
+ if (!(0, fs_1.existsSync)(reportPath)) {
22
+ throw new Error(`Expected report not found: ${reportPath}`);
23
+ }
24
+ const raw = (0, fs_1.readFileSync)(reportPath, 'utf-8');
25
+ return JSON.parse(raw);
26
+ }
27
+ function resolveAgent(options, mode) {
28
+ const cwd = options.cwd || process.cwd();
29
+ const { config } = (0, config_js_1.resolveConfig)(cwd, options.configPath, {
30
+ ...options,
31
+ mode,
32
+ });
33
+ if (options.allowFallback) {
34
+ config.impact.allowFallback = true;
35
+ }
36
+ return config;
37
+ }
38
+ function reportPathFor(configPath, mode) {
39
+ return (0, path_1.join)(configPath, '.e2e-ai-agents', mode === 'impact' ? 'impact.json' : 'gap.json');
40
+ }
41
+ async function analyzeImpact(options = {}) {
42
+ const config = resolveAgent(options, 'impact');
43
+ await (0, runner_js_1.runImpact)(config, { apply: options.apply ?? false });
44
+ const reportRoot = config.testsRoot || config.path;
45
+ const reportPath = reportPathFor(reportRoot, 'impact');
46
+ const report = readReportJson(reportPath);
47
+ return { report, reportPath };
48
+ }
49
+ async function findGaps(options = {}) {
50
+ const config = resolveAgent(options, 'gap');
51
+ await (0, runner_js_1.runGap)(config, { apply: options.apply ?? false });
52
+ const reportRoot = config.testsRoot || config.path;
53
+ const reportPath = reportPathFor(reportRoot, 'gap');
54
+ const report = readReportJson(reportPath);
55
+ return { report, reportPath };
56
+ }
57
+ async function recommendTests(options = {}) {
58
+ const config = resolveAgent(options, 'impact');
59
+ await (0, runner_js_1.runImpact)(config, { apply: options.apply ?? false });
60
+ const reportRoot = config.testsRoot || config.path;
61
+ const impactPath = reportPathFor(reportRoot, 'impact');
62
+ const report = readReportJson(impactPath);
63
+ const basePlan = (0, plan_js_1.buildPlanFromImpactReport)(report, config.policy);
64
+ const withActions = (0, plan_js_1.attachDeveloperActions)(basePlan, {
65
+ appPath: config.path,
66
+ testsRoot: reportRoot,
67
+ sinceRef: config.git.since,
68
+ });
69
+ const plan = (0, operational_insights_js_1.applyOperationalInsights)(withActions, reportRoot);
70
+ const planPath = (0, plan_js_1.writePlanReport)(reportRoot, plan);
71
+ const ciSummaryMarkdown = (0, plan_js_1.renderCiSummaryMarkdown)(plan);
72
+ const ciSummaryPath = (0, plan_js_1.writeCiSummary)(reportRoot, ciSummaryMarkdown);
73
+ return {
74
+ report,
75
+ reportPath: impactPath,
76
+ plan,
77
+ planPath,
78
+ ciSummaryMarkdown,
79
+ ciSummaryPath,
80
+ };
81
+ }
82
+ function handoffGeneratedTests(options) {
83
+ return (0, handoff_js_1.finalizeGeneratedTests)(options);
84
+ }
85
+ function ingestTraceability(options) {
86
+ const cwd = options.cwd || process.cwd();
87
+ const { config } = (0, config_js_1.resolveConfig)(cwd, options.configPath, {
88
+ path: options.path,
89
+ testsRoot: options.testsRoot,
90
+ mode: 'impact',
91
+ });
92
+ const reportRoot = config.testsRoot || config.path;
93
+ return (0, traceability_ingest_js_1.ingestTraceabilityInput)(reportRoot, config.impact.traceability, options.payload, options.options);
94
+ }
95
+ function captureTraceability(options) {
96
+ const cwd = options.cwd || process.cwd();
97
+ const { config } = (0, config_js_1.resolveConfig)(cwd, options.configPath, {
98
+ path: options.path,
99
+ testsRoot: options.testsRoot,
100
+ mode: 'impact',
101
+ });
102
+ const reportRoot = config.testsRoot || config.path;
103
+ const captureOptions = {
104
+ appPath: config.path,
105
+ testsRoot: reportRoot,
106
+ reportPath: options.reportPath,
107
+ sinceRef: options.sinceRef || config.git.since,
108
+ outputPath: options.outputPath,
109
+ coverageMapPath: options.coverageMapPath,
110
+ changedFilesPath: options.changedFilesPath,
111
+ };
112
+ return (0, traceability_capture_js_1.captureTraceabilityInput)(captureOptions);
113
+ }
@@ -0,0 +1,53 @@
1
+ import type { GenerateOptions, ImageInput, LLMProvider, LLMResponse, ProviderCapabilities, ProviderUsageStats } from './provider_interface.js';
2
+ /**
3
+ * Abstract base class for all LLM providers
4
+ * Eliminates 240+ lines of duplicate stats management code
5
+ * Provides common functionality for token tracking, cost calculation, and stats management
6
+ */
7
+ export declare abstract class BaseProvider implements LLMProvider {
8
+ abstract name: string;
9
+ abstract capabilities: ProviderCapabilities;
10
+ protected stats: ProviderUsageStats;
11
+ constructor();
12
+ /**
13
+ * Initialize stats object with default values
14
+ */
15
+ protected initializeStats(): void;
16
+ /**
17
+ * Update stats with new usage data
18
+ * Maintains rolling average for response time
19
+ */
20
+ protected updateStats(usage: {
21
+ inputTokens: number;
22
+ outputTokens: number;
23
+ totalTokens: number;
24
+ }, responseTime: number, cost: number): void;
25
+ /**
26
+ * Get a copy of current usage stats
27
+ */
28
+ getUsageStats(): ProviderUsageStats;
29
+ /**
30
+ * Reset all usage stats to initial state
31
+ */
32
+ resetUsageStats(): void;
33
+ /**
34
+ * Abstract methods that must be implemented by subclasses
35
+ */
36
+ abstract generateText(prompt: string, options?: GenerateOptions): Promise<LLMResponse>;
37
+ abstract analyzeImage(images: ImageInput[], prompt: string, options?: GenerateOptions): Promise<LLMResponse>;
38
+ abstract streamText(prompt: string, options?: GenerateOptions): AsyncGenerator<string, void, unknown>;
39
+ abstract checkHealth(): Promise<{
40
+ healthy: boolean;
41
+ message: string;
42
+ }>;
43
+ /**
44
+ * Calculate cost for token usage, accounting for prompt caching discounts
45
+ * Cached tokens cost 90% less than regular tokens
46
+ */
47
+ protected calculateCost(usage: {
48
+ inputTokens: number;
49
+ outputTokens: number;
50
+ cachedTokens?: number;
51
+ }, costPer1MInputTokens: number, costPer1MOutputTokens: number): number;
52
+ }
53
+ //# sourceMappingURL=base_provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base_provider.d.ts","sourceRoot":"","sources":["../src/base_provider.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACR,eAAe,EACf,UAAU,EACV,WAAW,EACX,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EACrB,MAAM,yBAAyB,CAAC;AAEjC;;;;GAIG;AACH,8BAAsB,YAAa,YAAW,WAAW;IACrD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAAC;IAE5C,SAAS,CAAC,KAAK,EAAG,kBAAkB,CAAC;;IAMrC;;OAEG;IACH,SAAS,CAAC,eAAe,IAAI,IAAI;IAcjC;;;OAGG;IACH,SAAS,CAAC,WAAW,CACjB,KAAK,EAAE;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAC,EACvE,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,GACb,IAAI;IAeP;;OAEG;IACH,aAAa,IAAI,kBAAkB;IAInC;;OAEG;IACH,eAAe,IAAI,IAAI;IAIvB;;OAEG;IACH,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC;IACtF,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC;IAC5G,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC;IACrG,QAAQ,CAAC,WAAW,IAAI,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAC;IAEpE;;;OAGG;IACH,SAAS,CAAC,aAAa,CACnB,KAAK,EAAE;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAC,EACzE,oBAAoB,EAAE,MAAM,EAC5B,qBAAqB,EAAE,MAAM,GAC9B,MAAM;CAmBZ"}
@@ -0,0 +1,81 @@
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.BaseProvider = void 0;
6
+ /**
7
+ * Abstract base class for all LLM providers
8
+ * Eliminates 240+ lines of duplicate stats management code
9
+ * Provides common functionality for token tracking, cost calculation, and stats management
10
+ */
11
+ class BaseProvider {
12
+ constructor() {
13
+ this.initializeStats();
14
+ }
15
+ /**
16
+ * Initialize stats object with default values
17
+ */
18
+ initializeStats() {
19
+ this.stats = {
20
+ requestCount: 0,
21
+ totalInputTokens: 0,
22
+ totalOutputTokens: 0,
23
+ totalTokens: 0,
24
+ totalCost: 0,
25
+ averageResponseTimeMs: 0,
26
+ failedRequests: 0,
27
+ startTime: new Date(),
28
+ lastUpdated: new Date(),
29
+ };
30
+ }
31
+ /**
32
+ * Update stats with new usage data
33
+ * Maintains rolling average for response time
34
+ */
35
+ updateStats(usage, responseTime, cost) {
36
+ this.stats.requestCount++;
37
+ this.stats.totalInputTokens += usage.inputTokens;
38
+ this.stats.totalOutputTokens += usage.outputTokens;
39
+ this.stats.totalTokens += usage.totalTokens;
40
+ this.stats.totalCost += cost;
41
+ // Update rolling average response time
42
+ const totalRequests = this.stats.requestCount;
43
+ this.stats.averageResponseTimeMs =
44
+ (this.stats.averageResponseTimeMs * (totalRequests - 1) + responseTime) / totalRequests;
45
+ this.stats.lastUpdated = new Date();
46
+ }
47
+ /**
48
+ * Get a copy of current usage stats
49
+ */
50
+ getUsageStats() {
51
+ return { ...this.stats };
52
+ }
53
+ /**
54
+ * Reset all usage stats to initial state
55
+ */
56
+ resetUsageStats() {
57
+ this.initializeStats();
58
+ }
59
+ /**
60
+ * Calculate cost for token usage, accounting for prompt caching discounts
61
+ * Cached tokens cost 90% less than regular tokens
62
+ */
63
+ calculateCost(usage, costPer1MInputTokens, costPer1MOutputTokens) {
64
+ // Calculate input token cost
65
+ let inputCost = 0;
66
+ // Cached tokens cost 90% less
67
+ if (usage.cachedTokens) {
68
+ const cachedCost = (usage.cachedTokens / 1000000) * (costPer1MInputTokens * 0.1);
69
+ const uncachedInputTokens = usage.inputTokens - usage.cachedTokens;
70
+ const uncachedCost = (uncachedInputTokens / 1000000) * costPer1MInputTokens;
71
+ inputCost = cachedCost + uncachedCost;
72
+ }
73
+ else {
74
+ inputCost = (usage.inputTokens / 1000000) * costPer1MInputTokens;
75
+ }
76
+ // Calculate output token cost
77
+ const outputCost = (usage.outputTokens / 1000000) * costPer1MOutputTokens;
78
+ return inputCost + outputCost;
79
+ }
80
+ }
81
+ exports.BaseProvider = BaseProvider;
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}