@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.
- package/README.md +77 -6
- package/cli/dist/index.js +10072 -4502
- package/deployment/cloudformation/agent-health-observability.yaml +762 -0
- package/dist/assets/index-CCQRDlO0.js +243 -0
- package/dist/assets/index-CNHQVbcj.css +1 -0
- package/dist/index.html +2 -2
- package/docs/ARCHITECTURE.md +450 -0
- package/docs/BACKEND_JOB_QUEUE.md +405 -0
- package/docs/CLAUDE_CODE_TELEMETRY.md +283 -0
- package/docs/CLI.md +431 -0
- package/docs/CODING_AGENT_ANALYTICS.md +298 -0
- package/docs/CONFIGURATION.md +388 -0
- package/docs/CONNECTORS.md +536 -0
- package/docs/INSTRUMENT_WITH_OTEL.md +390 -0
- package/docs/ML-COMMONS-SETUP.md +289 -0
- package/docs/NPX_PACKAGING.md +195 -0
- package/docs/PERFORMANCE-MONITORING.md +200 -0
- package/docs/PERFORMANCE.md +390 -0
- package/docs/PI_PROFILING.md +169 -0
- package/docs/PLAN-non-agui-agent-support.md +525 -0
- package/docs/SDK.md +577 -0
- package/docs/SKILLS.md +264 -0
- package/docs/blogs/2026-02-28-opensearch-agent-health.md +200 -0
- package/docs/blogs/getting-started-blog.md +608 -0
- package/docs/diagrams/Agent-health.excalidraw +5656 -0
- package/docs/diagrams/architecture.png +0 -0
- package/docs/plans/field-redesign.md +468 -0
- package/docs/rfcs/001-coding-agent-analytics.md +374 -0
- package/docs/rfcs/002-enterprise-leaderboard.md +267 -0
- package/docs/rfcs/003-remote-aggregation.md +146 -0
- package/docs/rfcs/004-test-sdk-v2.md +599 -0
- package/docs/skills/AGENT_HEALTH.md +598 -0
- package/docs/skills/AGENT_PROFILE.md +191 -0
- package/docs/skills/add-connector/SKILL.md +68 -0
- package/docs/skills/agent-health-profile/SKILL.md +40 -0
- package/docs/skills/config-auth/SKILL.md +194 -0
- package/docs/skills/config-auth/evals/evals.json +35 -0
- package/docs/skills/create-pr/SKILL.md +73 -0
- package/docs/skills/instrument-otel/SKILL.md +84 -0
- package/docs/skills/write-test/SKILL.md +124 -0
- package/docs/ui prd.md +376 -0
- package/examples/README.md +53 -0
- package/examples/config/agent-health.config.example.ts +155 -0
- package/examples/connectors/echo-connector.ts +131 -0
- package/examples/eval-files/demo.eval.js +128 -0
- package/examples/eval-files/sdk-hooks-demo.eval.js +99 -0
- package/examples/pi-profiling/README.md +77 -0
- package/examples/pi-profiling/agent-health-profile.ts +417 -0
- package/lib/dist/lib/agentUtils.d.ts +29 -0
- package/lib/dist/lib/agentUtils.d.ts.map +1 -0
- package/lib/dist/lib/agentUtils.js +43 -0
- package/lib/dist/lib/agentUtils.js.map +1 -0
- package/lib/dist/lib/benchmarkExport.d.ts +14 -0
- package/lib/dist/lib/benchmarkExport.d.ts.map +1 -0
- package/lib/dist/lib/benchmarkExport.js +41 -0
- package/lib/dist/lib/benchmarkExport.js.map +1 -0
- package/lib/dist/lib/benchmarkVersionUtils.d.ts +37 -0
- package/lib/dist/lib/benchmarkVersionUtils.d.ts.map +1 -0
- package/lib/dist/lib/benchmarkVersionUtils.js +68 -0
- package/lib/dist/lib/benchmarkVersionUtils.js.map +1 -0
- package/lib/dist/lib/config/defineConfig.d.ts +27 -0
- package/lib/dist/lib/config/defineConfig.d.ts.map +1 -0
- package/lib/dist/lib/config/defineConfig.js +28 -0
- package/lib/dist/lib/config/defineConfig.js.map +1 -0
- package/lib/dist/lib/config/index.d.ts +9 -0
- package/lib/dist/lib/config/index.d.ts.map +1 -0
- package/lib/dist/lib/config/index.js +8 -0
- package/lib/dist/lib/config/index.js.map +1 -0
- package/lib/dist/lib/config/loader.d.ts +39 -0
- package/lib/dist/lib/config/loader.d.ts.map +1 -0
- package/lib/dist/lib/config/loader.js +258 -0
- package/lib/dist/lib/config/loader.js.map +1 -0
- package/lib/dist/lib/config/statePaths.d.ts +61 -0
- package/lib/dist/lib/config/statePaths.d.ts.map +1 -0
- package/lib/dist/lib/config/statePaths.js +188 -0
- package/lib/dist/lib/config/statePaths.js.map +1 -0
- package/lib/dist/lib/config/types.d.ts +231 -0
- package/lib/dist/lib/config/types.d.ts.map +1 -0
- package/lib/dist/lib/config/types.js +6 -0
- package/lib/dist/lib/config/types.js.map +1 -0
- package/lib/dist/lib/config.d.ts +39 -0
- package/lib/dist/lib/config.d.ts.map +1 -0
- package/lib/dist/lib/config.js +118 -0
- package/lib/dist/lib/config.js.map +1 -0
- package/lib/dist/lib/constants.d.ts +70 -0
- package/lib/dist/lib/constants.d.ts.map +1 -0
- package/lib/dist/lib/constants.js +365 -0
- package/lib/dist/lib/constants.js.map +1 -0
- package/lib/dist/lib/contextUtilization.d.ts +23 -0
- package/lib/dist/lib/contextUtilization.d.ts.map +1 -0
- package/lib/dist/lib/contextUtilization.js +72 -0
- package/lib/dist/lib/contextUtilization.js.map +1 -0
- package/lib/dist/lib/dashboardMetrics.d.ts +87 -0
- package/lib/dist/lib/dashboardMetrics.d.ts.map +1 -0
- package/lib/dist/lib/dashboardMetrics.js +242 -0
- package/lib/dist/lib/dashboardMetrics.js.map +1 -0
- package/lib/dist/lib/dataSourceConfig.d.ts +108 -0
- package/lib/dist/lib/dataSourceConfig.d.ts.map +1 -0
- package/lib/dist/lib/dataSourceConfig.js +166 -0
- package/lib/dist/lib/dataSourceConfig.js.map +1 -0
- package/lib/dist/lib/debug.d.ts +26 -0
- package/lib/dist/lib/debug.d.ts.map +1 -0
- package/lib/dist/lib/debug.js +132 -0
- package/lib/dist/lib/debug.js.map +1 -0
- package/lib/dist/lib/diagnostics.d.ts +28 -0
- package/lib/dist/lib/diagnostics.d.ts.map +1 -0
- package/lib/dist/lib/diagnostics.js +65 -0
- package/lib/dist/lib/diagnostics.js.map +1 -0
- package/lib/dist/lib/envCompat.d.ts +27 -0
- package/lib/dist/lib/envCompat.d.ts.map +1 -0
- package/lib/dist/lib/envCompat.js +73 -0
- package/lib/dist/lib/envCompat.js.map +1 -0
- package/lib/dist/lib/findPackageRoot.d.ts +7 -0
- package/lib/dist/lib/findPackageRoot.d.ts.map +1 -0
- package/lib/dist/lib/findPackageRoot.js +57 -0
- package/lib/dist/lib/findPackageRoot.js.map +1 -0
- package/lib/dist/lib/hooks.d.ts +36 -0
- package/lib/dist/lib/hooks.d.ts.map +1 -0
- package/lib/dist/lib/hooks.js +112 -0
- package/lib/dist/lib/hooks.js.map +1 -0
- package/lib/dist/lib/index.d.ts +47 -0
- package/lib/dist/lib/index.d.ts.map +1 -0
- package/lib/dist/lib/index.js +62 -0
- package/lib/dist/lib/index.js.map +1 -0
- package/lib/dist/lib/labels.d.ts +90 -0
- package/lib/dist/lib/labels.d.ts.map +1 -0
- package/lib/dist/lib/labels.js +158 -0
- package/lib/dist/lib/labels.js.map +1 -0
- package/lib/dist/lib/markdown.d.ts +16 -0
- package/lib/dist/lib/markdown.d.ts.map +1 -0
- package/lib/dist/lib/markdown.js +42 -0
- package/lib/dist/lib/markdown.js.map +1 -0
- package/lib/dist/lib/matchers/expect.d.ts +3 -0
- package/lib/dist/lib/matchers/expect.d.ts.map +1 -0
- package/lib/dist/lib/matchers/expect.js +225 -0
- package/lib/dist/lib/matchers/expect.js.map +1 -0
- package/lib/dist/lib/matchers/index.d.ts +8 -0
- package/lib/dist/lib/matchers/index.d.ts.map +1 -0
- package/lib/dist/lib/matchers/index.js +9 -0
- package/lib/dist/lib/matchers/index.js.map +1 -0
- package/lib/dist/lib/matchers/judgeAccessor.d.ts +113 -0
- package/lib/dist/lib/matchers/judgeAccessor.d.ts.map +1 -0
- package/lib/dist/lib/matchers/judgeAccessor.js +183 -0
- package/lib/dist/lib/matchers/judgeAccessor.js.map +1 -0
- package/lib/dist/lib/matchers/session.d.ts +39 -0
- package/lib/dist/lib/matchers/session.d.ts.map +1 -0
- package/lib/dist/lib/matchers/session.js +116 -0
- package/lib/dist/lib/matchers/session.js.map +1 -0
- package/lib/dist/lib/matchers/traces.d.ts +55 -0
- package/lib/dist/lib/matchers/traces.d.ts.map +1 -0
- package/lib/dist/lib/matchers/traces.js +116 -0
- package/lib/dist/lib/matchers/traces.js.map +1 -0
- package/lib/dist/lib/matchers/types.d.ts +75 -0
- package/lib/dist/lib/matchers/types.d.ts.map +1 -0
- package/lib/dist/lib/matchers/types.js +6 -0
- package/lib/dist/lib/matchers/types.js.map +1 -0
- package/lib/dist/lib/packagePaths.d.ts +29 -0
- package/lib/dist/lib/packagePaths.d.ts.map +1 -0
- package/lib/dist/lib/packagePaths.js +63 -0
- package/lib/dist/lib/packagePaths.js.map +1 -0
- package/lib/dist/lib/performance.d.ts +51 -0
- package/lib/dist/lib/performance.d.ts.map +1 -0
- package/lib/dist/lib/performance.js +159 -0
- package/lib/dist/lib/performance.js.map +1 -0
- package/lib/dist/lib/portConfig.d.ts +29 -0
- package/lib/dist/lib/portConfig.d.ts.map +1 -0
- package/lib/dist/lib/portConfig.js +64 -0
- package/lib/dist/lib/portConfig.js.map +1 -0
- package/lib/dist/lib/preferences.d.ts +63 -0
- package/lib/dist/lib/preferences.d.ts.map +1 -0
- package/lib/dist/lib/preferences.js +117 -0
- package/lib/dist/lib/preferences.js.map +1 -0
- package/lib/dist/lib/resolveAgentModel.d.ts +22 -0
- package/lib/dist/lib/resolveAgentModel.d.ts.map +1 -0
- package/lib/dist/lib/resolveAgentModel.js +37 -0
- package/lib/dist/lib/resolveAgentModel.js.map +1 -0
- package/lib/dist/lib/runStats.d.ts +92 -0
- package/lib/dist/lib/runStats.d.ts.map +1 -0
- package/lib/dist/lib/runStats.js +160 -0
- package/lib/dist/lib/runStats.js.map +1 -0
- package/lib/dist/lib/telemetry/constants.d.ts +60 -0
- package/lib/dist/lib/telemetry/constants.d.ts.map +1 -0
- package/lib/dist/lib/telemetry/constants.js +87 -0
- package/lib/dist/lib/telemetry/constants.js.map +1 -0
- package/lib/dist/lib/telemetry/evalSpans.d.ts +61 -0
- package/lib/dist/lib/telemetry/evalSpans.d.ts.map +1 -0
- package/lib/dist/lib/telemetry/evalSpans.js +254 -0
- package/lib/dist/lib/telemetry/evalSpans.js.map +1 -0
- package/lib/dist/lib/telemetry/index.d.ts +11 -0
- package/lib/dist/lib/telemetry/index.d.ts.map +1 -0
- package/lib/dist/lib/telemetry/index.js +15 -0
- package/lib/dist/lib/telemetry/index.js.map +1 -0
- package/lib/dist/lib/telemetry/opensearchExporter.d.ts +43 -0
- package/lib/dist/lib/telemetry/opensearchExporter.d.ts.map +1 -0
- package/lib/dist/lib/telemetry/opensearchExporter.js +217 -0
- package/lib/dist/lib/telemetry/opensearchExporter.js.map +1 -0
- package/lib/dist/lib/telemetry/provider.d.ts +55 -0
- package/lib/dist/lib/telemetry/provider.d.ts.map +1 -0
- package/lib/dist/lib/telemetry/provider.js +140 -0
- package/lib/dist/lib/telemetry/provider.js.map +1 -0
- package/lib/dist/lib/testCaseLabels.d.ts +34 -0
- package/lib/dist/lib/testCaseLabels.d.ts.map +1 -0
- package/lib/dist/lib/testCaseLabels.js +88 -0
- package/lib/dist/lib/testCaseLabels.js.map +1 -0
- package/lib/dist/lib/testCaseValidation.d.ts +140 -0
- package/lib/dist/lib/testCaseValidation.d.ts.map +1 -0
- package/lib/dist/lib/testCaseValidation.js +162 -0
- package/lib/dist/lib/testCaseValidation.js.map +1 -0
- package/lib/dist/lib/testCases/agentFixture.d.ts +80 -0
- package/lib/dist/lib/testCases/agentFixture.d.ts.map +1 -0
- package/lib/dist/lib/testCases/agentFixture.js +43 -0
- package/lib/dist/lib/testCases/agentFixture.js.map +1 -0
- package/lib/dist/lib/testCases/authoringSurface.d.ts +10 -0
- package/lib/dist/lib/testCases/authoringSurface.d.ts.map +1 -0
- package/lib/dist/lib/testCases/authoringSurface.js +54 -0
- package/lib/dist/lib/testCases/authoringSurface.js.map +1 -0
- package/lib/dist/lib/testCases/codemod.d.ts +13 -0
- package/lib/dist/lib/testCases/codemod.d.ts.map +1 -0
- package/lib/dist/lib/testCases/codemod.js +169 -0
- package/lib/dist/lib/testCases/codemod.js.map +1 -0
- package/lib/dist/lib/testCases/define.d.ts +114 -0
- package/lib/dist/lib/testCases/define.d.ts.map +1 -0
- package/lib/dist/lib/testCases/define.js +253 -0
- package/lib/dist/lib/testCases/define.js.map +1 -0
- package/lib/dist/lib/testCases/evaluators.d.ts +80 -0
- package/lib/dist/lib/testCases/evaluators.d.ts.map +1 -0
- package/lib/dist/lib/testCases/evaluators.js +105 -0
- package/lib/dist/lib/testCases/evaluators.js.map +1 -0
- package/lib/dist/lib/testCases/index.d.ts +14 -0
- package/lib/dist/lib/testCases/index.d.ts.map +1 -0
- package/lib/dist/lib/testCases/index.js +12 -0
- package/lib/dist/lib/testCases/index.js.map +1 -0
- package/lib/dist/lib/testCases/judge.d.ts +165 -0
- package/lib/dist/lib/testCases/judge.d.ts.map +1 -0
- package/lib/dist/lib/testCases/judge.js +359 -0
- package/lib/dist/lib/testCases/judge.js.map +1 -0
- package/lib/dist/lib/testCases/loader.d.ts +26 -0
- package/lib/dist/lib/testCases/loader.d.ts.map +1 -0
- package/lib/dist/lib/testCases/loader.js +149 -0
- package/lib/dist/lib/testCases/loader.js.map +1 -0
- package/lib/dist/lib/testCases/types.d.ts +242 -0
- package/lib/dist/lib/testCases/types.d.ts.map +1 -0
- package/lib/dist/lib/testCases/types.js +6 -0
- package/lib/dist/lib/testCases/types.js.map +1 -0
- package/lib/dist/lib/theme.d.ts +6 -0
- package/lib/dist/lib/theme.d.ts.map +1 -0
- package/lib/dist/lib/theme.js +36 -0
- package/lib/dist/lib/theme.js.map +1 -0
- package/lib/dist/lib/uiTelemetry.d.ts +7 -0
- package/lib/dist/lib/uiTelemetry.d.ts.map +1 -0
- package/lib/dist/lib/uiTelemetry.js +25 -0
- package/lib/dist/lib/uiTelemetry.js.map +1 -0
- package/lib/dist/lib/utils.d.ts +96 -0
- package/lib/dist/lib/utils.d.ts.map +1 -0
- package/lib/dist/lib/utils.js +232 -0
- package/lib/dist/lib/utils.js.map +1 -0
- package/lib/dist/lib/workflow/consolidate.d.ts +12 -0
- package/lib/dist/lib/workflow/consolidate.d.ts.map +1 -0
- package/lib/dist/lib/workflow/consolidate.js +33 -0
- package/lib/dist/lib/workflow/consolidate.js.map +1 -0
- package/lib/dist/lib/workflow/index.d.ts +13 -0
- package/lib/dist/lib/workflow/index.d.ts.map +1 -0
- package/lib/dist/lib/workflow/index.js +12 -0
- package/lib/dist/lib/workflow/index.js.map +1 -0
- package/lib/dist/lib/workflow/ledger.d.ts +30 -0
- package/lib/dist/lib/workflow/ledger.d.ts.map +1 -0
- package/lib/dist/lib/workflow/ledger.js +41 -0
- package/lib/dist/lib/workflow/ledger.js.map +1 -0
- package/lib/dist/lib/workflow/pool.d.ts +13 -0
- package/lib/dist/lib/workflow/pool.d.ts.map +1 -0
- package/lib/dist/lib/workflow/pool.js +44 -0
- package/lib/dist/lib/workflow/pool.js.map +1 -0
- package/lib/dist/lib/workflow/source.d.ts +22 -0
- package/lib/dist/lib/workflow/source.d.ts.map +1 -0
- package/lib/dist/lib/workflow/source.js +29 -0
- package/lib/dist/lib/workflow/source.js.map +1 -0
- package/lib/dist/lib/workflow/stepB.d.ts +71 -0
- package/lib/dist/lib/workflow/stepB.d.ts.map +1 -0
- package/lib/dist/lib/workflow/stepB.js +99 -0
- package/lib/dist/lib/workflow/stepB.js.map +1 -0
- package/lib/dist/lib/workflow/types.d.ts +86 -0
- package/lib/dist/lib/workflow/types.d.ts.map +1 -0
- package/lib/dist/lib/workflow/types.js +6 -0
- package/lib/dist/lib/workflow/types.js.map +1 -0
- package/lib/dist/lib/workflow/workflow.d.ts +119 -0
- package/lib/dist/lib/workflow/workflow.d.ts.map +1 -0
- package/lib/dist/lib/workflow/workflow.js +195 -0
- package/lib/dist/lib/workflow/workflow.js.map +1 -0
- package/lib/dist/services/agent/aguiConverter.d.ts +50 -0
- package/lib/dist/services/agent/aguiConverter.d.ts.map +1 -0
- package/lib/dist/services/agent/aguiConverter.js +449 -0
- package/lib/dist/services/agent/aguiConverter.js.map +1 -0
- package/lib/dist/services/agent/index.d.ts +10 -0
- package/lib/dist/services/agent/index.d.ts.map +1 -0
- package/lib/dist/services/agent/index.js +12 -0
- package/lib/dist/services/agent/index.js.map +1 -0
- package/lib/dist/services/agent/payloadBuilder.d.ts +33 -0
- package/lib/dist/services/agent/payloadBuilder.d.ts.map +1 -0
- package/lib/dist/services/agent/payloadBuilder.js +75 -0
- package/lib/dist/services/agent/payloadBuilder.js.map +1 -0
- package/lib/dist/services/agent/sseStream.d.ts +43 -0
- package/lib/dist/services/agent/sseStream.d.ts.map +1 -0
- package/lib/dist/services/agent/sseStream.js +223 -0
- package/lib/dist/services/agent/sseStream.js.map +1 -0
- package/lib/dist/services/connectors/agui/AGUIStreamingConnector.d.ts +44 -0
- package/lib/dist/services/connectors/agui/AGUIStreamingConnector.d.ts.map +1 -0
- package/lib/dist/services/connectors/agui/AGUIStreamingConnector.js +95 -0
- package/lib/dist/services/connectors/agui/AGUIStreamingConnector.js.map +1 -0
- package/lib/dist/services/connectors/base/BaseConnector.d.ts +81 -0
- package/lib/dist/services/connectors/base/BaseConnector.d.ts.map +1 -0
- package/lib/dist/services/connectors/base/BaseConnector.js +170 -0
- package/lib/dist/services/connectors/base/BaseConnector.js.map +1 -0
- package/lib/dist/services/connectors/claude-code/ClaudeCodeConnector.d.ts +116 -0
- package/lib/dist/services/connectors/claude-code/ClaudeCodeConnector.d.ts.map +1 -0
- package/lib/dist/services/connectors/claude-code/ClaudeCodeConnector.js +403 -0
- package/lib/dist/services/connectors/claude-code/ClaudeCodeConnector.js.map +1 -0
- package/lib/dist/services/connectors/index.d.ts +13 -0
- package/lib/dist/services/connectors/index.d.ts.map +1 -0
- package/lib/dist/services/connectors/index.js +32 -0
- package/lib/dist/services/connectors/index.js.map +1 -0
- package/lib/dist/services/connectors/kiro/KiroConnector.d.ts +48 -0
- package/lib/dist/services/connectors/kiro/KiroConnector.d.ts.map +1 -0
- package/lib/dist/services/connectors/kiro/KiroConnector.js +158 -0
- package/lib/dist/services/connectors/kiro/KiroConnector.js.map +1 -0
- package/lib/dist/services/connectors/langgraph/LangGraphConnector.d.ts +36 -0
- package/lib/dist/services/connectors/langgraph/LangGraphConnector.d.ts.map +1 -0
- package/lib/dist/services/connectors/langgraph/LangGraphConnector.js +175 -0
- package/lib/dist/services/connectors/langgraph/LangGraphConnector.js.map +1 -0
- package/lib/dist/services/connectors/mock/MockConnector.d.ts +37 -0
- package/lib/dist/services/connectors/mock/MockConnector.d.ts.map +1 -0
- package/lib/dist/services/connectors/mock/MockConnector.js +120 -0
- package/lib/dist/services/connectors/mock/MockConnector.js.map +1 -0
- package/lib/dist/services/connectors/openai-compatible/OpenAICompatibleConnector.d.ts +42 -0
- package/lib/dist/services/connectors/openai-compatible/OpenAICompatibleConnector.d.ts.map +1 -0
- package/lib/dist/services/connectors/openai-compatible/OpenAICompatibleConnector.js +133 -0
- package/lib/dist/services/connectors/openai-compatible/OpenAICompatibleConnector.js.map +1 -0
- package/lib/dist/services/connectors/pi/PiConnector.d.ts +87 -0
- package/lib/dist/services/connectors/pi/PiConnector.d.ts.map +1 -0
- package/lib/dist/services/connectors/pi/PiConnector.js +274 -0
- package/lib/dist/services/connectors/pi/PiConnector.js.map +1 -0
- package/lib/dist/services/connectors/registry.d.ts +57 -0
- package/lib/dist/services/connectors/registry.d.ts.map +1 -0
- package/lib/dist/services/connectors/registry.js +106 -0
- package/lib/dist/services/connectors/registry.js.map +1 -0
- package/lib/dist/services/connectors/rest/RESTConnector.d.ts +38 -0
- package/lib/dist/services/connectors/rest/RESTConnector.d.ts.map +1 -0
- package/lib/dist/services/connectors/rest/RESTConnector.js +117 -0
- package/lib/dist/services/connectors/rest/RESTConnector.js.map +1 -0
- package/lib/dist/services/connectors/server.d.ts +13 -0
- package/lib/dist/services/connectors/server.d.ts.map +1 -0
- package/lib/dist/services/connectors/server.js +34 -0
- package/lib/dist/services/connectors/server.js.map +1 -0
- package/lib/dist/services/connectors/strands/StrandsConnector.d.ts +48 -0
- package/lib/dist/services/connectors/strands/StrandsConnector.d.ts.map +1 -0
- package/lib/dist/services/connectors/strands/StrandsConnector.js +221 -0
- package/lib/dist/services/connectors/strands/StrandsConnector.js.map +1 -0
- package/lib/dist/services/connectors/subprocess/SubprocessConnector.d.ts +88 -0
- package/lib/dist/services/connectors/subprocess/SubprocessConnector.d.ts.map +1 -0
- package/lib/dist/services/connectors/subprocess/SubprocessConnector.js +418 -0
- package/lib/dist/services/connectors/subprocess/SubprocessConnector.js.map +1 -0
- package/lib/dist/services/connectors/types.d.ts +213 -0
- package/lib/dist/services/connectors/types.d.ts.map +1 -0
- package/lib/dist/services/connectors/types.js +6 -0
- package/lib/dist/services/connectors/types.js.map +1 -0
- package/lib/dist/services/evaluation/bedrockJudge.d.ts +64 -0
- package/lib/dist/services/evaluation/bedrockJudge.d.ts.map +1 -0
- package/lib/dist/services/evaluation/bedrockJudge.js +167 -0
- package/lib/dist/services/evaluation/bedrockJudge.js.map +1 -0
- package/lib/dist/services/evaluation/evaluatorError.d.ts +56 -0
- package/lib/dist/services/evaluation/evaluatorError.d.ts.map +1 -0
- package/lib/dist/services/evaluation/evaluatorError.js +56 -0
- package/lib/dist/services/evaluation/evaluatorError.js.map +1 -0
- package/lib/dist/services/evaluation/index.d.ts +106 -0
- package/lib/dist/services/evaluation/index.d.ts.map +1 -0
- package/lib/dist/services/evaluation/index.js +684 -0
- package/lib/dist/services/evaluation/index.js.map +1 -0
- package/lib/dist/services/evaluation/mockTrajectory.d.ts +3 -0
- package/lib/dist/services/evaluation/mockTrajectory.d.ts.map +1 -0
- package/lib/dist/services/evaluation/mockTrajectory.js +72 -0
- package/lib/dist/services/evaluation/mockTrajectory.js.map +1 -0
- package/lib/dist/services/opensearch/client.d.ts +26 -0
- package/lib/dist/services/opensearch/client.d.ts.map +1 -0
- package/lib/dist/services/opensearch/client.js +131 -0
- package/lib/dist/services/opensearch/client.js.map +1 -0
- package/lib/dist/services/opensearch/index.d.ts +16 -0
- package/lib/dist/services/opensearch/index.d.ts.map +1 -0
- package/lib/dist/services/opensearch/index.js +25 -0
- package/lib/dist/services/opensearch/index.js.map +1 -0
- package/lib/dist/services/storage/asyncBenchmarkStorage.d.ts +123 -0
- package/lib/dist/services/storage/asyncBenchmarkStorage.d.ts.map +1 -0
- package/lib/dist/services/storage/asyncBenchmarkStorage.js +429 -0
- package/lib/dist/services/storage/asyncBenchmarkStorage.js.map +1 -0
- package/lib/dist/services/storage/asyncRunStorage.d.ts +127 -0
- package/lib/dist/services/storage/asyncRunStorage.d.ts.map +1 -0
- package/lib/dist/services/storage/asyncRunStorage.js +448 -0
- package/lib/dist/services/storage/asyncRunStorage.js.map +1 -0
- package/lib/dist/services/storage/asyncTestCaseStorage.d.ts +156 -0
- package/lib/dist/services/storage/asyncTestCaseStorage.d.ts.map +1 -0
- package/lib/dist/services/storage/asyncTestCaseStorage.js +285 -0
- package/lib/dist/services/storage/asyncTestCaseStorage.js.map +1 -0
- package/lib/dist/services/storage/index.d.ts +17 -0
- package/lib/dist/services/storage/index.d.ts.map +1 -0
- package/lib/dist/services/storage/index.js +20 -0
- package/lib/dist/services/storage/index.js.map +1 -0
- package/lib/dist/services/storage/migration.d.ts +54 -0
- package/lib/dist/services/storage/migration.d.ts.map +1 -0
- package/lib/dist/services/storage/migration.js +296 -0
- package/lib/dist/services/storage/migration.js.map +1 -0
- package/lib/dist/services/storage/opensearchClient.d.ts +924 -0
- package/lib/dist/services/storage/opensearchClient.d.ts.map +1 -0
- package/lib/dist/services/storage/opensearchClient.js +435 -0
- package/lib/dist/services/storage/opensearchClient.js.map +1 -0
- package/lib/dist/services/traces/browserRecovery.d.ts +26 -0
- package/lib/dist/services/traces/browserRecovery.d.ts.map +1 -0
- package/lib/dist/services/traces/browserRecovery.js +81 -0
- package/lib/dist/services/traces/browserRecovery.js.map +1 -0
- package/lib/dist/services/traces/categoryStyles.d.ts +21 -0
- package/lib/dist/services/traces/categoryStyles.d.ts.map +1 -0
- package/lib/dist/services/traces/categoryStyles.js +56 -0
- package/lib/dist/services/traces/categoryStyles.js.map +1 -0
- package/lib/dist/services/traces/executionOrderTransform.d.ts +35 -0
- package/lib/dist/services/traces/executionOrderTransform.d.ts.map +1 -0
- package/lib/dist/services/traces/executionOrderTransform.js +313 -0
- package/lib/dist/services/traces/executionOrderTransform.js.map +1 -0
- package/lib/dist/services/traces/fetchSpansForRun.d.ts +86 -0
- package/lib/dist/services/traces/fetchSpansForRun.d.ts.map +1 -0
- package/lib/dist/services/traces/fetchSpansForRun.js +69 -0
- package/lib/dist/services/traces/fetchSpansForRun.js.map +1 -0
- package/lib/dist/services/traces/flowTransform.d.ts +24 -0
- package/lib/dist/services/traces/flowTransform.d.ts.map +1 -0
- package/lib/dist/services/traces/flowTransform.js +228 -0
- package/lib/dist/services/traces/flowTransform.js.map +1 -0
- package/lib/dist/services/traces/index.d.ts +121 -0
- package/lib/dist/services/traces/index.d.ts.map +1 -0
- package/lib/dist/services/traces/index.js +255 -0
- package/lib/dist/services/traces/index.js.map +1 -0
- package/lib/dist/services/traces/intentTransform.d.ts +20 -0
- package/lib/dist/services/traces/intentTransform.d.ts.map +1 -0
- package/lib/dist/services/traces/intentTransform.js +131 -0
- package/lib/dist/services/traces/intentTransform.js.map +1 -0
- package/lib/dist/services/traces/judgeAgentsHints.d.ts +63 -0
- package/lib/dist/services/traces/judgeAgentsHints.d.ts.map +1 -0
- package/lib/dist/services/traces/judgeAgentsHints.js +89 -0
- package/lib/dist/services/traces/judgeAgentsHints.js.map +1 -0
- package/lib/dist/services/traces/messageExtraction.d.ts +15 -0
- package/lib/dist/services/traces/messageExtraction.d.ts.map +1 -0
- package/lib/dist/services/traces/messageExtraction.js +251 -0
- package/lib/dist/services/traces/messageExtraction.js.map +1 -0
- package/lib/dist/services/traces/spanCategorization.d.ts +63 -0
- package/lib/dist/services/traces/spanCategorization.d.ts.map +1 -0
- package/lib/dist/services/traces/spanCategorization.js +276 -0
- package/lib/dist/services/traces/spanCategorization.js.map +1 -0
- package/lib/dist/services/traces/spanPreprocessing.d.ts +37 -0
- package/lib/dist/services/traces/spanPreprocessing.d.ts.map +1 -0
- package/lib/dist/services/traces/spanPreprocessing.js +102 -0
- package/lib/dist/services/traces/spanPreprocessing.js.map +1 -0
- package/lib/dist/services/traces/spansToTrajectory.d.ts +36 -0
- package/lib/dist/services/traces/spansToTrajectory.d.ts.map +1 -0
- package/lib/dist/services/traces/spansToTrajectory.js +387 -0
- package/lib/dist/services/traces/spansToTrajectory.js.map +1 -0
- package/lib/dist/services/traces/toolSimilarity.d.ts +35 -0
- package/lib/dist/services/traces/toolSimilarity.d.ts.map +1 -0
- package/lib/dist/services/traces/toolSimilarity.js +203 -0
- package/lib/dist/services/traces/toolSimilarity.js.map +1 -0
- package/lib/dist/services/traces/traceComparison.d.ts +31 -0
- package/lib/dist/services/traces/traceComparison.d.ts.map +1 -0
- package/lib/dist/services/traces/traceComparison.js +318 -0
- package/lib/dist/services/traces/traceComparison.js.map +1 -0
- package/lib/dist/services/traces/traceGrouping.d.ts +19 -0
- package/lib/dist/services/traces/traceGrouping.d.ts.map +1 -0
- package/lib/dist/services/traces/traceGrouping.js +107 -0
- package/lib/dist/services/traces/traceGrouping.js.map +1 -0
- package/lib/dist/services/traces/tracePoller.d.ts +84 -0
- package/lib/dist/services/traces/tracePoller.d.ts.map +1 -0
- package/lib/dist/services/traces/tracePoller.js +309 -0
- package/lib/dist/services/traces/tracePoller.js.map +1 -0
- package/lib/dist/services/traces/traceStats.d.ts +45 -0
- package/lib/dist/services/traces/traceStats.d.ts.map +1 -0
- package/lib/dist/services/traces/traceStats.js +114 -0
- package/lib/dist/services/traces/traceStats.js.map +1 -0
- package/lib/dist/services/traces/traceSummary.d.ts +47 -0
- package/lib/dist/services/traces/traceSummary.d.ts.map +1 -0
- package/lib/dist/services/traces/traceSummary.js +68 -0
- package/lib/dist/services/traces/traceSummary.js.map +1 -0
- package/lib/dist/services/traces/utils.d.ts +33 -0
- package/lib/dist/services/traces/utils.d.ts.map +1 -0
- package/lib/dist/services/traces/utils.js +114 -0
- package/lib/dist/services/traces/utils.js.map +1 -0
- package/lib/dist/types/agui.d.ts +13 -0
- package/lib/dist/types/agui.d.ts.map +1 -0
- package/lib/dist/types/agui.js +16 -0
- package/lib/dist/types/agui.js.map +1 -0
- package/lib/dist/types/index.d.ts +1175 -0
- package/lib/dist/types/index.d.ts.map +1 -0
- package/lib/dist/types/index.js +12 -0
- package/lib/dist/types/index.js.map +1 -0
- package/lib/dist/types/skills.d.ts +146 -0
- package/lib/dist/types/skills.d.ts.map +1 -0
- package/lib/dist/types/skills.js +6 -0
- package/lib/dist/types/skills.js.map +1 -0
- package/observio-sample-agent/pi-package/README.md +112 -0
- package/observio-sample-agent/pi-package/extensions/agent-health.ts +373 -0
- package/observio-sample-agent/pi-package/package.json +17 -0
- package/observio-sample-agent/pi-package/prompts/agent-health.md +37 -0
- package/observio-sample-agent/pi-package/skills/create-pr/SKILL.md +88 -0
- package/observio-sample-agent/pi-package/skills/fix-bug/SKILL.md +71 -0
- package/observio-sample-agent/pi-package/skills/implement-feature/SKILL.md +156 -0
- package/observio-sample-agent/pi-package/skills/instrument-otel/SKILL.md +208 -0
- package/observio-sample-agent/pi-package/skills/setup-collector/SKILL.md +146 -0
- package/observio-sample-agent/pi-package/skills/write-test/SKILL.md +115 -0
- package/package.json +64 -13
- package/server/dist/app.js +32651 -17637
- package/server/dist/index.js +29875 -14638
- package/tsconfig.lib.json +71 -0
- package/dist/assets/index-EvPLSTAS.js +0 -267
- package/dist/assets/index-RXasQKUs.css +0 -1
- package/lib/dist/config/index.js +0 -404
- 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.
|