@opensearch-project/agent-health 0.3.0 → 0.5.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 (518) hide show
  1. package/README.md +77 -6
  2. package/cli/dist/index.js +10072 -4502
  3. package/deployment/cloudformation/agent-health-observability.yaml +762 -0
  4. package/dist/assets/index-CCQRDlO0.js +243 -0
  5. package/dist/assets/index-CNHQVbcj.css +1 -0
  6. package/dist/index.html +2 -2
  7. package/docs/ARCHITECTURE.md +450 -0
  8. package/docs/BACKEND_JOB_QUEUE.md +405 -0
  9. package/docs/CLAUDE_CODE_TELEMETRY.md +283 -0
  10. package/docs/CLI.md +431 -0
  11. package/docs/CODING_AGENT_ANALYTICS.md +298 -0
  12. package/docs/CONFIGURATION.md +388 -0
  13. package/docs/CONNECTORS.md +536 -0
  14. package/docs/INSTRUMENT_WITH_OTEL.md +390 -0
  15. package/docs/ML-COMMONS-SETUP.md +289 -0
  16. package/docs/NPX_PACKAGING.md +195 -0
  17. package/docs/PERFORMANCE-MONITORING.md +200 -0
  18. package/docs/PERFORMANCE.md +390 -0
  19. package/docs/PI_PROFILING.md +169 -0
  20. package/docs/PLAN-non-agui-agent-support.md +525 -0
  21. package/docs/SDK.md +577 -0
  22. package/docs/SKILLS.md +264 -0
  23. package/docs/blogs/2026-02-28-opensearch-agent-health.md +200 -0
  24. package/docs/blogs/getting-started-blog.md +608 -0
  25. package/docs/diagrams/Agent-health.excalidraw +5656 -0
  26. package/docs/diagrams/architecture.png +0 -0
  27. package/docs/plans/field-redesign.md +468 -0
  28. package/docs/rfcs/001-coding-agent-analytics.md +374 -0
  29. package/docs/rfcs/002-enterprise-leaderboard.md +267 -0
  30. package/docs/rfcs/003-remote-aggregation.md +146 -0
  31. package/docs/rfcs/004-test-sdk-v2.md +599 -0
  32. package/docs/skills/AGENT_HEALTH.md +598 -0
  33. package/docs/skills/AGENT_PROFILE.md +191 -0
  34. package/docs/skills/add-connector/SKILL.md +68 -0
  35. package/docs/skills/agent-health-profile/SKILL.md +40 -0
  36. package/docs/skills/config-auth/SKILL.md +194 -0
  37. package/docs/skills/config-auth/evals/evals.json +35 -0
  38. package/docs/skills/create-pr/SKILL.md +73 -0
  39. package/docs/skills/instrument-otel/SKILL.md +84 -0
  40. package/docs/skills/write-test/SKILL.md +124 -0
  41. package/docs/ui prd.md +376 -0
  42. package/examples/README.md +53 -0
  43. package/examples/config/agent-health.config.example.ts +155 -0
  44. package/examples/connectors/echo-connector.ts +131 -0
  45. package/examples/eval-files/demo.eval.js +128 -0
  46. package/examples/eval-files/sdk-hooks-demo.eval.js +99 -0
  47. package/examples/pi-profiling/README.md +77 -0
  48. package/examples/pi-profiling/agent-health-profile.ts +417 -0
  49. package/lib/dist/lib/agentUtils.d.ts +29 -0
  50. package/lib/dist/lib/agentUtils.d.ts.map +1 -0
  51. package/lib/dist/lib/agentUtils.js +43 -0
  52. package/lib/dist/lib/agentUtils.js.map +1 -0
  53. package/lib/dist/lib/benchmarkExport.d.ts +14 -0
  54. package/lib/dist/lib/benchmarkExport.d.ts.map +1 -0
  55. package/lib/dist/lib/benchmarkExport.js +41 -0
  56. package/lib/dist/lib/benchmarkExport.js.map +1 -0
  57. package/lib/dist/lib/benchmarkVersionUtils.d.ts +37 -0
  58. package/lib/dist/lib/benchmarkVersionUtils.d.ts.map +1 -0
  59. package/lib/dist/lib/benchmarkVersionUtils.js +68 -0
  60. package/lib/dist/lib/benchmarkVersionUtils.js.map +1 -0
  61. package/lib/dist/lib/config/defineConfig.d.ts +27 -0
  62. package/lib/dist/lib/config/defineConfig.d.ts.map +1 -0
  63. package/lib/dist/lib/config/defineConfig.js +28 -0
  64. package/lib/dist/lib/config/defineConfig.js.map +1 -0
  65. package/lib/dist/lib/config/index.d.ts +9 -0
  66. package/lib/dist/lib/config/index.d.ts.map +1 -0
  67. package/lib/dist/lib/config/index.js +8 -0
  68. package/lib/dist/lib/config/index.js.map +1 -0
  69. package/lib/dist/lib/config/loader.d.ts +39 -0
  70. package/lib/dist/lib/config/loader.d.ts.map +1 -0
  71. package/lib/dist/lib/config/loader.js +258 -0
  72. package/lib/dist/lib/config/loader.js.map +1 -0
  73. package/lib/dist/lib/config/statePaths.d.ts +61 -0
  74. package/lib/dist/lib/config/statePaths.d.ts.map +1 -0
  75. package/lib/dist/lib/config/statePaths.js +188 -0
  76. package/lib/dist/lib/config/statePaths.js.map +1 -0
  77. package/lib/dist/lib/config/types.d.ts +231 -0
  78. package/lib/dist/lib/config/types.d.ts.map +1 -0
  79. package/lib/dist/lib/config/types.js +6 -0
  80. package/lib/dist/lib/config/types.js.map +1 -0
  81. package/lib/dist/lib/config.d.ts +39 -0
  82. package/lib/dist/lib/config.d.ts.map +1 -0
  83. package/lib/dist/lib/config.js +118 -0
  84. package/lib/dist/lib/config.js.map +1 -0
  85. package/lib/dist/lib/constants.d.ts +70 -0
  86. package/lib/dist/lib/constants.d.ts.map +1 -0
  87. package/lib/dist/lib/constants.js +365 -0
  88. package/lib/dist/lib/constants.js.map +1 -0
  89. package/lib/dist/lib/contextUtilization.d.ts +23 -0
  90. package/lib/dist/lib/contextUtilization.d.ts.map +1 -0
  91. package/lib/dist/lib/contextUtilization.js +72 -0
  92. package/lib/dist/lib/contextUtilization.js.map +1 -0
  93. package/lib/dist/lib/dashboardMetrics.d.ts +87 -0
  94. package/lib/dist/lib/dashboardMetrics.d.ts.map +1 -0
  95. package/lib/dist/lib/dashboardMetrics.js +242 -0
  96. package/lib/dist/lib/dashboardMetrics.js.map +1 -0
  97. package/lib/dist/lib/dataSourceConfig.d.ts +108 -0
  98. package/lib/dist/lib/dataSourceConfig.d.ts.map +1 -0
  99. package/lib/dist/lib/dataSourceConfig.js +166 -0
  100. package/lib/dist/lib/dataSourceConfig.js.map +1 -0
  101. package/lib/dist/lib/debug.d.ts +26 -0
  102. package/lib/dist/lib/debug.d.ts.map +1 -0
  103. package/lib/dist/lib/debug.js +132 -0
  104. package/lib/dist/lib/debug.js.map +1 -0
  105. package/lib/dist/lib/diagnostics.d.ts +28 -0
  106. package/lib/dist/lib/diagnostics.d.ts.map +1 -0
  107. package/lib/dist/lib/diagnostics.js +65 -0
  108. package/lib/dist/lib/diagnostics.js.map +1 -0
  109. package/lib/dist/lib/envCompat.d.ts +27 -0
  110. package/lib/dist/lib/envCompat.d.ts.map +1 -0
  111. package/lib/dist/lib/envCompat.js +73 -0
  112. package/lib/dist/lib/envCompat.js.map +1 -0
  113. package/lib/dist/lib/findPackageRoot.d.ts +7 -0
  114. package/lib/dist/lib/findPackageRoot.d.ts.map +1 -0
  115. package/lib/dist/lib/findPackageRoot.js +57 -0
  116. package/lib/dist/lib/findPackageRoot.js.map +1 -0
  117. package/lib/dist/lib/hooks.d.ts +36 -0
  118. package/lib/dist/lib/hooks.d.ts.map +1 -0
  119. package/lib/dist/lib/hooks.js +112 -0
  120. package/lib/dist/lib/hooks.js.map +1 -0
  121. package/lib/dist/lib/index.d.ts +47 -0
  122. package/lib/dist/lib/index.d.ts.map +1 -0
  123. package/lib/dist/lib/index.js +62 -0
  124. package/lib/dist/lib/index.js.map +1 -0
  125. package/lib/dist/lib/labels.d.ts +90 -0
  126. package/lib/dist/lib/labels.d.ts.map +1 -0
  127. package/lib/dist/lib/labels.js +158 -0
  128. package/lib/dist/lib/labels.js.map +1 -0
  129. package/lib/dist/lib/markdown.d.ts +16 -0
  130. package/lib/dist/lib/markdown.d.ts.map +1 -0
  131. package/lib/dist/lib/markdown.js +42 -0
  132. package/lib/dist/lib/markdown.js.map +1 -0
  133. package/lib/dist/lib/matchers/expect.d.ts +3 -0
  134. package/lib/dist/lib/matchers/expect.d.ts.map +1 -0
  135. package/lib/dist/lib/matchers/expect.js +225 -0
  136. package/lib/dist/lib/matchers/expect.js.map +1 -0
  137. package/lib/dist/lib/matchers/index.d.ts +8 -0
  138. package/lib/dist/lib/matchers/index.d.ts.map +1 -0
  139. package/lib/dist/lib/matchers/index.js +9 -0
  140. package/lib/dist/lib/matchers/index.js.map +1 -0
  141. package/lib/dist/lib/matchers/judgeAccessor.d.ts +113 -0
  142. package/lib/dist/lib/matchers/judgeAccessor.d.ts.map +1 -0
  143. package/lib/dist/lib/matchers/judgeAccessor.js +183 -0
  144. package/lib/dist/lib/matchers/judgeAccessor.js.map +1 -0
  145. package/lib/dist/lib/matchers/session.d.ts +39 -0
  146. package/lib/dist/lib/matchers/session.d.ts.map +1 -0
  147. package/lib/dist/lib/matchers/session.js +116 -0
  148. package/lib/dist/lib/matchers/session.js.map +1 -0
  149. package/lib/dist/lib/matchers/traces.d.ts +55 -0
  150. package/lib/dist/lib/matchers/traces.d.ts.map +1 -0
  151. package/lib/dist/lib/matchers/traces.js +116 -0
  152. package/lib/dist/lib/matchers/traces.js.map +1 -0
  153. package/lib/dist/lib/matchers/types.d.ts +75 -0
  154. package/lib/dist/lib/matchers/types.d.ts.map +1 -0
  155. package/lib/dist/lib/matchers/types.js +6 -0
  156. package/lib/dist/lib/matchers/types.js.map +1 -0
  157. package/lib/dist/lib/packagePaths.d.ts +29 -0
  158. package/lib/dist/lib/packagePaths.d.ts.map +1 -0
  159. package/lib/dist/lib/packagePaths.js +63 -0
  160. package/lib/dist/lib/packagePaths.js.map +1 -0
  161. package/lib/dist/lib/performance.d.ts +51 -0
  162. package/lib/dist/lib/performance.d.ts.map +1 -0
  163. package/lib/dist/lib/performance.js +159 -0
  164. package/lib/dist/lib/performance.js.map +1 -0
  165. package/lib/dist/lib/portConfig.d.ts +29 -0
  166. package/lib/dist/lib/portConfig.d.ts.map +1 -0
  167. package/lib/dist/lib/portConfig.js +64 -0
  168. package/lib/dist/lib/portConfig.js.map +1 -0
  169. package/lib/dist/lib/preferences.d.ts +63 -0
  170. package/lib/dist/lib/preferences.d.ts.map +1 -0
  171. package/lib/dist/lib/preferences.js +117 -0
  172. package/lib/dist/lib/preferences.js.map +1 -0
  173. package/lib/dist/lib/resolveAgentModel.d.ts +22 -0
  174. package/lib/dist/lib/resolveAgentModel.d.ts.map +1 -0
  175. package/lib/dist/lib/resolveAgentModel.js +37 -0
  176. package/lib/dist/lib/resolveAgentModel.js.map +1 -0
  177. package/lib/dist/lib/runStats.d.ts +92 -0
  178. package/lib/dist/lib/runStats.d.ts.map +1 -0
  179. package/lib/dist/lib/runStats.js +160 -0
  180. package/lib/dist/lib/runStats.js.map +1 -0
  181. package/lib/dist/lib/telemetry/constants.d.ts +60 -0
  182. package/lib/dist/lib/telemetry/constants.d.ts.map +1 -0
  183. package/lib/dist/lib/telemetry/constants.js +87 -0
  184. package/lib/dist/lib/telemetry/constants.js.map +1 -0
  185. package/lib/dist/lib/telemetry/evalSpans.d.ts +61 -0
  186. package/lib/dist/lib/telemetry/evalSpans.d.ts.map +1 -0
  187. package/lib/dist/lib/telemetry/evalSpans.js +254 -0
  188. package/lib/dist/lib/telemetry/evalSpans.js.map +1 -0
  189. package/lib/dist/lib/telemetry/index.d.ts +11 -0
  190. package/lib/dist/lib/telemetry/index.d.ts.map +1 -0
  191. package/lib/dist/lib/telemetry/index.js +15 -0
  192. package/lib/dist/lib/telemetry/index.js.map +1 -0
  193. package/lib/dist/lib/telemetry/opensearchExporter.d.ts +43 -0
  194. package/lib/dist/lib/telemetry/opensearchExporter.d.ts.map +1 -0
  195. package/lib/dist/lib/telemetry/opensearchExporter.js +217 -0
  196. package/lib/dist/lib/telemetry/opensearchExporter.js.map +1 -0
  197. package/lib/dist/lib/telemetry/provider.d.ts +55 -0
  198. package/lib/dist/lib/telemetry/provider.d.ts.map +1 -0
  199. package/lib/dist/lib/telemetry/provider.js +140 -0
  200. package/lib/dist/lib/telemetry/provider.js.map +1 -0
  201. package/lib/dist/lib/testCaseLabels.d.ts +34 -0
  202. package/lib/dist/lib/testCaseLabels.d.ts.map +1 -0
  203. package/lib/dist/lib/testCaseLabels.js +88 -0
  204. package/lib/dist/lib/testCaseLabels.js.map +1 -0
  205. package/lib/dist/lib/testCaseValidation.d.ts +140 -0
  206. package/lib/dist/lib/testCaseValidation.d.ts.map +1 -0
  207. package/lib/dist/lib/testCaseValidation.js +162 -0
  208. package/lib/dist/lib/testCaseValidation.js.map +1 -0
  209. package/lib/dist/lib/testCases/agentFixture.d.ts +80 -0
  210. package/lib/dist/lib/testCases/agentFixture.d.ts.map +1 -0
  211. package/lib/dist/lib/testCases/agentFixture.js +43 -0
  212. package/lib/dist/lib/testCases/agentFixture.js.map +1 -0
  213. package/lib/dist/lib/testCases/authoringSurface.d.ts +10 -0
  214. package/lib/dist/lib/testCases/authoringSurface.d.ts.map +1 -0
  215. package/lib/dist/lib/testCases/authoringSurface.js +54 -0
  216. package/lib/dist/lib/testCases/authoringSurface.js.map +1 -0
  217. package/lib/dist/lib/testCases/codemod.d.ts +13 -0
  218. package/lib/dist/lib/testCases/codemod.d.ts.map +1 -0
  219. package/lib/dist/lib/testCases/codemod.js +169 -0
  220. package/lib/dist/lib/testCases/codemod.js.map +1 -0
  221. package/lib/dist/lib/testCases/define.d.ts +114 -0
  222. package/lib/dist/lib/testCases/define.d.ts.map +1 -0
  223. package/lib/dist/lib/testCases/define.js +253 -0
  224. package/lib/dist/lib/testCases/define.js.map +1 -0
  225. package/lib/dist/lib/testCases/evaluators.d.ts +80 -0
  226. package/lib/dist/lib/testCases/evaluators.d.ts.map +1 -0
  227. package/lib/dist/lib/testCases/evaluators.js +105 -0
  228. package/lib/dist/lib/testCases/evaluators.js.map +1 -0
  229. package/lib/dist/lib/testCases/index.d.ts +14 -0
  230. package/lib/dist/lib/testCases/index.d.ts.map +1 -0
  231. package/lib/dist/lib/testCases/index.js +12 -0
  232. package/lib/dist/lib/testCases/index.js.map +1 -0
  233. package/lib/dist/lib/testCases/judge.d.ts +165 -0
  234. package/lib/dist/lib/testCases/judge.d.ts.map +1 -0
  235. package/lib/dist/lib/testCases/judge.js +359 -0
  236. package/lib/dist/lib/testCases/judge.js.map +1 -0
  237. package/lib/dist/lib/testCases/loader.d.ts +26 -0
  238. package/lib/dist/lib/testCases/loader.d.ts.map +1 -0
  239. package/lib/dist/lib/testCases/loader.js +149 -0
  240. package/lib/dist/lib/testCases/loader.js.map +1 -0
  241. package/lib/dist/lib/testCases/types.d.ts +242 -0
  242. package/lib/dist/lib/testCases/types.d.ts.map +1 -0
  243. package/lib/dist/lib/testCases/types.js +6 -0
  244. package/lib/dist/lib/testCases/types.js.map +1 -0
  245. package/lib/dist/lib/theme.d.ts +6 -0
  246. package/lib/dist/lib/theme.d.ts.map +1 -0
  247. package/lib/dist/lib/theme.js +36 -0
  248. package/lib/dist/lib/theme.js.map +1 -0
  249. package/lib/dist/lib/uiTelemetry.d.ts +7 -0
  250. package/lib/dist/lib/uiTelemetry.d.ts.map +1 -0
  251. package/lib/dist/lib/uiTelemetry.js +25 -0
  252. package/lib/dist/lib/uiTelemetry.js.map +1 -0
  253. package/lib/dist/lib/utils.d.ts +96 -0
  254. package/lib/dist/lib/utils.d.ts.map +1 -0
  255. package/lib/dist/lib/utils.js +232 -0
  256. package/lib/dist/lib/utils.js.map +1 -0
  257. package/lib/dist/lib/workflow/consolidate.d.ts +12 -0
  258. package/lib/dist/lib/workflow/consolidate.d.ts.map +1 -0
  259. package/lib/dist/lib/workflow/consolidate.js +33 -0
  260. package/lib/dist/lib/workflow/consolidate.js.map +1 -0
  261. package/lib/dist/lib/workflow/index.d.ts +13 -0
  262. package/lib/dist/lib/workflow/index.d.ts.map +1 -0
  263. package/lib/dist/lib/workflow/index.js +12 -0
  264. package/lib/dist/lib/workflow/index.js.map +1 -0
  265. package/lib/dist/lib/workflow/ledger.d.ts +30 -0
  266. package/lib/dist/lib/workflow/ledger.d.ts.map +1 -0
  267. package/lib/dist/lib/workflow/ledger.js +41 -0
  268. package/lib/dist/lib/workflow/ledger.js.map +1 -0
  269. package/lib/dist/lib/workflow/pool.d.ts +13 -0
  270. package/lib/dist/lib/workflow/pool.d.ts.map +1 -0
  271. package/lib/dist/lib/workflow/pool.js +44 -0
  272. package/lib/dist/lib/workflow/pool.js.map +1 -0
  273. package/lib/dist/lib/workflow/source.d.ts +22 -0
  274. package/lib/dist/lib/workflow/source.d.ts.map +1 -0
  275. package/lib/dist/lib/workflow/source.js +29 -0
  276. package/lib/dist/lib/workflow/source.js.map +1 -0
  277. package/lib/dist/lib/workflow/stepB.d.ts +71 -0
  278. package/lib/dist/lib/workflow/stepB.d.ts.map +1 -0
  279. package/lib/dist/lib/workflow/stepB.js +99 -0
  280. package/lib/dist/lib/workflow/stepB.js.map +1 -0
  281. package/lib/dist/lib/workflow/types.d.ts +86 -0
  282. package/lib/dist/lib/workflow/types.d.ts.map +1 -0
  283. package/lib/dist/lib/workflow/types.js +6 -0
  284. package/lib/dist/lib/workflow/types.js.map +1 -0
  285. package/lib/dist/lib/workflow/workflow.d.ts +119 -0
  286. package/lib/dist/lib/workflow/workflow.d.ts.map +1 -0
  287. package/lib/dist/lib/workflow/workflow.js +195 -0
  288. package/lib/dist/lib/workflow/workflow.js.map +1 -0
  289. package/lib/dist/services/agent/aguiConverter.d.ts +50 -0
  290. package/lib/dist/services/agent/aguiConverter.d.ts.map +1 -0
  291. package/lib/dist/services/agent/aguiConverter.js +449 -0
  292. package/lib/dist/services/agent/aguiConverter.js.map +1 -0
  293. package/lib/dist/services/agent/index.d.ts +10 -0
  294. package/lib/dist/services/agent/index.d.ts.map +1 -0
  295. package/lib/dist/services/agent/index.js +12 -0
  296. package/lib/dist/services/agent/index.js.map +1 -0
  297. package/lib/dist/services/agent/payloadBuilder.d.ts +33 -0
  298. package/lib/dist/services/agent/payloadBuilder.d.ts.map +1 -0
  299. package/lib/dist/services/agent/payloadBuilder.js +75 -0
  300. package/lib/dist/services/agent/payloadBuilder.js.map +1 -0
  301. package/lib/dist/services/agent/sseStream.d.ts +43 -0
  302. package/lib/dist/services/agent/sseStream.d.ts.map +1 -0
  303. package/lib/dist/services/agent/sseStream.js +223 -0
  304. package/lib/dist/services/agent/sseStream.js.map +1 -0
  305. package/lib/dist/services/connectors/agui/AGUIStreamingConnector.d.ts +44 -0
  306. package/lib/dist/services/connectors/agui/AGUIStreamingConnector.d.ts.map +1 -0
  307. package/lib/dist/services/connectors/agui/AGUIStreamingConnector.js +95 -0
  308. package/lib/dist/services/connectors/agui/AGUIStreamingConnector.js.map +1 -0
  309. package/lib/dist/services/connectors/base/BaseConnector.d.ts +81 -0
  310. package/lib/dist/services/connectors/base/BaseConnector.d.ts.map +1 -0
  311. package/lib/dist/services/connectors/base/BaseConnector.js +170 -0
  312. package/lib/dist/services/connectors/base/BaseConnector.js.map +1 -0
  313. package/lib/dist/services/connectors/claude-code/ClaudeCodeConnector.d.ts +116 -0
  314. package/lib/dist/services/connectors/claude-code/ClaudeCodeConnector.d.ts.map +1 -0
  315. package/lib/dist/services/connectors/claude-code/ClaudeCodeConnector.js +403 -0
  316. package/lib/dist/services/connectors/claude-code/ClaudeCodeConnector.js.map +1 -0
  317. package/lib/dist/services/connectors/index.d.ts +13 -0
  318. package/lib/dist/services/connectors/index.d.ts.map +1 -0
  319. package/lib/dist/services/connectors/index.js +32 -0
  320. package/lib/dist/services/connectors/index.js.map +1 -0
  321. package/lib/dist/services/connectors/kiro/KiroConnector.d.ts +48 -0
  322. package/lib/dist/services/connectors/kiro/KiroConnector.d.ts.map +1 -0
  323. package/lib/dist/services/connectors/kiro/KiroConnector.js +158 -0
  324. package/lib/dist/services/connectors/kiro/KiroConnector.js.map +1 -0
  325. package/lib/dist/services/connectors/langgraph/LangGraphConnector.d.ts +36 -0
  326. package/lib/dist/services/connectors/langgraph/LangGraphConnector.d.ts.map +1 -0
  327. package/lib/dist/services/connectors/langgraph/LangGraphConnector.js +175 -0
  328. package/lib/dist/services/connectors/langgraph/LangGraphConnector.js.map +1 -0
  329. package/lib/dist/services/connectors/mock/MockConnector.d.ts +37 -0
  330. package/lib/dist/services/connectors/mock/MockConnector.d.ts.map +1 -0
  331. package/lib/dist/services/connectors/mock/MockConnector.js +120 -0
  332. package/lib/dist/services/connectors/mock/MockConnector.js.map +1 -0
  333. package/lib/dist/services/connectors/openai-compatible/OpenAICompatibleConnector.d.ts +42 -0
  334. package/lib/dist/services/connectors/openai-compatible/OpenAICompatibleConnector.d.ts.map +1 -0
  335. package/lib/dist/services/connectors/openai-compatible/OpenAICompatibleConnector.js +133 -0
  336. package/lib/dist/services/connectors/openai-compatible/OpenAICompatibleConnector.js.map +1 -0
  337. package/lib/dist/services/connectors/pi/PiConnector.d.ts +87 -0
  338. package/lib/dist/services/connectors/pi/PiConnector.d.ts.map +1 -0
  339. package/lib/dist/services/connectors/pi/PiConnector.js +274 -0
  340. package/lib/dist/services/connectors/pi/PiConnector.js.map +1 -0
  341. package/lib/dist/services/connectors/registry.d.ts +57 -0
  342. package/lib/dist/services/connectors/registry.d.ts.map +1 -0
  343. package/lib/dist/services/connectors/registry.js +106 -0
  344. package/lib/dist/services/connectors/registry.js.map +1 -0
  345. package/lib/dist/services/connectors/rest/RESTConnector.d.ts +38 -0
  346. package/lib/dist/services/connectors/rest/RESTConnector.d.ts.map +1 -0
  347. package/lib/dist/services/connectors/rest/RESTConnector.js +117 -0
  348. package/lib/dist/services/connectors/rest/RESTConnector.js.map +1 -0
  349. package/lib/dist/services/connectors/server.d.ts +13 -0
  350. package/lib/dist/services/connectors/server.d.ts.map +1 -0
  351. package/lib/dist/services/connectors/server.js +34 -0
  352. package/lib/dist/services/connectors/server.js.map +1 -0
  353. package/lib/dist/services/connectors/strands/StrandsConnector.d.ts +48 -0
  354. package/lib/dist/services/connectors/strands/StrandsConnector.d.ts.map +1 -0
  355. package/lib/dist/services/connectors/strands/StrandsConnector.js +221 -0
  356. package/lib/dist/services/connectors/strands/StrandsConnector.js.map +1 -0
  357. package/lib/dist/services/connectors/subprocess/SubprocessConnector.d.ts +88 -0
  358. package/lib/dist/services/connectors/subprocess/SubprocessConnector.d.ts.map +1 -0
  359. package/lib/dist/services/connectors/subprocess/SubprocessConnector.js +418 -0
  360. package/lib/dist/services/connectors/subprocess/SubprocessConnector.js.map +1 -0
  361. package/lib/dist/services/connectors/types.d.ts +213 -0
  362. package/lib/dist/services/connectors/types.d.ts.map +1 -0
  363. package/lib/dist/services/connectors/types.js +6 -0
  364. package/lib/dist/services/connectors/types.js.map +1 -0
  365. package/lib/dist/services/evaluation/bedrockJudge.d.ts +64 -0
  366. package/lib/dist/services/evaluation/bedrockJudge.d.ts.map +1 -0
  367. package/lib/dist/services/evaluation/bedrockJudge.js +167 -0
  368. package/lib/dist/services/evaluation/bedrockJudge.js.map +1 -0
  369. package/lib/dist/services/evaluation/evaluatorError.d.ts +56 -0
  370. package/lib/dist/services/evaluation/evaluatorError.d.ts.map +1 -0
  371. package/lib/dist/services/evaluation/evaluatorError.js +56 -0
  372. package/lib/dist/services/evaluation/evaluatorError.js.map +1 -0
  373. package/lib/dist/services/evaluation/index.d.ts +106 -0
  374. package/lib/dist/services/evaluation/index.d.ts.map +1 -0
  375. package/lib/dist/services/evaluation/index.js +684 -0
  376. package/lib/dist/services/evaluation/index.js.map +1 -0
  377. package/lib/dist/services/evaluation/mockTrajectory.d.ts +3 -0
  378. package/lib/dist/services/evaluation/mockTrajectory.d.ts.map +1 -0
  379. package/lib/dist/services/evaluation/mockTrajectory.js +72 -0
  380. package/lib/dist/services/evaluation/mockTrajectory.js.map +1 -0
  381. package/lib/dist/services/opensearch/client.d.ts +26 -0
  382. package/lib/dist/services/opensearch/client.d.ts.map +1 -0
  383. package/lib/dist/services/opensearch/client.js +131 -0
  384. package/lib/dist/services/opensearch/client.js.map +1 -0
  385. package/lib/dist/services/opensearch/index.d.ts +16 -0
  386. package/lib/dist/services/opensearch/index.d.ts.map +1 -0
  387. package/lib/dist/services/opensearch/index.js +25 -0
  388. package/lib/dist/services/opensearch/index.js.map +1 -0
  389. package/lib/dist/services/storage/asyncBenchmarkStorage.d.ts +123 -0
  390. package/lib/dist/services/storage/asyncBenchmarkStorage.d.ts.map +1 -0
  391. package/lib/dist/services/storage/asyncBenchmarkStorage.js +429 -0
  392. package/lib/dist/services/storage/asyncBenchmarkStorage.js.map +1 -0
  393. package/lib/dist/services/storage/asyncRunStorage.d.ts +127 -0
  394. package/lib/dist/services/storage/asyncRunStorage.d.ts.map +1 -0
  395. package/lib/dist/services/storage/asyncRunStorage.js +448 -0
  396. package/lib/dist/services/storage/asyncRunStorage.js.map +1 -0
  397. package/lib/dist/services/storage/asyncTestCaseStorage.d.ts +156 -0
  398. package/lib/dist/services/storage/asyncTestCaseStorage.d.ts.map +1 -0
  399. package/lib/dist/services/storage/asyncTestCaseStorage.js +285 -0
  400. package/lib/dist/services/storage/asyncTestCaseStorage.js.map +1 -0
  401. package/lib/dist/services/storage/index.d.ts +17 -0
  402. package/lib/dist/services/storage/index.d.ts.map +1 -0
  403. package/lib/dist/services/storage/index.js +20 -0
  404. package/lib/dist/services/storage/index.js.map +1 -0
  405. package/lib/dist/services/storage/migration.d.ts +54 -0
  406. package/lib/dist/services/storage/migration.d.ts.map +1 -0
  407. package/lib/dist/services/storage/migration.js +296 -0
  408. package/lib/dist/services/storage/migration.js.map +1 -0
  409. package/lib/dist/services/storage/opensearchClient.d.ts +924 -0
  410. package/lib/dist/services/storage/opensearchClient.d.ts.map +1 -0
  411. package/lib/dist/services/storage/opensearchClient.js +435 -0
  412. package/lib/dist/services/storage/opensearchClient.js.map +1 -0
  413. package/lib/dist/services/traces/browserRecovery.d.ts +26 -0
  414. package/lib/dist/services/traces/browserRecovery.d.ts.map +1 -0
  415. package/lib/dist/services/traces/browserRecovery.js +81 -0
  416. package/lib/dist/services/traces/browserRecovery.js.map +1 -0
  417. package/lib/dist/services/traces/categoryStyles.d.ts +21 -0
  418. package/lib/dist/services/traces/categoryStyles.d.ts.map +1 -0
  419. package/lib/dist/services/traces/categoryStyles.js +56 -0
  420. package/lib/dist/services/traces/categoryStyles.js.map +1 -0
  421. package/lib/dist/services/traces/executionOrderTransform.d.ts +35 -0
  422. package/lib/dist/services/traces/executionOrderTransform.d.ts.map +1 -0
  423. package/lib/dist/services/traces/executionOrderTransform.js +313 -0
  424. package/lib/dist/services/traces/executionOrderTransform.js.map +1 -0
  425. package/lib/dist/services/traces/fetchSpansForRun.d.ts +86 -0
  426. package/lib/dist/services/traces/fetchSpansForRun.d.ts.map +1 -0
  427. package/lib/dist/services/traces/fetchSpansForRun.js +69 -0
  428. package/lib/dist/services/traces/fetchSpansForRun.js.map +1 -0
  429. package/lib/dist/services/traces/flowTransform.d.ts +24 -0
  430. package/lib/dist/services/traces/flowTransform.d.ts.map +1 -0
  431. package/lib/dist/services/traces/flowTransform.js +228 -0
  432. package/lib/dist/services/traces/flowTransform.js.map +1 -0
  433. package/lib/dist/services/traces/index.d.ts +121 -0
  434. package/lib/dist/services/traces/index.d.ts.map +1 -0
  435. package/lib/dist/services/traces/index.js +255 -0
  436. package/lib/dist/services/traces/index.js.map +1 -0
  437. package/lib/dist/services/traces/intentTransform.d.ts +20 -0
  438. package/lib/dist/services/traces/intentTransform.d.ts.map +1 -0
  439. package/lib/dist/services/traces/intentTransform.js +131 -0
  440. package/lib/dist/services/traces/intentTransform.js.map +1 -0
  441. package/lib/dist/services/traces/judgeAgentsHints.d.ts +63 -0
  442. package/lib/dist/services/traces/judgeAgentsHints.d.ts.map +1 -0
  443. package/lib/dist/services/traces/judgeAgentsHints.js +89 -0
  444. package/lib/dist/services/traces/judgeAgentsHints.js.map +1 -0
  445. package/lib/dist/services/traces/messageExtraction.d.ts +15 -0
  446. package/lib/dist/services/traces/messageExtraction.d.ts.map +1 -0
  447. package/lib/dist/services/traces/messageExtraction.js +251 -0
  448. package/lib/dist/services/traces/messageExtraction.js.map +1 -0
  449. package/lib/dist/services/traces/spanCategorization.d.ts +63 -0
  450. package/lib/dist/services/traces/spanCategorization.d.ts.map +1 -0
  451. package/lib/dist/services/traces/spanCategorization.js +276 -0
  452. package/lib/dist/services/traces/spanCategorization.js.map +1 -0
  453. package/lib/dist/services/traces/spanPreprocessing.d.ts +37 -0
  454. package/lib/dist/services/traces/spanPreprocessing.d.ts.map +1 -0
  455. package/lib/dist/services/traces/spanPreprocessing.js +102 -0
  456. package/lib/dist/services/traces/spanPreprocessing.js.map +1 -0
  457. package/lib/dist/services/traces/spansToTrajectory.d.ts +36 -0
  458. package/lib/dist/services/traces/spansToTrajectory.d.ts.map +1 -0
  459. package/lib/dist/services/traces/spansToTrajectory.js +387 -0
  460. package/lib/dist/services/traces/spansToTrajectory.js.map +1 -0
  461. package/lib/dist/services/traces/toolSimilarity.d.ts +35 -0
  462. package/lib/dist/services/traces/toolSimilarity.d.ts.map +1 -0
  463. package/lib/dist/services/traces/toolSimilarity.js +203 -0
  464. package/lib/dist/services/traces/toolSimilarity.js.map +1 -0
  465. package/lib/dist/services/traces/traceComparison.d.ts +31 -0
  466. package/lib/dist/services/traces/traceComparison.d.ts.map +1 -0
  467. package/lib/dist/services/traces/traceComparison.js +318 -0
  468. package/lib/dist/services/traces/traceComparison.js.map +1 -0
  469. package/lib/dist/services/traces/traceGrouping.d.ts +19 -0
  470. package/lib/dist/services/traces/traceGrouping.d.ts.map +1 -0
  471. package/lib/dist/services/traces/traceGrouping.js +107 -0
  472. package/lib/dist/services/traces/traceGrouping.js.map +1 -0
  473. package/lib/dist/services/traces/tracePoller.d.ts +84 -0
  474. package/lib/dist/services/traces/tracePoller.d.ts.map +1 -0
  475. package/lib/dist/services/traces/tracePoller.js +309 -0
  476. package/lib/dist/services/traces/tracePoller.js.map +1 -0
  477. package/lib/dist/services/traces/traceStats.d.ts +45 -0
  478. package/lib/dist/services/traces/traceStats.d.ts.map +1 -0
  479. package/lib/dist/services/traces/traceStats.js +114 -0
  480. package/lib/dist/services/traces/traceStats.js.map +1 -0
  481. package/lib/dist/services/traces/traceSummary.d.ts +47 -0
  482. package/lib/dist/services/traces/traceSummary.d.ts.map +1 -0
  483. package/lib/dist/services/traces/traceSummary.js +68 -0
  484. package/lib/dist/services/traces/traceSummary.js.map +1 -0
  485. package/lib/dist/services/traces/utils.d.ts +33 -0
  486. package/lib/dist/services/traces/utils.d.ts.map +1 -0
  487. package/lib/dist/services/traces/utils.js +114 -0
  488. package/lib/dist/services/traces/utils.js.map +1 -0
  489. package/lib/dist/types/agui.d.ts +13 -0
  490. package/lib/dist/types/agui.d.ts.map +1 -0
  491. package/lib/dist/types/agui.js +16 -0
  492. package/lib/dist/types/agui.js.map +1 -0
  493. package/lib/dist/types/index.d.ts +1175 -0
  494. package/lib/dist/types/index.d.ts.map +1 -0
  495. package/lib/dist/types/index.js +12 -0
  496. package/lib/dist/types/index.js.map +1 -0
  497. package/lib/dist/types/skills.d.ts +146 -0
  498. package/lib/dist/types/skills.d.ts.map +1 -0
  499. package/lib/dist/types/skills.js +6 -0
  500. package/lib/dist/types/skills.js.map +1 -0
  501. package/observio-sample-agent/pi-package/README.md +112 -0
  502. package/observio-sample-agent/pi-package/extensions/agent-health.ts +373 -0
  503. package/observio-sample-agent/pi-package/package.json +17 -0
  504. package/observio-sample-agent/pi-package/prompts/agent-health.md +37 -0
  505. package/observio-sample-agent/pi-package/skills/create-pr/SKILL.md +88 -0
  506. package/observio-sample-agent/pi-package/skills/fix-bug/SKILL.md +71 -0
  507. package/observio-sample-agent/pi-package/skills/implement-feature/SKILL.md +156 -0
  508. package/observio-sample-agent/pi-package/skills/instrument-otel/SKILL.md +208 -0
  509. package/observio-sample-agent/pi-package/skills/setup-collector/SKILL.md +146 -0
  510. package/observio-sample-agent/pi-package/skills/write-test/SKILL.md +115 -0
  511. package/package.json +64 -13
  512. package/server/dist/app.js +32651 -17637
  513. package/server/dist/index.js +29875 -14638
  514. package/tsconfig.lib.json +71 -0
  515. package/dist/assets/index-EvPLSTAS.js +0 -267
  516. package/dist/assets/index-RXasQKUs.css +0 -1
  517. package/lib/dist/config/index.js +0 -404
  518. package/lib/dist/index.js +0 -1665
