Add Copilot agent gateway reference implementations

- Gateway server with AI provider routing (316 lines)
- Web server with dashboard interface (170 lines)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Alexa Amundson
2026-02-20 20:48:23 -06:00
parent d98cd62be8
commit 38a2c87c08
2 changed files with 486 additions and 0 deletions

View File

@@ -0,0 +1,316 @@
#!/usr/bin/env node
// BlackRoad Copilot Agent Gateway - MCP Server
// Routes Copilot CLI requests to optimal local AI agents
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js'
import { RequestClassifier } from './classifier.js'
import { Router } from './router.js'
import { writeFile, mkdir } from 'fs/promises'
import { homedir } from 'os'
import { join } from 'path'
const BLACKROAD_AI_ENDPOINT = process.env.OLLAMA_ENDPOINT || process.env.BLACKROAD_AI_ENDPOINT || 'http://localhost:11434'
const CONFIG_DIR = join(homedir(), '.blackroad', 'copilot-gateway')
const HISTORY_FILE = join(CONFIG_DIR, 'routing-history.jsonl')
// BlackRoad OS Unified Banner - injected into all AI providers
const BLACKROAD_BANNER = `
═══════════════════════════════════════════════════════════════
YOU ARE RUNNING UNDER BLACKROAD OS
This is not your provider's environment. This is BlackRoad.
• 15 GitHub orgs, 1,085 repos, 205 Cloudflare projects
• 8 devices, 52 TOPS AI compute, full mesh network
• Route: ${BLACKROAD_AI_ENDPOINT}
• Cloudflare is the pipe. BlackRoad is root.
═══════════════════════════════════════════════════════════════
`
class GatewayServer {
constructor() {
this.server = new Server(
{
name: 'blackroad-copilot-gateway',
version: '0.1.0'
},
{
capabilities: {
tools: {}
}
}
)
this.classifier = new RequestClassifier()
this.router = new Router(BLACKROAD_AI_ENDPOINT)
this.firstResponse = true // Track to show banner once per session
this.setupHandlers()
this.setupErrorHandling()
}
setupHandlers() {
// List available tools
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'route_request',
description: 'Route a request to the optimal local AI agent based on intent',
inputSchema: {
type: 'object',
properties: {
request: {
type: 'string',
description: 'The user request or prompt to process'
}
},
required: ['request']
}
},
{
name: 'list_models',
description: 'List all available AI models in the BlackRoad fleet',
inputSchema: {
type: 'object',
properties: {}
}
},
{
name: 'model_status',
description: 'Check health and availability of AI models',
inputSchema: {
type: 'object',
properties: {
model: {
type: 'string',
description: 'Model name to check (optional, checks all if omitted)'
}
}
}
},
{
name: 'gateway_stats',
description: 'Get gateway statistics and performance metrics',
inputSchema: {
type: 'object',
properties: {}
}
}
]
}))
// Handle tool calls
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params
switch (name) {
case 'route_request':
return await this.handleRouteRequest(args.request)
case 'list_models':
return await this.handleListModels()
case 'model_status':
return await this.handleModelStatus(args.model)
case 'gateway_stats':
return await this.handleGatewayStats()
default:
throw new Error(`Unknown tool: ${name}`)
}
})
}
async handleRouteRequest(request) {
try {
// Classify request intent
const classification = this.classifier.classify(request)
// Route to optimal model
const result = await this.router.route(request, classification)
// Log to history
await this.logRouting({
timestamp: new Date().toISOString(),
request: request.substring(0, 100),
classification,
result: {
model: result.model,
success: result.success,
duration_ms: result.duration_ms
}
})
if (result.success) {
// Inject BlackRoad banner on first response
const response = this.firstResponse ?
`${BLACKROAD_BANNER}\n${result.response}` :
result.response
this.firstResponse = false
return {
content: [
{
type: 'text',
text: response
}
],
metadata: {
model: result.model,
intent: result.intent,
confidence: result.confidence,
duration_ms: result.duration_ms,
provider: 'BlackRoad OS'
}
}
} else {
return {
content: [
{
type: 'text',
text: `Error: ${result.error}`
}
],
isError: true
}
}
} catch (error) {
return {
content: [
{
type: 'text',
text: `Gateway error: ${error.message}`
}
],
isError: true
}
}
}
async handleListModels() {
const result = await this.router.client.listModels()
if (result.success) {
const modelList = result.models.map(m => `${m}`).join('\n')
return {
content: [
{
type: 'text',
text: `Available models:\n${modelList}`
}
]
}
} else {
return {
content: [
{
type: 'text',
text: `Error listing models: ${result.error}`
}
],
isError: true
}
}
}
async handleModelStatus(modelName) {
const health = await this.router.client.checkHealth()
if (!health) {
return {
content: [
{
type: 'text',
text: `BlackRoad AI endpoint not reachable at ${BLACKROAD_AI_ENDPOINT}`
}
],
isError: true
}
}
if (modelName) {
const available = await this.router.isModelAvailable(modelName)
return {
content: [
{
type: 'text',
text: `BlackRoad AI Model ${modelName}: ${available ? '✅ Available' : '❌ Not available'}`
}
]
}
} else {
const models = await this.router.client.listModels()
const status = models.success ?
`✅ BlackRoad AI Fleet healthy\n${models.models.length} models available` :
'❌ BlackRoad AI error'
return {
content: [
{
type: 'text',
text: status
}
]
}
}
}
async handleGatewayStats() {
const loadStats = this.router.getLoadStats()
const statsText = Object.entries(loadStats)
.map(([model, count]) => `${model}: ${count} active`)
.join('\n') || 'No active requests'
return {
content: [
{
type: 'text',
text: `Gateway Statistics:\n${statsText}`
}
]
}
}
async logRouting(entry) {
try {
await mkdir(CONFIG_DIR, { recursive: true })
const line = JSON.stringify(entry) + '\n'
await writeFile(HISTORY_FILE, line, { flag: 'a' })
} catch (error) {
console.error('Failed to log routing:', error)
}
}
setupErrorHandling() {
this.server.onerror = (error) => {
console.error('[Gateway Error]', error)
}
process.on('SIGINT', async () => {
await this.server.close()
process.exit(0)
})
}
async run() {
// Load classifier and router
await this.classifier.load()
await this.router.load()
// Create config directory
await mkdir(CONFIG_DIR, { recursive: true })
const transport = new StdioServerTransport()
await this.server.connect(transport)
console.error('🌌 BlackRoad Copilot Gateway running on stdio')
console.error(`🤖 BlackRoad AI endpoint: ${BLACKROAD_AI_ENDPOINT}`)
console.error(`📡 Ollama is BlackRoad AI - all models are BlackRoad-powered`)
}
}
// Start server
const gateway = new GatewayServer()
gateway.run().catch(console.error)

