model-test-bench 1.0.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 (288) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +389 -0
  3. package/dist/bin/mtb.d.ts +3 -0
  4. package/dist/bin/mtb.d.ts.map +1 -0
  5. package/dist/bin/mtb.js +148 -0
  6. package/dist/bin/mtb.js.map +1 -0
  7. package/dist/server/index.d.ts +13 -0
  8. package/dist/server/index.d.ts.map +1 -0
  9. package/dist/server/index.js +72 -0
  10. package/dist/server/index.js.map +1 -0
  11. package/dist/server/interfaces/evaluator.d.ts +15 -0
  12. package/dist/server/interfaces/evaluator.d.ts.map +1 -0
  13. package/dist/server/interfaces/evaluator.js +2 -0
  14. package/dist/server/interfaces/evaluator.js.map +1 -0
  15. package/dist/server/interfaces/logger.d.ts +9 -0
  16. package/dist/server/interfaces/logger.d.ts.map +1 -0
  17. package/dist/server/interfaces/logger.js +2 -0
  18. package/dist/server/interfaces/logger.js.map +1 -0
  19. package/dist/server/interfaces/runner.d.ts +9 -0
  20. package/dist/server/interfaces/runner.d.ts.map +1 -0
  21. package/dist/server/interfaces/runner.js +2 -0
  22. package/dist/server/interfaces/runner.js.map +1 -0
  23. package/dist/server/interfaces/storage.d.ts +36 -0
  24. package/dist/server/interfaces/storage.d.ts.map +1 -0
  25. package/dist/server/interfaces/storage.js +2 -0
  26. package/dist/server/interfaces/storage.js.map +1 -0
  27. package/dist/server/routes/eval-queue.d.ts +23 -0
  28. package/dist/server/routes/eval-queue.d.ts.map +1 -0
  29. package/dist/server/routes/eval-queue.js +45 -0
  30. package/dist/server/routes/eval-queue.js.map +1 -0
  31. package/dist/server/routes/evaluations.d.ts +8 -0
  32. package/dist/server/routes/evaluations.d.ts.map +1 -0
  33. package/dist/server/routes/evaluations.js +221 -0
  34. package/dist/server/routes/evaluations.js.map +1 -0
  35. package/dist/server/routes/providers.d.ts +5 -0
  36. package/dist/server/routes/providers.d.ts.map +1 -0
  37. package/dist/server/routes/providers.js +179 -0
  38. package/dist/server/routes/providers.js.map +1 -0
  39. package/dist/server/routes/run-queue.d.ts +17 -0
  40. package/dist/server/routes/run-queue.d.ts.map +1 -0
  41. package/dist/server/routes/run-queue.js +34 -0
  42. package/dist/server/routes/run-queue.js.map +1 -0
  43. package/dist/server/routes/run-sse.d.ts +18 -0
  44. package/dist/server/routes/run-sse.d.ts.map +1 -0
  45. package/dist/server/routes/run-sse.js +57 -0
  46. package/dist/server/routes/run-sse.js.map +1 -0
  47. package/dist/server/routes/runs.d.ts +9 -0
  48. package/dist/server/routes/runs.d.ts.map +1 -0
  49. package/dist/server/routes/runs.js +380 -0
  50. package/dist/server/routes/runs.js.map +1 -0
  51. package/dist/server/routes/scenarios.d.ts +5 -0
  52. package/dist/server/routes/scenarios.d.ts.map +1 -0
  53. package/dist/server/routes/scenarios.js +181 -0
  54. package/dist/server/routes/scenarios.js.map +1 -0
  55. package/dist/server/services/eval-helpers.d.ts +22 -0
  56. package/dist/server/services/eval-helpers.d.ts.map +1 -0
  57. package/dist/server/services/eval-helpers.js +75 -0
  58. package/dist/server/services/eval-helpers.js.map +1 -0
  59. package/dist/server/services/eval-parsers-debate-impl.d.ts +11 -0
  60. package/dist/server/services/eval-parsers-debate-impl.d.ts.map +1 -0
  61. package/dist/server/services/eval-parsers-debate-impl.js +133 -0
  62. package/dist/server/services/eval-parsers-debate-impl.js.map +1 -0
  63. package/dist/server/services/eval-parsers.d.ts +24 -0
  64. package/dist/server/services/eval-parsers.d.ts.map +1 -0
  65. package/dist/server/services/eval-parsers.js +153 -0
  66. package/dist/server/services/eval-parsers.js.map +1 -0
  67. package/dist/server/services/eval-prompts.d.ts +9 -0
  68. package/dist/server/services/eval-prompts.d.ts.map +1 -0
  69. package/dist/server/services/eval-prompts.js +164 -0
  70. package/dist/server/services/eval-prompts.js.map +1 -0
  71. package/dist/server/services/evaluator.d.ts +10 -0
  72. package/dist/server/services/evaluator.d.ts.map +1 -0
  73. package/dist/server/services/evaluator.js +143 -0
  74. package/dist/server/services/evaluator.js.map +1 -0
  75. package/dist/server/services/fs-adapter.d.ts +20 -0
  76. package/dist/server/services/fs-adapter.d.ts.map +1 -0
  77. package/dist/server/services/fs-adapter.js +13 -0
  78. package/dist/server/services/fs-adapter.js.map +1 -0
  79. package/dist/server/services/instruction-parser.d.ts +26 -0
  80. package/dist/server/services/instruction-parser.d.ts.map +1 -0
  81. package/dist/server/services/instruction-parser.js +121 -0
  82. package/dist/server/services/instruction-parser.js.map +1 -0
  83. package/dist/server/services/log-rotator.d.ts +20 -0
  84. package/dist/server/services/log-rotator.d.ts.map +1 -0
  85. package/dist/server/services/log-rotator.js +60 -0
  86. package/dist/server/services/log-rotator.js.map +1 -0
  87. package/dist/server/services/logger.d.ts +15 -0
  88. package/dist/server/services/logger.d.ts.map +1 -0
  89. package/dist/server/services/logger.js +69 -0
  90. package/dist/server/services/logger.js.map +1 -0
  91. package/dist/server/services/model-factory.d.ts +10 -0
  92. package/dist/server/services/model-factory.d.ts.map +1 -0
  93. package/dist/server/services/model-factory.js +33 -0
  94. package/dist/server/services/model-factory.js.map +1 -0
  95. package/dist/server/services/runner.d.ts +9 -0
  96. package/dist/server/services/runner.d.ts.map +1 -0
  97. package/dist/server/services/runner.js +99 -0
  98. package/dist/server/services/runner.js.map +1 -0
  99. package/dist/server/services/seeder.d.ts +5 -0
  100. package/dist/server/services/seeder.d.ts.map +1 -0
  101. package/dist/server/services/seeder.js +79 -0
  102. package/dist/server/services/seeder.js.map +1 -0
  103. package/dist/server/services/storage-test-helpers.d.ts +15 -0
  104. package/dist/server/services/storage-test-helpers.d.ts.map +1 -0
  105. package/dist/server/services/storage-test-helpers.js +151 -0
  106. package/dist/server/services/storage-test-helpers.js.map +1 -0
  107. package/dist/server/services/storage.d.ts +35 -0
  108. package/dist/server/services/storage.d.ts.map +1 -0
  109. package/dist/server/services/storage.js +219 -0
  110. package/dist/server/services/storage.js.map +1 -0
  111. package/dist/server/services/tools.d.ts +6 -0
  112. package/dist/server/services/tools.d.ts.map +1 -0
  113. package/dist/server/services/tools.js +94 -0
  114. package/dist/server/services/tools.js.map +1 -0
  115. package/dist/server/services/transcript-formatter.d.ts +18 -0
  116. package/dist/server/services/transcript-formatter.d.ts.map +1 -0
  117. package/dist/server/services/transcript-formatter.js +227 -0
  118. package/dist/server/services/transcript-formatter.js.map +1 -0
  119. package/dist/server/services/update-checker.d.ts +3 -0
  120. package/dist/server/services/update-checker.d.ts.map +1 -0
  121. package/dist/server/services/update-checker.js +34 -0
  122. package/dist/server/services/update-checker.js.map +1 -0
  123. package/dist/server/types/evaluation.d.ts +94 -0
  124. package/dist/server/types/evaluation.d.ts.map +1 -0
  125. package/dist/server/types/evaluation.js +5 -0
  126. package/dist/server/types/evaluation.js.map +1 -0
  127. package/dist/server/types/index.d.ts +5 -0
  128. package/dist/server/types/index.d.ts.map +1 -0
  129. package/dist/server/types/index.js +5 -0
  130. package/dist/server/types/index.js.map +1 -0
  131. package/dist/server/types/provider.d.ts +23 -0
  132. package/dist/server/types/provider.d.ts.map +1 -0
  133. package/dist/server/types/provider.js +5 -0
  134. package/dist/server/types/provider.js.map +1 -0
  135. package/dist/server/types/run.d.ts +31 -0
  136. package/dist/server/types/run.d.ts.map +1 -0
  137. package/dist/server/types/run.js +5 -0
  138. package/dist/server/types/run.js.map +1 -0
  139. package/dist/server/types/scenario.d.ts +19 -0
  140. package/dist/server/types/scenario.d.ts.map +1 -0
  141. package/dist/server/types/scenario.js +5 -0
  142. package/dist/server/types/scenario.js.map +1 -0
  143. package/dist/src/server/index.d.ts +13 -0
  144. package/dist/src/server/index.d.ts.map +1 -0
  145. package/dist/src/server/index.js +72 -0
  146. package/dist/src/server/index.js.map +1 -0
  147. package/dist/src/server/interfaces/evaluator.d.ts +15 -0
  148. package/dist/src/server/interfaces/evaluator.d.ts.map +1 -0
  149. package/dist/src/server/interfaces/evaluator.js +2 -0
  150. package/dist/src/server/interfaces/evaluator.js.map +1 -0
  151. package/dist/src/server/interfaces/logger.d.ts +9 -0
  152. package/dist/src/server/interfaces/logger.d.ts.map +1 -0
  153. package/dist/src/server/interfaces/logger.js +2 -0
  154. package/dist/src/server/interfaces/logger.js.map +1 -0
  155. package/dist/src/server/interfaces/runner.d.ts +9 -0
  156. package/dist/src/server/interfaces/runner.d.ts.map +1 -0
  157. package/dist/src/server/interfaces/runner.js +2 -0
  158. package/dist/src/server/interfaces/runner.js.map +1 -0
  159. package/dist/src/server/interfaces/storage.d.ts +36 -0
  160. package/dist/src/server/interfaces/storage.d.ts.map +1 -0
  161. package/dist/src/server/interfaces/storage.js +2 -0
  162. package/dist/src/server/interfaces/storage.js.map +1 -0
  163. package/dist/src/server/routes/eval-queue.d.ts +23 -0
  164. package/dist/src/server/routes/eval-queue.d.ts.map +1 -0
  165. package/dist/src/server/routes/eval-queue.js +45 -0
  166. package/dist/src/server/routes/eval-queue.js.map +1 -0
  167. package/dist/src/server/routes/evaluations.d.ts +8 -0
  168. package/dist/src/server/routes/evaluations.d.ts.map +1 -0
  169. package/dist/src/server/routes/evaluations.js +221 -0
  170. package/dist/src/server/routes/evaluations.js.map +1 -0
  171. package/dist/src/server/routes/providers.d.ts +5 -0
  172. package/dist/src/server/routes/providers.d.ts.map +1 -0
  173. package/dist/src/server/routes/providers.js +179 -0
  174. package/dist/src/server/routes/providers.js.map +1 -0
  175. package/dist/src/server/routes/run-queue.d.ts +17 -0
  176. package/dist/src/server/routes/run-queue.d.ts.map +1 -0
  177. package/dist/src/server/routes/run-queue.js +34 -0
  178. package/dist/src/server/routes/run-queue.js.map +1 -0
  179. package/dist/src/server/routes/run-sse.d.ts +18 -0
  180. package/dist/src/server/routes/run-sse.d.ts.map +1 -0
  181. package/dist/src/server/routes/run-sse.js +57 -0
  182. package/dist/src/server/routes/run-sse.js.map +1 -0
  183. package/dist/src/server/routes/runs.d.ts +9 -0
  184. package/dist/src/server/routes/runs.d.ts.map +1 -0
  185. package/dist/src/server/routes/runs.js +380 -0
  186. package/dist/src/server/routes/runs.js.map +1 -0
  187. package/dist/src/server/routes/scenarios.d.ts +5 -0
  188. package/dist/src/server/routes/scenarios.d.ts.map +1 -0
  189. package/dist/src/server/routes/scenarios.js +181 -0
  190. package/dist/src/server/routes/scenarios.js.map +1 -0
  191. package/dist/src/server/services/eval-helpers.d.ts +22 -0
  192. package/dist/src/server/services/eval-helpers.d.ts.map +1 -0
  193. package/dist/src/server/services/eval-helpers.js +75 -0
  194. package/dist/src/server/services/eval-helpers.js.map +1 -0
  195. package/dist/src/server/services/eval-parsers-debate-impl.d.ts +11 -0
  196. package/dist/src/server/services/eval-parsers-debate-impl.d.ts.map +1 -0
  197. package/dist/src/server/services/eval-parsers-debate-impl.js +133 -0
  198. package/dist/src/server/services/eval-parsers-debate-impl.js.map +1 -0
  199. package/dist/src/server/services/eval-parsers.d.ts +24 -0
  200. package/dist/src/server/services/eval-parsers.d.ts.map +1 -0
  201. package/dist/src/server/services/eval-parsers.js +153 -0
  202. package/dist/src/server/services/eval-parsers.js.map +1 -0
  203. package/dist/src/server/services/eval-prompts.d.ts +9 -0
  204. package/dist/src/server/services/eval-prompts.d.ts.map +1 -0
  205. package/dist/src/server/services/eval-prompts.js +164 -0
  206. package/dist/src/server/services/eval-prompts.js.map +1 -0
  207. package/dist/src/server/services/evaluator.d.ts +10 -0
  208. package/dist/src/server/services/evaluator.d.ts.map +1 -0
  209. package/dist/src/server/services/evaluator.js +143 -0
  210. package/dist/src/server/services/evaluator.js.map +1 -0
  211. package/dist/src/server/services/fs-adapter.d.ts +20 -0
  212. package/dist/src/server/services/fs-adapter.d.ts.map +1 -0
  213. package/dist/src/server/services/fs-adapter.js +13 -0
  214. package/dist/src/server/services/fs-adapter.js.map +1 -0
  215. package/dist/src/server/services/instruction-parser.d.ts +26 -0
  216. package/dist/src/server/services/instruction-parser.d.ts.map +1 -0
  217. package/dist/src/server/services/instruction-parser.js +121 -0
  218. package/dist/src/server/services/instruction-parser.js.map +1 -0
  219. package/dist/src/server/services/log-rotator.d.ts +20 -0
  220. package/dist/src/server/services/log-rotator.d.ts.map +1 -0
  221. package/dist/src/server/services/log-rotator.js +60 -0
  222. package/dist/src/server/services/log-rotator.js.map +1 -0
  223. package/dist/src/server/services/logger.d.ts +15 -0
  224. package/dist/src/server/services/logger.d.ts.map +1 -0
  225. package/dist/src/server/services/logger.js +69 -0
  226. package/dist/src/server/services/logger.js.map +1 -0
  227. package/dist/src/server/services/model-factory.d.ts +10 -0
  228. package/dist/src/server/services/model-factory.d.ts.map +1 -0
  229. package/dist/src/server/services/model-factory.js +33 -0
  230. package/dist/src/server/services/model-factory.js.map +1 -0
  231. package/dist/src/server/services/runner.d.ts +9 -0
  232. package/dist/src/server/services/runner.d.ts.map +1 -0
  233. package/dist/src/server/services/runner.js +99 -0
  234. package/dist/src/server/services/runner.js.map +1 -0
  235. package/dist/src/server/services/seeder.d.ts +5 -0
  236. package/dist/src/server/services/seeder.d.ts.map +1 -0
  237. package/dist/src/server/services/seeder.js +79 -0
  238. package/dist/src/server/services/seeder.js.map +1 -0
  239. package/dist/src/server/services/storage.d.ts +35 -0
  240. package/dist/src/server/services/storage.d.ts.map +1 -0
  241. package/dist/src/server/services/storage.js +219 -0
  242. package/dist/src/server/services/storage.js.map +1 -0
  243. package/dist/src/server/services/tools.d.ts +6 -0
  244. package/dist/src/server/services/tools.d.ts.map +1 -0
  245. package/dist/src/server/services/tools.js +94 -0
  246. package/dist/src/server/services/tools.js.map +1 -0
  247. package/dist/src/server/services/transcript-formatter.d.ts +18 -0
  248. package/dist/src/server/services/transcript-formatter.d.ts.map +1 -0
  249. package/dist/src/server/services/transcript-formatter.js +227 -0
  250. package/dist/src/server/services/transcript-formatter.js.map +1 -0
  251. package/dist/src/server/services/update-checker.d.ts +3 -0
  252. package/dist/src/server/services/update-checker.d.ts.map +1 -0
  253. package/dist/src/server/services/update-checker.js +34 -0
  254. package/dist/src/server/services/update-checker.js.map +1 -0
  255. package/dist/src/server/types/evaluation.d.ts +94 -0
  256. package/dist/src/server/types/evaluation.d.ts.map +1 -0
  257. package/dist/src/server/types/evaluation.js +5 -0
  258. package/dist/src/server/types/evaluation.js.map +1 -0
  259. package/dist/src/server/types/index.d.ts +5 -0
  260. package/dist/src/server/types/index.d.ts.map +1 -0
  261. package/dist/src/server/types/index.js +5 -0
  262. package/dist/src/server/types/index.js.map +1 -0
  263. package/dist/src/server/types/provider.d.ts +23 -0
  264. package/dist/src/server/types/provider.d.ts.map +1 -0
  265. package/dist/src/server/types/provider.js +5 -0
  266. package/dist/src/server/types/provider.js.map +1 -0
  267. package/dist/src/server/types/run.d.ts +31 -0
  268. package/dist/src/server/types/run.d.ts.map +1 -0
  269. package/dist/src/server/types/run.js +5 -0
  270. package/dist/src/server/types/run.js.map +1 -0
  271. package/dist/src/server/types/scenario.d.ts +19 -0
  272. package/dist/src/server/types/scenario.d.ts.map +1 -0
  273. package/dist/src/server/types/scenario.js +5 -0
  274. package/dist/src/server/types/scenario.js.map +1 -0
  275. package/dist/web/assets/index-AJu1Yn5F.js +70 -0
  276. package/dist/web/assets/index-C_ioEISr.css +1 -0
  277. package/dist/web/index.html +15 -0
  278. package/docs/schemas/provider-api.example.json +12 -0
  279. package/docs/schemas/provider-openai.example.json +11 -0
  280. package/docs/schemas/scenario-baseline.example.json +24 -0
  281. package/docs/schemas/scenario-carwash-baseline.example.json +22 -0
  282. package/docs/schemas/scenario-carwash-with-system-prompt.example.json +24 -0
  283. package/docs/schemas/scenario-golden-rules-baseline.example.json +24 -0
  284. package/docs/schemas/scenario-golden-rules-with-system-prompt.example.json +28 -0
  285. package/docs/schemas/scenario-negative-analysis-baseline.example.json +23 -0
  286. package/docs/schemas/scenario-negative-analysis-with-system-prompt.example.json +25 -0
  287. package/docs/schemas/scenario-with-system-prompt.example.json +25 -0
  288. package/package.json +97 -0
