@inspectr/mcplab 1.28.5 → 1.30.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 (181) hide show
  1. package/README.md +74 -6
  2. package/dist/app/assets/index-8I9ZyPIK.js +243 -0
  3. package/dist/app/assets/index-jX7LoIQP.css +2 -0
  4. package/dist/app/assets/sse-queue-worker-Iwmqd2oW.js +1 -0
  5. package/dist/app/index.html +2 -2
  6. package/dist/app-server/app-context.d.ts +75 -115
  7. package/dist/app-server/app-context.d.ts.map +1 -1
  8. package/dist/app-server/app-dist.d.ts +3 -3
  9. package/dist/app-server/app-dist.js.map +1 -1
  10. package/dist/app-server/app-run-artifacts.d.ts +4 -0
  11. package/dist/app-server/app-run-artifacts.d.ts.map +1 -0
  12. package/dist/app-server/app-run-artifacts.js +66 -0
  13. package/dist/app-server/app-run-artifacts.js.map +1 -0
  14. package/dist/app-server/assistant-common.d.ts +27 -37
  15. package/dist/app-server/assistant-common.d.ts.map +1 -1
  16. package/dist/app-server/assistant-common.js +110 -1
  17. package/dist/app-server/assistant-common.js.map +1 -1
  18. package/dist/app-server/assistant-events.d.ts +8 -28
  19. package/dist/app-server/browser-launch.d.ts +3 -3
  20. package/dist/app-server/browser-launch.js.map +1 -1
  21. package/dist/app-server/browser-provider-learning.d.ts +26 -0
  22. package/dist/app-server/browser-provider-learning.d.ts.map +1 -0
  23. package/dist/app-server/browser-provider-learning.js +353 -0
  24. package/dist/app-server/browser-provider-learning.js.map +1 -0
  25. package/dist/app-server/config-store.d.ts +13 -21
  26. package/dist/app-server/connection-test-routes.d.ts +8 -0
  27. package/dist/app-server/connection-test-routes.d.ts.map +1 -0
  28. package/dist/app-server/connection-test-routes.js +34 -0
  29. package/dist/app-server/connection-test-routes.js.map +1 -0
  30. package/dist/app-server/decision-routes.d.ts +8 -0
  31. package/dist/app-server/decision-routes.d.ts.map +1 -0
  32. package/dist/app-server/decision-routes.js +27 -0
  33. package/dist/app-server/decision-routes.js.map +1 -0
  34. package/dist/app-server/dev-mcp.d.ts +2 -5
  35. package/dist/app-server/evals-routes.d.ts +8 -18
  36. package/dist/app-server/evaluation-group-results.d.ts +11 -0
  37. package/dist/app-server/evaluation-group-results.d.ts.map +1 -0
  38. package/dist/app-server/evaluation-group-results.js +46 -0
  39. package/dist/app-server/evaluation-group-results.js.map +1 -0
  40. package/dist/app-server/evaluation-journal-projection.d.ts +9 -0
  41. package/dist/app-server/evaluation-journal-projection.d.ts.map +1 -0
  42. package/dist/app-server/evaluation-journal-projection.js +76 -0
  43. package/dist/app-server/evaluation-journal-projection.js.map +1 -0
  44. package/dist/app-server/evaluation-journal-writer.d.ts +23 -0
  45. package/dist/app-server/evaluation-journal-writer.d.ts.map +1 -0
  46. package/dist/app-server/evaluation-journal-writer.js +41 -0
  47. package/dist/app-server/evaluation-journal-writer.js.map +1 -0
  48. package/dist/app-server/evaluation-result-projection.d.ts +12 -0
  49. package/dist/app-server/evaluation-result-projection.d.ts.map +1 -0
  50. package/dist/app-server/evaluation-result-projection.js +107 -0
  51. package/dist/app-server/evaluation-result-projection.js.map +1 -0
  52. package/dist/app-server/execution-journal.d.ts +13 -0
  53. package/dist/app-server/execution-journal.d.ts.map +1 -0
  54. package/dist/app-server/execution-journal.js +39 -0
  55. package/dist/app-server/execution-journal.js.map +1 -0
  56. package/dist/app-server/http.d.ts +1 -1
  57. package/dist/app-server/index.d.ts +1 -1
  58. package/dist/app-server/inspectr-session-manager.d.ts +45 -0
  59. package/dist/app-server/inspectr-session-manager.d.ts.map +1 -0
  60. package/dist/app-server/inspectr-session-manager.js +203 -0
  61. package/dist/app-server/inspectr-session-manager.js.map +1 -0
  62. package/dist/app-server/jobs.d.ts +6 -9
  63. package/dist/app-server/libraries-store.d.ts +26 -10
  64. package/dist/app-server/libraries-store.d.ts.map +1 -1
  65. package/dist/app-server/libraries-store.js +130 -3
  66. package/dist/app-server/libraries-store.js.map +1 -1
  67. package/dist/app-server/live-tests-routes.d.ts +17 -0
  68. package/dist/app-server/live-tests-routes.d.ts.map +1 -0
  69. package/dist/app-server/live-tests-routes.js +82 -0
  70. package/dist/app-server/live-tests-routes.js.map +1 -0
  71. package/dist/app-server/live-tests.d.ts +78 -0
  72. package/dist/app-server/live-tests.d.ts.map +1 -0
  73. package/dist/app-server/live-tests.js +285 -0
  74. package/dist/app-server/live-tests.js.map +1 -0
  75. package/dist/app-server/markdown-reports.d.ts +7 -7
  76. package/dist/app-server/oauth-debugger-domain.d.ts +183 -207
  77. package/dist/app-server/oauth-debugger-domain.js.map +1 -1
  78. package/dist/app-server/oauth-debugger.d.ts +10 -17
  79. package/dist/app-server/oauth-debugger.js +1 -1
  80. package/dist/app-server/oauth-debugger.js.map +1 -1
  81. package/dist/app-server/oauth-runtime-domain.d.ts +42 -53
  82. package/dist/app-server/oauth-runtime-domain.js.map +1 -1
  83. package/dist/app-server/oauth-runtime-routes.d.ts +12 -12
  84. package/dist/app-server/oauth-session-manager.d.ts +44 -50
  85. package/dist/app-server/oauth-session-manager.d.ts.map +1 -1
  86. package/dist/app-server/oauth-session-manager.js.map +1 -1
  87. package/dist/app-server/provider-models.d.ts +2 -7
  88. package/dist/app-server/provider-models.d.ts.map +1 -1
  89. package/dist/app-server/provider-models.js +11 -12
  90. package/dist/app-server/provider-models.js.map +1 -1
  91. package/dist/app-server/request-origin.d.ts +6 -0
  92. package/dist/app-server/request-origin.d.ts.map +1 -0
  93. package/dist/app-server/request-origin.js +61 -0
  94. package/dist/app-server/request-origin.js.map +1 -0
  95. package/dist/app-server/result-assistant-domain.d.ts +66 -82
  96. package/dist/app-server/result-assistant-domain.d.ts.map +1 -1
  97. package/dist/app-server/result-assistant-domain.js.map +1 -1
  98. package/dist/app-server/result-assistant-tools.d.ts +5 -5
  99. package/dist/app-server/result-assistant.d.ts +9 -21
  100. package/dist/app-server/result-assistant.js.map +1 -1
  101. package/dist/app-server/router.d.ts +7 -1
  102. package/dist/app-server/router.d.ts.map +1 -1
  103. package/dist/app-server/router.js +375 -57
  104. package/dist/app-server/router.js.map +1 -1
  105. package/dist/app-server/rover-connection.d.ts +48 -0
  106. package/dist/app-server/rover-connection.d.ts.map +1 -0
  107. package/dist/app-server/rover-connection.js +172 -0
  108. package/dist/app-server/rover-connection.js.map +1 -0
  109. package/dist/app-server/run-agent-selection.d.ts +2 -5
  110. package/dist/app-server/run-queue-domain.d.ts +89 -65
  111. package/dist/app-server/run-queue-domain.d.ts.map +1 -1
  112. package/dist/app-server/run-queue-domain.js +723 -9
  113. package/dist/app-server/run-queue-domain.js.map +1 -1
  114. package/dist/app-server/run-queue-events.d.ts +3 -10
  115. package/dist/app-server/run-queue-events.d.ts.map +1 -1
  116. package/dist/app-server/run-queue-events.js +114 -14
  117. package/dist/app-server/run-queue-events.js.map +1 -1
  118. package/dist/app-server/run-queue-executor.d.ts +22 -48
  119. package/dist/app-server/run-queue-executor.d.ts.map +1 -1
  120. package/dist/app-server/run-queue-executor.js +91 -30
  121. package/dist/app-server/run-queue-executor.js.map +1 -1
  122. package/dist/app-server/run-queue-state.d.ts +81 -47
  123. package/dist/app-server/run-queue-state.d.ts.map +1 -1
  124. package/dist/app-server/run-queue-state.js.map +1 -1
  125. package/dist/app-server/runs-routes.d.ts +13 -35
  126. package/dist/app-server/runs-routes.d.ts.map +1 -1
  127. package/dist/app-server/runs-routes.js +196 -29
  128. package/dist/app-server/runs-routes.js.map +1 -1
  129. package/dist/app-server/runs-routes.test-helpers.d.ts +42 -38
  130. package/dist/app-server/runs-routes.test-helpers.d.ts.map +1 -1
  131. package/dist/app-server/runs-routes.test-helpers.js +4 -1
  132. package/dist/app-server/runs-routes.test-helpers.js.map +1 -1
  133. package/dist/app-server/runs-store.d.ts +60 -43
  134. package/dist/app-server/runs-store.d.ts.map +1 -1
  135. package/dist/app-server/runs-store.js +157 -70
  136. package/dist/app-server/runs-store.js.map +1 -1
  137. package/dist/app-server/scenario-assistant-domain.d.ts +131 -157
  138. package/dist/app-server/scenario-assistant-domain.d.ts.map +1 -1
  139. package/dist/app-server/scenario-assistant-domain.js +7 -15
  140. package/dist/app-server/scenario-assistant-domain.js.map +1 -1
  141. package/dist/app-server/scenario-assistant.d.ts +10 -26
  142. package/dist/app-server/scenario-assistant.js.map +1 -1
  143. package/dist/app-server/settings-store.d.ts +4 -8
  144. package/dist/app-server/settings-store.d.ts.map +1 -1
  145. package/dist/app-server/settings-store.js +33 -15
  146. package/dist/app-server/settings-store.js.map +1 -1
  147. package/dist/app-server/static-serving.d.ts +7 -13
  148. package/dist/app-server/store-utils.d.ts +1 -1
  149. package/dist/app-server/tool-analysis-domain.d.ts +167 -183
  150. package/dist/app-server/tool-analysis-domain.d.ts.map +1 -1
  151. package/dist/app-server/tool-analysis-domain.js +2 -59
  152. package/dist/app-server/tool-analysis-domain.js.map +1 -1
  153. package/dist/app-server/tool-analysis-storage.d.ts +20 -34
  154. package/dist/app-server/tool-analysis.d.ts +10 -19
  155. package/dist/app-server/types.d.ts +26 -27
  156. package/dist/app-server/types.d.ts.map +1 -1
  157. package/dist/app-server/version-info.d.ts +6 -6
  158. package/dist/app-server/version-info.js.map +1 -1
  159. package/dist/app-server/workspace-paths.d.ts +2 -1
  160. package/dist/app-server/workspace-paths.d.ts.map +1 -1
  161. package/dist/app-server/workspace-paths.js +5 -1
  162. package/dist/app-server/workspace-paths.js.map +1 -1
  163. package/dist/cli-branding.d.ts +1 -1
  164. package/dist/cli-branding.js.map +1 -1
  165. package/dist/cli.d.ts +1 -1
  166. package/dist/cli.js +5 -6
  167. package/dist/cli.js.map +1 -1
  168. package/dist/eval-config-files.d.ts +5 -8
  169. package/dist/interactive-helpers.d.ts +11 -15
  170. package/dist/migrate-utils.d.ts +1 -1
  171. package/dist/results/context.d.ts +1 -1
  172. package/dist/results/format.d.ts +7 -14
  173. package/dist/results/indexer.d.ts +2 -9
  174. package/dist/results/search.d.ts +1 -1
  175. package/dist/results/types.d.ts +2 -11
  176. package/dist/run-interactive.d.ts +21 -23
  177. package/dist/test-results-fixture.d.ts +4 -4
  178. package/package.json +8 -6
  179. package/dist/app/assets/index-Bxq-wlTN.css +0 -1
  180. package/dist/app/assets/index-j_NpCqyK.js +0 -258
  181. package/dist/app/assets/sse-queue-worker-BMo6aPaB.js +0 -1