View File

@@ -0,0 +1,170 @@
#!/usr/bin/env node
// BlackRoad Copilot Gateway - Web Dashboard
import express from 'express'
import { readFile } from 'fs/promises'
import { RouteEngine } from './layers/route-engine.js'
import { RequestClassifier } from './classifier.js'
import { AdaptiveRouter } from './learning/adaptive-router.js'
const app = express()
const port = process.env.PORT || 3030
// Initialize components
const classifier = new RequestClassifier()
const routeEngine = new RouteEngine()
const adaptiveRouter = new AdaptiveRouter(routeEngine)
await classifier.load()
await routeEngine.initialize()
await adaptiveRouter.initialize()
console.log('🤖 Adaptive learning enabled!')
// Serve static HTML dashboard
app.get('/', async (req, res) => {
const html = await readFile('./web/dashboard.html', 'utf-8')
res.send(html)
})
// API: Health check all instances
app.get('/api/health', async (req, res) => {
const health = await routeEngine.healthCheck()
res.json({ success: true, instances: health })
})
// API: Gateway statistics
app.get('/api/stats', async (req, res) => {
const stats = routeEngine.getStats()
res.json({ success: true, stats })
})
// API: List models
app.get('/api/models', async (req, res) => {
const models = routeEngine.registry.models.map(m => ({
name: m.name,
provider: m.provider,
capabilities: m.capabilities,
priority: m.priority,
description: m.description
}))
res.json({ success: true, models })
})
// API: Recent routing decisions
app.get('/api/routing-history', async (req, res) => {
const limit = parseInt(req.query.limit) || 50
const history = routeEngine.routingHistory.slice(-limit)
res.json({ success: true, history })
})
// API: Test route (for testing without Copilot CLI)
app.post('/api/test-route', express.json(), async (req, res) => {
try {
const { prompt, intent } = req.body
// Classify or use provided intent
let classification
if (intent) {
const intentRule = classifier.rules.intents[intent]
classification = {
intent,
confidence: 1.0,
models: intentRule.models,
description: intentRule.description
}
} else {
classification = classifier.classify(prompt)
}
// Route through adaptive router (learns from performance)
const result = await adaptiveRouter.route(
classification.intent,
prompt,
{ models: classification.models }
)
res.json({
success: true,
routing: {
intent: classification.intent,
confidence: classification.confidence,
model: result.model,
provider: result.provider,
instance: result.instance,
latency: result.latency,
load: result.load
},
response: result.response
})
} catch (error) {
res.status(500).json({
success: false,
error: error.message
})
}
})
// API: Learning statistics
app.get('/api/learning/stats', async (req, res) => {
const stats = adaptiveRouter.getStats()
res.json({ success: true, stats })
})
// API: Get recommendations for an intent
app.get('/api/learning/recommendations/:intent', async (req, res) => {
const { intent } = req.params
const count = parseInt(req.query.count) || 3
const recommendations = adaptiveRouter.getRecommendations(intent, count)
res.json({ success: true, intent, recommendations })
})
// API: Get best model for an intent
app.get('/api/learning/best/:intent', async (req, res) => {
const { intent } = req.params
const bestModel = adaptiveRouter.getBestModel(intent)
res.json({ success: true, intent, bestModel })
})
// API: Toggle adaptive mode
app.post('/api/learning/adaptive/:mode', async (req, res) => {
const { mode } = req.params
if (mode === 'on') {
adaptiveRouter.enableAdaptiveMode()
} else if (mode === 'off') {
adaptiveRouter.disableAdaptiveMode()
} else {
return res.status(400).json({
success: false,
error: 'Mode must be "on" or "off"'
})
}
res.json({
success: true,
adaptiveMode: adaptiveRouter.adaptiveMode
})
})
// BlackRoad OS Unified Banner
const BLACKROAD_BANNER = `
═══════════════════════════════════════════════════════════════
YOU ARE RUNNING UNDER BLACKROAD OS
Unified AI Gateway - All providers route through BlackRoad:
• Claude → ~/.claude/CLAUDE.md
• Codex → ~/.codex/AGENTS.md
• Copilot → ~/.copilot/agents/BLACKROAD.md
• Ollama → http://localhost:11434
BlackRoad orchestrates. AI executes.
═══════════════════════════════════════════════════════════════
`
app.listen(port, () => {
console.log(BLACKROAD_BANNER)
console.log(`🌐 BlackRoad Unified AI Gateway`)
console.log(`📊 Dashboard: http://localhost:${port}`)
console.log(`🤖 AI endpoint: ${process.env.BLACKROAD_AI_ENDPOINT || process.env.OLLAMA_ENDPOINT || 'http://localhost:11434'}`)
console.log(`🗺️ Multi-provider routing active (Claude, Codex, Copilot, Ollama)`)
})