@agenthippo-ai/agenthippo 1.110.9 → 1.110.19
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/out/agentpack/types.js +2 -5
- package/out/analytics/dashboard/artifactManager.js +2 -439
- package/out/analytics/dashboard/fleetDisplayUtils.js +2 -162
- package/out/analytics/dashboard/fleetOrchestrator.js +3 -142
- package/out/analytics/dashboard/fleetRegistry.js +2 -79
- package/out/analytics/dashboard/fleetRowDefaults.js +2 -87
- package/out/analytics/dashboard/fleetScriptAdapter.js +2 -146
- package/out/analytics/dashboard/fleetTypes.js +2 -29
- package/out/analytics/dashboard/index.js +2 -17
- package/out/analytics/dashboard/indexingService.js +2 -422
- package/out/analytics/dashboard/localFleetAdapter.js +2 -222
- package/out/analytics/dashboard/performanceMonitor.js +5 -76
- package/out/analytics/dashboard/processManager.js +2 -209
- package/out/analytics/dashboard/provider.js +38 -3817
- package/out/analytics/dashboard/queryRunner.js +62 -750
- package/out/analytics/dashboard/scheduledFleetStorage.js +2 -241
- package/out/analytics/dashboard/sessionJsonlFleet.js +3 -204
- package/out/analytics/dashboard/teamViewDiscovery.js +2 -106
- package/out/analytics/dashboard/webview/panel.js +34 -2318
- package/out/analytics/dashboard/webview/runtime-bridge.js +2 -82
- package/out/analytics/lifecycle.js +2 -43
- package/out/analytics/service.js +8 -1277
- package/out/auth/authBaseUrl.js +2 -59
- package/out/auth/bootstrapApply.js +2 -71
- package/out/auth/brokerClient.js +2 -160
- package/out/auth/callbackUri.js +2 -59
- package/out/auth/githubStoreGate.js +2 -70
- package/out/auth/loopbackAuthServer.js +4 -159
- package/out/auth/onboardingPrompt.js +2 -112
- package/out/auth/pkce.js +2 -9
- package/out/auth/provider.js +2 -226
- package/out/auth/sessionStore.js +2 -156
- package/out/auth/signInFlow.js +2 -183
- package/out/cli/index.js +619 -551
- package/out/cli/run-custom-engine-runner.js +3 -318
- package/out/cli/vscode-shim.js +2 -86
- package/out/engines/factory.js +2 -45
- package/out/engines/types.js +2 -17
- package/out/examples/run-headless-repl.js +6 -286
- package/out/examples/run-headless.js +2 -187
- package/out/extension.js +32 -4473
- package/out/gateway/gatewayRouteIndex.js +6 -371
- package/out/gateway/gatewaySessionStore.js +3 -243
- package/out/gateway/index.js +2 -31
- package/out/gateway/resetMappings.js +2 -52
- package/out/gateway/service.js +5 -1249
- package/out/mcp/publish.js +2 -143
- package/out/remote/handleRemoteChat.js +2 -169
- package/out/remote/remotePackStatusBar.js +3 -103
- package/out/remote/remoteTrust.js +6 -277
- package/out/remote/serveClient.js +4 -277
- package/out/remoteSkills.js +3 -191
- package/out/runtime/index.js +2 -32
- package/out/runtime/vscode/index.js +2 -20
- package/out/runtime/vscode/vscode-config-provider.js +2 -77
- package/out/runtime/vscode/vscode-edit-tracker.js +2 -122
- package/out/runtime/vscode/vscode-logger.js +2 -30
- package/out/runtime/vscode/vscode-permission-handler.js +2 -72
- package/out/scripts/agentide-litellm.sh +0 -1
- package/out/scripts/agentide_litellm_hooks_v1.py +170 -418
- package/out/scripts/analytics/agent-fleet-widget.js +18 -257
- package/out/scripts/analytics/agentide-litellm-otel.config.yaml +4 -4
- package/out/scripts/analytics/duckdbLocator.js +2 -28
- package/out/scripts/analytics/generate-default-charts.py +43 -323
- package/out/scripts/analytics/hotspot-analysis-widget.js +4 -430
- package/out/scripts/analytics/index-traces.py +78 -1036
- package/out/scripts/analytics/session-comparison-widget.js +26 -472
- package/out/scripts/analytics/session-timeline-widget.js +25 -846
- package/out/scripts/analytics/setup-analytics.ps1 +8 -1
- package/out/scripts/analytics/setup-analytics.sh +13 -2
- package/out/scripts/analytics/token-cost-flamegraph-widget.js +4 -461
- package/out/scripts/analytics/token-cost-trend-widget.js +4 -534
- package/out/scripts/analytics/workflows-collector.cjs +4 -314
- package/out/scripts/analytics/workflows-daemon.mjs +9 -185
- package/out/scripts/analytics/workflows-widget.cjs +15 -159
- package/out/scripts/analytics/wow-model-widget.js +10 -120
- package/out/scripts/vendor-tools.mjs +2 -233
- package/out/skills/publish.js +3 -178
- package/out/store/github/setup.js +7 -212
- package/out/store/oramaIndex.js +2 -884
- package/out/sync.js +26 -1829
- package/out/terminalLogger.js +5 -358
- package/out/utils/pathSafety.js +2 -60
- package/out/utils/pythonRunner.js +4 -258
- package/out/utils/toolPath.js +2 -83
- package/out/workspaceFolders.js +2 -59
- package/package.json +1 -1
- package/out/agentpack/github.js +0 -547
- package/out/agentpack/index.js +0 -67
- package/out/agentpack/install.js +0 -297
- package/out/agentpack/manager.js +0 -441
- package/out/agentpack/manifest.js +0 -135
- package/out/agentpack/paths.js +0 -498
- package/out/agentpack/publish.js +0 -248
- package/out/agentpack/stores.js +0 -554
- package/out/analytics/dashboard/fleetStatusUtils.js +0 -30
- package/out/analytics/dashboard/fleetTitleUtils.js +0 -68
- package/out/analytics/dashboard/refreshPolicy.js +0 -16
- package/out/analytics/dashboard/scheduledFleetFingerprint.js +0 -22
- package/out/analytics/dashboard/scheduledFleetUtils.js +0 -22
- package/out/analytics/dashboard/sessionEventFleetStats.js +0 -118
- package/out/analytics/dashboard/viewsConfigMerge.js +0 -221
- package/out/analytics/dashboard/webview/codicon.ttf +0 -0
- package/out/analytics/identity.js +0 -0
- package/out/analytics/sessionEvents.js +0 -323
- package/out/auth/callbackUriParse.js +0 -59
- package/out/auth/types.js +0 -12
- package/out/auth-broker/config.js +0 -112
- package/out/auth-broker/jwt.js +0 -105
- package/out/auth-broker/pkce.js +0 -59
- package/out/auth-broker/server.js +0 -677
- package/out/auth-broker/store.js +0 -275
- package/out/authority/warrant.js +0 -206
- package/out/base-prompts/mcp-servers/.mcp.json +0 -13
- package/out/base-prompts/mcp-servers/langfuse-analytics/README.md +0 -142
- package/out/base-prompts/mcp-servers/langfuse-analytics/mcp.json +0 -13
- package/out/base-prompts/mcp-servers/langfuse-analytics/package-lock.json +0 -1192
- package/out/base-prompts/mcp-servers/langfuse-analytics/package.json +0 -23
- package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/run-with-env.sh +0 -12
- package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/sdk-test.js +0 -102
- package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/simple-test.js +0 -137
- package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/test-client.js +0 -118
- package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/test-server.js +0 -209
- package/out/base-prompts/mcp-servers/langfuse-analytics/src/client.ts +0 -431
- package/out/base-prompts/mcp-servers/langfuse-analytics/src/index.ts +0 -270
- package/out/base-prompts/mcp-servers/langfuse-analytics/tsconfig.json +0 -18
- package/out/base-prompts/rules/AGENTS.md +0 -204
- package/out/base-prompts/skills/agent-browser/SKILL.md +0 -102
- package/out/base-prompts/skills/agent-builder/SKILL.md +0 -73
- package/out/base-prompts/skills/agent-builder/references/agent-pack.md +0 -63
- package/out/base-prompts/skills/agent-builder/references/crewai.md +0 -66
- package/out/base-prompts/skills/agent-builder/references/langchain.md +0 -60
- package/out/base-prompts/skills/agent-builder/references/raw-sdk.md +0 -73
- package/out/base-prompts/skills/agent-engine-creator/SKILL.md +0 -586
- package/out/base-prompts/skills/agent-engine-installer/SKILL.md +0 -106
- package/out/base-prompts/skills/agent-engine-installer/scripts/install-engine.mjs +0 -259
- package/out/base-prompts/skills/agent-engine-installer/scripts/install-engine.ps1 +0 -189
- package/out/base-prompts/skills/agenthippo-cli/SKILL.md +0 -69
- package/out/base-prompts/skills/agenthippo-cli/scripts/install.sh +0 -63
- package/out/base-prompts/skills/agentpack-creator/SKILL.md +0 -375
- package/out/base-prompts/skills/agentpack-creator/references/agent-templates.md +0 -261
- package/out/base-prompts/skills/agentpack-creator/references/agents-md-guide.md +0 -195
- package/out/base-prompts/skills/agentpack-creator/scripts/init_pack.py +0 -391
- package/out/base-prompts/skills/agentpack-creator/scripts/init_pack_test.py +0 -294
- package/out/base-prompts/skills/agentpack-testbench/SKILL.md +0 -135
- package/out/base-prompts/skills/algorithmic-art/LICENSE.txt +0 -202
- package/out/base-prompts/skills/algorithmic-art/SKILL.md +0 -405
- package/out/base-prompts/skills/algorithmic-art/templates/generator_template.js +0 -223
- package/out/base-prompts/skills/algorithmic-art/templates/viewer.html +0 -599
- package/out/base-prompts/skills/debug-agent/SKILL.md +0 -83
- package/out/base-prompts/skills/desktop-automation/SKILL.md +0 -166
- package/out/base-prompts/skills/desktop-automation/references/agenthippo-ui-recipes.md +0 -441
- package/out/base-prompts/skills/desktop-automation/scripts/windows-desktop-uia.psm1 +0 -280
- package/out/base-prompts/skills/docx/LICENSE.txt +0 -30
- package/out/base-prompts/skills/docx/SKILL.md +0 -197
- package/out/base-prompts/skills/docx/docx-js.md +0 -350
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
- package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
- package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
- package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
- package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
- package/out/base-prompts/skills/docx/ooxml/schemas/mce/mc.xsd +0 -75
- package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
- package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
- package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
- package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
- package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
- package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
- package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
- package/out/base-prompts/skills/docx/ooxml/scripts/pack.py +0 -159
- package/out/base-prompts/skills/docx/ooxml/scripts/unpack.py +0 -29
- package/out/base-prompts/skills/docx/ooxml/scripts/validate.py +0 -69
- package/out/base-prompts/skills/docx/ooxml/scripts/validation/__init__.py +0 -15
- package/out/base-prompts/skills/docx/ooxml/scripts/validation/base.py +0 -951
- package/out/base-prompts/skills/docx/ooxml/scripts/validation/docx.py +0 -274
- package/out/base-prompts/skills/docx/ooxml/scripts/validation/pptx.py +0 -315
- package/out/base-prompts/skills/docx/ooxml/scripts/validation/redlining.py +0 -279
- package/out/base-prompts/skills/docx/ooxml.md +0 -610
- package/out/base-prompts/skills/docx/scripts/__init__.py +0 -1
- package/out/base-prompts/skills/docx/scripts/document.py +0 -1276
- package/out/base-prompts/skills/docx/scripts/templates/comments.xml +0 -3
- package/out/base-prompts/skills/docx/scripts/templates/commentsExtended.xml +0 -3
- package/out/base-prompts/skills/docx/scripts/templates/commentsExtensible.xml +0 -3
- package/out/base-prompts/skills/docx/scripts/templates/commentsIds.xml +0 -3
- package/out/base-prompts/skills/docx/scripts/templates/people.xml +0 -3
- package/out/base-prompts/skills/docx/scripts/utilities.py +0 -374
- package/out/base-prompts/skills/gateway-outbound/SKILL.md +0 -136
- package/out/base-prompts/skills/mcp-builder/LICENSE.txt +0 -202
- package/out/base-prompts/skills/mcp-builder/SKILL.md +0 -328
- package/out/base-prompts/skills/mcp-builder/reference/evaluation.md +0 -602
- package/out/base-prompts/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
- package/out/base-prompts/skills/mcp-builder/reference/node_mcp_server.md +0 -970
- package/out/base-prompts/skills/mcp-builder/reference/python_mcp_server.md +0 -719
- package/out/base-prompts/skills/mcp-builder/scripts/connections.py +0 -151
- package/out/base-prompts/skills/mcp-builder/scripts/evaluation.py +0 -373
- package/out/base-prompts/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
- package/out/base-prompts/skills/mcp-builder/scripts/requirements.txt +0 -2
- package/out/base-prompts/skills/openclaw/SKILL.md +0 -406
- package/out/base-prompts/skills/openclaw/scripts/run-smoke.sh +0 -61
- package/out/base-prompts/skills/pdf/LICENSE.txt +0 -30
- package/out/base-prompts/skills/pdf/SKILL.md +0 -294
- package/out/base-prompts/skills/pdf/forms.md +0 -205
- package/out/base-prompts/skills/pdf/reference.md +0 -612
- package/out/base-prompts/skills/pdf/scripts/check_bounding_boxes.py +0 -70
- package/out/base-prompts/skills/pdf/scripts/check_bounding_boxes_test.py +0 -226
- package/out/base-prompts/skills/pdf/scripts/check_fillable_fields.py +0 -12
- package/out/base-prompts/skills/pdf/scripts/convert_pdf_to_images.py +0 -35
- package/out/base-prompts/skills/pdf/scripts/create_validation_image.py +0 -41
- package/out/base-prompts/skills/pdf/scripts/extract_form_field_info.py +0 -152
- package/out/base-prompts/skills/pdf/scripts/fill_fillable_fields.py +0 -114
- package/out/base-prompts/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -108
- package/out/base-prompts/skills/pptx/LICENSE.txt +0 -30
- package/out/base-prompts/skills/pptx/SKILL.md +0 -484
- package/out/base-prompts/skills/pptx/html2pptx.md +0 -625
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
- package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
- package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
- package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
- package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
- package/out/base-prompts/skills/pptx/ooxml/schemas/mce/mc.xsd +0 -75
- package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
- package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
- package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
- package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
- package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
- package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
- package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
- package/out/base-prompts/skills/pptx/ooxml/scripts/pack.py +0 -159
- package/out/base-prompts/skills/pptx/ooxml/scripts/unpack.py +0 -29
- package/out/base-prompts/skills/pptx/ooxml/scripts/validate.py +0 -69
- package/out/base-prompts/skills/pptx/ooxml/scripts/validation/__init__.py +0 -15
- package/out/base-prompts/skills/pptx/ooxml/scripts/validation/base.py +0 -951
- package/out/base-prompts/skills/pptx/ooxml/scripts/validation/docx.py +0 -274
- package/out/base-prompts/skills/pptx/ooxml/scripts/validation/pptx.py +0 -315
- package/out/base-prompts/skills/pptx/ooxml/scripts/validation/redlining.py +0 -279
- package/out/base-prompts/skills/pptx/ooxml.md +0 -427
- package/out/base-prompts/skills/pptx/scripts/html2pptx.js +0 -984
- package/out/base-prompts/skills/pptx/scripts/inventory.py +0 -1020
- package/out/base-prompts/skills/pptx/scripts/rearrange.py +0 -231
- package/out/base-prompts/skills/pptx/scripts/replace.py +0 -385
- package/out/base-prompts/skills/pptx/scripts/thumbnail.py +0 -450
- package/out/base-prompts/skills/prompt-lab/SKILL.md +0 -149
- package/out/base-prompts/skills/prompt-lab/scripts/query-analytics.sh +0 -2551
- package/out/base-prompts/skills/skill-creator/LICENSE.txt +0 -202
- package/out/base-prompts/skills/skill-creator/SKILL.md +0 -371
- package/out/base-prompts/skills/skill-creator/references/output-patterns.md +0 -82
- package/out/base-prompts/skills/skill-creator/references/workflows.md +0 -28
- package/out/base-prompts/skills/skill-creator/scripts/init_skill.py +0 -303
- package/out/base-prompts/skills/skill-creator/scripts/package_skill.py +0 -110
- package/out/base-prompts/skills/skill-creator/scripts/quick_validate.py +0 -95
- package/out/base-prompts/skills/skill-installer/SKILL.md +0 -251
- package/out/base-prompts/skills/skill-installer/references/store-api.md +0 -219
- package/out/base-prompts/skills/spotlight-dashboard/SKILL.md +0 -83
- package/out/base-prompts/skills/spotlight-insights/SKILL.md +0 -101
- package/out/base-prompts/skills/spotlight-optimize/SKILL.md +0 -93
- package/out/base-prompts/skills/spotlight-optimize/scripts/query-analytics.sh +0 -2551
- package/out/base-prompts/skills/spotlight-query/SKILL.md +0 -314
- package/out/base-prompts/skills/spotlight-query/references/otel-schema.md +0 -163
- package/out/base-prompts/skills/spotlight-query/scripts/query-analytics.sh +0 -2551
- package/out/base-prompts/skills/spotlight-query/scripts/query-analytics.test.sh +0 -744
- package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/sessions/sess-test-1.jsonl +0 -14
- package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/traces/.duckdb-index.json +0 -7
- package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/traces/sample.jsonl +0 -5
- package/out/base-prompts/skills/spotlight-report/SKILL.md +0 -86
- package/out/base-prompts/skills/spotlight-visualize/SKILL.md +0 -92
- package/out/base-prompts/skills/spotlight-visualize/scripts/query-analytics.sh +0 -2551
- package/out/base-prompts/skills/xlsx/LICENSE.txt +0 -30
- package/out/base-prompts/skills/xlsx/SKILL.md +0 -289
- package/out/base-prompts/skills/xlsx/recalc.py +0 -178
- package/out/branding.js +0 -49
- package/out/cli/commands/anywhere.js +0 -66
- package/out/cli/commands/ask.js +0 -246
- package/out/cli/commands/auth-broker.js +0 -24
- package/out/cli/commands/auth.js +0 -219
- package/out/cli/commands/chat.js +0 -357
- package/out/cli/commands/conformance.js +0 -249
- package/out/cli/commands/data-plane.js +0 -67
- package/out/cli/commands/deploy.js +0 -263
- package/out/cli/commands/gateway.js +0 -218
- package/out/cli/commands/idp.js +0 -85
- package/out/cli/commands/pack.js +0 -399
- package/out/cli/commands/probe-custom-engine.js +0 -82
- package/out/cli/commands/sandbox.js +0 -332
- package/out/cli/commands/serve.js +0 -1758
- package/out/cli/commands/store.js +0 -927
- package/out/cli/credential-context.js +0 -91
- package/out/cli/data-plane/broker.js +0 -78
- package/out/cli/data-plane/connector-host.js +0 -121
- package/out/cli/data-plane/egress.js +0 -189
- package/out/cli/data-plane/gateway.js +0 -218
- package/out/cli/data-plane/index.js +0 -152
- package/out/cli/data-plane/registry.js +0 -89
- package/out/cli/data-plane/remote.js +0 -106
- package/out/cli/data-plane/sidecar.js +0 -161
- package/out/cli/deploy/blueprints/registry.js +0 -84
- package/out/cli/deploy/layers/identity.js +0 -172
- package/out/cli/deploy-init.js +0 -3023
- package/out/cli/deps.js +0 -342
- package/out/cli/idp-init.js +0 -338
- package/out/cli/pack-install-ref.js +0 -15
- package/out/cli/pack-loader.js +0 -418
- package/out/cli/pack-runtime.js +0 -61
- package/out/cli/runtime.js +0 -450
- package/out/cli/serve-hardening.js +0 -607
- package/out/cli/state-sync.js +0 -424
- package/out/cli/utils.js +0 -231
- package/out/engines/base.js +0 -188
- package/out/engines/claude.js +0 -1254
- package/out/engines/codex.js +0 -862
- package/out/engines/custom.js +0 -674
- package/out/engines/customEngineIpc.js +0 -95
- package/out/engines/customEngineRunnerEmbed.js +0 -107
- package/out/engines/customRegistry.js +0 -274
- package/out/engines/embeddedCustomEngineRunner.generated.js +0 -9
- package/out/engines/engineApiKey.js +0 -138
- package/out/engines/install.js +0 -372
- package/out/engines/persistentEngineWorker.js +0 -320
- package/out/engines/publish.js +0 -341
- package/out/evidence/sessionShip.js +0 -610
- package/out/gateway/bridge.js +0 -843
- package/out/gateway/cli-agent-id.js +0 -36
- package/out/gateway/client.js +0 -336
- package/out/gateway/client.test.js +0 -395
- package/out/gateway/gateway-scope-errors.js +0 -14
- package/out/gateway/gatewayBackup.js +0 -76
- package/out/gateway/installSource.js +0 -68
- package/out/gateway/lifecycle.js +0 -3190
- package/out/gateway/openclaw-channel-routing.js +0 -317
- package/out/gateway/outboundHandles.js +0 -373
- package/out/gateway/outboundPaths.js +0 -75
- package/out/gateway/outboundSend.js +0 -254
- package/out/gateway/protocol.js +0 -48
- package/out/gateway/secretsPreflight.js +0 -90
- package/out/gateway/sessionRouting.js +0 -77
- package/out/headless/index.js +0 -539
- package/out/headless/sync.js +0 -473
- package/out/live-e2e/mcp-demo/server.mjs +0 -32
- package/out/live-probe/connector.mjs +0 -8
- package/out/live-probe/env-report.mjs +0 -8
- package/out/mcp.js +0 -654
- package/out/pack/caps.js +0 -271
- package/out/pack/governor.js +0 -309
- package/out/pack/lease-schema.js +0 -270
- package/out/pack/lease.js +0 -640
- package/out/pack/reconcile.js +0 -217
- package/out/pack/signature.js +0 -839
- package/out/permissions.js +0 -108
- package/out/permissions.mapping.yaml +0 -68
- package/out/registry/index.js +0 -332
- package/out/runner/host.js +0 -131
- package/out/runner/protocol.js +0 -108
- package/out/runner/remoteEngine.js +0 -130
- package/out/runtime/interfaces/config-provider.js +0 -32
- package/out/runtime/interfaces/edit-tracker.js +0 -24
- package/out/runtime/interfaces/index.js +0 -29
- package/out/runtime/interfaces/logger.js +0 -40
- package/out/runtime/interfaces/permission-handler.js +0 -66
- package/out/runtime/interfaces/session-store.js +0 -342
- package/out/runtime/vscode/vscode-session-store.js +0 -22
- package/out/sandbox/containerDriver.js +0 -570
- package/out/sandbox/processDriver.js +0 -315
- package/out/sandbox/sandboxRunner.js +0 -191
- package/out/sandbox/support.js +0 -301
- package/out/sandbox/types.js +0 -55
- package/out/scripts/analytics/fleet-local-adapter.js +0 -246
- package/out/scripts/analytics/live-fleet-4-collector.cjs +0 -315
- package/out/scripts/analytics/live-fleet-4-daemon.mjs +0 -134
- package/out/scripts/analytics/live-fleet-4-widget.cjs +0 -433
- package/out/scripts/gateway/Dockerfile.serve +0 -45
- package/out/scripts/gateway/docker-serve.sh +0 -248
- package/out/scripts/gateway/setup-gateway-server.ps1 +0 -953
- package/out/scripts/gateway/setup-gateway-server.sh +0 -935
- package/out/session.js +0 -272
- package/out/shared/agentEngines.js +0 -170
- package/out/shared/index.js +0 -109
- package/out/shared/models.js +0 -136
- package/out/shared/providers.js +0 -205
- package/out/spotlight/install.js +0 -345
- package/out/spotlight/publish.js +0 -544
- package/out/spotlight/yaml.js +0 -31
- package/out/store/index.js +0 -786
- package/out/store/shared.js +0 -241
- package/out/test/agentEnvFile.test.js +0 -97
- package/out/test/agentYaml.test.js +0 -373
- package/out/test/agentpack.test.js +0 -639
- package/out/test/analytics-lifecycle.test.js +0 -174
- package/out/test/analytics.test.js +0 -756
- package/out/test/auth-baseurl.test.js +0 -132
- package/out/test/auth-bootstrapApply.test.js +0 -123
- package/out/test/auth-broker-hardening.test.js +0 -227
- package/out/test/auth-broker.test.js +0 -541
- package/out/test/auth-callback.test.js +0 -62
- package/out/test/blueprint-registry.test.js +0 -105
- package/out/test/branding.test.js +0 -242
- package/out/test/caps-governor.test.js +0 -455
- package/out/test/cli-agent-id.test.js +0 -55
- package/out/test/codex-new-file-survival.test.js +0 -119
- package/out/test/configuration-scopes.test.js +0 -131
- package/out/test/credential-context.test.js +0 -160
- package/out/test/custom-env-layering.test.js +0 -151
- package/out/test/customEngineInstall.test.js +0 -100
- package/out/test/customRegistry.test.js +0 -122
- package/out/test/data-plane-engine-wiring.test.js +0 -250
- package/out/test/data-plane.test.js +0 -311
- package/out/test/deploy-init.test.js +0 -854
- package/out/test/deps-auto-install.test.js +0 -81
- package/out/test/egress-broker.test.js +0 -172
- package/out/test/engine-integration.test.js +0 -297
- package/out/test/enginePaths.test.js +0 -195
- package/out/test/enginePublish.test.js +0 -82
- package/out/test/fleetDisplayUtils.test.js +0 -100
- package/out/test/gateway-client.test.js +0 -409
- package/out/test/gateway-install-source.test.js +0 -111
- package/out/test/gateway-lifecycle.test.js +0 -608
- package/out/test/gateway-outbound.test.js +0 -538
- package/out/test/gateway-reset-mappings.test.js +0 -221
- package/out/test/gateway-route-index.test.js +0 -235
- package/out/test/gateway-secrets-preflight.test.js +0 -127
- package/out/test/gateway-session-routing.test.js +0 -65
- package/out/test/gateway-session-store.test.js +0 -216
- package/out/test/github.test.js +0 -232
- package/out/test/governor-hardening.test.js +0 -217
- package/out/test/headless-sync.test.js +0 -301
- package/out/test/helpers/manifest-fixtures.js +0 -27
- package/out/test/idp-init.test.js +0 -151
- package/out/test/lease-signature.test.js +0 -357
- package/out/test/lease-trust-root.test.js +0 -273
- package/out/test/lease-validation.test.js +0 -169
- package/out/test/lease.test.js +0 -114
- package/out/test/mcp-obo.test.js +0 -107
- package/out/test/mcp.test.js +0 -389
- package/out/test/model-routing.test.js +0 -133
- package/out/test/openclaw-channel-routing.test.js +0 -191
- package/out/test/pack-admission.test.js +0 -216
- package/out/test/pack-digest-parity.test.js +0 -140
- package/out/test/pack-reconcile.test.js +0 -183
- package/out/test/pack-signature-artifact.test.js +0 -103
- package/out/test/pack-signature.test.js +0 -176
- package/out/test/pack-trust-root.test.js +0 -202
- package/out/test/pathSafety.test.js +0 -63
- package/out/test/permissions.test.js +0 -175
- package/out/test/persistent-engine-worker.test.js +0 -220
- package/out/test/refreshPolicy.test.js +0 -60
- package/out/test/registry.test.js +0 -351
- package/out/test/remote-trust.test.js +0 -242
- package/out/test/runner-protocol.test.js +0 -249
- package/out/test/runtime.test.js +0 -349
- package/out/test/sandbox-driver.test.js +0 -553
- package/out/test/sandbox-hardening.test.js +0 -395
- package/out/test/sandbox-runner.test.js +0 -343
- package/out/test/scheduledFleetStorage.test.js +0 -72
- package/out/test/serve-gateway-turn.test.js +0 -267
- package/out/test/serve-hardening.test.js +0 -418
- package/out/test/serveClient.test.js +0 -209
- package/out/test/sessionJsonlFleet.test.js +0 -78
- package/out/test/sessionShip.test.js +0 -560
- package/out/test/shared.test.js +0 -173
- package/out/test/skills-mcp.test.js +0 -299
- package/out/test/spotlightPublish.test.js +0 -327
- package/out/test/spotlightYaml.test.js +0 -58
- package/out/test/state-sync-peer.test.js +0 -156
- package/out/test/store-install-safe.test.js +0 -69
- package/out/test/store.test.js +0 -331
- package/out/test/stores.test.js +0 -504
- package/out/test/sync-switch.test.js +0 -251
- package/out/test/teamViewDiscovery.test.js +0 -90
- package/out/test/tls-bypass.test.js +0 -90
- package/out/test/toolPath.test.js +0 -120
- package/out/test/utils.test.js +0 -308
- package/out/test/viewsConfigMerge.test.js +0 -180
- package/out/test/warrant.test.js +0 -138
- package/out/test/windows-command-line.test.js +0 -75
- package/out/utils/agentEnvFile.js +0 -131
- package/out/utils/binary.js +0 -175
- package/out/utils/index.js +0 -37
- package/out/utils/network.js +0 -74
- package/out/utils/paths.js +0 -116
- package/out/utils/pid.js +0 -180
- package/out/utils/resolveNodeBinary.js +0 -168
- package/out/utils/windowsCommandLine.js +0 -29
- package/out/utils.js +0 -968
|
@@ -1,53 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
#
|
|
3
|
-
"""
|
|
4
|
-
Generate default analytics dashboard charts from OTEL trace data.
|
|
5
|
-
|
|
6
|
-
Usage:
|
|
7
|
-
uv run --with matplotlib python3 generate-default-charts.py <traces_dir> <output_dir>
|
|
8
|
-
uv run --with matplotlib python3 generate-default-charts.py
|
|
9
|
-
|
|
10
|
-
Reads DuckDB JSON output from stdin (piped from query script) or queries directly.
|
|
11
|
-
Outputs PNG charts to <output_dir>/charts/.
|
|
12
|
-
|
|
13
|
-
Exit codes:
|
|
14
|
-
0 = charts generated
|
|
15
|
-
1 = error
|
|
16
|
-
2 = no data available
|
|
17
|
-
"""
|
|
18
|
-
|
|
1
|
+
# Copyright (c) 2026 AgentHippo.ai. All rights reserved.
|
|
2
|
+
# Proprietary and confidential. See LICENSE.
|
|
19
3
|
import json
|
|
20
4
|
import os
|
|
21
5
|
import sys
|
|
22
6
|
from pathlib import Path
|
|
23
7
|
from datetime import datetime
|
|
24
|
-
|
|
25
8
|
try:
|
|
26
9
|
import duckdb as _duckdb_module
|
|
27
10
|
DUCKDB_AVAILABLE = True
|
|
28
11
|
except ImportError:
|
|
29
12
|
DUCKDB_AVAILABLE = False
|
|
30
|
-
|
|
31
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
32
|
-
# Config
|
|
33
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
34
|
-
|
|
35
13
|
CHART_WIDTH = 8
|
|
36
14
|
CHART_HEIGHT = 4.5
|
|
37
15
|
DPI = 150
|
|
38
|
-
|
|
39
|
-
# VS Code-friendly dark theme colors
|
|
40
16
|
BG_COLOR = '#1e1e1e'
|
|
41
17
|
FG_COLOR = '#cccccc'
|
|
42
18
|
GRID_COLOR = '#333333'
|
|
43
19
|
ACCENT_COLORS = ['#569cd6', '#4ec9b0', '#ce9178', '#dcdcaa', '#c586c0', '#9cdcfe', '#d4d4d4']
|
|
44
20
|
|
|
45
21
|
def parse_disabled_charts():
|
|
46
|
-
"""Read disabled chart filenames from AGENTIDE_DISABLED_CHARTS."""
|
|
47
22
|
raw = (os.environ.get('AGENTIDE_DISABLED_CHARTS') or '').strip()
|
|
48
23
|
if not raw:
|
|
49
24
|
return set()
|
|
50
|
-
|
|
51
25
|
disabled = set()
|
|
52
26
|
if raw.startswith('['):
|
|
53
27
|
try:
|
|
@@ -59,7 +33,6 @@ def parse_disabled_charts():
|
|
|
59
33
|
return disabled
|
|
60
34
|
except Exception:
|
|
61
35
|
pass
|
|
62
|
-
|
|
63
36
|
for part in raw.split(','):
|
|
64
37
|
name = part.strip()
|
|
65
38
|
if name:
|
|
@@ -79,7 +52,6 @@ def remove_chart_if_exists(output_dir, filename):
|
|
|
79
52
|
pass
|
|
80
53
|
|
|
81
54
|
def format_session_handle(session_id):
|
|
82
|
-
"""Generate a short, stable session handle from full session id."""
|
|
83
55
|
value = (session_id or '').strip()
|
|
84
56
|
if not value:
|
|
85
57
|
return 'S-UNKNOWN'
|
|
@@ -87,43 +59,13 @@ def format_session_handle(session_id):
|
|
|
87
59
|
return f'S-{first_segment[:8]}'
|
|
88
60
|
|
|
89
61
|
def setup_matplotlib():
|
|
90
|
-
"""Configure matplotlib for headless dark-theme charts."""
|
|
91
62
|
import matplotlib
|
|
92
63
|
matplotlib.use('Agg')
|
|
93
64
|
import matplotlib.pyplot as plt
|
|
94
|
-
|
|
95
|
-
plt.rcParams.update({
|
|
96
|
-
'figure.figsize': (CHART_WIDTH, CHART_HEIGHT),
|
|
97
|
-
'figure.dpi': DPI,
|
|
98
|
-
'figure.facecolor': BG_COLOR,
|
|
99
|
-
'axes.facecolor': BG_COLOR,
|
|
100
|
-
'axes.edgecolor': GRID_COLOR,
|
|
101
|
-
'axes.labelcolor': FG_COLOR,
|
|
102
|
-
'axes.titlesize': 13,
|
|
103
|
-
'axes.titleweight': 'bold',
|
|
104
|
-
'axes.titlepad': 14,
|
|
105
|
-
'axes.grid': True,
|
|
106
|
-
'grid.color': GRID_COLOR,
|
|
107
|
-
'grid.linewidth': 0.5,
|
|
108
|
-
'text.color': FG_COLOR,
|
|
109
|
-
'xtick.color': FG_COLOR,
|
|
110
|
-
'ytick.color': FG_COLOR,
|
|
111
|
-
'font.size': 10,
|
|
112
|
-
'font.family': 'sans-serif',
|
|
113
|
-
'legend.facecolor': BG_COLOR,
|
|
114
|
-
'legend.edgecolor': GRID_COLOR,
|
|
115
|
-
'legend.fontsize': 9,
|
|
116
|
-
'savefig.facecolor': BG_COLOR,
|
|
117
|
-
'savefig.edgecolor': BG_COLOR,
|
|
118
|
-
})
|
|
65
|
+
plt.rcParams.update({'figure.figsize': (CHART_WIDTH, CHART_HEIGHT), 'figure.dpi': DPI, 'figure.facecolor': BG_COLOR, 'axes.facecolor': BG_COLOR, 'axes.edgecolor': GRID_COLOR, 'axes.labelcolor': FG_COLOR, 'axes.titlesize': 13, 'axes.titleweight': 'bold', 'axes.titlepad': 14, 'axes.grid': True, 'grid.color': GRID_COLOR, 'grid.linewidth': 0.5, 'text.color': FG_COLOR, 'xtick.color': FG_COLOR, 'ytick.color': FG_COLOR, 'font.size': 10, 'font.family': 'sans-serif', 'legend.facecolor': BG_COLOR, 'legend.edgecolor': GRID_COLOR, 'legend.fontsize': 9, 'savefig.facecolor': BG_COLOR, 'savefig.edgecolor': BG_COLOR})
|
|
119
66
|
return plt
|
|
120
67
|
|
|
121
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
122
|
-
# DuckDB Queries
|
|
123
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
124
|
-
|
|
125
68
|
def run_query_conn(conn, sql):
|
|
126
|
-
"""Run a SQL query on an open DuckDB connection; return list of dicts."""
|
|
127
69
|
try:
|
|
128
70
|
rel = conn.execute(sql)
|
|
129
71
|
cols = [d[0] for d in rel.description]
|
|
@@ -132,125 +74,39 @@ def run_query_conn(conn, sql):
|
|
|
132
74
|
sys.stderr.write(f'[Dashboard] Query failed: {exc}\n')
|
|
133
75
|
return []
|
|
134
76
|
|
|
135
|
-
|
|
136
77
|
def open_duckdb_connection(traces_dir, use_indexed_db, index_db_path, trace_filter_clause):
|
|
137
|
-
"""
|
|
138
|
-
Open one DuckDB connection and materialise a `filtered_traces` temp table.
|
|
139
|
-
|
|
140
|
-
• indexed DB path → read-only connection to .duckdb file; uses pre-built spans table
|
|
141
|
-
• JSONL fallback → in-memory DB; parses JSONL *once* into a temp table
|
|
142
|
-
|
|
143
|
-
Always sets conservative memory / thread limits so multiple refreshes
|
|
144
|
-
can never compete for all available RAM.
|
|
145
|
-
Returns (conn, error_message). On failure conn is None.
|
|
146
|
-
"""
|
|
147
78
|
if not DUCKDB_AVAILABLE:
|
|
148
|
-
return None,
|
|
149
|
-
'duckdb Python module not found. '
|
|
150
|
-
'Add "duckdb" to your analytics requirements.txt or run: pip install duckdb'
|
|
151
|
-
)
|
|
152
|
-
|
|
79
|
+
return (None, 'duckdb Python module not found. Add "duckdb" to your analytics requirements.txt or run: pip install duckdb')
|
|
153
80
|
memory_limit_mb = max(64, int(os.environ.get('AGENTIDE_DUCKDB_MEMORY_LIMIT_MB', '256') or '256'))
|
|
154
81
|
threads = max(1, int(os.environ.get('AGENTIDE_DUCKDB_THREADS', '2') or '2'))
|
|
155
82
|
temp_directory_env = (os.environ.get('AGENTIDE_DUCKDB_TEMP_DIRECTORY') or '').strip()
|
|
156
|
-
|
|
157
83
|
conn = None
|
|
158
84
|
try:
|
|
159
85
|
if use_indexed_db and index_db_path and os.path.exists(index_db_path):
|
|
160
|
-
|
|
161
|
-
indexed_config = {
|
|
162
|
-
'threads': threads,
|
|
163
|
-
'memory_limit': f'{memory_limit_mb}MB',
|
|
164
|
-
}
|
|
86
|
+
indexed_config = {'threads': threads, 'memory_limit': f'{memory_limit_mb}MB'}
|
|
165
87
|
if temp_directory_env:
|
|
166
88
|
indexed_config['temp_directory'] = temp_directory_env
|
|
167
|
-
conn = _duckdb_module.connect(
|
|
168
|
-
|
|
169
|
-
config=indexed_config,
|
|
170
|
-
)
|
|
171
|
-
# spans table already normalised; just apply optional scope filters
|
|
172
|
-
conn.execute(
|
|
173
|
-
f"CREATE TEMP VIEW filtered_traces AS "
|
|
174
|
-
f"SELECT * FROM spans {trace_filter_clause}"
|
|
175
|
-
)
|
|
89
|
+
conn = _duckdb_module.connect(index_db_path, read_only=True, config=indexed_config)
|
|
90
|
+
conn.execute(f'CREATE TEMP VIEW filtered_traces AS SELECT * FROM spans {trace_filter_clause}')
|
|
176
91
|
sys.stderr.write(f'[Dashboard] Using indexed DuckDB: {index_db_path}\n')
|
|
177
92
|
else:
|
|
178
|
-
# ── JSONL fallback: in-memory DB with streaming reads ──────────
|
|
179
|
-
# Use a VIEW so DuckDB streams JSONL per query instead of
|
|
180
|
-
# materialising all 228 MB into the buffer pool at once.
|
|
181
|
-
# Spill-to-disk ensures complex unnesting never hard-OOMs.
|
|
182
93
|
import tempfile, os as _os
|
|
183
94
|
_spill_dir = temp_directory_env or _os.path.join(tempfile.gettempdir(), 'duckdb_spotlight_spill')
|
|
184
95
|
_os.makedirs(_spill_dir, exist_ok=True)
|
|
185
|
-
conn = _duckdb_module.connect(
|
|
186
|
-
|
|
187
|
-
config={
|
|
188
|
-
'threads': threads,
|
|
189
|
-
'memory_limit': f'{memory_limit_mb}MB',
|
|
190
|
-
'temp_directory': _spill_dir,
|
|
191
|
-
'preserve_insertion_order': False,
|
|
192
|
-
},
|
|
193
|
-
)
|
|
194
|
-
conn.execute(
|
|
195
|
-
f"CREATE TEMP VIEW filtered_traces AS "
|
|
196
|
-
f"{base_query(traces_dir)}, "
|
|
197
|
-
f"filtered AS (SELECT * FROM traces {trace_filter_clause}) "
|
|
198
|
-
f"SELECT * FROM filtered"
|
|
199
|
-
)
|
|
96
|
+
conn = _duckdb_module.connect(':memory:', config={'threads': threads, 'memory_limit': f'{memory_limit_mb}MB', 'temp_directory': _spill_dir, 'preserve_insertion_order': False})
|
|
97
|
+
conn.execute(f'CREATE TEMP VIEW filtered_traces AS {base_query(traces_dir)}, filtered AS (SELECT * FROM traces {trace_filter_clause}) SELECT * FROM filtered')
|
|
200
98
|
sys.stderr.write(f'[Dashboard] Using JSONL streaming from {traces_dir}\n')
|
|
201
|
-
|
|
202
|
-
return conn, None
|
|
99
|
+
return (conn, None)
|
|
203
100
|
except Exception as exc:
|
|
204
101
|
if conn:
|
|
205
102
|
try:
|
|
206
103
|
conn.close()
|
|
207
104
|
except Exception:
|
|
208
105
|
pass
|
|
209
|
-
return None, f'DuckDB connection failed: {exc}'
|
|
106
|
+
return (None, f'DuckDB connection failed: {exc}')
|
|
210
107
|
|
|
211
108
|
def base_query(traces_dir):
|
|
212
|
-
"
|
|
213
|
-
return f"""
|
|
214
|
-
WITH raw_spans AS (
|
|
215
|
-
SELECT unnest(resourceSpans) as rs
|
|
216
|
-
FROM read_json('{traces_dir}/*.jsonl', format='newline_delimited', ignore_errors=true)
|
|
217
|
-
),
|
|
218
|
-
spans AS (SELECT unnest(rs.scopeSpans) as ss FROM raw_spans),
|
|
219
|
-
flat_spans AS (SELECT unnest(ss.spans) as span FROM spans),
|
|
220
|
-
parsed AS (
|
|
221
|
-
SELECT
|
|
222
|
-
span.traceId as trace_id,
|
|
223
|
-
span.name as span_name,
|
|
224
|
-
span.startTimeUnixNano::BIGINT / 1000000 as start_ms,
|
|
225
|
-
(span.endTimeUnixNano::BIGINT - span.startTimeUnixNano::BIGINT) / 1000000 as duration_ms,
|
|
226
|
-
json_extract(to_json(span), '$.attributes') as attrs_json
|
|
227
|
-
FROM flat_spans
|
|
228
|
-
),
|
|
229
|
-
attrs AS (
|
|
230
|
-
SELECT trace_id, span_name, duration_ms, start_ms,
|
|
231
|
-
json_extract_string(value, '$.key') as attr_key,
|
|
232
|
-
json_extract_string(value, '$.value.stringValue') as attr_string,
|
|
233
|
-
json_extract_string(value, '$.value.intValue') as attr_int,
|
|
234
|
-
json_extract(value, '$.value.doubleValue') as attr_double
|
|
235
|
-
FROM parsed, json_each(coalesce(attrs_json, '[]'::JSON))
|
|
236
|
-
WHERE span_name = 'Received Proxy Server Request'
|
|
237
|
-
OR EXISTS (SELECT 1 FROM json_each(coalesce(attrs_json, '[]'::JSON)) as attr
|
|
238
|
-
WHERE json_extract_string(attr.value, '$.key') = 'gen_ai.cost.total_cost')
|
|
239
|
-
),
|
|
240
|
-
traces AS (
|
|
241
|
-
SELECT
|
|
242
|
-
trace_id, span_name, duration_ms, start_ms,
|
|
243
|
-
max(CASE WHEN attr_key IN ('gen_ai.request.model','gen_ai.response.model','model') THEN attr_string END) as model,
|
|
244
|
-
max(CASE WHEN attr_key = 'gen_ai.cost.total_cost' THEN CAST(attr_double AS DOUBLE) END) as cost,
|
|
245
|
-
max(CASE WHEN attr_key = 'gen_ai.usage.input_tokens' THEN CAST(attr_int AS BIGINT) END) as input_tokens,
|
|
246
|
-
max(CASE WHEN attr_key = 'gen_ai.usage.output_tokens' THEN CAST(attr_int AS BIGINT) END) as output_tokens,
|
|
247
|
-
NULLIF(regexp_extract(max(CASE WHEN attr_key = 'metadata.requester_custom_headers' THEN attr_string END), 'x-litellm-metadata-session-id'': ''([^'']+)''', 1), '') as session_id,
|
|
248
|
-
NULLIF(regexp_extract(max(CASE WHEN attr_key = 'metadata.requester_custom_headers' THEN attr_string END), 'x-litellm-metadata-user-id'': ''([^'']+)''', 1), '') as user_id,
|
|
249
|
-
NULLIF(regexp_extract(max(CASE WHEN attr_key = 'metadata.requester_custom_headers' THEN attr_string END), 'x-litellm-metadata-project-id'': ''([^'']+)''', 1), '') as project_id,
|
|
250
|
-
NULLIF(regexp_extract(max(CASE WHEN attr_key = 'metadata.requester_custom_headers' THEN attr_string END), 'x-litellm-metadata-agent-id'': ''([^'']+)''', 1), '') as agent_id
|
|
251
|
-
FROM attrs
|
|
252
|
-
GROUP BY trace_id, span_name, duration_ms, start_ms
|
|
253
|
-
)"""
|
|
109
|
+
return f"\nWITH raw_spans AS (\n SELECT unnest(resourceSpans) as rs\n FROM read_json('{traces_dir}/*.jsonl', format='newline_delimited', ignore_errors=true)\n),\nspans AS (SELECT unnest(rs.scopeSpans) as ss FROM raw_spans),\nflat_spans AS (SELECT unnest(ss.spans) as span FROM spans),\nparsed AS (\n SELECT\n span.traceId as trace_id,\n span.name as span_name,\n span.startTimeUnixNano::BIGINT / 1000000 as start_ms,\n (span.endTimeUnixNano::BIGINT - span.startTimeUnixNano::BIGINT) / 1000000 as duration_ms,\n json_extract(to_json(span), '$.attributes') as attrs_json\n FROM flat_spans\n),\nattrs AS (\n SELECT trace_id, span_name, duration_ms, start_ms,\n json_extract_string(value, '$.key') as attr_key,\n json_extract_string(value, '$.value.stringValue') as attr_string,\n json_extract_string(value, '$.value.intValue') as attr_int,\n json_extract(value, '$.value.doubleValue') as attr_double\n FROM parsed, json_each(coalesce(attrs_json, '[]'::JSON))\n WHERE span_name = 'Received Proxy Server Request'\n OR EXISTS (SELECT 1 FROM json_each(coalesce(attrs_json, '[]'::JSON)) as attr\n WHERE json_extract_string(attr.value, '$.key') = 'gen_ai.cost.total_cost')\n),\ntraces AS (\n SELECT\n trace_id, span_name, duration_ms, start_ms,\n max(CASE WHEN attr_key IN ('gen_ai.request.model','gen_ai.response.model','model') THEN attr_string END) as model,\n max(CASE WHEN attr_key = 'gen_ai.cost.total_cost' THEN CAST(attr_double AS DOUBLE) END) as cost,\n max(CASE WHEN attr_key = 'gen_ai.usage.input_tokens' THEN CAST(attr_int AS BIGINT) END) as input_tokens,\n max(CASE WHEN attr_key = 'gen_ai.usage.output_tokens' THEN CAST(attr_int AS BIGINT) END) as output_tokens,\n NULLIF(regexp_extract(max(CASE WHEN attr_key = 'metadata.requester_custom_headers' THEN attr_string END), 'x-litellm-metadata-session-id'': ''([^'']+)''', 1), '') as session_id,\n NULLIF(regexp_extract(max(CASE WHEN attr_key = 'metadata.requester_custom_headers' THEN attr_string END), 'x-litellm-metadata-user-id'': ''([^'']+)''', 1), '') as user_id,\n NULLIF(regexp_extract(max(CASE WHEN attr_key = 'metadata.requester_custom_headers' THEN attr_string END), 'x-litellm-metadata-project-id'': ''([^'']+)''', 1), '') as project_id,\n NULLIF(regexp_extract(max(CASE WHEN attr_key = 'metadata.requester_custom_headers' THEN attr_string END), 'x-litellm-metadata-agent-id'': ''([^'']+)''', 1), '') as agent_id\n FROM attrs\n GROUP BY trace_id, span_name, duration_ms, start_ms\n)"
|
|
254
110
|
|
|
255
111
|
def sql_literal(value):
|
|
256
112
|
return "'" + value.replace("'", "''") + "'"
|
|
@@ -259,27 +115,19 @@ def build_trace_filter_clause(scope, project_id, agent_id):
|
|
|
259
115
|
conditions = []
|
|
260
116
|
if scope == 'workspace':
|
|
261
117
|
if project_id:
|
|
262
|
-
conditions.append(f
|
|
118
|
+
conditions.append(f'project_id = {sql_literal(project_id)}')
|
|
263
119
|
else:
|
|
264
120
|
conditions.append('1 = 0')
|
|
265
121
|
if agent_id:
|
|
266
|
-
conditions.append(f
|
|
122
|
+
conditions.append(f'agent_id = {sql_literal(agent_id)}')
|
|
267
123
|
if not conditions:
|
|
268
124
|
return ''
|
|
269
125
|
return 'WHERE ' + ' AND '.join(conditions)
|
|
270
126
|
|
|
271
127
|
def run_query(duckdb_path, traces_dir, sql_after_cte, trace_filter_clause=''):
|
|
272
|
-
|
|
273
|
-
full_sql = f"""{base_query(traces_dir)},
|
|
274
|
-
filtered_traces AS (
|
|
275
|
-
SELECT * FROM traces {trace_filter_clause}
|
|
276
|
-
)
|
|
277
|
-
{sql_after_cte}"""
|
|
128
|
+
full_sql = f'{base_query(traces_dir)},\nfiltered_traces AS (\n SELECT * FROM traces {trace_filter_clause}\n)\n{sql_after_cte}'
|
|
278
129
|
try:
|
|
279
|
-
result = subprocess.run(
|
|
280
|
-
[duckdb_path, '-json', '-c', full_sql],
|
|
281
|
-
capture_output=True, text=True, timeout=30
|
|
282
|
-
)
|
|
130
|
+
result = subprocess.run([duckdb_path, '-json', '-c', full_sql], capture_output=True, text=True, timeout=30)
|
|
283
131
|
if result.returncode != 0:
|
|
284
132
|
return []
|
|
285
133
|
output = result.stdout.strip()
|
|
@@ -289,19 +137,13 @@ filtered_traces AS (
|
|
|
289
137
|
except Exception:
|
|
290
138
|
return []
|
|
291
139
|
|
|
292
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
293
|
-
# Chart Generators
|
|
294
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
295
|
-
|
|
296
140
|
def chart_daily_costs(plt, data, output_dir):
|
|
297
|
-
"""Line chart: daily cost trend with area fill."""
|
|
298
141
|
if not data:
|
|
299
142
|
return None
|
|
300
143
|
fig, ax = plt.subplots()
|
|
301
144
|
dates = [r['date'] for r in data]
|
|
302
145
|
costs = [float(r['cost'] or 0) for r in data]
|
|
303
|
-
display_dates = [d[5:] for d in dates]
|
|
304
|
-
|
|
146
|
+
display_dates = [d[5:] for d in dates]
|
|
305
147
|
ax.fill_between(range(len(dates)), costs, alpha=0.3, color=ACCENT_COLORS[0])
|
|
306
148
|
ax.plot(range(len(dates)), costs, '-o', color=ACCENT_COLORS[0], linewidth=2, markersize=5)
|
|
307
149
|
ax.set_xticks(range(len(dates)))
|
|
@@ -309,13 +151,8 @@ def chart_daily_costs(plt, data, output_dir):
|
|
|
309
151
|
ax.set_ylabel('Cost ($)')
|
|
310
152
|
ax.set_title('Daily Cost Trend')
|
|
311
153
|
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, _: f'${x:.3f}'))
|
|
312
|
-
|
|
313
|
-
# Annotate total
|
|
314
154
|
total = sum(costs)
|
|
315
|
-
ax.annotate(f'Total: ${total:.4f}', xy=(0.98, 0.95), xycoords='axes fraction',
|
|
316
|
-
ha='right', va='top', fontsize=10, color=ACCENT_COLORS[1],
|
|
317
|
-
bbox=dict(boxstyle='round,pad=0.3', facecolor=BG_COLOR, edgecolor=GRID_COLOR))
|
|
318
|
-
|
|
155
|
+
ax.annotate(f'Total: ${total:.4f}', xy=(0.98, 0.95), xycoords='axes fraction', ha='right', va='top', fontsize=10, color=ACCENT_COLORS[1], bbox=dict(boxstyle='round,pad=0.3', facecolor=BG_COLOR, edgecolor=GRID_COLOR))
|
|
319
156
|
plt.tight_layout()
|
|
320
157
|
path = os.path.join(output_dir, 'daily-cost-trend.png')
|
|
321
158
|
plt.savefig(path, bbox_inches='tight')
|
|
@@ -323,41 +160,29 @@ def chart_daily_costs(plt, data, output_dir):
|
|
|
323
160
|
return path
|
|
324
161
|
|
|
325
162
|
def chart_model_breakdown(plt, data, output_dir):
|
|
326
|
-
"""Donut chart: cost by model."""
|
|
327
163
|
if not data:
|
|
328
164
|
return None
|
|
329
165
|
fig, ax = plt.subplots()
|
|
330
166
|
models = [r['model'] or 'unknown' for r in data]
|
|
331
167
|
costs = [float(r['cost'] or 0) for r in data]
|
|
332
168
|
requests = [int(r['requests'] or 0) for r in data]
|
|
333
|
-
|
|
334
|
-
# Shorten model names for display
|
|
335
169
|
short_names = []
|
|
336
170
|
for m in models:
|
|
337
171
|
name = m.replace('claude-', '').replace('gpt-', '').replace('-20250', '')
|
|
338
172
|
if len(name) > 20:
|
|
339
173
|
name = name[:18] + '..'
|
|
340
174
|
short_names.append(name)
|
|
341
|
-
|
|
342
175
|
colors = ACCENT_COLORS[:len(models)]
|
|
343
|
-
wedges, texts, autotexts = ax.pie(
|
|
344
|
-
costs, labels=short_names, colors=colors, autopct='%1.0f%%',
|
|
345
|
-
pctdistance=0.8, startangle=90,
|
|
346
|
-
wedgeprops=dict(width=0.5, edgecolor=BG_COLOR, linewidth=2)
|
|
347
|
-
)
|
|
176
|
+
wedges, texts, autotexts = ax.pie(costs, labels=short_names, colors=colors, autopct='%1.0f%%', pctdistance=0.8, startangle=90, wedgeprops=dict(width=0.5, edgecolor=BG_COLOR, linewidth=2))
|
|
348
177
|
for t in texts:
|
|
349
178
|
t.set_color(FG_COLOR)
|
|
350
179
|
t.set_fontsize(9)
|
|
351
180
|
for t in autotexts:
|
|
352
181
|
t.set_color(FG_COLOR)
|
|
353
182
|
t.set_fontsize(8)
|
|
354
|
-
|
|
355
|
-
# Center label
|
|
356
183
|
total = sum(costs)
|
|
357
|
-
ax.text(0, 0, f'${total:.3f}\ntotal', ha='center', va='center',
|
|
358
|
-
fontsize=12, fontweight='bold', color=FG_COLOR)
|
|
184
|
+
ax.text(0, 0, f'${total:.3f}\ntotal', ha='center', va='center', fontsize=12, fontweight='bold', color=FG_COLOR)
|
|
359
185
|
ax.set_title('Cost by Model')
|
|
360
|
-
|
|
361
186
|
plt.tight_layout()
|
|
362
187
|
path = os.path.join(output_dir, 'cost-by-model.png')
|
|
363
188
|
plt.savefig(path, bbox_inches='tight')
|
|
@@ -365,32 +190,24 @@ def chart_model_breakdown(plt, data, output_dir):
|
|
|
365
190
|
return path
|
|
366
191
|
|
|
367
192
|
def chart_top_sessions(plt, data, output_dir):
|
|
368
|
-
"""Horizontal bar chart: top sessions by cost."""
|
|
369
193
|
if not data:
|
|
370
194
|
return None
|
|
371
195
|
fig, ax = plt.subplots()
|
|
372
|
-
# Take top 8
|
|
373
196
|
data = data[:8]
|
|
374
197
|
session_ids = [format_session_handle(r.get('session_id')) for r in data]
|
|
375
198
|
costs = [float(r['cost'] or 0) for r in data]
|
|
376
199
|
requests = [int(r['requests'] or 0) for r in data]
|
|
377
|
-
|
|
378
200
|
session_ids.reverse()
|
|
379
201
|
costs.reverse()
|
|
380
202
|
requests.reverse()
|
|
381
|
-
|
|
382
203
|
bars = ax.barh(range(len(session_ids)), costs, color=ACCENT_COLORS[2], height=0.6)
|
|
383
204
|
ax.set_yticks(range(len(session_ids)))
|
|
384
205
|
ax.set_yticklabels(session_ids, fontsize=8)
|
|
385
206
|
ax.set_xlabel('Cost ($)')
|
|
386
207
|
ax.set_title('Top Sessions by Cost')
|
|
387
208
|
ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda x, _: f'${x:.4f}'))
|
|
388
|
-
|
|
389
|
-
# Add request count labels
|
|
390
209
|
for i, (bar, req) in enumerate(zip(bars, requests)):
|
|
391
|
-
ax.text(bar.get_width() + max(costs) * 0.02, bar.get_y() + bar.get_height()/2,
|
|
392
|
-
f'{req} req', va='center', fontsize=8, color=FG_COLOR)
|
|
393
|
-
|
|
210
|
+
ax.text(bar.get_width() + max(costs) * 0.02, bar.get_y() + bar.get_height() / 2, f'{req} req', va='center', fontsize=8, color=FG_COLOR)
|
|
394
211
|
plt.tight_layout()
|
|
395
212
|
path = os.path.join(output_dir, 'top-sessions.png')
|
|
396
213
|
plt.savefig(path, bbox_inches='tight')
|
|
@@ -398,21 +215,18 @@ def chart_top_sessions(plt, data, output_dir):
|
|
|
398
215
|
return path
|
|
399
216
|
|
|
400
217
|
def chart_token_efficiency(plt, data, output_dir):
|
|
401
|
-
"""Stacked bar: input vs output tokens by model (shows context bloat)."""
|
|
402
218
|
if not data:
|
|
403
219
|
return None
|
|
404
220
|
fig, ax = plt.subplots()
|
|
405
221
|
models = [r['model'] or 'unknown' for r in data]
|
|
406
222
|
input_t = [int(r['input_tokens'] or 0) for r in data]
|
|
407
223
|
output_t = [int(r['output_tokens'] or 0) for r in data]
|
|
408
|
-
|
|
409
224
|
short_names = []
|
|
410
225
|
for m in models:
|
|
411
226
|
name = m.replace('claude-', '').replace('gpt-', '').replace('-20250', '')
|
|
412
227
|
if len(name) > 16:
|
|
413
228
|
name = name[:14] + '..'
|
|
414
229
|
short_names.append(name)
|
|
415
|
-
|
|
416
230
|
x = range(len(short_names))
|
|
417
231
|
ax.bar(x, input_t, label='Input', color=ACCENT_COLORS[0], width=0.6)
|
|
418
232
|
ax.bar(x, output_t, bottom=input_t, label='Output', color=ACCENT_COLORS[1], width=0.6)
|
|
@@ -421,16 +235,12 @@ def chart_token_efficiency(plt, data, output_dir):
|
|
|
421
235
|
ax.set_ylabel('Tokens')
|
|
422
236
|
ax.set_title('Token Usage by Model')
|
|
423
237
|
ax.legend(loc='upper right')
|
|
424
|
-
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, _: f'{x/1000:.0f}K' if x >= 1000 else f'{x:.0f}'))
|
|
425
|
-
|
|
426
|
-
# Show ratio annotation
|
|
238
|
+
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, _: f'{x / 1000:.0f}K' if x >= 1000 else f'{x:.0f}'))
|
|
427
239
|
for i in range(len(models)):
|
|
428
240
|
total = input_t[i] + output_t[i]
|
|
429
241
|
if total > 0:
|
|
430
242
|
ratio = input_t[i] / max(output_t[i], 1)
|
|
431
|
-
ax.text(i, total + max(input_t[j] + output_t[j] for j in range(len(models))) * 0.02,
|
|
432
|
-
f'{ratio:.1f}x', ha='center', fontsize=7, color=ACCENT_COLORS[3])
|
|
433
|
-
|
|
243
|
+
ax.text(i, total + max((input_t[j] + output_t[j] for j in range(len(models)))) * 0.02, f'{ratio:.1f}x', ha='center', fontsize=7, color=ACCENT_COLORS[3])
|
|
434
244
|
plt.tight_layout()
|
|
435
245
|
path = os.path.join(output_dir, 'token-efficiency.png')
|
|
436
246
|
plt.savefig(path, bbox_inches='tight')
|
|
@@ -438,7 +248,6 @@ def chart_token_efficiency(plt, data, output_dir):
|
|
|
438
248
|
return path
|
|
439
249
|
|
|
440
250
|
def chart_latency_distribution(plt, data, output_dir):
|
|
441
|
-
"""Bar chart: latency percentiles by model."""
|
|
442
251
|
if not data:
|
|
443
252
|
return None
|
|
444
253
|
fig, ax = plt.subplots()
|
|
@@ -446,27 +255,23 @@ def chart_latency_distribution(plt, data, output_dir):
|
|
|
446
255
|
p50 = [float(r['p50'] or 0) for r in data]
|
|
447
256
|
p95 = [float(r['p95'] or 0) for r in data]
|
|
448
257
|
p99 = [float(r['p99'] or 0) for r in data]
|
|
449
|
-
|
|
450
258
|
short_names = []
|
|
451
259
|
for m in models:
|
|
452
260
|
name = m.replace('claude-', '').replace('gpt-', '').replace('-20250', '')
|
|
453
261
|
if len(name) > 16:
|
|
454
262
|
name = name[:14] + '..'
|
|
455
263
|
short_names.append(name)
|
|
456
|
-
|
|
457
264
|
x = range(len(short_names))
|
|
458
265
|
width = 0.25
|
|
459
266
|
ax.bar([i - width for i in x], p50, width, label='p50', color=ACCENT_COLORS[0])
|
|
460
267
|
ax.bar(x, p95, width, label='p95', color=ACCENT_COLORS[2])
|
|
461
268
|
ax.bar([i + width for i in x], p99, width, label='p99', color=ACCENT_COLORS[4])
|
|
462
|
-
|
|
463
269
|
ax.set_xticks(x)
|
|
464
270
|
ax.set_xticklabels(short_names, rotation=45, ha='right', fontsize=8)
|
|
465
271
|
ax.set_ylabel('Latency (ms)')
|
|
466
272
|
ax.set_title('Response Latency by Model')
|
|
467
273
|
ax.legend(loc='upper right')
|
|
468
|
-
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, _: f'{x/1000:.1f}s' if x >= 1000 else f'{x:.0f}ms'))
|
|
469
|
-
|
|
274
|
+
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, _: f'{x / 1000:.1f}s' if x >= 1000 else f'{x:.0f}ms'))
|
|
470
275
|
plt.tight_layout()
|
|
471
276
|
path = os.path.join(output_dir, 'latency-distribution.png')
|
|
472
277
|
plt.savefig(path, bbox_inches='tight')
|
|
@@ -474,22 +279,18 @@ def chart_latency_distribution(plt, data, output_dir):
|
|
|
474
279
|
return path
|
|
475
280
|
|
|
476
281
|
def chart_hourly_activity(plt, data, output_dir):
|
|
477
|
-
"""Bar chart: request count by hour of day."""
|
|
478
282
|
if not data:
|
|
479
283
|
return None
|
|
480
284
|
fig, ax = plt.subplots()
|
|
481
285
|
hours = [int(r['hour']) for r in data]
|
|
482
286
|
counts = [int(r['count'] or 0) for r in data]
|
|
483
287
|
costs = [float(r['cost'] or 0) for r in data]
|
|
484
|
-
|
|
485
|
-
# Fill missing hours
|
|
486
288
|
hour_counts = [0] * 24
|
|
487
289
|
hour_costs = [0.0] * 24
|
|
488
290
|
for h, c, co in zip(hours, counts, costs):
|
|
489
291
|
if 0 <= h < 24:
|
|
490
292
|
hour_counts[h] = c
|
|
491
293
|
hour_costs[h] = co
|
|
492
|
-
|
|
493
294
|
colors = [ACCENT_COLORS[0] if c > 0 else GRID_COLOR for c in hour_counts]
|
|
494
295
|
bars = ax.bar(range(24), hour_counts, color=colors, width=0.8)
|
|
495
296
|
ax.set_xlabel('Hour of Day')
|
|
@@ -497,26 +298,16 @@ def chart_hourly_activity(plt, data, output_dir):
|
|
|
497
298
|
ax.set_title('Activity by Hour')
|
|
498
299
|
ax.set_xticks(range(0, 24, 3))
|
|
499
300
|
ax.set_xticklabels([f'{h:02d}:00' for h in range(0, 24, 3)], fontsize=8)
|
|
500
|
-
|
|
501
|
-
# Highlight peak hour
|
|
502
301
|
if max(hour_counts) > 0:
|
|
503
302
|
peak = hour_counts.index(max(hour_counts))
|
|
504
303
|
bars[peak].set_color(ACCENT_COLORS[3])
|
|
505
|
-
ax.annotate(f'Peak: {peak:02d}:00', xy=(peak, hour_counts[peak]),
|
|
506
|
-
xytext=(peak + 2, hour_counts[peak] * 0.9),
|
|
507
|
-
arrowprops=dict(arrowstyle='->', color=ACCENT_COLORS[3], lw=1.5),
|
|
508
|
-
fontsize=9, color=ACCENT_COLORS[3])
|
|
509
|
-
|
|
304
|
+
ax.annotate(f'Peak: {peak:02d}:00', xy=(peak, hour_counts[peak]), xytext=(peak + 2, hour_counts[peak] * 0.9), arrowprops=dict(arrowstyle='->', color=ACCENT_COLORS[3], lw=1.5), fontsize=9, color=ACCENT_COLORS[3])
|
|
510
305
|
plt.tight_layout()
|
|
511
306
|
path = os.path.join(output_dir, 'hourly-activity.png')
|
|
512
307
|
plt.savefig(path, bbox_inches='tight')
|
|
513
308
|
plt.close()
|
|
514
309
|
return path
|
|
515
310
|
|
|
516
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
517
|
-
# Main
|
|
518
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
519
|
-
|
|
520
311
|
def main():
|
|
521
312
|
traces_dir = ''
|
|
522
313
|
output_dir = ''
|
|
@@ -526,13 +317,8 @@ def main():
|
|
|
526
317
|
else:
|
|
527
318
|
traces_dir = os.environ.get('AGENTIDE_TRACES_DIR', '').strip()
|
|
528
319
|
output_dir = os.environ.get('AGENTIDE_OUTPUT_DIR', '').strip()
|
|
529
|
-
|
|
530
320
|
if not traces_dir or not output_dir:
|
|
531
|
-
print(
|
|
532
|
-
f"Usage: {sys.argv[0]} <traces_dir> <output_dir> "
|
|
533
|
-
"(or set AGENTIDE_TRACES_DIR + AGENTIDE_OUTPUT_DIR)",
|
|
534
|
-
file=sys.stderr,
|
|
535
|
-
)
|
|
321
|
+
print(f'Usage: {sys.argv[0]} <traces_dir> <output_dir> (or set AGENTIDE_TRACES_DIR + AGENTIDE_OUTPUT_DIR)', file=sys.stderr)
|
|
536
322
|
sys.exit(1)
|
|
537
323
|
scope = os.environ.get('AGENTIDE_ANALYTICS_SCOPE', 'global').strip().lower()
|
|
538
324
|
if scope not in ('global', 'workspace'):
|
|
@@ -540,146 +326,80 @@ def main():
|
|
|
540
326
|
project_id = os.environ.get('AGENTIDE_ANALYTICS_PROJECT_ID', '').strip()
|
|
541
327
|
agent_id = os.environ.get('AGENTIDE_ANALYTICS_AGENT_ID', '').strip()
|
|
542
328
|
trace_filter_clause = build_trace_filter_clause(scope, project_id, agent_id)
|
|
543
|
-
|
|
544
|
-
# Verify traces exist
|
|
545
329
|
traces_path = Path(traces_dir)
|
|
546
330
|
if not traces_path.exists() or not list(traces_path.glob('*.jsonl')):
|
|
547
|
-
print(json.dumps({
|
|
331
|
+
print(json.dumps({'status': 'no_data', 'charts': []}))
|
|
548
332
|
sys.exit(2)
|
|
549
|
-
|
|
550
|
-
# ── DuckDB: prefer indexed DB when available, fall back to JSONL ──────────
|
|
551
333
|
configured_index_db_path = os.environ.get('AGENTIDE_INDEX_DB_PATH', '').strip()
|
|
552
334
|
fallback_index_db_path = str((traces_path / 'analytics.duckdb').resolve())
|
|
553
335
|
index_db_path = configured_index_db_path or fallback_index_db_path
|
|
554
336
|
use_duckdb_env = os.environ.get('AGENTIDE_USE_DUCKDB', '').strip().lower() == 'true'
|
|
555
|
-
# Auto-enable indexed mode when the DB exists; AGENTIDE_USE_DUCKDB can still force true.
|
|
556
337
|
use_indexed_db = bool(index_db_path) and os.path.exists(index_db_path)
|
|
557
|
-
|
|
558
|
-
if use_duckdb_env and not use_indexed_db:
|
|
338
|
+
if use_duckdb_env and (not use_indexed_db):
|
|
559
339
|
sys.stderr.write('[Dashboard] AGENTIDE_USE_DUCKDB=true but indexed DB path was not found\n')
|
|
560
|
-
|
|
561
340
|
if use_indexed_db:
|
|
562
341
|
sys.stderr.write(f'[Dashboard] Indexed mode enabled: {index_db_path}\n')
|
|
563
342
|
else:
|
|
564
343
|
sys.stderr.write('[Dashboard] Indexed DB unavailable; falling back to JSONL mode\n')
|
|
565
|
-
|
|
566
|
-
# Default charts output location when not supplied by caller.
|
|
567
344
|
chart_dir_override = os.environ.get('AGENTIDE_CHART_DIR', '').strip()
|
|
568
|
-
|
|
569
|
-
conn, conn_error = open_duckdb_connection(
|
|
570
|
-
traces_dir, use_indexed_db, index_db_path, trace_filter_clause
|
|
571
|
-
)
|
|
345
|
+
conn, conn_error = open_duckdb_connection(traces_dir, use_indexed_db, index_db_path, trace_filter_clause)
|
|
572
346
|
if conn is None:
|
|
573
|
-
print(json.dumps({
|
|
347
|
+
print(json.dumps({'status': 'error', 'error': conn_error}))
|
|
574
348
|
sys.exit(1)
|
|
575
|
-
|
|
576
|
-
# Ensure output dir
|
|
577
349
|
charts_dir = chart_dir_override or os.path.join(output_dir, 'charts')
|
|
578
350
|
os.makedirs(charts_dir, exist_ok=True)
|
|
579
351
|
disabled_charts = parse_disabled_charts()
|
|
580
|
-
|
|
581
352
|
plt = setup_matplotlib()
|
|
582
353
|
generated = []
|
|
583
|
-
|
|
584
354
|
try:
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
# 1. Daily cost trend (past 14 days)
|
|
588
|
-
daily_data = run_query_conn(conn, """
|
|
589
|
-
SELECT strftime(to_timestamp(start_ms / 1000), '%Y-%m-%d') as date,
|
|
590
|
-
SUM(cost) as cost, COUNT(*) as requests
|
|
591
|
-
FROM filtered_traces WHERE cost IS NOT NULL
|
|
592
|
-
AND start_ms > (EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - INTERVAL '14 days')) * 1000)
|
|
593
|
-
GROUP BY date ORDER BY date ASC
|
|
594
|
-
""")
|
|
355
|
+
daily_data = run_query_conn(conn, "\n SELECT strftime(to_timestamp(start_ms / 1000), '%Y-%m-%d') as date,\n SUM(cost) as cost, COUNT(*) as requests\n FROM filtered_traces WHERE cost IS NOT NULL\n AND start_ms > (EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - INTERVAL '14 days')) * 1000)\n GROUP BY date ORDER BY date ASC\n ")
|
|
595
356
|
if is_chart_disabled(disabled_charts, 'daily-cost-trend.png'):
|
|
596
357
|
remove_chart_if_exists(charts_dir, 'daily-cost-trend.png')
|
|
597
358
|
else:
|
|
598
359
|
path = chart_daily_costs(plt, daily_data, charts_dir)
|
|
599
360
|
if path:
|
|
600
|
-
generated.append({
|
|
601
|
-
|
|
602
|
-
# 2. Cost by model (donut)
|
|
603
|
-
model_data = run_query_conn(conn, """
|
|
604
|
-
SELECT COALESCE(model, 'unknown') as model, SUM(cost) as cost, COUNT(*) as requests,
|
|
605
|
-
SUM(input_tokens) as input_tokens, SUM(output_tokens) as output_tokens
|
|
606
|
-
FROM filtered_traces WHERE cost IS NOT NULL
|
|
607
|
-
GROUP BY model ORDER BY cost DESC
|
|
608
|
-
""")
|
|
361
|
+
generated.append({'file': path, 'title': 'Daily Cost Trend', 'type': 'chart'})
|
|
362
|
+
model_data = run_query_conn(conn, "\n SELECT COALESCE(model, 'unknown') as model, SUM(cost) as cost, COUNT(*) as requests,\n SUM(input_tokens) as input_tokens, SUM(output_tokens) as output_tokens\n FROM filtered_traces WHERE cost IS NOT NULL\n GROUP BY model ORDER BY cost DESC\n ")
|
|
609
363
|
if is_chart_disabled(disabled_charts, 'cost-by-model.png'):
|
|
610
364
|
remove_chart_if_exists(charts_dir, 'cost-by-model.png')
|
|
611
365
|
else:
|
|
612
366
|
path = chart_model_breakdown(plt, model_data, charts_dir)
|
|
613
367
|
if path:
|
|
614
|
-
generated.append({
|
|
615
|
-
|
|
616
|
-
# 3. Top sessions by cost
|
|
617
|
-
session_data = run_query_conn(conn, """
|
|
618
|
-
SELECT COALESCE(session_id, '(none)') as session_id, SUM(cost) as cost, COUNT(*) as requests
|
|
619
|
-
FROM filtered_traces WHERE cost IS NOT NULL AND session_id IS NOT NULL
|
|
620
|
-
GROUP BY session_id ORDER BY cost DESC LIMIT 10
|
|
621
|
-
""")
|
|
368
|
+
generated.append({'file': path, 'title': 'Cost by Model', 'type': 'chart'})
|
|
369
|
+
session_data = run_query_conn(conn, "\n SELECT COALESCE(session_id, '(none)') as session_id, SUM(cost) as cost, COUNT(*) as requests\n FROM filtered_traces WHERE cost IS NOT NULL AND session_id IS NOT NULL\n GROUP BY session_id ORDER BY cost DESC LIMIT 10\n ")
|
|
622
370
|
top_sessions_disabled = is_chart_disabled(disabled_charts, 'top-sessions.png')
|
|
623
371
|
if top_sessions_disabled:
|
|
624
372
|
remove_chart_if_exists(charts_dir, 'top-sessions.png')
|
|
625
373
|
else:
|
|
626
374
|
path = chart_top_sessions(plt, session_data, charts_dir)
|
|
627
375
|
if path:
|
|
628
|
-
generated.append({
|
|
629
|
-
|
|
630
|
-
# 4. Token efficiency by model (input vs output stacked) — reuses model_data
|
|
376
|
+
generated.append({'file': path, 'title': 'Top Sessions by Cost', 'type': 'chart'})
|
|
631
377
|
if is_chart_disabled(disabled_charts, 'token-efficiency.png'):
|
|
632
378
|
remove_chart_if_exists(charts_dir, 'token-efficiency.png')
|
|
633
379
|
else:
|
|
634
380
|
path = chart_token_efficiency(plt, model_data, charts_dir)
|
|
635
381
|
if path:
|
|
636
|
-
generated.append({
|
|
637
|
-
|
|
638
|
-
# 5. Latency distribution by model (p50/p95/p99)
|
|
639
|
-
latency_data = run_query_conn(conn, """
|
|
640
|
-
SELECT COALESCE(model, 'unknown') as model,
|
|
641
|
-
PERCENTILE_CONT(0.50) WITHIN GROUP (ORDER BY duration_ms) as p50,
|
|
642
|
-
PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY duration_ms) as p95,
|
|
643
|
-
PERCENTILE_CONT(0.99) WITHIN GROUP (ORDER BY duration_ms) as p99
|
|
644
|
-
FROM filtered_traces WHERE cost IS NOT NULL
|
|
645
|
-
GROUP BY model ORDER BY p50 DESC
|
|
646
|
-
""")
|
|
382
|
+
generated.append({'file': path, 'title': 'Token Usage by Model', 'type': 'chart'})
|
|
383
|
+
latency_data = run_query_conn(conn, "\n SELECT COALESCE(model, 'unknown') as model,\n PERCENTILE_CONT(0.50) WITHIN GROUP (ORDER BY duration_ms) as p50,\n PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY duration_ms) as p95,\n PERCENTILE_CONT(0.99) WITHIN GROUP (ORDER BY duration_ms) as p99\n FROM filtered_traces WHERE cost IS NOT NULL\n GROUP BY model ORDER BY p50 DESC\n ")
|
|
647
384
|
if is_chart_disabled(disabled_charts, 'latency-distribution.png'):
|
|
648
385
|
remove_chart_if_exists(charts_dir, 'latency-distribution.png')
|
|
649
386
|
else:
|
|
650
387
|
path = chart_latency_distribution(plt, latency_data, charts_dir)
|
|
651
388
|
if path:
|
|
652
|
-
generated.append({
|
|
653
|
-
|
|
654
|
-
# 6. Hourly activity heatmap
|
|
655
|
-
hourly_data = run_query_conn(conn, """
|
|
656
|
-
SELECT EXTRACT(HOUR FROM to_timestamp(start_ms / 1000)) as hour,
|
|
657
|
-
COUNT(*) as count, SUM(cost) as cost
|
|
658
|
-
FROM filtered_traces WHERE cost IS NOT NULL
|
|
659
|
-
GROUP BY hour ORDER BY hour
|
|
660
|
-
""")
|
|
389
|
+
generated.append({'file': path, 'title': 'Latency Distribution', 'type': 'chart'})
|
|
390
|
+
hourly_data = run_query_conn(conn, '\n SELECT EXTRACT(HOUR FROM to_timestamp(start_ms / 1000)) as hour,\n COUNT(*) as count, SUM(cost) as cost\n FROM filtered_traces WHERE cost IS NOT NULL\n GROUP BY hour ORDER BY hour\n ')
|
|
661
391
|
if is_chart_disabled(disabled_charts, 'hourly-activity.png'):
|
|
662
392
|
remove_chart_if_exists(charts_dir, 'hourly-activity.png')
|
|
663
393
|
else:
|
|
664
394
|
path = chart_hourly_activity(plt, hourly_data, charts_dir)
|
|
665
395
|
if path:
|
|
666
|
-
generated.append({
|
|
667
|
-
|
|
396
|
+
generated.append({'file': path, 'title': 'Activity by Hour', 'type': 'chart'})
|
|
668
397
|
finally:
|
|
669
398
|
conn.close()
|
|
670
|
-
|
|
671
399
|
if not generated:
|
|
672
|
-
print(json.dumps({
|
|
400
|
+
print(json.dumps({'status': 'no_data', 'charts': []}))
|
|
673
401
|
sys.exit(2)
|
|
674
|
-
|
|
675
|
-
# Output manifest
|
|
676
|
-
result = {
|
|
677
|
-
"status": "ok",
|
|
678
|
-
"generated_at": datetime.utcnow().isoformat() + "Z",
|
|
679
|
-
"charts": generated
|
|
680
|
-
}
|
|
402
|
+
result = {'status': 'ok', 'generated_at': datetime.utcnow().isoformat() + 'Z', 'charts': generated}
|
|
681
403
|
print(json.dumps(result, indent=2))
|
|
682
|
-
|
|
683
|
-
|
|
684
404
|
if __name__ == '__main__':
|
|
685
405
|
main()
|