@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,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `LlmRouter` — single source of truth for routing, retries, fallbacks,
|
|
3
|
+
* rate-limits, spend tracking, and circuit breaking.
|
|
4
|
+
*
|
|
5
|
+
* Phase 5: walks the full fallback chain. Per-error gates control which
|
|
6
|
+
* fallback steps are eligible. content_policy / auth / invalid_request
|
|
7
|
+
* never trigger cross-provider fallback (security default).
|
|
8
|
+
*/
|
|
9
|
+
import { RouterError, classifyError } from './errors.js';
|
|
10
|
+
import { DEFAULT_RETRY_POLICY, runWithRetry } from './retry.js';
|
|
11
|
+
import { TokenBucketRateLimiter } from './rate-limiter.js';
|
|
12
|
+
import { CircuitBreaker } from './circuit-breaker.js';
|
|
13
|
+
export class LlmRouter {
|
|
14
|
+
config;
|
|
15
|
+
resolver;
|
|
16
|
+
rateLimiter;
|
|
17
|
+
circuitBreaker;
|
|
18
|
+
ledger;
|
|
19
|
+
newId;
|
|
20
|
+
now;
|
|
21
|
+
sleep;
|
|
22
|
+
random;
|
|
23
|
+
errorClassifiers;
|
|
24
|
+
constructor(deps) {
|
|
25
|
+
this.config = deps.config;
|
|
26
|
+
this.resolver = deps.resolver;
|
|
27
|
+
this.ledger = deps.ledger;
|
|
28
|
+
this.newId = deps.newId ?? defaultNewId;
|
|
29
|
+
this.now = deps.now ?? Date.now;
|
|
30
|
+
this.sleep = deps.sleep;
|
|
31
|
+
this.random = deps.random;
|
|
32
|
+
this.errorClassifiers = deps.errorClassifiers ?? {};
|
|
33
|
+
this.rateLimiter =
|
|
34
|
+
deps.rateLimiter ??
|
|
35
|
+
new TokenBucketRateLimiter({
|
|
36
|
+
config: deps.config.rateLimit,
|
|
37
|
+
now: deps.now,
|
|
38
|
+
sleep: deps.sleep
|
|
39
|
+
? (ms) => deps.sleep(ms)
|
|
40
|
+
: undefined,
|
|
41
|
+
onRateLimit: deps.config.onRateLimit,
|
|
42
|
+
});
|
|
43
|
+
this.circuitBreaker =
|
|
44
|
+
deps.circuitBreaker ??
|
|
45
|
+
new CircuitBreaker({
|
|
46
|
+
config: deps.config.circuitBreaker,
|
|
47
|
+
now: deps.now,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/** Inspect the active config (immutable snapshot). */
|
|
51
|
+
getConfig() {
|
|
52
|
+
return this.config;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolve the route for a tag (or pinned model) and walk the chain
|
|
56
|
+
* primary → fallback[0] → fallback[1] until either success or the
|
|
57
|
+
* chain is exhausted.
|
|
58
|
+
*
|
|
59
|
+
* Per ADR R5:
|
|
60
|
+
* - auth / content_policy / invalid_request never trigger fallback
|
|
61
|
+
* - rate_limit / server_5xx / timeout default to the full chain;
|
|
62
|
+
* RouteFallback.on can restrict per-step
|
|
63
|
+
* - All attempts are ledgered (including failed ones with cost)
|
|
64
|
+
*/
|
|
65
|
+
async invoke(opts) {
|
|
66
|
+
const startedAt = this.now();
|
|
67
|
+
if (!this.resolver) {
|
|
68
|
+
throw new Error('LlmRouter.invoke requires an AdapterResolver (deps.resolver)');
|
|
69
|
+
}
|
|
70
|
+
// Pre-flight budget enforcement (Phase 4)
|
|
71
|
+
this.enforceBudgetPreflight(opts);
|
|
72
|
+
const chain = this.buildChain(opts);
|
|
73
|
+
const allAttempts = [];
|
|
74
|
+
let totalCostUsd = 0;
|
|
75
|
+
let lastError;
|
|
76
|
+
let lastErrorClass;
|
|
77
|
+
let priorAttempted = false; // true once any step has actually run
|
|
78
|
+
const maxCost = this.config.maxFallbackCostUsd ?? 1.0;
|
|
79
|
+
for (let step = 0; step < chain.length; step += 1) {
|
|
80
|
+
const link = chain[step];
|
|
81
|
+
const adapter = this.resolver.resolve(link.model);
|
|
82
|
+
// Skip non-primary steps whose `on` gate doesn't match the previous
|
|
83
|
+
// error. If no step has yet attempted (e.g., circuit breaker skipped
|
|
84
|
+
// every prior step) we let the fallback run regardless of its gate —
|
|
85
|
+
// there's no prior error to filter against.
|
|
86
|
+
if (step > 0 && priorAttempted && !this.shouldTryFallback(link, lastErrorClass)) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
// Circuit-breaker — if open, skip this provider entirely (no adapter
|
|
90
|
+
// call, no rate-limit consumption, no ledger row).
|
|
91
|
+
if (!this.circuitBreaker.canAttempt(adapter.provider)) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
this.circuitBreaker.reserveAttempt(adapter.provider);
|
|
95
|
+
priorAttempted = true;
|
|
96
|
+
const llmOpts = this.buildInvokeOpts(opts, link.model);
|
|
97
|
+
const estimatedTokens = this.estimateTokens(llmOpts);
|
|
98
|
+
const policyFor = (cls) => this.config.retryPolicy[cls] ?? DEFAULT_RETRY_POLICY[cls];
|
|
99
|
+
const classify = (err) => {
|
|
100
|
+
const override = this.errorClassifiers[adapter.provider];
|
|
101
|
+
return override?.(err) ?? classifyError(err);
|
|
102
|
+
};
|
|
103
|
+
const retryRun = await runWithRetry(async () => {
|
|
104
|
+
await this.rateLimiter.acquire(adapter.provider, estimatedTokens);
|
|
105
|
+
return adapter.invoke(llmOpts);
|
|
106
|
+
}, {
|
|
107
|
+
policyFor,
|
|
108
|
+
classify,
|
|
109
|
+
sleep: this.sleep,
|
|
110
|
+
now: this.now,
|
|
111
|
+
random: this.random,
|
|
112
|
+
signal: opts.signal,
|
|
113
|
+
});
|
|
114
|
+
const stepAttempts = retryRun.attempts.map((a) => ({
|
|
115
|
+
model: link.model,
|
|
116
|
+
provider: adapter.provider,
|
|
117
|
+
attemptIndex: a.index,
|
|
118
|
+
fallbackIndex: step,
|
|
119
|
+
errorClass: a.errorClass,
|
|
120
|
+
durationMs: a.durationMs,
|
|
121
|
+
costUsd: undefined,
|
|
122
|
+
}));
|
|
123
|
+
allAttempts.push(...stepAttempts);
|
|
124
|
+
if (retryRun.result) {
|
|
125
|
+
const last = stepAttempts[stepAttempts.length - 1];
|
|
126
|
+
if (last)
|
|
127
|
+
last.costUsd = retryRun.result.costUsd;
|
|
128
|
+
totalCostUsd += retryRun.result.costUsd;
|
|
129
|
+
this.recordSpend(opts, adapter.provider, link.model, stepAttempts, retryRun.result, undefined);
|
|
130
|
+
this.circuitBreaker.recordSuccess(adapter.provider);
|
|
131
|
+
const outcome = {
|
|
132
|
+
result: retryRun.result,
|
|
133
|
+
attempts: allAttempts,
|
|
134
|
+
totalDurationMs: Math.max(0, this.now() - startedAt),
|
|
135
|
+
totalCostUsd,
|
|
136
|
+
};
|
|
137
|
+
this.populateBudgetRemaining(outcome, opts);
|
|
138
|
+
return outcome;
|
|
139
|
+
}
|
|
140
|
+
lastError = retryRun.error ?? new Error('LlmRouter: unknown failure');
|
|
141
|
+
lastErrorClass = stepAttempts[stepAttempts.length - 1]?.errorClass ?? 'unknown';
|
|
142
|
+
// Record this step's spend regardless (even though no cost was billed).
|
|
143
|
+
this.recordSpend(opts, adapter.provider, link.model, stepAttempts, undefined, lastError);
|
|
144
|
+
// Update circuit breaker: only retryable provider faults count
|
|
145
|
+
// toward tripping the breaker — auth/content_policy/invalid_request
|
|
146
|
+
// are caller / data issues, not provider health, so they don't open
|
|
147
|
+
// the circuit.
|
|
148
|
+
if (!isTerminal(lastErrorClass)) {
|
|
149
|
+
this.circuitBreaker.recordFailure(adapter.provider);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
// Terminal classes leave breaker state untouched and short-circuit.
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
// Per-call cost ceiling — abort the chain if we've already exceeded it.
|
|
156
|
+
if (totalCostUsd > maxCost) {
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
const finalErr = lastError ?? new Error('LlmRouter: chain produced no error and no result');
|
|
161
|
+
throw new RouterError(`route '${opts.tag}' failed: ${finalErr.message}`, {
|
|
162
|
+
attempts: allAttempts,
|
|
163
|
+
cause: finalErr,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
/** Build the ordered chain of (model, on-gate) steps for a given tag. */
|
|
167
|
+
buildChain(opts) {
|
|
168
|
+
if (opts.model) {
|
|
169
|
+
// Pinned model — no fallbacks (escape hatch).
|
|
170
|
+
return [{ model: opts.model }];
|
|
171
|
+
}
|
|
172
|
+
const route = this.config.routes.find((r) => r.tag === opts.tag);
|
|
173
|
+
if (!route) {
|
|
174
|
+
throw new Error(`LlmRouter: no route for tag '${opts.tag}' (and no opts.model pin)`);
|
|
175
|
+
}
|
|
176
|
+
const chain = [{ model: route.primary }];
|
|
177
|
+
for (const fb of route.fallbacks ?? []) {
|
|
178
|
+
chain.push({ model: fb.model, on: fb.on });
|
|
179
|
+
}
|
|
180
|
+
return chain;
|
|
181
|
+
}
|
|
182
|
+
/** Decide whether to try this fallback step given the prior error class. */
|
|
183
|
+
shouldTryFallback(fallback, priorClass) {
|
|
184
|
+
if (!priorClass)
|
|
185
|
+
return false;
|
|
186
|
+
if (isTerminal(priorClass))
|
|
187
|
+
return false;
|
|
188
|
+
// No `on` filter means "any retryable error".
|
|
189
|
+
if (!fallback.on || fallback.on.length === 0)
|
|
190
|
+
return true;
|
|
191
|
+
return fallback.on.includes(priorClass);
|
|
192
|
+
}
|
|
193
|
+
// ── Budget + ledger helpers ────────────────────────────────────────────
|
|
194
|
+
enforceBudgetPreflight(opts) {
|
|
195
|
+
if (!this.ledger || !this.config.budgets)
|
|
196
|
+
return;
|
|
197
|
+
const remaining = this.computeRemainingBudget(opts);
|
|
198
|
+
if (remaining === undefined)
|
|
199
|
+
return;
|
|
200
|
+
if (remaining > 0)
|
|
201
|
+
return;
|
|
202
|
+
const breach = this.config.budgets.onBreach;
|
|
203
|
+
if (breach === 'fail') {
|
|
204
|
+
throw new Error(`LlmRouter: budget exhausted for tag='${opts.tag}' (run='${opts.runId ?? ''}')`);
|
|
205
|
+
}
|
|
206
|
+
if (breach === 'queue') {
|
|
207
|
+
throw new Error(`LlmRouter: budget exhausted; queue mode not yet implemented`);
|
|
208
|
+
}
|
|
209
|
+
// 'downgrade' — Phase 5 will pick a cheaper fallback. Phase 4 lets the call
|
|
210
|
+
// through and trusts the per-call cap.
|
|
211
|
+
}
|
|
212
|
+
computeRemainingBudget(opts) {
|
|
213
|
+
if (!this.ledger || !this.config.budgets)
|
|
214
|
+
return undefined;
|
|
215
|
+
const b = this.config.budgets;
|
|
216
|
+
let remaining;
|
|
217
|
+
const setMin = (val) => {
|
|
218
|
+
remaining = remaining === undefined ? val : Math.min(remaining, val);
|
|
219
|
+
};
|
|
220
|
+
if (b.dailyUsd !== undefined) {
|
|
221
|
+
const since = startOfTodayIso();
|
|
222
|
+
setMin(b.dailyUsd - this.ledger.totalUsd({ since }));
|
|
223
|
+
}
|
|
224
|
+
if (b.perRunUsd !== undefined && opts.runId) {
|
|
225
|
+
setMin(b.perRunUsd - this.ledger.totalUsd({ runId: opts.runId }));
|
|
226
|
+
}
|
|
227
|
+
const tagCap = b.perTagUsd?.[opts.tag];
|
|
228
|
+
if (tagCap !== undefined) {
|
|
229
|
+
setMin(tagCap - this.ledger.totalUsd({ tag: opts.tag }));
|
|
230
|
+
}
|
|
231
|
+
return remaining;
|
|
232
|
+
}
|
|
233
|
+
populateBudgetRemaining(outcome, opts) {
|
|
234
|
+
const r = this.computeRemainingBudget(opts);
|
|
235
|
+
if (r !== undefined)
|
|
236
|
+
outcome.budgetRemainingUsd = r;
|
|
237
|
+
}
|
|
238
|
+
recordSpend(opts, provider, modelId, attempts, result, err) {
|
|
239
|
+
if (!this.ledger)
|
|
240
|
+
return;
|
|
241
|
+
const last = attempts[attempts.length - 1];
|
|
242
|
+
this.ledger.record({
|
|
243
|
+
id: this.newId(),
|
|
244
|
+
ts: new Date(this.now()).toISOString(),
|
|
245
|
+
runId: opts.runId,
|
|
246
|
+
project: opts.project,
|
|
247
|
+
user: opts.user,
|
|
248
|
+
tag: opts.tag,
|
|
249
|
+
provider,
|
|
250
|
+
model: modelId,
|
|
251
|
+
inputTokens: result?.usage.inputTokens ?? 0,
|
|
252
|
+
outputTokens: result?.usage.outputTokens ?? 0,
|
|
253
|
+
cacheReadTokens: result?.usage.cacheReadTokens ?? 0,
|
|
254
|
+
cacheWriteTokens: result?.usage.cacheWriteTokens ?? 0,
|
|
255
|
+
costUsd: result?.costUsd ?? 0,
|
|
256
|
+
durationMs: attempts.reduce((a, x) => a + x.durationMs, 0),
|
|
257
|
+
fallbackIndex: last?.fallbackIndex ?? 0,
|
|
258
|
+
attemptCount: attempts.length,
|
|
259
|
+
errorClass: err ? (last?.errorClass ?? 'unknown') : undefined,
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Rough token estimate for pre-flight rate-limit checks. Uses the
|
|
264
|
+
* standard ~4-chars-per-token heuristic over message content. We bias
|
|
265
|
+
* slightly high (with maxTokens) so the bucket reserves enough room
|
|
266
|
+
* for the response too.
|
|
267
|
+
*/
|
|
268
|
+
estimateTokens(opts) {
|
|
269
|
+
const promptChars = opts.messages.reduce((acc, m) => acc + m.content.length, 0);
|
|
270
|
+
const promptTokens = Math.ceil(promptChars / 4);
|
|
271
|
+
const responseTokens = opts.maxTokens ?? 1024;
|
|
272
|
+
return promptTokens + responseTokens;
|
|
273
|
+
}
|
|
274
|
+
// ── Build invoke options for the underlying adapter ───────────────────
|
|
275
|
+
buildInvokeOpts(opts, modelId) {
|
|
276
|
+
const messages = typeof opts.prompt === 'string'
|
|
277
|
+
? [{ role: 'user', content: opts.prompt }]
|
|
278
|
+
: opts.prompt.map((m) => ({ role: m.role, content: m.content }));
|
|
279
|
+
return {
|
|
280
|
+
model: modelId,
|
|
281
|
+
messages,
|
|
282
|
+
tools: opts.tools,
|
|
283
|
+
maxTokens: opts.maxTokens,
|
|
284
|
+
temperature: opts.temperature,
|
|
285
|
+
cacheBreakpoint: opts.cacheBreakpoint,
|
|
286
|
+
providerOptions: opts.providerOptions,
|
|
287
|
+
signal: opts.signal,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// ── Helpers ───────────────────────────────────────────────────────────────
|
|
292
|
+
function startOfTodayIso() {
|
|
293
|
+
const d = new Date();
|
|
294
|
+
d.setUTCHours(0, 0, 0, 0);
|
|
295
|
+
return d.toISOString();
|
|
296
|
+
}
|
|
297
|
+
function defaultNewId() {
|
|
298
|
+
// Cheap monotonic id — Date.now in base36 + a 6-char random suffix.
|
|
299
|
+
const ts = Date.now().toString(36);
|
|
300
|
+
const rand = Math.random().toString(36).slice(2, 8);
|
|
301
|
+
return `s-${ts}-${rand}`;
|
|
302
|
+
}
|
|
303
|
+
function isTerminal(cls) {
|
|
304
|
+
return cls === 'auth' || cls === 'content_policy' || cls === 'invalid_request';
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/router/router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SpendLedger — SQLite-backed per-call spend ledger.
|
|
3
|
+
*
|
|
4
|
+
* One row per terminal outcome (success or final failure). Failed calls
|
|
5
|
+
* that incurred no cost still get a row so retry-driven amplification is
|
|
6
|
+
* visible in audit. Schema locked in `AGENT-CORE-LLM-ROUTER-ADR.md` §4.
|
|
7
|
+
*
|
|
8
|
+
* Default location: `~/.anvil/router/spend.sqlite`. Honors `process.env.
|
|
9
|
+
* ANVIL_HOME` to relocate the entire `~/.anvil/` tree (memory-core convention).
|
|
10
|
+
*/
|
|
11
|
+
import Database from 'better-sqlite3';
|
|
12
|
+
export declare const SPEND_LEDGER_SCHEMA_SQL = "\nCREATE TABLE IF NOT EXISTS spend (\n id TEXT PRIMARY KEY,\n ts TEXT NOT NULL,\n run_id TEXT,\n project TEXT,\n user TEXT,\n tag TEXT NOT NULL,\n provider TEXT NOT NULL,\n model TEXT NOT NULL,\n input_tokens INTEGER NOT NULL DEFAULT 0,\n output_tokens INTEGER NOT NULL DEFAULT 0,\n cache_read_tokens INTEGER NOT NULL DEFAULT 0,\n cache_write_tokens INTEGER NOT NULL DEFAULT 0,\n cost_usd REAL NOT NULL DEFAULT 0,\n duration_ms INTEGER NOT NULL DEFAULT 0,\n fallback_index INTEGER NOT NULL DEFAULT 0,\n attempt_count INTEGER NOT NULL DEFAULT 1,\n error_class TEXT,\n trace_id TEXT\n);\n\nCREATE INDEX IF NOT EXISTS idx_spend_run ON spend(run_id, ts);\nCREATE INDEX IF NOT EXISTS idx_spend_project ON spend(project, ts);\nCREATE INDEX IF NOT EXISTS idx_spend_tag ON spend(tag, ts);\nCREATE INDEX IF NOT EXISTS idx_spend_provider ON spend(provider, ts);\n";
|
|
13
|
+
export interface SpendRow {
|
|
14
|
+
id: string;
|
|
15
|
+
ts: string;
|
|
16
|
+
runId?: string;
|
|
17
|
+
project?: string;
|
|
18
|
+
user?: string;
|
|
19
|
+
tag: string;
|
|
20
|
+
provider: string;
|
|
21
|
+
model: string;
|
|
22
|
+
inputTokens: number;
|
|
23
|
+
outputTokens: number;
|
|
24
|
+
cacheReadTokens?: number;
|
|
25
|
+
cacheWriteTokens?: number;
|
|
26
|
+
costUsd: number;
|
|
27
|
+
durationMs: number;
|
|
28
|
+
fallbackIndex: number;
|
|
29
|
+
attemptCount: number;
|
|
30
|
+
errorClass?: string;
|
|
31
|
+
traceId?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface SpendQueryOpts {
|
|
34
|
+
runId?: string;
|
|
35
|
+
project?: string;
|
|
36
|
+
tag?: string;
|
|
37
|
+
provider?: string;
|
|
38
|
+
/** ISO timestamp lower-bound (inclusive). */
|
|
39
|
+
since?: string;
|
|
40
|
+
/** ISO timestamp upper-bound (exclusive). */
|
|
41
|
+
until?: string;
|
|
42
|
+
}
|
|
43
|
+
export declare function defaultSpendLedgerPath(): string;
|
|
44
|
+
export declare class SpendLedger {
|
|
45
|
+
readonly filePath: string;
|
|
46
|
+
readonly db: Database.Database;
|
|
47
|
+
constructor(filePath?: string);
|
|
48
|
+
/**
|
|
49
|
+
* Idempotent column adds — for SQLite files created before a column
|
|
50
|
+
* existed, we ALTER TABLE if missing. Mirrors memory-core's pattern.
|
|
51
|
+
*/
|
|
52
|
+
private applyAdditiveMigrations;
|
|
53
|
+
record(row: SpendRow): void;
|
|
54
|
+
/** Sum of cost_usd across rows matching the query. */
|
|
55
|
+
totalUsd(opts?: SpendQueryOpts): number;
|
|
56
|
+
/** Aggregated cost grouped by tag (or runId / project). */
|
|
57
|
+
groupBy(field: 'tag' | 'run_id' | 'project' | 'provider', opts?: SpendQueryOpts): Array<{
|
|
58
|
+
key: string;
|
|
59
|
+
totalUsd: number;
|
|
60
|
+
count: number;
|
|
61
|
+
}>;
|
|
62
|
+
/** Most-recent rows; default 50. */
|
|
63
|
+
recent(limit?: number): SpendRow[];
|
|
64
|
+
/** Total count — convenience for tests + sanity checks. */
|
|
65
|
+
count(opts?: SpendQueryOpts): number;
|
|
66
|
+
close(): void;
|
|
67
|
+
private buildWhere;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=spend-ledger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spend-ledger.d.ts","sourceRoot":"","sources":["../../src/router/spend-ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAKtC,eAAO,MAAM,uBAAuB,42BA0BnC,CAAC;AAEF,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAG/C;AAED,qBAAa,WAAW;aAGM,QAAQ,EAAE,MAAM;IAF5C,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC;gBAEH,QAAQ,GAAE,MAAiC;IAQvE;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAW/B,MAAM,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI;IAkC3B,sDAAsD;IACtD,QAAQ,CAAC,IAAI,GAAE,cAAmB,GAAG,MAAM;IAQ3C,2DAA2D;IAC3D,OAAO,CACL,KAAK,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,EAChD,IAAI,GAAE,cAAmB,GACxB,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAY1D,oCAAoC;IACpC,MAAM,CAAC,KAAK,SAAK,GAAG,QAAQ,EAAE;IAO9B,2DAA2D;IAC3D,KAAK,CAAC,IAAI,GAAE,cAAmB,GAAG,MAAM;IAMxC,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,UAAU;CAgCnB"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SpendLedger — SQLite-backed per-call spend ledger.
|
|
3
|
+
*
|
|
4
|
+
* One row per terminal outcome (success or final failure). Failed calls
|
|
5
|
+
* that incurred no cost still get a row so retry-driven amplification is
|
|
6
|
+
* visible in audit. Schema locked in `AGENT-CORE-LLM-ROUTER-ADR.md` §4.
|
|
7
|
+
*
|
|
8
|
+
* Default location: `~/.anvil/router/spend.sqlite`. Honors `process.env.
|
|
9
|
+
* ANVIL_HOME` to relocate the entire `~/.anvil/` tree (memory-core convention).
|
|
10
|
+
*/
|
|
11
|
+
import Database from 'better-sqlite3';
|
|
12
|
+
import { mkdirSync } from 'node:fs';
|
|
13
|
+
import { dirname, join } from 'node:path';
|
|
14
|
+
import { homedir } from 'node:os';
|
|
15
|
+
export const SPEND_LEDGER_SCHEMA_SQL = `
|
|
16
|
+
CREATE TABLE IF NOT EXISTS spend (
|
|
17
|
+
id TEXT PRIMARY KEY,
|
|
18
|
+
ts TEXT NOT NULL,
|
|
19
|
+
run_id TEXT,
|
|
20
|
+
project TEXT,
|
|
21
|
+
user TEXT,
|
|
22
|
+
tag TEXT NOT NULL,
|
|
23
|
+
provider TEXT NOT NULL,
|
|
24
|
+
model TEXT NOT NULL,
|
|
25
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
26
|
+
output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
27
|
+
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
|
|
28
|
+
cache_write_tokens INTEGER NOT NULL DEFAULT 0,
|
|
29
|
+
cost_usd REAL NOT NULL DEFAULT 0,
|
|
30
|
+
duration_ms INTEGER NOT NULL DEFAULT 0,
|
|
31
|
+
fallback_index INTEGER NOT NULL DEFAULT 0,
|
|
32
|
+
attempt_count INTEGER NOT NULL DEFAULT 1,
|
|
33
|
+
error_class TEXT,
|
|
34
|
+
trace_id TEXT
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
CREATE INDEX IF NOT EXISTS idx_spend_run ON spend(run_id, ts);
|
|
38
|
+
CREATE INDEX IF NOT EXISTS idx_spend_project ON spend(project, ts);
|
|
39
|
+
CREATE INDEX IF NOT EXISTS idx_spend_tag ON spend(tag, ts);
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_spend_provider ON spend(provider, ts);
|
|
41
|
+
`;
|
|
42
|
+
export function defaultSpendLedgerPath() {
|
|
43
|
+
const root = process.env.ANVIL_HOME ?? join(homedir(), '.anvil');
|
|
44
|
+
return join(root, 'router', 'spend.sqlite');
|
|
45
|
+
}
|
|
46
|
+
export class SpendLedger {
|
|
47
|
+
filePath;
|
|
48
|
+
db;
|
|
49
|
+
constructor(filePath = defaultSpendLedgerPath()) {
|
|
50
|
+
this.filePath = filePath;
|
|
51
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
52
|
+
this.db = new Database(filePath);
|
|
53
|
+
this.db.pragma('journal_mode = WAL');
|
|
54
|
+
this.db.exec(SPEND_LEDGER_SCHEMA_SQL);
|
|
55
|
+
this.applyAdditiveMigrations();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Idempotent column adds — for SQLite files created before a column
|
|
59
|
+
* existed, we ALTER TABLE if missing. Mirrors memory-core's pattern.
|
|
60
|
+
*/
|
|
61
|
+
applyAdditiveMigrations() {
|
|
62
|
+
const cols = this.db.pragma('table_info(spend)').map((c) => c.name);
|
|
63
|
+
const ensure = (name, ddl) => {
|
|
64
|
+
if (!cols.includes(name)) {
|
|
65
|
+
this.db.exec(`ALTER TABLE spend ADD COLUMN ${ddl}`);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
ensure('error_class', 'error_class TEXT');
|
|
69
|
+
ensure('trace_id', 'trace_id TEXT');
|
|
70
|
+
}
|
|
71
|
+
record(row) {
|
|
72
|
+
const stmt = this.db.prepare(`INSERT OR REPLACE INTO spend(
|
|
73
|
+
id, ts, run_id, project, user, tag, provider, model,
|
|
74
|
+
input_tokens, output_tokens, cache_read_tokens, cache_write_tokens,
|
|
75
|
+
cost_usd, duration_ms, fallback_index, attempt_count, error_class, trace_id
|
|
76
|
+
) VALUES (
|
|
77
|
+
@id, @ts, @runId, @project, @user, @tag, @provider, @model,
|
|
78
|
+
@inputTokens, @outputTokens, @cacheReadTokens, @cacheWriteTokens,
|
|
79
|
+
@costUsd, @durationMs, @fallbackIndex, @attemptCount, @errorClass, @traceId
|
|
80
|
+
)`);
|
|
81
|
+
stmt.run({
|
|
82
|
+
id: row.id,
|
|
83
|
+
ts: row.ts,
|
|
84
|
+
runId: row.runId ?? null,
|
|
85
|
+
project: row.project ?? null,
|
|
86
|
+
user: row.user ?? null,
|
|
87
|
+
tag: row.tag,
|
|
88
|
+
provider: row.provider,
|
|
89
|
+
model: row.model,
|
|
90
|
+
inputTokens: row.inputTokens,
|
|
91
|
+
outputTokens: row.outputTokens,
|
|
92
|
+
cacheReadTokens: row.cacheReadTokens ?? 0,
|
|
93
|
+
cacheWriteTokens: row.cacheWriteTokens ?? 0,
|
|
94
|
+
costUsd: row.costUsd,
|
|
95
|
+
durationMs: row.durationMs,
|
|
96
|
+
fallbackIndex: row.fallbackIndex,
|
|
97
|
+
attemptCount: row.attemptCount,
|
|
98
|
+
errorClass: row.errorClass ?? null,
|
|
99
|
+
traceId: row.traceId ?? null,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/** Sum of cost_usd across rows matching the query. */
|
|
103
|
+
totalUsd(opts = {}) {
|
|
104
|
+
const { sql, params } = this.buildWhere(opts);
|
|
105
|
+
const row = this.db
|
|
106
|
+
.prepare(`SELECT COALESCE(SUM(cost_usd), 0) AS total FROM spend ${sql}`)
|
|
107
|
+
.get(...params);
|
|
108
|
+
return row.total;
|
|
109
|
+
}
|
|
110
|
+
/** Aggregated cost grouped by tag (or runId / project). */
|
|
111
|
+
groupBy(field, opts = {}) {
|
|
112
|
+
const { sql, params } = this.buildWhere(opts);
|
|
113
|
+
return this.db
|
|
114
|
+
.prepare(`SELECT ${field} AS key, COALESCE(SUM(cost_usd), 0) AS totalUsd, COUNT(*) AS count
|
|
115
|
+
FROM spend ${sql}
|
|
116
|
+
GROUP BY ${field}
|
|
117
|
+
ORDER BY totalUsd DESC`)
|
|
118
|
+
.all(...params);
|
|
119
|
+
}
|
|
120
|
+
/** Most-recent rows; default 50. */
|
|
121
|
+
recent(limit = 50) {
|
|
122
|
+
const rows = this.db
|
|
123
|
+
.prepare(`SELECT * FROM spend ORDER BY ts DESC LIMIT ?`)
|
|
124
|
+
.all(limit);
|
|
125
|
+
return rows.map(rowToSpend);
|
|
126
|
+
}
|
|
127
|
+
/** Total count — convenience for tests + sanity checks. */
|
|
128
|
+
count(opts = {}) {
|
|
129
|
+
const { sql, params } = this.buildWhere(opts);
|
|
130
|
+
const row = this.db.prepare(`SELECT COUNT(*) AS c FROM spend ${sql}`).get(...params);
|
|
131
|
+
return row.c;
|
|
132
|
+
}
|
|
133
|
+
close() {
|
|
134
|
+
this.db.close();
|
|
135
|
+
}
|
|
136
|
+
buildWhere(opts) {
|
|
137
|
+
const where = [];
|
|
138
|
+
const params = [];
|
|
139
|
+
if (opts.runId !== undefined) {
|
|
140
|
+
where.push('run_id = ?');
|
|
141
|
+
params.push(opts.runId);
|
|
142
|
+
}
|
|
143
|
+
if (opts.project !== undefined) {
|
|
144
|
+
where.push('project = ?');
|
|
145
|
+
params.push(opts.project);
|
|
146
|
+
}
|
|
147
|
+
if (opts.tag !== undefined) {
|
|
148
|
+
where.push('tag = ?');
|
|
149
|
+
params.push(opts.tag);
|
|
150
|
+
}
|
|
151
|
+
if (opts.provider !== undefined) {
|
|
152
|
+
where.push('provider = ?');
|
|
153
|
+
params.push(opts.provider);
|
|
154
|
+
}
|
|
155
|
+
if (opts.since !== undefined) {
|
|
156
|
+
where.push('ts >= ?');
|
|
157
|
+
params.push(opts.since);
|
|
158
|
+
}
|
|
159
|
+
if (opts.until !== undefined) {
|
|
160
|
+
where.push('ts < ?');
|
|
161
|
+
params.push(opts.until);
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
sql: where.length ? `WHERE ${where.join(' AND ')}` : '',
|
|
165
|
+
params,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function rowToSpend(row) {
|
|
170
|
+
return {
|
|
171
|
+
id: row.id,
|
|
172
|
+
ts: row.ts,
|
|
173
|
+
runId: row.run_id ?? undefined,
|
|
174
|
+
project: row.project ?? undefined,
|
|
175
|
+
user: row.user ?? undefined,
|
|
176
|
+
tag: row.tag,
|
|
177
|
+
provider: row.provider,
|
|
178
|
+
model: row.model,
|
|
179
|
+
inputTokens: row.input_tokens,
|
|
180
|
+
outputTokens: row.output_tokens,
|
|
181
|
+
cacheReadTokens: row.cache_read_tokens ?? 0,
|
|
182
|
+
cacheWriteTokens: row.cache_write_tokens ?? 0,
|
|
183
|
+
costUsd: row.cost_usd,
|
|
184
|
+
durationMs: row.duration_ms,
|
|
185
|
+
fallbackIndex: row.fallback_index,
|
|
186
|
+
attemptCount: row.attempt_count,
|
|
187
|
+
errorClass: row.error_class ?? undefined,
|
|
188
|
+
traceId: row.trace_id ?? undefined,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=spend-ledger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spend-ledger.js","sourceRoot":"","sources":["../../src/router/spend-ledger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router telemetry — OTel parent + child spans for `LlmRouter.invoke`.
|
|
3
|
+
*
|
|
4
|
+
* Span hierarchy (per ADR R10):
|
|
5
|
+
* anvil.router.invoke — one per invoke() call
|
|
6
|
+
* anvil.router.attempt — one per RouteAttempt (success or failure)
|
|
7
|
+
* gen_ai.invoke — emitted by instrumentModelAdapter (legacy
|
|
8
|
+
* adapters) or LanguageModel callers
|
|
9
|
+
*
|
|
10
|
+
* Attributes:
|
|
11
|
+
* anvil.router.route_id, anvil.router.tag, anvil.router.run_id,
|
|
12
|
+
* anvil.router.attempt, anvil.router.error_class,
|
|
13
|
+
* anvil.router.fallback_index, anvil.router.budget_remaining_usd,
|
|
14
|
+
* anvil.router.circuit_breaker_state, anvil.router.total_cost_usd,
|
|
15
|
+
* anvil.router.attempt_count
|
|
16
|
+
*
|
|
17
|
+
* Wrapper-style — call `withRouterSpans(router, opts)` to capture spans
|
|
18
|
+
* around a single invoke. The wrapper is a no-op when `recordContent` is
|
|
19
|
+
* false; it never throws on tracer absence.
|
|
20
|
+
*/
|
|
21
|
+
import type { LlmRouter } from './router.js';
|
|
22
|
+
import type { InvokeOpts, RouteOutcome } from './types.js';
|
|
23
|
+
export declare const ROUTER_INVOKE_SPAN = "anvil.router.invoke";
|
|
24
|
+
export declare const ROUTER_ATTEMPT_SPAN = "anvil.router.attempt";
|
|
25
|
+
export declare const RouterAttr: {
|
|
26
|
+
readonly ROUTE_ID: "anvil.router.route_id";
|
|
27
|
+
readonly TAG: "anvil.router.tag";
|
|
28
|
+
readonly RUN_ID: "anvil.router.run_id";
|
|
29
|
+
readonly PROJECT: "anvil.router.project";
|
|
30
|
+
readonly USER: "anvil.router.user";
|
|
31
|
+
readonly ATTEMPT: "anvil.router.attempt";
|
|
32
|
+
readonly ATTEMPT_COUNT: "anvil.router.attempt_count";
|
|
33
|
+
readonly ERROR_CLASS: "anvil.router.error_class";
|
|
34
|
+
readonly FALLBACK_INDEX: "anvil.router.fallback_index";
|
|
35
|
+
readonly BUDGET_REMAINING_USD: "anvil.router.budget_remaining_usd";
|
|
36
|
+
readonly CIRCUIT_BREAKER_STATE: "anvil.router.circuit_breaker_state";
|
|
37
|
+
readonly TOTAL_COST_USD: "anvil.router.total_cost_usd";
|
|
38
|
+
readonly PROVIDER: "anvil.router.provider";
|
|
39
|
+
readonly MODEL: "anvil.router.model";
|
|
40
|
+
readonly COST_USD: "anvil.router.cost_usd";
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Wrap a single `LlmRouter.invoke()` call with a parent span and one
|
|
44
|
+
* child span per RouteAttempt. The wrapper post-walks `outcome.attempts`
|
|
45
|
+
* to emit children — this keeps the router code itself untouched.
|
|
46
|
+
*/
|
|
47
|
+
export declare function invokeWithSpans(router: LlmRouter, opts: InvokeOpts): Promise<RouteOutcome>;
|
|
48
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/router/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAgB,MAAM,YAAY,CAAC;AAGzE,eAAO,MAAM,kBAAkB,wBAAwB,CAAC;AACxD,eAAO,MAAM,mBAAmB,yBAAyB,CAAC;AAE1D,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;CAgBb,CAAC;AAEX;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,YAAY,CAAC,CAsCvB"}
|