diff --git a/examples/9-router-qa-dry-run.js b/examples/9-router-qa-dry-run.js new file mode 100644 index 0000000..49fc100 --- /dev/null +++ b/examples/9-router-qa-dry-run.js @@ -0,0 +1,83 @@ +/** + * Example 9: Router QA Dry Run + * + * Demonstrates how to validate a fallback routing setup without calling any + * real LLM APIs. This is useful before release checks, CI smoke tests, or + * onboarding a new fallback chain. + * + * Prerequisites: + * npm install tokenfirewall + */ + +let tokenfirewall; + +try { + tokenfirewall = require("tokenfirewall"); +} catch (error) { + if (error.code !== "MODULE_NOT_FOUND") { + throw error; + } + tokenfirewall = require("../dist/index.js"); +} + +const { + createModelRouter, + disableModelRouter, + isCrossProviderEnabled, + registerApiKeys, +} = tokenfirewall; + +// Register placeholder keys so provider configuration is shaped like +// production, without making network calls in this dry run. +registerApiKeys({ + openai: "test-openai-key", + anthropic: "test-anthropic-key", + gemini: "test-gemini-key", +}); + +const router = createModelRouter({ + strategy: "fallback", + fallbackMap: { + "gpt-4o": ["claude-3-5-sonnet-20241022", "gemini-2.5-pro"], + "claude-3-5-sonnet-20241022": ["gpt-4o-mini"], + }, + maxRetries: 2, + enableCrossProvider: true, +}); + +console.log("Router strategy:", router.getStrategy()); +console.log("Max retries:", router.getMaxRetries()); +console.log("Cross-provider enabled:", isCrossProviderEnabled()); + +const firstDecision = router.handleFailure({ + error: { status: 429, message: "rate limited" }, + originalModel: "gpt-4o", + provider: "openai", + requestBody: { + model: "gpt-4o", + messages: [{ role: "user", content: "Summarize this release plan." }], + }, + retryCount: 0, + attemptedModels: ["gpt-4o"], +}); + +console.log("\nFirst retry decision:"); +console.log(firstDecision); + +const secondDecision = router.handleFailure({ + error: { status: 503, message: "provider unavailable" }, + originalModel: "gpt-4o", + provider: "anthropic", + requestBody: { + model: "claude-3-5-sonnet-20241022", + messages: [{ role: "user", content: "Summarize this release plan." }], + }, + retryCount: 1, + attemptedModels: ["gpt-4o", "claude-3-5-sonnet-20241022"], +}); + +console.log("\nSecond retry decision:"); +console.log(secondDecision); + +disableModelRouter(); +console.log("\nRouter disabled:", !isCrossProviderEnabled()); diff --git a/examples/README.md b/examples/README.md index 006828c..8c3d46b 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,6 +1,6 @@ # TokenFirewall Examples -This directory contains practical examples showing how to use tokenfirewall in real-world scenarios. +This directory contains nine practical examples showing how to use tokenfirewall in real-world scenarios. ## Quick Start @@ -152,6 +152,26 @@ node examples/8-cross-provider-fallback.js --- +### 9. Router QA Dry Run (`9-router-qa-dry-run.js`) +**What it shows:** +- Validating fallback router configuration without real API calls +- Registering placeholder provider keys for deterministic smoke tests +- Simulating rate-limit and provider-unavailable failures +- Inspecting retry decisions and cross-provider router state + +**Best for:** CI smoke checks, release QA, and safely testing fallback chains before using live provider keys + +**Run:** +```bash +node examples/9-router-qa-dry-run.js +``` + +**Prerequisites:** +- Run `npm run build` first when executing from a local checkout +- No real provider API keys are required + +--- + ## Common Patterns ### Pattern 1: Block Mode (Strict Budget)