@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,272 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ import { LLMProviderError, UnsupportedCapabilityError } from './provider_interface.js';
4
+ import { sanitizeErrorMessage, validateAndSanitizeUrl } from './provider_utils.js';
5
+ import { BaseProvider } from './base_provider.js';
6
+ import { logger } from './logger.js';
7
+ function normalizeUrl(baseUrl, pathSuffix) {
8
+ const trimmed = baseUrl.replace(/\/+$/, '');
9
+ if (trimmed.endsWith(pathSuffix)) {
10
+ return trimmed;
11
+ }
12
+ return `${trimmed}${pathSuffix}`;
13
+ }
14
+ async function postJson(url, headers, body, timeoutMs, context) {
15
+ const controller = new AbortController();
16
+ const timer = timeoutMs ? setTimeout(() => controller.abort(), timeoutMs) : undefined;
17
+ try {
18
+ const response = await fetch(url, {
19
+ method: 'POST',
20
+ headers: {
21
+ 'content-type': 'application/json',
22
+ ...headers,
23
+ },
24
+ body: JSON.stringify(body),
25
+ signal: controller.signal,
26
+ });
27
+ if (!response.ok) {
28
+ throw new Error(`HTTP ${response.status}`);
29
+ }
30
+ return (await response.json());
31
+ }
32
+ catch (error) {
33
+ if (error instanceof Error && error.name === 'AbortError') {
34
+ throw new Error(`Request timeout (${context})`);
35
+ }
36
+ throw error;
37
+ }
38
+ finally {
39
+ if (timer) {
40
+ clearTimeout(timer);
41
+ }
42
+ }
43
+ }
44
+ export class CustomProvider extends BaseProvider {
45
+ constructor(config) {
46
+ super();
47
+ this.name = 'custom';
48
+ const validation = validateAndSanitizeUrl(config.baseUrl);
49
+ if (!validation.valid) {
50
+ throw new Error(`Invalid base URL: ${validation.warning}`);
51
+ }
52
+ if (validation.warning) {
53
+ logger.warn(`HTTPS required for remote URLs: ${validation.warning}`);
54
+ }
55
+ this.config = config;
56
+ this.capabilities = {
57
+ vision: config.requestFormat !== 'custom',
58
+ streaming: false,
59
+ maxTokens: 0,
60
+ costPer1MInputTokens: 0,
61
+ costPer1MOutputTokens: 0,
62
+ supportsTools: false,
63
+ supportsPromptCaching: false,
64
+ typicalResponseTimeMs: 0,
65
+ };
66
+ }
67
+ async generateText(prompt, options) {
68
+ const startTime = Date.now();
69
+ try {
70
+ if (prompt.length > 10 * 1024 * 1024) {
71
+ throw new Error('Prompt exceeds maximum size (10MB)');
72
+ }
73
+ const response = await this.dispatchRequest(prompt, options);
74
+ const responseTime = Date.now() - startTime;
75
+ const text = response.text;
76
+ const usage = response.usage;
77
+ const cost = response.cost;
78
+ this.updateStats(usage, responseTime, cost);
79
+ return {
80
+ text,
81
+ usage,
82
+ cost,
83
+ metadata: response.metadata,
84
+ };
85
+ }
86
+ catch (error) {
87
+ this.stats.failedRequests++;
88
+ throw new LLMProviderError(sanitizeErrorMessage(error, 'generateText'), this.name, undefined, error);
89
+ }
90
+ }
91
+ async analyzeImage(images, prompt, options) {
92
+ if (this.config.requestFormat === 'custom') {
93
+ throw new UnsupportedCapabilityError(this.name, 'vision');
94
+ }
95
+ const startTime = Date.now();
96
+ try {
97
+ if (images.length === 0 || images.length > 20) {
98
+ throw new Error('Image count must be between 1 and 20');
99
+ }
100
+ if (prompt.length > 10 * 1024 * 1024) {
101
+ throw new Error('Prompt exceeds maximum size (10MB)');
102
+ }
103
+ const response = await this.dispatchRequest(prompt, options, images);
104
+ const responseTime = Date.now() - startTime;
105
+ const text = response.text;
106
+ const usage = response.usage;
107
+ const cost = response.cost;
108
+ this.updateStats(usage, responseTime, cost);
109
+ return {
110
+ text,
111
+ usage,
112
+ cost,
113
+ metadata: response.metadata,
114
+ };
115
+ }
116
+ catch (error) {
117
+ this.stats.failedRequests++;
118
+ throw new LLMProviderError(sanitizeErrorMessage(error, 'analyzeImage'), this.name, undefined, error);
119
+ }
120
+ }
121
+ async dispatchRequest(prompt, options, images) {
122
+ switch (this.config.requestFormat) {
123
+ case 'openai':
124
+ return this.requestOpenAI(prompt, options, images);
125
+ case 'anthropic':
126
+ return this.requestAnthropic(prompt, options, images);
127
+ case 'custom':
128
+ return this.requestCustom(prompt, options);
129
+ default:
130
+ throw new Error(`Unsupported request format: ${this.config.requestFormat}`);
131
+ }
132
+ }
133
+ async requestOpenAI(prompt, options, images) {
134
+ const url = normalizeUrl(this.config.baseUrl, '/chat/completions');
135
+ const messages = [];
136
+ if (options?.systemPrompt) {
137
+ messages.push({ role: 'system', content: options.systemPrompt });
138
+ }
139
+ if (images && images.length > 0) {
140
+ const content = [
141
+ { type: 'text', text: prompt },
142
+ ];
143
+ for (const image of images) {
144
+ const mediaType = (image.mimeType || image.mediaType || 'image/png');
145
+ if (!['image/png', 'image/jpeg', 'image/webp'].includes(mediaType)) {
146
+ throw new Error(`Unsupported image type: ${mediaType}`);
147
+ }
148
+ const data = image.data || image.base64 || '';
149
+ if (data.length > 20 * 1024 * 1024) {
150
+ throw new Error('Image data exceeds maximum size (20MB)');
151
+ }
152
+ content.push({
153
+ type: 'image_url',
154
+ image_url: { url: `data:${mediaType};base64,${data}` },
155
+ });
156
+ if (image.description) {
157
+ content.push({ type: 'text', text: `[Image: ${image.description}]` });
158
+ }
159
+ }
160
+ messages.push({ role: 'user', content });
161
+ }
162
+ else {
163
+ messages.push({ role: 'user', content: prompt });
164
+ }
165
+ const body = {
166
+ model: this.config.model,
167
+ messages,
168
+ max_tokens: options?.maxTokens,
169
+ temperature: options?.temperature,
170
+ top_p: options?.topP,
171
+ stop: options?.stopSequences,
172
+ };
173
+ const response = await postJson(url, this.config.auth, body, options?.timeout, 'openai');
174
+ const text = response.choices?.[0]?.message?.content || '';
175
+ const usage = {
176
+ inputTokens: response.usage?.prompt_tokens || 0,
177
+ outputTokens: response.usage?.completion_tokens || 0,
178
+ totalTokens: response.usage?.total_tokens || 0,
179
+ };
180
+ return {
181
+ text,
182
+ usage,
183
+ cost: 0,
184
+ metadata: {
185
+ finishReason: response.choices?.[0]?.finish_reason,
186
+ },
187
+ };
188
+ }
189
+ async requestAnthropic(prompt, options, images) {
190
+ const url = normalizeUrl(this.config.baseUrl, '/messages');
191
+ const content = [
192
+ { type: 'text', text: prompt },
193
+ ];
194
+ if (images && images.length > 0) {
195
+ for (const image of images) {
196
+ const mediaType = (image.mimeType || image.mediaType || 'image/png');
197
+ if (!['image/png', 'image/jpeg', 'image/webp', 'image/gif'].includes(mediaType)) {
198
+ throw new Error(`Unsupported image type: ${mediaType}`);
199
+ }
200
+ const data = image.data || image.base64 || '';
201
+ if (data.length > 20 * 1024 * 1024) {
202
+ throw new Error('Image data exceeds maximum size (20MB)');
203
+ }
204
+ content.push({
205
+ type: 'image',
206
+ source: {
207
+ type: 'base64',
208
+ media_type: mediaType,
209
+ data,
210
+ },
211
+ });
212
+ if (image.description) {
213
+ content.push({ type: 'text', text: `[Image: ${image.description}]` });
214
+ }
215
+ }
216
+ }
217
+ const body = {
218
+ model: this.config.model,
219
+ max_tokens: options?.maxTokens || 4000,
220
+ temperature: options?.temperature,
221
+ top_p: options?.topP,
222
+ stop_sequences: options?.stopSequences,
223
+ system: options?.systemPrompt,
224
+ messages: [
225
+ {
226
+ role: 'user',
227
+ content,
228
+ },
229
+ ],
230
+ };
231
+ const response = await postJson(url, this.config.auth, body, options?.timeout, 'anthropic');
232
+ const text = (response.content || []).map((block) => block.text).join('\n');
233
+ const usage = {
234
+ inputTokens: response.usage?.input_tokens || 0,
235
+ outputTokens: response.usage?.output_tokens || 0,
236
+ totalTokens: (response.usage?.input_tokens || 0) + (response.usage?.output_tokens || 0),
237
+ };
238
+ return {
239
+ text,
240
+ usage,
241
+ cost: 0,
242
+ metadata: {
243
+ stopReason: response.stop_reason,
244
+ },
245
+ };
246
+ }
247
+ async requestCustom(prompt, options) {
248
+ if (!this.config.transformRequest || !this.config.transformResponse) {
249
+ throw new Error('Custom providers require transformRequest and transformResponse');
250
+ }
251
+ const body = this.config.transformRequest(prompt, options);
252
+ const response = await postJson(this.config.baseUrl, this.config.auth, body, options?.timeout, 'custom');
253
+ const transformed = this.config.transformResponse(response);
254
+ return {
255
+ text: transformed.text,
256
+ usage: transformed.usage,
257
+ cost: transformed.cost,
258
+ metadata: transformed.metadata,
259
+ };
260
+ }
261
+ // CustomProvider doesn't support streaming
262
+ async *streamText() {
263
+ throw new Error('Streaming not supported for custom providers');
264
+ }
265
+ // CustomProvider doesn't have built-in health checks
266
+ async checkHealth() {
267
+ return {
268
+ healthy: true,
269
+ message: 'Custom provider configured',
270
+ };
271
+ }
272
+ }
@@ -0,0 +1,50 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ /**
4
+ * Autonomous E2E Testing System
5
+ *
6
+ * A specification-driven testing system that bridges PDF/Markdown specs
7
+ * with Playwright's native agents for test planning, generation, and healing.
8
+ *
9
+ * Quick Start:
10
+ * ```typescript
11
+ * import {SpecBridge, createAnthropicBridge} from '@mattermost/playwright-lib/autonomous';
12
+ *
13
+ * // Convert a specification to Playwright-compatible markdown
14
+ * const bridge = createAnthropicBridge(process.env.ANTHROPIC_API_KEY);
15
+ * const result = await bridge.convertToPlaywrightSpecs('spec.pdf', 'specs/');
16
+ *
17
+ * // Then use Playwright agents:
18
+ * // @planner explore http://localhost:8065
19
+ * // @generator create tests from specs/
20
+ * // @healer fix failing tests
21
+ * ```
22
+ *
23
+ * Architecture:
24
+ * - SpecificationParser: Parses PDF/MD/JSON specs into structured format
25
+ * - SpecBridge: Converts specs to Playwright Agent-compatible markdown
26
+ * - LLM Providers: Pluggable AI providers (Anthropic, Ollama, OpenAI)
27
+ *
28
+ * The heavy lifting (test generation, execution, healing) is delegated to
29
+ * Playwright's built-in agents which are production-ready and maintained
30
+ * by the Playwright team.
31
+ */
32
+ // Core Components
33
+ export { SpecificationParser } from './spec_parser.js';
34
+ // LLM Providers (re-exported from parent package)
35
+ export { LLMProviderFactory } from '../provider_factory.js';
36
+ export { OllamaProvider } from '../ollama_provider.js';
37
+ export { AnthropicProvider } from '../anthropic_provider.js';
38
+ /**
39
+ * Version info
40
+ */
41
+ export const VERSION = '2.0.0';
42
+ export const SUPPORTED_PLAYWRIGHT_VERSION = '1.56.0';
43
+ /**
44
+ * Feature flags
45
+ */
46
+ export const FEATURES = {
47
+ LLM_AGNOSTIC: true,
48
+ SPECIFICATION_DRIVEN: true,
49
+ PLAYWRIGHT_AGENTS: true,
50
+ };