src/server/agent-config.ts
Rama main · réplica de lectura del repositorio original.
// Agent config READ path (shared across users), as its own leaf module.
//
// Why it isn't in claude.ts: the security runtime reads a flag from it (`allowUntrustedReplies`, see
// `mayReplyTo`), and claude.ts imports the runtime — plus the whole engine/skills/sessions graph. A leaf
// that only touches fs + paths keeps that dependency one-way and cheap. The WRITE path stays in claude.ts
// (it also has to tell data-sync, which pulls the Agent SDK).
import { existsSync, readFileSync } from 'node:fs';
import { dataPath } from './paths.ts';
import type { AgentSettings as AgentConfig } from './shraga-config.ts';
export const CONFIG_PATH = dataPath('agent-config.json');
export const DEFAULT_CONFIG: AgentConfig = {
/** ToolSearch loads deferred MCP tools; without it, permission prompts / tool graph can block Meta Ads tools. */
allowedTools: ['Read', 'Edit', 'Bash', 'WebSearch', 'Glob', 'LS', 'ToolSearch'],
permissionMode: 'acceptEdits',
maxTurns: 15,
// Defaults are what a fresh self-hosted install runs before anyone touches the UI, so they favour
// cost/latency over ceiling. Both are overridable per-deployment via agent-config.json and per-send
// via directives — an operator who wants a bigger model sets it once; every operator pays for a default.
model: 'claude-sonnet-5',
effort: 'low',
// `allowUntrustedReplies` is deliberately absent: undefined = off, so a fresh install never auto-replies
// to an unverified sender, and an owner has to turn it on explicitly.
};
export function getAgentConfig(): AgentConfig {
// agent-config.json (UI-writable, git-tracked) is the single source of truth for agent settings.
let config = { ...DEFAULT_CONFIG };
if (existsSync(CONFIG_PATH)) {
try { Object.assign(config, JSON.parse(readFileSync(CONFIG_PATH, 'utf-8'))); } catch (e) { console.warn('[claude] failed to parse agent-config.json:', e); }
}
return config;
}