Add NexusAI: universal MCP service (TTS/STT/image/video/music/web-search)

Monorepo-lite with shared @nexusai/core and @nexusai/mcp-server (stdio).
Provider-agnostic tools with explicit provider selection; NordRouter adapter
(media generate/poll/download, estimate, upload, models) and search via
perplexity/sonar. Local STT via faster-whisper uv sidecar. SQLite journal of
every generation for usage stats and future admin. 10 MCP tools.
This commit is contained in:
OpenCode
2026-08-17 17:06:47 +07:00
parent 82087be1b3
commit 02fc536e85
32 changed files with 3861 additions and 0 deletions
@@ -0,0 +1,42 @@
/**
* MCP servers communicate over stdio, so ALL logs must go to stderr.
* Never write logs to stdout — it corrupts the JSON-RPC stream.
*/
type Level = 'debug' | 'info' | 'warn' | 'error';
const LEVELS: Record<Level, number> = { debug: 10, info: 20, warn: 30, error: 40 };
function currentThreshold(): number {
const env = (process.env.NEXUS_LOG_LEVEL || 'info').toLowerCase() as Level;
return LEVELS[env] ?? LEVELS.info;
}
function emit(level: Level, scope: string, message: string, extra?: unknown): void {
if (LEVELS[level] < currentThreshold()) return;
const ts = new Date().toISOString();
let line = `[${ts}] ${level.toUpperCase()} (${scope}) ${message}`;
if (extra !== undefined) {
try {
line += ` ${typeof extra === 'string' ? extra : JSON.stringify(extra)}`;
} catch {
line += ' [unserializable extra]';
}
}
process.stderr.write(line + '\n');
}
export interface Logger {
debug(message: string, extra?: unknown): void;
info(message: string, extra?: unknown): void;
warn(message: string, extra?: unknown): void;
error(message: string, extra?: unknown): void;
}
export function createLogger(scope: string): Logger {
return {
debug: (m, e) => emit('debug', scope, m, e),
info: (m, e) => emit('info', scope, m, e),
warn: (m, e) => emit('warn', scope, m, e),
error: (m, e) => emit('error', scope, m, e),
};
}