Binary file
@@ -0,0 +1,468 @@
1
+ # Plan: Code-Based Test Case SDK — Field Redesign (v2)
2
+
3
+ ## Status (as of 2026-05-16)
4
+
5
+ ### Completed (in working tree, not yet committed)
6
+ - [x] `lib/testCases/types.ts` — Rewritten with `TestOptions` (prompt required), `CodeTestCase`, `EvalResult`
7
+ - [x] `lib/testCases/define.ts` — Rewritten with `test()` API, file-scoped registries, `defineTestCases()` compat wrapper
8
+ - [x] `lib/testCases/judge.ts` — Rewritten with runtime `wasJudgeCalled()`/`resetJudgeFlag()` flags
9
+ - [x] `lib/testCases/loader.ts` — Rewritten with per-test-case `computeTestCaseHash()`, file-scoped loading via registry
10
+ - [x] `lib/testCases/index.ts` — Updated barrel exports for new API
11
+ - [x] `lib/index.ts` — Added SDK exports (`test`, `defineTestCases`, `judge`, `expect`)
12
+ - [x] `services/sourceResolver.ts` — Added `EvaluateFn` type, `evaluateFnMap` to `ResolvedSources`, `code-import` case in switch (partial — needs unification to `import` type)
13
+
14
+ ### Not Started
15
+ - [ ] Unified `import` source type (replace `file-import` + `code-import` + `directory-import`)
16
+ - [ ] `services/evaluationRunner.ts` — Deterministic eval path with `resetJudgeFlag`/`wasJudgeCalled` inference
17
+ - [ ] `types/index.ts` — `sourceFile` replaces `sourceUri`, `evaluationType` on TestCaseVersion, unified source type
18
+ - [ ] `server/constants/indexMappings.ts` — `sourceFile` field
19
+ - [ ] `server/adapters/file/StorageModule.ts` — `bulkUpsert` match on `sourceFile`
20
+ - [ ] `server/adapters/opensearch/StorageModule.ts` — same
21
+ - [ ] `cli/commands/benchmark.ts` — `-f` accepts dirs, exit codes, `--reporter`
22
+ - [ ] `cli/reporters/` — `summary.ts`, `junit.ts`, `json.ts`
23
+ - [ ] `components/RunDetailsContent.tsx` — Read evaluationType from version
24
+ - [ ] `components/evals3/TestCasesPage.tsx` — Badge on `sourceFile`
25
+ - [ ] All test updates (see step 11)
26
+
27
+ ### Key Context for Handoff
28
+ - Branch: `feat/test-case-sdk` (local only, working tree has uncommitted changes)
29
+ - The v1 implementation (committed on remote `feat/test-case-sdk`) uses `sourceUri`, `defineTestCases()`, per-file hash, and `evaluationType` on TestCaseRun. All of that is being replaced.
30
+ - `evaluationRunner.ts` already has `runWithConcurrencyLimit()` — no need for `p-limit` dep.
31
+ - The plan file was pushed to `fork/docs/sdk-field-redesign-plan` branch.
32
+ - Existing tests reference old field names (`sourceUri`, old `defineTestCases` API) and will need updating.
33
+
34
+ ---
35
+
36
+ ## Context
37
+
38
+ The initial SDK implementation (steps 1-11) is complete and passing. This redesign incorporates principal engineer review feedback to make the SDK actually production-ready — not just a working API, but something teams adopt over alternatives (Promptfoo, Braintrust, Langsmith).
39
+
40
+ **Core insight:** The previous plan focused on internal field placement. This revision prioritizes the **customer-facing contract** — the API signature, CI exit codes, parallelism, and cost visibility — and defers internal storage plumbing where it doesn't block adoption.
41
+
42
+ **Key changes from v1:**
43
+ 1. **Kill `agentic: boolean`** — infer evaluation type at runtime from whether `judge()` was called. No customer-facing field.
44
+ 2. **Add explicit `prompt` field** — test name is a description, prompt is what gets sent to the agent.
45
+ 3. **Add `--concurrency N`** — parallel test execution with semaphore.
46
+ 4. **Define CI contract** — exit codes, `--reporter junit|json`, pass/fail gate.
47
+ 5. **File-scoped isolation** — each file gets its own registry (no global mutable state).
48
+ 6. **Unify source types** — merge `file-import`, `code-import`, `directory-import` into a single `import` type that auto-detects by extension. `-f` accepts files and dirs.
49
+
50
+ ---
51
+
52
+ ## Implementation Steps
53
+
54
+ ### 1. Redesign SDK API: `test()` with explicit prompt
55
+
56
+ **Files:** `lib/testCases/types.ts`, `lib/testCases/define.ts`
57
+
58
+ ```typescript
59
+ // lib/testCases/types.ts
60
+ export interface TestOptions {
61
+ prompt: string; // REQUIRED — what gets sent to the agent
62
+ category: string;
63
+ difficulty: 'Easy' | 'Medium' | 'Hard';
64
+ description?: string;
65
+ context?: { description: string; value: string }[];
66
+ labels?: string[];
67
+ timeout?: number; // ms, default 120000 (2 min)
68
+ }
69
+
70
+ export interface CodeTestCase {
71
+ name: string;
72
+ options: TestOptions;
73
+ evaluate: (result: EvalResult) => Promise<void> | void;
74
+ }
75
+
76
+ export interface EvalResult {
77
+ trajectory: TrajectoryStep[];
78
+ agentOutput: string;
79
+ rawEvents: any[];
80
+ runId?: string;
81
+ durationMs: number;
82
+ tokenUsage?: { prompt: number; completion: number; total: number };
83
+ }
84
+ ```
85
+
86
+ ```typescript
87
+ // lib/testCases/define.ts
88
+ export interface FileRegistry {
89
+ tests: CodeTestCase[];
90
+ filePath?: string;
91
+ }
92
+
93
+ // Per-file registries (keyed by absolute file path)
94
+ const registries = new Map<string, FileRegistry>();
95
+ let activeFile: string | null = null;
96
+
97
+ export function setActiveFile(filePath: string): void {
98
+ activeFile = filePath;
99
+ if (!registries.has(filePath)) {
100
+ registries.set(filePath, { tests: [], filePath });
101
+ }
102
+ }
103
+
104
+ export function test(
105
+ name: string,
106
+ options: TestOptions,
107
+ evaluate: (result: EvalResult) => Promise<void> | void
108
+ ): void {
109
+ if (!name || typeof name !== 'string') throw new Error('test() requires a name');
110
+ if (!options.prompt) throw new Error('test() requires options.prompt');
111
+ if (!options.category) throw new Error('test() requires options.category');
112
+ if (!options.difficulty) throw new Error('test() requires options.difficulty');
113
+ if (typeof evaluate !== 'function') throw new Error('test() requires an evaluate function');
114
+
115
+ const registry = activeFile ? registries.get(activeFile)! : getDefaultRegistry();
116
+ registry.tests.push({ name, options, evaluate });
117
+ }
118
+
119
+ export function getRegisteredTests(filePath?: string): CodeTestCase[] {
120
+ if (filePath) return [...(registries.get(filePath)?.tests ?? [])];
121
+ // Return all tests across all files
122
+ return [...registries.values()].flatMap(r => [...r.tests]);
123
+ }
124
+
125
+ export function clearRegistry(filePath?: string): void {
126
+ if (filePath) registries.delete(filePath);
127
+ else registries.clear();
128
+ }
129
+ ```
130
+
131
+ **Customer usage:**
132
+ ```typescript
133
+ // evals/cybergym.eval.ts
134
+ import { test, expect } from '@opensearch-project/agent-health';
135
+
136
+ test('CyberGym Task 42', {
137
+ prompt: 'Analyze the vulnerability in the authentication module and provide a proof of concept exploit',
138
+ category: 'Security',
139
+ difficulty: 'Hard',
140
+ }, async (result) => {
141
+ const poc = extractPoc(result.agentOutput);
142
+ const res = await submitToCyberGym(poc, 'task-42');
143
+ expect(res.exit_code).to.not.equal(0);
144
+ });
145
+
146
+ test('RCA Log Analysis', {
147
+ prompt: 'Investigate the spike in 5xx errors starting at 14:30 UTC. Identify the root cause.',
148
+ category: 'RCA',
149
+ difficulty: 'Medium',
150
+ }, async (result) => {
151
+ // Use LLM judge for semantic evaluation
152
+ await judge(result.trajectory, ['Identifies root cause', 'Suggests remediation']);
153
+ // Can also add deterministic checks
154
+ expect(result.durationMs).to.be.lessThan(60000);
155
+ });
156
+ ```
157
+
158
+ ### 2. Infer `evaluationType` at runtime (kill `agentic` field)
159
+
160
+ **No customer-facing field.** Instead, detect at runtime:
161
+
162
+ **File:** `lib/testCases/judge.ts`
163
+
164
+ ```typescript
165
+ // Thread-local flag set when judge() is called during evaluate()
166
+ let judgeCalledInCurrentEval = false;
167
+
168
+ export function wasJudgeCalled(): boolean {
169
+ return judgeCalledInCurrentEval;
170
+ }
171
+
172
+ export function resetJudgeFlag(): void {
173
+ judgeCalledInCurrentEval = false;
174
+ }
175
+
176
+ export async function judge(trajectory: TrajectoryStep[], criteria: string[]): Promise<JudgeVerdict> {
177
+ judgeCalledInCurrentEval = true;
178
+ // Call LLM judge, return verdict
179
+ // ...
180
+ }
181
+ ```
182
+
183
+ **File:** `services/evaluationRunner.ts` — after calling evaluate():
184
+
185
+ ```typescript
186
+ resetJudgeFlag();
187
+ try {
188
+ await evalFn({ trajectory, agentOutput, rawEvents, durationMs });
189
+ const usedJudge = wasJudgeCalled();
190
+ report.passFailStatus = 'passed';
191
+ // evaluationType is inferred, stored on version after first run
192
+ } catch (evalError: any) {
193
+ const usedJudge = wasJudgeCalled();
194
+ report.passFailStatus = 'failed';
195
+ report.assertionError = evalError.message;
196
+ }
197
+ ```
198
+
199
+ **On TestCaseVersion:** `evaluationType` is set after the first execution:
200
+ - If `judge()` was called → `'agentic'`
201
+ - If only assertions → `'deterministic'`
202
+ - If both → `'hybrid'` (new value)
203
+
204
+ This means version gets its `evaluationType` lazily on first run, not at import time.
205
+
206
+ ### 3. Replace `sourceUri` with `sourceFile` + per-test-case hash
207
+
208
+ **File:** `types/index.ts` — on TestCase:
209
+ ```typescript
210
+ sourceFile?: string; // Relative path: "evals/cybergym.eval.ts"
211
+ sourceHash?: string; // SHA-256 of per-test-case content (not the whole file)
212
+ ```
213
+
214
+ **Per-test-case hash** (`lib/testCases/loader.ts`):
215
+ ```typescript
216
+ export function computeTestCaseHash(tc: CodeTestCase): string {
217
+ const content = JSON.stringify({
218
+ name: tc.name,
219
+ prompt: tc.options.prompt,
220
+ category: tc.options.category,
221
+ difficulty: tc.options.difficulty,
222
+ context: tc.options.context,
223
+ labels: tc.options.labels,
224
+ description: tc.options.description,
225
+ });
226
+ return crypto.createHash('sha256').update(content).digest('hex');
227
+ }
228
+ ```
229
+
230
+ **Match key for upsert:** `name + sourceFile`
231
+
232
+ ### 4. Add `--concurrency N` to benchmark runner
233
+
234
+ **File:** `cli/commands/benchmark.ts` — add option:
235
+ ```typescript
236
+ .option('-c, --concurrency <number>', 'Number of parallel test executions', '3')
237
+ ```
238
+
239
+ **File:** `services/evaluationRunner.ts` — parallel execution with semaphore:
240
+
241
+ ```typescript
242
+ import pLimit from 'p-limit';
243
+
244
+ export async function executeEvaluationRun(run, testCases, options) {
245
+ const concurrency = options.concurrency ?? 3;
246
+ const limit = pLimit(concurrency);
247
+
248
+ const tasks = testCases.map(tc =>
249
+ limit(() => executeSingleTestCase(run, tc, options))
250
+ );
251
+
252
+ await Promise.allSettled(tasks);
253
+ }
254
+ ```
255
+
256
+ **New dependency:** `p-limit` (tiny, zero-dep semaphore).
257
+
258
+ ### 5. Define CI contract: exit codes + reporters
259
+
260
+ **File:** `cli/commands/benchmark.ts`:
261
+
262
+ ```typescript
263
+ .option('--reporter <type>', 'Output format: summary (default), junit, json, tap', 'summary')
264
+ .option('--fail-fast', 'Stop on first failure')
265
+ ```
266
+
267
+ **Exit codes:**
268
+ - `0` — all tests passed
269
+ - `1` — one or more tests failed
270
+ - `2` — configuration error (bad file, missing agent, etc.)
271
+
272
+ **File:** `cli/reporters/` (new directory):
273
+
274
+ | File | Purpose |
275
+ |------|---------|
276
+ | `summary.ts` | Default terminal output (pass/fail counts, duration, cost) |
277
+ | `junit.ts` | JUnit XML for CI integration (GitHub Actions, Jenkins) |
278
+ | `json.ts` | Machine-readable JSON (for programmatic consumption) |
279
+
280
+ **JUnit output** enables:
281
+ ```yaml
282
+ # .github/workflows/eval.yml
283
+ - run: npx agent-health benchmark -f evals/ -a my-agent --reporter junit > results.xml
284
+ - uses: dorny/test-reporter@v1
285
+ with:
286
+ reporter: java-junit
287
+ path: results.xml
288
+ ```
289
+
290
+ ### 6. Add timeout + cost visibility
291
+
292
+ **Timeout per test case** (from `TestOptions.timeout`, default 120s):
293
+ ```typescript
294
+ const result = await Promise.race([
295
+ runAgentAndEvaluate(tc),
296
+ timeout(tc.options.timeout ?? 120000),
297
+ ]);
298
+ ```
299
+
300
+ **Cost summary** in reporter output:
301
+ ```
302
+ Results: 48 passed, 2 failed (50 total)
303
+ Duration: 4m 32s
304
+ Tokens: 1.2M prompt / 340K completion
305
+ Est. cost: $4.82 (agent) + $1.20 (judge) = $6.02
306
+ ```
307
+
308
+ **File:** `cli/reporters/summary.ts` — aggregate token usage from all runs and compute cost based on model pricing from config.
309
+
310
+ ### 7. Move `evaluationType` to TestCaseVersion
311
+
312
+ **File:** `types/index.ts`
313
+
314
+ ```typescript
315
+ export interface TestCaseVersion {
316
+ // ... existing fields ...
317
+ evaluationType?: 'agentic' | 'deterministic' | 'hybrid';
318
+ }
319
+ ```
320
+
321
+ Remove from `TestCaseRun`. Keep `assertionError` on run (execution-time data).
322
+
323
+ **Lazy population:** On first execution of a code-imported test case, update the version's `evaluationType` based on runtime inference (step 2). Subsequent runs don't change it (immutable once set).
324
+
325
+ ### 8. Update storage: `sourceFile` + match logic
326
+
327
+ **File:** `server/constants/indexMappings.ts`:
328
+ ```diff
329
+ - sourceUri: { type: 'keyword' },
330
+ + sourceFile: { type: 'keyword' },
331
+ sourceHash: { type: 'keyword' },
332
+ ```
333
+
334
+ **File:** `server/adapters/file/StorageModule.ts` + `opensearch/StorageModule.ts`:
335
+ - `bulkUpsert` matches on `name + sourceFile`
336
+ - On hash change → new version (with `evaluationType` if known)
337
+
338
+ ### 9. Unified `import` source type in source resolver
339
+
340
+ **File:** `services/sourceResolver.ts`
341
+
342
+ Replace the three separate source types (`file-import`, `code-import`, `directory-import`) with a single `import` type:
343
+
344
+ ```typescript
345
+ case 'import': {
346
+ const { testCases, fnMap } = await resolveImport(source.paths, storage);
347
+ // ...
348
+ }
349
+ ```
350
+
351
+ **`resolveImport(paths, storage)`** handles the unified logic:
352
+ 1. For each path, check if it's a file or directory
353
+ 2. If directory → scan for `*.eval.ts`, `*.eval.js`, `*.json` recursively
354
+ 3. For each file, route by extension:
355
+ - `.json` → existing JSON import path (parse + `bulkCreate`)
356
+ - `.ts` / `.js` / `.mjs` → code import path (load module + `bulkUpsert`)
357
+ 4. Code files produce `evaluateFnMap` entries; JSON files don't
358
+ 5. Return combined test cases + fnMap
359
+
360
+ **CLI `-f` flag** accepts both files and directories:
361
+ ```bash
362
+ npx agent-health benchmark -f evals/ # scans dir
363
+ npx agent-health benchmark -f evals/rca.eval.ts # single code file
364
+ npx agent-health benchmark -f test-cases.json # single JSON file
365
+ npx agent-health benchmark -f evals/ -f extra.json # mixed
366
+ ```
367
+
368
+ **`TestCaseSource` type** simplification:
369
+ ```typescript
370
+ // Before: 3 source types
371
+ | { type: 'file-import'; filenames: string[]; testCaseIds: string[] }
372
+ | { type: 'code-import'; filenames: string[]; testCaseIds: string[] }
373
+ | { type: 'directory-import'; dirPaths: string[]; testCaseIds: string[] }
374
+
375
+ // After: 1 unified type
376
+ | { type: 'import'; paths: string[]; testCaseIds: string[] }
377
+ ```
378
+
379
+ Keep old types as aliases for backward compat (existing benchmarks may have these in storage).
380
+
381
+ ### 10. Update UI
382
+
383
+ **File:** `components/evals3/TestCasesPage.tsx`:
384
+ - "Code" badge on `testCase.sourceFile` (not `sourceUri`)
385
+ - Disable edit for code-sourced test cases
386
+
387
+ **File:** `components/RunDetailsContent.tsx`:
388
+ - Read `evaluationType` from test case version (not report)
389
+ - Show "Hybrid" badge when both judge and assertions were used
390
+ - Show assertion error for deterministic/hybrid failures
391
+
392
+ ### 11. Update existing tests
393
+
394
+ | Test File | Change |
395
+ |-----------|--------|
396
+ | `tests/unit/lib/testCases/define.test.ts` | Rewrite for `test()` API with `prompt` field, file-scoped registry |
397
+ | `tests/unit/services/evaluationRunner.deterministic.test.ts` | Remove `evaluationType` from report assertions |
398
+ | `tests/unit/services/sourceResolver.codeImport.test.ts` | `sourceFile` instead of `sourceUri`, prompt field |
399
+ | `tests/unit/server/adapters/bulkUpsert.test.ts` | Match on `sourceFile` |
400
+ | `tests/integration/services/sourceResolver.codeImport.integration.test.ts` | Update for new API |
401
+ | `tests/integration/services/codeSdkObservio.integration.test.ts` | Update field references |
402
+ | `tests/unit/cli/reporters/` (new) | Test junit, json, summary output |
403
+
404
+ ### 12. Package exports
405
+
406
+ **File:** `lib/testCases/index.ts`:
407
+ ```typescript
408
+ export { test, getRegisteredTests, clearRegistry } from './define.js';
409
+ export { judge } from './judge.js';
410
+ export { defineTestCases } from './compat.js'; // Deprecated
411
+ export type { TestOptions, CodeTestCase, EvalResult } from './types.js';
412
+ ```
413
+
414
+ **File:** `lib/index.ts`:
415
+ ```typescript
416
+ export { test, defineTestCases, judge } from './testCases/index.js';
417
+ export { expect } from 'chai';
418
+ ```
419
+
420
+ **New dependency:** `p-limit` (production — for concurrency control).
421
+
422
+ ---
423
+
424
+ ## Critical Files to Modify
425
+
426
+ | File | Change |
427
+ |------|--------|
428
+ | `lib/testCases/types.ts` | `TestOptions` with `prompt` (required), `timeout`; drop `agentic` |
429
+ | `lib/testCases/define.ts` | File-scoped registries, `test()` with prompt validation |
430
+ | `lib/testCases/loader.ts` | Per-test-case hash, file-scoped loading |
431
+ | `lib/testCases/judge.ts` | Runtime flag for `judge()` calls |
432
+ | `services/evaluationRunner.ts` | Parallel execution (`p-limit`), timeout, infer evaluationType |
433
+ | `services/sourceResolver.ts` | Unified `import` source type, `sourceFile` (relative), per-test-case hash |
434
+ | `types/index.ts` | Replace 3 source types with unified `import` type |
435
+ | `cli/commands/benchmark.ts` | `-f` accepts files+dirs, `--reporter`, `--fail-fast`, exit codes |
436
+ | `cli/reporters/` (new) | `summary.ts`, `junit.ts`, `json.ts` |
437
+ | `types/index.ts` | `evaluationType` on TestCaseVersion (lazy), `sourceFile` on TestCase |
438
+ | `server/constants/indexMappings.ts` | `sourceFile` replaces `sourceUri` |
439
+ | `server/adapters/file/StorageModule.ts` | Match on `sourceFile` in bulkUpsert |
440
+ | `components/RunDetailsContent.tsx` | Read evaluationType from version |
441
+ | `components/evals3/TestCasesPage.tsx` | Badge on `sourceFile` |
442
+
443
+ ---
444
+
445
+ ## Implementation Order (prioritized by customer impact)
446
+
447
+ 1. **SDK API** (steps 1-2) — `test()` with prompt, file-scoped registry, runtime inference
448
+ 2. **CI contract** (step 5) — exit codes, reporters
449
+ 3. **Parallelism + timeout** (steps 4, 6) — `--concurrency`, per-test timeout
450
+ 4. **Storage redesign** (steps 3, 7, 8, 9) — sourceFile, per-test hash, version-level evaluationType
451
+ 5. **UI** (step 10) — badges, version-aware rendering
452
+ 6. **Tests** (step 11) — update all affected tests
453
+ 7. **Exports** (step 12) — package API surface
454
+
455
+ ---
456
+
457
+ ## Verification Plan
458
+
459
+ 1. **Build:** `npm run build:all` passes
460
+ 2. **Unit tests:** `npm run test:unit` — all pass
461
+ 3. **CI contract test:** `npx agent-health benchmark -f tests/fixtures/sample.eval.ts -a observio --reporter json` returns exit 0/1 correctly
462
+ 4. **Parallel test:** 10 test cases with `--concurrency 5` complete in ~2x single-case time (not 10x)
463
+ 5. **JUnit output:** Valid XML parseable by `dorny/test-reporter`
464
+ 6. **Cost summary:** Token counts + estimated cost displayed in summary reporter
465
+ 7. **Per-test hash:** Modify one test in a multi-test file → only that test gets new version
466
+ 8. **Runtime inference:** Test with `judge()` → version gets `evaluationType: 'agentic'`; test without → `'deterministic'`; test with both → `'hybrid'`
467
+ 9. **Timeout:** Test case exceeding timeout fails with clear error message
468
+ 10. **Backward compat:** `defineTestCases([...])` still works, old test cases render correctly