@agenthippo-ai/agenthippo 0.1.0
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/LICENSE +21 -0
- package/bin/agenthippo.js +2 -0
- package/out/agentpack/github.js +547 -0
- package/out/agentpack/index.js +66 -0
- package/out/agentpack/install.js +297 -0
- package/out/agentpack/manager.js +441 -0
- package/out/agentpack/manifest.js +135 -0
- package/out/agentpack/paths.js +475 -0
- package/out/agentpack/publish.js +248 -0
- package/out/agentpack/stores.js +554 -0
- package/out/agentpack/types.js +5 -0
- package/out/analytics/dashboard/artifactManager.js +439 -0
- package/out/analytics/dashboard/fleetDisplayUtils.js +159 -0
- package/out/analytics/dashboard/fleetOrchestrator.js +142 -0
- package/out/analytics/dashboard/fleetRegistry.js +79 -0
- package/out/analytics/dashboard/fleetRowDefaults.js +87 -0
- package/out/analytics/dashboard/fleetScriptAdapter.js +146 -0
- package/out/analytics/dashboard/fleetStatusUtils.js +30 -0
- package/out/analytics/dashboard/fleetTitleUtils.js +68 -0
- package/out/analytics/dashboard/fleetTypes.js +29 -0
- package/out/analytics/dashboard/index.js +17 -0
- package/out/analytics/dashboard/indexingService.js +422 -0
- package/out/analytics/dashboard/localFleetAdapter.js +222 -0
- package/out/analytics/dashboard/performanceMonitor.js +76 -0
- package/out/analytics/dashboard/processManager.js +209 -0
- package/out/analytics/dashboard/provider.js +3885 -0
- package/out/analytics/dashboard/queryRunner.js +994 -0
- package/out/analytics/dashboard/refreshPolicy.js +16 -0
- package/out/analytics/dashboard/scheduledFleetFingerprint.js +22 -0
- package/out/analytics/dashboard/scheduledFleetStorage.js +241 -0
- package/out/analytics/dashboard/scheduledFleetUtils.js +22 -0
- package/out/analytics/dashboard/sessionEventFleetStats.js +118 -0
- package/out/analytics/dashboard/sessionJsonlFleet.js +204 -0
- package/out/analytics/dashboard/teamViewDiscovery.js +106 -0
- package/out/analytics/dashboard/viewsConfigMerge.js +221 -0
- package/out/analytics/dashboard/webview/analytics-panel.html +155 -0
- package/out/analytics/dashboard/webview/codicon.ttf +0 -0
- package/out/analytics/dashboard/webview/index.html +78 -0
- package/out/analytics/dashboard/webview/panel.js +2295 -0
- package/out/analytics/dashboard/webview/runtime-bridge.js +82 -0
- package/out/analytics/dashboard/webview/styles.css +1009 -0
- package/out/analytics/lifecycle.js +43 -0
- package/out/analytics/service.js +1279 -0
- package/out/analytics/sessionEvents.js +231 -0
- package/out/auth/bootstrapApply.js +72 -0
- package/out/auth/brokerClient.js +126 -0
- package/out/auth/callbackUri.js +59 -0
- package/out/auth/callbackUriParse.js +59 -0
- package/out/auth/githubStoreGate.js +70 -0
- package/out/auth/loopbackAuthServer.js +165 -0
- package/out/auth/pkce.js +9 -0
- package/out/auth/provider.js +239 -0
- package/out/auth/sessionStore.js +193 -0
- package/out/auth/signInFlow.js +182 -0
- package/out/auth/types.js +12 -0
- package/out/auth-broker/config.js +62 -0
- package/out/auth-broker/jwt.js +105 -0
- package/out/auth-broker/pkce.js +57 -0
- package/out/auth-broker/server.js +539 -0
- package/out/auth-broker/store.js +273 -0
- package/out/base-prompts/gateway/openclaw-starter.json5 +144 -0
- package/out/base-prompts/gateway/slack-socket-mode-minimal.manifest.json +44 -0
- package/out/base-prompts/mcp-servers/.mcp.json +13 -0
- package/out/base-prompts/mcp-servers/langfuse-analytics/README.md +142 -0
- package/out/base-prompts/mcp-servers/langfuse-analytics/mcp.json +13 -0
- package/out/base-prompts/mcp-servers/langfuse-analytics/package-lock.json +1192 -0
- package/out/base-prompts/mcp-servers/langfuse-analytics/package.json +23 -0
- package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/run-with-env.sh +12 -0
- package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/sdk-test.js +102 -0
- package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/simple-test.js +137 -0
- package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/test-client.js +118 -0
- package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/test-server.js +209 -0
- package/out/base-prompts/mcp-servers/langfuse-analytics/src/client.ts +431 -0
- package/out/base-prompts/mcp-servers/langfuse-analytics/src/index.ts +270 -0
- package/out/base-prompts/mcp-servers/langfuse-analytics/tsconfig.json +18 -0
- package/out/base-prompts/rules/AGENTS.md +204 -0
- package/out/base-prompts/skills/agent-browser/SKILL.md +102 -0
- package/out/base-prompts/skills/agent-builder/SKILL.md +73 -0
- package/out/base-prompts/skills/agent-builder/references/agent-pack.md +63 -0
- package/out/base-prompts/skills/agent-builder/references/crewai.md +66 -0
- package/out/base-prompts/skills/agent-builder/references/langchain.md +60 -0
- package/out/base-prompts/skills/agent-builder/references/raw-sdk.md +73 -0
- package/out/base-prompts/skills/agent-engine-creator/SKILL.md +586 -0
- package/out/base-prompts/skills/agent-engine-installer/SKILL.md +106 -0
- package/out/base-prompts/skills/agent-engine-installer/scripts/install-engine.mjs +259 -0
- package/out/base-prompts/skills/agent-engine-installer/scripts/install-engine.ps1 +189 -0
- package/out/base-prompts/skills/agenthippo-cli/SKILL.md +69 -0
- package/out/base-prompts/skills/agenthippo-cli/scripts/install.sh +63 -0
- package/out/base-prompts/skills/agentpack-creator/SKILL.md +375 -0
- package/out/base-prompts/skills/agentpack-creator/references/agent-templates.md +261 -0
- package/out/base-prompts/skills/agentpack-creator/references/agents-md-guide.md +195 -0
- package/out/base-prompts/skills/agentpack-creator/scripts/init_pack.py +391 -0
- package/out/base-prompts/skills/agentpack-creator/scripts/init_pack_test.py +294 -0
- package/out/base-prompts/skills/agentpack-testbench/SKILL.md +135 -0
- package/out/base-prompts/skills/algorithmic-art/LICENSE.txt +202 -0
- package/out/base-prompts/skills/algorithmic-art/SKILL.md +405 -0
- package/out/base-prompts/skills/algorithmic-art/templates/generator_template.js +223 -0
- package/out/base-prompts/skills/algorithmic-art/templates/viewer.html +599 -0
- package/out/base-prompts/skills/debug-agent/SKILL.md +83 -0
- package/out/base-prompts/skills/desktop-automation/SKILL.md +166 -0
- package/out/base-prompts/skills/desktop-automation/references/agenthippo-ui-recipes.md +441 -0
- package/out/base-prompts/skills/desktop-automation/scripts/windows-desktop-uia.psm1 +280 -0
- package/out/base-prompts/skills/docx/LICENSE.txt +30 -0
- package/out/base-prompts/skills/docx/SKILL.md +197 -0
- package/out/base-prompts/skills/docx/docx-js.md +350 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/mce/mc.xsd +75 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/out/base-prompts/skills/docx/ooxml/scripts/pack.py +159 -0
- package/out/base-prompts/skills/docx/ooxml/scripts/unpack.py +29 -0
- package/out/base-prompts/skills/docx/ooxml/scripts/validate.py +69 -0
- package/out/base-prompts/skills/docx/ooxml/scripts/validation/__init__.py +15 -0
- package/out/base-prompts/skills/docx/ooxml/scripts/validation/base.py +951 -0
- package/out/base-prompts/skills/docx/ooxml/scripts/validation/docx.py +274 -0
- package/out/base-prompts/skills/docx/ooxml/scripts/validation/pptx.py +315 -0
- package/out/base-prompts/skills/docx/ooxml/scripts/validation/redlining.py +279 -0
- package/out/base-prompts/skills/docx/ooxml.md +610 -0
- package/out/base-prompts/skills/docx/scripts/__init__.py +1 -0
- package/out/base-prompts/skills/docx/scripts/document.py +1276 -0
- package/out/base-prompts/skills/docx/scripts/templates/comments.xml +3 -0
- package/out/base-prompts/skills/docx/scripts/templates/commentsExtended.xml +3 -0
- package/out/base-prompts/skills/docx/scripts/templates/commentsExtensible.xml +3 -0
- package/out/base-prompts/skills/docx/scripts/templates/commentsIds.xml +3 -0
- package/out/base-prompts/skills/docx/scripts/templates/people.xml +3 -0
- package/out/base-prompts/skills/docx/scripts/utilities.py +374 -0
- package/out/base-prompts/skills/gateway-outbound/SKILL.md +136 -0
- package/out/base-prompts/skills/mcp-builder/LICENSE.txt +202 -0
- package/out/base-prompts/skills/mcp-builder/SKILL.md +328 -0
- package/out/base-prompts/skills/mcp-builder/reference/evaluation.md +602 -0
- package/out/base-prompts/skills/mcp-builder/reference/mcp_best_practices.md +249 -0
- package/out/base-prompts/skills/mcp-builder/reference/node_mcp_server.md +970 -0
- package/out/base-prompts/skills/mcp-builder/reference/python_mcp_server.md +719 -0
- package/out/base-prompts/skills/mcp-builder/scripts/connections.py +151 -0
- package/out/base-prompts/skills/mcp-builder/scripts/evaluation.py +373 -0
- package/out/base-prompts/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/out/base-prompts/skills/mcp-builder/scripts/requirements.txt +2 -0
- package/out/base-prompts/skills/openclaw/SKILL.md +406 -0
- package/out/base-prompts/skills/openclaw/scripts/run-smoke.sh +61 -0
- package/out/base-prompts/skills/pdf/LICENSE.txt +30 -0
- package/out/base-prompts/skills/pdf/SKILL.md +294 -0
- package/out/base-prompts/skills/pdf/forms.md +205 -0
- package/out/base-prompts/skills/pdf/reference.md +612 -0
- package/out/base-prompts/skills/pdf/scripts/check_bounding_boxes.py +70 -0
- package/out/base-prompts/skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
- package/out/base-prompts/skills/pdf/scripts/check_fillable_fields.py +12 -0
- package/out/base-prompts/skills/pdf/scripts/convert_pdf_to_images.py +35 -0
- package/out/base-prompts/skills/pdf/scripts/create_validation_image.py +41 -0
- package/out/base-prompts/skills/pdf/scripts/extract_form_field_info.py +152 -0
- package/out/base-prompts/skills/pdf/scripts/fill_fillable_fields.py +114 -0
- package/out/base-prompts/skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
- package/out/base-prompts/skills/pptx/LICENSE.txt +30 -0
- package/out/base-prompts/skills/pptx/SKILL.md +484 -0
- package/out/base-prompts/skills/pptx/html2pptx.md +625 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/mce/mc.xsd +75 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/out/base-prompts/skills/pptx/ooxml/scripts/pack.py +159 -0
- package/out/base-prompts/skills/pptx/ooxml/scripts/unpack.py +29 -0
- package/out/base-prompts/skills/pptx/ooxml/scripts/validate.py +69 -0
- package/out/base-prompts/skills/pptx/ooxml/scripts/validation/__init__.py +15 -0
- package/out/base-prompts/skills/pptx/ooxml/scripts/validation/base.py +951 -0
- package/out/base-prompts/skills/pptx/ooxml/scripts/validation/docx.py +274 -0
- package/out/base-prompts/skills/pptx/ooxml/scripts/validation/pptx.py +315 -0
- package/out/base-prompts/skills/pptx/ooxml/scripts/validation/redlining.py +279 -0
- package/out/base-prompts/skills/pptx/ooxml.md +427 -0
- package/out/base-prompts/skills/pptx/scripts/html2pptx.js +984 -0
- package/out/base-prompts/skills/pptx/scripts/inventory.py +1020 -0
- package/out/base-prompts/skills/pptx/scripts/rearrange.py +231 -0
- package/out/base-prompts/skills/pptx/scripts/replace.py +385 -0
- package/out/base-prompts/skills/pptx/scripts/thumbnail.py +450 -0
- package/out/base-prompts/skills/prompt-lab/SKILL.md +149 -0
- package/out/base-prompts/skills/prompt-lab/scripts/query-analytics.sh +2551 -0
- package/out/base-prompts/skills/skill-creator/LICENSE.txt +202 -0
- package/out/base-prompts/skills/skill-creator/SKILL.md +371 -0
- package/out/base-prompts/skills/skill-creator/references/output-patterns.md +82 -0
- package/out/base-prompts/skills/skill-creator/references/workflows.md +28 -0
- package/out/base-prompts/skills/skill-creator/scripts/init_skill.py +303 -0
- package/out/base-prompts/skills/skill-creator/scripts/package_skill.py +110 -0
- package/out/base-prompts/skills/skill-creator/scripts/quick_validate.py +95 -0
- package/out/base-prompts/skills/skill-installer/SKILL.md +251 -0
- package/out/base-prompts/skills/skill-installer/references/store-api.md +219 -0
- package/out/base-prompts/skills/spotlight-dashboard/SKILL.md +83 -0
- package/out/base-prompts/skills/spotlight-insights/SKILL.md +101 -0
- package/out/base-prompts/skills/spotlight-optimize/SKILL.md +93 -0
- package/out/base-prompts/skills/spotlight-optimize/scripts/query-analytics.sh +2551 -0
- package/out/base-prompts/skills/spotlight-query/SKILL.md +314 -0
- package/out/base-prompts/skills/spotlight-query/references/otel-schema.md +163 -0
- package/out/base-prompts/skills/spotlight-query/scripts/query-analytics.sh +2551 -0
- package/out/base-prompts/skills/spotlight-query/scripts/query-analytics.test.sh +744 -0
- package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/sessions/sess-test-1.jsonl +14 -0
- package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/traces/.duckdb-index.json +7 -0
- package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/traces/sample.jsonl +5 -0
- package/out/base-prompts/skills/spotlight-report/SKILL.md +86 -0
- package/out/base-prompts/skills/spotlight-visualize/SKILL.md +92 -0
- package/out/base-prompts/skills/spotlight-visualize/scripts/query-analytics.sh +2551 -0
- package/out/base-prompts/skills/xlsx/LICENSE.txt +30 -0
- package/out/base-prompts/skills/xlsx/SKILL.md +289 -0
- package/out/base-prompts/skills/xlsx/recalc.py +178 -0
- package/out/branding.js +23 -0
- package/out/cli/commands/anywhere.js +66 -0
- package/out/cli/commands/ask.js +243 -0
- package/out/cli/commands/auth-broker.js +24 -0
- package/out/cli/commands/auth.js +219 -0
- package/out/cli/commands/chat.js +354 -0
- package/out/cli/commands/deploy.js +223 -0
- package/out/cli/commands/gateway.js +160 -0
- package/out/cli/commands/pack.js +220 -0
- package/out/cli/commands/probe-custom-engine.js +82 -0
- package/out/cli/commands/serve.js +583 -0
- package/out/cli/commands/store.js +919 -0
- package/out/cli/credential-context.js +113 -0
- package/out/cli/deploy-init.js +2087 -0
- package/out/cli/deps.js +238 -0
- package/out/cli/index.js +390 -0
- package/out/cli/pack-loader.js +376 -0
- package/out/cli/run-custom-engine-runner.js +318 -0
- package/out/cli/runtime.js +409 -0
- package/out/cli/serve-hardening.js +325 -0
- package/out/cli/state-sync.js +135 -0
- package/out/cli/utils.js +220 -0
- package/out/cli/vscode-shim.js +86 -0
- package/out/engines/base.js +159 -0
- package/out/engines/claude.js +1215 -0
- package/out/engines/codex.js +759 -0
- package/out/engines/custom.js +632 -0
- package/out/engines/customEngineIpc.js +95 -0
- package/out/engines/customEngineRunnerEmbed.js +107 -0
- package/out/engines/customRegistry.js +274 -0
- package/out/engines/embeddedCustomEngineRunner.generated.js +9 -0
- package/out/engines/engineApiKey.js +138 -0
- package/out/engines/factory.js +45 -0
- package/out/engines/install.js +372 -0
- package/out/engines/persistentEngineWorker.js +320 -0
- package/out/engines/publish.js +341 -0
- package/out/engines/types.js +17 -0
- package/out/examples/run-headless-repl.js +291 -0
- package/out/examples/run-headless.js +187 -0
- package/out/extension.js +4472 -0
- package/out/gateway/bridge.js +805 -0
- package/out/gateway/cli-agent-id.js +36 -0
- package/out/gateway/client.js +303 -0
- package/out/gateway/client.test.js +395 -0
- package/out/gateway/gateway-scope-errors.js +14 -0
- package/out/gateway/gatewayBackup.js +76 -0
- package/out/gateway/gatewayRouteIndex.js +371 -0
- package/out/gateway/gatewaySessionStore.js +243 -0
- package/out/gateway/index.js +31 -0
- package/out/gateway/lifecycle.js +3056 -0
- package/out/gateway/openclaw-channel-routing.js +317 -0
- package/out/gateway/outboundHandles.js +373 -0
- package/out/gateway/outboundPaths.js +72 -0
- package/out/gateway/outboundSend.js +254 -0
- package/out/gateway/protocol.js +48 -0
- package/out/gateway/resetMappings.js +52 -0
- package/out/gateway/service.js +1244 -0
- package/out/gateway/sessionRouting.js +77 -0
- package/out/headless/index.js +505 -0
- package/out/headless/sync.js +473 -0
- package/out/mcp/publish.js +143 -0
- package/out/mcp.js +597 -0
- package/out/permissions.js +108 -0
- package/out/permissions.mapping.yaml +68 -0
- package/out/registry/index.js +332 -0
- package/out/remote/handleRemoteChat.js +122 -0
- package/out/remote/remotePackStatusBar.js +103 -0
- package/out/remote/serveClient.js +216 -0
- package/out/remoteSkills.js +191 -0
- package/out/runtime/index.js +32 -0
- package/out/runtime/interfaces/config-provider.js +32 -0
- package/out/runtime/interfaces/edit-tracker.js +22 -0
- package/out/runtime/interfaces/index.js +29 -0
- package/out/runtime/interfaces/logger.js +40 -0
- package/out/runtime/interfaces/permission-handler.js +66 -0
- package/out/runtime/interfaces/session-store.js +342 -0
- package/out/runtime/vscode/index.js +20 -0
- package/out/runtime/vscode/vscode-config-provider.js +77 -0
- package/out/runtime/vscode/vscode-edit-tracker.js +120 -0
- package/out/runtime/vscode/vscode-logger.js +30 -0
- package/out/runtime/vscode/vscode-permission-handler.js +72 -0
- package/out/runtime/vscode/vscode-session-store.js +22 -0
- package/out/scripts/agentide-litellm.ps1 +501 -0
- package/out/scripts/agentide-litellm.sh +700 -0
- package/out/scripts/agentide_litellm_hooks_v1.py +604 -0
- package/out/scripts/analytics/agent-fleet-widget.js +954 -0
- package/out/scripts/analytics/agentide-litellm-otel.config.yaml +160 -0
- package/out/scripts/analytics/default-seed-scripts.json +12 -0
- package/out/scripts/analytics/duckdbLocator.js +29 -0
- package/out/scripts/analytics/fleet-local-adapter.js +246 -0
- package/out/scripts/analytics/fleet-workflow.sh +263 -0
- package/out/scripts/analytics/generate-default-charts.py +685 -0
- package/out/scripts/analytics/hotspot-analysis-widget.js +909 -0
- package/out/scripts/analytics/index-traces.py +1394 -0
- package/out/scripts/analytics/install-analytics.sh +286 -0
- package/out/scripts/analytics/live-fleet-4-collector.cjs +315 -0
- package/out/scripts/analytics/live-fleet-4-daemon.mjs +134 -0
- package/out/scripts/analytics/live-fleet-4-widget.cjs +433 -0
- package/out/scripts/analytics/otel-collector.yaml +55 -0
- package/out/scripts/analytics/query-analytics.ps1 +396 -0
- package/out/scripts/analytics/query-analytics.sh +2551 -0
- package/out/scripts/analytics/session-comparison-widget.js +1468 -0
- package/out/scripts/analytics/session-timeline-widget.js +2137 -0
- package/out/scripts/analytics/setup-analytics.ps1 +432 -0
- package/out/scripts/analytics/setup-analytics.sh +854 -0
- package/out/scripts/analytics/start-analytics.ps1 +169 -0
- package/out/scripts/analytics/start-analytics.sh +323 -0
- package/out/scripts/analytics/token-cost-flamegraph-widget.js +954 -0
- package/out/scripts/analytics/token-cost-trend-widget.js +1062 -0
- package/out/scripts/analytics/workflows-collector.cjs +315 -0
- package/out/scripts/analytics/workflows-daemon.mjs +186 -0
- package/out/scripts/analytics/workflows-widget.cjs +433 -0
- package/out/scripts/analytics/wow-model-widget.js +191 -0
- package/out/scripts/gateway/Dockerfile.serve +45 -0
- package/out/scripts/gateway/docker-serve.sh +248 -0
- package/out/scripts/gateway/setup-gateway-server.ps1 +953 -0
- package/out/scripts/gateway/setup-gateway-server.sh +935 -0
- package/out/scripts/gateway/setup-gateway.ps1 +1813 -0
- package/out/scripts/gateway/setup-gateway.sh +1541 -0
- package/out/scripts/setup-cli.ps1 +86 -0
- package/out/scripts/setup-cli.sh +117 -0
- package/out/scripts/tools-manifest.json +83 -0
- package/out/scripts/vendor-tools.mjs +234 -0
- package/out/session.js +272 -0
- package/out/shared/agentEngines.js +170 -0
- package/out/shared/index.js +109 -0
- package/out/shared/models.js +235 -0
- package/out/shared/providers.js +202 -0
- package/out/skills/publish.js +178 -0
- package/out/spotlight/install.js +339 -0
- package/out/spotlight/publish.js +544 -0
- package/out/spotlight/yaml.js +31 -0
- package/out/store/github/setup.js +235 -0
- package/out/store/github/templates/build-index.ts +339 -0
- package/out/store/github/templates/build-index.yml +97 -0
- package/out/store/github/templates/package.json +11 -0
- package/out/store/index.js +755 -0
- package/out/store/oramaIndex.js +884 -0
- package/out/store/shared.js +241 -0
- package/out/sync.js +1827 -0
- package/out/terminalLogger.js +358 -0
- package/out/test/agentEnvFile.test.js +97 -0
- package/out/test/agentYaml.test.js +373 -0
- package/out/test/agentpack.test.js +639 -0
- package/out/test/analytics-lifecycle.test.js +174 -0
- package/out/test/analytics.test.js +524 -0
- package/out/test/auth-bootstrapApply.test.js +102 -0
- package/out/test/auth-broker.test.js +434 -0
- package/out/test/auth-callback.test.js +62 -0
- package/out/test/branding.test.js +229 -0
- package/out/test/cli-agent-id.test.js +55 -0
- package/out/test/credential-context.test.js +105 -0
- package/out/test/customEngineInstall.test.js +100 -0
- package/out/test/customRegistry.test.js +122 -0
- package/out/test/deploy-init.test.js +532 -0
- package/out/test/deps-auto-install.test.js +81 -0
- package/out/test/engine-integration.test.js +297 -0
- package/out/test/enginePaths.test.js +195 -0
- package/out/test/enginePublish.test.js +82 -0
- package/out/test/fleetDisplayUtils.test.js +96 -0
- package/out/test/gateway-client.test.js +381 -0
- package/out/test/gateway-lifecycle.test.js +608 -0
- package/out/test/gateway-outbound.test.js +531 -0
- package/out/test/gateway-reset-mappings.test.js +221 -0
- package/out/test/gateway-route-index.test.js +235 -0
- package/out/test/gateway-session-routing.test.js +47 -0
- package/out/test/gateway-session-store.test.js +216 -0
- package/out/test/github.test.js +232 -0
- package/out/test/headless-sync.test.js +279 -0
- package/out/test/helpers/manifest-fixtures.js +27 -0
- package/out/test/mcp-obo.test.js +82 -0
- package/out/test/mcp.test.js +307 -0
- package/out/test/openclaw-channel-routing.test.js +191 -0
- package/out/test/pathSafety.test.js +63 -0
- package/out/test/permissions.test.js +175 -0
- package/out/test/persistent-engine-worker.test.js +220 -0
- package/out/test/refreshPolicy.test.js +60 -0
- package/out/test/registry.test.js +351 -0
- package/out/test/runtime.test.js +349 -0
- package/out/test/scheduledFleetStorage.test.js +72 -0
- package/out/test/serve-hardening.test.js +192 -0
- package/out/test/serveClient.test.js +173 -0
- package/out/test/sessionJsonlFleet.test.js +78 -0
- package/out/test/shared.test.js +173 -0
- package/out/test/skills-mcp.test.js +299 -0
- package/out/test/spotlightPublish.test.js +299 -0
- package/out/test/spotlightYaml.test.js +58 -0
- package/out/test/state-sync-peer.test.js +74 -0
- package/out/test/store.test.js +331 -0
- package/out/test/stores.test.js +504 -0
- package/out/test/sync-switch.test.js +251 -0
- package/out/test/teamViewDiscovery.test.js +90 -0
- package/out/test/toolPath.test.js +120 -0
- package/out/test/utils.test.js +308 -0
- package/out/test/viewsConfigMerge.test.js +180 -0
- package/out/test/windows-command-line.test.js +75 -0
- package/out/utils/agentEnvFile.js +131 -0
- package/out/utils/binary.js +175 -0
- package/out/utils/index.js +37 -0
- package/out/utils/network.js +74 -0
- package/out/utils/pathSafety.js +60 -0
- package/out/utils/paths.js +116 -0
- package/out/utils/pid.js +180 -0
- package/out/utils/pythonRunner.js +258 -0
- package/out/utils/resolveNodeBinary.js +168 -0
- package/out/utils/toolPath.js +83 -0
- package/out/utils/windowsCommandLine.js +29 -0
- package/out/utils.js +915 -0
- package/out/workspaceFolders.js +59 -0
- package/package.json +41 -0
|
@@ -0,0 +1,1215 @@
|
|
|
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.ClaudeEngine = void 0;
|
|
40
|
+
const fs_1 = require("fs");
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const base_1 = require("./base");
|
|
43
|
+
const utils_1 = require("../utils");
|
|
44
|
+
const permissions_1 = require("../permissions");
|
|
45
|
+
const mcp_1 = require("../mcp");
|
|
46
|
+
const session_1 = require("../session");
|
|
47
|
+
const agentpack_1 = require("../agentpack");
|
|
48
|
+
const shared_1 = require("../shared");
|
|
49
|
+
// File tools we track for edit diffs via hooks (Set for O(1) lookup)
|
|
50
|
+
// Includes Claude SDK tools, Computer Use tools, and common variations
|
|
51
|
+
const FILE_TOOLS = new Set([
|
|
52
|
+
'Write', 'Edit', 'FileEdit', 'FileWrite', 'MultiEdit',
|
|
53
|
+
// Claude Computer Use / text_editor tools
|
|
54
|
+
'str_replace_editor', 'Str_replace_editor', 'TextEditor', 'text_editor',
|
|
55
|
+
// Bash can modify files - track it too
|
|
56
|
+
'Bash', 'bash', 'shell', 'Shell',
|
|
57
|
+
]);
|
|
58
|
+
// -----------------------------------------------------------------------------
|
|
59
|
+
// Constants
|
|
60
|
+
// -----------------------------------------------------------------------------
|
|
61
|
+
const ACTIVE_SESSION_IDLE_TTL_MS = 1000 * 60 * 30; // 30 minutes
|
|
62
|
+
/** Build canUseTool handler: AskUserQuestion → emitter.question (workbench askQuestions); other tools → allow. */
|
|
63
|
+
function buildCanUseTool(emitter, logger) {
|
|
64
|
+
return async (toolName, input) => {
|
|
65
|
+
if (toolName === 'AskUserQuestion') {
|
|
66
|
+
const askInput = input;
|
|
67
|
+
const questions = askInput?.questions ?? [];
|
|
68
|
+
if (questions.length === 0) {
|
|
69
|
+
logger.warn('[AgentIDE] AskUserQuestion with no questions');
|
|
70
|
+
return { behavior: 'allow', updatedInput: { ...askInput, answers: {} } };
|
|
71
|
+
}
|
|
72
|
+
const answers = {};
|
|
73
|
+
for (const q of questions) {
|
|
74
|
+
const payload = {
|
|
75
|
+
questionId: `ask-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
76
|
+
prompt: q.question,
|
|
77
|
+
options: q.options?.map(o => ({ label: o.label, description: o.description })),
|
|
78
|
+
multiSelect: q.multiSelect,
|
|
79
|
+
};
|
|
80
|
+
const answer = await emitter.question(payload);
|
|
81
|
+
if (answer.declined || answer.cancelled) {
|
|
82
|
+
return { behavior: 'deny', message: 'User declined or cancelled the question.' };
|
|
83
|
+
}
|
|
84
|
+
const value = answer.freeText ?? answer.selected.join(', ');
|
|
85
|
+
answers[q.question] = value;
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
behavior: 'allow',
|
|
89
|
+
updatedInput: { questions: askInput.questions, answers },
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Other tools: allow (permission mode / hooks handle approval elsewhere)
|
|
93
|
+
return { behavior: 'allow', updatedInput: input };
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
// Per-process runtime context for agents: lets the agent locate its per-session context export.
|
|
97
|
+
const AGENTIDE_CONTEXT_EXPORT_PATH_ENV_VAR = 'AGENTIDE_CONTEXT_EXPORT_PATH';
|
|
98
|
+
const AGENTIDE_TERMINAL_LOG_PATH_ENV_VAR = 'AGENTIDE_TERMINAL_LOG_PATH';
|
|
99
|
+
// -----------------------------------------------------------------------------
|
|
100
|
+
// Async Queue for Claude Persistent Sessions
|
|
101
|
+
// -----------------------------------------------------------------------------
|
|
102
|
+
function createAsyncQueue() {
|
|
103
|
+
let closed = false;
|
|
104
|
+
const buffer = [];
|
|
105
|
+
const pending = [];
|
|
106
|
+
return {
|
|
107
|
+
enqueue(value) {
|
|
108
|
+
if (closed) {
|
|
109
|
+
throw new Error('Cannot enqueue into a closed queue');
|
|
110
|
+
}
|
|
111
|
+
const next = pending.shift();
|
|
112
|
+
if (next) {
|
|
113
|
+
next({ value, done: false });
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
buffer.push(value);
|
|
117
|
+
},
|
|
118
|
+
close() {
|
|
119
|
+
closed = true;
|
|
120
|
+
while (pending.length) {
|
|
121
|
+
const next = pending.shift();
|
|
122
|
+
next?.({ value: undefined, done: true });
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
[Symbol.asyncIterator]() {
|
|
126
|
+
return {
|
|
127
|
+
next() {
|
|
128
|
+
if (buffer.length) {
|
|
129
|
+
const value = buffer.shift();
|
|
130
|
+
return Promise.resolve({ value, done: false });
|
|
131
|
+
}
|
|
132
|
+
if (closed) {
|
|
133
|
+
return Promise.resolve({ value: undefined, done: true });
|
|
134
|
+
}
|
|
135
|
+
return new Promise(resolve => pending.push(resolve));
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function createClaudePersistentQuerySession(params) {
|
|
142
|
+
const input = createAsyncQueue();
|
|
143
|
+
const abortController = new AbortController();
|
|
144
|
+
const q = params.queryFn({
|
|
145
|
+
prompt: input,
|
|
146
|
+
options: {
|
|
147
|
+
...params.options,
|
|
148
|
+
abortController,
|
|
149
|
+
resume: params.resumeSessionId
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
const iterator = q[Symbol.asyncIterator]();
|
|
153
|
+
let closed = false;
|
|
154
|
+
let sessionId = params.resumeSessionId ?? null;
|
|
155
|
+
return {
|
|
156
|
+
get sessionId() {
|
|
157
|
+
return sessionId;
|
|
158
|
+
},
|
|
159
|
+
async setMaxThinkingTokens(maxThinkingTokens) {
|
|
160
|
+
if (closed) {
|
|
161
|
+
throw new Error('Cannot setMaxThinkingTokens on closed Claude session');
|
|
162
|
+
}
|
|
163
|
+
await q.setMaxThinkingTokens(maxThinkingTokens);
|
|
164
|
+
},
|
|
165
|
+
async interrupt() {
|
|
166
|
+
if (closed) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
await q.interrupt();
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
// Best-effort; caller may fall back to close()
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
async send(message) {
|
|
177
|
+
if (closed) {
|
|
178
|
+
throw new Error('Cannot send to closed Claude session');
|
|
179
|
+
}
|
|
180
|
+
let userMessage;
|
|
181
|
+
if (typeof message === 'string') {
|
|
182
|
+
userMessage = {
|
|
183
|
+
type: 'user',
|
|
184
|
+
session_id: '',
|
|
185
|
+
message: {
|
|
186
|
+
role: 'user',
|
|
187
|
+
content: [{ type: 'text', text: message }]
|
|
188
|
+
},
|
|
189
|
+
parent_tool_use_id: null
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
userMessage = message;
|
|
194
|
+
}
|
|
195
|
+
input.enqueue(userMessage);
|
|
196
|
+
},
|
|
197
|
+
async *receive() {
|
|
198
|
+
while (true) {
|
|
199
|
+
const { value, done } = await iterator.next();
|
|
200
|
+
if (done) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const msg = value;
|
|
204
|
+
if (msg.type === 'system' && msg.subtype === 'init') {
|
|
205
|
+
sessionId = msg.session_id;
|
|
206
|
+
}
|
|
207
|
+
yield msg;
|
|
208
|
+
if (msg.type === 'result') {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
close() {
|
|
214
|
+
if (closed) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
closed = true;
|
|
218
|
+
input.close();
|
|
219
|
+
abortController.abort();
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
// -----------------------------------------------------------------------------
|
|
224
|
+
// Claude Provider
|
|
225
|
+
// -----------------------------------------------------------------------------
|
|
226
|
+
class ClaudeEngine {
|
|
227
|
+
config;
|
|
228
|
+
computeAgentideSignature;
|
|
229
|
+
getBundledBasePromptsDir;
|
|
230
|
+
id = 'claude';
|
|
231
|
+
displayName = 'Claude';
|
|
232
|
+
activeSessions = new Map();
|
|
233
|
+
constructor(config, computeAgentideSignature, getBundledBasePromptsDir) {
|
|
234
|
+
this.config = config;
|
|
235
|
+
this.computeAgentideSignature = computeAgentideSignature;
|
|
236
|
+
this.getBundledBasePromptsDir = getBundledBasePromptsDir;
|
|
237
|
+
}
|
|
238
|
+
async stream(message, options, emitter, runtime, signal) {
|
|
239
|
+
// Use logger from runtime context
|
|
240
|
+
const logger = runtime.logger;
|
|
241
|
+
// Edit tracker from runtime context (optional)
|
|
242
|
+
const editTracker = runtime.editTracker;
|
|
243
|
+
// Resolve API routing (LiteLLM proxy vs direct Anthropic)
|
|
244
|
+
const { apiKey, baseUrl, useLiteLLM } = (0, utils_1.resolveApiRouting)(options, this.config.litellmApiKey, this.config.litellmBaseUrl);
|
|
245
|
+
if (!apiKey) {
|
|
246
|
+
throw new Error('Claude API key not provided');
|
|
247
|
+
}
|
|
248
|
+
logger.info(`[AgentIDE] Claude using ${useLiteLLM ? 'LiteLLM proxy' : 'direct Anthropic'}, baseUrl: ${baseUrl || 'default'}, workspaceRoot=${options.workspaceRoot}, additionalDirs=${options.additionalDirectories?.length ?? 0}`);
|
|
249
|
+
await emitter.progress('Thinking...');
|
|
250
|
+
// Build LiteLLM metadata headers for OTEL analytics.
|
|
251
|
+
// Use requestId from options (generated by caller) for Layer 1/Layer 2 correlation.
|
|
252
|
+
const litellmMetadataHeaders = (0, base_1.buildLiteLLMMetadataHeaders)(useLiteLLM, {
|
|
253
|
+
sessionId: options.sessionId,
|
|
254
|
+
analyticsUserId: options.analyticsUserId,
|
|
255
|
+
analyticsProjectId: (0, base_1.resolveAnalyticsProjectId)(options.analyticsProjectId, options.workspaceRoot),
|
|
256
|
+
agentId: options.agentPackId ?? 'default',
|
|
257
|
+
agentVersion: options.agentPackVersion ?? 'workspace',
|
|
258
|
+
source: 'agenthippo',
|
|
259
|
+
engine: 'claude',
|
|
260
|
+
requestId: options.requestId,
|
|
261
|
+
});
|
|
262
|
+
// Build environment for Claude SDK.
|
|
263
|
+
// Setup-token auth must use Claude's OAuth token env var instead of ANTHROPIC_API_KEY.
|
|
264
|
+
const claudeEnv = {
|
|
265
|
+
...process.env,
|
|
266
|
+
...(runtime.cliEnvPatch ?? {}),
|
|
267
|
+
'DEBUG_CLAUDE_AGENT_SDK': '1',
|
|
268
|
+
'CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC': '1',
|
|
269
|
+
};
|
|
270
|
+
const isSetupTokenAuth = (0, shared_1.isAnthropicSetupToken)(apiKey);
|
|
271
|
+
if (isSetupTokenAuth) {
|
|
272
|
+
const normalizedSetupToken = (0, shared_1.normalizeAnthropicSetupToken)(apiKey);
|
|
273
|
+
claudeEnv['CLAUDE_CODE_OAUTH_TOKEN'] = normalizedSetupToken;
|
|
274
|
+
// Important: do NOT also set ANTHROPIC_AUTH_TOKEN here.
|
|
275
|
+
// The Claude SDK prioritizes ANTHROPIC_AUTH_TOKEN over CLAUDE_CODE_OAUTH_TOKEN.
|
|
276
|
+
// Setting both can force the wrong auth path and yield 401 Invalid bearer token.
|
|
277
|
+
delete claudeEnv['ANTHROPIC_AUTH_TOKEN'];
|
|
278
|
+
delete claudeEnv['ANTHROPIC_API_KEY'];
|
|
279
|
+
logger.info('[AgentIDE] Claude using setup-token auth (CLAUDE_CODE_OAUTH_TOKEN)');
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
claudeEnv['ANTHROPIC_API_KEY'] = apiKey;
|
|
283
|
+
claudeEnv['ANTHROPIC_AUTH_TOKEN'] = apiKey;
|
|
284
|
+
delete claudeEnv['CLAUDE_CODE_OAUTH_TOKEN'];
|
|
285
|
+
}
|
|
286
|
+
// Expose the VS Code chat session id to the agent process so it can locate:
|
|
287
|
+
// .agentide/sessions/<sessionId>/context.md
|
|
288
|
+
const rawChatSessionId = options.sessionId?.trim();
|
|
289
|
+
const contextSessionId = options.contextSessionId?.trim() || rawChatSessionId;
|
|
290
|
+
if (contextSessionId) {
|
|
291
|
+
claudeEnv[AGENTIDE_CONTEXT_EXPORT_PATH_ENV_VAR] = path.join(options.workspaceRoot, agentpack_1.AGENT_CONSTANTS.AGENTIDE_DIR_NAME, 'sessions', contextSessionId, 'context.md');
|
|
292
|
+
claudeEnv[AGENTIDE_TERMINAL_LOG_PATH_ENV_VAR] = path.join(options.workspaceRoot, agentpack_1.AGENT_CONSTANTS.AGENTIDE_DIR_NAME, 'sessions', contextSessionId, 'terminal.md');
|
|
293
|
+
}
|
|
294
|
+
// Resolve runtime paths for config directories (agent-isolated)
|
|
295
|
+
// Note: cwd is ALWAYS workspaceRoot - active agent content is synced to workspace's .claude/.codex
|
|
296
|
+
const agentId = options.agentPackId ?? 'default';
|
|
297
|
+
const runtimePaths = (0, agentpack_1.resolveRuntimePaths)(options.workspaceRoot, this.config.storagePath, agentId, options.agentPackVersion);
|
|
298
|
+
// Claude config directory (isolated per agent for session/state isolation)
|
|
299
|
+
const claudeConfigDir = runtimePaths.claudeConfigDir;
|
|
300
|
+
claudeEnv['CLAUDE_CONFIG_DIR'] = claudeConfigDir;
|
|
301
|
+
await fs_1.promises.mkdir(claudeConfigDir, { recursive: true });
|
|
302
|
+
// Always set AGENT_ID for agent to know its identity
|
|
303
|
+
claudeEnv['AGENT_ID'] = agentId;
|
|
304
|
+
if (options.agentPackVersion) {
|
|
305
|
+
claudeEnv['AGENTIDE_AGENT_VERSION'] = options.agentPackVersion;
|
|
306
|
+
}
|
|
307
|
+
if (agentId !== 'default') {
|
|
308
|
+
logger.info(`[AgentIDE] Claude using agent: ${agentId}, CLAUDE_CONFIG_DIR=${claudeConfigDir} (agent-isolated)`);
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
logger.info(`[AgentIDE] Claude using default agent, CLAUDE_CONFIG_DIR=${claudeConfigDir}`);
|
|
312
|
+
}
|
|
313
|
+
if (litellmMetadataHeaders.length > 0) {
|
|
314
|
+
claudeEnv['ANTHROPIC_CUSTOM_HEADERS'] = litellmMetadataHeaders.join('\n');
|
|
315
|
+
}
|
|
316
|
+
// Only set ANTHROPIC_BASE_URL if using a custom endpoint (not direct Anthropic API).
|
|
317
|
+
// The default Anthropic endpoint is https://api.anthropic.com/v1 - don't override for that.
|
|
318
|
+
const DEFAULT_ANTHROPIC_ENDPOINT = 'https://api.anthropic.com/v1';
|
|
319
|
+
const isCustomEndpoint = baseUrl && baseUrl !== DEFAULT_ANTHROPIC_ENDPOINT;
|
|
320
|
+
if (isCustomEndpoint) {
|
|
321
|
+
// The Anthropic SDK always appends /v1/messages to ANTHROPIC_BASE_URL, so strip any
|
|
322
|
+
// trailing /v1 to avoid a doubled /v1/v1/messages path. Applies to all custom
|
|
323
|
+
// endpoints (OpenRouter, local gateways, etc.); direct Anthropic is excluded above.
|
|
324
|
+
let anthropicBaseUrl = baseUrl.endsWith('/v1')
|
|
325
|
+
? baseUrl.slice(0, -3)
|
|
326
|
+
: baseUrl;
|
|
327
|
+
claudeEnv['ANTHROPIC_BASE_URL'] = anthropicBaseUrl;
|
|
328
|
+
logger.info(`[AgentIDE] Using custom Anthropic base URL: ${anthropicBaseUrl}`);
|
|
329
|
+
if ((0, utils_1.applyLocalTlsBypass)(claudeEnv, anthropicBaseUrl)) {
|
|
330
|
+
logger.info('[AgentIDE] Disabling TLS verification for local HTTPS');
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
const modelName = options.modelId;
|
|
334
|
+
if (!modelName) {
|
|
335
|
+
throw new Error('Claude modelId not provided for streaming request');
|
|
336
|
+
}
|
|
337
|
+
logger.info(`[AgentIDE] Using Claude model: ${modelName}`);
|
|
338
|
+
let streamedTextBuffer = '';
|
|
339
|
+
const emitUniqueMarkdown = async (text) => {
|
|
340
|
+
if (!text) {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
const bufLen = streamedTextBuffer.length;
|
|
344
|
+
const textLen = text.length;
|
|
345
|
+
if (bufLen === 0) {
|
|
346
|
+
streamedTextBuffer = text;
|
|
347
|
+
await emitter.text(text);
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
if (textLen === bufLen) {
|
|
351
|
+
if (text === streamedTextBuffer) {
|
|
352
|
+
logger.debug('[AgentIDE] Claude: exact duplicate, skipping');
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
else if (textLen > bufLen) {
|
|
357
|
+
if (text.startsWith(streamedTextBuffer)) {
|
|
358
|
+
const remainder = text.slice(bufLen);
|
|
359
|
+
streamedTextBuffer = text;
|
|
360
|
+
logger.debug(`[AgentIDE] Claude: emitting remainder (${remainder.length} chars)`);
|
|
361
|
+
await emitter.text(remainder);
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
if (streamedTextBuffer.endsWith(text)) {
|
|
367
|
+
logger.debug('[AgentIDE] Claude: suffix already streamed, skipping');
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
streamedTextBuffer = text;
|
|
372
|
+
await emitter.text(text);
|
|
373
|
+
};
|
|
374
|
+
const convo = (0, session_1.buildConversationKey)('claude', options);
|
|
375
|
+
logger.info(`[AgentIDE] Claude conversationKey=${convo.key} (chatSessionId=${convo.chatSessionId}, signature=${convo.signatureHash}${convo.isEphemeral ? ', ephemeral' : ''})`);
|
|
376
|
+
await (0, session_1.withConversationLock)(convo.key, async () => {
|
|
377
|
+
// Get engine settings from runtime config provider or VS Code
|
|
378
|
+
const engineSettings = (0, utils_1.getAgentideEngineSettings)(runtime?.configProvider);
|
|
379
|
+
const maxThinkingTokens = (typeof engineSettings.claudeMaxThinkingTokens === 'number' && engineSettings.claudeMaxThinkingTokens > 0)
|
|
380
|
+
? Math.floor(engineSettings.claudeMaxThinkingTokens)
|
|
381
|
+
: null;
|
|
382
|
+
logger.debug(`[AgentIDE] Claude maxThinkingTokens=${maxThinkingTokens ?? 'default/disabled'}`);
|
|
383
|
+
const cheapModel = (engineSettings.claudeCheapModel || '').trim();
|
|
384
|
+
if (cheapModel) {
|
|
385
|
+
// Route Claude's lightweight/background model usage (including subagents) to a cheaper model.
|
|
386
|
+
claudeEnv['ANTHROPIC_DEFAULT_HAIKU_MODEL'] = cheapModel;
|
|
387
|
+
claudeEnv['CLAUDE_CODE_SUBAGENT_MODEL'] = cheapModel;
|
|
388
|
+
logger.debug(`[AgentIDE] Claude cheapModel=${cheapModel}`);
|
|
389
|
+
}
|
|
390
|
+
// Resolve unified permissions (from manifest via options, or defaults)
|
|
391
|
+
const effectivePerms = options.permissions ?? permissions_1.DEFAULT_PERMISSIONS;
|
|
392
|
+
logger.debug(`[AgentIDE] Claude permissions: fileAccess=${effectivePerms.fileAccess}`);
|
|
393
|
+
// Build workspace folders list for permission mapping
|
|
394
|
+
const workspaceFolders = (0, utils_1.stableAdditionalDirs)([
|
|
395
|
+
options.workspaceRoot,
|
|
396
|
+
...(options.additionalDirectories ?? []),
|
|
397
|
+
]);
|
|
398
|
+
// Map unified permissions to Claude SDK options
|
|
399
|
+
const claudePermOpts = (0, permissions_1.toClaudeOptions)(effectivePerms, workspaceFolders);
|
|
400
|
+
logger.debug(`[AgentIDE] Claude mapped: permissionMode=${claudePermOpts.permissionMode}, allowDangerouslySkipPermissions=${claudePermOpts.allowDangerouslySkipPermissions}, dirs=${claudePermOpts.additionalDirectories?.length ?? 'undefined'}`);
|
|
401
|
+
// Build additional directories for tool access
|
|
402
|
+
// Always include workspace root and config dir
|
|
403
|
+
const claudeToolDirectories = (0, utils_1.stableAdditionalDirs)([
|
|
404
|
+
...(claudePermOpts.additionalDirectories ?? []),
|
|
405
|
+
claudeConfigDir,
|
|
406
|
+
]);
|
|
407
|
+
const agentideSignature = await this.computeAgentideSignature(options.workspaceRoot, options.additionalDirectories);
|
|
408
|
+
const rawChatSessionId = options.sessionId;
|
|
409
|
+
const workspaceRoot = options.workspaceRoot;
|
|
410
|
+
// Mutable container for edit state - populated after session is obtained.
|
|
411
|
+
// Using a container object avoids repeated Map lookups in hot-path hooks.
|
|
412
|
+
const editStateRef = { current: null };
|
|
413
|
+
// Git commands don't modify file content - skip tracking them
|
|
414
|
+
const isGitCommand = (command) => {
|
|
415
|
+
const trimmed = command.trim();
|
|
416
|
+
// Match git commands at start, or after && or ; or |
|
|
417
|
+
return /(?:^|&&|\||;)\s*git\s+/.test(trimmed);
|
|
418
|
+
};
|
|
419
|
+
// Extract files from tool input based on tool type
|
|
420
|
+
const getFilesFromToolInput = (toolName, toolInput) => {
|
|
421
|
+
const input = toolInput;
|
|
422
|
+
if (!input) {
|
|
423
|
+
return [];
|
|
424
|
+
}
|
|
425
|
+
if (toolName === 'Bash') {
|
|
426
|
+
const command = input.command;
|
|
427
|
+
if (!command) {
|
|
428
|
+
return [];
|
|
429
|
+
}
|
|
430
|
+
// Skip git commands - they don't modify file content
|
|
431
|
+
if (isGitCommand(command)) {
|
|
432
|
+
return [];
|
|
433
|
+
}
|
|
434
|
+
return (0, utils_1.extractFilePaths)(command, workspaceRoot);
|
|
435
|
+
}
|
|
436
|
+
// File tools (Write, Edit, etc.) have file_path or path
|
|
437
|
+
const filePath = (input.file_path ?? input.path);
|
|
438
|
+
if (!filePath) {
|
|
439
|
+
return [];
|
|
440
|
+
}
|
|
441
|
+
const absPath = path.isAbsolute(filePath) ? filePath : path.join(workspaceRoot, filePath);
|
|
442
|
+
return [absPath];
|
|
443
|
+
};
|
|
444
|
+
// Cached return value to avoid object allocation on every call
|
|
445
|
+
const CONTINUE = { continue: true };
|
|
446
|
+
// PreToolUse hook: snapshot files BEFORE tool modifies them
|
|
447
|
+
// MUST await startTracking so opId is available for PostToolUse
|
|
448
|
+
const preToolUseHook = async (input, toolUseID, _options) => {
|
|
449
|
+
try {
|
|
450
|
+
logger.debug(`[AgentIDE] PreToolUse hook called: toolUseID=${toolUseID}, event=${input.hook_event_name}`);
|
|
451
|
+
const state = editStateRef.current;
|
|
452
|
+
if (!state) {
|
|
453
|
+
logger.debug(`[AgentIDE] PreToolUse: no edit state`);
|
|
454
|
+
return CONTINUE;
|
|
455
|
+
}
|
|
456
|
+
if (state.aborted) {
|
|
457
|
+
logger.debug(`[AgentIDE] PreToolUse: aborted`);
|
|
458
|
+
return CONTINUE;
|
|
459
|
+
}
|
|
460
|
+
if (input.hook_event_name !== 'PreToolUse') {
|
|
461
|
+
logger.debug(`[AgentIDE] PreToolUse: wrong event ${input.hook_event_name}`);
|
|
462
|
+
return CONTINUE;
|
|
463
|
+
}
|
|
464
|
+
if (!rawChatSessionId) {
|
|
465
|
+
logger.debug(`[AgentIDE] PreToolUse: no rawChatSessionId`);
|
|
466
|
+
return CONTINUE;
|
|
467
|
+
}
|
|
468
|
+
if (!editTracker) {
|
|
469
|
+
logger.debug(`[AgentIDE] PreToolUse: no edit tracker available`);
|
|
470
|
+
return CONTINUE;
|
|
471
|
+
}
|
|
472
|
+
const toolName = input.tool_name;
|
|
473
|
+
if (!FILE_TOOLS.has(toolName)) {
|
|
474
|
+
logger.debug(`[AgentIDE] PreToolUse: tool ${toolName} not tracked (not in FILE_TOOLS)`);
|
|
475
|
+
return CONTINUE;
|
|
476
|
+
}
|
|
477
|
+
const toolUseId = input.tool_use_id;
|
|
478
|
+
const files = getFilesFromToolInput(toolName, input.tool_input).filter(f => !(0, utils_1.isBinaryFile)(f));
|
|
479
|
+
logger.debug(`[AgentIDE] PreToolUse: ${toolName} files=${files.length}: ${files.join(', ')}`);
|
|
480
|
+
if (files.length === 0) {
|
|
481
|
+
return CONTINUE;
|
|
482
|
+
}
|
|
483
|
+
// Start edit tracking via abstracted interface
|
|
484
|
+
logger.debug(`[AgentIDE] PreToolUse: calling startTracking for ${files.length} files`);
|
|
485
|
+
try {
|
|
486
|
+
const result = await editTracker.startTracking(rawChatSessionId, files);
|
|
487
|
+
if (result?.operationId !== undefined && state && !state.aborted) {
|
|
488
|
+
logger.debug(`[AgentIDE] PreToolUse: startTracking returned opId=${result.operationId}`);
|
|
489
|
+
state.pendingOperations.set(toolUseId, result.operationId);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
catch (e) {
|
|
493
|
+
logger.warn(`[AgentIDE] PreToolUse: startTracking failed: ${e}`);
|
|
494
|
+
// Continue without edit tracking - agent should still work
|
|
495
|
+
}
|
|
496
|
+
return CONTINUE;
|
|
497
|
+
}
|
|
498
|
+
catch (e) {
|
|
499
|
+
logger.error(`[AgentIDE] PreToolUse hook EXCEPTION`, e instanceof Error ? e : undefined);
|
|
500
|
+
return CONTINUE;
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
// PostToolUse hook: compute diffs AFTER tool completes
|
|
504
|
+
// MUST await stopTracking to compute diffs
|
|
505
|
+
const postToolUseHook = async (input, toolUseID, _options) => {
|
|
506
|
+
try {
|
|
507
|
+
logger.debug(`[AgentIDE] PostToolUse hook called: toolUseID=${toolUseID}, event=${input.hook_event_name}`);
|
|
508
|
+
const state = editStateRef.current;
|
|
509
|
+
if (!state || state.aborted || input.hook_event_name !== 'PostToolUse' || !rawChatSessionId) {
|
|
510
|
+
return CONTINUE;
|
|
511
|
+
}
|
|
512
|
+
if (!editTracker) {
|
|
513
|
+
return CONTINUE;
|
|
514
|
+
}
|
|
515
|
+
const toolUseId = input.tool_use_id;
|
|
516
|
+
if (!toolUseId) {
|
|
517
|
+
return CONTINUE;
|
|
518
|
+
}
|
|
519
|
+
const opId = state.pendingOperations.get(toolUseId);
|
|
520
|
+
logger.debug(`[AgentIDE] PostToolUse: toolUseId=${toolUseId} opId=${opId}`);
|
|
521
|
+
if (opId !== undefined) {
|
|
522
|
+
state.pendingOperations.delete(toolUseId); // Delete early to prevent double-stop
|
|
523
|
+
try {
|
|
524
|
+
await editTracker.stopTracking(rawChatSessionId, opId);
|
|
525
|
+
logger.debug(`[AgentIDE] PostToolUse: stopTracking done`);
|
|
526
|
+
}
|
|
527
|
+
catch (e) {
|
|
528
|
+
logger.warn(`[AgentIDE] PostToolUse: stopTracking failed: ${e}`);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return CONTINUE;
|
|
532
|
+
}
|
|
533
|
+
catch (e) {
|
|
534
|
+
logger.error(`[AgentIDE] PostToolUse hook EXCEPTION`, e instanceof Error ? e : undefined);
|
|
535
|
+
return CONTINUE;
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
logger.debug(`[AgentIDE] Setting up Claude hooks for session ${rawChatSessionId}`);
|
|
539
|
+
// Test hook to verify hooks work at all
|
|
540
|
+
const sessionStartHook = async (input, _toolUseID, _options) => {
|
|
541
|
+
logger.debug(`[AgentIDE] SessionStart hook called! event=${input.hook_event_name}`);
|
|
542
|
+
return CONTINUE;
|
|
543
|
+
};
|
|
544
|
+
// Load MCP servers for the active agent and pass directly to SDK
|
|
545
|
+
const mcpServers = await this.loadMcpServersForClaude(logger, options.workspaceRoot, agentId);
|
|
546
|
+
// Determine cwd and settingSources
|
|
547
|
+
// cwd is ALWAYS workspaceRoot - active agent content has been synced to workspace's .claude/
|
|
548
|
+
// Agent packs: settingSources is 'project' only (no user ~/.claude/ mixing)
|
|
549
|
+
// Default agent: settingSources includes 'user' and 'project'
|
|
550
|
+
const queryCwd = options.workspaceRoot;
|
|
551
|
+
const querySettingSources = agentId !== 'default'
|
|
552
|
+
? ['project'] // Agent pack: only pack's synced .claude/ settings, no ~/.claude/
|
|
553
|
+
: ['user', 'project']; // Default agent: inherit from user + project
|
|
554
|
+
// When using bypassPermissions, allowDangerouslySkipPermissions must be true
|
|
555
|
+
// Otherwise the SDK will still prompt for permissions
|
|
556
|
+
const skipPermissions = claudePermOpts.allowDangerouslySkipPermissions === true ? true : undefined;
|
|
557
|
+
const queryOptions = {
|
|
558
|
+
model: modelName,
|
|
559
|
+
cwd: queryCwd,
|
|
560
|
+
additionalDirectories: claudeToolDirectories,
|
|
561
|
+
settingSources: querySettingSources,
|
|
562
|
+
env: claudeEnv,
|
|
563
|
+
// Use mapped permissions from unified AgentPermissions
|
|
564
|
+
permissionMode: claudePermOpts.permissionMode,
|
|
565
|
+
allowDangerouslySkipPermissions: skipPermissions,
|
|
566
|
+
includePartialMessages: true,
|
|
567
|
+
persistSession: true,
|
|
568
|
+
...(maxThinkingTokens ? { maxThinkingTokens } : {}),
|
|
569
|
+
...(Object.keys(mcpServers).length > 0 ? { mcpServers } : {}),
|
|
570
|
+
// Path to Claude Code CLI (for headless mode when bundled)
|
|
571
|
+
...(this.config.claudeCodeExecutablePath ? { pathToClaudeCodeExecutable: this.config.claudeCodeExecutablePath } : {}),
|
|
572
|
+
// AskUserQuestion → emitter.question (workbench askQuestions); other tools → allow
|
|
573
|
+
canUseTool: buildCanUseTool(emitter, logger),
|
|
574
|
+
// Hooks for tracking file modifications (edit diffs) - fire-and-forget, zero agent impact
|
|
575
|
+
hooks: {
|
|
576
|
+
SessionStart: [{ hooks: [sessionStartHook] }],
|
|
577
|
+
PreToolUse: [{ hooks: [preToolUseHook] }],
|
|
578
|
+
PostToolUse: [{ hooks: [postToolUseHook] }],
|
|
579
|
+
},
|
|
580
|
+
stderr: (line) => {
|
|
581
|
+
logger.debug(`[AgentIDE] Claude CLI stderr: ${line}`);
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
const sessionEntry = await this.getOrCreateSession({
|
|
585
|
+
conversationKey: convo.key,
|
|
586
|
+
chatSessionId: convo.chatSessionId,
|
|
587
|
+
signatureHash: convo.signatureHash,
|
|
588
|
+
signatureRaw: convo.signatureRaw,
|
|
589
|
+
agentideSignature,
|
|
590
|
+
isEphemeral: convo.isEphemeral,
|
|
591
|
+
modelId: modelName,
|
|
592
|
+
cheapModel: cheapModel || undefined,
|
|
593
|
+
queryOptions,
|
|
594
|
+
logger
|
|
595
|
+
});
|
|
596
|
+
const session = sessionEntry.session;
|
|
597
|
+
const editState = sessionEntry.editTrackingState;
|
|
598
|
+
// Populate the ref so hooks can access the edit state without Map lookups
|
|
599
|
+
editStateRef.current = editState;
|
|
600
|
+
let aborted = false;
|
|
601
|
+
const onAbort = () => {
|
|
602
|
+
aborted = true;
|
|
603
|
+
editState.aborted = true; // Signal hooks to stop
|
|
604
|
+
// Clean up any pending edit operations - release locks so future turns don't deadlock
|
|
605
|
+
const pendingOpIds = Array.from(editState.pendingOperations.values());
|
|
606
|
+
editState.pendingOperations.clear();
|
|
607
|
+
if (rawChatSessionId && pendingOpIds.length > 0 && editTracker) {
|
|
608
|
+
for (const opId of pendingOpIds) {
|
|
609
|
+
void editTracker.stopTracking(rawChatSessionId, opId).catch(() => { });
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
logger.info('[AgentIDE] Claude cancel requested; interrupting session...');
|
|
613
|
+
// Best-effort: interrupt the current turn but keep the persistent session alive.
|
|
614
|
+
// Fall back to closing the session if interrupt fails.
|
|
615
|
+
void session.interrupt().catch(() => {
|
|
616
|
+
try {
|
|
617
|
+
session.close();
|
|
618
|
+
}
|
|
619
|
+
catch {
|
|
620
|
+
// ignore
|
|
621
|
+
}
|
|
622
|
+
});
|
|
623
|
+
};
|
|
624
|
+
if (signal?.aborted) {
|
|
625
|
+
onAbort();
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
629
|
+
try {
|
|
630
|
+
try {
|
|
631
|
+
await session.setMaxThinkingTokens(maxThinkingTokens);
|
|
632
|
+
logger.debug(`[AgentIDE] Claude setMaxThinkingTokens(${maxThinkingTokens ?? 'null'}) ok`);
|
|
633
|
+
}
|
|
634
|
+
catch (e) {
|
|
635
|
+
logger.warn(`[AgentIDE] Claude setMaxThinkingTokens(${maxThinkingTokens ?? 'null'}) failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
636
|
+
}
|
|
637
|
+
await session.send(message);
|
|
638
|
+
let thinkingDeltaCount = 0;
|
|
639
|
+
let thinkingCharCount = 0;
|
|
640
|
+
let thinkingStartBlockCount = 0;
|
|
641
|
+
let redactedThinkingBlockCount = 0;
|
|
642
|
+
let toolUseBlockCount = 0;
|
|
643
|
+
let toolUseEmitCount = 0;
|
|
644
|
+
let toolProgressCount = 0;
|
|
645
|
+
let inputJsonDeltaCount = 0;
|
|
646
|
+
const emittedToolUseIds = new Set();
|
|
647
|
+
const emittedToolUseIdsWithInput = new Set();
|
|
648
|
+
const emittedToolEndIds = new Set();
|
|
649
|
+
const activeToolUseById = new Map();
|
|
650
|
+
const toolUseIdByIndex = new Map();
|
|
651
|
+
const toolUseNameByIndex = new Map();
|
|
652
|
+
const toolUseJsonByIndex = new Map();
|
|
653
|
+
const previewThinking = (s) => s
|
|
654
|
+
.replace(/\r/g, '')
|
|
655
|
+
.replace(/\n/g, '\\n')
|
|
656
|
+
.slice(0, 160);
|
|
657
|
+
const formatToolInputForDisplay = (_toolName, input) => {
|
|
658
|
+
if (typeof input === 'string') {
|
|
659
|
+
const trimmed = input.trim();
|
|
660
|
+
return trimmed ? input : undefined;
|
|
661
|
+
}
|
|
662
|
+
if (!input || typeof input !== 'object') {
|
|
663
|
+
return undefined;
|
|
664
|
+
}
|
|
665
|
+
const obj = input;
|
|
666
|
+
// Common "command" pattern
|
|
667
|
+
const cmd = obj['command'];
|
|
668
|
+
if (typeof cmd === 'string' && cmd.trim()) {
|
|
669
|
+
return cmd.trim();
|
|
670
|
+
}
|
|
671
|
+
const args = obj['args'];
|
|
672
|
+
if (Array.isArray(args) && args.every(a => typeof a === 'string')) {
|
|
673
|
+
return args.join(' ');
|
|
674
|
+
}
|
|
675
|
+
// Common "path" pattern (e.g. file tools)
|
|
676
|
+
const maybeLocation = obj['location'];
|
|
677
|
+
const maybeLocationPath = (maybeLocation && typeof maybeLocation === 'object')
|
|
678
|
+
? maybeLocation['path']
|
|
679
|
+
: undefined;
|
|
680
|
+
const pathLike = obj['path'] ?? obj['file_path'] ?? obj['file'] ?? obj['filename'] ?? maybeLocationPath;
|
|
681
|
+
const parts = [];
|
|
682
|
+
if (typeof pathLike === 'string' && pathLike.trim()) {
|
|
683
|
+
parts.push(pathLike.trim());
|
|
684
|
+
}
|
|
685
|
+
// Avoid dumping large contents (WriteTool often includes full file content)
|
|
686
|
+
const content = obj['content'];
|
|
687
|
+
if (typeof content === 'string') {
|
|
688
|
+
parts.push(`contentBytes=${Buffer.byteLength(content, 'utf8')}`);
|
|
689
|
+
}
|
|
690
|
+
const patchLike = obj['patch'] ?? obj['diff'];
|
|
691
|
+
if (typeof patchLike === 'string') {
|
|
692
|
+
parts.push(`patchBytes=${Buffer.byteLength(patchLike, 'utf8')}`);
|
|
693
|
+
}
|
|
694
|
+
if (parts.length > 0) {
|
|
695
|
+
return parts.join(' ');
|
|
696
|
+
}
|
|
697
|
+
const MAX_STRING_CHARS = 300;
|
|
698
|
+
const MAX_ARRAY_ITEMS = 30;
|
|
699
|
+
const MAX_DEPTH = 4;
|
|
700
|
+
const sanitize = (value, depth) => {
|
|
701
|
+
if (typeof value === 'string') {
|
|
702
|
+
return value.length > MAX_STRING_CHARS
|
|
703
|
+
? `${value.slice(0, MAX_STRING_CHARS)}… (${value.length} chars)`
|
|
704
|
+
: value;
|
|
705
|
+
}
|
|
706
|
+
if (typeof value === 'number' || typeof value === 'boolean' || value === null) {
|
|
707
|
+
return value;
|
|
708
|
+
}
|
|
709
|
+
if (Array.isArray(value)) {
|
|
710
|
+
if (depth >= MAX_DEPTH) {
|
|
711
|
+
return `[Array(${value.length})]`;
|
|
712
|
+
}
|
|
713
|
+
const head = value.slice(0, MAX_ARRAY_ITEMS).map(v => sanitize(v, depth + 1));
|
|
714
|
+
return value.length > MAX_ARRAY_ITEMS
|
|
715
|
+
? [...head, `… (${value.length - MAX_ARRAY_ITEMS} more)`]
|
|
716
|
+
: head;
|
|
717
|
+
}
|
|
718
|
+
if (typeof value === 'object' && value) {
|
|
719
|
+
if (depth >= MAX_DEPTH) {
|
|
720
|
+
return '[Object]';
|
|
721
|
+
}
|
|
722
|
+
const out = {};
|
|
723
|
+
for (const [k, v] of Object.entries(value)) {
|
|
724
|
+
// Heuristic: collapse huge string payloads in fields like "content", "text", "data", etc.
|
|
725
|
+
if (typeof v === 'string' && /content|text|data|body|patch|diff/i.test(k) && v.length > MAX_STRING_CHARS) {
|
|
726
|
+
out[k] = `<${Buffer.byteLength(v, 'utf8')} bytes>`;
|
|
727
|
+
continue;
|
|
728
|
+
}
|
|
729
|
+
out[k] = sanitize(v, depth + 1);
|
|
730
|
+
}
|
|
731
|
+
return out;
|
|
732
|
+
}
|
|
733
|
+
return undefined;
|
|
734
|
+
};
|
|
735
|
+
try {
|
|
736
|
+
const json = JSON.stringify(sanitize(input, 0), null, 2);
|
|
737
|
+
const trimmed = json.trim();
|
|
738
|
+
if (trimmed === '{}' || trimmed === '[]') {
|
|
739
|
+
return undefined;
|
|
740
|
+
}
|
|
741
|
+
return json;
|
|
742
|
+
}
|
|
743
|
+
catch {
|
|
744
|
+
return undefined;
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
const getToolUseInfoFromBlock = (block) => {
|
|
748
|
+
if (!block || typeof block !== 'object') {
|
|
749
|
+
return undefined;
|
|
750
|
+
}
|
|
751
|
+
const b = block;
|
|
752
|
+
const type = b['type'];
|
|
753
|
+
if (type === 'tool_use' || type === 'server_tool_use') {
|
|
754
|
+
const id = b['id'];
|
|
755
|
+
const name = b['name'];
|
|
756
|
+
const input = b['input'];
|
|
757
|
+
if (typeof id === 'string' && typeof name === 'string') {
|
|
758
|
+
return { id, name, input };
|
|
759
|
+
}
|
|
760
|
+
return undefined;
|
|
761
|
+
}
|
|
762
|
+
if (type === 'mcp_tool_use') {
|
|
763
|
+
const id = b['id'];
|
|
764
|
+
const name = b['name'];
|
|
765
|
+
const serverName = b['server_name'];
|
|
766
|
+
const input = b['input'];
|
|
767
|
+
if (typeof id === 'string' && typeof name === 'string' && typeof serverName === 'string') {
|
|
768
|
+
return { id, name: `${serverName}.${name}`, input };
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
return undefined;
|
|
772
|
+
};
|
|
773
|
+
const stringifyToolResult = (value) => {
|
|
774
|
+
if (typeof value === 'string') {
|
|
775
|
+
return value;
|
|
776
|
+
}
|
|
777
|
+
if (value === undefined || value === null) {
|
|
778
|
+
return undefined;
|
|
779
|
+
}
|
|
780
|
+
try {
|
|
781
|
+
return JSON.stringify(value, null, 2);
|
|
782
|
+
}
|
|
783
|
+
catch {
|
|
784
|
+
return String(value);
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
const extractToolResultText = (value) => {
|
|
788
|
+
if (typeof value === 'string') {
|
|
789
|
+
return value;
|
|
790
|
+
}
|
|
791
|
+
if (Array.isArray(value)) {
|
|
792
|
+
const parts = [];
|
|
793
|
+
for (const part of value) {
|
|
794
|
+
if (typeof part === 'string') {
|
|
795
|
+
parts.push(part);
|
|
796
|
+
continue;
|
|
797
|
+
}
|
|
798
|
+
if (!part || typeof part !== 'object') {
|
|
799
|
+
continue;
|
|
800
|
+
}
|
|
801
|
+
const p = part;
|
|
802
|
+
if (typeof p['text'] === 'string') {
|
|
803
|
+
parts.push(p['text']);
|
|
804
|
+
continue;
|
|
805
|
+
}
|
|
806
|
+
const asString = stringifyToolResult(part);
|
|
807
|
+
if (asString) {
|
|
808
|
+
parts.push(asString);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
const joined = parts.join('\n').trim();
|
|
812
|
+
return joined || undefined;
|
|
813
|
+
}
|
|
814
|
+
if (value && typeof value === 'object') {
|
|
815
|
+
const obj = value;
|
|
816
|
+
if (typeof obj['text'] === 'string') {
|
|
817
|
+
return obj['text'];
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
return stringifyToolResult(value);
|
|
821
|
+
};
|
|
822
|
+
const getToolResultInfoFromBlock = (block) => {
|
|
823
|
+
if (!block || typeof block !== 'object') {
|
|
824
|
+
return undefined;
|
|
825
|
+
}
|
|
826
|
+
const b = block;
|
|
827
|
+
const type = b['type'];
|
|
828
|
+
if (type !== 'tool_result' && type !== 'server_tool_result' && type !== 'mcp_tool_result') {
|
|
829
|
+
return undefined;
|
|
830
|
+
}
|
|
831
|
+
const toolUseId = b['tool_use_id'];
|
|
832
|
+
if (typeof toolUseId !== 'string' || !toolUseId) {
|
|
833
|
+
return undefined;
|
|
834
|
+
}
|
|
835
|
+
const resultText = extractToolResultText(b['content'] ?? b['result'] ?? b['output'] ?? b['data'] ?? b['text']);
|
|
836
|
+
const isError = typeof b['is_error'] === 'boolean'
|
|
837
|
+
? b['is_error']
|
|
838
|
+
: (typeof b['isError'] === 'boolean' ? b['isError'] : undefined);
|
|
839
|
+
return { toolUseId, resultText, isError };
|
|
840
|
+
};
|
|
841
|
+
const emitToolStart = async (toolName, toolUseId, formattedInput) => {
|
|
842
|
+
const shouldEmit = !emittedToolUseIds.has(toolUseId)
|
|
843
|
+
|| (!!formattedInput && !emittedToolUseIdsWithInput.has(toolUseId));
|
|
844
|
+
if (!shouldEmit) {
|
|
845
|
+
activeToolUseById.set(toolUseId, toolName);
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
toolUseEmitCount++;
|
|
849
|
+
emittedToolUseIds.add(toolUseId);
|
|
850
|
+
if (formattedInput) {
|
|
851
|
+
emittedToolUseIdsWithInput.add(toolUseId);
|
|
852
|
+
}
|
|
853
|
+
activeToolUseById.set(toolUseId, toolName);
|
|
854
|
+
if (!aborted) {
|
|
855
|
+
await emitter.toolStart(toolName, formattedInput, toolUseId);
|
|
856
|
+
}
|
|
857
|
+
};
|
|
858
|
+
const emitToolEnd = async (toolUseId, resultText, isError, fallbackToolName) => {
|
|
859
|
+
if (emittedToolEndIds.has(toolUseId)) {
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
const toolName = activeToolUseById.get(toolUseId) ?? fallbackToolName ?? 'tool';
|
|
863
|
+
if (!emittedToolUseIds.has(toolUseId)) {
|
|
864
|
+
// Ensure there's a matching start row before finalizing.
|
|
865
|
+
await emitToolStart(toolName, toolUseId);
|
|
866
|
+
}
|
|
867
|
+
emittedToolEndIds.add(toolUseId);
|
|
868
|
+
activeToolUseById.delete(toolUseId);
|
|
869
|
+
if (!aborted) {
|
|
870
|
+
await emitter.toolEnd(toolName, toolUseId, resultText, isError);
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
let persistedThisTurn = false;
|
|
874
|
+
let messageCount = 0;
|
|
875
|
+
for await (const msg of session.receive()) {
|
|
876
|
+
messageCount++;
|
|
877
|
+
const m = msg;
|
|
878
|
+
const sessionIdFromMsg = m.session_id;
|
|
879
|
+
if (!persistedThisTurn && sessionIdFromMsg) {
|
|
880
|
+
persistedThisTurn = true;
|
|
881
|
+
await (0, base_1.persistSessionIfNeeded)('claude', convo, sessionIdFromMsg, options);
|
|
882
|
+
}
|
|
883
|
+
const subtype = m.type === 'result' || m.type === 'system' ? m.subtype : undefined;
|
|
884
|
+
logger.debug(`[AgentIDE] Claude msg #${messageCount}: type=${m.type}, subtype=${subtype || 'none'}`);
|
|
885
|
+
// If the user cancelled the turn, keep draining the SDK stream until it yields a terminal result,
|
|
886
|
+
// but do not emit any further UI events. This prevents "leftover" result messages from surfacing
|
|
887
|
+
// on the next turn (e.g., error_during_execution after a Stop).
|
|
888
|
+
if (aborted && m.type !== 'result') {
|
|
889
|
+
continue;
|
|
890
|
+
}
|
|
891
|
+
if (m.type === 'stream_event') {
|
|
892
|
+
const event = m.event;
|
|
893
|
+
const eventType = event.type;
|
|
894
|
+
if (eventType === 'content_block_start') {
|
|
895
|
+
const contentBlock = event.content_block;
|
|
896
|
+
const blockType = contentBlock?.type;
|
|
897
|
+
const blockIndex = event.index;
|
|
898
|
+
if (blockType === 'thinking') {
|
|
899
|
+
const initialThinking = contentBlock?.thinking;
|
|
900
|
+
thinkingStartBlockCount++;
|
|
901
|
+
if (typeof initialThinking === 'string' && initialThinking) {
|
|
902
|
+
thinkingCharCount += initialThinking.length;
|
|
903
|
+
logger.debug(`[AgentIDE] Claude thinking block start (${initialThinking.length} chars): ${previewThinking(initialThinking)}`);
|
|
904
|
+
if (!aborted) {
|
|
905
|
+
await emitter.thinking(initialThinking);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
else {
|
|
909
|
+
logger.debug('[AgentIDE] Claude thinking block start (no initial thinking text)');
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
else if (blockType === 'redacted_thinking') {
|
|
913
|
+
redactedThinkingBlockCount++;
|
|
914
|
+
const data = contentBlock?.data;
|
|
915
|
+
logger.debug(`[AgentIDE] Claude redacted_thinking block start (dataType=${typeof data})`);
|
|
916
|
+
}
|
|
917
|
+
else {
|
|
918
|
+
const toolResult = getToolResultInfoFromBlock(event.content_block);
|
|
919
|
+
if (toolResult) {
|
|
920
|
+
await emitToolEnd(toolResult.toolUseId, toolResult.resultText, toolResult.isError);
|
|
921
|
+
continue;
|
|
922
|
+
}
|
|
923
|
+
// Tool use blocks are reported as content blocks in stream events.
|
|
924
|
+
const toolUse = getToolUseInfoFromBlock(event.content_block);
|
|
925
|
+
if (toolUse) {
|
|
926
|
+
toolUseBlockCount++;
|
|
927
|
+
if (typeof blockIndex === 'number') {
|
|
928
|
+
toolUseIdByIndex.set(blockIndex, toolUse.id);
|
|
929
|
+
toolUseNameByIndex.set(blockIndex, toolUse.name);
|
|
930
|
+
}
|
|
931
|
+
if (!emittedToolUseIds.has(toolUse.id)) {
|
|
932
|
+
const formatted = formatToolInputForDisplay(toolUse.name, toolUse.input);
|
|
933
|
+
logger.debug(`[AgentIDE] Claude tool_use start: ${toolUse.name} (id=${toolUse.id}, input=${formatted ? 'yes' : 'no'})`);
|
|
934
|
+
await emitToolStart(toolUse.name, toolUse.id, formatted);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
else if (eventType === 'content_block_delta') {
|
|
940
|
+
const delta = event.delta;
|
|
941
|
+
const deltaType = delta.type;
|
|
942
|
+
const thinking = delta.thinking;
|
|
943
|
+
const text = delta.text;
|
|
944
|
+
if (deltaType === 'thinking_delta' && typeof thinking === 'string' && thinking) {
|
|
945
|
+
thinkingDeltaCount++;
|
|
946
|
+
thinkingCharCount += thinking.length;
|
|
947
|
+
if (thinkingDeltaCount <= 3) {
|
|
948
|
+
logger.debug(`[AgentIDE] Claude thinking delta #${thinkingDeltaCount} (${thinking.length} chars): ${previewThinking(thinking)}`);
|
|
949
|
+
}
|
|
950
|
+
if (!aborted) {
|
|
951
|
+
await emitter.thinking(thinking);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
else if (deltaType === 'input_json_delta') {
|
|
955
|
+
// Some tool inputs stream as JSON fragments; emit a toolStart once we can parse valid JSON.
|
|
956
|
+
const index = event.index;
|
|
957
|
+
const partial = delta.partial_json;
|
|
958
|
+
if (typeof index === 'number' && typeof partial === 'string' && partial) {
|
|
959
|
+
inputJsonDeltaCount++;
|
|
960
|
+
const prev = toolUseJsonByIndex.get(index) ?? '';
|
|
961
|
+
const next = prev + partial;
|
|
962
|
+
toolUseJsonByIndex.set(index, next);
|
|
963
|
+
const toolUseId = toolUseIdByIndex.get(index);
|
|
964
|
+
if (toolUseId && !emittedToolUseIdsWithInput.has(toolUseId)) {
|
|
965
|
+
try {
|
|
966
|
+
const parsed = JSON.parse(next);
|
|
967
|
+
const toolName = toolUseNameByIndex.get(index) ?? 'tool';
|
|
968
|
+
const formatted = formatToolInputForDisplay(toolName, parsed);
|
|
969
|
+
if (formatted) {
|
|
970
|
+
logger.debug(`[AgentIDE] Claude tool_use input_json parsed: ${toolName} (id=${toolUseId})`);
|
|
971
|
+
await emitToolStart(toolName, toolUseId, formatted);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
catch {
|
|
975
|
+
// not parseable yet
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
else if (deltaType === 'text_delta' && typeof text === 'string' && text) {
|
|
981
|
+
streamedTextBuffer += text;
|
|
982
|
+
if (!aborted) {
|
|
983
|
+
await emitter.text(text);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
else if (m.type === 'assistant') {
|
|
989
|
+
const content = m.message.content;
|
|
990
|
+
if (Array.isArray(content)) {
|
|
991
|
+
for (const block of content) {
|
|
992
|
+
const blockType = block.type;
|
|
993
|
+
const blockText = block.text;
|
|
994
|
+
const toolResult = getToolResultInfoFromBlock(block);
|
|
995
|
+
if (toolResult) {
|
|
996
|
+
await emitToolEnd(toolResult.toolUseId, toolResult.resultText, toolResult.isError);
|
|
997
|
+
continue;
|
|
998
|
+
}
|
|
999
|
+
const toolUse = getToolUseInfoFromBlock(block);
|
|
1000
|
+
if (toolUse && !emittedToolUseIds.has(toolUse.id)) {
|
|
1001
|
+
toolUseBlockCount++;
|
|
1002
|
+
const formatted = formatToolInputForDisplay(toolUse.name, toolUse.input);
|
|
1003
|
+
logger.debug(`[AgentIDE] Claude tool_use (assistant msg): ${toolUse.name} (id=${toolUse.id}, input=${formatted ? 'yes' : 'no'})`);
|
|
1004
|
+
await emitToolStart(toolUse.name, toolUse.id, formatted);
|
|
1005
|
+
continue;
|
|
1006
|
+
}
|
|
1007
|
+
if (blockType === 'text' && typeof blockText === 'string' && blockText) {
|
|
1008
|
+
if (!aborted) {
|
|
1009
|
+
await emitUniqueMarkdown(blockText);
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
else if (m.type === 'tool_progress') {
|
|
1016
|
+
toolProgressCount++;
|
|
1017
|
+
const toolUseId = m.tool_use_id;
|
|
1018
|
+
const toolName = m.tool_name || 'tool';
|
|
1019
|
+
if (toolUseId && !emittedToolUseIds.has(toolUseId)) {
|
|
1020
|
+
logger.debug(`[AgentIDE] Claude tool_progress: ${toolName} (tool_use_id=${toolUseId})`);
|
|
1021
|
+
await emitToolStart(toolName, toolUseId);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
else if (m.type === 'system') {
|
|
1025
|
+
if (m.subtype === 'status' && m.status === 'compacting') {
|
|
1026
|
+
if (!aborted) {
|
|
1027
|
+
await emitter.progress('Compacting context…');
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
else if (m.type === 'result') {
|
|
1032
|
+
if (m.subtype === 'success') {
|
|
1033
|
+
// Successful completion: only emit to UI if we weren't cancelled.
|
|
1034
|
+
if (!aborted) {
|
|
1035
|
+
await emitUniqueMarkdown(m.result);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
else {
|
|
1039
|
+
// Error completion: treat as fatal only if the user didn't cancel.
|
|
1040
|
+
if (!aborted) {
|
|
1041
|
+
throw new Error(m.errors?.join('\n') || m.subtype);
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
const genericMessageContent = m.message?.content;
|
|
1046
|
+
if (m.type !== 'assistant' && Array.isArray(genericMessageContent)) {
|
|
1047
|
+
for (const block of genericMessageContent) {
|
|
1048
|
+
const toolResult = getToolResultInfoFromBlock(block);
|
|
1049
|
+
if (toolResult) {
|
|
1050
|
+
await emitToolEnd(toolResult.toolUseId, toolResult.resultText, toolResult.isError);
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
for (const [toolUseId, toolName] of Array.from(activeToolUseById.entries())) {
|
|
1056
|
+
await emitToolEnd(toolUseId, 'Completed', false, toolName);
|
|
1057
|
+
}
|
|
1058
|
+
logger.info(`[AgentIDE] Claude thinking summary: startBlocks=${thinkingStartBlockCount}, redactedBlocks=${redactedThinkingBlockCount}, deltas=${thinkingDeltaCount}, chars=${thinkingCharCount}`);
|
|
1059
|
+
logger.info(`[AgentIDE] Claude tool summary: toolBlocks=${toolUseBlockCount}, toolEmits=${toolUseEmitCount}, toolProgressMsgs=${toolProgressCount}, inputJsonDeltas=${inputJsonDeltaCount}`);
|
|
1060
|
+
if (thinkingStartBlockCount === 0 && thinkingDeltaCount === 0 && redactedThinkingBlockCount === 0) {
|
|
1061
|
+
logger.debug('[AgentIDE] Claude emitted no thinking blocks/deltas. Ensure model supports extended thinking and set agentide.claude.maxThinkingTokens >= 1024.');
|
|
1062
|
+
}
|
|
1063
|
+
if (toolUseBlockCount === 0 && toolProgressCount === 0) {
|
|
1064
|
+
logger.debug('[AgentIDE] Claude emitted no tool usage events. If tools were used, ensure includePartialMessages=true and parse tool_use blocks.');
|
|
1065
|
+
}
|
|
1066
|
+
(0, base_1.touchSessionIfNeeded)(convo);
|
|
1067
|
+
}
|
|
1068
|
+
catch (e) {
|
|
1069
|
+
if (!aborted) {
|
|
1070
|
+
throw e;
|
|
1071
|
+
}
|
|
1072
|
+
logger.info(`[AgentIDE] Claude stream aborted: ${e instanceof Error ? e.message : String(e)}`);
|
|
1073
|
+
}
|
|
1074
|
+
finally {
|
|
1075
|
+
signal?.removeEventListener('abort', onAbort);
|
|
1076
|
+
}
|
|
1077
|
+
}, {
|
|
1078
|
+
signal,
|
|
1079
|
+
// Agent turns may run for hours; keep this high as a safety net only.
|
|
1080
|
+
timeoutMs: session_1.DEFAULT_CONVERSATION_LOCK_TIMEOUT_MS,
|
|
1081
|
+
label: 'claude.stream'
|
|
1082
|
+
});
|
|
1083
|
+
await emitter.done();
|
|
1084
|
+
logger.info('[AgentIDE] Claude streaming complete');
|
|
1085
|
+
}
|
|
1086
|
+
dispose() {
|
|
1087
|
+
for (const entry of this.activeSessions.values()) {
|
|
1088
|
+
try {
|
|
1089
|
+
entry.session.close();
|
|
1090
|
+
}
|
|
1091
|
+
catch {
|
|
1092
|
+
// ignore
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
this.activeSessions.clear();
|
|
1096
|
+
}
|
|
1097
|
+
onMaintenance(logger) {
|
|
1098
|
+
this.sweepIdleSessions(logger);
|
|
1099
|
+
}
|
|
1100
|
+
sweepIdleSessions(logger) {
|
|
1101
|
+
const now = Date.now();
|
|
1102
|
+
for (const [key, entry] of this.activeSessions.entries()) {
|
|
1103
|
+
if (now - entry.lastUsedAt > ACTIVE_SESSION_IDLE_TTL_MS) {
|
|
1104
|
+
try {
|
|
1105
|
+
entry.session.close();
|
|
1106
|
+
logger?.info(`[AgentIDE] Closed idle Claude session (key=${key}, idleMs=${now - entry.lastUsedAt})`);
|
|
1107
|
+
}
|
|
1108
|
+
catch {
|
|
1109
|
+
// ignore
|
|
1110
|
+
}
|
|
1111
|
+
this.activeSessions.delete(key);
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
// ---------------------------------------------------------------------------
|
|
1116
|
+
// Session Management
|
|
1117
|
+
// ---------------------------------------------------------------------------
|
|
1118
|
+
async getOrCreateSession(params) {
|
|
1119
|
+
const existing = this.activeSessions.get(params.conversationKey);
|
|
1120
|
+
if (existing
|
|
1121
|
+
&& existing.signatureHash === params.signatureHash
|
|
1122
|
+
&& existing.modelId === params.modelId
|
|
1123
|
+
&& existing.cheapModel === params.cheapModel
|
|
1124
|
+
&& existing.agentideSignature === params.agentideSignature) {
|
|
1125
|
+
existing.lastUsedAt = Date.now();
|
|
1126
|
+
// Reset edit tracking state for new turn - clear any orphaned pending operations
|
|
1127
|
+
existing.editTrackingState.aborted = false;
|
|
1128
|
+
existing.editTrackingState.pendingOperations.clear();
|
|
1129
|
+
void (0, session_1.touchPersistedSession)(params.conversationKey);
|
|
1130
|
+
params.logger.debug(`[AgentIDE] REUSING existing Claude session (key=${params.conversationKey}) - NOTE: hooks from original session creation are used, not new ones`);
|
|
1131
|
+
return existing;
|
|
1132
|
+
}
|
|
1133
|
+
let resumeSessionId;
|
|
1134
|
+
if (existing) {
|
|
1135
|
+
if (existing.signatureHash === params.signatureHash && existing.agentideSignature !== params.agentideSignature) {
|
|
1136
|
+
params.logger.info(`[AgentIDE] AgentIDE manifest changed (${existing.agentideSignature} → ${params.agentideSignature}), restarting Claude session with resume`);
|
|
1137
|
+
resumeSessionId = existing.session.sessionId ?? undefined;
|
|
1138
|
+
}
|
|
1139
|
+
if (existing.modelId !== params.modelId) {
|
|
1140
|
+
params.logger.info(`[AgentIDE] Model changed (${existing.modelId} → ${params.modelId}), will resume session with new model`);
|
|
1141
|
+
resumeSessionId = existing.session.sessionId ?? undefined;
|
|
1142
|
+
}
|
|
1143
|
+
if (existing.cheapModel !== params.cheapModel) {
|
|
1144
|
+
params.logger.info(`[AgentIDE] Cheap model changed (${existing.cheapModel ?? 'unset'} → ${params.cheapModel ?? 'unset'}), will resume session with updated env`);
|
|
1145
|
+
resumeSessionId = existing.session.sessionId ?? undefined;
|
|
1146
|
+
}
|
|
1147
|
+
try {
|
|
1148
|
+
existing.session.close();
|
|
1149
|
+
}
|
|
1150
|
+
catch {
|
|
1151
|
+
// ignore
|
|
1152
|
+
}
|
|
1153
|
+
this.activeSessions.delete(params.conversationKey);
|
|
1154
|
+
}
|
|
1155
|
+
if (!resumeSessionId && !params.isEphemeral) {
|
|
1156
|
+
resumeSessionId = (0, base_1.getPersistedSessionId)('claude', params.conversationKey);
|
|
1157
|
+
}
|
|
1158
|
+
if (resumeSessionId) {
|
|
1159
|
+
params.logger.info(`[AgentIDE] Claude session will resume: ${resumeSessionId} (model: ${params.modelId})`);
|
|
1160
|
+
}
|
|
1161
|
+
else {
|
|
1162
|
+
params.logger.info(`[AgentIDE] Claude session starting new (model: ${params.modelId})`);
|
|
1163
|
+
}
|
|
1164
|
+
const sdk = await import('@anthropic-ai/claude-agent-sdk');
|
|
1165
|
+
const session = createClaudePersistentQuerySession({
|
|
1166
|
+
resumeSessionId,
|
|
1167
|
+
queryFn: sdk.query,
|
|
1168
|
+
options: params.queryOptions
|
|
1169
|
+
});
|
|
1170
|
+
const entry = {
|
|
1171
|
+
session,
|
|
1172
|
+
chatSessionId: params.chatSessionId,
|
|
1173
|
+
signatureHash: params.signatureHash,
|
|
1174
|
+
agentideSignature: params.agentideSignature,
|
|
1175
|
+
modelId: params.modelId,
|
|
1176
|
+
cheapModel: params.cheapModel,
|
|
1177
|
+
lastUsedAt: Date.now(),
|
|
1178
|
+
editTrackingState: {
|
|
1179
|
+
aborted: false,
|
|
1180
|
+
pendingOperations: new Map(),
|
|
1181
|
+
},
|
|
1182
|
+
};
|
|
1183
|
+
this.activeSessions.set(params.conversationKey, entry);
|
|
1184
|
+
return entry;
|
|
1185
|
+
}
|
|
1186
|
+
// ---------------------------------------------------------------------------
|
|
1187
|
+
// MCP Configuration
|
|
1188
|
+
// ---------------------------------------------------------------------------
|
|
1189
|
+
/**
|
|
1190
|
+
* Load MCP servers for the active agent and return them in Claude SDK format.
|
|
1191
|
+
* - Default agent: uses bundled MCP servers from extension
|
|
1192
|
+
* - Pack agents: uses pack's mcp/ directory
|
|
1193
|
+
*
|
|
1194
|
+
* The SDK accepts mcpServers directly in query options.
|
|
1195
|
+
*/
|
|
1196
|
+
async loadMcpServersForClaude(logger, workspaceRoot, agentId = 'default') {
|
|
1197
|
+
const basePromptsDir = this.getBundledBasePromptsDir();
|
|
1198
|
+
const servers = await (0, mcp_1.loadMcpServers)(agentId, workspaceRoot, basePromptsDir);
|
|
1199
|
+
if (servers.length === 0) {
|
|
1200
|
+
return {};
|
|
1201
|
+
}
|
|
1202
|
+
const mcpServers = {};
|
|
1203
|
+
for (const s of servers) {
|
|
1204
|
+
mcpServers[s.name] = {
|
|
1205
|
+
command: s.command,
|
|
1206
|
+
args: s.args,
|
|
1207
|
+
...(s.env && Object.keys(s.env).length > 0 ? { env: s.env } : {})
|
|
1208
|
+
};
|
|
1209
|
+
}
|
|
1210
|
+
const source = agentId === 'default' ? 'bundled' : `pack:${agentId}`;
|
|
1211
|
+
logger.debug(`[AgentIDE] Claude MCP servers loaded (${source}): ${servers.map(s => s.name).join(', ')}`);
|
|
1212
|
+
return mcpServers;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
exports.ClaudeEngine = ClaudeEngine;
|