Files
boocode/apps/server/src/config.ts
indifferentketchup e423579e99 v2.0.5: FAST_MODEL routing + tool-use summaries + Qwen dispatch + Arena
Source-level recon of QwenLM/qwen-code (Apache-2.0) informed 4 lifts:

1. FAST_MODEL config: optional env var routes cheap LLM calls (titles,
   summaries, labeling) to a smaller model on llama-swap. auto_name.ts
   uses ctx.config.FAST_MODEL ?? session.model. Set FAST_MODEL=nemotron-
   nano-4b to avoid loading the 35B model for 20-token title generation.

2. Tool-use summaries (services/inference/tool-summaries.ts): utility
   that generates "git-commit-subject-style" labels for tool batches via
   a fast-model LLM call. System prompt + truncation logic ported from
   Qwen Code's toolUseSummary.ts. Exported via @boocode/server/inference
   for BooCoder's dispatcher to call after task completion.

3. Qwen as dispatchable agent: added to agent-probe.ts KNOWN_AGENTS.
   PTY dispatch builds: qwen -p "<task>" --output-format stream-json
   (NDJSON structured events over stdout). Env: OPENAI_BASE_URL +
   OPENAI_API_KEY points Qwen Code at llama-swap. execution_path CHECK
   constraint extended with 'qwen'.

4. Arena routes (routes/arena.ts): POST /api/arena dispatches the same
   task to N contestants (2-5, each with different agent/model), each
   getting its own task row linked by arena_id UUID. GET /api/arena/:id
   shows all contestants. POST /api/arena/:id/select/:task_id marks
   winner. Schema: arena_id column added to tasks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 14:05:59 +00:00

45 lines
1.9 KiB
TypeScript

import { z } from 'zod';
const ConfigSchema = z.object({
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
PORT: z.coerce.number().int().positive().default(3000),
HOST: z.string().default('0.0.0.0'),
DATABASE_URL: z.string().url(),
LLAMA_SWAP_URL: z.string().url(),
PROJECT_ROOT_WHITELIST: z.string().default('/opt'),
BOOTSTRAP_ROOT: z.string().default('/opt/projects'),
DEFAULT_MODEL: z.string().default('qwen3.6-35b-a3b-mxfp4'),
LOG_LEVEL: z.string().default('info'),
// v1.11.8: SearXNG JSON endpoint for web_search / web_fetch tools.
// Defaults to the internal Tailscale Fathom URL (bypasses Authelia).
// The public search.indifferentketchup.com URL would 302 to auth and
// is unusable from the server context — keep the internal one.
SEARXNG_URL: z.string().url().default('http://100.114.205.53:8888'),
GITEA_BASE_URL: z.string().url().default('https://git.indifferentketchup.com'),
GITEA_USER: z.string().default('indifferentketchup'),
GITEA_TOKEN: z.string().optional(),
GITEA_SSH_HOST: z.string().default('100.114.205.53:2222'),
// v1.15.0-mcp-multi: path to the MCP config JSON file. Default /data/mcp.json
// (bind-mounted alongside AGENTS.md). File missing = no MCP (opt-in).
MCP_CONFIG_PATH: z.string().optional(),
// v2.0.5: cheaper model for titles, summaries, labeling. Falls back to
// session model (auto_name) or DEFAULT_MODEL when unset.
FAST_MODEL: z.string().optional(),
});
export type Config = z.infer<typeof ConfigSchema>;
let cached: Config | null = null;
export function loadConfig(): Config {
if (cached) return cached;
const parsed = ConfigSchema.safeParse(process.env);
if (!parsed.success) {
console.error('Invalid environment configuration:');
console.error(parsed.error.flatten().fieldErrors);
process.exit(1);
}
cached = parsed.data;
return cached;
}