@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,273 @@
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.SpecBridge = void 0;
6
+ exports.createAnthropicBridge = createAnthropicBridge;
7
+ exports.createOllamaBridge = createOllamaBridge;
8
+ /**
9
+ * Spec Bridge - Bridge between PDF specs and Playwright Agent workflow
10
+ *
11
+ * This module converts specification documents (PDF, Markdown, JSON) into
12
+ * Playwright-compatible markdown files that can be consumed by Playwright's
13
+ * native agents (Planner, Generator, Healer).
14
+ *
15
+ * Flow: PDF → SpecParser → Markdown specs → Playwright Planner
16
+ *
17
+ * The Playwright agents (available in Playwright 1.56+) provide production-ready:
18
+ * - Test planning and exploration
19
+ * - Test code generation
20
+ * - Automatic test healing
21
+ *
22
+ * Usage:
23
+ * ```typescript
24
+ * const bridge = new SpecBridge({type: 'anthropic', apiKey: process.env.ANTHROPIC_API_KEY});
25
+ * const specPaths = await bridge.convertToPlaywrightSpecs('spec.pdf', 'specs/');
26
+ * // Now use Playwright agents: @planner, @generator, @healer
27
+ * ```
28
+ */
29
+ const fs_1 = require("fs");
30
+ const path_1 = require("path");
31
+ const provider_factory_js_1 = require("../provider_factory.js");
32
+ const spec_parser_js_1 = require("../e2e-test-gen/spec_parser.js");
33
+ /**
34
+ * Bridge between PDF/JSON specs and Playwright Agent workflow
35
+ *
36
+ * Converts specification documents into Playwright-compatible markdown
37
+ * that can be consumed by Playwright's native agents.
38
+ */
39
+ class SpecBridge {
40
+ constructor(config) {
41
+ // Handle both single provider and hybrid config
42
+ let llmProvider;
43
+ if ('primary' in config.llmConfig) {
44
+ // It's a HybridConfig
45
+ llmProvider = provider_factory_js_1.LLMProviderFactory.createHybrid(config.llmConfig);
46
+ }
47
+ else {
48
+ // It's a ProviderConfig
49
+ llmProvider = provider_factory_js_1.LLMProviderFactory.create(config.llmConfig);
50
+ }
51
+ this.parser = new spec_parser_js_1.SpecificationParser(llmProvider);
52
+ this.outputDir = config.outputDir || 'specs';
53
+ this.overwrite = config.overwrite !== false;
54
+ }
55
+ /**
56
+ * Convert a specification file to Playwright-compatible markdown specs
57
+ *
58
+ * @param inputPath - Path to the input specification (PDF, MD, or JSON)
59
+ * @param outputDir - Optional override for output directory
60
+ * @returns Conversion result with paths and metadata
61
+ */
62
+ async convertToPlaywrightSpecs(inputPath, outputDir) {
63
+ /* eslint-disable no-console */
64
+ const targetDir = outputDir || this.outputDir;
65
+ const warnings = [];
66
+ console.log(`Converting specification: ${inputPath}`);
67
+ // Parse the specification
68
+ const specs = await this.parser.parse(inputPath, 'file');
69
+ if (specs.length === 0) {
70
+ warnings.push('No features extracted from specification');
71
+ return {
72
+ specPaths: [],
73
+ features: [],
74
+ totalScenarios: 0,
75
+ warnings,
76
+ };
77
+ }
78
+ // Create output directory
79
+ (0, fs_1.mkdirSync)(targetDir, { recursive: true });
80
+ const specPaths = [];
81
+ let totalScenarios = 0;
82
+ for (const spec of specs) {
83
+ // Validate the spec
84
+ const validation = this.parser.validateSpec(spec);
85
+ if (!validation.valid) {
86
+ warnings.push(`Feature "${spec.name}": ${validation.errors.join(', ')}`);
87
+ }
88
+ // Convert to Playwright markdown format
89
+ const markdown = this.toPlaywrightMarkdown(spec);
90
+ // Generate output filename
91
+ const filename = `${spec.id}.md`;
92
+ const outputPath = (0, path_1.join)(targetDir, filename);
93
+ // Check for existing file
94
+ if ((0, fs_1.existsSync)(outputPath) && !this.overwrite) {
95
+ warnings.push(`Skipping existing file: ${outputPath}`);
96
+ continue;
97
+ }
98
+ // Write the spec file
99
+ (0, fs_1.writeFileSync)(outputPath, markdown, 'utf-8');
100
+ specPaths.push(outputPath);
101
+ totalScenarios += spec.scenarios.length;
102
+ console.log(` Created: ${outputPath} (${spec.scenarios.length} scenarios)`);
103
+ }
104
+ console.log(`Converted ${specs.length} feature(s) with ${totalScenarios} scenario(s)`);
105
+ /* eslint-enable no-console */
106
+ return {
107
+ specPaths,
108
+ features: specs,
109
+ totalScenarios,
110
+ warnings,
111
+ };
112
+ }
113
+ /**
114
+ * Convert a FeatureSpecification to Playwright Agent markdown format
115
+ *
116
+ * The format is designed to be consumed by Playwright's Planner and Generator agents.
117
+ * It includes structured test scenarios in Given-When-Then format.
118
+ */
119
+ toPlaywrightMarkdown(spec) {
120
+ const lines = [];
121
+ // Header
122
+ lines.push(`# ${spec.name}`);
123
+ lines.push('');
124
+ // Metadata
125
+ lines.push(`**Priority**: ${spec.priority}`);
126
+ if (spec.targetUrls.length > 0) {
127
+ lines.push(`**Target URLs**: ${spec.targetUrls.join(', ')}`);
128
+ }
129
+ lines.push('');
130
+ // Description
131
+ if (spec.description) {
132
+ lines.push('## Description');
133
+ lines.push('');
134
+ lines.push(spec.description);
135
+ lines.push('');
136
+ }
137
+ // Test Scenarios
138
+ if (spec.scenarios.length > 0) {
139
+ lines.push('## Test Scenarios');
140
+ lines.push('');
141
+ for (const scenario of spec.scenarios) {
142
+ lines.push(this.formatScenario(scenario));
143
+ lines.push('');
144
+ }
145
+ }
146
+ // Acceptance Criteria
147
+ if (spec.acceptanceCriteria.length > 0) {
148
+ lines.push('## Acceptance Criteria');
149
+ lines.push('');
150
+ for (const criterion of spec.acceptanceCriteria) {
151
+ lines.push(`- ${criterion}`);
152
+ }
153
+ lines.push('');
154
+ }
155
+ // Screenshots reference (if any)
156
+ if (spec.screenshots.length > 0) {
157
+ lines.push('## Reference Screenshots');
158
+ lines.push('');
159
+ for (const screenshot of spec.screenshots) {
160
+ lines.push(`- ${screenshot.description}: \`${screenshot.path}\``);
161
+ }
162
+ lines.push('');
163
+ }
164
+ // Metadata footer
165
+ lines.push('---');
166
+ lines.push(`*Generated from: ${(0, path_1.basename)(spec.sourcePath)}*`);
167
+ lines.push(`*Feature ID: ${spec.id}*`);
168
+ return lines.join('\n');
169
+ }
170
+ /**
171
+ * Format a business scenario in Playwright-friendly markdown
172
+ */
173
+ formatScenario(scenario) {
174
+ const lines = [];
175
+ lines.push(`### ${scenario.name}`);
176
+ lines.push('');
177
+ lines.push(`**Priority**: ${scenario.priority}`);
178
+ lines.push('');
179
+ if (scenario.given) {
180
+ lines.push(`**Given**: ${scenario.given}`);
181
+ }
182
+ if (scenario.when) {
183
+ lines.push(`**When**: ${scenario.when}`);
184
+ }
185
+ if (scenario.then) {
186
+ lines.push(`**Then**: ${scenario.then}`);
187
+ }
188
+ return lines.join('\n');
189
+ }
190
+ /**
191
+ * Parse a spec file without writing output
192
+ * Useful for validation or inspection
193
+ */
194
+ async parseSpec(inputPath) {
195
+ return this.parser.parse(inputPath, 'file');
196
+ }
197
+ /**
198
+ * Validate a specification file
199
+ */
200
+ async validateSpec(inputPath) {
201
+ const specs = await this.parser.parse(inputPath, 'file');
202
+ const allErrors = [];
203
+ let totalScenarios = 0;
204
+ for (const spec of specs) {
205
+ const validation = this.parser.validateSpec(spec);
206
+ if (!validation.valid) {
207
+ allErrors.push(...validation.errors.map((e) => `${spec.name}: ${e}`));
208
+ }
209
+ totalScenarios += spec.scenarios.length;
210
+ }
211
+ return {
212
+ valid: allErrors.length === 0,
213
+ errors: allErrors,
214
+ features: specs.length,
215
+ scenarios: totalScenarios,
216
+ };
217
+ }
218
+ /**
219
+ * Get a summary of the specification
220
+ */
221
+ async getSpecSummary(inputPath) {
222
+ const specs = await this.parser.parse(inputPath, 'file');
223
+ const lines = [];
224
+ lines.push(`Specification Summary: ${(0, path_1.basename)(inputPath)}`);
225
+ lines.push('='.repeat(50));
226
+ lines.push('');
227
+ for (const spec of specs) {
228
+ const summary = this.parser.getSpecSummary(spec);
229
+ lines.push(`Feature: ${summary.name}`);
230
+ lines.push(` Priority: ${summary.priority}`);
231
+ lines.push(` Scenarios: ${summary.scenarioCount}`);
232
+ lines.push(` - Must-have: ${summary.mustHaveScenarios}`);
233
+ lines.push(` - Should-have: ${summary.shouldHaveScenarios}`);
234
+ lines.push(` - Nice-to-have: ${summary.niceToHaveScenarios}`);
235
+ lines.push(` Acceptance Criteria: ${summary.acceptanceCriteriaCount}`);
236
+ lines.push(` Has Screenshots: ${summary.hasScreenshots ? 'Yes' : 'No'}`);
237
+ lines.push('');
238
+ }
239
+ return lines.join('\n');
240
+ }
241
+ }
242
+ exports.SpecBridge = SpecBridge;
243
+ /**
244
+ * Create a SpecBridge with Anthropic provider
245
+ * Convenience function for common use case
246
+ */
247
+ function createAnthropicBridge(apiKey, outputDir) {
248
+ return new SpecBridge({
249
+ llmConfig: {
250
+ type: 'anthropic',
251
+ config: {
252
+ apiKey: apiKey || process.env.ANTHROPIC_API_KEY || '',
253
+ },
254
+ },
255
+ outputDir,
256
+ });
257
+ }
258
+ /**
259
+ * Create a SpecBridge with Ollama provider (free, local)
260
+ * Convenience function for local development
261
+ */
262
+ function createOllamaBridge(model, outputDir) {
263
+ return new SpecBridge({
264
+ llmConfig: {
265
+ type: 'ollama',
266
+ config: {
267
+ model: model || 'deepseek-r1:7b',
268
+ baseUrl: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',
269
+ },
270
+ },
271
+ outputDir,
272
+ });
273
+ }
@@ -0,0 +1,23 @@
1
+ import type { SubsystemRiskImpactConfig } from './config.js';
2
+ export type RiskPriority = 'P0' | 'P1' | 'P2';
3
+ export interface SubsystemRiskRuleMatch {
4
+ ruleId: string;
5
+ scoreDelta: number;
6
+ priorityFloor?: RiskPriority;
7
+ reasons: string[];
8
+ keywords: string[];
9
+ }
10
+ export interface SubsystemRiskMapInfo {
11
+ source: 'map';
12
+ enabled: boolean;
13
+ mapPath: string;
14
+ mapFound: boolean;
15
+ rulesLoaded: number;
16
+ }
17
+ export interface SubsystemRiskResolver {
18
+ info: SubsystemRiskMapInfo;
19
+ warnings: string[];
20
+ matchFile: (relativePath: string) => SubsystemRiskRuleMatch[];
21
+ }
22
+ export declare function loadSubsystemRiskResolver(config: SubsystemRiskImpactConfig): SubsystemRiskResolver;
23
+ //# sourceMappingURL=subsystem_risk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subsystem_risk.d.ts","sourceRoot":"","sources":["../../src/agent/subsystem_risk.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,aAAa,CAAC;AAG3D,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AA2B9C,MAAM,WAAW,sBAAsB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,KAAK,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IAClC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,sBAAsB,EAAE,CAAC;CACjE;AAyGD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,yBAAyB,GAAG,qBAAqB,CAuHlG"}
@@ -0,0 +1,207 @@
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.loadSubsystemRiskResolver = loadSubsystemRiskResolver;
6
+ const fs_1 = require("fs");
7
+ const utils_js_1 = require("./utils.js");
8
+ const PRIORITY_RANK = {
9
+ P0: 0,
10
+ P1: 1,
11
+ P2: 2,
12
+ };
13
+ function coerceNumber(value) {
14
+ if (typeof value === 'number' && Number.isFinite(value)) {
15
+ return value;
16
+ }
17
+ if (typeof value === 'string') {
18
+ const parsed = Number(value);
19
+ if (Number.isFinite(parsed)) {
20
+ return parsed;
21
+ }
22
+ }
23
+ return undefined;
24
+ }
25
+ function normalizePriority(value) {
26
+ if (value === 'P0' || value === 'P1' || value === 'P2') {
27
+ return value;
28
+ }
29
+ return undefined;
30
+ }
31
+ function parseStringArray(value) {
32
+ if (!Array.isArray(value)) {
33
+ return [];
34
+ }
35
+ return value
36
+ .filter((item) => typeof item === 'string')
37
+ .map((item) => item.trim())
38
+ .filter(Boolean);
39
+ }
40
+ function parsePathArray(value) {
41
+ return parseStringArray(value).map((item) => (0, utils_js_1.normalizePath)(item));
42
+ }
43
+ function parseKeywords(value) {
44
+ if (!Array.isArray(value)) {
45
+ return [];
46
+ }
47
+ return Array.from(new Set(value
48
+ .filter((item) => typeof item === 'string')
49
+ .map((item) => item.trim().toLowerCase())
50
+ .filter(Boolean)));
51
+ }
52
+ function parseRules(rawRules, warnings) {
53
+ if (!Array.isArray(rawRules)) {
54
+ warnings.push('Subsystem risk map has no "rules" array.');
55
+ return [];
56
+ }
57
+ const parsed = [];
58
+ for (let i = 0; i < rawRules.length; i += 1) {
59
+ const rawRule = rawRules[i];
60
+ if (!rawRule || typeof rawRule !== 'object') {
61
+ continue;
62
+ }
63
+ const patterns = parsePathArray(rawRule.patterns);
64
+ if (patterns.length === 0) {
65
+ warnings.push(`Subsystem risk rule at index ${i} has no valid patterns and was skipped.`);
66
+ continue;
67
+ }
68
+ const id = typeof rawRule.id === 'string' && rawRule.id.trim()
69
+ ? rawRule.id.trim()
70
+ : `rule-${i + 1}`;
71
+ const description = typeof rawRule.description === 'string' ? rawRule.description.trim() : undefined;
72
+ const reasons = parseStringArray(rawRule.reasons);
73
+ const keywords = parseKeywords(rawRule.keywords);
74
+ const scoreDelta = coerceNumber(rawRule.scoreDelta) ?? 0;
75
+ const priorityFloor = normalizePriority(rawRule.priorityFloor);
76
+ const normalizedReasons = reasons.length > 0
77
+ ? reasons
78
+ : (description ? [description] : []);
79
+ parsed.push({
80
+ id,
81
+ description,
82
+ patterns,
83
+ scoreDelta,
84
+ priorityFloor,
85
+ reasons: normalizedReasons,
86
+ keywords,
87
+ });
88
+ }
89
+ return parsed;
90
+ }
91
+ function comparePriority(a, b) {
92
+ return PRIORITY_RANK[a] <= PRIORITY_RANK[b] ? a : b;
93
+ }
94
+ function loadSubsystemRiskResolver(config) {
95
+ const mapPath = (0, utils_js_1.normalizePath)(config.mapPath);
96
+ const warnings = [];
97
+ if (!config.enabled) {
98
+ return {
99
+ info: {
100
+ source: 'map',
101
+ enabled: false,
102
+ mapPath,
103
+ mapFound: false,
104
+ rulesLoaded: 0,
105
+ },
106
+ warnings,
107
+ matchFile: () => [],
108
+ };
109
+ }
110
+ if (!(0, fs_1.existsSync)(config.mapPath)) {
111
+ warnings.push(`Subsystem risk map file not found: ${config.mapPath}`);
112
+ return {
113
+ info: {
114
+ source: 'map',
115
+ enabled: true,
116
+ mapPath,
117
+ mapFound: false,
118
+ rulesLoaded: 0,
119
+ },
120
+ warnings,
121
+ matchFile: () => [],
122
+ };
123
+ }
124
+ let raw;
125
+ try {
126
+ raw = JSON.parse((0, fs_1.readFileSync)(config.mapPath, 'utf-8'));
127
+ }
128
+ catch {
129
+ warnings.push(`Subsystem risk map is invalid JSON: ${config.mapPath}`);
130
+ return {
131
+ info: {
132
+ source: 'map',
133
+ enabled: true,
134
+ mapPath,
135
+ mapFound: true,
136
+ rulesLoaded: 0,
137
+ },
138
+ warnings,
139
+ matchFile: () => [],
140
+ };
141
+ }
142
+ const rules = parseRules(raw.rules, warnings);
143
+ if (rules.length === 0) {
144
+ warnings.push(`Subsystem risk map loaded but no valid rules were found: ${config.mapPath}`);
145
+ }
146
+ const maxRules = Math.max(1, Math.round(config.maxRulesPerFile));
147
+ return {
148
+ info: {
149
+ source: 'map',
150
+ enabled: true,
151
+ mapPath,
152
+ mapFound: true,
153
+ rulesLoaded: rules.length,
154
+ },
155
+ warnings,
156
+ matchFile: (relativePath) => {
157
+ const normalizedPath = (0, utils_js_1.normalizePath)(relativePath);
158
+ const matches = [];
159
+ for (const rule of rules) {
160
+ const matched = rule.patterns.some((pattern) => (0, utils_js_1.matchGlob)(normalizedPath, pattern));
161
+ if (!matched) {
162
+ continue;
163
+ }
164
+ const reasons = rule.reasons.length > 0
165
+ ? rule.reasons
166
+ : [`Subsystem risk rule matched: ${rule.id}`];
167
+ matches.push({
168
+ ruleId: rule.id,
169
+ scoreDelta: rule.scoreDelta,
170
+ priorityFloor: rule.priorityFloor,
171
+ reasons,
172
+ keywords: rule.keywords,
173
+ priorityRank: rule.priorityFloor ? PRIORITY_RANK[rule.priorityFloor] : 99,
174
+ });
175
+ }
176
+ if (matches.length <= maxRules) {
177
+ return matches.map(({ priorityRank, ...rest }) => rest);
178
+ }
179
+ matches.sort((a, b) => {
180
+ const deltaDiff = Math.abs(b.scoreDelta) - Math.abs(a.scoreDelta);
181
+ if (deltaDiff !== 0) {
182
+ return deltaDiff;
183
+ }
184
+ const priorityDiff = a.priorityRank - b.priorityRank;
185
+ if (priorityDiff !== 0) {
186
+ return priorityDiff;
187
+ }
188
+ return a.ruleId.localeCompare(b.ruleId);
189
+ });
190
+ const capped = matches.slice(0, maxRules).map(({ priorityRank, ...rest }) => rest);
191
+ let floor;
192
+ for (const match of capped) {
193
+ if (match.priorityFloor) {
194
+ floor = floor ? comparePriority(floor, match.priorityFloor) : match.priorityFloor;
195
+ }
196
+ }
197
+ if (floor) {
198
+ for (const match of capped) {
199
+ if (!match.priorityFloor) {
200
+ match.priorityFloor = floor;
201
+ }
202
+ }
203
+ }
204
+ return capped;
205
+ },
206
+ };
207
+ }
@@ -0,0 +1,84 @@
1
+ export interface GenerationMetric {
2
+ id: string;
3
+ timestamp: string;
4
+ operation: 'explore' | 'generate' | 'heal' | 'validate' | 'score' | 'pdf-parse';
5
+ model: string;
6
+ tokensInput: number;
7
+ tokensOutput: number;
8
+ costUsd: number;
9
+ durationMs: number;
10
+ success: boolean;
11
+ errorType?: string;
12
+ errorMessage?: string;
13
+ metadata?: Record<string, unknown>;
14
+ }
15
+ export interface TelemetryReport {
16
+ period: {
17
+ start: string;
18
+ end: string;
19
+ };
20
+ summary: {
21
+ totalOperations: number;
22
+ successCount: number;
23
+ failureCount: number;
24
+ successRate: number;
25
+ totalCost: number;
26
+ avgCost: number;
27
+ totalTokens: number;
28
+ avgDuration: number;
29
+ };
30
+ byModel: Record<string, {
31
+ count: number;
32
+ totalCost: number;
33
+ avgCost: number;
34
+ successRate: number;
35
+ }>;
36
+ byOperation: Record<string, {
37
+ count: number;
38
+ totalCost: number;
39
+ avgDuration: number;
40
+ successRate: number;
41
+ }>;
42
+ }
43
+ export declare class TelemetryCollector {
44
+ private metricsDir;
45
+ private metrics;
46
+ constructor(metricsDir?: string);
47
+ /**
48
+ * Ensure metrics directory exists
49
+ */
50
+ private ensureMetricsDir;
51
+ /**
52
+ * Get today's metrics file path
53
+ */
54
+ private getTodayPath;
55
+ /**
56
+ * Load metrics from disk
57
+ */
58
+ private loadTodayMetrics;
59
+ /**
60
+ * Track a metric
61
+ */
62
+ track(metric: Omit<GenerationMetric, 'id'>): void;
63
+ /**
64
+ * Save metrics to disk
65
+ */
66
+ private saveMetrics;
67
+ /**
68
+ * Calculate cost for a metric
69
+ */
70
+ static calculateCost(model: string, tokensInput: number, tokensOutput: number): number;
71
+ /**
72
+ * Generate report for a date range
73
+ */
74
+ generateReport(since?: Date, until?: Date): TelemetryReport;
75
+ /**
76
+ * Format report for console output
77
+ */
78
+ static formatReport(report: TelemetryReport): string;
79
+ /**
80
+ * Export metrics as JSON
81
+ */
82
+ exportJson(filepath: string): void;
83
+ }
84
+ //# sourceMappingURL=telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/agent/telemetry.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,gBAAgB;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,WAAW,CAAC;IAChF,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAC,CAAC;IACrC,OAAO,EAAE;QACL,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,OAAO,EAAE,MAAM,CACX,MAAM,EACN;QACI,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;KACvB,CACJ,CAAC;IACF,WAAW,EAAE,MAAM,CACf,MAAM,EACN;QACI,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;KACvB,CACJ,CAAC;CACL;AAQD,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAA8C;gBAEjD,UAAU,GAAE,MAAiC;IAMzD;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;OAEG;IACH,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAYxB;;OAEG;IACH,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,GAAG,IAAI;IAejD;;OAEG;IACH,OAAO,CAAC,WAAW;IAMnB;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAMtF;;OAEG;IACH,cAAc,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,IAAI,GAAG,eAAe;IAuF3D;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM;IAmCpD;;OAEG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;CAQrC"}