@@ -0,0 +1,9 @@
1
+ import type { ResultsJson } from '@inspectr/mcplab-core';
2
+ export declare function projectEvaluationJournal(params: {
3
+ runsDir: string;
4
+ evaluationRunId: string;
5
+ evaluationName?: string;
6
+ runNote?: string;
7
+ executionStatus?: 'stopped';
8
+ }): ResultsJson | null;
9
+ //# sourceMappingURL=evaluation-journal-projection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluation-journal-projection.d.ts","sourceRoot":"","sources":["../../src/app-server/evaluation-journal-projection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAKzD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,SAAS,CAAC;CAC7B,GAAG,WAAW,GAAG,IAAI,CA2ErB"}
@@ -0,0 +1,76 @@
1
+ import { join } from 'node:path';
2
+ import { projectEvaluationResult } from './evaluation-result-projection.js';
3
+ import { persistAppRunArtifacts } from './app-run-artifacts.js';
4
+ import { readExecutionEvents } from './execution-journal.js';
5
+ export function projectEvaluationJournal(params) {
6
+ const events = readExecutionEvents(join(params.runsDir, params.evaluationRunId));
7
+ const executions = events
8
+ .filter((event) => event.type === 'execution_completed' && event.results)
9
+ .reduce((results, event) => {
10
+ const executionId = event.executionId ?? event.results.metadata.run_id;
11
+ if (results.some((result) => result.metadata.run_id === executionId))
12
+ return results;
13
+ results.push(event.results);
14
+ return results;
15
+ }, []);
16
+ if (executions.length === 0)
17
+ return null;
18
+ const failedExecutions = new Set(events
19
+ .filter((event) => event.type === 'execution_failed')
20
+ .map((event) => event.executionId ?? event.eventId));
21
+ const stoppedExecutions = new Set(events
22
+ .filter((event) => event.type === 'execution_stopped' || event.type === 'evaluation_stopped')
23
+ .map((event) => event.executionId ?? event.eventId));
24
+ const executionTraceRecords = events
25
+ .filter((event) => event.type === 'execution_completed' && Array.isArray(event.traceRecords))
26
+ .flatMap((event) => event.traceRecords);
27
+ const roverTraceEvents = events.filter((event) => event.type === 'rover_event');
28
+ const traceRecords = [...executionTraceRecords, ...roverTraceEvents].sort((a, b) => {
29
+ const timestamp = (record) => typeof record.ts === 'string'
30
+ ? Date.parse(record.ts)
31
+ : typeof record.ts_start === 'string'
32
+ ? Date.parse(record.ts_start)
33
+ : 0;
34
+ return timestamp(a) - timestamp(b);
35
+ });
36
+ const results = projectEvaluationResult({
37
+ evaluationRunId: params.evaluationRunId,
38
+ runId: params.evaluationRunId,
39
+ evaluationName: params.evaluationName,
40
+ runNote: params.runNote,
41
+ executions,
42
+ failedExecutions: failedExecutions.size,
43
+ stoppedExecutions: stoppedExecutions.size
44
+ });
45
+ if (params.executionStatus || stoppedExecutions.size > 0)
46
+ results.metadata.execution_status = 'stopped';
47
+ const start = events.find((event) => event.type === 'evaluation_started');
48
+ if (typeof start?.newConversationBeforeStart === 'boolean')
49
+ results.metadata.rerun_new_conversation_before_start = start.newConversationBeforeStart;
50
+ if (typeof start?.newConversationBetweenScenarios === 'boolean')
51
+ results.metadata.rerun_new_conversation_between_scenarios =
52
+ start.newConversationBetweenScenarios;
53
+ persistAppRunArtifacts({
54
+ runDir: join(params.runsDir, params.evaluationRunId),
55
+ results,
56
+ resolvedConfig: {
57
+ evaluation_run_id: params.evaluationRunId,
58
+ evaluation_name: params.evaluationName
59
+ },
60
+ ...(traceRecords.length > 0
61
+ ? {
62
+ traceRecords: [
63
+ {
64
+ type: 'trace_meta',
65
+ trace_version: 3,
66
+ run_id: params.evaluationRunId,
67
+ ts: new Date().toISOString()
68
+ },
69
+ ...traceRecords
70
+ ]
71
+ }
72
+ : {})
73
+ });
74
+ return results;
75
+ }
76
+ //# sourceMappingURL=evaluation-journal-projection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluation-journal-projection.js","sourceRoot":"","sources":["../../src/app-server/evaluation-journal-projection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { ResultsJson, ScenarioRunTraceRecord } from '@inspectr/mcplab-core';
2
+ import { appendExecutionEvent } from './execution-journal.js';
3
+ type JournalWriterOptions = {
4
+ runsDir: string;
5
+ evaluationRunId: string;
6
+ evaluationName?: string;
7
+ runNote?: string;
8
+ appendEvent?: typeof appendExecutionEvent;
9
+ };
10
+ export declare function recordEvaluationExecution(options: JournalWriterOptions & {
11
+ executionId: string;
12
+ results: ResultsJson;
13
+ traceRecords?: ScenarioRunTraceRecord[];
14
+ executionSource: 'mcplab' | 'rover';
15
+ eventId?: string;
16
+ }): ResultsJson | null;
17
+ export declare function recordEvaluationTerminalExecution(options: JournalWriterOptions & {
18
+ executionId: string;
19
+ status: 'error' | 'stopped';
20
+ reason: string;
21
+ }): ResultsJson | null;
22
+ export {};
23
+ //# sourceMappingURL=evaluation-journal-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluation-journal-writer.d.ts","sourceRoot":"","sources":["../../src/app-server/evaluation-journal-writer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAA8B,MAAM,wBAAwB,CAAC;AAG1F,KAAK,oBAAoB,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,oBAAoB,CAAC;CAC3C,CAAC;AAEF,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,oBAAoB,GAAG;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACxC,eAAe,EAAE,QAAQ,GAAG,OAAO,CAAC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACA,WAAW,GAAG,IAAI,CAqBpB;AAED,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,oBAAoB,GAAG;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB,GACA,WAAW,GAAG,IAAI,CAoBpB"}
@@ -0,0 +1,41 @@
1
+ import { join } from 'node:path';
2
+ import { appendExecutionEvent } from './execution-journal.js';
3
+ import { projectEvaluationJournal } from './evaluation-journal-projection.js';
4
+ export function recordEvaluationExecution(options) {
5
+ const event = {
6
+ eventId: options.eventId ?? `${options.executionSource}-result-${options.executionId}`,
7
+ type: 'execution_completed',
8
+ ts: new Date().toISOString(),
9
+ evaluationRunId: options.evaluationRunId,
10
+ executionId: options.executionId,
11
+ executionSource: options.executionSource,
12
+ results: options.results,
13
+ ...(options.traceRecords ? { traceRecords: options.traceRecords } : {})
14
+ };
15
+ (options.appendEvent ?? appendExecutionEvent)(join(options.runsDir, options.evaluationRunId), event);
16
+ return projectEvaluationJournal({
17
+ runsDir: options.runsDir,
18
+ evaluationRunId: options.evaluationRunId,
19
+ evaluationName: options.evaluationName,
20
+ runNote: options.runNote
21
+ });
22
+ }
23
+ export function recordEvaluationTerminalExecution(options) {
24
+ const event = {
25
+ eventId: `execution-${options.status}-${options.executionId}`,
26
+ type: options.status === 'error' ? 'execution_failed' : 'execution_stopped',
27
+ ts: new Date().toISOString(),
28
+ executionId: options.executionId,
29
+ evaluationRunId: options.evaluationRunId,
30
+ reason: options.reason
31
+ };
32
+ (options.appendEvent ?? appendExecutionEvent)(join(options.runsDir, options.evaluationRunId), event);
33
+ return projectEvaluationJournal({
34
+ runsDir: options.runsDir,
35
+ evaluationRunId: options.evaluationRunId,
36
+ evaluationName: options.evaluationName,
37
+ runNote: options.runNote,
38
+ ...(options.status === 'stopped' ? { executionStatus: 'stopped' } : {})
39
+ });
40
+ }
41
+ //# sourceMappingURL=evaluation-journal-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluation-journal-writer.js","sourceRoot":"","sources":["../../src/app-server/evaluation-journal-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,oBAAoB,EAA8B,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAU9E,MAAM,UAAU,yBAAyB,CACvC,OAMC;IAED,MAAM,KAAK,GAA0B;QACnC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,GAAG,OAAO,CAAC,eAAe,WAAW,OAAO,CAAC,WAAW,EAAE;QACtF,IAAI,EAAE,qBAAqB;QAC3B,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC5B,eAAe,EAAE,OAAO,CAAC,eAAe;QACxC,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,eAAe,EAAE,OAAO,CAAC,eAAe;QACxC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxE,CAAC;IACF,CAAC,OAAO,CAAC,WAAW,IAAI,oBAAoB,CAAC,CAC3C,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,EAC9C,KAAK,CACN,CAAC;IACF,OAAO,wBAAwB,CAAC;QAC9B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,eAAe,EAAE,OAAO,CAAC,eAAe;QACxC,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iCAAiC,CAC/C,OAIC;IAED,MAAM,KAAK,GAA0B;QACnC,OAAO,EAAE,aAAa,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,WAAW,EAAE;QAC7D,IAAI,EAAE,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,mBAAmB;QAC3E,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,eAAe,EAAE,OAAO,CAAC,eAAe;QACxC,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC;IACF,CAAC,OAAO,CAAC,WAAW,IAAI,oBAAoB,CAAC,CAC3C,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,EAC9C,KAAK,CACN,CAAC;IACF,OAAO,wBAAwB,CAAC;QAC9B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,eAAe,EAAE,OAAO,CAAC,eAAe;QACxC,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,SAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACjF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ResultsJson } from '@inspectr/mcplab-core';
2
+ /** Project completed execution snapshots into the single canonical evaluation result. */
3
+ export declare function projectEvaluationResult(params: {
4
+ evaluationRunId: string;
5
+ runId: string;
6
+ executions: ResultsJson[];
7
+ evaluationName?: string;
8
+ runNote?: string;
9
+ failedExecutions?: number;
10
+ stoppedExecutions?: number;
11
+ }): ResultsJson;
12
+ //# sourceMappingURL=evaluation-result-projection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluation-result-projection.d.ts","sourceRoot":"","sources":["../../src/app-server/evaluation-result-projection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,uBAAuB,CAAC;AAErE,yFAAyF;AACzF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC9C,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,WAAW,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,GAAG,WAAW,CAmId"}
@@ -0,0 +1,107 @@
1
+ import { calculatePassRate } from '@inspectr/mcplab-core';
2
+ /** Project completed execution snapshots into the single canonical evaluation result. */
3
+ export function projectEvaluationResult(params) {
4
+ const executions = params.executions;
5
+ const failedExecutions = params.failedExecutions ?? 0;
6
+ const stoppedExecutions = params.stoppedExecutions ?? 0;
7
+ const totalRuns = executions.reduce((sum, result) => sum + result.summary.total_runs, 0) +
8
+ failedExecutions +
9
+ stoppedExecutions;
10
+ const totalScenarios = executions.reduce((sum, result) => sum + result.summary.total_scenarios, 0);
11
+ const weighted = (field) => {
12
+ if (totalRuns === 0)
13
+ return null;
14
+ const values = executions.map((result) => result.summary[field]);
15
+ if (field === 'avg_tool_latency_ms' && values.some((value) => value === null))
16
+ return null;
17
+ return (executions.reduce((sum, result) => sum + (result.summary[field] ?? 0) * result.summary.total_runs, 0) / totalRuns);
18
+ };
19
+ const outcomes = {
20
+ passed: 0,
21
+ failed: failedExecutions,
22
+ incomplete: 0,
23
+ error: 0,
24
+ stopped: stoppedExecutions
25
+ };
26
+ for (const result of executions) {
27
+ for (const outcome of Object.keys(outcomes)) {
28
+ outcomes[outcome] = (outcomes[outcome] ?? 0) + (result.summary.outcomes?.[outcome] ?? 0);
29
+ }
30
+ }
31
+ if (outcomes.stopped === 0)
32
+ delete outcomes.stopped;
33
+ const sourceMetadata = executions[0]?.metadata;
34
+ const configPaths = Array.from(new Set(executions.map((result) => result.metadata.config_path).filter(Boolean)));
35
+ const rerunAgents = Array.from(new Set(executions.flatMap((result) => result.metadata.rerun_agents ?? [])));
36
+ const rerunScenarioIds = Array.from(new Set(executions.flatMap((result) => result.metadata.rerun_scenario_ids ?? [])));
37
+ // Children share evaluation overrides, but Rover snapshots may omit them and
38
+ // MCP snapshots contain only the overrides for their selected scenarios.
39
+ const serverOverrideAll = executions.find((result) => (result.metadata.rerun_server_override_all?.length ?? 0) > 0)?.metadata.rerun_server_override_all;
40
+ const scenarioServerOverrides = Object.fromEntries(executions.flatMap((result) => Object.entries(result.metadata.rerun_scenario_server_overrides ?? {})));
41
+ const executionSources = new Set(executions.map((result) => result.metadata.execution_source).filter(Boolean));
42
+ const executionClients = new Set(executions.map((result) => result.metadata.execution_client).filter(Boolean));
43
+ const aggregateNumericMetadata = (key) => {
44
+ const values = executions.map((result) => result.metadata[key]);
45
+ const numericValues = values.filter((value) => typeof value === 'number' && Number.isFinite(value));
46
+ if (values.length === 0 || numericValues.length !== values.length) {
47
+ return undefined;
48
+ }
49
+ return numericValues.reduce((sum, value) => sum + value, 0);
50
+ };
51
+ const mcpServerVersions = new Map();
52
+ for (const execution of executions) {
53
+ for (const [serverId, version] of Object.entries(execution.metadata.mcp_server_versions ?? {})) {
54
+ const previous = mcpServerVersions.get(serverId);
55
+ if (!mcpServerVersions.has(serverId))
56
+ mcpServerVersions.set(serverId, version);
57
+ else if (previous !== version)
58
+ mcpServerVersions.set(serverId, null);
59
+ }
60
+ }
61
+ const toolTokensTotal = aggregateNumericMetadata('tool_tokens_total');
62
+ const totalDurationMs = aggregateNumericMetadata('total_duration_ms');
63
+ const totalToolDurationMs = aggregateNumericMetadata('total_tool_duration_ms');
64
+ const executionClient = executionClients.size === 1
65
+ ? Array.from(executionClients)[0]
66
+ : executionClients.size > 1
67
+ ? 'mixed'
68
+ : undefined;
69
+ return {
70
+ metadata: {
71
+ run_id: params.runId,
72
+ timestamp: new Date().toISOString(),
73
+ config_hash: sourceMetadata?.config_hash ?? params.evaluationRunId,
74
+ config_path: configPaths.length === 1 ? configPaths[0] : undefined,
75
+ cli_version: sourceMetadata?.cli_version ?? 'unknown',
76
+ mcp_server_versions: Object.fromEntries(mcpServerVersions),
77
+ ...(toolTokensTotal !== undefined ? { tool_tokens_total: toolTokensTotal } : {}),
78
+ ...(totalDurationMs !== undefined ? { total_duration_ms: totalDurationMs } : {}),
79
+ ...(totalToolDurationMs !== undefined ? { total_tool_duration_ms: totalToolDurationMs } : {}),
80
+ ...(executionClient ? { execution_client: executionClient } : {}),
81
+ ...(executionSources.size === 1
82
+ ? { execution_source: executions[0]?.metadata.execution_source }
83
+ : {}),
84
+ config_name: params.evaluationName ||
85
+ sourceMetadata?.config_name ||
86
+ `Evaluation ${params.evaluationRunId}`,
87
+ ...(params.runNote?.trim() ? { run_note: params.runNote.trim() } : {}),
88
+ ...(rerunAgents.length > 0 ? { rerun_agents: rerunAgents } : {}),
89
+ ...(rerunScenarioIds.length > 0 ? { rerun_scenario_ids: rerunScenarioIds } : {}),
90
+ ...(serverOverrideAll ? { rerun_server_override_all: [...serverOverrideAll] } : {}),
91
+ ...(Object.keys(scenarioServerOverrides).length > 0
92
+ ? { rerun_scenario_server_overrides: scenarioServerOverrides }
93
+ : {}),
94
+ evaluation_run_id: params.runId
95
+ },
96
+ summary: {
97
+ total_scenarios: totalScenarios,
98
+ total_runs: totalRuns,
99
+ pass_rate: calculatePassRate(outcomes.passed ?? 0, totalRuns, outcomes.stopped),
100
+ avg_tool_calls_per_run: weighted('avg_tool_calls_per_run') ?? 0,
101
+ avg_tool_latency_ms: weighted('avg_tool_latency_ms'),
102
+ outcomes
103
+ },
104
+ scenarios: executions.flatMap((result) => result.scenarios)
105
+ };
106
+ }
107
+ //# sourceMappingURL=evaluation-result-projection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluation-result-projection.js","sourceRoot":"","sources":["../../src/app-server/evaluation-result-projection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface ExecutionJournalEvent {
2
+ eventId: string;
3
+ type: string;
4
+ ts: string;
5
+ executionId?: string;
6
+ [key: string]: unknown;
7
+ }
8
+ export declare function journalPath(runDir: string): string;
9
+ export declare function appendExecutionEvent(runDir: string, event: ExecutionJournalEvent): void;
10
+ export declare function readExecutionEvents(runDir: string): ExecutionJournalEvent[];
11
+ export declare function readLatestResultSnapshot(runDir: string): ExecutionJournalEvent | null;
12
+ export declare function writeAtomicText(path: string, content: string): void;
13
+ //# sourceMappingURL=execution-journal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-journal.d.ts","sourceRoot":"","sources":["../../src/app-server/execution-journal.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB,GAAG,IAAI,CAGvF;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAiB3E;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAGrF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAInE"}
@@ -0,0 +1,39 @@
1
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ export function journalPath(runDir) {
4
+ return join(runDir, 'execution-events.jsonl');
5
+ }
6
+ export function appendExecutionEvent(runDir, event) {
7
+ mkdirSync(runDir, { recursive: true });
8
+ appendFileSync(journalPath(runDir), `${JSON.stringify(event)}\n`, 'utf8');
9
+ }
10
+ export function readExecutionEvents(runDir) {
11
+ const path = journalPath(runDir);
12
+ if (!existsSync(path))
13
+ return [];
14
+ return readFileSync(path, 'utf8')
15
+ .split('\n')
16
+ .map((line) => line.trim())
17
+ .filter(Boolean)
18
+ .flatMap((line) => {
19
+ try {
20
+ const value = JSON.parse(line);
21
+ return value && typeof value.eventId === 'string' && typeof value.type === 'string'
22
+ ? [value]
23
+ : [];
24
+ }
25
+ catch {
26
+ return [];
27
+ }
28
+ });
29
+ }
30
+ export function readLatestResultSnapshot(runDir) {
31
+ const snapshots = readExecutionEvents(runDir).filter((event) => event.type === 'result_snapshot');
32
+ return snapshots[snapshots.length - 1] ?? null;
33
+ }
34
+ export function writeAtomicText(path, content) {
35
+ const temporaryPath = `${path}.tmp-${process.pid}-${Date.now()}`;
36
+ writeFileSync(temporaryPath, content, 'utf8');
37
+ renameSync(temporaryPath, path);
38
+ }
39
+ //# sourceMappingURL=execution-journal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-journal.js","sourceRoot":"","sources":["../../src/app-server/execution-journal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,UAAU,EACV,SAAS,EACT,YAAY,EACZ,UAAU,EACV,aAAa,EACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAUjC,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,IAAI,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAc,EAAE,KAA4B;IAC/E,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,cAAc,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC;SAC9B,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,OAAO,CAAC;SACf,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAChB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA0B,CAAC;YACxD,OAAO,KAAK,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;gBACjF,CAAC,CAAC,CAAC,KAAK,CAAC;gBACT,CAAC,CAAC,EAAE,CAAC;QACT,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,MAAc;IACrD,MAAM,SAAS,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,iBAAiB,CAAC,CAAC;IAClG,OAAO,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,OAAe;IAC3D,MAAM,aAAa,GAAG,GAAG,IAAI,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACjE,aAAa,CAAC,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9C,UAAU,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;AAClC,CAAC"}
@@ -3,4 +3,4 @@ export declare function asJson(res: ServerResponse, code: number, body: unknown)
3
3
  export declare function asHtml(res: ServerResponse, code: number, body: string): void;
