@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.
- package/LICENSE +168 -0
- package/README.md +620 -0
- package/dist/agent/analysis.d.ts +62 -0
- package/dist/agent/analysis.d.ts.map +1 -0
- package/dist/agent/analysis.js +292 -0
- package/dist/agent/blast_radius.d.ts +4 -0
- package/dist/agent/blast_radius.d.ts.map +1 -0
- package/dist/agent/blast_radius.js +37 -0
- package/dist/agent/cache_utils.d.ts +38 -0
- package/dist/agent/cache_utils.d.ts.map +1 -0
- package/dist/agent/cache_utils.js +67 -0
- package/dist/agent/config.d.ts +148 -0
- package/dist/agent/config.d.ts.map +1 -0
- package/dist/agent/config.js +640 -0
- package/dist/agent/dependency_graph.d.ts +14 -0
- package/dist/agent/dependency_graph.d.ts.map +1 -0
- package/dist/agent/dependency_graph.js +227 -0
- package/dist/agent/feedback.d.ts +55 -0
- package/dist/agent/feedback.d.ts.map +1 -0
- package/dist/agent/feedback.js +257 -0
- package/dist/agent/flags.d.ts +23 -0
- package/dist/agent/flags.d.ts.map +1 -0
- package/dist/agent/flags.js +171 -0
- package/dist/agent/flow_catalog.d.ts +25 -0
- package/dist/agent/flow_catalog.d.ts.map +1 -0
- package/dist/agent/flow_catalog.js +106 -0
- package/dist/agent/flow_mapping.d.ts +10 -0
- package/dist/agent/flow_mapping.d.ts.map +1 -0
- package/dist/agent/flow_mapping.js +84 -0
- package/dist/agent/framework.d.ts +13 -0
- package/dist/agent/framework.d.ts.map +1 -0
- package/dist/agent/framework.js +149 -0
- package/dist/agent/gap_suggestions.d.ts +14 -0
- package/dist/agent/gap_suggestions.d.ts.map +1 -0
- package/dist/agent/gap_suggestions.js +101 -0
- package/dist/agent/generator.d.ts +10 -0
- package/dist/agent/generator.d.ts.map +1 -0
- package/dist/agent/generator.js +115 -0
- package/dist/agent/git.d.ts +11 -0
- package/dist/agent/git.d.ts.map +1 -0
- package/dist/agent/git.js +90 -0
- package/dist/agent/handoff.d.ts +22 -0
- package/dist/agent/handoff.d.ts.map +1 -0
- package/dist/agent/handoff.js +180 -0
- package/dist/agent/impact-analyzer.d.ts +114 -0
- package/dist/agent/impact-analyzer.d.ts.map +1 -0
- package/dist/agent/impact-analyzer.js +557 -0
- package/dist/agent/index.d.ts +21 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +38 -0
- package/dist/agent/model-router.d.ts +57 -0
- package/dist/agent/model-router.d.ts.map +1 -0
- package/dist/agent/model-router.js +154 -0
- package/dist/agent/operational_insights.d.ts +41 -0
- package/dist/agent/operational_insights.d.ts.map +1 -0
- package/dist/agent/operational_insights.js +126 -0
- package/dist/agent/pipeline.d.ts +23 -0
- package/dist/agent/pipeline.d.ts.map +1 -0
- package/dist/agent/pipeline.js +609 -0
- package/dist/agent/plan.d.ts +91 -0
- package/dist/agent/plan.d.ts.map +1 -0
- package/dist/agent/plan.js +331 -0
- package/dist/agent/playwright_report.d.ts +8 -0
- package/dist/agent/playwright_report.d.ts.map +1 -0
- package/dist/agent/playwright_report.js +126 -0
- package/dist/agent/report-generator.d.ts +24 -0
- package/dist/agent/report-generator.d.ts.map +1 -0
- package/dist/agent/report-generator.js +250 -0
- package/dist/agent/report.d.ts +81 -0
- package/dist/agent/report.d.ts.map +1 -0
- package/dist/agent/report.js +147 -0
- package/dist/agent/runner.d.ts +7 -0
- package/dist/agent/runner.d.ts.map +1 -0
- package/dist/agent/runner.js +576 -0
- package/dist/agent/selectors.d.ts +10 -0
- package/dist/agent/selectors.d.ts.map +1 -0
- package/dist/agent/selectors.js +75 -0
- package/dist/agent/spec-bridge.d.ts +101 -0
- package/dist/agent/spec-bridge.d.ts.map +1 -0
- package/dist/agent/spec-bridge.js +273 -0
- package/dist/agent/spec-builder.d.ts +102 -0
- package/dist/agent/spec-builder.d.ts.map +1 -0
- package/dist/agent/spec-builder.js +273 -0
- package/dist/agent/subsystem_risk.d.ts +23 -0
- package/dist/agent/subsystem_risk.d.ts.map +1 -0
- package/dist/agent/subsystem_risk.js +207 -0
- package/dist/agent/telemetry.d.ts +84 -0
- package/dist/agent/telemetry.d.ts.map +1 -0
- package/dist/agent/telemetry.js +220 -0
- package/dist/agent/test_path.d.ts +2 -0
- package/dist/agent/test_path.d.ts.map +1 -0
- package/dist/agent/test_path.js +23 -0
- package/dist/agent/tests.d.ts +18 -0
- package/dist/agent/tests.d.ts.map +1 -0
- package/dist/agent/tests.js +106 -0
- package/dist/agent/traceability.d.ts +22 -0
- package/dist/agent/traceability.d.ts.map +1 -0
- package/dist/agent/traceability.js +183 -0
- package/dist/agent/traceability_capture.d.ts +18 -0
- package/dist/agent/traceability_capture.d.ts.map +1 -0
- package/dist/agent/traceability_capture.js +313 -0
- package/dist/agent/traceability_ingest.d.ts +21 -0
- package/dist/agent/traceability_ingest.d.ts.map +1 -0
- package/dist/agent/traceability_ingest.js +237 -0
- package/dist/agent/utils.d.ts +13 -0
- package/dist/agent/utils.d.ts.map +1 -0
- package/dist/agent/utils.js +152 -0
- package/dist/agent/validators/selector-validator.d.ts +74 -0
- package/dist/agent/validators/selector-validator.d.ts.map +1 -0
- package/dist/agent/validators/selector-validator.js +165 -0
- package/dist/anthropic_provider.d.ts +65 -0
- package/dist/anthropic_provider.d.ts.map +1 -0
- package/dist/anthropic_provider.js +332 -0
- package/dist/api.d.ts +48 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +113 -0
- package/dist/base_provider.d.ts +53 -0
- package/dist/base_provider.d.ts.map +1 -0
- package/dist/base_provider.js +81 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +843 -0
- package/dist/custom_provider.d.ts +20 -0
- package/dist/custom_provider.d.ts.map +1 -0
- package/dist/custom_provider.js +276 -0
- package/dist/e2e-test-gen/index.d.ts +51 -0
- package/dist/e2e-test-gen/index.d.ts.map +1 -0
- package/dist/e2e-test-gen/index.js +57 -0
- package/dist/e2e-test-gen/spec_parser.d.ts +142 -0
- package/dist/e2e-test-gen/spec_parser.d.ts.map +1 -0
- package/dist/e2e-test-gen/spec_parser.js +786 -0
- package/dist/e2e-test-gen/types.d.ts +185 -0
- package/dist/e2e-test-gen/types.d.ts.map +1 -0
- package/dist/e2e-test-gen/types.js +4 -0
- package/dist/esm/agent/analysis.js +287 -0
- package/dist/esm/agent/blast_radius.js +34 -0
- package/dist/esm/agent/cache_utils.js +63 -0
- package/dist/esm/agent/config.js +637 -0
- package/dist/esm/agent/dependency_graph.js +224 -0
- package/dist/esm/agent/feedback.js +253 -0
- package/dist/esm/agent/flags.js +160 -0
- package/dist/esm/agent/flow_catalog.js +103 -0
- package/dist/esm/agent/flow_mapping.js +81 -0
- package/dist/esm/agent/framework.js +145 -0
- package/dist/esm/agent/gap_suggestions.js +98 -0
- package/dist/esm/agent/generator.js +112 -0
- package/dist/esm/agent/git.js +87 -0
- package/dist/esm/agent/handoff.js +177 -0
- package/dist/esm/agent/impact-analyzer.js +548 -0
- package/dist/esm/agent/index.js +22 -0
- package/dist/esm/agent/model-router.js +150 -0
- package/dist/esm/agent/operational_insights.js +123 -0
- package/dist/esm/agent/pipeline.js +605 -0
- package/dist/esm/agent/plan.js +324 -0
- package/dist/esm/agent/playwright_report.js +123 -0
- package/dist/esm/agent/report-generator.js +247 -0
- package/dist/esm/agent/report.js +144 -0
- package/dist/esm/agent/runner.js +572 -0
- package/dist/esm/agent/selectors.js +71 -0
- package/dist/esm/agent/spec-bridge.js +267 -0
- package/dist/esm/agent/spec-builder.js +267 -0
- package/dist/esm/agent/subsystem_risk.js +204 -0
- package/dist/esm/agent/telemetry.js +216 -0
- package/dist/esm/agent/test_path.js +20 -0
- package/dist/esm/agent/tests.js +101 -0
- package/dist/esm/agent/traceability.js +180 -0
- package/dist/esm/agent/traceability_capture.js +310 -0
- package/dist/esm/agent/traceability_ingest.js +234 -0
- package/dist/esm/agent/utils.js +138 -0
- package/dist/esm/agent/validators/selector-validator.js +160 -0
- package/dist/esm/anthropic_provider.js +324 -0
- package/dist/esm/api.js +105 -0
- package/dist/esm/base_provider.js +77 -0
- package/dist/esm/cli.js +841 -0
- package/dist/esm/custom_provider.js +272 -0
- package/dist/esm/e2e-test-gen/index.js +50 -0
- package/dist/esm/e2e-test-gen/spec_parser.js +782 -0
- package/dist/esm/e2e-test-gen/types.js +3 -0
- package/dist/esm/index.js +16 -0
- package/dist/esm/logger.js +89 -0
- package/dist/esm/mcp-server.js +465 -0
- package/dist/esm/ollama_provider.js +300 -0
- package/dist/esm/openai_provider.js +242 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/plan-and-test-constants.js +126 -0
- package/dist/esm/provider_factory.js +336 -0
- package/dist/esm/provider_interface.js +23 -0
- package/dist/esm/provider_utils.js +96 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/logger.d.ts +23 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +93 -0
- package/dist/mcp-server.d.ts +35 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +469 -0
- package/dist/ollama_provider.d.ts +65 -0
- package/dist/ollama_provider.d.ts.map +1 -0
- package/dist/ollama_provider.js +308 -0
- package/dist/openai_provider.d.ts +23 -0
- package/dist/openai_provider.d.ts.map +1 -0
- package/dist/openai_provider.js +250 -0
- package/dist/plan-and-test-constants.d.ts +110 -0
- package/dist/plan-and-test-constants.d.ts.map +1 -0
- package/dist/plan-and-test-constants.js +132 -0
- package/dist/provider_factory.d.ts +99 -0
- package/dist/provider_factory.d.ts.map +1 -0
- package/dist/provider_factory.js +341 -0
- package/dist/provider_interface.d.ts +358 -0
- package/dist/provider_interface.d.ts.map +1 -0
- package/dist/provider_interface.js +28 -0
- package/dist/provider_utils.d.ts +39 -0
- package/dist/provider_utils.d.ts.map +1 -0
- package/dist/provider_utils.js +103 -0
- package/package.json +101 -0
- package/schemas/gap.schema.json +18 -0
- package/schemas/impact.schema.json +418 -0
- package/schemas/plan.schema.json +285 -0
- package/schemas/subsystem-risk-map.schema.json +62 -0
- 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
|
+
};
|