@inspectr/mcplab 0.1.0

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 (136) hide show
  1. package/README.md +762 -0
  2. package/dist/app/android-chrome-192x192.png +0 -0
  3. package/dist/app/android-chrome-512x512.png +0 -0
  4. package/dist/app/apple-touch-icon.png +0 -0
  5. package/dist/app/assets/index-DT-Z4AVG.js +249 -0
  6. package/dist/app/assets/index-EP4WAY8u.css +1 -0
  7. package/dist/app/favicon-16x16.png +0 -0
  8. package/dist/app/favicon-32x32.png +0 -0
  9. package/dist/app/favicon.svg +13 -0
  10. package/dist/app/index.html +26 -0
  11. package/dist/app/inspectr_logo_color.svg +9 -0
  12. package/dist/app/mcp.png +0 -0
  13. package/dist/app/mcp.svg +1 -0
  14. package/dist/app/robots.txt +14 -0
  15. package/dist/app/site.webmanifest +1 -0
  16. package/dist/app-server/app-context.d.ts +164 -0
  17. package/dist/app-server/app-context.d.ts.map +1 -0
  18. package/dist/app-server/app-context.js +2 -0
  19. package/dist/app-server/app-context.js.map +1 -0
  20. package/dist/app-server/assistant-common.d.ts +41 -0
  21. package/dist/app-server/assistant-common.d.ts.map +1 -0
  22. package/dist/app-server/assistant-common.js +104 -0
  23. package/dist/app-server/assistant-common.js.map +1 -0
  24. package/dist/app-server/config-store.d.ts +15 -0
  25. package/dist/app-server/config-store.d.ts.map +1 -0
  26. package/dist/app-server/config-store.js +67 -0
  27. package/dist/app-server/config-store.js.map +1 -0
  28. package/dist/app-server/dev-mcp.d.ts +6 -0
  29. package/dist/app-server/dev-mcp.d.ts.map +1 -0
  30. package/dist/app-server/dev-mcp.js +71 -0
  31. package/dist/app-server/dev-mcp.js.map +1 -0
  32. package/dist/app-server/evals-routes.d.ts +22 -0
  33. package/dist/app-server/evals-routes.d.ts.map +1 -0
  34. package/dist/app-server/evals-routes.js +135 -0
  35. package/dist/app-server/evals-routes.js.map +1 -0
  36. package/dist/app-server/http.d.ts +5 -0
  37. package/dist/app-server/http.d.ts.map +1 -0
  38. package/dist/app-server/http.js +31 -0
  39. package/dist/app-server/http.js.map +1 -0
  40. package/dist/app-server/index.d.ts +3 -0
  41. package/dist/app-server/index.d.ts.map +1 -0
  42. package/dist/app-server/index.js +2 -0
  43. package/dist/app-server/index.js.map +1 -0
  44. package/dist/app-server/jobs.d.ts +15 -0
  45. package/dist/app-server/jobs.d.ts.map +1 -0
  46. package/dist/app-server/jobs.js +11 -0
  47. package/dist/app-server/jobs.js.map +1 -0
  48. package/dist/app-server/libraries-store.d.ts +15 -0
  49. package/dist/app-server/libraries-store.d.ts.map +1 -0
  50. package/dist/app-server/libraries-store.js +61 -0
  51. package/dist/app-server/libraries-store.js.map +1 -0
  52. package/dist/app-server/markdown-reports.d.ts +12 -0
  53. package/dist/app-server/markdown-reports.d.ts.map +1 -0
  54. package/dist/app-server/markdown-reports.js +145 -0
  55. package/dist/app-server/markdown-reports.js.map +1 -0
  56. package/dist/app-server/oauth-debugger-domain.d.ts +230 -0
  57. package/dist/app-server/oauth-debugger-domain.d.ts.map +1 -0
  58. package/dist/app-server/oauth-debugger-domain.js +1098 -0
  59. package/dist/app-server/oauth-debugger-domain.js.map +1 -0
  60. package/dist/app-server/oauth-debugger.d.ts +20 -0
  61. package/dist/app-server/oauth-debugger.d.ts.map +1 -0
  62. package/dist/app-server/oauth-debugger.js +193 -0
  63. package/dist/app-server/oauth-debugger.js.map +1 -0
  64. package/dist/app-server/provider-models.d.ts +8 -0
  65. package/dist/app-server/provider-models.d.ts.map +1 -0
  66. package/dist/app-server/provider-models.js +60 -0
  67. package/dist/app-server/provider-models.js.map +1 -0
  68. package/dist/app-server/result-assistant-domain.d.ts +87 -0
  69. package/dist/app-server/result-assistant-domain.d.ts.map +1 -0
  70. package/dist/app-server/result-assistant-domain.js +212 -0
  71. package/dist/app-server/result-assistant-domain.js.map +1 -0
  72. package/dist/app-server/result-assistant.d.ts +22 -0
  73. package/dist/app-server/result-assistant.d.ts.map +1 -0
  74. package/dist/app-server/result-assistant.js +328 -0
  75. package/dist/app-server/result-assistant.js.map +1 -0
  76. package/dist/app-server/router.d.ts +4 -0
  77. package/dist/app-server/router.d.ts.map +1 -0
  78. package/dist/app-server/router.js +374 -0
  79. package/dist/app-server/router.js.map +1 -0
  80. package/dist/app-server/runs-routes.d.ts +44 -0
  81. package/dist/app-server/runs-routes.d.ts.map +1 -0
  82. package/dist/app-server/runs-routes.js +555 -0
  83. package/dist/app-server/runs-routes.js.map +1 -0
  84. package/dist/app-server/runs-store.d.ts +23 -0
  85. package/dist/app-server/runs-store.d.ts.map +1 -0
  86. package/dist/app-server/runs-store.js +84 -0
  87. package/dist/app-server/runs-store.js.map +1 -0
  88. package/dist/app-server/scenario-assistant-domain.d.ts +162 -0
  89. package/dist/app-server/scenario-assistant-domain.d.ts.map +1 -0
  90. package/dist/app-server/scenario-assistant-domain.js +269 -0
  91. package/dist/app-server/scenario-assistant-domain.js.map +1 -0
  92. package/dist/app-server/scenario-assistant.d.ts +29 -0
  93. package/dist/app-server/scenario-assistant.d.ts.map +1 -0
  94. package/dist/app-server/scenario-assistant.js +246 -0
  95. package/dist/app-server/scenario-assistant.js.map +1 -0
  96. package/dist/app-server/settings-store.d.ts +4 -0
  97. package/dist/app-server/settings-store.d.ts.map +1 -0
  98. package/dist/app-server/settings-store.js +32 -0
  99. package/dist/app-server/settings-store.js.map +1 -0
  100. package/dist/app-server/snapshots-routes.d.ts +24 -0
  101. package/dist/app-server/snapshots-routes.d.ts.map +1 -0
  102. package/dist/app-server/snapshots-routes.js +82 -0
  103. package/dist/app-server/snapshots-routes.js.map +1 -0
  104. package/dist/app-server/static-serving.d.ts +17 -0
  105. package/dist/app-server/static-serving.d.ts.map +1 -0
  106. package/dist/app-server/static-serving.js +64 -0
  107. package/dist/app-server/static-serving.js.map +1 -0
  108. package/dist/app-server/store-utils.d.ts +5 -0
  109. package/dist/app-server/store-utils.d.ts.map +1 -0
  110. package/dist/app-server/store-utils.js +26 -0
  111. package/dist/app-server/store-utils.js.map +1 -0
  112. package/dist/app-server/tool-analysis-domain.d.ts +146 -0
  113. package/dist/app-server/tool-analysis-domain.d.ts.map +1 -0
  114. package/dist/app-server/tool-analysis-domain.js +556 -0
  115. package/dist/app-server/tool-analysis-domain.js.map +1 -0
  116. package/dist/app-server/tool-analysis-storage.d.ts +41 -0
  117. package/dist/app-server/tool-analysis-storage.d.ts.map +1 -0
  118. package/dist/app-server/tool-analysis-storage.js +110 -0
  119. package/dist/app-server/tool-analysis-storage.js.map +1 -0
  120. package/dist/app-server/tool-analysis.d.ts +22 -0
  121. package/dist/app-server/tool-analysis.d.ts.map +1 -0
  122. package/dist/app-server/tool-analysis.js +271 -0
  123. package/dist/app-server/tool-analysis.js.map +1 -0
  124. package/dist/app-server/types.d.ts +28 -0
  125. package/dist/app-server/types.d.ts.map +1 -0
  126. package/dist/app-server/types.js +2 -0
  127. package/dist/app-server/types.js.map +1 -0
  128. package/dist/cli.d.ts +3 -0
  129. package/dist/cli.d.ts.map +1 -0
  130. package/dist/cli.js +544 -0
  131. package/dist/cli.js.map +1 -0
  132. package/dist/snapshot.d.ts +80 -0
  133. package/dist/snapshot.d.ts.map +1 -0
  134. package/dist/snapshot.js +401 -0
  135. package/dist/snapshot.js.map +1 -0
  136. package/package.json +55 -0
