@agenthippo-ai/agenthippo 1.110.11 → 1.110.20
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 -302
- 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 -1283
- 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 +618 -564
- 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 +127 -459
- package/out/scripts/analytics/agent-fleet-widget.js +18 -257
- package/out/scripts/analytics/agentide-litellm-otel.config.yaml +0 -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/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 +10 -6
- package/out/agentpack/github.js +0 -547
- package/out/agentpack/index.js +0 -69
- 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 -521
- 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 -324
- 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 -681
- 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 -151
- 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 -351
- package/out/cli/commands/serve.js +0 -1950
- package/out/cli/commands/store.js +0 -927
- package/out/cli/credential-context.js +0 -108
- 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 -153
- 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 -225
- package/out/cli/deploy/blueprints/registry.js +0 -84
- package/out/cli/deploy/layers/identity.js +0 -175
- 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 -776
- 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 -680
- 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 -643
- 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 -546
- 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 -326
- package/out/pack/lease-schema.js +0 -273
- package/out/pack/lease.js +0 -682
- 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 -141
- package/out/runner/protocol.js +0 -128
- package/out/runner/remoteEngine.js +0 -166
- 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 -572
- package/out/sandbox/processDriver.js +0 -318
- package/out/sandbox/sandboxRunner.js +0 -303
- 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 -460
- 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 -282
- package/out/test/data-plane.test.js +0 -624
- package/out/test/deploy-init.test.js +0 -860
- 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 -222
- 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 -224
- package/out/test/lease.test.js +0 -114
- package/out/test/localFleetAdapter.test.js +0 -91
- 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 -406
- package/out/test/sandbox-runner.test.js +0 -343
- package/out/test/sandbox-scope.test.js +0 -449
- package/out/test/scheduledFleetStorage.test.js +0 -72
- package/out/test/serve-cron-acceptance.test.js +0 -370
- package/out/test/serve-gateway-turn.test.js +0 -389
- package/out/test/serve-hardening.test.js +0 -591
- package/out/test/serveClient.test.js +0 -209
- package/out/test/sessionJsonlFleet.test.js +0 -78
- package/out/test/sessionShip.test.js +0 -618
- 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,776 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*---------------------------------------------------------------------------------------------
|
|
3
|
-
* Copyright (c) AgentHippo.ai. All rights reserved.
|
|
4
|
-
*--------------------------------------------------------------------------------------------*/
|
|
5
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
-
}
|
|
11
|
-
Object.defineProperty(o, k2, desc);
|
|
12
|
-
}) : (function(o, m, k, k2) {
|
|
13
|
-
if (k2 === undefined) k2 = k;
|
|
14
|
-
o[k2] = m[k];
|
|
15
|
-
}));
|
|
16
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
-
}) : function(o, v) {
|
|
19
|
-
o["default"] = v;
|
|
20
|
-
});
|
|
21
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
-
var ownKeys = function(o) {
|
|
23
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
-
var ar = [];
|
|
25
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
-
return ar;
|
|
27
|
-
};
|
|
28
|
-
return ownKeys(o);
|
|
29
|
-
};
|
|
30
|
-
return function (mod) {
|
|
31
|
-
if (mod && mod.__esModule) return mod;
|
|
32
|
-
var result = {};
|
|
33
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
-
__setModuleDefault(result, mod);
|
|
35
|
-
return result;
|
|
36
|
-
};
|
|
37
|
-
})();
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.TurnGate = exports.TURN_LIMIT_BUSY_MESSAGE = exports.RATE_LIMIT_BUSY_MESSAGE = exports.TURN_GATE_BUSY_MESSAGE = exports.TURN_GATE_RETRY_AFTER_SECONDS = exports.TURN_QUEUE_ENV = exports.MAX_CONCURRENT_TURNS_ENV = exports.TurnLimiter = exports.SESSION_WITHOUT_USER_REASON = exports.REQUIRE_TENANT_ISOLATION_ENV = exports.IDENTITY_PROXY_SECRET_ENV = exports.IDENTITY_HEADER_ENV = exports.PIN_ONLY_IDENTITY_HEADERS = exports.RateLimiter = exports.XFF_TRUSTED_HOPS_ENV = exports.CONTAINER_SERVE_HOST = exports.SERVE_HOST_ENV = exports.DEFAULT_BIND_HOST = exports.SERVICE_USER_ENV = exports.DEFAULT_MAX_BODY_BYTES = void 0;
|
|
40
|
-
exports.resolveStateDir = resolveStateDir;
|
|
41
|
-
exports.resolveAnalyticsSessionsDir = resolveAnalyticsSessionsDir;
|
|
42
|
-
exports.resolveServiceIdentity = resolveServiceIdentity;
|
|
43
|
-
exports.isLoopbackHost = isLoopbackHost;
|
|
44
|
-
exports.resolveBindHost = resolveBindHost;
|
|
45
|
-
exports.clientIp = clientIp;
|
|
46
|
-
exports.hasTrustedProxyProof = hasTrustedProxyProof;
|
|
47
|
-
exports.identityHeaderAdvice = identityHeaderAdvice;
|
|
48
|
-
exports.tenantIsolationAdvice = tenantIsolationAdvice;
|
|
49
|
-
exports.resolveUserId = resolveUserId;
|
|
50
|
-
exports.resolveDataToken = resolveDataToken;
|
|
51
|
-
exports.peerToUserId = peerToUserId;
|
|
52
|
-
exports.userNamespaceHash = userNamespaceHash;
|
|
53
|
-
exports.resolveServeSessionKey = resolveServeSessionKey;
|
|
54
|
-
exports.corsHeaders = corsHeaders;
|
|
55
|
-
exports.createTurnGateFromEnv = createTurnGateFromEnv;
|
|
56
|
-
exports.createRejectionWarner = createRejectionWarner;
|
|
57
|
-
exports.readBodyWithCap = readBodyWithCap;
|
|
58
|
-
/**
|
|
59
|
-
* Serve helpers: state-dir resolution, identity header reading, CORS, turn limiting, body cap.
|
|
60
|
-
*
|
|
61
|
-
* Auth and credential checking are the deploy layer's responsibility (Caddy, Cloud Run IAP,
|
|
62
|
-
* Databricks Apps SSO, etc.). Serve trusts the identity headers set by the layer in front;
|
|
63
|
-
* it does not validate tokens or enforce bearer keys itself.
|
|
64
|
-
*
|
|
65
|
-
* SECURITY CONTRACT: serve trusts the identity and data-token headers below unconditionally.
|
|
66
|
-
* It MUST sit behind a proxy that (a) authenticates the caller and sets the identity header,
|
|
67
|
-
* and (b) STRIPS any client-supplied copies of these headers on the way in. Deployments where
|
|
68
|
-
* other workloads share the network with serve (compose, sidecar platforms) can additionally
|
|
69
|
-
* require proof that a request came through that proxy — see IDENTITY_PROXY_SECRET_ENV.
|
|
70
|
-
*/
|
|
71
|
-
const os = __importStar(require("os"));
|
|
72
|
-
const path = __importStar(require("path"));
|
|
73
|
-
const crypto = __importStar(require("crypto"));
|
|
74
|
-
const paths_1 = require("../utils/paths");
|
|
75
|
-
const config_1 = require("../auth-broker/config");
|
|
76
|
-
/** Default cap on a single request body (1 MiB). Chat messages are small; large bodies are abuse or bugs. */
|
|
77
|
-
exports.DEFAULT_MAX_BODY_BYTES = 1024 * 1024;
|
|
78
|
-
/**
|
|
79
|
-
* Resolve where session state is persisted. Precedence:
|
|
80
|
-
* 1. explicit --state-dir
|
|
81
|
-
* 2. AGENTHIPPO_HOME (the documented container mount point)
|
|
82
|
-
* 3. tmpdir (dev/local only; lost on restart)
|
|
83
|
-
*
|
|
84
|
-
* Returns `{ dir, ephemeral }` so the caller can warn when ephemeral state is
|
|
85
|
-
* detected in a long-lived deployment.
|
|
86
|
-
*/
|
|
87
|
-
function resolveStateDir(stateDirOpt, env = process.env) {
|
|
88
|
-
const explicit = stateDirOpt?.trim();
|
|
89
|
-
if (explicit) {
|
|
90
|
-
return { dir: path.resolve(explicit), ephemeral: false };
|
|
91
|
-
}
|
|
92
|
-
const home = env.AGENTHIPPO_HOME?.trim() || env.AGENTIDE_HOME?.trim();
|
|
93
|
-
if (home) {
|
|
94
|
-
return { dir: path.join(path.resolve(home), 'serve-state'), ephemeral: false };
|
|
95
|
-
}
|
|
96
|
-
return { dir: path.join(os.tmpdir(), 'agenthippo-server'), ephemeral: true };
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Where serve's Layer 2 analytics (tool-call/warrant JSONL) should live. Precedence:
|
|
100
|
-
* 1. AGENT_HOME_DIR / AGENTHIPPO_HOME set → getAgentideHome()/analytics/sessions — the
|
|
101
|
-
* exact location sessionJsonlFleet.ts and query-analytics.sh already scan by default,
|
|
102
|
-
* so this data stays discoverable to Spotlight/DuckDB.
|
|
103
|
-
* 2. Neither set, but the resolved state dir is non-ephemeral (an explicit --state-dir
|
|
104
|
-
* was given) → <stateDir>/analytics/sessions. Not the canonical scan location, but
|
|
105
|
-
* still durable — never regress below whatever durability the caller already
|
|
106
|
-
* established just to be discoverable.
|
|
107
|
-
* 3. Neither set and state is ephemeral (no --state-dir, no home-dir env var at all) →
|
|
108
|
-
* falls through to getAgentideHome()'s own os.homedir() default, matching the
|
|
109
|
-
* already-correct IDE-local behavior — nothing durable was configured either way.
|
|
110
|
-
*/
|
|
111
|
-
function resolveAnalyticsSessionsDir(stateDir, stateDirEphemeral, env = process.env) {
|
|
112
|
-
const homeOverride = env.AGENT_HOME_DIR?.trim() || env.AGENTHIPPO_HOME?.trim();
|
|
113
|
-
if (!homeOverride && !stateDirEphemeral) {
|
|
114
|
-
return path.join(stateDir, 'analytics', 'sessions');
|
|
115
|
-
}
|
|
116
|
-
return path.join((0, paths_1.getAgentideHome)(), 'analytics', 'sessions');
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Env: the identity an UNATTENDED turn runs as — a cron- or channel-fired run with no chat peer
|
|
120
|
-
* (PLAN/agent-identity.md §5). Deployment configuration, deliberately not a pack field: it names
|
|
121
|
-
* an identity that exists only in the operator's environment and must match their role map.
|
|
122
|
-
*/
|
|
123
|
-
exports.SERVICE_USER_ENV = 'AGENTHIPPO_SERVICE_USER';
|
|
124
|
-
/** Longest identity we will carry. Generous; the point is to reject a pasted file, not to be tight. */
|
|
125
|
-
const MAX_SERVICE_USER_LEN = 256;
|
|
126
|
-
/**
|
|
127
|
-
* Validate the service identity at boot.
|
|
128
|
-
*
|
|
129
|
-
* **Shape, not vocabulary.** An earlier draft of the design required `^svc:[a-z0-9-]+$` and would
|
|
130
|
-
* have refused to boot on the two handles an enterprise operator is most likely to bind: a SPIFFE
|
|
131
|
-
* ID (`spiffe://corp/ns/agents/invoice`) and a Microsoft Entra agent identity object id. Both are
|
|
132
|
-
* exactly the federated principals §8 wants this to become, so the validator checks that the value
|
|
133
|
-
* is a usable single token and warns — rather than refuses — when it carries no recognisable
|
|
134
|
-
* namespace.
|
|
135
|
-
*
|
|
136
|
-
* Malformed IS a boot refusal though: the alternative is a fleet that looks configured and runs
|
|
137
|
-
* every scheduled job anonymously.
|
|
138
|
-
*/
|
|
139
|
-
function resolveServiceIdentity(env = process.env) {
|
|
140
|
-
const raw = env[exports.SERVICE_USER_ENV];
|
|
141
|
-
if (raw === undefined) {
|
|
142
|
-
return {};
|
|
143
|
-
}
|
|
144
|
-
const identity = raw.trim();
|
|
145
|
-
if (!identity) {
|
|
146
|
-
return { error: `${exports.SERVICE_USER_ENV} is set but empty. Unset it, or give it the identity unattended runs should act as.` };
|
|
147
|
-
}
|
|
148
|
-
if (/\s/.test(identity)) {
|
|
149
|
-
return { error: `${exports.SERVICE_USER_ENV} must not contain whitespace, got ${JSON.stringify(raw)}.` };
|
|
150
|
-
}
|
|
151
|
-
if (identity.length > MAX_SERVICE_USER_LEN) {
|
|
152
|
-
return { error: `${exports.SERVICE_USER_ENV} is ${identity.length} chars; the maximum is ${MAX_SERVICE_USER_LEN}.` };
|
|
153
|
-
}
|
|
154
|
-
// Recognised shapes: the local convention, a SPIFFE ID, or a bare GUID (Entra object id).
|
|
155
|
-
const namespaced = /^svc:/.test(identity)
|
|
156
|
-
|| /^spiffe:\/\//.test(identity)
|
|
157
|
-
|| /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(identity);
|
|
158
|
-
if (!namespaced) {
|
|
159
|
-
return {
|
|
160
|
-
identity,
|
|
161
|
-
warning: `${exports.SERVICE_USER_ENV}="${identity}" carries no namespace marker (svc: / spiffe:// / GUID). `
|
|
162
|
-
+ 'It will be used verbatim and must be mapped in the connector role map, exactly like a human identity. '
|
|
163
|
-
+ 'If it can collide with a real user id, prefix it with `svc:`.',
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
return { identity };
|
|
167
|
-
}
|
|
168
|
-
/** Loopback default — safe everywhere a human runs `serve` locally. */
|
|
169
|
-
exports.DEFAULT_BIND_HOST = '127.0.0.1';
|
|
170
|
-
/** True when a bind address is reachable only from this machine. */
|
|
171
|
-
function isLoopbackHost(host) {
|
|
172
|
-
const h = host.trim().toLowerCase().replace(/^\[|\]$/g, '');
|
|
173
|
-
return h === 'localhost' || h === '::1' || /^127\./.test(h);
|
|
174
|
-
}
|
|
175
|
-
/** Env var for the listen address (used by generated deploy Dockerfiles). */
|
|
176
|
-
exports.SERVE_HOST_ENV = 'AGENTHIPPO_SERVE_HOST';
|
|
177
|
-
/** Bind address baked into container deploy artifacts (Docker / Cloud Run sidecars). */
|
|
178
|
-
exports.CONTAINER_SERVE_HOST = '0.0.0.0';
|
|
179
|
-
/**
|
|
180
|
-
* Resolve the listen address. Precedence: explicit `--host` → AGENTHIPPO_SERVE_HOST → 127.0.0.1.
|
|
181
|
-
*
|
|
182
|
-
* Defaults to loopback so a local `serve` is never reachable off-box by accident. Containers
|
|
183
|
-
* (where the SSO proxy reaches the agent over a Docker network) MUST opt into `0.0.0.0` —
|
|
184
|
-
* generated deploy artifacts set `AGENTHIPPO_SERVE_HOST=0.0.0.0` for exactly this reason.
|
|
185
|
-
*/
|
|
186
|
-
function resolveBindHost(hostOpt, env = process.env) {
|
|
187
|
-
return hostOpt?.trim() || env.AGENTHIPPO_SERVE_HOST?.trim() || exports.DEFAULT_BIND_HOST;
|
|
188
|
-
}
|
|
189
|
-
/** Env var: number of trusted proxy hops in front of serve (default 1 — the single Caddy). */
|
|
190
|
-
exports.XFF_TRUSTED_HOPS_ENV = 'AGENTHIPPO_XFF_TRUSTED_HOPS';
|
|
191
|
-
/**
|
|
192
|
-
* Best-effort client IP for rate-limiting keys.
|
|
193
|
-
*
|
|
194
|
-
* Each trusted proxy appends the IP it observed to `X-Forwarded-For`, so with N trusted hops
|
|
195
|
-
* the real client is the Nth entry from the right (a client-spoofed left-most entry is just
|
|
196
|
-
* prepended and never reached). Default is 1 (the documented single Caddy). Behind
|
|
197
|
-
* Cloudflare Tunnel → Caddy there are two hops — Caddy appends cloudflared's container IP,
|
|
198
|
-
* which is identical for every client, so leaving hops at 1 there collapses all users into one
|
|
199
|
-
* rate-limit bucket. Set AGENTHIPPO_XFF_TRUSTED_HOPS=2 for the tunnel profile.
|
|
200
|
-
* Falls back to the socket address for direct/local callers. This is a coarse abuse key, not
|
|
201
|
-
* an identity — never use it for authorization.
|
|
202
|
-
*/
|
|
203
|
-
function clientIp(req, env = process.env) {
|
|
204
|
-
const xff = req.headers['x-forwarded-for'];
|
|
205
|
-
const raw = Array.isArray(xff) ? xff[0] : xff;
|
|
206
|
-
if (raw) {
|
|
207
|
-
const parts = raw.split(',').map((s) => s.trim()).filter(Boolean);
|
|
208
|
-
if (parts.length > 0) {
|
|
209
|
-
const hopsRaw = Number(env[exports.XFF_TRUSTED_HOPS_ENV]);
|
|
210
|
-
const hops = Number.isInteger(hopsRaw) && hopsRaw >= 1 ? hopsRaw : 1;
|
|
211
|
-
return parts[Math.max(0, parts.length - hops)];
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
return req.socket?.remoteAddress || 'unknown';
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Fixed-window request rate limiter (per key, in-memory, per-process). Complements the
|
|
218
|
-
* per-session TurnLimiter: keying on a stable identity (user id, or client IP) closes the
|
|
219
|
-
* "rotate session_id to bypass" gap. `maxPerWindow <= 0` disables it.
|
|
220
|
-
*/
|
|
221
|
-
class RateLimiter {
|
|
222
|
-
maxPerWindow;
|
|
223
|
-
windowMs;
|
|
224
|
-
hits = new Map();
|
|
225
|
-
/** Cap the key map so a flood of distinct keys can't grow memory unbounded. */
|
|
226
|
-
static MAX_KEYS = 100_000;
|
|
227
|
-
constructor(maxPerWindow, windowMs = 60_000) {
|
|
228
|
-
this.maxPerWindow = maxPerWindow;
|
|
229
|
-
this.windowMs = windowMs;
|
|
230
|
-
}
|
|
231
|
-
/** Returns true if the request is allowed (and records it); false when the window cap is hit. */
|
|
232
|
-
tryConsume(key, now = Date.now()) {
|
|
233
|
-
if (!Number.isFinite(this.maxPerWindow) || this.maxPerWindow <= 0) {
|
|
234
|
-
return true; // disabled
|
|
235
|
-
}
|
|
236
|
-
const entry = this.hits.get(key);
|
|
237
|
-
if (!entry || entry.resetAt <= now) {
|
|
238
|
-
if (this.hits.size >= RateLimiter.MAX_KEYS) {
|
|
239
|
-
this.prune(now);
|
|
240
|
-
}
|
|
241
|
-
this.hits.set(key, { count: 1, resetAt: now + this.windowMs });
|
|
242
|
-
return true;
|
|
243
|
-
}
|
|
244
|
-
if (entry.count >= this.maxPerWindow) {
|
|
245
|
-
return false;
|
|
246
|
-
}
|
|
247
|
-
entry.count += 1;
|
|
248
|
-
return true;
|
|
249
|
-
}
|
|
250
|
-
/** Seconds until the key's window resets — for a Retry-After header. */
|
|
251
|
-
retryAfterSeconds(key, now = Date.now()) {
|
|
252
|
-
const entry = this.hits.get(key);
|
|
253
|
-
if (!entry) {
|
|
254
|
-
return Math.ceil(this.windowMs / 1000);
|
|
255
|
-
}
|
|
256
|
-
return Math.max(1, Math.ceil((entry.resetAt - now) / 1000));
|
|
257
|
-
}
|
|
258
|
-
prune(now) {
|
|
259
|
-
for (const [key, entry] of this.hits) {
|
|
260
|
-
if (entry.resetAt <= now) {
|
|
261
|
-
this.hits.delete(key);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
if (this.hits.size >= RateLimiter.MAX_KEYS) {
|
|
265
|
-
this.hits.clear();
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
exports.RateLimiter = RateLimiter;
|
|
270
|
-
/**
|
|
271
|
-
* Identity headers trusted when NOTHING is pinned.
|
|
272
|
-
*
|
|
273
|
-
* Every entry here is a header that exactly one platform sets AND owns the request path for, so
|
|
274
|
-
* a client-supplied copy cannot reach serve without that platform having been bypassed entirely.
|
|
275
|
-
*
|
|
276
|
-
* `x-agent-user` is deliberately NOT in this list, and this is a breaking change for anything
|
|
277
|
-
* that relied on it being trusted by default. It is AgentHippo's own canonical header — the name
|
|
278
|
-
* an arbitrary client is most likely to guess — it belongs to no platform that strips it, and it
|
|
279
|
-
* used to sit FIRST, so it beat every platform header that follows. The consequence on any
|
|
280
|
-
* deployment that had not pinned `AGENTHIPPO_IDENTITY_HEADER`: any HTTP client could send
|
|
281
|
-
* `x-agent-user: victim@example.com` and be namespaced into that user's session state, attach to
|
|
282
|
-
* their conversation, and be issued a data-plane turn nonce scoped to them. Cloud Run IAP makes
|
|
283
|
-
* this concrete — it strips `X-Goog-*` and forwards a client-supplied `x-agent-user` untouched.
|
|
284
|
-
*
|
|
285
|
-
* It remains perfectly valid as a PINNED header (`AGENTHIPPO_IDENTITY_HEADER=x-agent-user`),
|
|
286
|
-
* which is what a deployment whose proxy really does set and strip it should use — including the
|
|
287
|
-
* Caddy `forward_auth` flow, where `auth-broker/server.ts` sets `X-Agent-User` on `/api/ide/me`
|
|
288
|
-
* so Caddy can copy a VALIDATED identity upstream. That direction is the correct and only source
|
|
289
|
-
* of the header, and it is unaffected: pinning is exactly the declaration that it is trustworthy.
|
|
290
|
-
*/
|
|
291
|
-
const HEADER_ALIASES = [
|
|
292
|
-
'x-forwarded-email', // Databricks Apps
|
|
293
|
-
'x-forwarded-preferred-username', // Databricks Apps
|
|
294
|
-
'x-goog-authenticated-user-email', // Cloud Run IAP (prefixed value, stripped below)
|
|
295
|
-
'cf-access-authenticated-user-email', // Cloudflare Access
|
|
296
|
-
];
|
|
297
|
-
/**
|
|
298
|
-
* Headers that are only ever trusted when explicitly pinned.
|
|
299
|
-
*
|
|
300
|
-
* Kept as a named list rather than deleted, because "why is my identity header ignored?" needs an
|
|
301
|
-
* answer, and `identityHeaderAdvice` gives one that names the env var to set.
|
|
302
|
-
*/
|
|
303
|
-
exports.PIN_ONLY_IDENTITY_HEADERS = ['x-agent-user'];
|
|
304
|
-
/** Env var: pin the single identity header the deploy layer actually sets (and strips). */
|
|
305
|
-
exports.IDENTITY_HEADER_ENV = 'AGENTHIPPO_IDENTITY_HEADER';
|
|
306
|
-
/**
|
|
307
|
-
* Env var: shared secret proving the identity header was set by the trusted proxy, not by
|
|
308
|
-
* something else that can reach serve's port.
|
|
309
|
-
*
|
|
310
|
-
* Pinning declares WHICH header carries identity; it says nothing about WHO may assert it. On a
|
|
311
|
-
* shared network (compose, sidecar platforms where every container shares localhost) any
|
|
312
|
-
* neighbour that can dial serve can send the pinned header and be namespaced as that user —
|
|
313
|
-
* network topology cannot express "the agent may dial the gateway but not the reverse". When
|
|
314
|
-
* this is set, serve honours identity headers only on requests that also carry the matching
|
|
315
|
-
* `x-agenthippo-proxy-secret` (the same proof-of-proxy contract the auth-broker enforces for
|
|
316
|
-
* `X-Auth-Request-Email`); without proof the request runs anonymous, same as an unpinned
|
|
317
|
-
* header. Opt-in: unset keeps today's behaviour, because platform-header deployments (IAP,
|
|
318
|
-
* Databricks Apps) have an unforgeable header and no proxy hop that could attach a secret.
|
|
319
|
-
*/
|
|
320
|
-
exports.IDENTITY_PROXY_SECRET_ENV = 'AGENTHIPPO_IDENTITY_PROXY_SECRET';
|
|
321
|
-
/**
|
|
322
|
-
* Proof that an identity header was set by the trusted proxy and not by a client: the request
|
|
323
|
-
* carries `x-agenthippo-proxy-secret` matching the configured secret. Shared with the
|
|
324
|
-
* auth-broker, which applies the same contract to `X-Auth-Request-Email` (it lives here rather
|
|
325
|
-
* than in the broker because the broker already imports from this module).
|
|
326
|
-
*/
|
|
327
|
-
function hasTrustedProxyProof(headers, expectedSecret) {
|
|
328
|
-
if (!expectedSecret) {
|
|
329
|
-
return false;
|
|
330
|
-
}
|
|
331
|
-
const raw = headers[config_1.AUTH_PROXY_SECRET_HEADER];
|
|
332
|
-
const presented = typeof raw === 'string' ? raw : Array.isArray(raw) ? String(raw[0] ?? '') : '';
|
|
333
|
-
if (!presented) {
|
|
334
|
-
return false;
|
|
335
|
-
}
|
|
336
|
-
// Hash both sides first: timingSafeEqual throws on a length mismatch, which would itself leak
|
|
337
|
-
// the secret's length.
|
|
338
|
-
const a = crypto.createHash('sha256').update(presented).digest();
|
|
339
|
-
const b = crypto.createHash('sha256').update(expectedSecret).digest();
|
|
340
|
-
return crypto.timingSafeEqual(a, b);
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* Boot-time advice about identity trust. Returns the lines serve must print, loudest first.
|
|
344
|
-
*
|
|
345
|
-
* Not a refusal. Refusing to boot without a pin would stop deployments that are configured
|
|
346
|
-
* correctly today (Databricks Apps, Cloudflare Access) and whose platform header is genuinely
|
|
347
|
-
* unforgeable — a fail-closed default that mostly punishes the compliant is not a security win.
|
|
348
|
-
* What was actually dangerous was `x-agent-user` being trusted by default, and that is now gone.
|
|
349
|
-
*/
|
|
350
|
-
function identityHeaderAdvice(env = process.env, bindHost) {
|
|
351
|
-
const pinned = env[exports.IDENTITY_HEADER_ENV]?.trim();
|
|
352
|
-
if (pinned) {
|
|
353
|
-
return [];
|
|
354
|
-
}
|
|
355
|
-
// Severity follows reachability. On loopback nothing off-box can reach the port, so the same
|
|
356
|
-
// paragraph every local run is warning fatigue — and fatigue is why the message gets ignored
|
|
357
|
-
// on the deploy where it decides whether strangers can name themselves as another user.
|
|
358
|
-
const host = bindHost?.trim();
|
|
359
|
-
if (host && isLoopbackHost(host)) {
|
|
360
|
-
return [
|
|
361
|
-
`${exports.IDENTITY_HEADER_ENV} is not set. Fine for this loopback bind; pin it before exposing ` +
|
|
362
|
-
`serve on a network interface.`,
|
|
363
|
-
];
|
|
364
|
-
}
|
|
365
|
-
return [
|
|
366
|
-
...(host
|
|
367
|
-
? [`serve is bound to ${host} — reachable beyond this machine — with no ${exports.IDENTITY_HEADER_ENV} pinned. ` +
|
|
368
|
-
`Anyone who can reach this port is trusted to state who they are.`]
|
|
369
|
-
: []),
|
|
370
|
-
`${exports.IDENTITY_HEADER_ENV} is not set, so identity falls back to the platform header aliases ` +
|
|
371
|
-
`(${HEADER_ALIASES.join(', ')}). That is only safe when your proxy sets AND STRIPS every one of them. ` +
|
|
372
|
-
`Pin the single header your deploy layer really controls, e.g. ${exports.IDENTITY_HEADER_ENV}=x-goog-authenticated-user-email.`,
|
|
373
|
-
`NOTE: ${exports.PIN_ONLY_IDENTITY_HEADERS.join(', ')} is NO LONGER trusted by default — it is not stripped by any ` +
|
|
374
|
-
`platform, so an arbitrary client could send it and be namespaced as another user. If your proxy does set it ` +
|
|
375
|
-
`(the Caddy forward_auth / auth-broker flow does), pin it: ${exports.IDENTITY_HEADER_ENV}=x-agent-user.`,
|
|
376
|
-
];
|
|
377
|
-
}
|
|
378
|
-
/** Env var: turn the tenant-isolation advice below into a boot refusal. */
|
|
379
|
-
exports.REQUIRE_TENANT_ISOLATION_ENV = 'AGENTHIPPO_REQUIRE_TENANT_ISOLATION';
|
|
380
|
-
/** True when `child` is `parent` or sits beneath it. */
|
|
381
|
-
function isWithin(child, parent) {
|
|
382
|
-
const c = path.resolve(child);
|
|
383
|
-
const p = path.resolve(parent);
|
|
384
|
-
return c === p || c.startsWith(p + path.sep);
|
|
385
|
-
}
|
|
386
|
-
/**
|
|
387
|
-
* Boot-time advice about what a second user of this agent can read off the disk.
|
|
388
|
-
*
|
|
389
|
-
* The condition this exists for: a deployment that PINS an identity header has declared it serves
|
|
390
|
-
* more than one person, and a tier-0 (`--sandbox=process`) or sandbox-less serve gives every one
|
|
391
|
-
* of them the same uid, the same workspace and the same state dir. Per-user namespacing —
|
|
392
|
-
* `userScopedEngineHome`'s `users/<hash>`, user-namespaced session keys, per-session analytics
|
|
393
|
-
* JSONL — is naming, not access control: a same-uid process reads its neighbours' names by
|
|
394
|
-
* listing the directory. What sits there is the engines' own session files, i.e. the plaintext of
|
|
395
|
-
* every other user's conversation, including whatever rows the OBO connector correctly scoped to
|
|
396
|
-
* them on the way in. The data path stays isolated and the artifact path undoes it.
|
|
397
|
-
*
|
|
398
|
-
* The nesting check is the sharper half. `--workspace=/state/workspace --state-dir=/state` is the
|
|
399
|
-
* shape the samples shipped, and it puts the artifact store one `..` above the agent's own cwd —
|
|
400
|
-
* so reaching it takes no traversal trick, just a relative path. Unrelated subtrees
|
|
401
|
-
* (`--workspace=/work --state-dir=/state`) do not make a same-uid process unable to read /state;
|
|
402
|
-
* they stop it being the obvious next directory.
|
|
403
|
-
*
|
|
404
|
-
* Warn, not refuse, by default — the shipped samples are in exactly this shape and a fatal check
|
|
405
|
-
* would brick them on upgrade, which is the same trade `identityHeaderAdvice` documents. An
|
|
406
|
-
* operator who has finished the migration sets REQUIRE_TENANT_ISOLATION_ENV and gets the refusal.
|
|
407
|
-
*/
|
|
408
|
-
function tenantIsolationAdvice(input, env = process.env) {
|
|
409
|
-
// Unpinned means serve cannot tell one caller from another at all; identityHeaderAdvice owns
|
|
410
|
-
// that case and saying both at once buries the one the operator can act on.
|
|
411
|
-
if (!env[exports.IDENTITY_HEADER_ENV]?.trim()) {
|
|
412
|
-
return { level: 'ok', lines: [] };
|
|
413
|
-
}
|
|
414
|
-
const perSessionFilesystem = input.sandbox === 'container' && !input.sharedWorkspace;
|
|
415
|
-
if (perSessionFilesystem) {
|
|
416
|
-
return { level: 'ok', lines: [] };
|
|
417
|
-
}
|
|
418
|
-
const tier = input.sandbox === 'process' ? 'a tier-0 (--sandbox=process) sandbox' : 'no sandbox';
|
|
419
|
-
const lines = [
|
|
420
|
-
`${exports.IDENTITY_HEADER_ENV} is pinned — so this serve has more than one user — but it runs with ` +
|
|
421
|
-
`${tier}, which shares one uid, one workspace (${input.workspace ?? 'unset'}) and one state dir ` +
|
|
422
|
-
`(${input.stateDir}) across all of them. Any user can read every other user's engine session ` +
|
|
423
|
-
`files, which hold their conversations verbatim. Per-user paths are namespacing, not isolation.`,
|
|
424
|
-
`The boundary is --sandbox=container (per-session workspace and state, without ` +
|
|
425
|
-
`--shared-workspace) or one serve per tenant. Until then, restrict the pack's tool surface so ` +
|
|
426
|
-
`the agent has no way to read arbitrary files.`,
|
|
427
|
-
];
|
|
428
|
-
if (input.workspace && isWithin(input.workspace, input.stateDir)) {
|
|
429
|
-
lines.push(`--workspace ${input.workspace} sits INSIDE --state-dir ${input.stateDir}: every other ` +
|
|
430
|
-
`user's sessions, analytics and evidence spool are one '..' above the agent's own cwd. ` +
|
|
431
|
-
`Put them in unrelated subtrees (e.g. --workspace=/work --state-dir=/state).`);
|
|
432
|
-
}
|
|
433
|
-
else if (input.workspace && isWithin(input.stateDir, input.workspace)) {
|
|
434
|
-
lines.push(`--state-dir ${input.stateDir} sits INSIDE --workspace ${input.workspace}: every other ` +
|
|
435
|
-
`user's sessions, analytics and evidence spool are inside the directory the agent is ` +
|
|
436
|
-
`pointed at. Put them in unrelated subtrees (e.g. --workspace=/work --state-dir=/state).`);
|
|
437
|
-
}
|
|
438
|
-
const strict = /^(1|true|yes|on)$/i.test(env[exports.REQUIRE_TENANT_ISOLATION_ENV]?.trim() ?? '');
|
|
439
|
-
return { level: strict ? 'refuse' : 'warn', lines };
|
|
440
|
-
}
|
|
441
|
-
/**
|
|
442
|
-
* Resolve the end-user identity for a request.
|
|
443
|
-
*
|
|
444
|
-
* Proxy headers win over the request body. When AGENTHIPPO_IDENTITY_HEADER pins
|
|
445
|
-
* trust to one header, that pin is a hard boundary: if the pinned header is
|
|
446
|
-
* absent, identity resolves to undefined (never the request body) — a deployment
|
|
447
|
-
* that pins a header has declared it has a real proxy-verified identity, so an
|
|
448
|
-
* unauthenticated caller must not be able to name themselves via the client-
|
|
449
|
-
* controlled body. Body fallback is dev/internal convenience for the *unpinned*
|
|
450
|
-
* case only (e.g. direct curl against a local serve with no identity proxy) —
|
|
451
|
-
* and it must be OPTED INTO via AGENTHIPPO_ALLOW_BODY_IDENTITY=1 (serve-v4 §10
|
|
452
|
-
* hole 3). Before the gate it was safe "by convention": any deployment that
|
|
453
|
-
* forgot to pin a header silently let every caller name an arbitrary victim.
|
|
454
|
-
*
|
|
455
|
-
* The alias-list default (used when unpinned) is only safe when the proxy strips
|
|
456
|
-
* or overwrites ALL of the aliases; platforms that strip only their own header
|
|
457
|
-
* (Cloud Run IAP strips `X-Goog-*` but forwards a client-supplied `x-agent-user`
|
|
458
|
-
* untouched, which the alias list checks first) MUST pin theirs — deploy
|
|
459
|
-
* artifacts set it (e.g. cloudrun-deploy.sh pins `x-goog-authenticated-user-email`)
|
|
460
|
-
* so an authenticated caller cannot impersonate another user.
|
|
461
|
-
*
|
|
462
|
-
* Resolves identity for `analyticsUserId` attribution, the request-scoped
|
|
463
|
-
* credential context (per-user data scoping), and the user-namespaced session
|
|
464
|
-
* key (resolveServeSessionKey folds this identity into every session key).
|
|
465
|
-
*
|
|
466
|
-
* Per-turn *data credentials* (OBO token, e.g. X-Forwarded-Access-Token) are
|
|
467
|
-
* handled by resolveDataToken — not read here.
|
|
468
|
-
*/
|
|
469
|
-
function resolveUserId(headers, body, env = process.env) {
|
|
470
|
-
// Proof-of-proxy gate (IDENTITY_PROXY_SECRET_ENV): when configured, no identity — header OR
|
|
471
|
-
// body — is honoured without the matching secret header. A caller that fails this check is
|
|
472
|
-
// by definition not the trusted proxy, so the request runs anonymous rather than letting a
|
|
473
|
-
// network neighbour (or a dev body fallback) name a victim.
|
|
474
|
-
const proxySecret = env[exports.IDENTITY_PROXY_SECRET_ENV]?.trim();
|
|
475
|
-
if (proxySecret && !hasTrustedProxyProof(headers, proxySecret)) {
|
|
476
|
-
return undefined;
|
|
477
|
-
}
|
|
478
|
-
const pinned = env[exports.IDENTITY_HEADER_ENV]?.trim().toLowerCase();
|
|
479
|
-
const names = pinned ? [pinned] : HEADER_ALIASES;
|
|
480
|
-
for (const name of names) {
|
|
481
|
-
const v = headers[name];
|
|
482
|
-
const raw = (Array.isArray(v) ? v[0] : v)?.trim();
|
|
483
|
-
if (raw) {
|
|
484
|
-
// IAP sends "accounts.google.com:user@x.com"; keep the email half.
|
|
485
|
-
const colon = raw.lastIndexOf(':');
|
|
486
|
-
const value = colon >= 0 && raw.slice(colon + 1).includes('@') ? raw.slice(colon + 1) : raw;
|
|
487
|
-
return value;
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
if (pinned) {
|
|
491
|
-
// Pinned but absent: fail closed. Falling back to the body here would let any
|
|
492
|
-
// caller that merely reaches this port (proxy misconfiguration, direct network
|
|
493
|
-
// access, gcloud run services proxy bypassing IAP) name an arbitrary victim.
|
|
494
|
-
return undefined;
|
|
495
|
-
}
|
|
496
|
-
// Unpinned body identity is an explicit opt-in, never a default (§10 hole 3).
|
|
497
|
-
if (env.AGENTHIPPO_ALLOW_BODY_IDENTITY?.trim() !== '1') {
|
|
498
|
-
return undefined;
|
|
499
|
-
}
|
|
500
|
-
const fromBody = body?.user_id?.trim();
|
|
501
|
-
return fromBody || undefined;
|
|
502
|
-
}
|
|
503
|
-
const DATA_TOKEN_HEADERS = [
|
|
504
|
-
'x-forwarded-access-token', // Databricks Apps OBO token
|
|
505
|
-
'x-agent-data-token', // AgentHippo generic per-turn data credential
|
|
506
|
-
];
|
|
507
|
-
/**
|
|
508
|
-
* Resolve the per-turn *data* credential (the OBO token), distinct from the
|
|
509
|
-
* identity in resolveUserId. Fed into the request-scoped credential context so
|
|
510
|
-
* a data tool can act as the asking user. serve-v3 §11.1 (Design B).
|
|
511
|
-
*
|
|
512
|
-
* Like the identity headers, this is trusted unconditionally and is only safe
|
|
513
|
-
* behind a proxy that strips client-supplied copies (see the module SECURITY
|
|
514
|
-
* CONTRACT above).
|
|
515
|
-
*/
|
|
516
|
-
function resolveDataToken(headers) {
|
|
517
|
-
for (const name of DATA_TOKEN_HEADERS) {
|
|
518
|
-
const v = headers[name];
|
|
519
|
-
const raw = (Array.isArray(v) ? v[0] : v)?.trim();
|
|
520
|
-
if (raw) {
|
|
521
|
-
return raw;
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
return undefined;
|
|
525
|
-
}
|
|
526
|
-
/**
|
|
527
|
-
* Map a gateway channel sender (PeerInfo) to a stable `user_id` (serve-v3 §11 / #4).
|
|
528
|
-
* Prefers the stable channel id, namespaced by channel, so the Slack/Telegram
|
|
529
|
-
* sender becomes the user_id that drives per-user attribution and data scoping —
|
|
530
|
-
* extending the per-user-permission wedge to channel surfaces.
|
|
531
|
-
*/
|
|
532
|
-
function peerToUserId(peer) {
|
|
533
|
-
if (!peer) {
|
|
534
|
-
return undefined;
|
|
535
|
-
}
|
|
536
|
-
const id = peer.senderId?.trim() || peer.senderUsername?.trim() || peer.senderName?.trim();
|
|
537
|
-
if (!id) {
|
|
538
|
-
return undefined;
|
|
539
|
-
}
|
|
540
|
-
const channel = peer.channel?.trim();
|
|
541
|
-
return channel ? `${channel}:${id}` : id;
|
|
542
|
-
}
|
|
543
|
-
/** Stable reason code when a session_id is presented without a verified user on a pinned-identity deployment. */
|
|
544
|
-
exports.SESSION_WITHOUT_USER_REASON = 'session_without_verified_user';
|
|
545
|
-
/** Filesystem/S3-safe per-user namespace segment (user ids are emails/subjects — never raw path segments). */
|
|
546
|
-
function userNamespaceHash(userId) {
|
|
547
|
-
return crypto.createHash('sha256').update(userId).digest('hex').slice(0, 16);
|
|
548
|
-
}
|
|
549
|
-
/**
|
|
550
|
-
* Namespace the session key by the verified user (secure-obo-design §3.4 / §8 Phase 0).
|
|
551
|
-
*
|
|
552
|
-
* `session_id` is client-supplied; un-namespaced, any authenticated user who guesses another
|
|
553
|
-
* user's session_id attaches to that session's conversation state (which holds the other
|
|
554
|
-
* user's row-filtered query results). Prefixing the key with a hash of the verified user makes
|
|
555
|
-
* cross-user attachment structurally impossible without changing client behavior.
|
|
556
|
-
*
|
|
557
|
-
* Fail-closed rule: when the deployment pins an identity header (it declared a real
|
|
558
|
-
* proxy-verified identity exists), any turn without a verified user is rejected — with or
|
|
559
|
-
* without a session_id. Rejecting only named sessions would leave every identity-less
|
|
560
|
-
* caller sharing the durable `anon-unknown` conversation state. Unpinned deployments
|
|
561
|
-
* (local dev, no identity boundary at all) keep today's raw-key behavior.
|
|
562
|
-
*/
|
|
563
|
-
function resolveServeSessionKey(sessionId, userId, scope = 'session', env = process.env) {
|
|
564
|
-
const sid = sessionId?.trim();
|
|
565
|
-
const uid = userId?.trim();
|
|
566
|
-
if (uid) {
|
|
567
|
-
const sessionKey = `u${userNamespaceHash(uid)}--${sid || 'default'}`;
|
|
568
|
-
return { sessionKey, sandboxKey: scope === 'user' ? `u${userNamespaceHash(uid)}` : sessionKey };
|
|
569
|
-
}
|
|
570
|
-
if (env[exports.IDENTITY_HEADER_ENV]?.trim()) {
|
|
571
|
-
return { sessionKey: '', sandboxKey: '', rejected: exports.SESSION_WITHOUT_USER_REASON };
|
|
572
|
-
}
|
|
573
|
-
// No verified user, so there is no user to scope a sandbox TO. `user` scope deliberately does
|
|
574
|
-
// not apply here: merging unidentified callers would put two strangers in one sandbox on the
|
|
575
|
-
// strength of a fact nobody established. Local dev keeps one sandbox per session.
|
|
576
|
-
const sessionKey = sid || 'anon-unknown';
|
|
577
|
-
return { sessionKey, sandboxKey: sessionKey };
|
|
578
|
-
}
|
|
579
|
-
/** Build CORS headers. Serve is always behind a proxy; CORS is wide-open here. */
|
|
580
|
-
function corsHeaders() {
|
|
581
|
-
return {
|
|
582
|
-
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
|
583
|
-
'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Agent-User',
|
|
584
|
-
'Access-Control-Allow-Origin': '*',
|
|
585
|
-
};
|
|
586
|
-
}
|
|
587
|
-
/**
|
|
588
|
-
* Per-session turn admission control. Caps the number of turns a single
|
|
589
|
-
* conversation may run (abuse / runaway-loop guard for exposed deployments).
|
|
590
|
-
* In-memory and per-process — sufficient for single-container tiers; a shared
|
|
591
|
-
* store is a later concern.
|
|
592
|
-
*/
|
|
593
|
-
class TurnLimiter {
|
|
594
|
-
maxPerSession;
|
|
595
|
-
counts = new Map();
|
|
596
|
-
constructor(maxPerSession) {
|
|
597
|
-
this.maxPerSession = maxPerSession;
|
|
598
|
-
}
|
|
599
|
-
/** Returns true if the turn is allowed (and records it); false when the cap is exceeded. */
|
|
600
|
-
tryConsume(sessionKey) {
|
|
601
|
-
if (!Number.isFinite(this.maxPerSession) || this.maxPerSession <= 0) {
|
|
602
|
-
return true; // disabled
|
|
603
|
-
}
|
|
604
|
-
const current = this.counts.get(sessionKey) ?? 0;
|
|
605
|
-
if (current >= this.maxPerSession) {
|
|
606
|
-
return false;
|
|
607
|
-
}
|
|
608
|
-
this.counts.set(sessionKey, current + 1);
|
|
609
|
-
return true;
|
|
610
|
-
}
|
|
611
|
-
reset(sessionKey) {
|
|
612
|
-
this.counts.delete(sessionKey);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
exports.TurnLimiter = TurnLimiter;
|
|
616
|
-
/** Env: max concurrent engine turns per process (default 10). `0` disables the gate. */
|
|
617
|
-
exports.MAX_CONCURRENT_TURNS_ENV = 'AGENTHIPPO_MAX_CONCURRENT_TURNS';
|
|
618
|
-
/** Env: bounded FIFO waiter depth when at inflight cap (default 20). */
|
|
619
|
-
exports.TURN_QUEUE_ENV = 'AGENTHIPPO_TURN_QUEUE';
|
|
620
|
-
/** Fixed Retry-After seconds when the turn gate rejects (matches default queue timeout). */
|
|
621
|
-
exports.TURN_GATE_RETRY_AFTER_SECONDS = 15;
|
|
622
|
-
/** User-visible capacity message for gateway channels (Slack/Telegram can't receive HTTP 429). */
|
|
623
|
-
exports.TURN_GATE_BUSY_MESSAGE = 'At capacity — please retry in a moment';
|
|
624
|
-
/** User-visible message for gateway channels when the per-identity RateLimiter rejects. */
|
|
625
|
-
exports.RATE_LIMIT_BUSY_MESSAGE = 'Rate limit exceeded — please retry in a moment';
|
|
626
|
-
/** User-visible message for gateway channels when the per-session TurnLimiter rejects. */
|
|
627
|
-
exports.TURN_LIMIT_BUSY_MESSAGE = 'Per-session turn limit reached';
|
|
628
|
-
/**
|
|
629
|
-
* Process-wide concurrency gate for engine turns (semaphore + bounded FIFO).
|
|
630
|
-
*
|
|
631
|
-
* Caps simultaneous engine subprocesses so a burst cannot OOM the container.
|
|
632
|
-
* `maxInflight <= 0` disables. Waiters time out after `queueTimeoutMs` (burst
|
|
633
|
-
* absorber, not a job queue). Rejected callers get `null` — HTTP maps that to
|
|
634
|
-
* 429 + Retry-After; the gateway path emits a short channel message instead.
|
|
635
|
-
*/
|
|
636
|
-
class TurnGate {
|
|
637
|
-
maxInflight;
|
|
638
|
-
maxQueue;
|
|
639
|
-
queueTimeoutMs;
|
|
640
|
-
inflightCount = 0;
|
|
641
|
-
waiters = [];
|
|
642
|
-
constructor(maxInflight, maxQueue, queueTimeoutMs = exports.TURN_GATE_RETRY_AFTER_SECONDS * 1000) {
|
|
643
|
-
this.maxInflight = maxInflight;
|
|
644
|
-
this.maxQueue = maxQueue;
|
|
645
|
-
this.queueTimeoutMs = queueTimeoutMs;
|
|
646
|
-
}
|
|
647
|
-
/**
|
|
648
|
-
* Acquire a turn slot. Resolves with a `release()` callback, or `null` when
|
|
649
|
-
* the queue is full or the wait timed out. Always call `release()` in a
|
|
650
|
-
* `finally` when non-null.
|
|
651
|
-
*/
|
|
652
|
-
async acquire() {
|
|
653
|
-
if (!Number.isFinite(this.maxInflight) || this.maxInflight <= 0) {
|
|
654
|
-
return () => { };
|
|
655
|
-
}
|
|
656
|
-
if (this.inflightCount < this.maxInflight) {
|
|
657
|
-
this.inflightCount += 1;
|
|
658
|
-
return () => this.releaseSlot();
|
|
659
|
-
}
|
|
660
|
-
if (this.waiters.length >= this.maxQueue) {
|
|
661
|
-
return null;
|
|
662
|
-
}
|
|
663
|
-
return new Promise((resolve) => {
|
|
664
|
-
let settled = false;
|
|
665
|
-
const settle = (release) => {
|
|
666
|
-
if (settled) {
|
|
667
|
-
// Timed out after a slot was already offered — give the slot back.
|
|
668
|
-
if (release) {
|
|
669
|
-
release();
|
|
670
|
-
}
|
|
671
|
-
return;
|
|
672
|
-
}
|
|
673
|
-
settled = true;
|
|
674
|
-
clearTimeout(timer);
|
|
675
|
-
resolve(release);
|
|
676
|
-
};
|
|
677
|
-
const entry = {
|
|
678
|
-
resolve: settle,
|
|
679
|
-
timer: null,
|
|
680
|
-
};
|
|
681
|
-
const timer = setTimeout(() => {
|
|
682
|
-
const idx = this.waiters.indexOf(entry);
|
|
683
|
-
if (idx >= 0) {
|
|
684
|
-
this.waiters.splice(idx, 1);
|
|
685
|
-
}
|
|
686
|
-
settle(null);
|
|
687
|
-
}, this.queueTimeoutMs);
|
|
688
|
-
entry.timer = timer;
|
|
689
|
-
this.waiters.push(entry);
|
|
690
|
-
});
|
|
691
|
-
}
|
|
692
|
-
releaseSlot() {
|
|
693
|
-
const next = this.waiters.shift();
|
|
694
|
-
if (next) {
|
|
695
|
-
// Transfer the slot to the head waiter — do not decrement inflight.
|
|
696
|
-
next.resolve(() => this.releaseSlot());
|
|
697
|
-
return;
|
|
698
|
-
}
|
|
699
|
-
this.inflightCount = Math.max(0, this.inflightCount - 1);
|
|
700
|
-
}
|
|
701
|
-
get inflight() {
|
|
702
|
-
return this.inflightCount;
|
|
703
|
-
}
|
|
704
|
-
get queued() {
|
|
705
|
-
return this.waiters.length;
|
|
706
|
-
}
|
|
707
|
-
get max() {
|
|
708
|
-
return this.maxInflight > 0 ? this.maxInflight : 0;
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
exports.TurnGate = TurnGate;
|
|
712
|
-
/** Build a TurnGate from env (serve-v4 P0.1). Defaults: 10 inflight, 20 queued. */
|
|
713
|
-
function createTurnGateFromEnv(env = process.env) {
|
|
714
|
-
const inflightRaw = Number(env[exports.MAX_CONCURRENT_TURNS_ENV] ?? 10);
|
|
715
|
-
const queueRaw = Number(env[exports.TURN_QUEUE_ENV] ?? 20);
|
|
716
|
-
const maxInflight = Number.isFinite(inflightRaw) ? inflightRaw : 10;
|
|
717
|
-
const maxQueue = Number.isFinite(queueRaw) && queueRaw >= 0 ? queueRaw : 20;
|
|
718
|
-
return new TurnGate(maxInflight, maxQueue);
|
|
719
|
-
}
|
|
720
|
-
/**
|
|
721
|
-
* Rate-limited rejection logger — at most one warn per `intervalMs` so a flood
|
|
722
|
-
* of 429s does not spam the console.
|
|
723
|
-
*/
|
|
724
|
-
function createRejectionWarner(intervalMs = 5_000) {
|
|
725
|
-
let lastAt = 0;
|
|
726
|
-
return (msg) => {
|
|
727
|
-
const now = Date.now();
|
|
728
|
-
if (now - lastAt < intervalMs) {
|
|
729
|
-
return;
|
|
730
|
-
}
|
|
731
|
-
lastAt = now;
|
|
732
|
-
console.warn(msg);
|
|
733
|
-
};
|
|
734
|
-
}
|
|
735
|
-
/**
|
|
736
|
-
* Read a request body with a hard size cap. Past the cap it stops accumulating
|
|
737
|
-
* and rejects with a `tooLarge`-tagged error so the caller can respond 413.
|
|
738
|
-
*
|
|
739
|
-
* Deliberately does NOT destroy the socket here: destroying mid-upload resets
|
|
740
|
-
* the connection before the 413 can flush (the client only ever sees the
|
|
741
|
-
* interim 100-continue). We detach our listeners and let the handler send 413
|
|
742
|
-
* with `Connection: close`. Replaces serve's unbounded body accumulation.
|
|
743
|
-
*/
|
|
744
|
-
function readBodyWithCap(req, maxBytes = exports.DEFAULT_MAX_BODY_BYTES) {
|
|
745
|
-
return new Promise((resolve, reject) => {
|
|
746
|
-
let size = 0;
|
|
747
|
-
const chunks = [];
|
|
748
|
-
const onData = (chunk) => {
|
|
749
|
-
size += chunk.length;
|
|
750
|
-
if (size > maxBytes) {
|
|
751
|
-
cleanup();
|
|
752
|
-
const err = new Error(`Request body exceeds ${maxBytes} bytes`);
|
|
753
|
-
err.tooLarge = true;
|
|
754
|
-
reject(err);
|
|
755
|
-
return;
|
|
756
|
-
}
|
|
757
|
-
chunks.push(chunk);
|
|
758
|
-
};
|
|
759
|
-
const onEnd = () => {
|
|
760
|
-
cleanup();
|
|
761
|
-
resolve(Buffer.concat(chunks).toString('utf8'));
|
|
762
|
-
};
|
|
763
|
-
const onError = (err) => {
|
|
764
|
-
cleanup();
|
|
765
|
-
reject(err);
|
|
766
|
-
};
|
|
767
|
-
const cleanup = () => {
|
|
768
|
-
req.off('data', onData);
|
|
769
|
-
req.off('end', onEnd);
|
|
770
|
-
req.off('error', onError);
|
|
771
|
-
};
|
|
772
|
-
req.on('data', onData);
|
|
773
|
-
req.on('end', onEnd);
|
|
774
|
-
req.on('error', onError);
|
|
775
|
-
});
|
|
776
|
-
}
|