@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,390 @@
1
+ # Performance Optimization Guide
2
+
3
+ This document details the performance optimizations implemented in the Agent Health dashboard, specifically for the Benchmark Runs Overview page - the most data-intensive view in the application.
4
+
5
+ ## Overview
6
+
7
+ The Benchmark Runs Overview page (`/benchmarks/:id/runs`) displays:
8
+ - Multiple benchmark runs (potentially 100+)
9
+ - Test case execution results for each run
10
+ - Real-time status updates during active runs
11
+ - Historical run statistics and comparisons
12
+
13
+ **Performance Challenge**: Loading and updating this data efficiently without freezing the UI or overloading the network.
14
+
15
+ ## Architecture Pattern: Lightweight Polling Mode
16
+
17
+ The core optimization uses a **two-phase loading strategy**:
18
+
19
+ 1. **Initial Load** (Full Data) - Complete data fetch on page load
20
+ 2. **Polling Mode** (Lightweight) - Minimal data fetch for updates
21
+
22
+ ### Phase 1: Initial Load
23
+
24
+ **What happens:**
25
+ ```typescript
26
+ const benchmark = await asyncBenchmarkStorage.getById(benchmarkId, {
27
+ runsSize: 100 // Paginate runs
28
+ });
29
+ ```
30
+
31
+ **Data fetched:**
32
+ - Benchmark metadata (name, description, createdAt, etc.)
33
+ - Benchmark versions history (full)
34
+ - First 100 runs with complete details:
35
+ - Run configuration (agentKey, modelId, headers)
36
+ - Test case snapshots (version info)
37
+ - Results map (all test case outcomes)
38
+ - Stats (passed/failed/pending counts)
39
+
40
+ **Why full data?**
41
+ - User needs complete context on first view
42
+ - Static fields don't change during updates
43
+ - Baseline for comparison during polling
44
+
45
+ ### Phase 2: Polling Mode (Active Runs)
46
+
47
+ **What happens:**
48
+ ```typescript
49
+ const benchmark = await asyncBenchmarkStorage.getById(benchmarkId, {
50
+ fields: 'polling', // Lightweight mode
51
+ runsSize: 100
52
+ });
53
+ ```
54
+
55
+ **Data excluded** (via `_source_excludes` in OpenSearch):
56
+ - `versions` - Benchmark version history
57
+ - `runs.testCaseSnapshots` - Test case version snapshots
58
+ - `runs.headers` - Custom HTTP headers
59
+
60
+ **Data included** (lightweight fields):
61
+ - Run status (`running`, `completed`, etc.)
62
+ - Run results (test case outcomes)
63
+ - Run stats (passed/failed/pending counts)
64
+ - Timestamps (createdAt, updatedAt)
65
+
66
+ **Savings**: ~70-80% reduction in payload size for benchmarks with extensive version history or many runs with headers.
67
+
68
+ ## Backend Optimizations
69
+
70
+ ### 1. Field Projection (_source_excludes)
71
+
72
+ **Location**: `server/routes/storage/benchmarks.ts:456-459`
73
+
74
+ ```typescript
75
+ if (isPolling) {
76
+ getOptions._source_excludes = 'versions,runs.testCaseSnapshots,runs.headers';
77
+ }
78
+ ```
79
+
80
+ **How it works:**
81
+ - OpenSearch `_source_excludes` parameter tells the database not to return specified fields
82
+ - Happens at query time - no processing overhead
83
+ - Network transfer reduced proportionally to excluded data size
84
+
85
+ **Example savings**:
86
+ - Benchmark with 50 versions, 30 runs, each with 3 headers
87
+ - Full payload: ~500KB
88
+ - Polling payload: ~100KB
89
+ - **80% reduction**
90
+
91
+ ### 2. Run Pagination
92
+
93
+ **Location**: `server/routes/storage/benchmarks.ts:473-483`
94
+
95
+ ```typescript
96
+ if (runsSize !== null) {
97
+ const allRuns = normalized.runs;
98
+ const totalRuns = allRuns.length;
99
+ const paginatedRuns = allRuns.slice(runsOffset, runsOffset + runsSize);
100
+ return res.json({
101
+ ...normalized,
102
+ runs: paginatedRuns,
103
+ totalRuns,
104
+ hasMoreRuns: runsOffset + runsSize < totalRuns,
105
+ });
106
+ }
107
+ ```
108
+
109
+ **Why pagination?**
110
+ - Benchmarks can have 500+ runs over time
111
+ - UI only shows 100 most recent runs initially
112
+ - "Load More" button fetches older runs on demand
113
+
114
+ **API usage**:
115
+ ```typescript
116
+ // Get first 100 runs
117
+ GET /api/storage/benchmarks/:id?runsSize=100&runsOffset=0
118
+
119
+ // Get next 100 runs
120
+ GET /api/storage/benchmarks/:id?runsSize=100&runsOffset=100
121
+ ```
122
+
123
+ ### 3. Lazy Stats Backfill
124
+
125
+ **Location**: `server/routes/storage/benchmarks.ts:445-447`
126
+
127
+ ```typescript
128
+ // Lazy backfill: compute stats for completed runs missing them
129
+ await backfillRunStats(client, id, normalized.runs);
130
+ ```
131
+
132
+ **What it does:**
133
+ - Detects runs with missing or stale stats
134
+ - Recomputes stats from actual report data
135
+ - Updates OpenSearch in background (fire-and-forget)
136
+
137
+ **Why it's efficient:**
138
+ - Only computes for runs that need it (most don't)
139
+ - Non-blocking - response sent immediately
140
+ - Self-healing - fixes data inconsistencies automatically
141
+
142
+ **Backfill logic**:
143
+ ```typescript
144
+ const runsNeedingStats = runs.filter((r) => {
145
+ // Case 1: No stats at all
146
+ if (!r.stats && (r.status === 'completed' || r.status === 'cancelled')) {
147
+ return true;
148
+ }
149
+
150
+ // Case 2: Has stats but they appear stale
151
+ if (r.stats && r.stats.pending > 0 && r.status === 'completed') {
152
+ const allResultsCompleted = Object.values(r.results || {})
153
+ .every((result) => result.status === 'completed' || ...);
154
+ return allResultsCompleted; // Stale - recompute
155
+ }
156
+
157
+ return false;
158
+ });
159
+ ```
160
+
161
+ ## Frontend Optimizations
162
+
163
+ ### 1. Cached Static Fields
164
+
165
+ **Location**: `components/BenchmarkRunsPage.tsx:92-157`
166
+
167
+ ```typescript
168
+ // Cache for static fields excluded during polling
169
+ const cachedVersions = useRef<Benchmark['versions'] | null>(null);
170
+
171
+ // On initial load
172
+ cachedVersions.current = exp.versions;
173
+
174
+ // During polling
175
+ if (isPolling && cachedVersions.current) {
176
+ exp.versions = cachedVersions.current;
177
+ }
178
+ ```
179
+
180
+ **Why it matters:**
181
+ - Backend excludes versions during polling
182
+ - Frontend restores cached version from initial load
183
+ - UI components that depend on versions still work
184
+ - No need to re-fetch static data
185
+
186
+ ### 2. Conditional Test Case Loading
187
+
188
+ **Location**: `components/BenchmarkRunsPage.tsx:161-170`
189
+
190
+ ```typescript
191
+ // Only fetch test cases on initial load
192
+ if (!isPolling) {
193
+ const benchmarkTcs = await asyncTestCaseStorage.getByIds(exp.testCaseIds);
194
+ setTestCases(benchmarkTcs);
195
+ isInitialLoadDone.current = true;
196
+ }
197
+ ```
198
+
199
+ **Why it matters:**
200
+ - Test cases don't change during active runs
201
+ - Fetching on every poll is wasteful
202
+ - Bulk ID query (`getByIds`) is more efficient than individual lookups
203
+
204
+ ### 3. Adaptive Polling Intervals
205
+
206
+ **Location**: `components/BenchmarkRunsPage.tsx:347-355`
207
+
208
+ ```typescript
209
+ // Use 5s polling for background sync scenarios
210
+ // Use faster polling (2s) only when actively running with SSE connected
211
+ const interval = isRunning ? POLL_INTERVAL_MS : 5000;
212
+ ```
213
+
214
+ **Polling strategy**:
215
+
216
+ | Scenario | Interval | Reason |
217
+ |----------|----------|--------|
218
+ | Active run (SSE connected) | 2s | Real-time updates critical |
219
+ | Background sync (SSE disconnected) | 5s | Slower updates acceptable |
220
+ | No active runs | Stopped | No polling needed |
221
+
222
+ **Why adaptive?**
223
+ - Balances responsiveness vs. server load
224
+ - SSE handles most updates (polling is backup)
225
+ - Reduces unnecessary API calls by 60% in normal operation
226
+
227
+ ### 4. Derived Status with Memoization
228
+
229
+ **Location**: `components/BenchmarkRunsPage.tsx:47-77`
230
+
231
+ ```typescript
232
+ const getEffectiveRunStatus = (run: BenchmarkRun): BenchmarkRun['status'] => {
233
+ // Normalize legacy data (status: undefined) to proper enum values
234
+ if (run.status) return run.status;
235
+
236
+ // Derive from child results
237
+ const results = Object.values(run.results || {});
238
+ // ... status derivation logic
239
+ };
240
+ ```
241
+
242
+ **Why it matters:**
243
+ - Legacy runs may not have `status` field
244
+ - Computing on every render would be expensive
245
+ - Pure function enables React memoization
246
+ - UI always shows correct status
247
+
248
+ ## Network Metrics
249
+
250
+ ### Before Optimization (Full Polling)
251
+
252
+ **Benchmark with 30 runs, polling every 2s:**
253
+ - Payload size: ~500KB per request
254
+ - Network throughput: 250KB/s sustained
255
+ - Browser memory growth: ~50MB/min (cached responses)
256
+
257
+ ### After Optimization (Lightweight Polling)
258
+
259
+ **Same benchmark, lightweight polling:**
260
+ - Initial load: 500KB (one-time)
261
+ - Polling payload: 100KB per request
262
+ - Network throughput: 50KB/s sustained
263
+ - Browser memory: stable (~10MB)
264
+
265
+ **Improvement**: 80% reduction in network usage, 80% reduction in memory growth.
266
+
267
+ ## Best Practices for Contributors
268
+
269
+ ### Adding New Fields to Benchmark/Run
270
+
271
+ **❌ Don't:**
272
+ ```typescript
273
+ // Adding a large field that changes rarely
274
+ interface BenchmarkRun {
275
+ configuration: {
276
+ // 50KB of config data
277
+ };
278
+ }
279
+ ```
280
+
281
+ **✅ Do:**
282
+ ```typescript
283
+ // Add to polling exclusion list
284
+ if (isPolling) {
285
+ getOptions._source_excludes = 'versions,runs.testCaseSnapshots,runs.headers,runs.configuration';
286
+ }
287
+
288
+ // Cache on frontend
289
+ const cachedConfigs = useRef<Map<string, any>>(new Map());
290
+ ```
291
+
292
+ ### When to Use Pagination
293
+
294
+ **Use pagination when:**
295
+ - Entity count can grow unbounded (runs, test cases, reports)
296
+ - UI doesn't need all entities at once
297
+ - Sorting is by timestamp (newest first)
298
+
299
+ **Don't paginate when:**
300
+ - Entity count is fixed/small (<20 items)
301
+ - UI needs complete dataset for filtering
302
+ - Random access patterns are common
303
+
304
+ ### Monitoring Performance
305
+
306
+ **Debug mode logging:**
307
+ ```bash
308
+ # Enable debug mode
309
+ curl -X POST http://localhost:4001/api/debug -d '{"enabled":true}'
310
+
311
+ # Watch logs
312
+ # Look for: [Backfill], [StatsUpdate], polling frequency
313
+ ```
314
+
315
+ **Browser DevTools:**
316
+ - Network tab: Check payload sizes (should see 80% reduction in polling)
317
+ - Performance tab: Check for excessive re-renders
318
+ - Memory tab: Check for memory leaks (should be stable)
319
+
320
+ ## Troubleshooting
321
+
322
+ ### "Runs showing stale status"
323
+
324
+ **Symptom**: Runs show "pending" even though all tests completed.
325
+
326
+ **Fix**: Stats backfill runs automatically, but you can force refresh:
327
+ ```bash
328
+ curl -X POST http://localhost:4001/api/storage/benchmarks/:id/refresh-all-stats
329
+ ```
330
+
331
+ **Root cause**: Report updates bypassed stats refresh trigger.
332
+
333
+ ### "Polling not working"
334
+
335
+ **Symptom**: UI doesn't update during active runs.
336
+
337
+ **Check**:
338
+ 1. Is SSE stream connected? (Check network tab for `execute` event stream)
339
+ 2. Is polling enabled? (Check `shouldPoll` logic in component)
340
+ 3. Is backend responding? (Check server logs for polling requests)
341
+
342
+ ### "High memory usage"
343
+
344
+ **Symptom**: Browser tab using excessive memory.
345
+
346
+ **Likely causes**:
347
+ 1. Polling interval too fast (check if custom override exists)
348
+ 2. Not cleaning up intervals (check useEffect cleanup)
349
+ 3. Caching too much data (check ref size)
350
+
351
+ **Fix**: Reload page to reset, check console for errors.
352
+
353
+ ## Future Optimizations
354
+
355
+ ### Planned
356
+
357
+ 1. **Virtual scrolling** for run lists (500+ runs)
358
+ 2. **GraphQL-style field selection** (`?fields=id,name,status`)
359
+ 3. **WebSocket upgrades** (replace polling with push notifications)
360
+ 4. **IndexedDB caching** (offline support)
361
+
362
+ ### Under Consideration
363
+
364
+ 1. **Server-side rendering** for initial load
365
+ 2. **Incremental static regeneration** for historical data
366
+ 3. **Edge caching** with CDN for read-heavy workloads
367
+
368
+ ## Summary
369
+
370
+ **Key Takeaways:**
371
+
372
+ 1. **Lightweight polling** reduces network usage by 80%
373
+ 2. **Field projection** happens at database level (efficient)
374
+ 3. **Pagination** handles unbounded growth gracefully
375
+ 4. **Adaptive intervals** balance responsiveness vs. load
376
+ 5. **Lazy backfill** fixes data issues transparently
377
+
378
+ **Performance Gains:**
379
+
380
+ | Metric | Before | After | Improvement |
381
+ |--------|--------|-------|-------------|
382
+ | Polling payload | 500KB | 100KB | 80% ↓ |
383
+ | Network throughput | 250KB/s | 50KB/s | 80% ↓ |
384
+ | Memory growth | 50MB/min | 0MB/min | 100% ↓ |
385
+ | API calls (normal) | 30/min | 12/min | 60% ↓ |
386
+
387
+ **For more details**, see:
388
+ - Code: `components/BenchmarkRunsPage.tsx`
389
+ - Backend: `server/routes/storage/benchmarks.ts`
390
+ - Architecture: [ARCHITECTURE.md](ARCHITECTURE.md)
@@ -0,0 +1,169 @@
1
+ <!--
2
+ * Copyright OpenSearch Contributors
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ -->
5
+
6
+ # Profiling pi.dev sessions with Agent Health
7
+
8
+ **Agent profiling** is to an AI agent what a CPU/JVM profiler is to a running
9
+ program: you attach to a *real session*, sample its execution (OpenTelemetry
10
+ traces), and get back a report of where the agent went wrong and what to fix —
11
+ in the agent's **own codebase**, scored against an evaluator you choose as the
12
+ rubric. This guide covers profiling sessions of the [pi.dev](https://pi.dev)
13
+ coding agent.
14
+
15
+ For the cross-agent concept and the Claude Code path, see
16
+ [docs/skills/AGENT_PROFILE.md](skills/AGENT_PROFILE.md).
17
+
18
+ ## Why pi needs an extension
19
+
20
+ Claude Code emits OpenTelemetry natively (`CLAUDE_CODE_ENABLE_TELEMETRY`), so
21
+ `agent-health profile` can read a session's traces directly. **pi has no native
22
+ telemetry**, so a live pi session leaves nothing for `profile` to read.
23
+
24
+ A small, **zero-dependency** pi extension supplies the missing half. It both:
25
+
26
+ 1. **instruments** the running pi session — emitting OTel spans for the agent
27
+ loop; and
28
+ 2. **registers `/agent-health-profile`** — which runs the profile and feeds the
29
+ result back into the conversation so pi proposes fixes.
30
+
31
+ The extension ships as a single file:
32
+ [`examples/pi-profiling/agent-health-profile.ts`](../examples/pi-profiling/agent-health-profile.ts)
33
+ (see its [README](../examples/pi-profiling/README.md)). It speaks OTLP/HTTP JSON
34
+ over the built-in `fetch`, so there is nothing to `npm install`.
35
+
36
+ ## How it works
37
+
38
+ ```
39
+ pi session ──(extension emits OTel spans)──▶ OTLP endpoint ──▶ Agent Health trace store
40
+ │
41
+ /agent-health-profile ─────────────────────────────────────────────┤ resolves: evaluator rubric
42
+ ▼ samples: this session's spans → trajectory
43
+ { evaluator, trajectory, signals } + deterministic signal scan
44
+ │
45
+ the in-session pi agent adds: the live chat + the codebase
46
+ ▼
47
+ prioritized edits → applied on a branch → you review
48
+ ```
49
+
50
+ ## Install
51
+
52
+ ```bash
53
+ # 1. Drop the extension in. Global = every pi session; or .pi/extensions/ per project.
54
+ mkdir -p ~/.pi/agent/extensions
55
+ cp examples/pi-profiling/agent-health-profile.ts ~/.pi/agent/extensions/
56
+
57
+ # 2. Point telemetry at a trace store BEFORE starting pi (telemetry is opt-in —
58
+ # the extension only exports when this is set).
59
+ export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4001 # /v1/traces is appended
60
+ ```
61
+
62
+ The simplest zero-infra path is **Agent Health in file mode** (no OpenSearch):
63
+ its embedded `/v1/traces` receiver persists spans to disk and matches them by
64
+ `session.id` out of the box. For an OpenSearch-backed deployment, export to the
65
+ **same OTLP ingest your cluster reads from** (your OTel Collector / OSIS
66
+ pipeline) — the embedded receiver intentionally drops payloads when a cluster is
67
+ configured (no split-brain).
68
+
69
+ ## Configuration
70
+
71
+ | Env var | Default | Meaning |
72
+ |---------|---------|---------|
73
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | *(unset → telemetry off)* | OTLP traces target; `/v1/traces` is appended if missing |
74
+ | `OTEL_SERVICE_NAME` | `pi-agent` | `service.name` on emitted spans (keep `pi-agent` so `--service` defaults line up) |
75
+ | `OTEL_ENABLED` | `true` | set `false` to disable telemetry |
76
+ | `AGENT_HEALTH_REDACT` | *(unset)* | `1` → stamp redaction placeholders instead of capturing prompt / tool I/O |
77
+ | `AGENT_HEALTH_CLI` | `npx @opensearch-project/agent-health` | how the command invokes the CLI |
78
+
79
+ ## Usage
80
+
81
+ From inside a pi session, after you've worked normally and steered the agent:
82
+
83
+ ```
84
+ /agent-health-profile -e <evaluator-id> [-f "focus on routing; it ignored the SOP"]
85
+ ```
86
+
87
+ The command records the session id, runs the CLI, and feeds the JSON profile
88
+ (evaluator rubric + reconstructed trajectory + deterministic signals + your
89
+ feedback) back into the chat so pi proposes prioritized, evidence-cited edits on
90
+ a new branch.
91
+
92
+ Equivalently, from a shell:
93
+
94
+ ```bash
95
+ agent-health profile --session <id> --service pi-agent --output json
96
+ ```
97
+
98
+ `--service` auto-defaults to `pi-agent` when the session was resolved from the
99
+ pi marker file, so you can usually omit it.
100
+
101
+ ## What the extension emits
102
+
103
+ Each span follows the OpenTelemetry [Gen AI semantic
104
+ conventions](https://opentelemetry.io/docs/specs/semconv/gen-ai/) so Agent
105
+ Health categorizes it correctly:
106
+
107
+ | Span | `gen_ai.operation.name` | Notes |
108
+ |------|-------------------------|-------|
109
+ | `invoke_agent pi` (root) | `invoke_agent` | one per session; adopts a propagated `TRACEPARENT` when present |
110
+ | `chat <model>` (per turn) | `chat` | `gen_ai.usage.*` token counts + `llm.request` / `llm.response` prompt/completion events |
111
+ | `execute_tool <name>` | `execute_tool` | `gen_ai.tool.input` / `gen_ai.tool.output`; ERROR status on failure |
112
+
113
+ Every span carries `session.id`; the resource carries `service.name=pi-agent`.
114
+
115
+ The extension emits a **standard OTLP `session.id` attribute** — it is
116
+ schema-agnostic. The field path it lands on in OpenSearch (e.g. nested
117
+ `attributes.session.id` vs the legacy flattened `span.attributes.session@id`) is
118
+ decided by your **ingest pipeline**, not the extension; `agent-health profile`'s
119
+ session query and your ingest just need to agree on it.
120
+
121
+ ## Session identification
122
+
123
+ `profile` resolves the session id in priority order:
124
+
125
+ 1. `--session <id>` if you pass it,
126
+ 2. `.pi/agent-health/current-session` — written by this extension on
127
+ `session_start` (exact),
128
+ 3. `.claude/agent-health/current-session` (Claude Code), then the newest Claude
129
+ transcript for this cwd (heuristic fallback).
130
+
131
+ ## Deterministic signals
132
+
133
+ Before any LLM reasoning, `profile` runs a cheap signal scan over the session's
134
+ spans and hands the results to the rubric as evidence:
135
+
136
+ | id | meaning |
137
+ |----|---------|
138
+ | `user_redirect` | you corrected/redirected the agent mid-session |
139
+ | `tool_error_retry` | a tool failed, then was retried — tool-usage / description gap |
140
+ | `repeated_tool_calls` | identical tool+args invoked more than once — loop / distrust |
141
+ | `long_session` | unusually many turns — confusion or scope creep |
142
+ | `write_before_read` | mutated state before reading — safety / grounding gap |
143
+
144
+ ## Troubleshooting
145
+
146
+ - **"profile produced no JSON / no spans found"** — telemetry isn't reaching the
147
+ store, or the ingest schema and the session query disagree on the `session.id`
148
+ field path. Confirm `OTEL_EXPORTER_OTLP_ENDPOINT` is set and reachable, and
149
+ that the session ran *after* the extension loaded. Litmus test: the session
150
+ should appear in the Agent Health **Traces** tab.
151
+ - **Privacy** — set `AGENT_HEALTH_REDACT=1` to redact prompt / tool I/O (note:
152
+ the `user_redirect` signal needs prompt text to fire).
153
+
154
+ ## Caveats
155
+
156
+ - Profiling only sees sessions that ran **while the extension was loaded and
157
+ telemetry was on** — you cannot profile a session retroactively. Run a
158
+ session, then `/agent-health-profile`.
159
+ - The extension is read-only with respect to your code: it produces the profile
160
+ + a plan; apply edits on a **branch**, never the working tree.
161
+
162
+ ## See also
163
+
164
+ - [docs/skills/AGENT_PROFILE.md](skills/AGENT_PROFILE.md) — the cross-agent
165
+ profiling concept (Claude Code, Kiro, headless).
166
+ - [docs/INSTRUMENT_WITH_OTEL.md](INSTRUMENT_WITH_OTEL.md) — instrumenting your
167
+ own agent with OTel for Agent Health.
168
+ - [examples/pi-profiling/](../examples/pi-profiling/) — the distribution file
169
+ and its README.