4-package monorepo: - @tokenvault/core: Fastify 5.x proxy server, 7-stage pipeline, 3 provider adapters (Anthropic, OpenAI, Ollama), PostgreSQL ticket system, cost calculator with real provider pricing - @tokenvault/mcp: MCP server (stdio) with tv_ticket, tv_cost, tv_health tools for IDE integration - @tokenvault/client: TypeScript SDK with createTokenVaultClient() - @tokenvault/dashboard: Single-file HTML dashboard with MAGATAMA CI style (indigo #6366f1), bilingual DE+EN, 4 tabs OpenAI-compatible proxy at /v1/chat/completions — drop-in replacement. Every LLM request becomes a trackable ticket (TV-00001).
52 lines
1.5 KiB
TypeScript
52 lines
1.5 KiB
TypeScript
import Fastify from 'fastify';
|
|
import fastifyStatic from '@fastify/static';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { dirname, join } from 'node:path';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(__filename);
|
|
|
|
const PORT = parseInt(process.env['PORT'] ?? '3301', 10);
|
|
const CORE_URL = process.env['TOKENVAULT_CORE_URL'] ?? 'http://localhost:3300';
|
|
|
|
const app = Fastify({ logger: false });
|
|
|
|
// Serve static dashboard HTML
|
|
await app.register(fastifyStatic, {
|
|
root: join(__dirname, '..', 'public'),
|
|
prefix: '/',
|
|
});
|
|
|
|
// Proxy API requests to core
|
|
app.get('/api/health', async () => {
|
|
const res = await fetch(`${CORE_URL}/health`);
|
|
return res.json();
|
|
});
|
|
|
|
app.get('/api/tickets', async (req) => {
|
|
const qs = new URL(req.url, 'http://localhost').search;
|
|
const res = await fetch(`${CORE_URL}/v1/tickets${qs}`);
|
|
return res.json();
|
|
});
|
|
|
|
app.get('/api/tickets/stats', async (req) => {
|
|
const qs = new URL(req.url, 'http://localhost').search;
|
|
const res = await fetch(`${CORE_URL}/v1/tickets/stats${qs}`);
|
|
return res.json();
|
|
});
|
|
|
|
app.get('/api/cost', async (req) => {
|
|
const qs = new URL(req.url, 'http://localhost').search;
|
|
const res = await fetch(`${CORE_URL}/v1/cost${qs}`);
|
|
return res.json();
|
|
});
|
|
|
|
app.get('/api/cost/breakdown', async (req) => {
|
|
const qs = new URL(req.url, 'http://localhost').search;
|
|
const res = await fetch(`${CORE_URL}/v1/cost/breakdown${qs}`);
|
|
return res.json();
|
|
});
|
|
|
|
await app.listen({ port: PORT, host: '0.0.0.0' });
|
|
console.log(`TokenVault Dashboard running on http://localhost:${PORT}`);
|