@@ -0,0 +1,99 @@
1
+ // ---------------------------------------------------------------------------
2
+ // AiSdkRunner — executes a single run via Vercel AI SDK (streaming)
3
+ // ---------------------------------------------------------------------------
4
+ import { streamText, stepCountIs } from 'ai';
5
+ import { createModel } from './model-factory.js';
6
+ import { getEnabledTools } from './tools.js';
7
+ // ---------------------------------------------------------------------------
8
+ // Implementation
9
+ // ---------------------------------------------------------------------------
10
+ export class AiSdkRunner {
11
+ logger;
12
+ constructor(logger) {
13
+ this.logger = logger;
14
+ }
15
+ async executeRun(provider, scenario, run, callbacks, externalAbortController) {
16
+ const startTime = Date.now();
17
+ const messages = [];
18
+ const abortController = externalAbortController ?? new AbortController();
19
+ let timeoutId;
20
+ try {
21
+ // Set up timeout
22
+ const timeoutMs = provider.timeoutSeconds * 1000;
23
+ timeoutId = setTimeout(() => abortController.abort(), timeoutMs);
24
+ callbacks.onStatusChange('running');
25
+ // Build model and tools
26
+ const model = createModel(provider);
27
+ const tools = getEnabledTools(scenario.enabledTools);
28
+ const hasTools = Object.keys(tools).length > 0;
29
+ // Stream the query
30
+ const result = streamText({
31
+ model,
32
+ system: scenario.systemPrompt || undefined,
33
+ prompt: scenario.prompt,
34
+ temperature: provider.temperature,
35
+ maxOutputTokens: provider.maxTokens,
36
+ topP: provider.topP,
37
+ tools: hasTools ? tools : undefined,
38
+ stopWhen: stepCountIs(hasTools ? 10 : 1),
39
+ abortSignal: abortController.signal,
40
+ });
41
+ // Consume the stream, forwarding each part to the frontend via callbacks
42
+ for await (const part of result.fullStream) {
43
+ const record = {
44
+ timestamp: new Date().toISOString(),
45
+ message: part,
46
+ };
47
+ messages.push(record);
48
+ callbacks.onMessage(record);
49
+ }
50
+ // Await final aggregated values
51
+ const finalText = await result.text;
52
+ const usage = await result.usage;
53
+ const steps = await result.steps;
54
+ const durationMs = Date.now() - startTime;
55
+ const completedRun = {
56
+ ...run,
57
+ status: 'completed',
58
+ messages,
59
+ resultText: finalText,
60
+ totalCostUsd: 0,
61
+ durationMs,
62
+ numTurns: steps.length,
63
+ updatedAt: new Date().toISOString(),
64
+ };
65
+ callbacks.onStatusChange('completed');
66
+ this.logger.info('Run completed', {
67
+ runId: run.id,
68
+ durationMs,
69
+ inputTokens: usage?.inputTokens ?? 0,
70
+ outputTokens: usage?.outputTokens ?? 0,
71
+ steps: steps.length,
72
+ });
73
+ return completedRun;
74
+ }
75
+ catch (err) {
76
+ const durationMs = Date.now() - startTime;
77
+ const errorMessage = err instanceof Error ? err.message : String(err);
78
+ const isAbort = abortController.signal.aborted;
79
+ const errorRun = {
80
+ ...run,
81
+ status: isAbort ? 'cancelled' : 'failed',
82
+ messages,
83
+ resultText: '',
84
+ totalCostUsd: 0,
85
+ durationMs,
86
+ numTurns: 0,
87
+ error: isAbort ? `Timeout after ${provider.timeoutSeconds}s` : errorMessage,
88
+ updatedAt: new Date().toISOString(),
89
+ };
90
+ callbacks.onStatusChange(errorRun.status);
91
+ return errorRun;
92
+ }
93
+ finally {
94
+ if (timeoutId !== undefined)
95
+ clearTimeout(timeoutId);
96
+ }
97
+ }
98
+ }
99
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../../src/server/services/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { IStorage } from '../interfaces/storage.js';
2
+ import type { ILogger } from '../interfaces/logger.js';
3
+ /** Seed storage with example scenarios and providers when empty. */
4
+ export declare function seedIfEmpty(storage: IStorage, logger: ILogger): Promise<void>;
5
+ //# sourceMappingURL=seeder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seeder.d.ts","sourceRoot":"","sources":["../../../../src/server/services/seeder.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AA8CvD,oEAAoE;AACpE,wBAAsB,WAAW,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAoCnF"}
@@ -0,0 +1,79 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ /**
4
+ * Seed files that ship with the project under docs/schemas/.
5
+ * Each entry maps a source file to the storage method used to persist it.
6
+ * Seeding only runs when the respective list is empty — existing data is never overwritten.
7
+ */
8
+ const SEED_SCENARIOS = [
9
+ 'scenario-baseline.example.json',
10
+ 'scenario-with-system-prompt.example.json',
11
+ 'scenario-carwash-baseline.example.json',
12
+ 'scenario-carwash-with-system-prompt.example.json',
13
+ 'scenario-negative-analysis-baseline.example.json',
14
+ 'scenario-negative-analysis-with-system-prompt.example.json',
15
+ 'scenario-golden-rules-baseline.example.json',
16
+ 'scenario-golden-rules-with-system-prompt.example.json',
17
+ ];
18
+ const SEED_PROVIDERS = [
19
+ 'provider-api.example.json',
20
+ 'provider-openai.example.json',
21
+ ];
22
+ function resolveSchemasDir() {
23
+ // Try common locations: relative to cwd, relative to this file's compiled location
24
+ const candidates = [
25
+ path.join(process.cwd(), 'docs', 'schemas'),
26
+ path.join(process.cwd(), '..', 'docs', 'schemas'),
27
+ ];
28
+ for (const dir of candidates) {
29
+ if (fs.existsSync(dir))
30
+ return dir;
31
+ }
32
+ return candidates[0]; // fallback
33
+ }
34
+ function loadJsonFile(filePath) {
35
+ try {
36
+ const raw = fs.readFileSync(filePath, 'utf-8');
37
+ return JSON.parse(raw);
38
+ }
39
+ catch {
40
+ return undefined;
41
+ }
42
+ }
43
+ /** Seed storage with example scenarios and providers when empty. */
44
+ export async function seedIfEmpty(storage, logger) {
45
+ const schemasDir = resolveSchemasDir();
46
+ // Seed scenarios
47
+ const existingScenarios = await storage.listScenarios();
48
+ if (existingScenarios.length === 0) {
49
+ let seeded = 0;
50
+ for (const file of SEED_SCENARIOS) {
51
+ const scenario = loadJsonFile(path.join(schemasDir, file));
52
+ if (scenario) {
53
+ await storage.saveScenario(scenario);
54
+ seeded++;
55
+ logger.info('Seeded scenario', { name: scenario.name, id: scenario.id });
56
+ }
57
+ }
58
+ if (seeded === 0) {
59
+ logger.info('No seed scenarios found in ' + schemasDir);
60
+ }
61
+ }
62
+ // Seed providers
63
+ const existingProviders = await storage.listProviders();
64
+ if (existingProviders.length === 0) {
65
+ let seeded = 0;
66
+ for (const file of SEED_PROVIDERS) {
67
+ const provider = loadJsonFile(path.join(schemasDir, file));
68
+ if (provider) {
69
+ await storage.saveProvider(provider);
70
+ seeded++;
71
+ logger.info('Seeded provider', { name: provider.name, id: provider.id });
72
+ }
73
+ }
74
+ if (seeded === 0) {
75
+ logger.info('No seed providers found in ' + schemasDir);
76
+ }
77
+ }
78
+ }
79
+ //# sourceMappingURL=seeder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seeder.js","sourceRoot":"","sources":["../../../../src/server/services/seeder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { IStorage, ProviderFilter, ScenarioFilter, RunFilter, EvaluationFilter } from '../interfaces/storage.js';
2
+ import type { Provider, Scenario, Run, Evaluation } from '../types/index.js';
3
+ import type { FsAdapter } from './fs-adapter.js';
4
+ export declare class JsonFileStorage implements IStorage {
5
+ private readonly basePath;
6
+ private readonly fs;
7
+ private initialized;
8
+ private readonly entities;
9
+ constructor(basePath?: string, fsAdapter?: FsAdapter);
10
+ private ensureInit;
11
+ private entityDir;
12
+ private entityPath;
13
+ private getEntity;
14
+ private listEntities;
15
+ private saveEntity;
16
+ private deleteEntity;
17
+ getProvider(id: string): Promise<Provider | undefined>;
18
+ listProviders(filter?: ProviderFilter): Promise<readonly Provider[]>;
19
+ saveProvider(provider: Provider): Promise<void>;
20
+ deleteProvider(id: string): Promise<boolean>;
21
+ getScenario(id: string): Promise<Scenario | undefined>;
22
+ listScenarios(filter?: ScenarioFilter): Promise<readonly Scenario[]>;
23
+ saveScenario(scenario: Scenario): Promise<void>;
24
+ deleteScenario(id: string): Promise<boolean>;
25
+ private normalizeRun;
26
+ getRun(id: string): Promise<Run | undefined>;
27
+ listRuns(filter?: RunFilter): Promise<readonly Run[]>;
28
+ saveRun(run: Run): Promise<void>;
29
+ deleteRun(id: string): Promise<boolean>;
30
+ getEvaluation(id: string): Promise<Evaluation | undefined>;
31
+ listEvaluations(filter?: EvaluationFilter): Promise<readonly Evaluation[]>;
32
+ saveEvaluation(evaluation: Evaluation): Promise<void>;
33
+ deleteEvaluation(id: string): Promise<boolean>;
34
+ }
35
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../../src/server/services/storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACtH,OAAO,KAAK,EACV,QAAQ,EACR,QAAQ,EACR,GAAG,EACH,UAAU,EACX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQjD,qBAAa,eAAgB,YAAW,QAAQ;IAC9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAY;IAC/B,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAKvB;gBAEU,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,SAAS;YAgDtC,UAAU;IAwBxB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,UAAU;YAMJ,SAAS;YAWT,YAAY;YA6BZ,UAAU;YAeV,YAAY;IAc1B,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAItD,aAAa,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,QAAQ,EAAE,CAAC;IAKpE,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAK/C,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAM5C,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAItD,aAAa,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,QAAQ,EAAE,CAAC;IAKpE,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAK/C,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK5C,OAAO,CAAC,YAAY;IAed,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,SAAS,CAAC;IAI5C,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,GAAG,EAAE,CAAC;IAI3D,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAGvC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAC1D,eAAe,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC;IAC1E,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IACrD,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAC/C"}
@@ -0,0 +1,219 @@
1
+ import path from 'node:path';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { defaultFs } from './fs-adapter.js';
4
+ export class JsonFileStorage {
5
+ basePath;
6
+ fs;
7
+ initialized = false;
8
+ entities;
9
+ constructor(basePath, fsAdapter) {
10
+ this.basePath = basePath ?? path.join(process.cwd(), '.model-test-bench');
11
+ this.fs = fsAdapter ?? defaultFs;
12
+ this.entities = {
13
+ providers: {
14
+ subdir: 'providers',
15
+ sensitive: true,
16
+ matchesFilter: (s, f) => {
17
+ if (!f)
18
+ return true;
19
+ if (f.provider && s.providerName !== f.provider)
20
+ return false;
21
+ if (f.model && s.model !== f.model)
22
+ return false;
23
+ return true;
24
+ },
25
+ },
26
+ scenarios: {
27
+ subdir: 'scenarios/custom',
28
+ sensitive: false,
29
+ matchesFilter: (s, f) => {
30
+ if (!f)
31
+ return true;
32
+ if (f.category && s.category !== f.category)
33
+ return false;
34
+ return true;
35
+ },
36
+ },
37
+ runs: {
38
+ subdir: 'runs',
39
+ sensitive: false,
40
+ matchesFilter: (r, f) => {
41
+ if (!f)
42
+ return true;
43
+ if (f.providerId && r.providerId !== f.providerId)
44
+ return false;
45
+ if (f.scenarioId && r.scenarioId !== f.scenarioId)
46
+ return false;
47
+ if (f.status && r.status !== f.status)
48
+ return false;
49
+ return true;
50
+ },
51
+ },
52
+ evaluations: {
53
+ subdir: 'evaluations',
54
+ sensitive: false,
55
+ matchesFilter: (e, f) => {
56
+ if (!f)
57
+ return true;
58
+ if (f.runId && e.runId !== f.runId)
59
+ return false;
60
+ if (f.status && e.status !== f.status)
61
+ return false;
62
+ return true;
63
+ },
64
+ },
65
+ };
66
+ }
67
+ async ensureInit() {
68
+ if (this.initialized)
69
+ return;
70
+ // Migrate legacy 'setups' directory to 'providers'
71
+ const legacyDir = path.join(this.basePath, 'setups');
72
+ const newDir = path.join(this.basePath, 'providers');
73
+ try {
74
+ await this.fs.access(legacyDir);
75
+ try {
76
+ await this.fs.access(newDir);
77
+ }
78
+ catch {
79
+ // New dir doesn't exist — rename legacy dir
80
+ await this.fs.rename(legacyDir, newDir);
81
+ }
82
+ }
83
+ catch {
84
+ // Legacy dir doesn't exist — nothing to migrate
85
+ }
86
+ for (const cfg of Object.values(this.entities)) {
87
+ await this.fs.mkdir(path.join(this.basePath, cfg.subdir), { recursive: true });
88
+ }
89
+ this.initialized = true;
90
+ }
91
+ entityDir(subdir) {
92
+ return path.join(this.basePath, subdir);
93
+ }
94
+ entityPath(subdir, id) {
95
+ return path.join(this.basePath, subdir, `${id}.json`);
96
+ }
97
+ // ─── Generic CRUD ──────────────────────────────────────────────────
98
+ async getEntity(subdir, id) {
99
+ await this.ensureInit();
100
+ const filePath = this.entityPath(subdir, id);
101
+ try {
102
+ const raw = await this.fs.readFile(filePath, 'utf-8');
103
+ return JSON.parse(raw);
104
+ }
105
+ catch {
106
+ return undefined;
107
+ }
108
+ }
109
+ async listEntities(subdir, matchesFilter, filter) {
110
+ await this.ensureInit();
111
+ const dir = this.entityDir(subdir);
112
+ let files;
113
+ try {
114
+ files = await this.fs.readdir(dir);
115
+ }
116
+ catch {
117
+ return [];
118
+ }
119
+ const results = [];
120
+ for (const file of files) {
121
+ if (!file.endsWith('.json'))
122
+ continue;
123
+ try {
124
+ const raw = await this.fs.readFile(path.join(dir, file), 'utf-8');
125
+ const entity = JSON.parse(raw);
126
+ if (matchesFilter(entity, filter)) {
127
+ results.push(entity);
128
+ }
129
+ }
130
+ catch {
131
+ // Skip corrupt files
132
+ }
133
+ }
134
+ return results;
135
+ }
136
+ async saveEntity(subdir, entity, sensitive) {
137
+ await this.ensureInit();
138
+ const dir = this.entityDir(subdir);
139
+ const tmpPath = path.join(dir, `.tmp-${randomUUID()}.json`);
140
+ const finalPath = this.entityPath(subdir, entity.id);
141
+ const data = JSON.stringify(entity, null, 2);
142
+ const opts = sensitive ? { mode: 0o600 } : undefined;
143
+ await this.fs.writeFile(tmpPath, data, opts);
144
+ await this.fs.rename(tmpPath, finalPath);
145
+ }
146
+ async deleteEntity(subdir, id) {
147
+ await this.ensureInit();
148
+ const filePath = this.entityPath(subdir, id);
149
+ try {
150
+ await this.fs.access(filePath);
151
+ await this.fs.unlink(filePath);
152
+ return true;
153
+ }
154
+ catch {
155
+ return false;
156
+ }
157
+ }
158
+ // ─── Providers ──────────────────────────────────────────────────────
159
+ getProvider(id) {
160
+ return this.getEntity(this.entities.providers.subdir, id);
161
+ }
162
+ listProviders(filter) {
163
+ const cfg = this.entities.providers;
164
+ return this.listEntities(cfg.subdir, cfg.matchesFilter, filter);
165
+ }
166
+ saveProvider(provider) {
167
+ const cfg = this.entities.providers;
168
+ return this.saveEntity(cfg.subdir, provider, cfg.sensitive);
169
+ }
170
+ deleteProvider(id) {
171
+ return this.deleteEntity(this.entities.providers.subdir, id);
172
+ }
173
+ // ─── Scenarios ─────────────────────────────────────────────────────
174
+ getScenario(id) {
175
+ return this.getEntity(this.entities.scenarios.subdir, id);
176
+ }
177
+ listScenarios(filter) {
178
+ const cfg = this.entities.scenarios;
179
+ return this.listEntities(cfg.subdir, cfg.matchesFilter, filter);
180
+ }
181
+ saveScenario(scenario) {
182
+ const cfg = this.entities.scenarios;
183
+ return this.saveEntity(cfg.subdir, scenario, cfg.sensitive);
184
+ }
185
+ deleteScenario(id) {
186
+ return this.deleteEntity(this.entities.scenarios.subdir, id);
187
+ }
188
+ // ─── Runs ──────────────────────────────────────────────────────────
189
+ normalizeRun(raw) {
190
+ // Accept both old and new field names for backward compat
191
+ const r = raw;
192
+ if ('setupId' in r && !('providerId' in r)) {
193
+ return {
194
+ ...raw,
195
+ providerId: r['setupId'],
196
+ providerSnapshot: (r['setupSnapshot'] ?? raw.providerSnapshot),
197
+ reviewerProviderIds: (r['reviewerSetupIds'] ?? raw.reviewerProviderIds),
198
+ reviewerProviderSnapshots: (r['reviewerSetupSnapshots'] ?? raw.reviewerProviderSnapshots),
199
+ };
200
+ }
201
+ return raw;
202
+ }
203
+ async getRun(id) {
204
+ const raw = await this.getEntity(this.entities.runs.subdir, id);
205
+ return raw ? this.normalizeRun(raw) : undefined;
206
+ }
207
+ async listRuns(filter) {
208
+ const results = await this.listEntities(this.entities.runs.subdir, this.entities.runs.matchesFilter, filter);
209
+ return results.map((r) => this.normalizeRun(r));
210
+ }
211
+ saveRun(run) { return this.saveEntity(this.entities.runs.subdir, run, this.entities.runs.sensitive); }
212
+ deleteRun(id) { return this.deleteEntity(this.entities.runs.subdir, id); }
213
+ // ─── Evaluations ───────────────────────────────────────────────────
214
+ getEvaluation(id) { return this.getEntity(this.entities.evaluations.subdir, id); }
215
+ listEvaluations(filter) { return this.listEntities(this.entities.evaluations.subdir, this.entities.evaluations.matchesFilter, filter); }
216
+ saveEvaluation(evaluation) { return this.saveEntity(this.entities.evaluations.subdir, evaluation, this.entities.evaluations.sensitive); }
217
+ deleteEvaluation(id) { return this.deleteEntity(this.entities.evaluations.subdir, id); }
218
+ }
219
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../../src/server/services/storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { tool } from 'ai';
2
+ /** Get the list of all available tool names. */
3
+ export declare function getAvailableToolNames(): string[];
4
+ /** Get enabled tools filtered by name. Returns empty object if none enabled. */
5
+ export declare function getEnabledTools(enabledToolNames: readonly string[]): Record<string, ReturnType<typeof tool<any, any>>>;
6
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../../src/server/services/tools.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AA8E1B,gDAAgD;AAChD,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAEhD;AAED,gFAAgF;AAEhF,wBAAgB,eAAe,CAC7B,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAClC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CASnD"}
@@ -0,0 +1,94 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Built-in Tools — tool definitions for AI SDK generateText()
3
+ // ---------------------------------------------------------------------------
4
+ import { tool } from 'ai';
5
+ import { z } from 'zod';
6
+ import fs from 'node:fs/promises';
7
+ import path from 'node:path';
8
+ /** Read a file by path and return its content. */
9
+ const readFileTool = tool({
10
+ description: 'Read a file at the given path and return its content.',
11
+ inputSchema: z.object({
12
+ path: z.string().describe('Absolute or relative file path to read'),
13
+ }),
14
+ execute: async ({ path: filePath }) => {
15
+ const resolved = path.resolve(filePath);
16
+ const content = await fs.readFile(resolved, 'utf-8');
17
+ return content;
18
+ },
19
+ });
20
+ /** Search file contents by pattern (grep-like). */
21
+ const searchFileTool = tool({
22
+ description: 'Search file contents by regex pattern. Returns matching lines with file:line references.',
23
+ inputSchema: z.object({
24
+ pattern: z.string().describe('Regex pattern to search for'),
25
+ path: z.string().optional().describe('Directory or file path to search in (defaults to cwd)'),
26
+ }),
27
+ execute: async ({ pattern, path: searchPath }) => {
28
+ const dir = searchPath ? path.resolve(searchPath) : process.cwd();
29
+ const regex = new RegExp(pattern, 'g');
30
+ const results = [];
31
+ async function searchDir(dirPath) {
32
+ const entries = await fs.readdir(dirPath, { withFileTypes: true });
33
+ for (const entry of entries) {
34
+ const fullPath = path.join(dirPath, entry.name);
35
+ if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {
36
+ await searchDir(fullPath);
37
+ }
38
+ else if (entry.isFile()) {
39
+ try {
40
+ const content = await fs.readFile(fullPath, 'utf-8');
41
+ const lines = content.split('\n');
42
+ for (let i = 0; i < lines.length; i++) {
43
+ if (regex.test(lines[i])) {
44
+ results.push(`${fullPath}:${i + 1}: ${lines[i].trim()}`);
45
+ regex.lastIndex = 0;
46
+ }
47
+ }
48
+ }
49
+ catch { /* skip binary/unreadable files */ }
50
+ }
51
+ if (results.length >= 50)
52
+ return;
53
+ }
54
+ }
55
+ await searchDir(dir);
56
+ return results.length > 0
57
+ ? results.join('\n')
58
+ : `No matches found for pattern: ${pattern}`;
59
+ },
60
+ });
61
+ /** Web search (placeholder — not available in benchmark mode). */
62
+ const webSearchTool = tool({
63
+ description: 'Search the web for information. Returns search results.',
64
+ inputSchema: z.object({
65
+ query: z.string().describe('Search query'),
66
+ }),
67
+ execute: async ({ query }) => {
68
+ return `Web search is not available in benchmark mode. Query was: "${query}"`;
69
+ },
70
+ });
71
+ /** Registry of all built-in tools. */
72
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
73
+ const TOOL_REGISTRY = {
74
+ read_file: readFileTool,
75
+ search_file: searchFileTool,
76
+ web_search: webSearchTool,
77
+ };
78
+ /** Get the list of all available tool names. */
79
+ export function getAvailableToolNames() {
80
+ return Object.keys(TOOL_REGISTRY);
81
+ }
82
+ /** Get enabled tools filtered by name. Returns empty object if none enabled. */
83
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
84
+ export function getEnabledTools(enabledToolNames) {
85
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
86
+ const result = {};
87
+ for (const name of enabledToolNames) {
88
+ if (TOOL_REGISTRY[name]) {
89
+ result[name] = TOOL_REGISTRY[name];
90
+ }
91
+ }
92
+ return result;
93
+ }
94
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../../src/server/services/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { SDKMessageRecord } from '../types/index.js';
2
+ /** Structured summary extracted from a transcript. */
3
+ export interface TranscriptSummary {
4
+ readonly toolCallSequence: readonly string[];
5
+ readonly filesRead: readonly string[];
6
+ readonly filesModified: readonly string[];
7
+ readonly commandFailures: readonly string[];
8
+ readonly retryPatterns: readonly string[];
9
+ readonly askedClarifyingQuestions: boolean;
10
+ }
11
+ /** Full transcript output. */
12
+ export interface TranscriptResult {
13
+ readonly text: string;
14
+ readonly summary: TranscriptSummary;
15
+ }
16
+ /** Format SDK messages into a readable transcript and structured summary. */
17
+ export declare function formatTranscript(messages: readonly SDKMessageRecord[]): TranscriptResult;
18
+ //# sourceMappingURL=transcript-formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript-formatter.d.ts","sourceRoot":"","sources":["../../../../src/server/services/transcript-formatter.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAO1D,sDAAsD;AACtD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,wBAAwB,EAAE,OAAO,CAAC;CAC5C;AAED,8BAA8B;AAC9B,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;CACrC;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,GAAG,gBAAgB,CAsIxF"}