4
4
  export declare function asText(res: ServerResponse, code: number, body: string): void;
5
5
  export declare function parseBody(req: IncomingMessage): Promise<any>;
6
- //# sourceMappingURL=http.d.ts.map
6
+ //# sourceMappingURL=http.d.ts.map
@@ -1,3 +1,3 @@
1
1
  export type { AppServerOptions } from './types.js';
2
2
  export { startAppServer } from './router.js';
3
- //# sourceMappingURL=index.d.ts.map
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,45 @@
1
+ import type { McpRequestHeaderContext } from '@inspectr/mcplab-core';
2
+ export interface InspectrProxySession {
3
+ upstreamOrigin: string;
4
+ proxyOrigin: string;
5
+ dashboardUrl: string;
6
+ }
7
+ export declare function buildInspectrRequestHeaders(
8
+ context: McpRequestHeaderContext
9
+ ): Record<string, string>;
10
+ interface InspectrChild {
11
+ kill(signal?: NodeJS.Signals): boolean;
12
+ once(event: string, listener: (...args: any[]) => void): this;
13
+ }
14
+ interface InspectrSessionManagerOptions {
15
+ storageRoot: string;
16
+ commandPath?: string;
17
+ log?: (message: string) => void;
18
+ allocatePort?: () => Promise<number>;
19
+ spawn?: (
20
+ command: string,
21
+ args: string[],
22
+ options: {
23
+ cwd: string;
24
+ stdio: ['ignore', 'ignore', 'ignore'];
25
+ }
26
+ ) => InspectrChild;
27
+ waitForReady?: (session: InspectrProxySession, child: InspectrChild) => Promise<void>;
28
+ }
29
+ export declare class InspectrSessionManager {
30
+ private readonly storageRoot;
31
+ private readonly commandPath;
32
+ private readonly log;
33
+ private readonly allocatePort;
34
+ private readonly spawn;
35
+ private readonly waitForReady;
36
+ private readonly sessions;
37
+ private readonly starting;
38
+ constructor(options: InspectrSessionManagerOptions);
39
+ acquire(serverUrl: string): Promise<InspectrProxySession>;
40
+ closeAll(): Promise<void>;
41
+ private start;
42
+ }
43
+ export declare function rewriteUrlThroughInspectr(serverUrl: string, proxyOrigin: string): string;
44
+ export {};
45
+ //# sourceMappingURL=inspectr-session-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspectr-session-manager.d.ts","sourceRoot":"","sources":["../../src/app-server/inspectr-session-manager.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAErE,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,uBAAuB,GAC/B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYxB;AAED,UAAU,aAAa;IACrB,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IACvC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,IAAI,CAAC;CAC/D;AAED,UAAU,6BAA6B;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,CACN,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;KAAE,KAC5D,aAAa,CAAC;IACnB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvF;AAID,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA4B;IAChD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAwB;IACrD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsD;IAC5E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6D;IAC1F,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8C;gBAE3D,OAAO,EAAE,6BAA6B;IAS5C,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAczD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YAOjB,KAAK;CAiDpB;AA2BD,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAGxF"}
@@ -0,0 +1,203 @@
1
+ import { createHash, randomBytes } from 'node:crypto';
2
+ import { existsSync, mkdirSync, readFileSync } from 'node:fs';
3
+ import { spawn as defaultSpawn } from 'node:child_process';
4
+ import { createConnection, createServer } from 'node:net';
5
+ import { dirname, join } from 'node:path';
6
+ import { createRequire } from 'node:module';
7
+ export function buildInspectrRequestHeaders(context) {
8
+ const tags = [
9
+ 'mcplab',
10
+ `mcplab-run:${tagPart(context.runId)}`,
11
+ ...(context.scenarioId ? [`mcplab-scenario:${tagPart(context.scenarioId)}`] : []),
12
+ ...(context.agentName ? [`mcplab-agent:${tagPart(context.agentName)}`] : []),
13
+ `mcplab-server:${tagPart(context.serverName)}`
14
+ ];
15
+ return {
16
+ 'inspectr-tag': tags.join(', '),
17
+ 'inspectr-trace-id': context.requestId ?? `mcplab-run:${tagPart(context.runId)}`
18
+ };
19
+ }
20
+ export class InspectrSessionManager {
21
+ storageRoot;
22
+ commandPath;
23
+ log;
24
+ allocatePort;
25
+ spawn;
26
+ waitForReady;
27
+ sessions = new Map();
28
+ starting = new Map();
29
+ constructor(options) {
30
+ this.storageRoot = options.storageRoot;
31
+ this.commandPath = options.commandPath ?? resolveInspectrCommand();
32
+ this.log = options.log ?? console.log;
33
+ this.allocatePort = options.allocatePort ?? allocateFreePort;
34
+ this.spawn = options.spawn ?? ((command, args, spawnOptions) => defaultSpawn(command, args, spawnOptions));
35
+ this.waitForReady = options.waitForReady ?? waitForPorts;
36
+ }
37
+ async acquire(serverUrl) {
38
+ const upstreamOrigin = normalizeOrigin(serverUrl);
39
+ const existing = this.sessions.get(upstreamOrigin);
40
+ if (existing)
41
+ return existing;
42
+ const inFlight = this.starting.get(upstreamOrigin);
43
+ if (inFlight)
44
+ return inFlight;
45
+ const promise = this.start(upstreamOrigin).finally(() => {
46
+ this.starting.delete(upstreamOrigin);
47
+ });
48
+ this.starting.set(upstreamOrigin, promise);
49
+ return promise;
50
+ }
51
+ async closeAll() {
52
+ await Promise.allSettled(this.starting.values());
53
+ const sessions = [...this.sessions.values()];
54
+ this.sessions.clear();
55
+ await Promise.all(sessions.map((session) => stopChild(session.child)));
56
+ }
57
+ async start(upstreamOrigin) {
58
+ const proxyPort = await this.allocatePort();
59
+ const dashboardPort = await this.allocatePort();
60
+ const cwd = join(this.storageRoot, originKey(upstreamOrigin));
61
+ mkdirSync(cwd, { recursive: true });
62
+ const channel = `mcplab-${originKey(upstreamOrigin)}`;
63
+ const channelCode = randomBytes(16).toString('hex');
64
+ const dashboardUrl = new URL(`http://127.0.0.1:${dashboardPort}`);
65
+ dashboardUrl.searchParams.set('channel', channel);
66
+ dashboardUrl.searchParams.set('channelCode', channelCode);
67
+ const session = {
68
+ upstreamOrigin,
69
+ proxyOrigin: `http://127.0.0.1:${proxyPort}`,
70
+ dashboardUrl: dashboardUrl.toString()
71
+ };
72
+ const child = this.spawn(this.commandPath, [
73
+ `--listen=127.0.0.1:${proxyPort}`,
74
+ `--app-port=${dashboardPort}`,
75
+ `--backend=${upstreamOrigin}`,
76
+ `--channel=${channel}`,
77
+ `--channel-code=${channelCode}`,
78
+ '--print=false'
79
+ ], { cwd, stdio: ['ignore', 'ignore', 'ignore'] });
80
+ try {
81
+ await this.waitForReady(session, child);
82
+ }
83
+ catch (error) {
84
+ await stopChild(child);
85
+ throw new Error(`Inspectr failed to start for ${upstreamOrigin}: ${error instanceof Error ? error.message : String(error)}`);
86
+ }
87
+ this.log(`[mcplab-app] Inspectr started for ${session.upstreamOrigin}, proxy: ${session.proxyOrigin}, dashboard: ${session.dashboardUrl}`);
88
+ const managed = session;
89
+ Object.defineProperties(managed, {
90
+ child: { value: child, enumerable: false },
91
+ cwd: { value: cwd, enumerable: false }
92
+ });
93
+ this.sessions.set(upstreamOrigin, managed);
94
+ child.once('exit', () => {
95
+ if (this.sessions.get(upstreamOrigin) === managed)
96
+ this.sessions.delete(upstreamOrigin);
97
+ });
98
+ return managed;
99
+ }
100
+ }
101
+ function resolveInspectrCommand() {
102
+ const require = createRequire(import.meta.url);
103
+ const packageJsonPath = require.resolve('@inspectr/inspectr/package.json');
104
+ const manifest = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
105
+ const bin = typeof manifest.bin === 'string' ? manifest.bin : manifest.bin?.inspectr;
106
+ if (!bin)
107
+ throw new Error('Installed @inspectr/inspectr package has no inspectr executable');
108
+ const packageBin = join(dirname(packageJsonPath), bin);
109
+ return existsSync(packageBin) ? packageBin : 'inspectr';
110
+ }
111
+ function normalizeOrigin(serverUrl) {
112
+ let parsed;
113
+ try {
114
+ parsed = new URL(serverUrl);
115
+ }
116
+ catch {
117
+ throw new Error(`Inspectr requires an absolute MCP server URL: ${serverUrl}`);
118
+ }
119
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
120
+ throw new Error(`Inspectr supports HTTP MCP server URLs only: ${serverUrl}`);
121
+ }
122
+ return parsed.origin;
123
+ }
124
+ export function rewriteUrlThroughInspectr(serverUrl, proxyOrigin) {
125
+ const original = new URL(serverUrl);
126
+ return new URL(`${original.pathname}${original.search}`, proxyOrigin).toString();
127
+ }
128
+ function originKey(origin) {
129
+ return createHash('sha256').update(origin).digest('hex').slice(0, 16);
130
+ }
131
+ function tagPart(value) {
132
+ return value.trim().replace(/[\u0000-\u001f\u007f,]+/g, '_').slice(0, 120) || 'unknown';
133
+ }
134
+ async function allocateFreePort() {
135
+ const server = createServer();
136
+ await new Promise((resolve, reject) => {
137
+ server.once('error', reject);
138
+ server.listen(0, '127.0.0.1', () => resolve());
139
+ });
140
+ const address = server.address();
141
+ const port = typeof address === 'object' && address ? address.port : 0;
142
+ await new Promise((resolve) => server.close(() => resolve()));
143
+ if (!port)
144
+ throw new Error('Could not allocate a local Inspectr port');
145
+ return port;
146
+ }
147
+ async function waitForPorts(session, child) {
148
+ const ports = [new URL(session.proxyOrigin).port, new URL(session.dashboardUrl).port].map(Number);
149
+ let childExited = false;
150
+ const markExited = () => {
151
+ childExited = true;
152
+ };
153
+ child.once('error', markExited);
154
+ child.once('exit', markExited);
155
+ const deadline = Date.now() + 15_000;
156
+ let stableChecks = 0;
157
+ while (Date.now() < deadline) {
158
+ if (childExited)
159
+ throw new Error('Inspectr process exited during startup');
160
+ if (await Promise.all(ports.map(canConnect))) {
161
+ stableChecks += 1;
162
+ if (stableChecks >= 2 && (await hasDashboardConfig(session.dashboardUrl)))
163
+ return;
164
+ }
165
+ else {
166
+ stableChecks = 0;
167
+ }
168
+ await new Promise((resolve) => setTimeout(resolve, 50));
169
+ }
170
+ throw new Error('timed out waiting for Inspectr proxy and dashboard');
171
+ }
172
+ async function hasDashboardConfig(dashboardUrl) {
173
+ try {
174
+ const configUrl = new URL('/app/config', dashboardUrl);
175
+ const response = await fetch(configUrl, {
176
+ signal: AbortSignal.timeout(1_000)
177
+ });
178
+ if (!response.ok)
179
+ return false;
180
+ const config = (await response.json());
181
+ return Boolean(config.token && config.channel_code && config.sse_endpoint);
182
+ }
183
+ catch {
184
+ return false;
185
+ }
186
+ }
187
+ function canConnect(port) {
188
+ return new Promise((resolve) => {
189
+ const socket = createConnection({ host: '127.0.0.1', port });
190
+ socket.once('connect', () => {
191
+ socket.destroy();
192
+ resolve(true);
193
+ });
194
+ socket.once('error', () => {
195
+ socket.destroy();
196
+ resolve(false);
197
+ });
198
+ });
199
+ }
200
+ async function stopChild(child) {
201
+ child.kill('SIGTERM');
202
+ }
203
+ //# sourceMappingURL=inspectr-session-manager.js.map