@byan/copilot-router
Intelligent cost-optimizing router for GitHub Copilot CLI

Automatically route tasks to cheap (worker) or expensive (agent) models based on complexity analysis. Save up to 54% on LLM costs while maintaining quality.
🎯 Why Copilot Router?
Problem: Using expensive models (gpt-4o) for all tasks wastes money. Using cheap models (gpt-4o-mini) for complex tasks produces poor results.
Solution: Automatically analyze task complexity and route to the right model.
Cost Savings
Traditional (100% gpt-4o): $0.30 per 100 calls
Smart Routing (60/40 split): $0.138 per 100 calls
─────────────────────
Savings: 54% 💰 ($162/year per 1K daily calls)
Routing Logic
| < 30 | Worker | gpt-4o-mini | $0.0003 | Simple edits, formatting |
| 30-60 | Worker + Fallback | gpt-4o-mini → gpt-4o | $0.0003 | Medium complexity |
| ≥ 60 | Agent | gpt-4o | $0.003 | Analysis, reasoning, creation |
🚀 Installation
npm install @byan/copilot-router
Prerequisites:
- Node.js >= 18.0.0
- GitHub Copilot subscription
- GitHub Copilot CLI installed
🚀 Quick Start
Installation
npm install @byan/copilot-router
cd ~/copilot-router
npm link
Quick Test (30 seconds):
cd ~/copilot-router
node integrations/copilot-cli/cost-optimized-agent.js
📖 Full integration guide: COPILOT-CLI-INTEGRATION.md
🚀 Fast track: QUICK-START.md
Prerequisites:
- Node.js ≥ 18.0.0
- GitHub Copilot subscription (optional for test mode)
- TypeScript 5.0+ (for TypeScript projects)
Basic Usage
import { CopilotRouter } from '@byan/copilot-router';
const router = new CopilotRouter();
const result1 = await router.route({
input: "Fix typo in README",
type: 'simple'
});
console.log(result1.route);
console.log(result1.cost);
const result2 = await router.route({
input: "Design microservices architecture with event sourcing",
type: 'reasoning',
contextSize: 5000,
steps: 5
});
console.log(result2.route);
console.log(result2.cost);
const stats = router.getTracker().getStatistics();
console.log(`Saved ${stats.savingsPercent}%`);
await router.close();
Cost Tracking
const router = new CopilotRouter();
for (const task of tasks) {
await router.route(task);
}
const stats = router.getTracker().getStatistics();
console.log(`
Total calls: ${stats.totalCalls}
Worker: ${stats.workerCalls} (${stats.workerPercent}%)
Agent: ${stats.agentCalls} (${stats.agentPercent}%)
Cost: $${stats.actualCost}
Baseline: $${stats.baselineCost}
Savings: ${stats.savingsPercent}%
`);
const json = router.getTracker().exportJSON();
const csv = router.getTracker().exportCSV();
console.log(router.getTracker().printSummary());
📊 Features
Core Capabilities
- ✅ Complexity Analysis - 5-factor scoring algorithm (0-100 points)
- ✅ Automatic Routing - Worker vs Agent selection with fallback
- ✅ Cost Tracking - Real-time cost monitoring and reporting
- ✅ Retry Logic - Exponential backoff with 3 max attempts
- ✅ Test Mode - Development without GitHub authentication
- ✅ Type Safety - Full TypeScript support with strict mode
Complexity Factors
| Input Length | 0-20 pts | Prompt length (< 100 → 0, ≥ 1000 → 20) |
| Task Type | 0-30 pts | Simple (0), Format (5), Generate (15), Reasoning (30) |
| Context Size | 0-20 pts | Code/docs size (< 1K → 5, ≥ 5K → 20) |
| Steps | 0-15 pts | Multi-step tasks (1 step → 0, ≥ 4 → 15) |
| Output Format | 0-15 pts | Text (0), JSON (5), Complex (15) |
Total: 0-100 points → determines routing decision
Cost Tracking Metrics
- Total calls (worker/agent distribution)
- Token usage (per call and aggregate)
- Cost analysis (actual vs baseline)
- Savings percentage
- Fallback frequency
- Export to JSON/CSV/console
🏗️ Architecture
┌─────────────────────────────────────────────────────────┐
│ Your Application │
└─────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ @byan/copilot-router │
│ │
│ ┌──────────────────┐ ┌────────────────────────┐ │
│ │ ComplexityAnalyzer│ ──▶ │ CopilotRouter │ │
│ │ 5-factor scoring│ │ Route logic │ │
│ └──────────────────┘ │ Retry + Fallback │ │
│ └────────┬───────────────┘ │
│ │ │
│ ┌──────────────────┐ ▼ │
│ │ CostTracker │ ┌────────────────────────┐ │
│ │ Track metrics │ ◀─── │ CopilotClient │ │
│ │ Export reports │ │ Test/Real SDK modes │ │
│ └──────────────────┘ └────────┬───────────────┘ │
└────────────────────────────────────┼───────────────────┘
│
▼
┌────────────────────────┐
│ GitHub Copilot CLI SDK │
│ JSON-RPC │
└────────┬───────────────┘
│
┌────────────┴────────────┐
▼ ▼
┌──────────┐ ┌──────────┐
│ gpt-4o-mini│ │ gpt-4o │
│ (Worker) │ │ (Agent) │
│ $0.0003 │ │ $0.003 │
└──────────┘ └──────────┘
Components
| ComplexityAnalyzer | Score tasks 0-100 based on 5 factors |
| CopilotRouter | Route to worker/agent, handle retries/fallback |
| CostTracker | Track costs, calculate savings, export reports |
| CopilotClient | Wrap GitHub Copilot SDK, support test mode |
📚 API Reference
CopilotRouter
Main router class for task routing and execution.
Constructor
new CopilotRouter(config?: Partial<RouterConfig>)
Options:
interface RouterConfig {
workerThreshold: number;
agentThreshold: number;
fallbackEnabled: boolean;
workerModel: ModelConfig;
agentModel: ModelConfig;
maxRetries: number;
}
Methods
route(task: Task): Promise<RouteResult>
Route and execute a task.
const result = await router.route({
id: 'task-123',
input: 'Analyze this code',
type: 'analysis',
contextSize: 2000,
steps: 3,
outputFormat: 'json'
});
getTracker(): CostTracker
Get the cost tracker instance.
const tracker = router.getTracker();
const stats = tracker.getStatistics();
getConfig(): RouterConfig
Get current router configuration.
updateConfig(config: Partial<RouterConfig>): void
Update router configuration.
router.updateConfig({
workerThreshold: 25,
fallbackEnabled: false
});
close(): Promise<void>
Close the router and cleanup resources.
await router.close();
ComplexityAnalyzer
Analyze task complexity and generate scores.
Constructor
const analyzer = new ComplexityAnalyzer();
Methods
calculateComplexity(task: Task): ComplexityScore
Calculate complexity score for a task.
const score = analyzer.calculateComplexity({
input: 'Design architecture',
type: 'reasoning',
contextSize: 5000,
steps: 4,
outputFormat: 'complex'
});
getThresholds(): { worker: number, agent: number }
Get score thresholds.
CostTracker
Track costs and generate reports.
Constructor
const tracker = new CostTracker(agentCostPerCall?: number);
Methods
track(record: CallRecord): void
Track a single call.
tracker.track({
taskId: 'task-1',
model: 'worker',
modelName: 'gpt-4o-mini',
tokens: 500,
cost: 0.0003,
complexityScore: 25,
fallbackUsed: false
});
getStatistics(): CostStatistics
Get comprehensive statistics.
const stats = tracker.getStatistics();
getRecords(): CallRecord[]
Get all tracked records.
reset(): void
Clear all tracked data.
exportJSON(): string
Export data as JSON.
const json = tracker.exportJSON();
fs.writeFileSync('costs.json', json);
exportCSV(): string
Export data as CSV.
const csv = tracker.exportCSV();
fs.writeFileSync('costs.csv', csv);
printSummary(): string
Get formatted summary for console.
console.log(tracker.printSummary());
💡 Usage Examples
Example 1: Basic Routing
import { CopilotRouter } from '@byan/copilot-router';
const router = new CopilotRouter();
async function processTasks() {
const tasks = [
{ input: 'Fix typo', type: 'simple' },
{ input: 'Refactor function', type: 'generate', contextSize: 1000 },
{ input: 'Design system architecture', type: 'reasoning', steps: 5 }
];
for (const task of tasks) {
const result = await router.route(task);
console.log(`${result.route}: $${result.cost} (${result.tokens} tokens)`);
}
await router.close();
}
Example 2: Cost Optimization
import { CopilotRouter } from '@byan/copilot-router';
const router = new CopilotRouter({
workerThreshold: 25,
fallbackEnabled: true,
maxRetries: 5
});
await processLargeWorkload(router);
const stats = router.getTracker().getStatistics();
if (stats.savingsPercent < 40) {
console.warn('Savings below target, consider lowering threshold');
router.updateConfig({ workerThreshold: 20 });
}
console.log(`
Distribution: ${stats.workerPercent}% worker, ${stats.agentPercent}% agent
Savings: ${stats.savingsPercent}%
ROI: $${stats.savingsAmount}
`);
Example 3: Daily Cost Reports
import { CopilotRouter } from '@byan/copilot-router';
import fs from 'fs';
const router = new CopilotRouter();
async function generateDailyReport() {
for (const task of dailyTasks) {
await router.route(task);
}
const tracker = router.getTracker();
const timestamp = new Date().toISOString().split('T')[0];
fs.writeFileSync(
`reports/costs-${timestamp}.json`,
tracker.exportJSON()
);
fs.writeFileSync(
`reports/costs-${timestamp}.csv`,
tracker.exportCSV()
);
await sendEmail({
subject: `Cost Report ${timestamp}`,
body: tracker.printSummary()
});
await router.close();
}
Example 4: Custom Configuration
import { CopilotRouter, ModelConfig } from '@byan/copilot-router';
const customWorker: ModelConfig = {
model: 'gpt-4o-mini',
inputCost: 0.150 / 1_000_000,
outputCost: 0.600 / 1_000_000
};
const customAgent: ModelConfig = {
model: 'gpt-4o',
inputCost: 2.50 / 1_000_000,
outputCost: 10.00 / 1_000_000
};
const router = new CopilotRouter({
workerModel: customWorker,
agentModel: customAgent,
workerThreshold: 30,
agentThreshold: 60,
fallbackEnabled: true,
maxRetries: 3
});
Example 5: Integration with Express
import express from 'express';
import { CopilotRouter } from '@byan/copilot-router';
const app = express();
const router = new CopilotRouter();
app.post('/api/complete', async (req, res) => {
try {
const result = await router.route({
input: req.body.prompt,
type: req.body.type || 'generate',
contextSize: req.body.context?.length
});
res.json({
content: result.content,
cost: result.cost,
tokens: result.tokens,
route: result.route
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.get('/api/stats', (req, res) => {
const stats = router.getTracker().getStatistics();
res.json(stats);
});
app.listen(3000);
⚙️ Configuration
Environment Variables
GITHUB_TOKEN=your_github_token
COPILOT_WORKER_MODEL=gpt-4o-mini
COPILOT_AGENT_MODEL=gpt-4o
Router Configuration
const router = new CopilotRouter({
workerThreshold: 30,
agentThreshold: 60,
fallbackEnabled: true,
maxRetries: 3,
workerModel: {
model: 'gpt-4o-mini',
inputCost: 0.150 / 1_000_000,
outputCost: 0.600 / 1_000_000
},
agentModel: {
model: 'gpt-4o',
inputCost: 2.50 / 1_000_000,
outputCost: 10.00 / 1_000_000
}
});
Test Mode vs Real Mode
Test Mode (default):
- No GitHub authentication required
- Mocked LLM responses
- Fixed 500 tokens per call
- Great for development/testing
Real Mode:
- Requires GitHub Copilot subscription
- Actual API calls to Copilot SDK
- Real token usage and costs
- Production use
import { CopilotClient } from '@byan/copilot-router';
const testClient = new CopilotClient({ testMode: true });
const realClient = new CopilotClient({ testMode: false });
🔧 Troubleshooting
Common Issues
1. "Module not found: @github/copilot-sdk"
npm install @github/copilot-sdk
2. "Coverage below threshold"
The module has 80% coverage because real SDK mode paths aren't tested (require GitHub auth). This is expected in test mode.
3. "All tasks routed to worker"
Check task scoring:
import { ComplexityAnalyzer } from '@byan/copilot-router';
const analyzer = new ComplexityAnalyzer();
const score = analyzer.calculateComplexity(yourTask);
console.log(score);
Adjust thresholds:
router.updateConfig({
workerThreshold: 20,
agentThreshold: 50
});
4. "Costs don't match expectations"
In test mode, all calls use fixed 500 tokens. Real costs vary based on actual token usage.
5. "TypeScript compilation errors"
Ensure TypeScript 5.0+:
npm install --save-dev typescript@^5.0.0
Debug Mode
const router = new CopilotRouter({
debug: true
});
🧪 Development
Setup
git clone https://github.com/byan/copilot-router.git
cd copilot-router
npm install
npm run build
npm test
Project Structure
copilot-router/
├── src/
│ ├── types.ts # TypeScript type definitions
│ ├── analyzer.ts # Complexity scoring
│ ├── router.ts # Main routing logic
│ ├── copilot-client.ts # SDK wrapper
│ ├── cost-tracker.ts # Cost tracking
│ └── index.ts # Public exports
├── test/
│ ├── setup.test.ts # Setup validation
│ ├── analyzer.test.ts # Analyzer tests (36)
│ ├── router.test.ts # Router tests (25)
│ ├── copilot-client.test.ts # Client tests (23)
│ ├── cost-tracker.test.ts # Tracker tests (22)
│ └── integration.test.ts # Integration tests (5)
├── dist/ # Compiled JavaScript
├── package.json
├── tsconfig.json
└── README.md
Testing
npm test
npm test -- analyzer.test.ts
npm run test:watch
npm run test:coverage
npm test -- --verbose
Test Stats:
- Total: 115 tests
- Coverage: 80.19%
- All passing ✅
Building
npm run build
npm run build:watch
rm -rf dist && npm run build
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature)
- Make your changes
- Run tests (
npm test)
- Commit (
git commit -m 'feat: add amazing feature')
- Push (
git push origin feature/amazing-feature)
- Open a Pull Request
Commit Convention:
feat: New feature
fix: Bug fix
docs: Documentation only
test: Adding tests
refactor: Code refactoring
chore: Maintenance
📈 Roadmap
v1.0.0 (Current - Alpha 5)
v1.1.0 (Next)
v1.2.0 (Future)
📊 Performance
Benchmarks
| Complexity Analysis | < 1ms | Pure computation |
| Route Decision | < 1ms | Score-based logic |
| Test Mode Execution | ~10ms | Mocked response |
| Real Mode Execution | 500-2000ms | Actual LLM call |
Optimization Tips
- Batch processing: Route multiple tasks in parallel
- Caching: Cache complexity scores for similar tasks
- Threshold tuning: Lower thresholds for more worker usage
- Fallback disabled: Disable if quality is acceptable
- Connection pooling: Reuse router instances
await Promise.all(tasks.map(task => router.route(task)));
for (const task of tasks) {
await router.route(task);
}
🧪 Testing
npm test
npm test -- analyzer.test.ts
npm run test:watch
npm run test:coverage
Test Coverage:
- 115 tests total (all passing ✅)
- 80.19% code coverage
- 36 analyzer tests
- 25 router tests
- 23 client tests
- 22 tracker tests
- 5 integration tests
- 4 setup tests
📝 License
MIT © BYAN v2
See LICENSE for details.
🙏 Acknowledgments
Built with:
Part of the BYAN v2 ecosystem.
📞 Support
🎯 Quick Links
Status: 🟢 Stable v1.0.0
Stability: Production Ready
Released: February 10, 2026
NPM: @byan/copilot-router
Made with ❤️ by BYAN v2 - Builder of YAN