@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
@@ -0,0 +1,417 @@
1
+ /*
2
+ * Copyright OpenSearch Contributors
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ /**
7
+ * Agent Health — pi session profiling extension (single-file, zero-dependency).
8
+ *
9
+ * Drop this one file into `~/.pi/agent/extensions/` (global) or
10
+ * `.pi/extensions/` (project) and pi will auto-load it. No `npm install` — it
11
+ * speaks OTLP/HTTP JSON over the built-in `fetch`, so there are no
12
+ * `@opentelemetry/*` dependencies to resolve.
13
+ *
14
+ * Why it exists: pi has no native OpenTelemetry telemetry (unlike Claude Code's
15
+ * CLAUDE_CODE_ENABLE_TELEMETRY), so `agent-health profile` has nothing to read
16
+ * for a live pi session. This extension supplies that missing half — it
17
+ * instruments the running session and registers the profiling command.
18
+ *
19
+ * What it does:
20
+ * 1. Emits OTel spans for the session (root `invoke_agent pi`, one
21
+ * `chat <model>` span per turn with token usage + prompt/completion, and an
22
+ * `execute_tool <name>` span per tool call). Every span carries
23
+ * `session.id`; the resource carries `service.name=pi-agent`.
24
+ * 2. Records the session id to `.pi/agent-health/current-session` so
25
+ * `agent-health profile` resolves it deterministically.
26
+ * 3. Registers `/agent-health-profile -e <id> [-f "<feedback>"]`, which runs
27
+ * the CLI and feeds the rubric + trajectory + signals back into the chat.
28
+ *
29
+ * Config (env):
30
+ * - OTEL_EXPORTER_OTLP_ENDPOINT where to export (default http://localhost:4001;
31
+ * `/v1/traces` is appended if missing). Point at
32
+ * Agent Health's embedded receiver (file mode),
33
+ * an OTel Collector, or an OSIS pipeline.
34
+ * - OTEL_SERVICE_NAME default `pi-agent`.
35
+ * - OTEL_ENABLED=false disable telemetry (command still explains how).
36
+ * - AGENT_HEALTH_REDACT=1 stamp redaction placeholders instead of capturing
37
+ * prompt / tool I/O.
38
+ * - AGENT_HEALTH_CLI CLI invocation (default `npx @opensearch-project/agent-health`).
39
+ *
40
+ * See docs/skills/AGENT_PROFILE.md.
41
+ */
42
+
43
+ import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';
44
+ import { randomBytes } from 'node:crypto';
45
+ import { mkdirSync, writeFileSync } from 'node:fs';
46
+ import { join } from 'node:path';
47
+
48
+ // ─── Pure, exported helpers (unit-tested; no pi/OTel imports) ────────────────
49
+
50
+ export const PI_SERVICE_NAME = 'pi-agent';
51
+ export const PI_SCOPE_NAME = 'agent-health-pi';
52
+ export const DEFAULT_ENDPOINT = 'http://localhost:4001';
53
+ export const DEFAULT_CLI = 'npx @opensearch-project/agent-health';
54
+ export const DEFAULT_EVALUATOR = 'system-rca-default';
55
+ export const REDACTED = '[redacted]';
56
+
57
+ export type OtlpValue = { stringValue: string } | { intValue: string } | { boolValue: boolean };
58
+ export interface OtlpKeyValue { key: string; value: OtlpValue; }
59
+ export interface OtlpEvent { name: string; timeUnixNano: string; attributes: OtlpKeyValue[]; }
60
+ export interface OtlpSpan {
61
+ traceId: string;
62
+ spanId: string;
63
+ parentSpanId?: string;
64
+ name: string;
65
+ kind: number;
66
+ startTimeUnixNano: string;
67
+ endTimeUnixNano: string;
68
+ attributes: OtlpKeyValue[];
69
+ events: OtlpEvent[];
70
+ status: { code: number };
71
+ }
72
+
73
+ export function randomHex(bytes: number): string {
74
+ return randomBytes(bytes).toString('hex');
75
+ }
76
+ export const genTraceId = () => randomHex(16); // 32 hex chars
77
+ export const genSpanId = () => randomHex(8); // 16 hex chars
78
+
79
+ /** Parse a W3C `traceparent` (`00-<trace>-<span>-<flags>`). */
80
+ export function parseTraceparent(tp?: string): { traceId: string; spanId: string } | null {
81
+ if (!tp) return null;
82
+ const m = tp.trim().match(/^[0-9a-f]{2}-([0-9a-f]{32})-([0-9a-f]{16})-[0-9a-f]{2}$/i);
83
+ return m ? { traceId: m[1].toLowerCase(), spanId: m[2].toLowerCase() } : null;
84
+ }
85
+
86
+ /** Resolve the full OTLP traces URL from a base endpoint. */
87
+ export function resolveEndpoint(base?: string): string {
88
+ const b = (base || DEFAULT_ENDPOINT).replace(/\/$/, '');
89
+ return b.endsWith('/v1/traces') ? b : `${b}/v1/traces`;
90
+ }
91
+
92
+ /** Stable session id from pi's session file path (basename minus extension). */
93
+ export function sessionIdFromFile(file?: string | null): string | undefined {
94
+ if (!file) return undefined;
95
+ const base = file.split(/[\\/]/).pop() ?? file;
96
+ const stem = base.replace(/\.[^.]+$/, '').trim();
97
+ return stem || undefined;
98
+ }
99
+
100
+ export function numOrUndef(v: unknown): number | undefined {
101
+ const n = Number(v);
102
+ return Number.isFinite(n) ? n : undefined;
103
+ }
104
+
105
+ export function truncate(s: unknown, max = 5000): string {
106
+ const str = typeof s === 'string' ? s : safeStringify(s);
107
+ return str.length > max ? `${str.slice(0, max)}…` : str;
108
+ }
109
+
110
+ export function safeStringify(v: unknown): string {
111
+ if (v == null) return '';
112
+ if (typeof v === 'string') return v;
113
+ try { return JSON.stringify(v); } catch { return String(v); }
114
+ }
115
+
116
+ /** Pull plain text out of a pi assistant message `content` (string or blocks). */
117
+ export function extractText(content: unknown): string | undefined {
118
+ if (typeof content === 'string') return content || undefined;
119
+ if (!Array.isArray(content)) return undefined;
120
+ const parts = content
121
+ .filter((b): b is { type: string; text: string } =>
122
+ !!b && (b as any).type === 'text' && typeof (b as any).text === 'string')
123
+ .map((b) => b.text);
124
+ return parts.length ? parts.join('\n') : undefined;
125
+ }
126
+
127
+ /** Parse `<flag> <value>` (quoted or bare) from a raw command arg string. */
128
+ export function parseFlag(args: string, flags: string[]): string | undefined {
129
+ const names = flags.map((f) => f.replace(/^-+/, '')).join('|');
130
+ const re = new RegExp(`(?:^|\\s)(?:-{1,2})(?:${names})\\s+("([^"]*)"|'([^']*)'|(\\S+))`);
131
+ const m = (args || '').match(re);
132
+ return m ? (m[2] ?? m[3] ?? m[4]) : undefined;
133
+ }
134
+
135
+ /** Build the `agent-health profile …` argv (binary + args) for a pi session. */
136
+ export function buildProfileInvocation(opts: {
137
+ cli?: string; sessionId: string; evaluator?: string; feedback?: string; service?: string;
138
+ }): { bin: string; args: string[] } {
139
+ const [bin, ...binArgs] = (opts.cli || DEFAULT_CLI).trim().split(/\s+/);
140
+ const args = [
141
+ ...binArgs, 'profile',
142
+ '-e', opts.evaluator || DEFAULT_EVALUATOR,
143
+ '--session', opts.sessionId,
144
+ '--service', opts.service || PI_SERVICE_NAME,
145
+ '--output', 'json',
146
+ ];
147
+ if (opts.feedback) args.push('--feedback', opts.feedback);
148
+ return { bin, args };
149
+ }
150
+
151
+ /** Extract the JSON object from CLI stdout (tolerant of leading log lines). */
152
+ export function extractJson(stdout: string): unknown | null {
153
+ if (!stdout) return null;
154
+ const start = stdout.indexOf('{');
155
+ const end = stdout.lastIndexOf('}');
156
+ if (start === -1 || end === -1 || end < start) return null;
157
+ try { return JSON.parse(stdout.slice(start, end + 1)); } catch { return null; }
158
+ }
159
+
160
+ function kv(attributes: Record<string, string | number | boolean>): OtlpKeyValue[] {
161
+ return Object.entries(attributes).map(([key, value]) => ({
162
+ key,
163
+ value: typeof value === 'number'
164
+ ? { intValue: String(value) }
165
+ : typeof value === 'boolean'
166
+ ? { boolValue: value }
167
+ : { stringValue: String(value) },
168
+ }));
169
+ }
170
+
171
+ /** Wrap finished spans into an OTLP/JSON ExportTraceServiceRequest. */
172
+ export function buildOtlpPayload(serviceName: string, spans: OtlpSpan[]) {
173
+ return {
174
+ resourceSpans: [{
175
+ resource: { attributes: kv({ 'service.name': serviceName }) },
176
+ scopeSpans: [{ scope: { name: PI_SCOPE_NAME }, spans }],
177
+ }],
178
+ };
179
+ }
180
+
181
+ const SPAN_KIND_SERVER = 2;
182
+ const SPAN_KIND_CLIENT = 3;
183
+ const STATUS_OK = 1;
184
+ const STATUS_ERROR = 2;
185
+
186
+ export interface SpanTimes { startNs: string; endNs: string; }
187
+ export function msToNanos(ms: number): string { return `${Math.round(ms)}000000`; }
188
+
189
+ /** Root session span (`invoke_agent pi`). */
190
+ export function buildRootSpan(p: { traceId: string; spanId: string; parentSpanId?: string; sessionId: string; times: SpanTimes }): OtlpSpan {
191
+ return {
192
+ traceId: p.traceId, spanId: p.spanId, ...(p.parentSpanId ? { parentSpanId: p.parentSpanId } : {}),
193
+ name: 'invoke_agent pi', kind: SPAN_KIND_SERVER,
194
+ startTimeUnixNano: p.times.startNs, endTimeUnixNano: p.times.endNs,
195
+ attributes: kv({ 'gen_ai.operation.name': 'invoke_agent', 'gen_ai.system': 'pi', 'gen_ai.agent.name': 'pi', 'session.id': p.sessionId }),
196
+ events: [], status: { code: STATUS_OK },
197
+ };
198
+ }
199
+
200
+ /** Chat (LLM) span for one turn. */
201
+ export function buildChatSpan(p: {
202
+ traceId: string; spanId: string; parentSpanId: string; sessionId: string; times: SpanTimes;
203
+ model: string; inputTokens?: number; outputTokens?: number; userPrompt?: string; completion?: string; redact?: boolean;
204
+ }): OtlpSpan {
205
+ const attrs: Record<string, string | number | boolean> = {
206
+ 'gen_ai.operation.name': 'chat', 'gen_ai.system': 'pi', 'gen_ai.request.model': p.model || 'unknown', 'session.id': p.sessionId,
207
+ };
208
+ if (typeof p.inputTokens === 'number') attrs['gen_ai.usage.input_tokens'] = p.inputTokens;
209
+ if (typeof p.outputTokens === 'number') attrs['gen_ai.usage.output_tokens'] = p.outputTokens;
210
+ const events: OtlpEvent[] = [];
211
+ if (p.userPrompt != null) {
212
+ events.push({ name: 'llm.request', timeUnixNano: p.times.startNs, attributes: kv({ 'gen_ai.prompt': p.redact ? REDACTED : truncate(p.userPrompt) }) });
213
+ }
214
+ if (p.completion != null) {
215
+ events.push({ name: 'llm.response', timeUnixNano: p.times.endNs, attributes: kv({ 'llm.completion': p.redact ? REDACTED : truncate(p.completion) }) });
216
+ }
217
+ return {
218
+ traceId: p.traceId, spanId: p.spanId, parentSpanId: p.parentSpanId,
219
+ name: `chat ${p.model || 'pi'}`, kind: SPAN_KIND_CLIENT,
220
+ startTimeUnixNano: p.times.startNs, endTimeUnixNano: p.times.endNs,
221
+ attributes: kv(attrs), events, status: { code: STATUS_OK },
222
+ };
223
+ }
224
+
225
+ /** Tool execution span (`execute_tool <name>`). */
226
+ export function buildToolSpan(p: {
227
+ traceId: string; spanId: string; parentSpanId: string; sessionId: string; times: SpanTimes;
228
+ toolName: string; input?: unknown; output?: unknown; isError?: boolean; redact?: boolean;
229
+ }): OtlpSpan {
230
+ const attrs: Record<string, string | number | boolean> = {
231
+ 'gen_ai.operation.name': 'execute_tool', 'gen_ai.tool.name': p.toolName, 'session.id': p.sessionId,
232
+ };
233
+ if (p.input != null) attrs['gen_ai.tool.input'] = p.redact ? REDACTED : truncate(p.input, 3000);
234
+ if (p.output != null) attrs['gen_ai.tool.output'] = p.redact ? REDACTED : truncate(p.output, 3000);
235
+ return {
236
+ traceId: p.traceId, spanId: p.spanId, parentSpanId: p.parentSpanId,
237
+ name: `execute_tool ${p.toolName}`, kind: SPAN_KIND_CLIENT,
238
+ startTimeUnixNano: p.times.startNs, endTimeUnixNano: p.times.endNs,
239
+ attributes: kv(attrs), events: [], status: { code: p.isError ? STATUS_ERROR : STATUS_OK },
240
+ };
241
+ }
242
+
243
+ // ─── The extension (I/O wiring; not unit-tested) ─────────────────────────────
244
+
245
+ const SESSION_DIR = join('.pi', 'agent-health');
246
+ const SESSION_FILE = join(SESSION_DIR, 'current-session');
247
+
248
+ export default function (pi: ExtensionAPI) {
249
+ let sessionId: string | null = null;
250
+ let traceId: string | null = null;
251
+ let rootSpanId: string | null = null;
252
+ let rootStartNs: string | null = null;
253
+ const buffer: OtlpSpan[] = [];
254
+
255
+ // Per-turn / per-tool scratch state.
256
+ let turnStartMs = 0;
257
+ let pendingUserPrompt: string | undefined;
258
+ let firstTurnOfInvocation = false;
259
+ let lastUsage: { inputTokens?: number; outputTokens?: number } = {};
260
+ let lastCompletion: string | undefined;
261
+ let lastModel = 'unknown';
262
+ const toolStart = new Map<string, { startMs: number; toolName: string; input: unknown }>();
263
+
264
+ const redact = process.env.AGENT_HEALTH_REDACT === '1';
265
+ const endpoint = resolveEndpoint(process.env.OTEL_EXPORTER_OTLP_ENDPOINT);
266
+ const serviceName = process.env.OTEL_SERVICE_NAME || PI_SERVICE_NAME;
267
+ // Opt-in: only emit when an endpoint is explicitly configured, so a
268
+ // globally-installed copy never POSTs unexpectedly for unconfigured sessions.
269
+ const telemetryEnabled = (): boolean =>
270
+ process.env.OTEL_ENABLED !== 'false' && !!process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
271
+
272
+ async function flush(): Promise<void> {
273
+ if (!telemetryEnabled() || buffer.length === 0) return;
274
+ const batch = buffer.splice(0, buffer.length);
275
+ try {
276
+ await fetch(endpoint, {
277
+ method: 'POST',
278
+ headers: { 'Content-Type': 'application/json' },
279
+ body: JSON.stringify(buildOtlpPayload(serviceName, batch)),
280
+ });
281
+ } catch {
282
+ // Best-effort: drop the batch rather than block the session.
283
+ }
284
+ }
285
+
286
+ function recordSessionId(id: string): void {
287
+ try { mkdirSync(SESSION_DIR, { recursive: true }); writeFileSync(SESSION_FILE, id); } catch { /* best-effort */ }
288
+ }
289
+
290
+ pi.on('session_start', async (_e, ctx) => {
291
+ sessionId = sessionIdFromFile(ctx.sessionManager.getSessionFile()) ?? null;
292
+ if (!sessionId) return; // ephemeral session
293
+ recordSessionId(sessionId);
294
+ if (!telemetryEnabled()) return;
295
+
296
+ const parent = parseTraceparent(process.env.TRACEPARENT);
297
+ traceId = parent?.traceId ?? genTraceId();
298
+ rootSpanId = genSpanId();
299
+ rootStartNs = msToNanos(Date.now());
300
+ // Root span is finalized at shutdown; record start now.
301
+ });
302
+
303
+ pi.on('model_select', async (event) => {
304
+ const id = (event as { model?: { id?: string } }).model?.id;
305
+ if (id) lastModel = String(id);
306
+ });
307
+
308
+ pi.on('before_agent_start', async (event) => {
309
+ const prompt = (event as { prompt?: unknown }).prompt;
310
+ pendingUserPrompt = typeof prompt === 'string' ? prompt : undefined;
311
+ firstTurnOfInvocation = true;
312
+ });
313
+
314
+ pi.on('turn_start', async () => {
315
+ turnStartMs = Date.now();
316
+ lastUsage = {};
317
+ lastCompletion = undefined;
318
+ });
319
+
320
+ pi.on('message_end', async (event) => {
321
+ const msg = (event as { message?: any }).message;
322
+ if (!msg || msg.role !== 'assistant') return;
323
+ const usage = msg.usage || {};
324
+ lastUsage = {
325
+ inputTokens: numOrUndef(usage.inputTokens ?? usage.input_tokens ?? usage.promptTokens),
326
+ outputTokens: numOrUndef(usage.outputTokens ?? usage.output_tokens ?? usage.completionTokens),
327
+ };
328
+ lastCompletion = extractText(msg.content);
329
+ if (msg.model) lastModel = String(msg.model);
330
+ });
331
+
332
+ pi.on('turn_end', async () => {
333
+ if (!traceId || !rootSpanId || !sessionId) return;
334
+ buffer.push(buildChatSpan({
335
+ traceId, spanId: genSpanId(), parentSpanId: rootSpanId, sessionId,
336
+ times: { startNs: msToNanos(turnStartMs || Date.now()), endNs: msToNanos(Date.now()) },
337
+ model: lastModel, inputTokens: lastUsage.inputTokens, outputTokens: lastUsage.outputTokens,
338
+ userPrompt: firstTurnOfInvocation ? pendingUserPrompt : undefined, completion: lastCompletion, redact,
339
+ }));
340
+ firstTurnOfInvocation = false;
341
+ await flush();
342
+ });
343
+
344
+ pi.on('tool_execution_start', async (event) => {
345
+ const e = event as { toolCallId?: string; toolName?: string; args?: unknown };
346
+ toolStart.set(String(e.toolCallId), { startMs: Date.now(), toolName: String(e.toolName ?? 'tool'), input: e.args });
347
+ });
348
+
349
+ pi.on('tool_execution_end', async (event) => {
350
+ if (!traceId || !rootSpanId || !sessionId) return;
351
+ const e = event as { toolCallId?: string; result?: unknown; isError?: boolean };
352
+ const started = toolStart.get(String(e.toolCallId));
353
+ toolStart.delete(String(e.toolCallId));
354
+ buffer.push(buildToolSpan({
355
+ traceId, spanId: genSpanId(), parentSpanId: rootSpanId, sessionId,
356
+ times: { startNs: msToNanos(started?.startMs ?? Date.now()), endNs: msToNanos(Date.now()) },
357
+ toolName: started?.toolName ?? 'tool', input: started?.input, output: e.result, isError: !!e.isError, redact,
358
+ }));
359
+ await flush();
360
+ });
361
+
362
+ pi.on('session_shutdown', async () => {
363
+ if (traceId && rootSpanId && sessionId && rootStartNs) {
364
+ buffer.push(buildRootSpan({ traceId, spanId: rootSpanId, parentSpanId: parseTraceparent(process.env.TRACEPARENT)?.spanId, sessionId, times: { startNs: rootStartNs, endNs: msToNanos(Date.now()) } }));
365
+ }
366
+ await flush();
367
+ });
368
+
369
+ pi.registerCommand('agent-health-profile', {
370
+ description: 'Profile this pi session against an evaluator rubric and propose fixes',
371
+ handler: async (args, ctx) => {
372
+ const id = sessionId ?? sessionIdFromFile(ctx.sessionManager.getSessionFile());
373
+ if (!id) {
374
+ ctx.ui.notify('No session id (ephemeral session) — start pi without --no-session to profile.', 'warning');
375
+ return;
376
+ }
377
+ if (!telemetryEnabled()) {
378
+ ctx.ui.notify('Telemetry is off — set OTEL_EXPORTER_OTLP_ENDPOINT (e.g. http://localhost:4001 for file-mode Agent Health) and re-run the session so its traces are captured.', 'warning');
379
+ return;
380
+ }
381
+ await flush(); // ensure the just-finished turns are queryable
382
+
383
+ const { bin, args: cmdArgs } = buildProfileInvocation({
384
+ cli: process.env.AGENT_HEALTH_CLI || DEFAULT_CLI,
385
+ sessionId: id,
386
+ evaluator: parseFlag(args, ['-e', '--evaluator']),
387
+ feedback: parseFlag(args, ['-f', '--feedback']),
388
+ service: serviceName,
389
+ });
390
+ ctx.ui.notify(`Profiling pi session ${id}…`, 'info');
391
+ const result = await pi.exec(bin, cmdArgs, { timeout: 120_000 });
392
+ if (result.code !== 0) {
393
+ ctx.ui.notify(`profile failed (exit ${result.code}): ${truncate(result.stderr || result.stdout, 400)}`, 'error');
394
+ return;
395
+ }
396
+ const profile = extractJson(result.stdout);
397
+ if (!profile) {
398
+ ctx.ui.notify('profile produced no JSON — is telemetry reaching the trace store?', 'error');
399
+ return;
400
+ }
401
+ pi.sendUserMessage([
402
+ 'I ran `agent-health profile` on THIS pi session. Below is the JSON profile:',
403
+ 'the evaluator rubric (`evaluator.systemPrompt`), the reconstructed `trajectory`,',
404
+ 'deterministic `signals`, and my `userFeedback` (if any).',
405
+ '',
406
+ 'Using `evaluator.systemPrompt` as the rubric, review the trajectory + signals',
407
+ '+ THIS conversation (including any corrections I made) + the codebase here.',
408
+ 'Produce a prioritized list of concrete edits (file, change, why — cite the',
409
+ 'signal/`traceIds`, priority) and apply them on a NEW branch for review.',
410
+ '',
411
+ '```json',
412
+ truncate(JSON.stringify(profile), 60_000),
413
+ '```',
414
+ ].join('\n'));
415
+ },
416
+ });
417
+ }
@@ -0,0 +1,29 @@
1
+ import { AgentConfig } from '../types/index.js';
2
+ /**
3
+ * Determines if an agent can be run from the browser UI.
4
+ *
5
+ * Some agents (like Claude Code) require CLI execution because they:
6
+ * - Spawn local processes via child_process.spawn() (Node.js only)
7
+ * - Access local filesystem or environment variables
8
+ * - Cannot operate within browser sandbox security constraints
9
+ *
10
+ * @param agent - The agent configuration to check
11
+ * @returns true if the agent can be run from the browser, false if CLI-only
12
+ */
13
+ export declare function isBrowserCompatible(agent: AgentConfig): boolean;
14
+ /**
15
+ * Gets a user-friendly explanation for why an agent cannot run from the UI.
16
+ *
17
+ * @param agent - The agent configuration to check
18
+ * @returns Error message if agent requires CLI, null if browser-compatible
19
+ */
20
+ export declare function getAgentUnavailableReason(agent: AgentConfig): string | null;
21
+ /**
22
+ * Gets the first browser-compatible agent from a list.
23
+ * Useful for setting default selection in UI components.
24
+ *
25
+ * @param agents - List of agent configurations
26
+ * @returns The first browser-compatible agent, or undefined if none found
27
+ */
28
+ export declare function getFirstBrowserCompatibleAgent(agents: AgentConfig[]): AgentConfig | undefined;
29
+ //# sourceMappingURL=agentUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentUtils.d.ts","sourceRoot":"","sources":["../../agentUtils.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGtC;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAG/D;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAM3E;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,GAAG,SAAS,CAE7F"}
@@ -0,0 +1,43 @@
1
+ /*
2
+ * Copyright OpenSearch Contributors
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { BROWSER_SAFE_CONNECTORS } from '../lib/constants.js';
6
+ /**
7
+ * Determines if an agent can be run from the browser UI.
8
+ *
9
+ * Some agents (like Claude Code) require CLI execution because they:
10
+ * - Spawn local processes via child_process.spawn() (Node.js only)
11
+ * - Access local filesystem or environment variables
12
+ * - Cannot operate within browser sandbox security constraints
13
+ *
14
+ * @param agent - The agent configuration to check
15
+ * @returns true if the agent can be run from the browser, false if CLI-only
16
+ */
17
+ export function isBrowserCompatible(agent) {
18
+ const connectorType = agent.connectorType || 'agui-streaming';
19
+ return BROWSER_SAFE_CONNECTORS.includes(connectorType);
20
+ }
21
+ /**
22
+ * Gets a user-friendly explanation for why an agent cannot run from the UI.
23
+ *
24
+ * @param agent - The agent configuration to check
25
+ * @returns Error message if agent requires CLI, null if browser-compatible
26
+ */
27
+ export function getAgentUnavailableReason(agent) {
28
+ if (isBrowserCompatible(agent)) {
29
+ return null;
30
+ }
31
+ return `This agent requires the CLI. Run with: npx @opensearch-project/agent-health run -t <test-case> -a ${agent.key}`;
32
+ }
33
+ /**
34
+ * Gets the first browser-compatible agent from a list.
35
+ * Useful for setting default selection in UI components.
36
+ *
37
+ * @param agents - List of agent configurations
38
+ * @returns The first browser-compatible agent, or undefined if none found
39
+ */
40
+ export function getFirstBrowserCompatibleAgent(agents) {
41
+ return agents.find(agent => isBrowserCompatible(agent));
42
+ }
43
+ //# sourceMappingURL=agentUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentUtils.js","sourceRoot":"","sources":["../../agentUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAE1D;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAkB;IACpD,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,IAAI,gBAAgB,CAAC;IAC9D,OAAO,uBAAuB,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAAkB;IAC1D,IAAI,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,qGAAqG,KAAK,CAAC,GAAG,EAAE,CAAC;AAC1H,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,8BAA8B,CAAC,MAAqB;IAClE,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { TestCase } from '../types/index.js';
2
+ import type { ValidatedTestCaseInput } from '../lib/testCaseValidation.js';
3
+ /**
4
+ * Convert full TestCase objects to the import-compatible export format.
5
+ * The output matches the `testCaseSchema` shape from `lib/testCaseValidation.ts`,
6
+ * ensuring exported JSON can be re-imported via "Import JSON".
7
+ */
8
+ export declare function convertTestCasesToExportFormat(testCases: TestCase[]): ValidatedTestCaseInput[];
9
+ /**
10
+ * Generate a safe filename from a benchmark name.
11
+ * Sanitizes the name by replacing unsafe characters and appends `.json`.
12
+ */
13
+ export declare function generateExportFilename(benchmarkName: string): string;
14
+ //# sourceMappingURL=benchmarkExport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"benchmarkExport.d.ts","sourceRoot":"","sources":["../../benchmarkExport.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEvE;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,sBAAsB,EAAE,CAkB9F;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAUpE"}
@@ -0,0 +1,41 @@
1
+ /*
2
+ * Copyright OpenSearch Contributors
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ /**
6
+ * Convert full TestCase objects to the import-compatible export format.
7
+ * The output matches the `testCaseSchema` shape from `lib/testCaseValidation.ts`,
8
+ * ensuring exported JSON can be re-imported via "Import JSON".
9
+ */
10
+ export function convertTestCasesToExportFormat(testCases) {
11
+ return testCases.map((tc) => {
12
+ const exported = {
13
+ name: tc.name,
14
+ description: tc.description || '',
15
+ category: tc.category,
16
+ difficulty: tc.difficulty,
17
+ initialPrompt: tc.initialPrompt,
18
+ context: tc.context || [],
19
+ expectedOutcomes: tc.expectedOutcomes || [],
20
+ };
21
+ if (tc.subcategory) {
22
+ exported.subcategory = tc.subcategory;
23
+ }
24
+ return exported;
25
+ });
26
+ }
27
+ /**
28
+ * Generate a safe filename from a benchmark name.
29
+ * Sanitizes the name by replacing unsafe characters and appends `.json`.
30
+ */
31
+ export function generateExportFilename(benchmarkName) {
32
+ const sanitized = (benchmarkName || 'benchmark-export')
33
+ .trim()
34
+ .toLowerCase()
35
+ .replace(/[^a-z0-9_\-\s]/g, '')
36
+ .replace(/\s+/g, '-')
37
+ .replace(/-+/g, '-')
38
+ .replace(/^-|-$/g, '');
39
+ return `${sanitized || 'benchmark-export'}.json`;
40
+ }
41
+ //# sourceMappingURL=benchmarkExport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"benchmarkExport.js","sourceRoot":"","sources":["../../benchmarkExport.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;;;GAIG;AACH,MAAM,UAAU,8BAA8B,CAAC,SAAqB;IAClE,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QAC1B,MAAM,QAAQ,GAA2B;YACvC,IAAI,EAAE,EAAE,CAAC,IAAI;YACb,WAAW,EAAE,EAAE,CAAC,WAAW,IAAI,EAAE;YACjC,QAAQ,EAAE,EAAE,CAAC,QAAQ;YACrB,UAAU,EAAE,EAAE,CAAC,UAAU;YACzB,aAAa,EAAE,EAAE,CAAC,aAAa;YAC/B,OAAO,EAAE,EAAE,CAAC,OAAO,IAAI,EAAE;YACzB,gBAAgB,EAAE,EAAE,CAAC,gBAAgB,IAAI,EAAE;SAC5C,CAAC;QAEF,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YACnB,QAAQ,CAAC,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC;QACxC,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,aAAqB;IAC1D,MAAM,SAAS,GAAG,CAAC,aAAa,IAAI,kBAAkB,CAAC;SACpD,IAAI,EAAE;SACN,WAAW,EAAE;SACb,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC;SAC9B,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEzB,OAAO,GAAG,SAAS,IAAI,kBAAkB,OAAO,CAAC;AACnD,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { Benchmark, BenchmarkRun, TestCase } from '../types/index.js';
2
+ /**
3
+ * Enhanced version data with diff information
4
+ */
5
+ export interface VersionData {
6
+ version: number;
7
+ createdAt: string;
8
+ testCaseIds: string[];
9
+ isLatest: boolean;
10
+ added: string[];
11
+ removed: string[];
12
+ runCount: number;
13
+ }
14
+ /**
15
+ * Compute version data with diff information for a benchmark.
16
+ * Returns versions sorted by version number (newest first) with added/removed test case IDs.
17
+ */
18
+ export declare function computeVersionData(benchmark: Benchmark | null): VersionData[];
19
+ /**
20
+ * Get version data for a specific version number or the latest version.
21
+ * @param versionData - Array of computed version data
22
+ * @param selectedVersion - Version number to get, or null for latest
23
+ */
24
+ export declare function getSelectedVersionData(versionData: VersionData[], selectedVersion: number | null): VersionData | null;
25
+ /**
26
+ * Get test cases for a specific version.
27
+ * @param testCases - All available test cases
28
+ * @param selectedVersionData - The version data to get test cases for
29
+ */
30
+ export declare function getVersionTestCases(testCases: TestCase[], selectedVersionData: VersionData | null): TestCase[];
31
+ /**
32
+ * Filter runs by version.
33
+ * @param runs - All benchmark runs
34
+ * @param versionFilter - Version number to filter by, or 'all' for all runs
35
+ */
36
+ export declare function filterRunsByVersion(runs: BenchmarkRun[] | undefined, versionFilter: number | 'all'): BenchmarkRun[];
37
+ //# sourceMappingURL=benchmarkVersionUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"benchmarkVersionUtils.d.ts","sourceRoot":"","sources":["../../benchmarkVersionUtils.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAoB,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnF;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,WAAW,EAAE,CA0B7E;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,WAAW,EAAE,EAC1B,eAAe,EAAE,MAAM,GAAG,IAAI,GAC7B,WAAW,GAAG,IAAI,CAIpB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,QAAQ,EAAE,EACrB,mBAAmB,EAAE,WAAW,GAAG,IAAI,GACtC,QAAQ,EAAE,CAKZ;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,YAAY,EAAE,GAAG,SAAS,EAChC,aAAa,EAAE,MAAM,GAAG,KAAK,GAC5B,YAAY,EAAE,CAShB"}
@@ -0,0 +1,68 @@
1
+ /*
2
+ * Copyright OpenSearch Contributors
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ /**
6
+ * Compute version data with diff information for a benchmark.
7
+ * Returns versions sorted by version number (newest first) with added/removed test case IDs.
8
+ */
9
+ export function computeVersionData(benchmark) {
10
+ if (!benchmark?.versions || benchmark.versions.length === 0)
11
+ return [];
12
+ return benchmark.versions
13
+ .slice() // Create a copy to avoid mutating original
14
+ .sort((a, b) => b.version - a.version) // Newest first
15
+ .map((v, index, arr) => {
16
+ const prevVersion = arr[index + 1]; // Previous version (older)
17
+ const added = prevVersion
18
+ ? v.testCaseIds.filter(id => !prevVersion.testCaseIds.includes(id))
19
+ : [];
20
+ const removed = prevVersion
21
+ ? prevVersion.testCaseIds.filter(id => !v.testCaseIds.includes(id))
22
+ : [];
23
+ const runCount = benchmark.runs?.filter(r => (r.benchmarkVersion || 1) === v.version).length || 0;
24
+ return {
25
+ ...v,
26
+ isLatest: index === 0,
27
+ added,
28
+ removed,
29
+ runCount,
30
+ };
31
+ });
32
+ }
33
+ /**
34
+ * Get version data for a specific version number or the latest version.
35
+ * @param versionData - Array of computed version data
36
+ * @param selectedVersion - Version number to get, or null for latest
37
+ */
38
+ export function getSelectedVersionData(versionData, selectedVersion) {
39
+ if (versionData.length === 0)
40
+ return null;
41
+ if (selectedVersion === null)
42
+ return versionData[0]; // Latest
43
+ return versionData.find(v => v.version === selectedVersion) || versionData[0];
44
+ }
45
+ /**
46
+ * Get test cases for a specific version.
47
+ * @param testCases - All available test cases
48
+ * @param selectedVersionData - The version data to get test cases for
49
+ */
50
+ export function getVersionTestCases(testCases, selectedVersionData) {
51
+ if (!selectedVersionData)
52
+ return [];
53
+ return testCases.filter(tc => selectedVersionData.testCaseIds.includes(tc.id));
54
+ }
55
+ /**
56
+ * Filter runs by version.
57
+ * @param runs - All benchmark runs
58
+ * @param versionFilter - Version number to filter by, or 'all' for all runs
59
+ */
60
+ export function filterRunsByVersion(runs, versionFilter) {
61
+ if (!runs)
62
+ return [];
63
+ const sorted = [...runs].sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
64
+ if (versionFilter === 'all')
65
+ return sorted;
66
+ return sorted.filter(run => (run.benchmarkVersion || 1) === versionFilter);
67
+ }
68
+ //# sourceMappingURL=benchmarkVersionUtils.js.map