diff --git a/src/lib/agent-settings.ts b/src/lib/agent-settings.ts new file mode 100644 index 0000000..d480785 --- /dev/null +++ b/src/lib/agent-settings.ts @@ -0,0 +1,88 @@ +import type { AgentSettings } from "../types"; + +const DEFAULT_SETTINGS: AgentSettings = { + thinking: { + enabled: true, + effort: "medium", + keep: "all", + }, + loop_control: { + max_retries_per_step: 3, + reserved_context_size: 50000, + }, + background: { + keep_alive_on_exit: false, + }, + permission: { rules: [] }, + hooks: [], +}; + +function asRecord(value: unknown): Record { + if (value && typeof value === "object" && !Array.isArray(value)) { + return value as Record; + } + return {}; +} + +function getSection(rawOther: unknown, key: string): T | undefined { + const root = asRecord(rawOther); + const section = root[key]; + if (section === undefined || section === null) return undefined; + return section as T; +} + +export function getAgentSettings(rawOther: unknown): AgentSettings { + return { + thinking: { + ...DEFAULT_SETTINGS.thinking, + ...getSection(rawOther, "thinking"), + }, + loop_control: { + ...DEFAULT_SETTINGS.loop_control, + ...getSection(rawOther, "loop_control"), + }, + background: { + ...DEFAULT_SETTINGS.background, + ...getSection(rawOther, "background"), + }, + permission: { + rules: + getSection(rawOther, "permission")?.rules ?? + [], + }, + hooks: getSection(rawOther, "hooks") ?? [], + }; +} + +export function setAgentSettings( + rawOther: unknown, + patch: Partial +): unknown { + const root = { ...asRecord(rawOther) }; + const current = getAgentSettings(rawOther); + const next: AgentSettings = { + thinking: { ...current.thinking, ...patch.thinking }, + loop_control: { ...current.loop_control, ...patch.loop_control }, + background: { ...current.background, ...patch.background }, + permission: { + rules: patch.permission?.rules ?? current.permission?.rules ?? [], + }, + hooks: patch.hooks ?? current.hooks ?? [], + }; + + if (next.thinking) root.thinking = next.thinking; + if (next.loop_control) root.loop_control = next.loop_control; + if (next.background) root.background = next.background; + if (next.permission?.rules && next.permission.rules.length > 0) { + root.permission = next.permission; + } else { + delete root.permission; + } + if (next.hooks && next.hooks.length > 0) { + root.hooks = next.hooks; + } else { + delete root.hooks; + } + + return root; +}