feat: add log-level system to suppress noisy fallback debug output

Replace console.debug/log/warn calls in model router, retry, and daemon
startup with a structured logger that respects a configurable log_level.
Default level is 'info', suppressing verbose fallback debug messages in
the TUI while keeping them available via config when needed.

- Add src/logger.ts with debug/info/warn/error/silent levels
- Wire log_level into config schema (default: 'info')
- Initialize log level in both daemon and TUI startup paths
- Convert all console.debug in router.ts and retry.ts to logger.debug
- Convert console.log/warn in daemon/models.ts to logger.info/warn
This commit is contained in:
William Valentin
2026-02-09 21:23:07 -08:00
parent 94946eb7a8
commit 35f4cab0dc
8 changed files with 79 additions and 16 deletions
+4
View File
@@ -9,6 +9,7 @@ import type { AudioTranscriptionConfig } from '../models/media.js';
import type { ToolRegistry, ToolExecutor, BrowserManager } from '../tools/index.js';
import type { AgentConfigRegistry, AgentRouter } from '../agents/index.js';
import type { SandboxManager } from '../sandbox/index.js';
import { setLogLevel } from '../logger.js';
// ── Daemon Modules ──
import { Lifecycle } from './lifecycle.js';
@@ -51,6 +52,9 @@ export interface DaemonContext {
}
export async function startDaemon(config: Config): Promise<DaemonContext> {
// ── Log level ──
setLogLevel(config.log_level);
const lifecycle = new Lifecycle();
// ── Data & Sessions ──
+6 -5
View File
@@ -1,6 +1,7 @@
import type { Config, ModelConfig } from '../config/index.js';
import { AnthropicClient, OpenAIClient, OllamaClient, LlamaCppClient, GeminiClient, BedrockClient, GitHubModelsClient, ModelRouter, DEFAULT_RETRY_CONFIG } from '../models/index.js';
import type { ModelClient, RetryConfig, ModelTier } from '../models/index.js';
import { logger } from '../logger.js';
/**
* Create a ModelClient from a provider config entry.
@@ -166,7 +167,7 @@ export function createModelRouter(config: Config): ModelRouter {
// Named provider from local_providers map
fallbackChain.push(createClientFromConfig(models.local_providers[providerName]));
} else {
console.warn(`Fallback chain entry "${providerName}" not found — skipping`);
logger.warn(`Fallback chain entry "${providerName}" not found — skipping`);
}
}
@@ -211,13 +212,13 @@ export function createModelRouter(config: Config): ModelRouter {
if (tierFallbacks.size > 0) {
const tierNames = Array.from(tierFallbacks.keys()).join(', ');
console.log(`Per-tier fallbacks configured for: ${tierNames}`);
logger.info(`Per-tier fallbacks configured for: ${tierNames}`);
}
if (autoFallbackTiers.length > 0) {
console.log(`Auto same-model fallback (via GitHub Models) for: ${autoFallbackTiers.join(', ')}`);
logger.info(`Auto same-model fallback (via GitHub Models) for: ${autoFallbackTiers.join(', ')}`);
}
console.log(`Model router: default=${models.default.provider}/${models.default.model}, ` +
logger.info(`Model router: default=${models.default.provider}/${models.default.model}, ` +
`fallback=[${models.fallback_chain.join(', ')}]`);
// Build retry config if enabled
@@ -230,7 +231,7 @@ export function createModelRouter(config: Config): ModelRouter {
} : undefined;
if (retryConfig) {
console.log(`Retry policy: max_retries=${retryConfig.maxRetries}, initial_delay=${retryConfig.initialDelayMs}ms`);
logger.info(`Retry policy: max_retries=${retryConfig.maxRetries}, initial_delay=${retryConfig.initialDelayMs}ms`);
}
return new ModelRouter({