Files
stack/apps/orchestrator/src/config/orchestrator.config.ts
Jason Woltje af299abdaf
All checks were successful
ci/woodpecker/push/infra Pipeline was successful
ci/woodpecker/push/orchestrator Pipeline was successful
ci/woodpecker/push/api Pipeline was successful
ci/woodpecker/push/web Pipeline was successful
debug(auth): log session cookie source
2026-02-18 21:36:01 -06:00

97 lines
3.7 KiB
TypeScript

import { registerAs } from "@nestjs/config";
const normalizeAiProvider = (): "ollama" | "claude" | "openai" => {
const provider = process.env.AI_PROVIDER?.trim().toLowerCase();
if (!provider) {
return "ollama";
}
if (provider !== "ollama" && provider !== "claude" && provider !== "openai") {
return "ollama";
}
return provider;
};
const parseValkeyUrl = (url: string): { host?: string; port?: number; password?: string } => {
try {
const parsed = new URL(url);
const port = parsed.port ? parseInt(parsed.port, 10) : undefined;
return {
host: parsed.hostname || undefined,
port: Number.isNaN(port) ? undefined : port,
password: parsed.password ? decodeURIComponent(parsed.password) : undefined,
};
} catch {
return {};
}
};
export const orchestratorConfig = registerAs("orchestrator", () => {
const valkeyUrl = process.env.VALKEY_URL ?? "redis://localhost:6379";
const parsedValkeyUrl = parseValkeyUrl(valkeyUrl);
return {
host: process.env.HOST ?? process.env.BIND_ADDRESS ?? "127.0.0.1",
port: parseInt(process.env.ORCHESTRATOR_PORT ?? "3001", 10),
valkey: {
host: process.env.VALKEY_HOST ?? parsedValkeyUrl.host ?? "localhost",
port: parseInt(process.env.VALKEY_PORT ?? String(parsedValkeyUrl.port ?? 6379), 10),
password: process.env.VALKEY_PASSWORD ?? parsedValkeyUrl.password,
url: valkeyUrl,
connectTimeout: parseInt(process.env.VALKEY_CONNECT_TIMEOUT_MS ?? "5000", 10),
commandTimeout: parseInt(process.env.VALKEY_COMMAND_TIMEOUT_MS ?? "3000", 10),
},
claude: {
apiKey: process.env.CLAUDE_API_KEY,
},
aiProvider: normalizeAiProvider(),
docker: {
socketPath: process.env.DOCKER_SOCKET ?? "/var/run/docker.sock",
},
git: {
userName: process.env.GIT_USER_NAME ?? "Mosaic Orchestrator",
userEmail: process.env.GIT_USER_EMAIL ?? "orchestrator@mosaicstack.dev",
},
killswitch: {
enabled: process.env.KILLSWITCH_ENABLED === "true",
},
sandbox: {
enabled: process.env.SANDBOX_ENABLED !== "false",
defaultImage: process.env.SANDBOX_DEFAULT_IMAGE ?? "node:20-alpine",
defaultMemoryMB: parseInt(process.env.SANDBOX_DEFAULT_MEMORY_MB ?? "256", 10),
defaultCpuLimit: parseFloat(process.env.SANDBOX_DEFAULT_CPU_LIMIT ?? "1.0"),
networkMode: process.env.SANDBOX_NETWORK_MODE ?? "none",
},
coordinator: {
url: process.env.COORDINATOR_URL ?? "http://localhost:8000",
timeout: parseInt(process.env.COORDINATOR_TIMEOUT_MS ?? "30000", 10),
retries: parseInt(process.env.COORDINATOR_RETRIES ?? "3", 10),
apiKey: process.env.COORDINATOR_API_KEY,
},
yolo: {
enabled: process.env.YOLO_MODE === "true",
},
spawner: {
maxConcurrentAgents: parseInt(process.env.MAX_CONCURRENT_AGENTS ?? "2", 10),
sessionCleanupDelayMs: parseInt(process.env.SESSION_CLEANUP_DELAY_MS ?? "30000", 10),
},
queue: {
name: process.env.ORCHESTRATOR_QUEUE_NAME ?? "orchestrator-tasks",
maxRetries: parseInt(process.env.ORCHESTRATOR_QUEUE_MAX_RETRIES ?? "3", 10),
baseDelay: parseInt(process.env.ORCHESTRATOR_QUEUE_BASE_DELAY_MS ?? "1000", 10),
maxDelay: parseInt(process.env.ORCHESTRATOR_QUEUE_MAX_DELAY_MS ?? "60000", 10),
concurrency: parseInt(process.env.ORCHESTRATOR_QUEUE_CONCURRENCY ?? "1", 10),
completedRetentionCount: parseInt(process.env.QUEUE_COMPLETED_RETENTION_COUNT ?? "100", 10),
completedRetentionAgeSeconds: parseInt(
process.env.QUEUE_COMPLETED_RETENTION_AGE_S ?? "3600",
10
),
failedRetentionCount: parseInt(process.env.QUEUE_FAILED_RETENTION_COUNT ?? "1000", 10),
failedRetentionAgeSeconds: parseInt(process.env.QUEUE_FAILED_RETENTION_AGE_S ?? "86400", 10),
},
};
});