@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,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token-bucket rate limiter — per-provider RPM (requests/min) + TPM
|
|
3
|
+
* (tokens/min) buckets.
|
|
4
|
+
*
|
|
5
|
+
* Phase 3 ships only the in-process implementation. Cross-process mode
|
|
6
|
+
* (SQLite advisory file) is a deferred add-on once the router has real
|
|
7
|
+
* users running multiple parallel cli invocations against shared keys.
|
|
8
|
+
*
|
|
9
|
+
* Behavior:
|
|
10
|
+
* - One bucket per (provider, scope) where scope is 'rpm' | 'tpm'.
|
|
11
|
+
* - Buckets refill linearly at `capacity / 60_000` tokens/ms.
|
|
12
|
+
* - `acquire(provider, estimatedTokens)` waits until both buckets have
|
|
13
|
+
* enough tokens, then deducts. Behavior on dry bucket follows
|
|
14
|
+
* RouterConfig.onRateLimit:
|
|
15
|
+
* - 'wait' (default) — sleep until tokens are available
|
|
16
|
+
* - 'fail' — throw immediately
|
|
17
|
+
* - 'fallback' — return false; caller falls back
|
|
18
|
+
*
|
|
19
|
+
* Defaults reflect published provider docs as of 2026-04-29; override
|
|
20
|
+
* via RouterConfig.rateLimit.
|
|
21
|
+
*/
|
|
22
|
+
export const DEFAULT_RATE_LIMITS = {
|
|
23
|
+
// Anthropic Tier 4 default (Sonnet 4.6); Haiku is much higher.
|
|
24
|
+
claude: { rpm: 50, tpm: 80_000 },
|
|
25
|
+
// OpenAI Tier 1 default (gpt-4o RPM 500 / TPM 30k).
|
|
26
|
+
openai: { rpm: 500, tpm: 30_000 },
|
|
27
|
+
// Gemini 2.5 Pro default — 1000 RPM, 4M TPM in the AI Studio tier.
|
|
28
|
+
gemini: { rpm: 1000, tpm: 4_000_000 },
|
|
29
|
+
// OpenRouter aggregates upstream limits; default is conservative.
|
|
30
|
+
openrouter: { rpm: 200, tpm: 200_000 },
|
|
31
|
+
// Local providers — effectively unbounded.
|
|
32
|
+
ollama: {},
|
|
33
|
+
'gemini-cli': {},
|
|
34
|
+
adk: {},
|
|
35
|
+
};
|
|
36
|
+
const realSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
37
|
+
export class RateLimitedError extends Error {
|
|
38
|
+
provider;
|
|
39
|
+
waitMs;
|
|
40
|
+
constructor(provider, waitMs) {
|
|
41
|
+
super(`rate limit for provider '${provider}' exhausted; wait ${waitMs}ms`);
|
|
42
|
+
this.name = 'RateLimitedError';
|
|
43
|
+
this.provider = provider;
|
|
44
|
+
this.waitMs = waitMs;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export class TokenBucketRateLimiter {
|
|
48
|
+
config;
|
|
49
|
+
buckets = new Map();
|
|
50
|
+
now;
|
|
51
|
+
sleep;
|
|
52
|
+
onRateLimit;
|
|
53
|
+
constructor(deps = {}) {
|
|
54
|
+
this.config = { ...DEFAULT_RATE_LIMITS, ...deps.config };
|
|
55
|
+
this.now = deps.now ?? Date.now;
|
|
56
|
+
this.sleep = deps.sleep ?? realSleep;
|
|
57
|
+
this.onRateLimit = deps.onRateLimit ?? 'wait';
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Reserve 1 RPM token + N TPM tokens for the provider. If the bucket
|
|
61
|
+
* is dry the behavior depends on the configured `onRateLimit`:
|
|
62
|
+
* - 'wait' (default): awaits until available
|
|
63
|
+
* - 'fail': throws RateLimitedError
|
|
64
|
+
* - 'fallback': returns false; caller falls back
|
|
65
|
+
*/
|
|
66
|
+
async acquire(provider, estimatedTokens) {
|
|
67
|
+
const cfg = this.config[provider] ?? {};
|
|
68
|
+
const rpm = cfg.rpm;
|
|
69
|
+
const tpm = cfg.tpm;
|
|
70
|
+
if (rpm === undefined && tpm === undefined)
|
|
71
|
+
return true; // unbounded
|
|
72
|
+
while (true) {
|
|
73
|
+
this.refillAll(provider);
|
|
74
|
+
const rpmBucket = rpm !== undefined ? this.bucketFor(provider, 'rpm', rpm) : null;
|
|
75
|
+
const tpmBucket = tpm !== undefined ? this.bucketFor(provider, 'tpm', tpm) : null;
|
|
76
|
+
const rpmShort = rpmBucket && rpmBucket.tokens < 1;
|
|
77
|
+
const tpmShort = tpmBucket && tpmBucket.tokens < estimatedTokens;
|
|
78
|
+
if (!rpmShort && !tpmShort) {
|
|
79
|
+
if (rpmBucket)
|
|
80
|
+
rpmBucket.tokens -= 1;
|
|
81
|
+
if (tpmBucket)
|
|
82
|
+
tpmBucket.tokens -= estimatedTokens;
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
const waitMs = Math.max(rpmBucket && rpmShort ? this.waitTime(rpmBucket, 1) : 0, tpmBucket && tpmShort ? this.waitTime(tpmBucket, estimatedTokens) : 0);
|
|
86
|
+
if (this.onRateLimit === 'fail') {
|
|
87
|
+
throw new RateLimitedError(provider, waitMs);
|
|
88
|
+
}
|
|
89
|
+
if (this.onRateLimit === 'fallback') {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
await this.sleep(waitMs);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Best-effort introspection — returns current token counts. */
|
|
96
|
+
snapshot(provider) {
|
|
97
|
+
this.refillAll(provider);
|
|
98
|
+
return {
|
|
99
|
+
rpm: this.buckets.get(`${provider}:rpm`)?.tokens,
|
|
100
|
+
tpm: this.buckets.get(`${provider}:tpm`)?.tokens,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
bucketFor(provider, scope, capacityPerMin) {
|
|
104
|
+
const key = `${provider}:${scope}`;
|
|
105
|
+
let b = this.buckets.get(key);
|
|
106
|
+
if (!b) {
|
|
107
|
+
b = { capacityPerMin, tokens: capacityPerMin, lastRefillMs: this.now() };
|
|
108
|
+
this.buckets.set(key, b);
|
|
109
|
+
}
|
|
110
|
+
else if (b.capacityPerMin !== capacityPerMin) {
|
|
111
|
+
b.capacityPerMin = capacityPerMin;
|
|
112
|
+
}
|
|
113
|
+
return b;
|
|
114
|
+
}
|
|
115
|
+
refillAll(provider) {
|
|
116
|
+
for (const scope of ['rpm', 'tpm']) {
|
|
117
|
+
const b = this.buckets.get(`${provider}:${scope}`);
|
|
118
|
+
if (!b)
|
|
119
|
+
continue;
|
|
120
|
+
const now = this.now();
|
|
121
|
+
const elapsed = now - b.lastRefillMs;
|
|
122
|
+
if (elapsed <= 0)
|
|
123
|
+
continue;
|
|
124
|
+
const refill = (elapsed / 60_000) * b.capacityPerMin;
|
|
125
|
+
b.tokens = Math.min(b.capacityPerMin, b.tokens + refill);
|
|
126
|
+
b.lastRefillMs = now;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
waitTime(bucket, needed) {
|
|
130
|
+
const deficit = needed - bucket.tokens;
|
|
131
|
+
if (deficit <= 0)
|
|
132
|
+
return 0;
|
|
133
|
+
return Math.ceil((deficit / bucket.capacityPerMin) * 60_000);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/router/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,MAAM,CAAC,MAAM,mBAAmB,GAA4C;IAC1E,+DAA+D;IAC/D,MAAM,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE;IAChC,oDAAoD;IACpD,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE;IACjC,mEAAmE;IACnE,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE;IACrC,kEAAkE;IAClE,UAAU,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE;IACtC,2CAA2C;IAC3C,MAAM,EAAE,EAAE;IACV,YAAY,EAAE,EAAE;IAChB,GAAG,EAAE,EAAE;CACR,CAAC;AAmBF,MAAM,SAAS,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAE9E,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,QAAQ,CAAS;IACjB,MAAM,CAAS;IACxB,YAAY,QAAgB,EAAE,MAAc;QAC1C,KAAK,CAAC,4BAA4B,QAAQ,qBAAqB,MAAM,IAAI,CAAC,CAAC;QAC3E,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,MAAM,OAAO,sBAAsB;IAChB,MAAM,CAA0C;IAChD,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpC,GAAG,CAAe;IAClB,KAAK,CAAgC;IACrC,WAAW,CAA+B;IAE3D,YAAY,OAAwB,EAAE;QACpC,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,mBAAmB,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACzD,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;QAChC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC;QACrC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC;IAChD,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,CAAC,QAAgB,EAAE,eAAuB;QACrD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;QACpB,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;QACpB,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,CAAC,YAAY;QAErE,OAAO,IAAI,EAAE,CAAC;YACZ,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YACzB,MAAM,SAAS,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAClF,MAAM,SAAS,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAElF,MAAM,QAAQ,GAAG,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;YACnD,MAAM,QAAQ,GAAG,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,eAAe,CAAC;YACjE,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC3B,IAAI,SAAS;oBAAE,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC;gBACrC,IAAI,SAAS;oBAAE,SAAS,CAAC,MAAM,IAAI,eAAe,CAAC;gBACnD,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACrB,SAAS,IAAI,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACvD,SAAS,IAAI,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CACtE,CAAC;YAEF,IAAI,IAAI,CAAC,WAAW,KAAK,MAAM,EAAE,CAAC;gBAChC,MAAM,IAAI,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC/C,CAAC;YACD,IAAI,IAAI,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;gBACpC,OAAO,KAAK,CAAC;YACf,CAAC;YACD,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,gEAAgE;IAChE,QAAQ,CAAC,QAAgB;QACvB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACzB,OAAO;YACL,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,QAAQ,MAAM,CAAC,EAAE,MAAM;YAChD,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,QAAQ,MAAM,CAAC,EAAE,MAAM;SACjD,CAAC;IACJ,CAAC;IAEO,SAAS,CAAC,QAAgB,EAAE,KAAoB,EAAE,cAAsB;QAC9E,MAAM,GAAG,GAAG,GAAG,QAAQ,IAAI,KAAK,EAAE,CAAC;QACnC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YACzE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,CAAC,CAAC,cAAc,KAAK,cAAc,EAAE,CAAC;YAC/C,CAAC,CAAC,cAAc,GAAG,cAAc,CAAC;QACpC,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAEO,SAAS,CAAC,QAAgB;QAChC,KAAK,MAAM,KAAK,IAAI,CAAC,KAAK,EAAE,KAAK,CAAU,EAAE,CAAC;YAC5C,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,QAAQ,IAAI,KAAK,EAAE,CAAC,CAAC;YACnD,IAAI,CAAC,CAAC;gBAAE,SAAS;YACjB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,GAAG,GAAG,CAAC,CAAC,YAAY,CAAC;YACrC,IAAI,OAAO,IAAI,CAAC;gBAAE,SAAS;YAC3B,MAAM,MAAM,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC;YACrD,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;YACzD,CAAC,CAAC,YAAY,GAAG,GAAG,CAAC;QACvB,CAAC;IACH,CAAC;IAEO,QAAQ,CAAC,MAAc,EAAE,MAAc;QAC7C,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QACvC,IAAI,OAAO,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC,cAAc,CAAC,GAAG,MAAM,CAAC,CAAC;IAC/D,CAAC;CACF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolver — given a capability + complexity + tier preference list, walks
|
|
3
|
+
* the model registry and returns a routing chain `{ primary, fallbacks }`
|
|
4
|
+
* suitable for `LlmRouter.invoke`.
|
|
5
|
+
*
|
|
6
|
+
* Pure function. No I/O. No mutation of the registry.
|
|
7
|
+
*
|
|
8
|
+
* Algorithm:
|
|
9
|
+
* 1. Filter: model.capabilities ⊇ {capability}
|
|
10
|
+
* ∧ rank(complexity) ≤ rank(model.complexity_max)
|
|
11
|
+
* ∧ availability[model.id]?.available !== false
|
|
12
|
+
* ∧ context_tokens, if requested, ≤ model.context_tokens
|
|
13
|
+
* 2. Group by tier
|
|
14
|
+
* 3. Walk tiers in `prefer` order; within tier, yaml-declared order
|
|
15
|
+
* 4. Concatenate → [primary, ...fallbacks]
|
|
16
|
+
* 5. If empty → ModelResolutionError with per-step diagnostic counts
|
|
17
|
+
*/
|
|
18
|
+
import type { ModelRegistry, ModelCapability, ModelComplexity, ModelTier } from './model-registry.js';
|
|
19
|
+
import type { RouteFallback } from './types.js';
|
|
20
|
+
export interface ResolveModelOptions {
|
|
21
|
+
capability: ModelCapability;
|
|
22
|
+
complexity: ModelComplexity;
|
|
23
|
+
/** Tier preference order. Walked left-to-right; first non-empty tier wins. */
|
|
24
|
+
prefer: ModelTier[];
|
|
25
|
+
/** Optional minimum context window required by the call. */
|
|
26
|
+
minContextTokens?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface ResolvedChain {
|
|
29
|
+
primary: string;
|
|
30
|
+
fallbacks: RouteFallback[];
|
|
31
|
+
}
|
|
32
|
+
export declare class ModelResolutionError extends Error {
|
|
33
|
+
readonly opts: ResolveModelOptions;
|
|
34
|
+
readonly diagnostic: ResolutionDiagnostic;
|
|
35
|
+
constructor(opts: ResolveModelOptions, diagnostic: ResolutionDiagnostic);
|
|
36
|
+
}
|
|
37
|
+
export interface ResolutionDiagnostic {
|
|
38
|
+
totalInRegistry: number;
|
|
39
|
+
matchedCapability: number;
|
|
40
|
+
matchedComplexity: number;
|
|
41
|
+
matchedContext: number;
|
|
42
|
+
matchedAvailability: number;
|
|
43
|
+
}
|
|
44
|
+
export declare function resolveModel(opts: ResolveModelOptions, registry: ModelRegistry): ResolvedChain;
|
|
45
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/router/resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,eAAe,EACf,SAAS,EAEV,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,eAAe,CAAC;IAC5B,UAAU,EAAE,eAAe,CAAC;IAC5B,8EAA8E;IAC9E,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAED,qBAAa,oBAAqB,SAAQ,KAAK;aAE3B,IAAI,EAAE,mBAAmB;aACzB,UAAU,EAAE,oBAAoB;gBADhC,IAAI,EAAE,mBAAmB,EACzB,UAAU,EAAE,oBAAoB;CAKnD;AAED,MAAM,WAAW,oBAAoB;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAID,wBAAgB,YAAY,CAAC,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,aAAa,GAAG,aAAa,CAmD9F"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export class ModelResolutionError extends Error {
|
|
2
|
+
opts;
|
|
3
|
+
diagnostic;
|
|
4
|
+
constructor(opts, diagnostic) {
|
|
5
|
+
super(formatDiagnostic(opts, diagnostic));
|
|
6
|
+
this.opts = opts;
|
|
7
|
+
this.diagnostic = diagnostic;
|
|
8
|
+
this.name = 'ModelResolutionError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const COMPLEXITY_RANK = { S: 1, M: 2, L: 3 };
|
|
12
|
+
export function resolveModel(opts, registry) {
|
|
13
|
+
const requested = COMPLEXITY_RANK[opts.complexity];
|
|
14
|
+
const diag = {
|
|
15
|
+
totalInRegistry: registry.models.length,
|
|
16
|
+
matchedCapability: 0,
|
|
17
|
+
matchedComplexity: 0,
|
|
18
|
+
matchedContext: 0,
|
|
19
|
+
matchedAvailability: 0,
|
|
20
|
+
};
|
|
21
|
+
const passed = [];
|
|
22
|
+
for (const m of registry.models) {
|
|
23
|
+
if (!m.capabilities.includes(opts.capability))
|
|
24
|
+
continue;
|
|
25
|
+
diag.matchedCapability += 1;
|
|
26
|
+
if (COMPLEXITY_RANK[m.complexity_max] < requested)
|
|
27
|
+
continue;
|
|
28
|
+
diag.matchedComplexity += 1;
|
|
29
|
+
if (opts.minContextTokens !== undefined &&
|
|
30
|
+
m.context_tokens !== undefined &&
|
|
31
|
+
m.context_tokens < opts.minContextTokens) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
diag.matchedContext += 1;
|
|
35
|
+
if (registry.availability?.get(m.id)?.available === false)
|
|
36
|
+
continue;
|
|
37
|
+
diag.matchedAvailability += 1;
|
|
38
|
+
passed.push(m);
|
|
39
|
+
}
|
|
40
|
+
// Walk tier preference. Within a tier, preserve yaml-declared order
|
|
41
|
+
// (which is the order they appear in registry.models, since `passed`
|
|
42
|
+
// is built by iterating registry.models in order and we keep that).
|
|
43
|
+
const ordered = [];
|
|
44
|
+
for (const tier of opts.prefer) {
|
|
45
|
+
for (const m of passed) {
|
|
46
|
+
if (m.tier === tier)
|
|
47
|
+
ordered.push(m);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (ordered.length === 0) {
|
|
51
|
+
throw new ModelResolutionError(opts, diag);
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
primary: ordered[0].id,
|
|
55
|
+
fallbacks: ordered.slice(1).map((m) => ({ model: m.id })),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function formatDiagnostic(opts, d) {
|
|
59
|
+
const lines = [
|
|
60
|
+
`no model matches {capability: ${opts.capability}, complexity: ${opts.complexity}, prefer: [${opts.prefer.join(', ')}]}`,
|
|
61
|
+
` registry has ${d.totalInRegistry} model(s);`,
|
|
62
|
+
` ${d.matchedCapability} satisfied capability,`,
|
|
63
|
+
` ${d.matchedComplexity} also satisfied complexity_max,`,
|
|
64
|
+
` ${d.matchedContext} also satisfied context_tokens,`,
|
|
65
|
+
` ${d.matchedAvailability} were available.`,
|
|
66
|
+
` hint: add a matching model to ~/.anvil/models.yaml,`,
|
|
67
|
+
` or relax stage policy to a less strict capability/complexity.`,
|
|
68
|
+
];
|
|
69
|
+
return lines.join('\n');
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/router/resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-error retry engine.
|
|
3
|
+
*
|
|
4
|
+
* Drives a single attempt-loop against one adapter using `RetryPolicy`
|
|
5
|
+
* resolved from the active `ErrorClass`. The fallback walk (Phase 5)
|
|
6
|
+
* sits a layer up and consumes this primitive for each step.
|
|
7
|
+
*
|
|
8
|
+
* Default policy table per ADR R2:
|
|
9
|
+
* - rate_limit: 5 attempts, exponential, base 1000ms, max 30000ms
|
|
10
|
+
* - timeout: 3 attempts, linear, base 500ms, max 5000ms
|
|
11
|
+
* - server_5xx: 4 attempts, exponential, base 200ms, max 5000ms
|
|
12
|
+
* - auth: 0 attempts, constant (terminal — surface immediately)
|
|
13
|
+
* - content_policy: 0 attempts, constant (terminal)
|
|
14
|
+
* - invalid_request: 0 attempts, constant (terminal)
|
|
15
|
+
* - unknown: 1 attempt, constant, base 1000ms
|
|
16
|
+
*
|
|
17
|
+
* `Retry-After` headers — when present on the thrown error — override
|
|
18
|
+
* the computed backoff for that single delay.
|
|
19
|
+
*/
|
|
20
|
+
import type { ErrorClass, RetryPolicy } from './types.js';
|
|
21
|
+
export declare const DEFAULT_RETRY_POLICY: Record<ErrorClass, RetryPolicy>;
|
|
22
|
+
export interface RetryAttempt {
|
|
23
|
+
index: number;
|
|
24
|
+
errorClass?: ErrorClass;
|
|
25
|
+
error?: Error;
|
|
26
|
+
delayMs: number;
|
|
27
|
+
durationMs: number;
|
|
28
|
+
}
|
|
29
|
+
export interface RunWithRetryResult<T> {
|
|
30
|
+
result?: T;
|
|
31
|
+
error?: Error;
|
|
32
|
+
attempts: RetryAttempt[];
|
|
33
|
+
}
|
|
34
|
+
export interface RunWithRetryDeps {
|
|
35
|
+
/** Resolve the retry policy for a given error class. */
|
|
36
|
+
policyFor: (cls: ErrorClass) => RetryPolicy;
|
|
37
|
+
/**
|
|
38
|
+
* Adapter-specific overrides for `classifyError`. Returning `undefined`
|
|
39
|
+
* falls back to the generic heuristic.
|
|
40
|
+
*/
|
|
41
|
+
classify?: (err: unknown) => ErrorClass | undefined;
|
|
42
|
+
/** Sleep — injectable so tests can drive a fake clock. */
|
|
43
|
+
sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
|
|
44
|
+
/** Time source — injectable for deterministic durations. */
|
|
45
|
+
now?: () => number;
|
|
46
|
+
/** Random source for jitter — injectable for deterministic tests. */
|
|
47
|
+
random?: () => number;
|
|
48
|
+
signal?: AbortSignal;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Run `fn` under the active retry policy. Returns the success result
|
|
52
|
+
* once produced, or the final error after the policy budget is exhausted.
|
|
53
|
+
*
|
|
54
|
+
* Each invocation is recorded in `attempts[]` with its classification,
|
|
55
|
+
* pre-attempt delay, and wall-clock duration.
|
|
56
|
+
*/
|
|
57
|
+
export declare function runWithRetry<T>(fn: () => Promise<T>, deps: RunWithRetryDeps): Promise<RunWithRetryResult<T>>;
|
|
58
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/router/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG1D,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,UAAU,EAAE,WAAW,CAQhE,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,MAAM,CAAC,EAAE,CAAC,CAAC;IACX,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,SAAS,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,WAAW,CAAC;IAC5C;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,UAAU,GAAG,SAAS,CAAC;IACpD,0DAA0D;IAC1D,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,4DAA4D;IAC5D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAgBD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAClC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAwDhC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-error retry engine.
|
|
3
|
+
*
|
|
4
|
+
* Drives a single attempt-loop against one adapter using `RetryPolicy`
|
|
5
|
+
* resolved from the active `ErrorClass`. The fallback walk (Phase 5)
|
|
6
|
+
* sits a layer up and consumes this primitive for each step.
|
|
7
|
+
*
|
|
8
|
+
* Default policy table per ADR R2:
|
|
9
|
+
* - rate_limit: 5 attempts, exponential, base 1000ms, max 30000ms
|
|
10
|
+
* - timeout: 3 attempts, linear, base 500ms, max 5000ms
|
|
11
|
+
* - server_5xx: 4 attempts, exponential, base 200ms, max 5000ms
|
|
12
|
+
* - auth: 0 attempts, constant (terminal — surface immediately)
|
|
13
|
+
* - content_policy: 0 attempts, constant (terminal)
|
|
14
|
+
* - invalid_request: 0 attempts, constant (terminal)
|
|
15
|
+
* - unknown: 1 attempt, constant, base 1000ms
|
|
16
|
+
*
|
|
17
|
+
* `Retry-After` headers — when present on the thrown error — override
|
|
18
|
+
* the computed backoff for that single delay.
|
|
19
|
+
*/
|
|
20
|
+
import { classifyError, parseRetryAfterMs } from './errors.js';
|
|
21
|
+
export const DEFAULT_RETRY_POLICY = {
|
|
22
|
+
rate_limit: { attempts: 5, backoff: 'exponential', baseMs: 1000, maxMs: 30000 },
|
|
23
|
+
timeout: { attempts: 3, backoff: 'linear', baseMs: 500, maxMs: 5000 },
|
|
24
|
+
server_5xx: { attempts: 4, backoff: 'exponential', baseMs: 200, maxMs: 5000 },
|
|
25
|
+
auth: { attempts: 0, backoff: 'constant', baseMs: 0 },
|
|
26
|
+
content_policy: { attempts: 0, backoff: 'constant', baseMs: 0 },
|
|
27
|
+
invalid_request: { attempts: 0, backoff: 'constant', baseMs: 0 },
|
|
28
|
+
unknown: { attempts: 1, backoff: 'constant', baseMs: 1000 },
|
|
29
|
+
};
|
|
30
|
+
const realSleep = (ms, signal) => new Promise((resolve, reject) => {
|
|
31
|
+
if (signal?.aborted)
|
|
32
|
+
return reject(signal.reason);
|
|
33
|
+
const timer = setTimeout(resolve, ms);
|
|
34
|
+
signal?.addEventListener('abort', () => {
|
|
35
|
+
clearTimeout(timer);
|
|
36
|
+
reject(signal.reason);
|
|
37
|
+
}, { once: true });
|
|
38
|
+
});
|
|
39
|
+
/**
|
|
40
|
+
* Run `fn` under the active retry policy. Returns the success result
|
|
41
|
+
* once produced, or the final error after the policy budget is exhausted.
|
|
42
|
+
*
|
|
43
|
+
* Each invocation is recorded in `attempts[]` with its classification,
|
|
44
|
+
* pre-attempt delay, and wall-clock duration.
|
|
45
|
+
*/
|
|
46
|
+
export async function runWithRetry(fn, deps) {
|
|
47
|
+
const sleep = deps.sleep ?? realSleep;
|
|
48
|
+
const now = deps.now ?? Date.now;
|
|
49
|
+
const random = deps.random ?? Math.random;
|
|
50
|
+
const attempts = [];
|
|
51
|
+
let attemptIndex = 0;
|
|
52
|
+
while (true) {
|
|
53
|
+
const startedAt = now();
|
|
54
|
+
let outcome;
|
|
55
|
+
try {
|
|
56
|
+
const value = await fn();
|
|
57
|
+
outcome = { ok: true, value };
|
|
58
|
+
}
|
|
59
|
+
catch (raw) {
|
|
60
|
+
outcome = { ok: false, err: raw instanceof Error ? raw : new Error(String(raw)) };
|
|
61
|
+
}
|
|
62
|
+
const durationMs = Math.max(0, now() - startedAt);
|
|
63
|
+
if (outcome.ok) {
|
|
64
|
+
attempts.push({ index: attemptIndex, delayMs: 0, durationMs });
|
|
65
|
+
return { result: outcome.value, attempts };
|
|
66
|
+
}
|
|
67
|
+
const cls = deps.classify?.(outcome.err) ?? classifyError(outcome.err);
|
|
68
|
+
const policy = deps.policyFor(cls);
|
|
69
|
+
attempts.push({
|
|
70
|
+
index: attemptIndex,
|
|
71
|
+
errorClass: cls,
|
|
72
|
+
error: outcome.err,
|
|
73
|
+
delayMs: 0,
|
|
74
|
+
durationMs,
|
|
75
|
+
});
|
|
76
|
+
// Budget exhausted (or terminal class with attempts: 0).
|
|
77
|
+
if (attemptIndex >= policy.attempts) {
|
|
78
|
+
return { error: outcome.err, attempts };
|
|
79
|
+
}
|
|
80
|
+
// Compute the next delay. `Retry-After` overrides if present.
|
|
81
|
+
const headerDelay = parseRetryAfterMs(outcome.err.headers);
|
|
82
|
+
const computed = headerDelay ?? computeDelay(policy, attemptIndex, random);
|
|
83
|
+
attempts[attempts.length - 1].delayMs = computed;
|
|
84
|
+
if (computed > 0) {
|
|
85
|
+
try {
|
|
86
|
+
await sleep(computed, deps.signal);
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
return { error: e instanceof Error ? e : new Error(String(e)), attempts };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
attemptIndex += 1;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function computeDelay(policy, attemptIndex, random) {
|
|
96
|
+
const useJitter = policy.jitter ?? true;
|
|
97
|
+
let base;
|
|
98
|
+
switch (policy.backoff) {
|
|
99
|
+
case 'constant':
|
|
100
|
+
base = policy.baseMs;
|
|
101
|
+
break;
|
|
102
|
+
case 'linear':
|
|
103
|
+
base = policy.baseMs * (attemptIndex + 1);
|
|
104
|
+
break;
|
|
105
|
+
case 'exponential':
|
|
106
|
+
base = policy.baseMs * Math.pow(2, attemptIndex);
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
if (policy.maxMs !== undefined) {
|
|
110
|
+
base = Math.min(base, policy.maxMs);
|
|
111
|
+
}
|
|
112
|
+
if (!useJitter)
|
|
113
|
+
return Math.max(0, Math.round(base));
|
|
114
|
+
// ±25% jitter
|
|
115
|
+
const jitter = base * 0.25;
|
|
116
|
+
const value = base + (random() * 2 - 1) * jitter;
|
|
117
|
+
return Math.max(0, Math.round(value));
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/router/retry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
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 type { ErrorClass, InvokeOpts, RouteAttempt, RouteOutcome, RouterConfig } from './types.js';
|
|
10
|
+
import type { LanguageModel, LanguageModelInvokeOptions, InvokeResult } from '../types.js';
|
|
11
|
+
import { TokenBucketRateLimiter } from './rate-limiter.js';
|
|
12
|
+
import { SpendLedger } from './spend-ledger.js';
|
|
13
|
+
import { CircuitBreaker } from './circuit-breaker.js';
|
|
14
|
+
export interface AdapterResolver {
|
|
15
|
+
/** Resolve a model id to an executor. */
|
|
16
|
+
resolve(modelId: string): LanguageModel;
|
|
17
|
+
}
|
|
18
|
+
export interface LlmRouterDeps {
|
|
19
|
+
config: RouterConfig;
|
|
20
|
+
/**
|
|
21
|
+
* Resolves a model id → executor. Phase 5 wires this to ProviderRegistry.
|
|
22
|
+
* Tests inject fakes directly.
|
|
23
|
+
*/
|
|
24
|
+
resolver?: AdapterResolver;
|
|
25
|
+
/**
|
|
26
|
+
* Pre-flight rate limiter. If omitted, the router constructs an internal
|
|
27
|
+
* TokenBucketRateLimiter from `config.rateLimit`.
|
|
28
|
+
*/
|
|
29
|
+
rateLimiter?: TokenBucketRateLimiter;
|
|
30
|
+
/**
|
|
31
|
+
* Spend ledger. If omitted, no rows are recorded (useful for tests or
|
|
32
|
+
* embedded scenarios). Pass `new SpendLedger()` to use the default
|
|
33
|
+
* `~/.anvil/router/spend.sqlite` file.
|
|
34
|
+
*/
|
|
35
|
+
ledger?: SpendLedger;
|
|
36
|
+
/**
|
|
37
|
+
* Per-provider circuit breaker. If omitted, the router constructs one
|
|
38
|
+
* from `config.circuitBreaker` (or defaults).
|
|
39
|
+
*/
|
|
40
|
+
circuitBreaker?: CircuitBreaker;
|
|
41
|
+
/** Generate ledger row ids — injectable for deterministic tests. */
|
|
42
|
+
newId?: () => string;
|
|
43
|
+
/** Time source for deterministic tests. */
|
|
44
|
+
now?: () => number;
|
|
45
|
+
/** Sleep — injectable for deterministic tests. */
|
|
46
|
+
sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
|
|
47
|
+
/** Random source for jitter. */
|
|
48
|
+
random?: () => number;
|
|
49
|
+
/** Adapter-specific error classifiers (per-provider override). */
|
|
50
|
+
errorClassifiers?: Record<string, (err: unknown) => ErrorClass | undefined>;
|
|
51
|
+
}
|
|
52
|
+
export declare class LlmRouter {
|
|
53
|
+
protected readonly config: RouterConfig;
|
|
54
|
+
protected readonly resolver?: AdapterResolver;
|
|
55
|
+
protected readonly rateLimiter: TokenBucketRateLimiter;
|
|
56
|
+
protected readonly circuitBreaker: CircuitBreaker;
|
|
57
|
+
protected readonly ledger?: SpendLedger;
|
|
58
|
+
protected readonly newId: () => string;
|
|
59
|
+
protected readonly now: () => number;
|
|
60
|
+
protected readonly sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
|
|
61
|
+
protected readonly random?: () => number;
|
|
62
|
+
protected readonly errorClassifiers: Record<string, (err: unknown) => ErrorClass | undefined>;
|
|
63
|
+
constructor(deps: LlmRouterDeps);
|
|
64
|
+
/** Inspect the active config (immutable snapshot). */
|
|
65
|
+
getConfig(): Readonly<RouterConfig>;
|
|
66
|
+
/**
|
|
67
|
+
* Resolve the route for a tag (or pinned model) and walk the chain
|
|
68
|
+
* primary → fallback[0] → fallback[1] until either success or the
|
|
69
|
+
* chain is exhausted.
|
|
70
|
+
*
|
|
71
|
+
* Per ADR R5:
|
|
72
|
+
* - auth / content_policy / invalid_request never trigger fallback
|
|
73
|
+
* - rate_limit / server_5xx / timeout default to the full chain;
|
|
74
|
+
* RouteFallback.on can restrict per-step
|
|
75
|
+
* - All attempts are ledgered (including failed ones with cost)
|
|
76
|
+
*/
|
|
77
|
+
invoke(opts: InvokeOpts): Promise<RouteOutcome>;
|
|
78
|
+
/** Build the ordered chain of (model, on-gate) steps for a given tag. */
|
|
79
|
+
protected buildChain(opts: InvokeOpts): Array<{
|
|
80
|
+
model: string;
|
|
81
|
+
on?: ErrorClass[];
|
|
82
|
+
}>;
|
|
83
|
+
/** Decide whether to try this fallback step given the prior error class. */
|
|
84
|
+
protected shouldTryFallback(fallback: {
|
|
85
|
+
on?: ErrorClass[];
|
|
86
|
+
}, priorClass: ErrorClass | undefined): boolean;
|
|
87
|
+
protected enforceBudgetPreflight(opts: InvokeOpts): void;
|
|
88
|
+
protected computeRemainingBudget(opts: InvokeOpts): number | undefined;
|
|
89
|
+
protected populateBudgetRemaining(outcome: RouteOutcome, opts: InvokeOpts): void;
|
|
90
|
+
protected recordSpend(opts: InvokeOpts, provider: string, modelId: string, attempts: ReadonlyArray<RouteAttempt>, result: InvokeResult | undefined, err: Error | undefined): void;
|
|
91
|
+
/**
|
|
92
|
+
* Rough token estimate for pre-flight rate-limit checks. Uses the
|
|
93
|
+
* standard ~4-chars-per-token heuristic over message content. We bias
|
|
94
|
+
* slightly high (with maxTokens) so the bucket reserves enough room
|
|
95
|
+
* for the response too.
|
|
96
|
+
*/
|
|
97
|
+
protected estimateTokens(opts: LanguageModelInvokeOptions): number;
|
|
98
|
+
protected buildInvokeOpts(opts: InvokeOpts, modelId: string): LanguageModelInvokeOptions;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/router/router.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EAEV,YAAY,EAEZ,YAAY,EACZ,YAAY,EACb,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,aAAa,EAAE,0BAA0B,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3F,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC9B,yCAAyC;IACzC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC;CACzC;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B;;;OAGG;IACH,WAAW,CAAC,EAAE,sBAAsB,CAAC;IACrC;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IACrB,2CAA2C;IAC3C,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,kDAAkD;IAClD,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,gCAAgC;IAChC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IACtB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,UAAU,GAAG,SAAS,CAAC,CAAC;CAC7E;AAED,qBAAa,SAAS;IACpB,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IACxC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC9C,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,sBAAsB,CAAC;IACvD,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IAClD,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IACxC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;IACvC,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM,CAAC;IACrC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IACzC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,UAAU,GAAG,SAAS,CAAC,CAAC;gBAElF,IAAI,EAAE,aAAa;IA2B/B,sDAAsD;IACtD,SAAS,IAAI,QAAQ,CAAC,YAAY,CAAC;IAInC;;;;;;;;;;OAUG;IACG,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IAwHrD,yEAAyE;IACzE,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC;IAgBnF,4EAA4E;IAC5E,SAAS,CAAC,iBAAiB,CACzB,QAAQ,EAAE;QAAE,EAAE,CAAC,EAAE,UAAU,EAAE,CAAA;KAAE,EAC/B,UAAU,EAAE,UAAU,GAAG,SAAS,GACjC,OAAO;IAUV,SAAS,CAAC,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAgBxD,SAAS,CAAC,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS;IAqBtE,SAAS,CAAC,uBAAuB,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI;IAKhF,SAAS,CAAC,WAAW,CACnB,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,EACrC,MAAM,EAAE,YAAY,GAAG,SAAS,EAChC,GAAG,EAAE,KAAK,GAAG,SAAS,GACrB,IAAI;IAwBP;;;;;OAKG;IACH,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,0BAA0B,GAAG,MAAM;IASlE,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,0BAA0B;CAgBzF"}
|