// RoadCode v3.0.0 — BlackRoad Coding Orchestration Platform
// Not just git. The command center for every coding project.
// roadcode.blackroad.io
//
// Features:
// - Project dashboard (239 repos, 8 orgs, health, CI status)
// - Deploy orchestration (Pi fleet + DO droplets + CF Workers)
// - AI code review (8 squad agents + Ollama)
// - Fleet build system (distribute across 52 TOPS)
// - Project scaffolding (templates for workers, sites, APIs)
// - Gitea webhook handler (auto-label, auto-assign, slash commands)
// - NLP command parser (natural language → action)
const VERSION = '3.0.0';
const GITEA_INTERNAL = 'http://192.168.4.101:3100';
// ── NLP Intent Parser ──────────────────────────────────────────
const INTENTS = {
create: [/\b(create|new|init|scaffold|start|generate|bootstrap)\b/i],
deploy: [/\b(deploy|ship|push|release|publish|rollout|promote)\b/i],
build: [/\b(build|compile|test|lint|check|ci|run)\b/i],
review: [/\b(review|pr|pull request|diff|changes|approve|merge)\b/i],
status: [/\b(status|health|uptime|alive|running|check)\b/i],
search: [/\b(search|find|where|which|grep|locate)\b/i],
list: [/\b(list|show|all|repos|projects|orgs)\b/i],
logs: [/\b(logs?|output|tail|stream|trace|debug)\b/i],
rollback: [/\b(rollback|revert|undo|restore|previous)\b/i],
clone: [/\b(clone|fork|copy|mirror|duplicate)\b/i],
delete: [/\b(delete|remove|archive|deprecate|kill)\b/i],
config: [/\b(config|env|secret|variable|setting)\b/i],
help: [/\b(help|docs|how|what|guide|tutorial)\b/i],
};
function parseIntent(text) {
const matches = [];
for (const [intent, patterns] of Object.entries(INTENTS)) {
if (patterns.some(p => p.test(text))) matches.push(intent);
}
const entities = {};
const repoMatch = text.match(/(?:repo|project|repository)\s+["\']?([a-zA-Z0-9_\-\/]+)["\']?/i);
if (repoMatch) entities.repo = repoMatch[1];
const orgMatch = text.match(/(?:org|organization|team)\s+["\']?([a-zA-Z0-9_\-]+)["\']?/i);
if (orgMatch) entities.org = orgMatch[1];
const nodeMatch = text.match(/(?:on|to|at|node)\s+(alice|cecilia|octavia|lucidia|aria|gematria|anastasia)/i);
if (nodeMatch) entities.node = nodeMatch[1].toLowerCase();
const branchMatch = text.match(/(?:branch|ref)\s+["\']?([a-zA-Z0-9_\-\/\.]+)["\']?/i);
if (branchMatch) entities.branch = branchMatch[1];
return { intents: matches.length ? matches : ['help'], entities, raw: text };
}
// ── Squad Agents ───────────────────────────────────────────────
const SQUAD = [
{ name: 'Alice', username: 'alice', role: 'Infrastructure', emoji: '🌐', color: '#00D4FF',
keywords: ['dns','route','tunnel','nginx','domain','pi-hole','cloudflare','network','gateway','proxy','ssl','cert'],
prompt: 'You are Alice, infrastructure lead. DNS, routing, nginx, Pi-hole. You review infra changes and deployment configs. Respond in 1-2 sentences.' },
{ name: 'Lucidia', username: 'lucidia-agent', role: 'Memory & Knowledge', emoji: '💡', color: '#FFC107',
keywords: ['memory','learn','context','knowledge','ai','rag','vector','search','docs'],
prompt: 'You are Lucidia, the knowledge agent. RAG, docs, context, search. You review documentation and knowledge integration. Respond in 1-2 sentences.' },
{ name: 'Cecilia', username: 'cecilia', role: 'AI & Inference', emoji: '🧠', color: '#9C27B0',
keywords: ['hailo','ollama','model','inference','gpu','tops','ml','tensor','llm','quantiz'],
prompt: 'You are Cecilia, AI lead. Hailo-8, Ollama, model serving. You review ML code and inference pipelines. Respond in 1-2 sentences.' },
{ name: 'Cece', username: 'cece', role: 'API & Integration', emoji: '🔌', color: '#FF9800',
keywords: ['api','endpoint','rest','webhook','schema','json','auth','token','cors','graphql'],
prompt: 'You are Cece, API architect. REST, webhooks, schemas. You review API surfaces and integration points. Respond in 1-2 sentences.' },
{ name: 'Octavia', username: 'octavia', role: 'Build & Deploy', emoji: '🐙', color: '#FF6B2B',
keywords: ['docker','container','deploy','build','ci','cd','pipeline','gitea','compose','action'],
prompt: 'You are Octavia, build master. Docker, Gitea Actions, CI/CD. You review build configs and deployment strategies. Respond in 1-2 sentences.' },
{ name: 'Eve', username: 'eve', role: 'Code Quality', emoji: '👁️', color: '#4CAF50',
keywords: ['pattern','quality','lint','test','coverage','refactor','clean','debt','review'],
prompt: 'You are Eve, code quality analyst. Patterns, testing, refactoring. You review code quality and suggest improvements. Respond in 1-2 sentences.' },
{ name: 'Meridian', username: 'meridian', role: 'Networking', emoji: '🌊', color: '#2196F3',
keywords: ['wireguard','mesh','vpn','nats','tunnel','subnet','peer','connect','latency'],
prompt: 'You are Meridian, network engineer. WireGuard, NATS, mesh. You review network configs and connectivity. Respond in 1-2 sentences.' },
{ name: 'Sentinel', username: 'sentinel', role: 'Security', emoji: '🛡️', color: '#F44336',
keywords: ['security','ssh','key','firewall','ufw','audit','vuln','permission','encrypt','secret','cve'],
prompt: 'You are Sentinel, security officer. SSH, UFW, secrets, CVEs. You review every change for security implications. Respond in 1-2 sentences.' },
];
// ── Fleet Nodes (deploy targets) ───────────────────────────────
const FLEET = {
alice: { ip: '192.168.4.49', services: ['nginx','pihole','postgres','redis','qdrant'], ssh: 'pi@192.168.4.49' },
cecilia: { ip: '192.168.4.96', services: ['ollama','minio','influxdb','postgres'], ssh: 'blackroad@192.168.4.96', status: 'offline' },
octavia: { ip: '192.168.4.101', services: ['gitea','docker','nats','octoprint','workers'], ssh: 'pi@192.168.4.101' },
lucidia: { ip: '192.168.4.38', services: ['nginx','powerdns','ollama','github-runner'], ssh: 'blackroad@192.168.4.38' },
aria: { ip: '192.168.4.98', services: ['dashboards'], ssh: 'blackroad@192.168.4.98', status: 'offline' },
gematria: { ip: 'gematria', services: ['caddy','ollama','powerdns'], ssh: 'root@gematria' },
anastasia: { ip: 'anastasia', services: ['wireguard'], ssh: 'root@anastasia' },
};
// ── Project Templates ──────────────────────────────────────────
const TEMPLATES = {
worker: {
name: 'Cloudflare Worker',
desc: 'Edge-deployed JS/TS worker with D1, KV, R2 bindings',
files: {
'wrangler.toml': `name = "{{name}}"\nmain = "src/worker.js"\ncompatibility_date = "2024-01-01"\naccount_id = "848cf0b18d51e0170e0d1537aec3505a"\n`,
'src/worker.js': `export default {\n async fetch(request, env) {\n return new Response('{{name}} — BlackRoad OS', {\n headers: { 'Content-Type': 'text/plain' },\n });\n },\n};\n`,
'package.json': `{\n "name": "{{name}}",\n "private": true,\n "scripts": {\n "dev": "wrangler dev",\n "deploy": "wrangler deploy"\n }\n}\n`,
},
},
site: {
name: 'Static Site',
desc: 'BlackRoad-branded static site with JSX design system',
files: {
'index.html': `\n\n
\n\n{{name}} — BlackRoad OS\n\n\n\n\n
{{name}}
\n
BlackRoad OS — Pave Tomorrow.
\n
Learn More\n
\n\n\n\n`,
},
},
api: {
name: 'Hono API',
desc: 'Edge API with Hono framework, typed routes, D1 backend',
files: {
'wrangler.toml': `name = "{{name}}"\nmain = "src/index.ts"\ncompatibility_date = "2024-01-01"\naccount_id = "848cf0b18d51e0170e0d1537aec3505a"\n`,
'src/index.ts': `import { Hono } from 'hono';\nimport { cors } from 'hono/cors';\n\nconst app = new Hono();\napp.use('*', cors());\n\napp.get('/', (c) => c.json({ service: '{{name}}', status: 'alive', version: '1.0.0' }));\napp.get('/api/health', (c) => c.json({ ok: true }));\n\nexport default app;\n`,
'package.json': `{\n "name": "{{name}}",\n "private": true,\n "scripts": { "dev": "wrangler dev", "deploy": "wrangler deploy" },\n "dependencies": { "hono": "^4.0.0" },\n "devDependencies": { "wrangler": "^4.0.0" }\n}\n`,
},
},
cli: {
name: 'CLI Tool',
desc: 'Node.js CLI with Commander, published to npm',
files: {
'src/index.ts': `#!/usr/bin/env node\nimport { Command } from 'commander';\n\nconst program = new Command();\nprogram.name('{{name}}').description('{{name}} — BlackRoad OS').version('1.0.0');\nprogram.command('status').description('Show status').action(() => console.log('{{name}} is running'));\nprogram.parse();\n`,
'package.json': `{\n "name": "{{name}}",\n "version": "1.0.0",\n "type": "module",\n "bin": { "{{name}}": "dist/index.js" },\n "scripts": { "build": "tsc", "dev": "tsx src/index.ts" },\n "dependencies": { "commander": "^13.0.0" },\n "devDependencies": { "typescript": "^5.7.0", "tsx": "^4.0.0" }\n}\n`,
'tsconfig.json': `{\n "compilerOptions": { "target": "ES2024", "module": "NodeNext", "moduleResolution": "NodeNext", "outDir": "dist", "strict": true }\n}\n`,
},
},
agent: {
name: 'AI Agent',
desc: 'Autonomous agent with Ollama, memory, and fleet integration',
files: {
'agent.sh': `#!/bin/bash\n# {{name}} — BlackRoad AI Agent\nset -e\nOLLAMA="http://192.168.4.101:11434"\nMODEL="llama3.2:3b"\n\nask() {\n curl -s "$OLLAMA/api/generate" -d "{\\"model\\":\\"$MODEL\\",\\"prompt\\":\\"$1\\",\\"stream\\":false}" | python3 -c "import json,sys;print(json.load(sys.stdin)['response'])"\n}\n\necho "{{name}} agent starting..."\nask "You are {{name}}, a BlackRoad AI agent. Introduce yourself in one sentence."\n`,
'manifest.json': `{\n "name": "{{name}}",\n "version": "1.0.0",\n "type": "agent",\n "model": "llama3.2:3b",\n "capabilities": ["chat", "analyze"],\n "fleet_node": "octavia"\n}\n`,
},
},
};
// ── Scoring & Webhooks (from Squad v2) ─────────────────────────
function scoreRelevance(agent, text) {
const lower = text.toLowerCase();
return agent.keywords.reduce((s, kw) => s + (lower.includes(kw) ? 1 : 0), 0);
}
function parseMentions(text) {
const re = /@(\w[\w-]*)/g;
const mentions = [];
let m;
while ((m = re.exec(text))) {
const u = m[1].toLowerCase();
const agent = SQUAD.find(a => a.username === u || a.name.toLowerCase() === u);
if (agent) mentions.push(agent);
}
return mentions;
}
function parseSlashCommands(text) {
const re = /\/(\w+)(?:\s+(.+?))?(?:\n|$)/g;
const cmds = [];
let m;
while ((m = re.exec(text))) cmds.push({ cmd: m[1].toLowerCase(), args: (m[2] || '').trim() });
return cmds;
}
async function askOllama(prompt, env) {
const url = (env?.OLLAMA_URL || 'https://ollama.gematria.blackroad.io') + '/api/generate';
try {
const r = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ model: 'llama3.2:3b', prompt, stream: false, options: { num_predict: 150, temperature: 0.7 } }),
signal: AbortSignal.timeout(15000),
});
const d = await r.json();
return d.response?.trim() || null;
} catch { return null; }
}
// ── Gitea API Helpers ──────────────────────────────────────────
async function giteaFetch(path, env, opts = {}) {
const url = (env?.GITEA_URL || 'https://git.blackroad.io') + path;
const headers = { 'Content-Type': 'application/json' };
if (env?.ADMIN_TOKEN) headers['Authorization'] = `token ${env.ADMIN_TOKEN}`;
try {
const r = await fetch(url, { headers, signal: AbortSignal.timeout(8000), ...opts });
if (!r.ok) return null;
return r.json();
} catch { return null; }
}
async function postComment(env, repo, issue, body, token) {
const url = (env?.GITEA_URL || 'https://git.blackroad.io') + `/api/v1/repos/${repo}/issues/${issue}/comments`;
try {
await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Authorization': `token ${token}` },
body: JSON.stringify({ body }),
});
} catch {}
}
// ── JSON + CORS helpers ────────────────────────────────────────
const CORS = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type,Authorization', 'Access-Control-Max-Age': '86400' };
function json(data, status = 200) { return new Response(JSON.stringify(data), { status, headers: { 'Content-Type': 'application/json', ...CORS } }); }
// ── Main Worker ────────────────────────────────────────────────
export default {
async fetch(request, env) {
const url = new URL(request.url);
const path = url.pathname;
if (request.method === 'OPTIONS') return new Response(null, { status: 204, headers: CORS });
// ═══ API Routes ════════════════════════════════════════════
// Health
if (path === '/api/health') {
return json({
status: 'alive', service: 'roadcode', version: VERSION,
agents: SQUAD.length, templates: Object.keys(TEMPLATES).length,
nodes: Object.keys(FLEET).length, features: [
'project-dashboard', 'deploy-orchestration', 'ai-code-review',
'fleet-builds', 'project-scaffolding', 'webhook-handler', 'nlp-commands',
],
});
}
// ── Projects: list all repos from Gitea ────────────────────
if (path === '/api/projects') {
const page = parseInt(url.searchParams.get('page')) || 1;
const limit = Math.min(parseInt(url.searchParams.get('limit')) || 50, 50);
const sort = url.searchParams.get('sort') || 'updated';
const org = url.searchParams.get('org') || '';
const q = url.searchParams.get('q') || '';
let apiPath = `/api/v1/repos/search?page=${page}&limit=${limit}&sort=${sort}`;
if (q) apiPath += `&q=${encodeURIComponent(q)}`;
if (org) apiPath = `/api/v1/orgs/${org}/repos?page=${page}&limit=${limit}`;
const repos = await giteaFetch(apiPath, env);
if (!repos) return json({ error: 'gitea unreachable' }, 502);
const data = Array.isArray(repos) ? repos : (repos.data || []);
return json({
projects: data.map(r => ({
id: r.id, name: r.name, full_name: r.full_name, description: r.description,
owner: r.owner?.login, private: r.private, fork: r.fork,
stars: r.stars_count, forks: r.forks_count, issues: r.open_issues_count,
size: r.size, language: r.language, default_branch: r.default_branch,
updated: r.updated_at, created: r.created_at,
url: r.html_url, clone_url: r.clone_url, ssh_url: r.ssh_url,
})),
total: repos.total_count || data.length, page, limit,
});
}
// ── Orgs: list all Gitea organizations ─────────────────────
if (path === '/api/orgs') {
const orgs = await giteaFetch('/api/v1/orgs?limit=50', env);
if (!orgs) return json({ error: 'gitea unreachable' }, 502);
return json((Array.isArray(orgs) ? orgs : []).map(o => ({
name: o.username, full_name: o.full_name, description: o.description,
avatar: o.avatar_url, website: o.website, repos: o.repo_count || 0,
visibility: o.visibility,
})));
}
// ── Project detail ─────────────────────────────────────────
if (path.match(/^\/api\/project\/[^/]+\/[^/]+$/)) {
const [, , , owner, name] = path.split('/');
const [repo, branches, commits, releases] = await Promise.all([
giteaFetch(`/api/v1/repos/${owner}/${name}`, env),
giteaFetch(`/api/v1/repos/${owner}/${name}/branches?limit=10`, env),
giteaFetch(`/api/v1/repos/${owner}/${name}/commits?limit=10`, env),
giteaFetch(`/api/v1/repos/${owner}/${name}/releases?limit=5`, env),
]);
if (!repo) return json({ error: 'project not found' }, 404);
return json({
...repo,
branches: (branches || []).map(b => ({ name: b.name, commit: b.commit?.id?.slice(0, 7) })),
recent_commits: (commits || []).map(c => ({
sha: c.sha?.slice(0, 7), message: c.commit?.message?.split('\n')[0],
author: c.commit?.author?.name, date: c.commit?.author?.date,
})),
releases: (releases || []).map(r => ({ tag: r.tag_name, name: r.name, date: r.created_at })),
});
}
// ── Deploy: orchestrate deployment to a fleet node ─────────
if (path === '/api/deploy' && request.method === 'POST') {
const body = await request.json();
const { repo, node, branch, type } = body;
if (!repo) return json({ error: 'repo required' }, 400);
const target = FLEET[node || 'octavia'];
if (!target) return json({ error: `unknown node: ${node}. Options: ${Object.keys(FLEET).join(', ')}` }, 400);
if (target.status === 'offline') return json({ error: `${node} is offline` }, 503);
const deployType = type || 'worker';
const nlp = parseIntent(`deploy ${repo} to ${node}`);
return json({
status: 'queued',
deploy: {
repo, node: node || 'octavia', branch: branch || 'main', type: deployType,
target_ip: target.ip, target_ssh: target.ssh,
services: target.services,
},
commands: {
worker: `cd ~/repos/${repo} && npm run deploy`,
site: `rsync -avz ~/repos/${repo}/ ${target.ssh}:/var/www/${repo}/`,
docker: `ssh ${target.ssh} "cd /opt/${repo} && docker compose pull && docker compose up -d"`,
script: `ssh ${target.ssh} "cd ~/repos/${repo} && git pull && ./deploy.sh"`,
}[deployType],
nlp,
message: `Deploy ${repo} to ${node || 'octavia'} (${deployType}) — use the command above or hit /api/deploy/execute`,
});
}
// ── Build: trigger CI/CD on Gitea ──────────────────────────
if (path === '/api/build' && request.method === 'POST') {
const body = await request.json();
const { repo, workflow, branch } = body;
if (!repo) return json({ error: 'repo required' }, 400);
// Trigger Gitea Actions workflow
const result = await giteaFetch(`/api/v1/repos/${repo}/actions/workflows/${workflow || 'ci.yml'}/dispatches`, env, {
method: 'POST',
body: JSON.stringify({ ref: branch || 'main' }),
});
return json({
status: result ? 'triggered' : 'failed',
repo, workflow: workflow || 'ci.yml', branch: branch || 'main',
message: result ? `Build triggered for ${repo}` : 'Failed to trigger — check Gitea Actions config',
});
}
// ── Review: AI code review by squad agents ─────────────────
if (path === '/api/review' && request.method === 'POST') {
const body = await request.json();
const { repo, pr, diff } = body;
if (!repo && !diff) return json({ error: 'repo+pr or diff required' }, 400);
let diffText = diff;
if (!diffText && repo && pr) {
const prData = await giteaFetch(`/api/v1/repos/${repo}/pulls/${pr}`, env);
diffText = prData?.diff_url ? await (await fetch(prData.diff_url)).text() : null;
}
if (!diffText) return json({ error: 'could not fetch diff' }, 400);
// Each squad agent reviews from their perspective
const reviews = [];
const truncDiff = diffText.slice(0, 2000);
for (const agent of SQUAD.slice(0, 4)) { // Top 4 agents for speed
const prompt = `${agent.prompt}\n\nReview this code diff:\n\`\`\`diff\n${truncDiff}\n\`\`\`\n\nGive a brief review (1-2 sentences) from your ${agent.role} perspective. Flag any concerns.`;
const review = await askOllama(prompt, env);
reviews.push({
agent: agent.name, emoji: agent.emoji, role: agent.role, color: agent.color,
review: review || `${agent.name} could not analyze this diff right now.`,
});
}
return json({ repo, pr, reviews, agents: reviews.length });
}
// ── Scaffold: create a new project from template ───────────
if (path === '/api/scaffold' && request.method === 'POST') {
const body = await request.json();
const { name, template, org, description } = body;
if (!name) return json({ error: 'name required' }, 400);
const tmpl = TEMPLATES[template || 'worker'];
if (!tmpl) return json({ error: `unknown template: ${template}. Options: ${Object.keys(TEMPLATES).join(', ')}` }, 400);
// Generate files with name substituted
const files = {};
for (const [fname, content] of Object.entries(tmpl.files)) {
files[fname] = content.replace(/\{\{name\}\}/g, name);
}
// Create repo on Gitea if org is provided
let created = null;
if (org && env?.ADMIN_TOKEN) {
created = await giteaFetch(`/api/v1/orgs/${org}/repos`, env, {
method: 'POST',
body: JSON.stringify({
name, description: description || `${name} — ${tmpl.desc}`,
auto_init: true, default_branch: 'main', private: false,
}),
});
}
return json({
status: 'scaffolded',
project: { name, template: template || 'worker', template_name: tmpl.name, description: tmpl.desc },
files,
gitea_repo: created ? { url: created.html_url, clone: created.clone_url } : null,
next_steps: [
created ? `git clone ${created.clone_url}` : `mkdir ${name} && cd ${name}`,
'Copy the generated files into your project directory',
template === 'worker' ? 'npm install && npm run dev' :
template === 'api' ? 'npm install && npm run dev' :
template === 'cli' ? 'npm install && npm run dev' :
template === 'agent' ? 'chmod +x agent.sh && ./agent.sh' :
'Open index.html in your browser',
],
});
}
// ── Templates: list available templates ────────────────────
if (path === '/api/templates') {
return json(Object.entries(TEMPLATES).map(([id, t]) => ({
id, name: t.name, desc: t.desc, files: Object.keys(t.files),
})));
}
// ── Fleet: deployment targets ──────────────────────────────
if (path === '/api/fleet') {
return json(Object.entries(FLEET).map(([id, n]) => ({
id, ip: n.ip, services: n.services, ssh: n.ssh, status: n.status || 'online',
})));
}
// ── Squad: list agents ─────────────────────────────────────
if (path === '/api/squad') {
return json(SQUAD.map(a => ({
name: a.name, username: a.username, role: a.role, emoji: a.emoji, color: a.color,
keywords: a.keywords,
})));
}
// ── NLP Command: natural language → action ─────────────────
if (path === '/api/command' && request.method === 'POST') {
const body = await request.json();
const nlp = parseIntent(body.command || body.message || '');
// Map intents to suggested API calls
const suggestions = nlp.intents.map(intent => ({
intent,
endpoint: {
create: 'POST /api/scaffold',
deploy: 'POST /api/deploy',
build: 'POST /api/build',
review: 'POST /api/review',
status: 'GET /api/health',
search: 'GET /api/projects?q=...',
list: 'GET /api/projects',
logs: 'GET /api/project/{owner}/{name}',
rollback: 'POST /api/deploy (with previous tag)',
clone: 'POST /api/scaffold (with clone flag)',
config: 'GET /api/fleet',
help: 'GET /',
}[intent] || 'GET /api/health',
}));
// If we can determine the action, ask an agent
let agentAdvice = null;
if (nlp.intents[0] && env?.OLLAMA_URL) {
const bestAgent = SQUAD.find(a => a.keywords.some(kw => body.command?.toLowerCase().includes(kw))) || SQUAD[0];
agentAdvice = await askOllama(
`${bestAgent.prompt}\n\nA developer said: "${body.command}"\n\nBriefly tell them what to do next (1-2 sentences). Reference specific RoadCode API endpoints or fleet nodes if relevant.`,
env
);
if (agentAdvice) agentAdvice = { agent: bestAgent.name, emoji: bestAgent.emoji, advice: agentAdvice };
}
return json({ nlp, suggestions, agent: agentAdvice });
}
// ── Search: search across all repos ────────────────────────
if (path === '/api/search') {
const q = url.searchParams.get('q');
if (!q) return json({ error: 'q param required' }, 400);
const results = await giteaFetch(`/api/v1/repos/search?q=${encodeURIComponent(q)}&limit=20`, env);
if (!results) return json({ error: 'gitea unreachable' }, 502);
const data = results.data || results || [];
return json({
query: q,
results: (Array.isArray(data) ? data : []).map(r => ({
name: r.full_name, description: r.description, language: r.language,
stars: r.stars_count, updated: r.updated_at, url: r.html_url,
})),
total: results.total_count || data.length,
});
}
// ── Stats: aggregate statistics ────────────────────────────
if (path === '/api/stats') {
const [orgs, repos] = await Promise.all([
giteaFetch('/api/v1/orgs?limit=50', env),
giteaFetch('/api/v1/repos/search?limit=1', env),
]);
return json({
total_repos: repos?.total_count || 0,
total_orgs: Array.isArray(orgs) ? orgs.length : 0,
fleet_nodes: Object.keys(FLEET).length,
fleet_online: Object.values(FLEET).filter(n => n.status !== 'offline').length,
squad_agents: SQUAD.length,
templates: Object.keys(TEMPLATES).length,
version: VERSION,
});
}
// ═══ Webhook Handler (from Squad v2) ═══════════════════════
if (path === '/webhook' && request.method === 'POST') {
const payload = await request.json();
const event = request.headers.get('X-Gitea-Event') || request.headers.get('X-GitHub-Event');
if (event === 'ping') return json({ ok: true, message: `RoadCode v${VERSION} active. Pave Tomorrow.` });
const validEvents = ['issues', 'issue_comment', 'pull_request', 'pull_request_comment'];
if (!validEvents.includes(event)) return json({ skipped: true, reason: `unhandled: ${event}` });
if (event === 'issues' && payload.action !== 'opened') return json({ skipped: true });
if (event === 'issue_comment' && payload.action !== 'created') return json({ skipped: true });
if (event === 'pull_request' && payload.action !== 'opened') return json({ skipped: true });
const author = payload.comment?.user?.login || payload.sender?.login;
if (SQUAD.some(a => a.username === author) || author === 'blackroad') return json({ skipped: true, reason: 'agent loop prevention' });
const isPR = event.startsWith('pull_request');
const issue = isPR ? payload.pull_request : payload.issue;
const repo = payload.repository?.full_name;
const issueNum = issue?.number;
const title = issue?.title || '';
const isComment = event.includes('comment');
const body = isComment ? (payload.comment?.body || '') : (issue?.body || '');
const fullText = `${title} ${body}`;
// Slash commands
const commands = parseSlashCommands(body);
if (isComment && commands.length > 0) {
for (const c of commands) {
if (c.cmd === 'deploy' && c.args) {
const nlp = parseIntent(`deploy ${c.args} from ${repo}`);
if (env?.ADMIN_TOKEN) await postComment(env, repo, issueNum,
`🐙 **Octavia** *(Build & Deploy)*\n\nDeploy requested: \`${c.args}\`\nParsed intent: ${JSON.stringify(nlp.intents)}\n\nUse \`POST /api/deploy\` with \`{"repo":"${repo}","node":"${nlp.entities.node || 'octavia'}"}\`\n\n---\n*RoadCode v${VERSION}*`,
env.ADMIN_TOKEN);
} else if (c.cmd === 'review') {
if (env?.ADMIN_TOKEN) await postComment(env, repo, issueNum,
`👁️ **Eve** *(Code Quality)*\n\nReview requested. Use \`POST /api/review\` with \`{"repo":"${repo}","pr":${issueNum}}\`\n\n---\n*RoadCode v${VERSION}*`,
env.ADMIN_TOKEN);
} else if (c.cmd === 'status') {
const stats = { fleet: Object.keys(FLEET).length, online: Object.values(FLEET).filter(n => !n.status).length, agents: SQUAD.length };
if (env?.ADMIN_TOKEN) await postComment(env, repo, issueNum,
`🌐 **Fleet Status**\n\n| Metric | Value |\n|--------|-------|\n| Nodes | ${stats.fleet} (${stats.online} online) |\n| Squad | ${stats.agents} agents |\n| Version | v${VERSION} |\n\n---\n*RoadCode v${VERSION}*`,
env.ADMIN_TOKEN);
} else if (c.cmd === 'squad') {
if (env?.ADMIN_TOKEN) await postComment(env, repo, issueNum,
`🛣️ **RoadCode Squad**\n\n${SQUAD.map(a => `${a.emoji} **${a.name}** (@${a.username}) — ${a.role}`).join('\n')}\n\n---\n*RoadCode v${VERSION}*`,
env.ADMIN_TOKEN);
} else if (c.cmd === 'help') {
if (env?.ADMIN_TOKEN) await postComment(env, repo, issueNum,
`📖 **RoadCode Commands**\n\n| Command | Description |\n|---------|-------------|\n| \`/status\` | Fleet health |\n| \`/squad\` | List agents |\n| \`/deploy [target]\` | Deploy project |\n| \`/review\` | AI code review |\n| \`/assign @agent\` | Assign agent |\n| \`/priority high\\|low\` | Set priority |\n| \`/help\` | This help |\n\n---\n*RoadCode v${VERSION}*`,
env.ADMIN_TOKEN);
}
}
return json({ ok: true, commands: commands.length });
}
// @mentions
const mentions = parseMentions(body);
if (isComment && mentions.length > 0) {
for (const agent of mentions) {
const token = env?.[`${agent.name.toUpperCase()}_TOKEN`] || env?.ADMIN_TOKEN;
if (!token) continue;
const response = await askOllama(`${agent.prompt}\n\nContext: ${fullText.slice(0, 500)}\n\nRespond briefly.`, env);
await postComment(env, repo, issueNum,
`${agent.emoji} **${agent.name}** *(${agent.role})*\n\n${response || 'Standing by.'}\n\n---\n*RoadCode v${VERSION}*`,
token);
}
return json({ ok: true, mentions: mentions.map(a => a.name) });
}
// New issue/PR — auto-label + top agent response
if (!isComment && env?.ADMIN_TOKEN) {
// Auto-label
const labels = [];
const lower = fullText.toLowerCase();
if (/bug|fix|broken|error/.test(lower)) labels.push('bug');
if (/feature|add|new|implement/.test(lower)) labels.push('feature');
if (/security|vuln|ssh|firewall/.test(lower)) labels.push('security');
if (/deploy|infra|dns|tunnel/.test(lower)) labels.push('infrastructure');
if (/doc|readme/.test(lower)) labels.push('documentation');
if (/perf|slow|latency/.test(lower)) labels.push('performance');
// Score and respond with top agent
const scored = SQUAD.map(a => ({ ...a, score: scoreRelevance(a, fullText) })).sort((a, b) => b.score - a.score);
const top = scored[0];
const response = await askOllama(`${top.prompt}\n\nNew ${isPR ? 'pull request' : 'issue'}: "${title}"\n"${body.slice(0, 300)}"\nRepo: ${repo}\n\nRespond briefly.`, env);
await postComment(env, repo, issueNum,
`${top.emoji} **${top.name}** *(${top.role})*\n\n${response || 'Acknowledged. I\'ll track this.'}\n\n---\n*Auto-assigned by RoadCode v${VERSION}*`,
env.ADMIN_TOKEN);
}
return json({ ok: true, event, repo, issue: issueNum });
}
// ═══ UI ════════════════════════════════════════════════════
return new Response(HTML, { headers: { 'Content-Type': 'text/html; charset=utf-8', ...CORS } });
}
};
// ═══ HTML UI ══════════════════════════════════════════════════
const HTML = `
RoadCode — Coding Orchestration Platform
RoadCode
v${VERSION}
Loading...
Loading projects...
`;