@esankhan3/anvil-agent-core 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/README.md +142 -0
- package/dist/__tests__/adapter-enrichment.test.d.ts +12 -0
- package/dist/__tests__/adapter-enrichment.test.d.ts.map +1 -0
- package/dist/__tests__/adapter-enrichment.test.js +199 -0
- package/dist/__tests__/adapter-enrichment.test.js.map +1 -0
- package/dist/__tests__/adk-anthropic-llm.test.d.ts +18 -0
- package/dist/__tests__/adk-anthropic-llm.test.d.ts.map +1 -0
- package/dist/__tests__/adk-anthropic-llm.test.js +124 -0
- package/dist/__tests__/adk-anthropic-llm.test.js.map +1 -0
- package/dist/__tests__/cost-breakdown.test.d.ts +11 -0
- package/dist/__tests__/cost-breakdown.test.d.ts.map +1 -0
- package/dist/__tests__/cost-breakdown.test.js +163 -0
- package/dist/__tests__/cost-breakdown.test.js.map +1 -0
- package/dist/__tests__/mcp.test.d.ts +13 -0
- package/dist/__tests__/mcp.test.d.ts.map +1 -0
- package/dist/__tests__/mcp.test.js +413 -0
- package/dist/__tests__/mcp.test.js.map +1 -0
- package/dist/__tests__/ollama-adapter-agentic.test.d.ts +15 -0
- package/dist/__tests__/ollama-adapter-agentic.test.d.ts.map +1 -0
- package/dist/__tests__/ollama-adapter-agentic.test.js +268 -0
- package/dist/__tests__/ollama-adapter-agentic.test.js.map +1 -0
- package/dist/__tests__/ollama-adapter-executor.test.d.ts +10 -0
- package/dist/__tests__/ollama-adapter-executor.test.d.ts.map +1 -0
- package/dist/__tests__/ollama-adapter-executor.test.js +95 -0
- package/dist/__tests__/ollama-adapter-executor.test.js.map +1 -0
- package/dist/__tests__/openai-adapter-output.test.d.ts +17 -0
- package/dist/__tests__/openai-adapter-output.test.d.ts.map +1 -0
- package/dist/__tests__/openai-adapter-output.test.js +127 -0
- package/dist/__tests__/openai-adapter-output.test.js.map +1 -0
- package/dist/__tests__/opencode-adapter.test.d.ts +7 -0
- package/dist/__tests__/opencode-adapter.test.d.ts.map +1 -0
- package/dist/__tests__/opencode-adapter.test.js +141 -0
- package/dist/__tests__/opencode-adapter.test.js.map +1 -0
- package/dist/__tests__/openrouter-adapter-agentic.test.d.ts +11 -0
- package/dist/__tests__/openrouter-adapter-agentic.test.d.ts.map +1 -0
- package/dist/__tests__/openrouter-adapter-agentic.test.js +297 -0
- package/dist/__tests__/openrouter-adapter-agentic.test.js.map +1 -0
- package/dist/__tests__/router-circuit-breaker.test.d.ts +6 -0
- package/dist/__tests__/router-circuit-breaker.test.d.ts.map +1 -0
- package/dist/__tests__/router-circuit-breaker.test.js +253 -0
- package/dist/__tests__/router-circuit-breaker.test.js.map +1 -0
- package/dist/__tests__/router-config-loader.test.d.ts +8 -0
- package/dist/__tests__/router-config-loader.test.d.ts.map +1 -0
- package/dist/__tests__/router-config-loader.test.js +172 -0
- package/dist/__tests__/router-config-loader.test.js.map +1 -0
- package/dist/__tests__/router-discovery.test.d.ts +5 -0
- package/dist/__tests__/router-discovery.test.d.ts.map +1 -0
- package/dist/__tests__/router-discovery.test.js +129 -0
- package/dist/__tests__/router-discovery.test.js.map +1 -0
- package/dist/__tests__/router-fallback.test.d.ts +9 -0
- package/dist/__tests__/router-fallback.test.d.ts.map +1 -0
- package/dist/__tests__/router-fallback.test.js +283 -0
- package/dist/__tests__/router-fallback.test.js.map +1 -0
- package/dist/__tests__/router-local-executor.test.d.ts +6 -0
- package/dist/__tests__/router-local-executor.test.d.ts.map +1 -0
- package/dist/__tests__/router-local-executor.test.js +193 -0
- package/dist/__tests__/router-local-executor.test.js.map +1 -0
- package/dist/__tests__/router-model-registry.test.d.ts +8 -0
- package/dist/__tests__/router-model-registry.test.d.ts.map +1 -0
- package/dist/__tests__/router-model-registry.test.js +389 -0
- package/dist/__tests__/router-model-registry.test.js.map +1 -0
- package/dist/__tests__/router-rate-limiter.test.d.ts +8 -0
- package/dist/__tests__/router-rate-limiter.test.d.ts.map +1 -0
- package/dist/__tests__/router-rate-limiter.test.js +128 -0
- package/dist/__tests__/router-rate-limiter.test.js.map +1 -0
- package/dist/__tests__/router-resolver.test.d.ts +7 -0
- package/dist/__tests__/router-resolver.test.d.ts.map +1 -0
- package/dist/__tests__/router-resolver.test.js +110 -0
- package/dist/__tests__/router-resolver.test.js.map +1 -0
- package/dist/__tests__/router-retry.test.d.ts +7 -0
- package/dist/__tests__/router-retry.test.d.ts.map +1 -0
- package/dist/__tests__/router-retry.test.js +302 -0
- package/dist/__tests__/router-retry.test.js.map +1 -0
- package/dist/__tests__/router-scaffold.test.d.ts +11 -0
- package/dist/__tests__/router-scaffold.test.d.ts.map +1 -0
- package/dist/__tests__/router-scaffold.test.js +103 -0
- package/dist/__tests__/router-scaffold.test.js.map +1 -0
- package/dist/__tests__/router-spend-ledger.test.d.ts +8 -0
- package/dist/__tests__/router-spend-ledger.test.d.ts.map +1 -0
- package/dist/__tests__/router-spend-ledger.test.js +227 -0
- package/dist/__tests__/router-spend-ledger.test.js.map +1 -0
- package/dist/__tests__/router-telemetry.test.d.ts +11 -0
- package/dist/__tests__/router-telemetry.test.d.ts.map +1 -0
- package/dist/__tests__/router-telemetry.test.js +173 -0
- package/dist/__tests__/router-telemetry.test.js.map +1 -0
- package/dist/__tests__/single-shot.test.d.ts +12 -0
- package/dist/__tests__/single-shot.test.d.ts.map +1 -0
- package/dist/__tests__/single-shot.test.js +204 -0
- package/dist/__tests__/single-shot.test.js.map +1 -0
- package/dist/__tests__/skills-prompt.test.d.ts +11 -0
- package/dist/__tests__/skills-prompt.test.d.ts.map +1 -0
- package/dist/__tests__/skills-prompt.test.js +208 -0
- package/dist/__tests__/skills-prompt.test.js.map +1 -0
- package/dist/__tests__/skills.test.d.ts +11 -0
- package/dist/__tests__/skills.test.d.ts.map +1 -0
- package/dist/__tests__/skills.test.js +161 -0
- package/dist/__tests__/skills.test.js.map +1 -0
- package/dist/__tests__/telemetry-integration.test.d.ts +12 -0
- package/dist/__tests__/telemetry-integration.test.d.ts.map +1 -0
- package/dist/__tests__/telemetry-integration.test.js +153 -0
- package/dist/__tests__/telemetry-integration.test.js.map +1 -0
- package/dist/__tests__/telemetry.test.d.ts +13 -0
- package/dist/__tests__/telemetry.test.d.ts.map +1 -0
- package/dist/__tests__/telemetry.test.js +161 -0
- package/dist/__tests__/telemetry.test.js.map +1 -0
- package/dist/__tests__/upstream-error.test.d.ts +8 -0
- package/dist/__tests__/upstream-error.test.d.ts.map +1 -0
- package/dist/__tests__/upstream-error.test.js +186 -0
- package/dist/__tests__/upstream-error.test.js.map +1 -0
- package/dist/adk-adapter.d.ts +45 -0
- package/dist/adk-adapter.d.ts.map +1 -0
- package/dist/adk-adapter.js +403 -0
- package/dist/adk-adapter.js.map +1 -0
- package/dist/adk-anthropic-llm.d.ts +59 -0
- package/dist/adk-anthropic-llm.d.ts.map +1 -0
- package/dist/adk-anthropic-llm.js +397 -0
- package/dist/adk-anthropic-llm.js.map +1 -0
- package/dist/agent/index.d.ts +14 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +14 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/session/__tests__/bridge-tool-executor.test.d.ts +10 -0
- package/dist/agent/session/__tests__/bridge-tool-executor.test.d.ts.map +1 -0
- package/dist/agent/session/__tests__/bridge-tool-executor.test.js +152 -0
- package/dist/agent/session/__tests__/bridge-tool-executor.test.js.map +1 -0
- package/dist/agent/session/__tests__/collect-trajectory.test.d.ts +18 -0
- package/dist/agent/session/__tests__/collect-trajectory.test.d.ts.map +1 -0
- package/dist/agent/session/__tests__/collect-trajectory.test.js +208 -0
- package/dist/agent/session/__tests__/collect-trajectory.test.js.map +1 -0
- package/dist/agent/session/__tests__/run-with-agent.test.d.ts +8 -0
- package/dist/agent/session/__tests__/run-with-agent.test.d.ts.map +1 -0
- package/dist/agent/session/__tests__/run-with-agent.test.js +98 -0
- package/dist/agent/session/__tests__/run-with-agent.test.js.map +1 -0
- package/dist/agent/session/__tests__/runtime.test.d.ts +7 -0
- package/dist/agent/session/__tests__/runtime.test.d.ts.map +1 -0
- package/dist/agent/session/__tests__/runtime.test.js +361 -0
- package/dist/agent/session/__tests__/runtime.test.js.map +1 -0
- package/dist/agent/session/__tests__/skills-mcp-spawn.test.d.ts +15 -0
- package/dist/agent/session/__tests__/skills-mcp-spawn.test.d.ts.map +1 -0
- package/dist/agent/session/__tests__/skills-mcp-spawn.test.js +160 -0
- package/dist/agent/session/__tests__/skills-mcp-spawn.test.js.map +1 -0
- package/dist/agent/session/__tests__/spawn-telemetry.test.d.ts +13 -0
- package/dist/agent/session/__tests__/spawn-telemetry.test.d.ts.map +1 -0
- package/dist/agent/session/__tests__/spawn-telemetry.test.js +135 -0
- package/dist/agent/session/__tests__/spawn-telemetry.test.js.map +1 -0
- package/dist/agent/session/__tests__/types.test.d.ts +9 -0
- package/dist/agent/session/__tests__/types.test.d.ts.map +1 -0
- package/dist/agent/session/__tests__/types.test.js +220 -0
- package/dist/agent/session/__tests__/types.test.js.map +1 -0
- package/dist/agent/session/adapter.d.ts +108 -0
- package/dist/agent/session/adapter.d.ts.map +1 -0
- package/dist/agent/session/adapter.js +39 -0
- package/dist/agent/session/adapter.js.map +1 -0
- package/dist/agent/session/collect-trajectory.d.ts +36 -0
- package/dist/agent/session/collect-trajectory.d.ts.map +1 -0
- package/dist/agent/session/collect-trajectory.js +193 -0
- package/dist/agent/session/collect-trajectory.js.map +1 -0
- package/dist/agent/session/default-adapter-factory.d.ts +48 -0
- package/dist/agent/session/default-adapter-factory.d.ts.map +1 -0
- package/dist/agent/session/default-adapter-factory.js +227 -0
- package/dist/agent/session/default-adapter-factory.js.map +1 -0
- package/dist/agent/session/headless-types.d.ts +85 -0
- package/dist/agent/session/headless-types.d.ts.map +1 -0
- package/dist/agent/session/headless-types.js +16 -0
- package/dist/agent/session/headless-types.js.map +1 -0
- package/dist/agent/session/index.d.ts +18 -0
- package/dist/agent/session/index.d.ts.map +1 -0
- package/dist/agent/session/index.js +20 -0
- package/dist/agent/session/index.js.map +1 -0
- package/dist/agent/session/language-model-bridge.d.ts +84 -0
- package/dist/agent/session/language-model-bridge.d.ts.map +1 -0
- package/dist/agent/session/language-model-bridge.js +454 -0
- package/dist/agent/session/language-model-bridge.js.map +1 -0
- package/dist/agent/session/legacy-adapter-types.d.ts +63 -0
- package/dist/agent/session/legacy-adapter-types.d.ts.map +1 -0
- package/dist/agent/session/legacy-adapter-types.js +11 -0
- package/dist/agent/session/legacy-adapter-types.js.map +1 -0
- package/dist/agent/session/run-with-agent.d.ts +36 -0
- package/dist/agent/session/run-with-agent.d.ts.map +1 -0
- package/dist/agent/session/run-with-agent.js +81 -0
- package/dist/agent/session/run-with-agent.js.map +1 -0
- package/dist/agent/session/session-registry.d.ts +71 -0
- package/dist/agent/session/session-registry.d.ts.map +1 -0
- package/dist/agent/session/session-registry.js +209 -0
- package/dist/agent/session/session-registry.js.map +1 -0
- package/dist/agent/session/session.d.ts +76 -0
- package/dist/agent/session/session.d.ts.map +1 -0
- package/dist/agent/session/session.js +327 -0
- package/dist/agent/session/session.js.map +1 -0
- package/dist/agent/session/types.d.ts +230 -0
- package/dist/agent/session/types.d.ts.map +1 -0
- package/dist/agent/session/types.js +44 -0
- package/dist/agent/session/types.js.map +1 -0
- package/dist/checkpoint/__tests__/blob-store.test.d.ts +5 -0
- package/dist/checkpoint/__tests__/blob-store.test.d.ts.map +1 -0
- package/dist/checkpoint/__tests__/blob-store.test.js +82 -0
- package/dist/checkpoint/__tests__/blob-store.test.js.map +1 -0
- package/dist/checkpoint/__tests__/key.test.d.ts +7 -0
- package/dist/checkpoint/__tests__/key.test.d.ts.map +1 -0
- package/dist/checkpoint/__tests__/key.test.js +130 -0
- package/dist/checkpoint/__tests__/key.test.js.map +1 -0
- package/dist/checkpoint/__tests__/runner.test.d.ts +12 -0
- package/dist/checkpoint/__tests__/runner.test.d.ts.map +1 -0
- package/dist/checkpoint/__tests__/runner.test.js +201 -0
- package/dist/checkpoint/__tests__/runner.test.js.map +1 -0
- package/dist/checkpoint/__tests__/store.test.d.ts +6 -0
- package/dist/checkpoint/__tests__/store.test.d.ts.map +1 -0
- package/dist/checkpoint/__tests__/store.test.js +150 -0
- package/dist/checkpoint/__tests__/store.test.js.map +1 -0
- package/dist/checkpoint/blob-store.d.ts +41 -0
- package/dist/checkpoint/blob-store.d.ts.map +1 -0
- package/dist/checkpoint/blob-store.js +119 -0
- package/dist/checkpoint/blob-store.js.map +1 -0
- package/dist/checkpoint/index.d.ts +15 -0
- package/dist/checkpoint/index.d.ts.map +1 -0
- package/dist/checkpoint/index.js +14 -0
- package/dist/checkpoint/index.js.map +1 -0
- package/dist/checkpoint/key.d.ts +39 -0
- package/dist/checkpoint/key.d.ts.map +1 -0
- package/dist/checkpoint/key.js +112 -0
- package/dist/checkpoint/key.js.map +1 -0
- package/dist/checkpoint/runner.d.ts +83 -0
- package/dist/checkpoint/runner.d.ts.map +1 -0
- package/dist/checkpoint/runner.js +146 -0
- package/dist/checkpoint/runner.js.map +1 -0
- package/dist/checkpoint/store.d.ts +91 -0
- package/dist/checkpoint/store.d.ts.map +1 -0
- package/dist/checkpoint/store.js +292 -0
- package/dist/checkpoint/store.js.map +1 -0
- package/dist/checkpoint/types.d.ts +74 -0
- package/dist/checkpoint/types.d.ts.map +1 -0
- package/dist/checkpoint/types.js +16 -0
- package/dist/checkpoint/types.js.map +1 -0
- package/dist/claude-adapter.d.ts +23 -0
- package/dist/claude-adapter.d.ts.map +1 -0
- package/dist/claude-adapter.js +233 -0
- package/dist/claude-adapter.js.map +1 -0
- package/dist/cost.d.ts +67 -0
- package/dist/cost.d.ts.map +1 -0
- package/dist/cost.js +148 -0
- package/dist/cost.js.map +1 -0
- package/dist/data/model-prices.json +39681 -0
- package/dist/fallback-adapter.d.ts +51 -0
- package/dist/fallback-adapter.d.ts.map +1 -0
- package/dist/fallback-adapter.js +116 -0
- package/dist/fallback-adapter.js.map +1 -0
- package/dist/gemini-adapter.d.ts +22 -0
- package/dist/gemini-adapter.d.ts.map +1 -0
- package/dist/gemini-adapter.js +185 -0
- package/dist/gemini-adapter.js.map +1 -0
- package/dist/gemini-cli-adapter.d.ts +24 -0
- package/dist/gemini-cli-adapter.d.ts.map +1 -0
- package/dist/gemini-cli-adapter.js +169 -0
- package/dist/gemini-cli-adapter.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/client.d.ts +32 -0
- package/dist/mcp/client.d.ts.map +1 -0
- package/dist/mcp/client.js +92 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/config-loader.d.ts +36 -0
- package/dist/mcp/config-loader.d.ts.map +1 -0
- package/dist/mcp/config-loader.js +129 -0
- package/dist/mcp/config-loader.js.map +1 -0
- package/dist/mcp/index.d.ts +12 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +11 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/tool-merger.d.ts +18 -0
- package/dist/mcp/tool-merger.d.ts.map +1 -0
- package/dist/mcp/tool-merger.js +34 -0
- package/dist/mcp/tool-merger.js.map +1 -0
- package/dist/mcp/types.d.ts +35 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +10 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/ollama-adapter.d.ts +95 -0
- package/dist/ollama-adapter.d.ts.map +1 -0
- package/dist/ollama-adapter.js +404 -0
- package/dist/ollama-adapter.js.map +1 -0
- package/dist/openai-adapter.d.ts +40 -0
- package/dist/openai-adapter.d.ts.map +1 -0
- package/dist/openai-adapter.js +81 -0
- package/dist/openai-adapter.js.map +1 -0
- package/dist/opencode-adapter.d.ts +39 -0
- package/dist/opencode-adapter.d.ts.map +1 -0
- package/dist/opencode-adapter.js +105 -0
- package/dist/opencode-adapter.js.map +1 -0
- package/dist/openrouter-adapter.d.ts +69 -0
- package/dist/openrouter-adapter.d.ts.map +1 -0
- package/dist/openrouter-adapter.js +481 -0
- package/dist/openrouter-adapter.js.map +1 -0
- package/dist/registry.d.ts +55 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +191 -0
- package/dist/registry.js.map +1 -0
- package/dist/router/circuit-breaker.d.ts +57 -0
- package/dist/router/circuit-breaker.d.ts.map +1 -0
- package/dist/router/circuit-breaker.js +110 -0
- package/dist/router/circuit-breaker.js.map +1 -0
- package/dist/router/config-loader.d.ts +43 -0
- package/dist/router/config-loader.d.ts.map +1 -0
- package/dist/router/config-loader.js +155 -0
- package/dist/router/config-loader.js.map +1 -0
- package/dist/router/discovery.d.ts +37 -0
- package/dist/router/discovery.d.ts.map +1 -0
- package/dist/router/discovery.js +54 -0
- package/dist/router/discovery.js.map +1 -0
- package/dist/router/errors.d.ts +39 -0
- package/dist/router/errors.d.ts.map +1 -0
- package/dist/router/errors.js +103 -0
- package/dist/router/errors.js.map +1 -0
- package/dist/router/index.d.ts +31 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +20 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/local-executor.d.ts +62 -0
- package/dist/router/local-executor.d.ts.map +1 -0
- package/dist/router/local-executor.js +161 -0
- package/dist/router/local-executor.js.map +1 -0
- package/dist/router/model-registry.d.ts +90 -0
- package/dist/router/model-registry.d.ts.map +1 -0
- package/dist/router/model-registry.js +242 -0
- package/dist/router/model-registry.js.map +1 -0
- package/dist/router/rate-limiter.d.ts +63 -0
- package/dist/router/rate-limiter.d.ts.map +1 -0
- package/dist/router/rate-limiter.js +136 -0
- package/dist/router/rate-limiter.js.map +1 -0
- package/dist/router/resolver.d.ts +45 -0
- package/dist/router/resolver.d.ts.map +1 -0
- package/dist/router/resolver.js +71 -0
- package/dist/router/resolver.js.map +1 -0
- package/dist/router/retry.d.ts +58 -0
- package/dist/router/retry.d.ts.map +1 -0
- package/dist/router/retry.js +119 -0
- package/dist/router/retry.js.map +1 -0
- package/dist/router/router.d.ts +100 -0
- package/dist/router/router.d.ts.map +1 -0
- package/dist/router/router.js +306 -0
- package/dist/router/router.js.map +1 -0
- package/dist/router/spend-ledger.d.ts +69 -0
- package/dist/router/spend-ledger.d.ts.map +1 -0
- package/dist/router/spend-ledger.js +191 -0
- package/dist/router/spend-ledger.js.map +1 -0
- package/dist/router/telemetry.d.ts +48 -0
- package/dist/router/telemetry.d.ts.map +1 -0
- package/dist/router/telemetry.js +112 -0
- package/dist/router/telemetry.js.map +1 -0
- package/dist/router/types.d.ts +95 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/router/types.js +16 -0
- package/dist/router/types.js.map +1 -0
- package/dist/single-shot.d.ts +60 -0
- package/dist/single-shot.d.ts.map +1 -0
- package/dist/single-shot.js +385 -0
- package/dist/single-shot.js.map +1 -0
- package/dist/skills/activator.d.ts +17 -0
- package/dist/skills/activator.d.ts.map +1 -0
- package/dist/skills/activator.js +24 -0
- package/dist/skills/activator.js.map +1 -0
- package/dist/skills/compose.d.ts +43 -0
- package/dist/skills/compose.d.ts.map +1 -0
- package/dist/skills/compose.js +53 -0
- package/dist/skills/compose.js.map +1 -0
- package/dist/skills/index.d.ts +17 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +16 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/loader.d.ts +9 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +49 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/parser.d.ts +13 -0
- package/dist/skills/parser.d.ts.map +1 -0
- package/dist/skills/parser.js +60 -0
- package/dist/skills/parser.js.map +1 -0
- package/dist/skills/render.d.ts +11 -0
- package/dist/skills/render.d.ts.map +1 -0
- package/dist/skills/render.js +21 -0
- package/dist/skills/render.js.map +1 -0
- package/dist/skills/resolve-dir.d.ts +20 -0
- package/dist/skills/resolve-dir.d.ts.map +1 -0
- package/dist/skills/resolve-dir.js +30 -0
- package/dist/skills/resolve-dir.js.map +1 -0
- package/dist/skills/tool-policy.d.ts +26 -0
- package/dist/skills/tool-policy.d.ts.map +1 -0
- package/dist/skills/tool-policy.js +33 -0
- package/dist/skills/tool-policy.js.map +1 -0
- package/dist/skills/types.d.ts +42 -0
- package/dist/skills/types.d.ts.map +1 -0
- package/dist/skills/types.js +8 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/stream-format.d.ts +100 -0
- package/dist/stream-format.d.ts.map +1 -0
- package/dist/stream-format.js +90 -0
- package/dist/stream-format.js.map +1 -0
- package/dist/telemetry/attributes.d.ts +38 -0
- package/dist/telemetry/attributes.d.ts.map +1 -0
- package/dist/telemetry/attributes.js +39 -0
- package/dist/telemetry/attributes.js.map +1 -0
- package/dist/telemetry/config.d.ts +30 -0
- package/dist/telemetry/config.d.ts.map +1 -0
- package/dist/telemetry/config.js +54 -0
- package/dist/telemetry/config.js.map +1 -0
- package/dist/telemetry/exporters.d.ts +10 -0
- package/dist/telemetry/exporters.d.ts.map +1 -0
- package/dist/telemetry/exporters.js +46 -0
- package/dist/telemetry/exporters.js.map +1 -0
- package/dist/telemetry/index.d.ts +15 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +12 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/instrument.d.ts +36 -0
- package/dist/telemetry/instrument.d.ts.map +1 -0
- package/dist/telemetry/instrument.js +215 -0
- package/dist/telemetry/instrument.js.map +1 -0
- package/dist/telemetry/metrics.d.ts +45 -0
- package/dist/telemetry/metrics.d.ts.map +1 -0
- package/dist/telemetry/metrics.js +186 -0
- package/dist/telemetry/metrics.js.map +1 -0
- package/dist/telemetry/tracer.d.ts +33 -0
- package/dist/telemetry/tracer.d.ts.map +1 -0
- package/dist/telemetry/tracer.js +162 -0
- package/dist/telemetry/tracer.js.map +1 -0
- package/dist/tools/__tests__/builtin.test.d.ts +7 -0
- package/dist/tools/__tests__/builtin.test.d.ts.map +1 -0
- package/dist/tools/__tests__/builtin.test.js +242 -0
- package/dist/tools/__tests__/builtin.test.js.map +1 -0
- package/dist/tools/builtin.d.ts +29 -0
- package/dist/tools/builtin.d.ts.map +1 -0
- package/dist/tools/builtin.js +367 -0
- package/dist/tools/builtin.js.map +1 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +3 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/path-guard.d.ts +23 -0
- package/dist/tools/path-guard.d.ts.map +1 -0
- package/dist/tools/path-guard.js +66 -0
- package/dist/tools/path-guard.js.map +1 -0
- package/dist/tools/types.d.ts +45 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +11 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/types.d.ts +249 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +22 -0
- package/dist/types.js.map +1 -0
- package/dist/upstream-error.d.ts +64 -0
- package/dist/upstream-error.d.ts.map +1 -0
- package/dist/upstream-error.js +105 -0
- package/dist/upstream-error.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 6 integration tests — exercise full single-shot + adapter paths
|
|
3
|
+
* with telemetry enabled and assert on captured spans.
|
|
4
|
+
*
|
|
5
|
+
* These tests bridge the per-component unit tests (Phase 2/3/4) with
|
|
6
|
+
* end-to-end behaviour:
|
|
7
|
+
* - runClaude in CLI mode → fake claude script → withInvokeSpan path
|
|
8
|
+
* - Default (no env vars) → no spans exported (noop tracer)
|
|
9
|
+
* - ANVIL_OTEL_DISABLED=1 → kill-switch wins even when OTLP endpoint set
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=telemetry-integration.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/telemetry-integration.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 6 integration tests — exercise full single-shot + adapter paths
|
|
3
|
+
* with telemetry enabled and assert on captured spans.
|
|
4
|
+
*
|
|
5
|
+
* These tests bridge the per-component unit tests (Phase 2/3/4) with
|
|
6
|
+
* end-to-end behaviour:
|
|
7
|
+
* - runClaude in CLI mode → fake claude script → withInvokeSpan path
|
|
8
|
+
* - Default (no env vars) → no spans exported (noop tracer)
|
|
9
|
+
* - ANVIL_OTEL_DISABLED=1 → kill-switch wins even when OTLP endpoint set
|
|
10
|
+
*/
|
|
11
|
+
import { describe, it, beforeEach, afterEach } from 'node:test';
|
|
12
|
+
import assert from 'node:assert/strict';
|
|
13
|
+
import { writeFileSync, chmodSync, mkdirSync, rmSync } from 'node:fs';
|
|
14
|
+
import { join } from 'node:path';
|
|
15
|
+
import { tmpdir } from 'node:os';
|
|
16
|
+
import { randomBytes } from 'node:crypto';
|
|
17
|
+
import { trace } from '@opentelemetry/api';
|
|
18
|
+
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
|
|
19
|
+
import { InMemorySpanExporter, SimpleSpanProcessor, } from '@opentelemetry/sdk-trace-base';
|
|
20
|
+
import { resourceFromAttributes } from '@opentelemetry/resources';
|
|
21
|
+
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
|
|
22
|
+
import { resetTracer, loadTelemetryConfig } from '../telemetry/index.js';
|
|
23
|
+
import { GenAi } from '../telemetry/attributes.js';
|
|
24
|
+
// ── Test scaffolding ──────────────────────────────────────────────────────
|
|
25
|
+
function createTempDir() {
|
|
26
|
+
const dir = join(tmpdir(), `anvil-otel-int-${randomBytes(6).toString('hex')}`);
|
|
27
|
+
mkdirSync(dir, { recursive: true });
|
|
28
|
+
return dir;
|
|
29
|
+
}
|
|
30
|
+
function createFakeClaude(dir) {
|
|
31
|
+
const resultLine = JSON.stringify({
|
|
32
|
+
type: 'result',
|
|
33
|
+
result: 'integration ok',
|
|
34
|
+
total_cost_usd: 0.0042,
|
|
35
|
+
usage: { input_tokens: 1234, output_tokens: 567 },
|
|
36
|
+
duration_ms: 100,
|
|
37
|
+
});
|
|
38
|
+
const script = `#!/bin/bash\necho '${resultLine}'\n`;
|
|
39
|
+
const path = join(dir, 'fake-claude');
|
|
40
|
+
writeFileSync(path, script);
|
|
41
|
+
chmodSync(path, 0o755);
|
|
42
|
+
return path;
|
|
43
|
+
}
|
|
44
|
+
let exporter;
|
|
45
|
+
let provider;
|
|
46
|
+
async function installExporter() {
|
|
47
|
+
await resetTracer();
|
|
48
|
+
exporter = new InMemorySpanExporter();
|
|
49
|
+
provider = new NodeTracerProvider({
|
|
50
|
+
resource: resourceFromAttributes({ [ATTR_SERVICE_NAME]: 'anvil-agent-core-test' }),
|
|
51
|
+
spanProcessors: [new SimpleSpanProcessor(exporter)],
|
|
52
|
+
});
|
|
53
|
+
provider.register();
|
|
54
|
+
}
|
|
55
|
+
async function uninstallExporter() {
|
|
56
|
+
try {
|
|
57
|
+
await provider.forceFlush();
|
|
58
|
+
await provider.shutdown();
|
|
59
|
+
}
|
|
60
|
+
catch { }
|
|
61
|
+
exporter.reset();
|
|
62
|
+
trace.disable();
|
|
63
|
+
}
|
|
64
|
+
async function getSpans() {
|
|
65
|
+
await provider.forceFlush();
|
|
66
|
+
return exporter.getFinishedSpans();
|
|
67
|
+
}
|
|
68
|
+
// ── Tests ─────────────────────────────────────────────────────────────────
|
|
69
|
+
describe('Phase 6 integration — runClaude (cli mode) with telemetry', () => {
|
|
70
|
+
beforeEach(installExporter);
|
|
71
|
+
afterEach(uninstallExporter);
|
|
72
|
+
it('emits a gen_ai.invoke span with full attribute set', async () => {
|
|
73
|
+
const tmp = createTempDir();
|
|
74
|
+
const fakeBin = createFakeClaude(tmp);
|
|
75
|
+
// Set env BEFORE dynamic import so claude-runner config picks it up.
|
|
76
|
+
process.env.ANVIL_CLAUDE_BIN = fakeBin;
|
|
77
|
+
process.env.ANVIL_LLM_MODE = 'cli';
|
|
78
|
+
process.env.ANVIL_LLM_MODEL = 'claude-sonnet-4-6';
|
|
79
|
+
delete process.env.ANVIL_LLM_API_KEY;
|
|
80
|
+
try {
|
|
81
|
+
const ssMod = await import(`../single-shot.js?cb=${Date.now()}`);
|
|
82
|
+
ssMod.resetLlmConfig();
|
|
83
|
+
const result = await ssMod.runClaude('hello', 'be helpful', {
|
|
84
|
+
model: 'claude-sonnet-4-6',
|
|
85
|
+
});
|
|
86
|
+
assert.equal(result.result, 'integration ok');
|
|
87
|
+
assert.equal(result.inputTokens, 1234);
|
|
88
|
+
assert.equal(result.outputTokens, 567);
|
|
89
|
+
const spans = await getSpans();
|
|
90
|
+
assert.equal(spans.length, 1);
|
|
91
|
+
const a = spans[0].attributes;
|
|
92
|
+
assert.equal(a[GenAi.SYSTEM], 'claude');
|
|
93
|
+
assert.equal(a[GenAi.REQUEST_MODEL], 'claude-sonnet-4-6');
|
|
94
|
+
assert.equal(a[GenAi.USAGE_INPUT_TOKENS], 1234);
|
|
95
|
+
assert.equal(a[GenAi.USAGE_OUTPUT_TOKENS], 567);
|
|
96
|
+
// Cost from central table (sonnet-4-6: $3/$15) overrides 0.0042
|
|
97
|
+
const cost = a[GenAi.USAGE_COST_USD];
|
|
98
|
+
assert.ok(cost > 0, 'expected cost from central table');
|
|
99
|
+
// Components present
|
|
100
|
+
assert.ok(typeof a[GenAi.USAGE_COST_INPUT_USD] === 'number');
|
|
101
|
+
assert.ok(typeof a[GenAi.USAGE_COST_OUTPUT_USD] === 'number');
|
|
102
|
+
// Anvil extension
|
|
103
|
+
assert.equal(a['anvil.transport'], 'cli');
|
|
104
|
+
assert.equal(spans[0].status.code, 1); // OK
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
delete process.env.ANVIL_CLAUDE_BIN;
|
|
108
|
+
delete process.env.ANVIL_LLM_MODE;
|
|
109
|
+
delete process.env.ANVIL_LLM_MODEL;
|
|
110
|
+
try {
|
|
111
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
112
|
+
}
|
|
113
|
+
catch { }
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
describe('Phase 6 integration — config kill-switches', () => {
|
|
118
|
+
it('default (no env vars) resolves to noop / disabled', () => {
|
|
119
|
+
delete process.env.ANVIL_OTEL_CONSOLE;
|
|
120
|
+
delete process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
121
|
+
delete process.env.ANVIL_OTEL_DISABLED;
|
|
122
|
+
const cfg = loadTelemetryConfig();
|
|
123
|
+
assert.equal(cfg.enabled, false);
|
|
124
|
+
assert.equal(cfg.exporterMode, 'noop');
|
|
125
|
+
});
|
|
126
|
+
it('ANVIL_OTEL_DISABLED=1 wins over OTEL_EXPORTER_OTLP_ENDPOINT', () => {
|
|
127
|
+
process.env.ANVIL_OTEL_DISABLED = '1';
|
|
128
|
+
process.env.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://example.com:4318/v1/traces';
|
|
129
|
+
try {
|
|
130
|
+
const cfg = loadTelemetryConfig();
|
|
131
|
+
assert.equal(cfg.enabled, false);
|
|
132
|
+
assert.equal(cfg.exporterMode, 'noop');
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
delete process.env.ANVIL_OTEL_DISABLED;
|
|
136
|
+
delete process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
it('OTEL_EXPORTER_OTLP_ENDPOINT alone enables otlp mode', () => {
|
|
140
|
+
delete process.env.ANVIL_OTEL_DISABLED;
|
|
141
|
+
process.env.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://localhost:4318/v1/traces';
|
|
142
|
+
try {
|
|
143
|
+
const cfg = loadTelemetryConfig();
|
|
144
|
+
assert.equal(cfg.enabled, true);
|
|
145
|
+
assert.equal(cfg.exporterMode, 'otlp');
|
|
146
|
+
assert.equal(cfg.endpoint, 'http://localhost:4318/v1/traces');
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
delete process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
//# sourceMappingURL=telemetry-integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-integration.test.js","sourceRoot":"","sources":["../../src/__tests__/telemetry-integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 2 telemetry tests — assert that instrumented adapters emit spans
|
|
3
|
+
* with the expected GenAI semantic-convention attributes.
|
|
4
|
+
*
|
|
5
|
+
* The strategy:
|
|
6
|
+
* 1. Reset the agent-core tracer (so it'll re-resolve `trace.getTracer`)
|
|
7
|
+
* 2. Register a test-local NodeTracerProvider with InMemorySpanExporter
|
|
8
|
+
* 3. Run the instrumented adapter against a fake ModelAdapter
|
|
9
|
+
* 4. forceFlush() and read spans out of the exporter
|
|
10
|
+
* 5. Assert attributes
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=telemetry.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/telemetry.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 2 telemetry tests — assert that instrumented adapters emit spans
|
|
3
|
+
* with the expected GenAI semantic-convention attributes.
|
|
4
|
+
*
|
|
5
|
+
* The strategy:
|
|
6
|
+
* 1. Reset the agent-core tracer (so it'll re-resolve `trace.getTracer`)
|
|
7
|
+
* 2. Register a test-local NodeTracerProvider with InMemorySpanExporter
|
|
8
|
+
* 3. Run the instrumented adapter against a fake ModelAdapter
|
|
9
|
+
* 4. forceFlush() and read spans out of the exporter
|
|
10
|
+
* 5. Assert attributes
|
|
11
|
+
*/
|
|
12
|
+
import { describe, it, beforeEach, afterEach } from 'node:test';
|
|
13
|
+
import assert from 'node:assert/strict';
|
|
14
|
+
import { Writable } from 'node:stream';
|
|
15
|
+
import { trace } from '@opentelemetry/api';
|
|
16
|
+
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
|
|
17
|
+
import { InMemorySpanExporter, SimpleSpanProcessor, } from '@opentelemetry/sdk-trace-base';
|
|
18
|
+
import { resourceFromAttributes } from '@opentelemetry/resources';
|
|
19
|
+
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
|
|
20
|
+
import { instrumentModelAdapter } from '../telemetry/instrument.js';
|
|
21
|
+
import { resetTracer } from '../telemetry/tracer.js';
|
|
22
|
+
import { GenAi } from '../telemetry/attributes.js';
|
|
23
|
+
// ── Test-local OTel provider + exporter ────────────────────────────────────
|
|
24
|
+
let exporter;
|
|
25
|
+
let provider;
|
|
26
|
+
async function installInMemoryExporter() {
|
|
27
|
+
await resetTracer();
|
|
28
|
+
exporter = new InMemorySpanExporter();
|
|
29
|
+
provider = new NodeTracerProvider({
|
|
30
|
+
resource: resourceFromAttributes({ [ATTR_SERVICE_NAME]: 'anvil-agent-core-test' }),
|
|
31
|
+
spanProcessors: [new SimpleSpanProcessor(exporter)],
|
|
32
|
+
});
|
|
33
|
+
provider.register();
|
|
34
|
+
}
|
|
35
|
+
async function uninstallInMemoryExporter() {
|
|
36
|
+
try {
|
|
37
|
+
await provider.forceFlush();
|
|
38
|
+
await provider.shutdown();
|
|
39
|
+
}
|
|
40
|
+
catch { }
|
|
41
|
+
exporter.reset();
|
|
42
|
+
trace.disable();
|
|
43
|
+
}
|
|
44
|
+
async function getEmittedSpans() {
|
|
45
|
+
await provider.forceFlush();
|
|
46
|
+
return exporter.getFinishedSpans();
|
|
47
|
+
}
|
|
48
|
+
// ── Fake adapter ───────────────────────────────────────────────────────────
|
|
49
|
+
class FakeAdapter {
|
|
50
|
+
behavior;
|
|
51
|
+
provider = 'claude';
|
|
52
|
+
capabilities = {
|
|
53
|
+
tier: 'agentic',
|
|
54
|
+
streaming: true,
|
|
55
|
+
toolUse: true,
|
|
56
|
+
fileSystem: true,
|
|
57
|
+
shellExecution: true,
|
|
58
|
+
sessionResume: true,
|
|
59
|
+
promptCaching: true,
|
|
60
|
+
};
|
|
61
|
+
constructor(behavior = 'ok') {
|
|
62
|
+
this.behavior = behavior;
|
|
63
|
+
}
|
|
64
|
+
supportsModel(_modelId) { return true; }
|
|
65
|
+
getModelPricing(_modelId) { return [3, 15]; }
|
|
66
|
+
async checkAvailability() { return { available: true }; }
|
|
67
|
+
async run(config, _output) {
|
|
68
|
+
if (this.behavior === 'throw') {
|
|
69
|
+
throw new Error('boom');
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
output: 'fake output',
|
|
73
|
+
inputTokens: 1000,
|
|
74
|
+
outputTokens: 500,
|
|
75
|
+
costUsd: 0.0105,
|
|
76
|
+
durationMs: 42,
|
|
77
|
+
sessionId: 'sess-abc',
|
|
78
|
+
provider: this.provider,
|
|
79
|
+
model: config.model,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const NULL_STREAM = new Writable({ write(_c, _e, cb) { cb(); } });
|
|
84
|
+
const BASE_CONFIG = {
|
|
85
|
+
userPrompt: 'hello world',
|
|
86
|
+
projectPrompt: undefined,
|
|
87
|
+
model: 'claude-sonnet-4-6',
|
|
88
|
+
workingDir: '/tmp',
|
|
89
|
+
stage: 'build',
|
|
90
|
+
persona: 'engineer',
|
|
91
|
+
allowedTools: ['Read', 'Edit', 'Bash'],
|
|
92
|
+
};
|
|
93
|
+
// ── Tests ──────────────────────────────────────────────────────────────────
|
|
94
|
+
describe('telemetry — instrumentModelAdapter', () => {
|
|
95
|
+
beforeEach(installInMemoryExporter);
|
|
96
|
+
afterEach(uninstallInMemoryExporter);
|
|
97
|
+
afterEach(() => {
|
|
98
|
+
delete process.env.ANVIL_OTEL_RECORD_CONTENT;
|
|
99
|
+
});
|
|
100
|
+
it('emits a span with GenAI request + response attributes on success', async () => {
|
|
101
|
+
const wrapped = instrumentModelAdapter(new FakeAdapter('ok'));
|
|
102
|
+
const result = await wrapped.run(BASE_CONFIG, NULL_STREAM);
|
|
103
|
+
assert.equal(result.output, 'fake output');
|
|
104
|
+
const spans = await getEmittedSpans();
|
|
105
|
+
assert.equal(spans.length, 1);
|
|
106
|
+
const s = spans[0];
|
|
107
|
+
assert.equal(s.name, 'gen_ai.invoke');
|
|
108
|
+
assert.equal(s.attributes[GenAi.SYSTEM], 'claude');
|
|
109
|
+
assert.equal(s.attributes[GenAi.REQUEST_MODEL], 'claude-sonnet-4-6');
|
|
110
|
+
assert.equal(s.attributes[GenAi.USAGE_INPUT_TOKENS], 1000);
|
|
111
|
+
assert.equal(s.attributes[GenAi.USAGE_OUTPUT_TOKENS], 500);
|
|
112
|
+
// Phase 4 wrapper recomputes cost from the central table for known models.
|
|
113
|
+
// FP rounding means 0.003 + 0.0075 ≈ 0.010499999999999999 — assert within ε.
|
|
114
|
+
assert.ok(Math.abs(s.attributes[GenAi.USAGE_COST_USD] - 0.0105) < 1e-9, `expected cost ≈ 0.0105, got ${s.attributes[GenAi.USAGE_COST_USD]}`);
|
|
115
|
+
assert.equal(s.attributes[GenAi.RESPONSE_ID], 'sess-abc');
|
|
116
|
+
assert.equal(s.attributes['anvil.stage'], 'build');
|
|
117
|
+
assert.equal(s.attributes['anvil.persona'], 'engineer');
|
|
118
|
+
assert.equal(s.attributes[GenAi.TOOLS_COUNT], 3);
|
|
119
|
+
assert.equal(s.status.code, 1); // OK
|
|
120
|
+
});
|
|
121
|
+
it('does NOT include prompt/completion text by default', async () => {
|
|
122
|
+
const wrapped = instrumentModelAdapter(new FakeAdapter('ok'));
|
|
123
|
+
await wrapped.run(BASE_CONFIG, NULL_STREAM);
|
|
124
|
+
const spans = await getEmittedSpans();
|
|
125
|
+
const attrs = spans[0].attributes;
|
|
126
|
+
assert.equal(attrs[GenAi.PROMPT], undefined);
|
|
127
|
+
assert.equal(attrs[GenAi.COMPLETION], undefined);
|
|
128
|
+
});
|
|
129
|
+
it('records prompt and completion when ANVIL_OTEL_RECORD_CONTENT=1', async () => {
|
|
130
|
+
process.env.ANVIL_OTEL_RECORD_CONTENT = '1';
|
|
131
|
+
const wrapped = instrumentModelAdapter(new FakeAdapter('ok'));
|
|
132
|
+
await wrapped.run(BASE_CONFIG, NULL_STREAM);
|
|
133
|
+
const spans = await getEmittedSpans();
|
|
134
|
+
const attrs = spans[0].attributes;
|
|
135
|
+
assert.equal(attrs[GenAi.PROMPT], 'hello world');
|
|
136
|
+
assert.equal(attrs[GenAi.COMPLETION], 'fake output');
|
|
137
|
+
});
|
|
138
|
+
it('sets ERROR status and records exception when adapter throws', async () => {
|
|
139
|
+
const wrapped = instrumentModelAdapter(new FakeAdapter('throw'));
|
|
140
|
+
await assert.rejects(() => wrapped.run(BASE_CONFIG, NULL_STREAM), /boom/);
|
|
141
|
+
const spans = await getEmittedSpans();
|
|
142
|
+
assert.equal(spans.length, 1);
|
|
143
|
+
const s = spans[0];
|
|
144
|
+
assert.equal(s.status.code, 2); // ERROR
|
|
145
|
+
assert.match(s.status.message ?? '', /boom/);
|
|
146
|
+
assert.ok(s.events.length >= 1, 'expected an exception event recorded');
|
|
147
|
+
const exEvent = s.events.find((e) => e.name === 'exception');
|
|
148
|
+
assert.ok(exEvent, 'expected exception event');
|
|
149
|
+
});
|
|
150
|
+
it('preserves all delegating ModelAdapter methods', async () => {
|
|
151
|
+
const inner = new FakeAdapter('ok');
|
|
152
|
+
const wrapped = instrumentModelAdapter(inner);
|
|
153
|
+
assert.equal(wrapped.provider, 'claude');
|
|
154
|
+
assert.equal(wrapped.capabilities.tier, 'agentic');
|
|
155
|
+
assert.equal(wrapped.supportsModel('any'), true);
|
|
156
|
+
assert.deepEqual(wrapped.getModelPricing('any'), [3, 15]);
|
|
157
|
+
const avail = await wrapped.checkAvailability();
|
|
158
|
+
assert.equal(avail.available, true);
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
//# sourceMappingURL=telemetry.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.test.js","sourceRoot":"","sources":["../../src/__tests__/telemetry.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UpstreamError — shared contract for all adapters' chain-fallback
|
|
3
|
+
* trigger. The dashboard's runStageWithFallback duck-types this shape
|
|
4
|
+
* (name + retryable + status). Lock the classification rules so a
|
|
5
|
+
* future tweak doesn't silently regress chain-fallback behavior.
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=upstream-error.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upstream-error.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/upstream-error.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UpstreamError — shared contract for all adapters' chain-fallback
|
|
3
|
+
* trigger. The dashboard's runStageWithFallback duck-types this shape
|
|
4
|
+
* (name + retryable + status). Lock the classification rules so a
|
|
5
|
+
* future tweak doesn't silently regress chain-fallback behavior.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, it } from 'node:test';
|
|
8
|
+
import assert from 'node:assert/strict';
|
|
9
|
+
import { UpstreamError, isRetryableStatus, bodyLooksRetryable, synthesizeStatusFromCli, } from '../upstream-error.js';
|
|
10
|
+
describe('UpstreamError — status-based classification', () => {
|
|
11
|
+
it('marks 429 / 502 / 503 / 504 / 0 retryable', () => {
|
|
12
|
+
for (const status of [429, 502, 503, 504, 0, 408, 425]) {
|
|
13
|
+
const e = new UpstreamError(status, '', { provider: 'test' });
|
|
14
|
+
assert.equal(e.retryable, true, `status=${status} should be retryable`);
|
|
15
|
+
assert.equal(e.status, status);
|
|
16
|
+
assert.equal(e.name, 'UpstreamError');
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
it('marks 400 / 401 / 403 / 404 NOT retryable (config errors)', () => {
|
|
20
|
+
for (const status of [400, 401, 403, 404, 422]) {
|
|
21
|
+
const e = new UpstreamError(status, '', { provider: 'test' });
|
|
22
|
+
assert.equal(e.retryable, false, `status=${status} should NOT be retryable`);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
it('overrides retryable when explicitly passed', () => {
|
|
26
|
+
const forced = new UpstreamError(400, '', { provider: 'x', retryable: true });
|
|
27
|
+
assert.equal(forced.retryable, true);
|
|
28
|
+
const suppressed = new UpstreamError(429, '', { provider: 'x', retryable: false });
|
|
29
|
+
assert.equal(suppressed.retryable, false);
|
|
30
|
+
});
|
|
31
|
+
it('promotes to retryable when body matches a known transient pattern', () => {
|
|
32
|
+
// 200/400 with quota body — happens with OpenRouter wrapping upstreams.
|
|
33
|
+
const cases = [
|
|
34
|
+
'insufficient_quota',
|
|
35
|
+
'rate_limit_exceeded',
|
|
36
|
+
'overloaded_error',
|
|
37
|
+
'RESOURCE_EXHAUSTED',
|
|
38
|
+
'Quota exceeded for project',
|
|
39
|
+
'server is busy, please retry',
|
|
40
|
+
'Too many requests, slow down',
|
|
41
|
+
];
|
|
42
|
+
for (const body of cases) {
|
|
43
|
+
const e = new UpstreamError(400, body, { provider: 'test' });
|
|
44
|
+
assert.equal(e.retryable, true, `body="${body}" should mark retryable`);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
it('formats a clean message including provider + truncated body', () => {
|
|
48
|
+
const e = new UpstreamError(429, 'rate_limit_exceeded', { provider: 'anthropic' });
|
|
49
|
+
assert.match(e.message, /^anthropic 429: rate_limit_exceeded/);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
describe('isRetryableStatus', () => {
|
|
53
|
+
it('returns the canonical retryable set', () => {
|
|
54
|
+
const retryable = [0, 408, 425, 429, 502, 503, 504];
|
|
55
|
+
const terminal = [200, 201, 301, 400, 401, 403, 404, 422, 500, 501];
|
|
56
|
+
for (const s of retryable)
|
|
57
|
+
assert.equal(isRetryableStatus(s), true, String(s));
|
|
58
|
+
for (const s of terminal)
|
|
59
|
+
assert.equal(isRetryableStatus(s), false, String(s));
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe('bodyLooksRetryable', () => {
|
|
63
|
+
it('matches common transient-condition phrasings', () => {
|
|
64
|
+
const yes = [
|
|
65
|
+
'insufficient_quota',
|
|
66
|
+
'Insufficient Quota',
|
|
67
|
+
'rate_limit_error',
|
|
68
|
+
'rate-limit exceeded',
|
|
69
|
+
'overloaded_error',
|
|
70
|
+
'resource_exhausted',
|
|
71
|
+
'RESOURCE EXHAUSTED',
|
|
72
|
+
'Quota exceeded for the day',
|
|
73
|
+
'server busy, retry shortly',
|
|
74
|
+
'Service is temporarily unavailable',
|
|
75
|
+
'too many requests',
|
|
76
|
+
"qwen/qwen3-coder:free is temporarily rate-limited upstream",
|
|
77
|
+
];
|
|
78
|
+
for (const body of yes)
|
|
79
|
+
assert.equal(bodyLooksRetryable(body), true, body);
|
|
80
|
+
});
|
|
81
|
+
it('does NOT match auth / config / null bodies', () => {
|
|
82
|
+
const no = [
|
|
83
|
+
'',
|
|
84
|
+
'invalid api key',
|
|
85
|
+
'unauthorized',
|
|
86
|
+
'permission_denied',
|
|
87
|
+
'context length exceeded', // model-side limit, not retryable to a different model
|
|
88
|
+
'invalid_request_error',
|
|
89
|
+
];
|
|
90
|
+
for (const body of no)
|
|
91
|
+
assert.equal(bodyLooksRetryable(body), false, body);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
describe('synthesizeStatusFromCli — CLI subprocess stderr classification', () => {
|
|
95
|
+
it('maps Anthropic CLI quota / rate-limit stderr to retryable 429', () => {
|
|
96
|
+
const cases = [
|
|
97
|
+
'rate_limit_error: Number of request tokens has exceeded',
|
|
98
|
+
'overloaded_error: Server is overloaded; retry later',
|
|
99
|
+
'Credit balance is too low to access the Anthropic API',
|
|
100
|
+
'429 Too Many Requests',
|
|
101
|
+
'insufficient_quota for organization',
|
|
102
|
+
];
|
|
103
|
+
for (const stderr of cases) {
|
|
104
|
+
const r = synthesizeStatusFromCli(stderr);
|
|
105
|
+
assert.ok(r, `expected synth for "${stderr}"`);
|
|
106
|
+
assert.equal(r.status, 429);
|
|
107
|
+
assert.equal(r.retryable, true);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
it('maps Gemini CLI quota / rate-limit stderr to retryable 429', () => {
|
|
111
|
+
const cases = [
|
|
112
|
+
'RESOURCE_EXHAUSTED: Quota exceeded for project foo',
|
|
113
|
+
'Quota exceeded for metric: generate_content_free_tier_requests',
|
|
114
|
+
'rate limit exceeded: 60 requests/minute',
|
|
115
|
+
];
|
|
116
|
+
for (const stderr of cases) {
|
|
117
|
+
const r = synthesizeStatusFromCli(stderr);
|
|
118
|
+
assert.ok(r, `expected synth for "${stderr}"`);
|
|
119
|
+
assert.equal(r.status, 429);
|
|
120
|
+
assert.equal(r.retryable, true);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
it('maps outage signals to retryable 503', () => {
|
|
124
|
+
const cases = [
|
|
125
|
+
'INTERNAL Server Error',
|
|
126
|
+
'503 Service Unavailable',
|
|
127
|
+
'Gateway timeout reached',
|
|
128
|
+
];
|
|
129
|
+
for (const stderr of cases) {
|
|
130
|
+
const r = synthesizeStatusFromCli(stderr);
|
|
131
|
+
assert.ok(r, `expected synth for "${stderr}"`);
|
|
132
|
+
assert.equal(r.status, 503);
|
|
133
|
+
assert.equal(r.retryable, true);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
it('maps auth errors to NON-retryable 401', () => {
|
|
137
|
+
const cases = [
|
|
138
|
+
'Invalid API key',
|
|
139
|
+
'API key not valid',
|
|
140
|
+
'Unauthorized: 401',
|
|
141
|
+
'permission denied for project',
|
|
142
|
+
];
|
|
143
|
+
for (const stderr of cases) {
|
|
144
|
+
const r = synthesizeStatusFromCli(stderr);
|
|
145
|
+
assert.ok(r, `expected synth for "${stderr}"`);
|
|
146
|
+
assert.equal(r.status, 401);
|
|
147
|
+
assert.equal(r.retryable, false);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
it('returns undefined for unknown stderr (caller falls back to plain Error)', () => {
|
|
151
|
+
assert.equal(synthesizeStatusFromCli(''), undefined);
|
|
152
|
+
assert.equal(synthesizeStatusFromCli('Segmentation fault'), undefined);
|
|
153
|
+
assert.equal(synthesizeStatusFromCli('Cannot find module foo'), undefined);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
describe('Dashboard duck-type compatibility', () => {
|
|
157
|
+
// Mirror the exact check from
|
|
158
|
+
// packages/dashboard/server/pipeline-runner.ts:333 — every adapter's
|
|
159
|
+
// UpstreamError MUST satisfy this so chain-fallback works.
|
|
160
|
+
function isRetryableUpstreamError(err) {
|
|
161
|
+
if (!err || typeof err !== 'object')
|
|
162
|
+
return false;
|
|
163
|
+
const e = err;
|
|
164
|
+
if (e.retryable === true)
|
|
165
|
+
return true;
|
|
166
|
+
if (e.name === 'UpstreamError' && typeof e.status === 'number') {
|
|
167
|
+
return e.status === 429 || e.status === 502 || e.status === 503 || e.status === 504;
|
|
168
|
+
}
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
it('retryable UpstreamError instances pass the dashboard duck-type', () => {
|
|
172
|
+
const e1 = new UpstreamError(429, 'rate_limit', { provider: 'anthropic' });
|
|
173
|
+
const e2 = new UpstreamError(503, 'overloaded', { provider: 'gemini' });
|
|
174
|
+
const e3 = new UpstreamError(400, 'overloaded_error', { provider: 'anthropic' }); // body-promoted
|
|
175
|
+
assert.equal(isRetryableUpstreamError(e1), true);
|
|
176
|
+
assert.equal(isRetryableUpstreamError(e2), true);
|
|
177
|
+
assert.equal(isRetryableUpstreamError(e3), true);
|
|
178
|
+
});
|
|
179
|
+
it('non-retryable UpstreamError instances are correctly rejected', () => {
|
|
180
|
+
const e1 = new UpstreamError(401, 'invalid api key', { provider: 'gemini' });
|
|
181
|
+
const e2 = new UpstreamError(400, 'invalid_request_error', { provider: 'anthropic' });
|
|
182
|
+
assert.equal(isRetryableUpstreamError(e1), false);
|
|
183
|
+
assert.equal(isRetryableUpstreamError(e2), false);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
//# sourceMappingURL=upstream-error.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upstream-error.test.js","sourceRoot":"","sources":["../../src/__tests__/upstream-error.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google ADK adapter — agentic, provider-agnostic.
|
|
3
|
+
*
|
|
4
|
+
* Drives `@google/adk` (≥ 1.1.0) end-to-end:
|
|
5
|
+
* 1. Builds an `LlmAgent` with the requested model.
|
|
6
|
+
* 2. Wraps `BuiltinToolExecutor`'s schemas as ADK `FunctionTool`s.
|
|
7
|
+
* 3. Runs the agent through ADK's `Runner` + `InMemorySessionService`.
|
|
8
|
+
* 4. Translates each emitted ADK `Event` into Anvil Stream Format
|
|
9
|
+
* lines (text → emitContent, FunctionCall → emitToolUse,
|
|
10
|
+
* FunctionResponse → emitToolResult).
|
|
11
|
+
*
|
|
12
|
+
* Provider routing:
|
|
13
|
+
* - Model ids prefixed `adk:` (e.g. `adk:claude-sonnet-4-6`,
|
|
14
|
+
* `adk:gemini-2.5-flash`) route to this adapter via the
|
|
15
|
+
* `default-adapter-factory` resolver. Claude models go through the
|
|
16
|
+
* custom `AnthropicLlm` (registered idempotently here); Gemini
|
|
17
|
+
* models flow through ADK's built-in `Gemini` Llm.
|
|
18
|
+
* - The prefix is stripped before being handed to ADK's
|
|
19
|
+
* `LLMRegistry`, which matches against the model id directly
|
|
20
|
+
* (e.g. `^claude-/`).
|
|
21
|
+
*
|
|
22
|
+
* Capabilities are `tier: 'agentic'` because the Runner drives a real
|
|
23
|
+
* tool loop. Per-call `AbortController` + buffered emitContent match
|
|
24
|
+
* the patterns in `OllamaAdapter` / `OpenRouterAdapter` so concurrent
|
|
25
|
+
* spawns (per-repo backend + frontend) don't trample each other.
|
|
26
|
+
*
|
|
27
|
+
* Auth: `ANTHROPIC_API_KEY` for Claude models, `GOOGLE_API_KEY` /
|
|
28
|
+
* `GEMINI_API_KEY` for Gemini.
|
|
29
|
+
*/
|
|
30
|
+
import type { ModelAdapter, ModelAdapterConfig, ModelAdapterResult, ProviderCapabilities, ProviderName } from './types.js';
|
|
31
|
+
export declare class AdkAdapter implements ModelAdapter {
|
|
32
|
+
readonly provider: ProviderName;
|
|
33
|
+
readonly capabilities: ProviderCapabilities;
|
|
34
|
+
private readonly abortControllers;
|
|
35
|
+
supportsModel(modelId: string): boolean;
|
|
36
|
+
getModelPricing(modelId: string): [number, number] | null;
|
|
37
|
+
checkAvailability(): Promise<{
|
|
38
|
+
available: boolean;
|
|
39
|
+
version?: string;
|
|
40
|
+
error?: string;
|
|
41
|
+
}>;
|
|
42
|
+
run(config: ModelAdapterConfig, output: NodeJS.WritableStream): Promise<ModelAdapterResult>;
|
|
43
|
+
kill(): void;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=adk-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adk-adapter.d.ts","sourceRoot":"","sources":["../src/adk-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EAEb,MAAM,YAAY,CAAC;AAoDpB,qBAAa,UAAW,YAAW,YAAY;IAC7C,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAS;IACxC,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAWzC;IAEF,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA8B;IAE/D,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIvC,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAKnD,iBAAiB,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAuBtF,GAAG,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,CAAC,cAAc,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA6LjG,IAAI,IAAI,IAAI;CAMb"}
|