@@ -0,0 +1,246 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { isAbsolute, join } from 'node:path';
3
+ import { McpClientManager, loadConfig } from '@inspectr/mcplab-core';
4
+ export async function handleScenarioAssistantRoutes(params) {
5
+ const { req, res, pathname, method, settings, assistantSessions, deps } = params;
6
+ const { parseBody, asJson, cleanupAssistantSessions, touchAssistantSession, assistantSessionView, ensureInsideRoot, readLibraries, pickDefaultAssistantAgentName, resolveAssistantAgentFromConfig, resolveAssistantAgentFromLibraries, preloadAssistantTools, continueAssistantTurn, executeAssistantToolCall, summarizeToolResultForAssistant } = deps;
7
+ const errorMessage = (error) => (error instanceof Error ? error.message : String(error));
8
+ if (pathname === '/api/scenario-assistant/sessions' && method === 'POST') {
9
+ cleanupAssistantSessions(assistantSessions);
10
+ const body = (await parseBody(req));
11
+ const configPathRaw = body.configPath ? String(body.configPath).trim() : '';
12
+ const scenarioId = String(body.scenarioId ?? '').trim();
13
+ const requestedAssistantAgentName = String(body.selectedAssistantAgentName ?? '').trim();
14
+ const contextRaw = body.context ?? {};
15
+ if (!scenarioId) {
16
+ asJson(res, 400, { error: 'scenarioId is required' });
17
+ return true;
18
+ }
19
+ if (!contextRaw ||
20
+ typeof contextRaw !== 'object' ||
21
+ !('scenario' in contextRaw) ||
22
+ !contextRaw.scenario ||
23
+ typeof contextRaw.scenario !== 'object') {
24
+ asJson(res, 400, { error: 'context.scenario is required' });
25
+ return true;
26
+ }
27
+ const context = contextRaw;
28
+ let configPath;
29
+ let agentConfig;
30
+ let serversByName;
31
+ let warnings = [];
32
+ let selectedAssistantAgentName = '';
33
+ if (configPathRaw) {
34
+ configPath = isAbsolute(configPathRaw)
35
+ ? ensureInsideRoot(settings.evalsDir, configPathRaw)
36
+ : ensureInsideRoot(settings.evalsDir, join(settings.evalsDir, configPathRaw));
37
+ if (!existsSync(configPath)) {
38
+ asJson(res, 404, { error: `Config not found: ${configPath}` });
39
+ return true;
40
+ }
41
+ const loaded = loadConfig(configPath, { bundleRoot: settings.librariesDir });
42
+ warnings = [...(loaded.warnings ?? [])];
43
+ selectedAssistantAgentName = pickDefaultAssistantAgentName({
44
+ requested: requestedAssistantAgentName,
45
+ agentNames: Object.keys(loaded.config.agents)
46
+ });
47
+ if (!selectedAssistantAgentName) {
48
+ asJson(res, 400, {
49
+ error: 'No agents available for Scenario Assistant in this MCP Evaluation.'
50
+ });
51
+ return true;
52
+ }
53
+ agentConfig = resolveAssistantAgentFromConfig(loaded.config, selectedAssistantAgentName);
54
+ serversByName = loaded.config.servers;
55
+ }
56
+ else {
57
+ const libraries = readLibraries(settings.librariesDir);
58
+ selectedAssistantAgentName = pickDefaultAssistantAgentName({
59
+ requested: requestedAssistantAgentName,
60
+ settingsDefault: settings.scenarioAssistantAgentName,
61
+ agentNames: Object.keys(libraries.agents)
62
+ });
63
+ if (!selectedAssistantAgentName) {
64
+ asJson(res, 400, {
65
+ error: 'No library agents available for Scenario Assistant. Add an agent first.'
66
+ });
67
+ return true;
68
+ }
69
+ agentConfig = resolveAssistantAgentFromLibraries(libraries, selectedAssistantAgentName);
70
+ serversByName = libraries.servers;
71
+ }
72
+ const session = {
73
+ id: `sas-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
74
+ createdAt: Date.now(),
75
+ lastTouchedAt: Date.now(),
76
+ configPath,
77
+ selectedAssistantAgentName,
78
+ context,
79
+ agentConfig,
80
+ mcp: new McpClientManager(),
81
+ tools: [],
82
+ toolPublicMap: new Map(),
83
+ pendingToolCalls: [],
84
+ chatMessages: [],
85
+ llmMessages: [],
86
+ warnings
87
+ };
88
+ session.chatMessages.push({
89
+ id: `msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
90
+ role: 'system',
91
+ text: 'Scenario Assistant session created.',
92
+ createdAt: new Date().toISOString()
93
+ });
94
+ const selectedServerNames = Array.from(new Set(Array.isArray(context.scenario.serverNames)
95
+ ? context.scenario.serverNames.map((v) => String(v))
96
+ : []));
97
+ await preloadAssistantTools(session, serversByName, selectedServerNames);
98
+ assistantSessions.set(session.id, session);
99
+ asJson(res, 201, { sessionId: session.id, session: assistantSessionView(session) });
100
+ return true;
101
+ }
102
+ if (pathname.startsWith('/api/scenario-assistant/sessions/') && method === 'GET') {
103
+ cleanupAssistantSessions(assistantSessions);
104
+ const sessionId = pathname.replace('/api/scenario-assistant/sessions/', '');
105
+ const session = assistantSessions.get(sessionId);
106
+ if (!session) {
107
+ asJson(res, 404, { error: 'Scenario Assistant session not found' });
108
+ return true;
109
+ }
110
+ touchAssistantSession(session);
111
+ asJson(res, 200, { session: assistantSessionView(session) });
112
+ return true;
113
+ }
114
+ if (pathname.startsWith('/api/scenario-assistant/sessions/') && method === 'DELETE') {
115
+ cleanupAssistantSessions(assistantSessions);
116
+ const sessionId = pathname.replace('/api/scenario-assistant/sessions/', '');
117
+ assistantSessions.delete(sessionId);
118
+ asJson(res, 200, { ok: true });
119
+ return true;
120
+ }
121
+ if (pathname.startsWith('/api/scenario-assistant/sessions/') &&
122
+ pathname.endsWith('/messages') &&
123
+ method === 'POST') {
124
+ cleanupAssistantSessions(assistantSessions);
125
+ const parts = pathname.split('/');
126
+ const sessionId = parts[4];
127
+ const session = assistantSessions.get(sessionId);
128
+ if (!session) {
129
+ asJson(res, 404, { error: 'Scenario Assistant session not found' });
130
+ return true;
131
+ }
132
+ const body = await parseBody(req);
133
+ const message = String(body.message ?? '').trim();
134
+ if (!message) {
135
+ asJson(res, 400, { error: 'message is required' });
136
+ return true;
137
+ }
138
+ session.chatMessages.push({
139
+ id: `msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
140
+ role: 'user',
141
+ text: message,
142
+ createdAt: new Date().toISOString()
143
+ });
144
+ session.llmMessages.push({ role: 'user', content: message });
145
+ const output = await continueAssistantTurn(session);
146
+ asJson(res, 200, output);
147
+ return true;
148
+ }
149
+ if (pathname.startsWith('/api/scenario-assistant/sessions/') &&
150
+ pathname.includes('/tool-calls/') &&
151
+ pathname.endsWith('/approve') &&
152
+ method === 'POST') {
153
+ cleanupAssistantSessions(assistantSessions);
154
+ const parts = pathname.split('/');
155
+ const sessionId = parts[4];
156
+ const callId = parts[6];
157
+ const session = assistantSessions.get(sessionId);
158
+ if (!session) {
159
+ asJson(res, 404, { error: 'Scenario Assistant session not found' });
160
+ return true;
161
+ }
162
+ const pending = session.pendingToolCalls.find((call) => call.id === callId);
163
+ if (!pending) {
164
+ asJson(res, 404, { error: 'Scenario Assistant tool call not found' });
165
+ return true;
166
+ }
167
+ if (pending.status !== 'pending') {
168
+ asJson(res, 409, { error: `Tool call is already ${pending.status}` });
169
+ return true;
170
+ }
171
+ const body = (await parseBody(req));
172
+ if (Object.prototype.hasOwnProperty.call(body ?? {}, 'argumentsOverride')) {
173
+ pending.arguments = body.argumentsOverride;
174
+ }
175
+ pending.status = 'approved';
176
+ try {
177
+ const toolResult = await executeAssistantToolCall(session, pending);
178
+ pending.resultPreview = summarizeToolResultForAssistant(toolResult);
179
+ session.llmMessages.push({
180
+ role: 'tool',
181
+ content: pending.resultPreview,
182
+ tool_call_id: pending.id,
183
+ name: pending.publicToolName
184
+ });
185
+ }
186
+ catch (error) {
187
+ pending.status = 'error';
188
+ pending.error = errorMessage(error);
189
+ session.llmMessages.push({
190
+ role: 'tool',
191
+ content: JSON.stringify({ error: pending.error }),
192
+ tool_call_id: pending.id,
193
+ name: pending.publicToolName
194
+ });
195
+ session.chatMessages.push({
196
+ id: `msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
197
+ role: 'tool',
198
+ text: `Tool error (${pending.server}::${pending.tool}): ${pending.error}`,
199
+ createdAt: new Date().toISOString()
200
+ });
201
+ }
202
+ const output = await continueAssistantTurn(session);
203
+ asJson(res, 200, output);
204
+ return true;
205
+ }
206
+ if (pathname.startsWith('/api/scenario-assistant/sessions/') &&
207
+ pathname.includes('/tool-calls/') &&
208
+ pathname.endsWith('/deny') &&
209
+ method === 'POST') {
210
+ cleanupAssistantSessions(assistantSessions);
211
+ const parts = pathname.split('/');
212
+ const sessionId = parts[4];
213
+ const callId = parts[6];
214
+ const session = assistantSessions.get(sessionId);
215
+ if (!session) {
216
+ asJson(res, 404, { error: 'Scenario Assistant session not found' });
217
+ return true;
218
+ }
219
+ const pending = session.pendingToolCalls.find((call) => call.id === callId);
220
+ if (!pending) {
221
+ asJson(res, 404, { error: 'Scenario Assistant tool call not found' });
222
+ return true;
223
+ }
224
+ if (pending.status !== 'pending') {
225
+ asJson(res, 409, { error: `Tool call is already ${pending.status}` });
226
+ return true;
227
+ }
228
+ pending.status = 'denied';
229
+ session.llmMessages.push({
230
+ role: 'tool',
231
+ content: JSON.stringify({
232
+ denied: true,
233
+ reason: 'User denied tool call',
234
+ server: pending.server,
235
+ tool: pending.tool
236
+ }),
237
+ tool_call_id: pending.id,
238
+ name: pending.publicToolName
239
+ });
240
+ const output = await continueAssistantTurn(session);
241
+ asJson(res, 200, output);
242
+ return true;
243
+ }
244
+ return false;
245
+ }
246
+ //# sourceMappingURL=scenario-assistant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario-assistant.js","sourceRoot":"","sources":["../../src/app-server/scenario-assistant.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { AppSettings } from './types.js';
2
+ export declare function applySettingsOverrides(settings: AppSettings): void;
3
+ export declare function persistSettingsOverrides(settings: AppSettings): void;
4
+ //# sourceMappingURL=settings-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-store.d.ts","sourceRoot":"","sources":["../../src/app-server/settings-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAqB9C,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAIlE;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAOpE"}
@@ -0,0 +1,32 @@
1
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
4
+ function settingsOverridesFilePath(settings) {
5
+ return join(settings.librariesDir, '.mcplab-app-settings.yaml');
6
+ }
7
+ function loadSettingsOverrides(settings) {
8
+ const filePath = settingsOverridesFilePath(settings);
9
+ if (!existsSync(filePath))
10
+ return {};
11
+ try {
12
+ const parsed = parseYaml(readFileSync(filePath, 'utf8'));
13
+ return parsed && typeof parsed === 'object' ? parsed : {};
14
+ }
15
+ catch {
16
+ return {};
17
+ }
18
+ }
19
+ export function applySettingsOverrides(settings) {
20
+ const overrides = loadSettingsOverrides(settings);
21
+ settings.scenarioAssistantAgentName =
22
+ overrides.scenario_assistant_agent_name?.trim() || undefined;
23
+ }
24
+ export function persistSettingsOverrides(settings) {
25
+ const payload = {
26
+ ...(settings.scenarioAssistantAgentName
27
+ ? { scenario_assistant_agent_name: settings.scenarioAssistantAgentName }
28
+ : {})
29
+ };
30
+ writeFileSync(settingsOverridesFilePath(settings), `${stringifyYaml(payload)}\n`, 'utf8');
31
+ }
32
+ //# sourceMappingURL=settings-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-store.js","sourceRoot":"","sources":["../../src/app-server/settings-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AAOtE,SAAS,yBAAyB,CAAC,QAAqB;IACtD,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,2BAA2B,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAqB;IAClD,MAAM,QAAQ,GAAG,yBAAyB,CAAC,QAAQ,CAAC,CAAC;IACrD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAqC,CAAC;QAC7F,OAAO,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAAqB;IAC1D,MAAM,SAAS,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAClD,QAAQ,CAAC,0BAA0B;QACjC,SAAS,CAAC,6BAA6B,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,QAAqB;IAC5D,MAAM,OAAO,GAAyB;QACpC,GAAG,CAAC,QAAQ,CAAC,0BAA0B;YACrC,CAAC,CAAC,EAAE,6BAA6B,EAAE,QAAQ,CAAC,0BAA0B,EAAE;YACxE,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IACF,aAAa,CAAC,yBAAyB,CAAC,QAAQ,CAAC,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC5F,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { AppRouteDeps, AppRouteRequestContext } from './app-context.js';
3
+ export type SnapshotsRouteDeps = Pick<
4
+ AppRouteDeps,
5
+ | 'parseBody'
6
+ | 'asJson'
7
+ | 'listSnapshots'
8
+ | 'buildSnapshotFromRun'
9
+ | 'saveSnapshot'
10
+ | 'loadSnapshot'
11
+ | 'compareRunToSnapshot'
12
+ | 'getRunResults'
13
+ | 'decodeEvalId'
14
+ | 'readConfigRecord'
15
+ >;
16
+ export declare function handleSnapshotsRoutes(params: {
17
+ req: IncomingMessage;
18
+ res: ServerResponse;
19
+ pathname: string;
20
+ method: string;
21
+ settings: AppRouteRequestContext['settings'];
22
+ deps: SnapshotsRouteDeps;
23
+ }): Promise<boolean>;
24
+ //# sourceMappingURL=snapshots-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshots-routes.d.ts","sourceRoot":"","sources":["../../src/app-server/snapshots-routes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGjE,OAAO,KAAK,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE7E,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,YAAY,EACV,WAAW,GACX,QAAQ,GACR,eAAe,GACf,sBAAsB,GACtB,cAAc,GACd,cAAc,GACd,sBAAsB,GACtB,eAAe,GACf,cAAc,GACd,kBAAkB,CACrB,CAAC;AAEF,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,GAAG,EAAE,eAAe,CAAC;IACrB,GAAG,EAAE,cAAc,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAC7C,IAAI,EAAE,kBAAkB,CAAC;CAC1B,GAAG,OAAO,CAAC,OAAO,CAAC,CAiGnB"}
@@ -0,0 +1,82 @@
1
+ import { writeFileSync } from 'node:fs';
2
+ import { stringify as stringifyYaml } from 'yaml';
3
+ import { loadConfig } from '@inspectr/mcplab-core';
4
+ export async function handleSnapshotsRoutes(params) {
5
+ const { req, res, pathname, method, settings, deps } = params;
6
+ const { parseBody, asJson, listSnapshots, buildSnapshotFromRun, saveSnapshot, loadSnapshot, compareRunToSnapshot, getRunResults, decodeEvalId, readConfigRecord } = deps;
7
+ if (pathname === '/api/snapshots' && method === 'GET') {
8
+ asJson(res, 200, listSnapshots(settings.snapshotsDir));
9
+ return true;
10
+ }
11
+ if (pathname === '/api/snapshots' && method === 'POST') {
12
+ const body = await parseBody(req);
13
+ const runId = String(body.runId ?? '').trim();
14
+ const name = body.name ? String(body.name) : undefined;
15
+ if (!runId) {
16
+ asJson(res, 400, { error: 'runId is required' });
17
+ return true;
18
+ }
19
+ const results = getRunResults(runId, settings.runsDir);
20
+ const snapshot = buildSnapshotFromRun(results, name);
21
+ saveSnapshot(snapshot, settings.snapshotsDir);
22
+ asJson(res, 201, snapshot);
23
+ return true;
24
+ }
25
+ if (pathname === '/api/snapshots/generate-eval' && method === 'POST') {
26
+ const body = await parseBody(req);
27
+ const runId = String(body.runId ?? '').trim();
28
+ const configId = String(body.configId ?? '').trim();
29
+ const name = body.name ? String(body.name) : undefined;
30
+ if (!runId) {
31
+ asJson(res, 400, { error: 'runId is required' });
32
+ return true;
33
+ }
34
+ if (!configId) {
35
+ asJson(res, 400, { error: 'configId is required' });
36
+ return true;
37
+ }
38
+ const results = getRunResults(runId, settings.runsDir);
39
+ const snapshot = buildSnapshotFromRun(results, name);
40
+ saveSnapshot(snapshot, settings.snapshotsDir);
41
+ const configPath = decodeEvalId(configId, settings.evalsDir);
42
+ const { sourceConfig } = loadConfig(configPath, { bundleRoot: settings.librariesDir });
43
+ const nextConfig = {
44
+ ...sourceConfig,
45
+ snapshot_eval: {
46
+ enabled: true,
47
+ mode: sourceConfig.snapshot_eval?.mode ?? 'warn',
48
+ baseline_snapshot_id: snapshot.id,
49
+ baseline_source_run_id: runId,
50
+ last_updated_at: new Date().toISOString()
51
+ }
52
+ };
53
+ writeFileSync(configPath, `${stringifyYaml(nextConfig)}\n`, 'utf8');
54
+ asJson(res, 201, {
55
+ snapshot,
56
+ config: readConfigRecord(configPath, settings.evalsDir, settings.librariesDir)
57
+ });
58
+ return true;
59
+ }
60
+ if (pathname.startsWith('/api/snapshots/') && method === 'GET') {
61
+ const snapshotId = pathname.replace('/api/snapshots/', '');
62
+ asJson(res, 200, loadSnapshot(snapshotId, settings.snapshotsDir));
63
+ return true;
64
+ }
65
+ if (pathname.startsWith('/api/snapshots/') &&
66
+ pathname.endsWith('/compare') &&
67
+ method === 'POST') {
68
+ const snapshotId = pathname.split('/')[3];
69
+ const body = await parseBody(req);
70
+ const runId = String(body.runId ?? '').trim();
71
+ if (!runId) {
72
+ asJson(res, 400, { error: 'runId is required' });
73
+ return true;
74
+ }
75
+ const snapshot = loadSnapshot(snapshotId, settings.snapshotsDir);
76
+ const run = getRunResults(runId, settings.runsDir);
77
+ asJson(res, 200, compareRunToSnapshot(run, snapshot));
78
+ return true;
79
+ }
80
+ return false;
81
+ }
82
+ //# sourceMappingURL=snapshots-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshots-routes.js","sourceRoot":"","sources":["../../src/app-server/snapshots-routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ export declare function mapContentType(pathname: string): string;
3
+ export declare function proxyToVite(
4
+ req: IncomingMessage,
5
+ res: ServerResponse,
6
+ target: string,
7
+ pathname: string,
8
+ search: string
9
+ ): Promise<void>;
10
+ export declare function serveStatic(params: {
11
+ appDist: string;
12
+ pathname: string;
13
+ res: ServerResponse;
14
+ ensureInsideRoot: (rootDir: string, candidatePath: string) => string;
15
+ asText: (res: ServerResponse, code: number, body: string) => void;
16
+ }): void;
17
+ //# sourceMappingURL=static-serving.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-serving.d.ts","sourceRoot":"","sources":["../../src/app-server/static-serving.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGjE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUvD;AAED,wBAAsB,WAAW,CAC/B,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,iBAyBf;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,cAAc,CAAC;IACpB,gBAAgB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,KAAK,MAAM,CAAC;IACrE,MAAM,EAAE,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnE,QAmBA"}
@@ -0,0 +1,64 @@
1
+ import { createReadStream, existsSync, statSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ export function mapContentType(pathname) {
4
+ if (pathname.endsWith('.html'))
5
+ return 'text/html; charset=utf-8';
6
+ if (pathname.endsWith('.js'))
7
+ return 'application/javascript; charset=utf-8';
8
+ if (pathname.endsWith('.css'))
9
+ return 'text/css; charset=utf-8';
10
+ if (pathname.endsWith('.json'))
11
+ return 'application/json; charset=utf-8';
12
+ if (pathname.endsWith('.svg'))
13
+ return 'image/svg+xml';
14
+ if (pathname.endsWith('.png'))
15
+ return 'image/png';
16
+ if (pathname.endsWith('.jpg') || pathname.endsWith('.jpeg'))
17
+ return 'image/jpeg';
18
+ if (pathname.endsWith('.woff2'))
19
+ return 'font/woff2';
20
+ return 'application/octet-stream';
21
+ }
22
+ export async function proxyToVite(req, res, target, pathname, search) {
23
+ const url = `${target}${pathname}${search}`;
24
+ const method = req.method ?? 'GET';
25
+ const headers = new Headers();
26
+ for (const [key, value] of Object.entries(req.headers)) {
27
+ if (!value)
28
+ continue;
29
+ if (Array.isArray(value)) {
30
+ headers.set(key, value.join(','));
31
+ }
32
+ else {
33
+ headers.set(key, value);
34
+ }
35
+ }
36
+ const body = method === 'GET' || method === 'HEAD' ? undefined : req;
37
+ const response = await fetch(url, { method, headers, body: body, duplex: 'half' });
38
+ res.statusCode = response.status;
39
+ response.headers.forEach((value, key) => res.setHeader(key, value));
40
+ if (!response.body) {
41
+ res.end();
42
+ return;
43
+ }
44
+ for await (const chunk of response.body) {
45
+ res.write(chunk);
46
+ }
47
+ res.end();
48
+ }
49
+ export function serveStatic(params) {
50
+ const { appDist, pathname, res, ensureInsideRoot, asText } = params;
51
+ const cleanPath = pathname === '/' ? '/index.html' : pathname;
52
+ const requested = ensureInsideRoot(appDist, join(appDist, cleanPath));
53
+ const filePath = existsSync(requested) && statSync(requested).isFile()
54
+ ? requested
55
+ : ensureInsideRoot(appDist, join(appDist, 'index.html'));
56
+ if (!existsSync(filePath)) {
57
+ asText(res, 500, `Missing app build at ${appDist}. Run "npm run build -w @inspectr/mcplab-app".`);
58
+ return;
59
+ }
60
+ res.statusCode = 200;
61
+ res.setHeader('content-type', mapContentType(filePath));
62
+ createReadStream(filePath).pipe(res);
63
+ }
64
+ //# sourceMappingURL=static-serving.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-serving.js","sourceRoot":"","sources":["../../src/app-server/static-serving.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function ensureInsideRoot(rootDir: string, candidatePath: string): string;
2
+ export declare function encodeEvalId(absPath: string, rootDir: string): string;
3
+ export declare function decodeEvalId(id: string, rootDir: string): string;
4
+ export declare function safeFileName(name: string): string;
5
+ //# sourceMappingURL=store-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-utils.d.ts","sourceRoot":"","sources":["../../src/app-server/store-utils.ts"],"names":[],"mappings":"AAEA,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAO/E;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAGrE;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAGhE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASjD"}
@@ -0,0 +1,26 @@
1
+ import { join, resolve } from 'node:path';
2
+ export function ensureInsideRoot(rootDir, candidatePath) {
3
+ const root = resolve(rootDir);
4
+ const candidate = resolve(candidatePath);
5
+ if (!(candidate === root || candidate.startsWith(`${root}/`))) {
6
+ throw new Error(`Path outside allowed root: ${candidatePath}`);
7
+ }
8
+ return candidate;
9
+ }
10
+ export function encodeEvalId(absPath, rootDir) {
11
+ const rel = absPath.slice(resolve(rootDir).length + 1);
12
+ return Buffer.from(rel, 'utf8').toString('base64url');
13
+ }
14
+ export function decodeEvalId(id, rootDir) {
15
+ const rel = Buffer.from(id, 'base64url').toString('utf8');
16
+ return ensureInsideRoot(rootDir, join(rootDir, rel));
17
+ }
18
+ export function safeFileName(name) {
19
+ return (name
20
+ .trim()
21
+ .toLowerCase()
22
+ .replace(/[^a-z0-9-_]/g, '-')
23
+ .replace(/-+/g, '-')
24
+ .replace(/^-|-$/g, '') || `config-${Date.now()}`);
25
+ }
26
+ //# sourceMappingURL=store-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-utils.js","sourceRoot":"","sources":["../../src/app-server/store-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,aAAqB;IACrE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACzC,IAAI,CAAC,CAAC,SAAS,KAAK,IAAI,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CAAC,8BAA8B,aAAa,EAAE,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,OAAe;IAC3D,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvD,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAAU,EAAE,OAAe;IACtD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC1D,OAAO,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,CACL,IAAI;SACD,IAAI,EAAE;SACN,WAAW,EAAE;SACb,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC;SAC5B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,UAAU,IAAI,CAAC,GAAG,EAAE,EAAE,CACnD,CAAC;AACJ,CAAC"}