@seanhogg/builderforce-agents 2026.10.9 → 2026.10.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{audio-preflight-CvvHdoWy.js → audio-preflight-Dm9zyfJq.js} +1 -1
- package/dist/build-info.json +3 -3
- package/dist/{builderforce-BmrsVdFw.js → builderforce-2EpP2M8q.js} +3 -3
- package/dist/{builderforce-Bwyw0GJ6.js → builderforce-Cyg20uU8.js} +3 -3
- package/dist/{builderforce-onboarding-DuUfZ6oL.js → builderforce-onboarding-C89jVb-9.js} +1 -1
- package/dist/{builderforce-onboarding-Dq6VUSKZ.js → builderforce-onboarding-D5A-wEs-.js} +1 -1
- package/dist/chrome-DUBgoZpO.js +4 -0
- package/dist/{command-registry-COUcUWby.js → command-registry-CDcuHGpx.js} +1 -1
- package/dist/{command-registry-4_K-lfW5.js → command-registry-hHegQvBn.js} +1 -1
- package/dist/{completion-cli-DlvHqL86.js → completion-cli-Bqr0W4L6.js} +1 -1
- package/dist/{completion-cli-B2qcVd6q.js → completion-cli-Ch9ozmkg.js} +1 -1
- package/dist/{completion-cli-SdcQ-kQj.js → completion-cli-Ck0FTqPT.js} +1 -1
- package/dist/{completion-cli-DpFvU4Qn.js → completion-cli-Do4vXo1k.js} +1 -1
- package/dist/{doctor-completion-BSotFS6p.js → doctor-completion-BjBTLcoC.js} +1 -1
- package/dist/{doctor-completion-DVxbs-74.js → doctor-completion-Ccs-JEvV.js} +1 -1
- package/dist/{embedded-D-citLF2.js → embedded-cvG_LpfQ.js} +6 -6
- package/dist/entry.js +1 -1
- package/dist/extensionAPI.js +1 -1
- package/dist/{gateway-cli-D2Bg1Um6.js → gateway-cli-CiHNwzdS.js} +1 -1
- package/dist/{gateway-cli-DFEo8C0z.js → gateway-cli-z47dfosr.js} +1 -1
- package/dist/index.js +2 -2
- package/dist/{onboard-DfMVh1bM.js → onboard-D4uXN5Ec.js} +1 -1
- package/dist/{onboard-BVmZ4jMw.js → onboard-cB37uVxy.js} +1 -1
- package/dist/{onboard-interactive-B3-KBZbZ.js → onboard-interactive-CnXgQrpI.js} +1 -1
- package/dist/{onboard-interactive-Dc_7URYb.js → onboard-interactive-CoFFuSJT.js} +1 -1
- package/dist/{onboard-interactive-zgjmwJz-.js → onboard-interactive-gvfRcLOt.js} +1 -1
- package/dist/{onboard-interactive-DYJttZ2w.js → onboard-interactive-vwqLS6pe.js} +1 -1
- package/dist/{onboarding-CP9rrz8y.js → onboarding-B9GqKO5L.js} +2 -2
- package/dist/{onboarding-D4-HDbmU.js → onboarding-DdKW5K8Y.js} +2 -2
- package/dist/{onboarding.finalize-C2kZi7F0.js → onboarding.finalize-CcuO4Yxw.js} +1 -1
- package/dist/{onboarding.finalize-BfWXPgX7.js → onboarding.finalize-D3mTpOdc.js} +1 -1
- package/dist/plugin-sdk/{accounts-Cy3WCbWg.js → accounts-BwreSNAR.js} +1 -1
- package/dist/plugin-sdk/{active-listener-DVWVNlT9.js → active-listener-DpQ7aGYd.js} +1 -1
- package/dist/plugin-sdk/{agent-scope-DgKN27hJ.js → agent-scope-BQByW0cD.js} +1 -1
- package/dist/plugin-sdk/{api-key-rotation-ftXf7mBZ.js → api-key-rotation-7YdImWrh.js} +1 -1
- package/dist/plugin-sdk/{audio-preflight-CfTmmeS-.js → audio-preflight-EbkaATDO.js} +1 -1
- package/dist/plugin-sdk/{auth-json-BrNBg87n.js → auth-json-DK6qod1_.js} +1 -1
- package/dist/plugin-sdk/{bindings-CH-YLOLC.js → bindings-CDEzl4kl.js} +1 -1
- package/dist/plugin-sdk/{channel-web-B6rg0Rbf.js → channel-web-D2KuONp0.js} +1 -1
- package/dist/plugin-sdk/{chrome-CuXP-hes.js → chrome-SOXFIkUM.js} +1 -1
- package/dist/plugin-sdk/{chunk-C94IAOuf.js → chunk-cW0POl22.js} +1 -1
- package/dist/plugin-sdk/{command-format-B3XMq_73.js → command-format-CAX9XFjI.js} +1 -1
- package/dist/plugin-sdk/{common-n0l_XN-S.js → common-BxEWhN2X.js} +1 -1
- package/dist/plugin-sdk/{config-DsXZsCkJ.js → config-v1EU9Ll8.js} +2 -2
- package/dist/plugin-sdk/{fetch-B-GxSYRO.js → fetch-DH0Y8iyO.js} +1 -1
- package/dist/plugin-sdk/index.js +1 -1
- package/dist/plugin-sdk/{login-_my8QwPP.js → login-d1zBgykF.js} +1 -1
- package/dist/plugin-sdk/{login-qr-BaePtXuG.js → login-qr-B6exvQnN.js} +1 -1
- package/dist/plugin-sdk/{manager-BsC-4ymy.js → manager-BH_bmGds.js} +1 -1
- package/dist/plugin-sdk/{markdown-tables-BUfhHgfs.js → markdown-tables-Epim9b-0.js} +1 -1
- package/dist/plugin-sdk/{message-channel-CuZ2xOAM.js → message-channel-sBPQc_-T.js} +1 -1
- package/dist/plugin-sdk/{model-catalog-yuiXVcmw.js → model-catalog-cXsza5GU.js} +1 -1
- package/dist/plugin-sdk/{model-selection-BtgvnqB5.js → model-selection-K82MAGlL.js} +1 -1
- package/dist/plugin-sdk/{outbound-D_attiyO.js → outbound-Chn_H1O7.js} +1 -1
- package/dist/plugin-sdk/{plugins-BdkC9v5E.js → plugins-CaUOZBVb.js} +1 -1
- package/dist/plugin-sdk/{pw-ai-A7Rathx6.js → pw-ai-BIiJF7ZD.js} +1 -1
- package/dist/plugin-sdk/{qmd-manager-Dxn0jCpE.js → qmd-manager-BRe5fGZw.js} +1 -1
- package/dist/plugin-sdk/{registry-CZHRcH-q.js → registry-DJq2Cvo9.js} +1 -1
- package/dist/plugin-sdk/{render-CuA_WRX5.js → render-BUCRXPIk.js} +1 -1
- package/dist/plugin-sdk/{replies-DmLfO-pg.js → replies-Cz5OD3qN.js} +1 -1
- package/dist/plugin-sdk/{reply-3-ne-N_7.js → reply-D5Uk7pUv.js} +9 -9
- package/dist/plugin-sdk/{reply-prefix-w7kAvH11.js → reply-prefix-CCymsmsP.js} +1 -1
- package/dist/plugin-sdk/{resolve-route-0sbvl4ZN.js → resolve-route-DN1J7Wyc.js} +1 -1
- package/dist/plugin-sdk/{runner-4UfrAQnx.js → runner-CYkuO7Fh.js} +4 -4
- package/dist/plugin-sdk/{session-BB-yfDWx.js → session-D5jHDo78.js} +1 -1
- package/dist/plugin-sdk/{sqlite-JjFgDV-H.js → sqlite-BlMLqMl8.js} +1 -1
- package/dist/plugin-sdk/{subsystem-D0Ril4rt.js → subsystem-COTa5Ly_.js} +1 -1
- package/dist/plugin-sdk/{tool-images-WRTP95FT.js → tool-images-DSpchb4x.js} +1 -1
- package/dist/plugin-sdk/{tool-loop-detection-sC_rhJfb.js → tool-loop-detection-BP6u-mbh.js} +1 -1
- package/dist/plugin-sdk/web-BbganhKi.js +1 -0
- package/dist/plugin-sdk/{whatsapp-actions-ThxQ5niy.js → whatsapp-actions-CZUqxmP1.js} +1 -1
- package/dist/{program-2w7Ue902.js → program-BgDciyOQ.js} +2 -2
- package/dist/{program-context-BCwL3wlM.js → program-context-CpxTJP1m.js} +1 -1
- package/dist/{prompt-select-styled-Dd5swW2b.js → prompt-select-styled-Bu7WPMzB.js} +1 -1
- package/dist/{prompt-select-styled-hB_nLOn1.js → prompt-select-styled-Qb0DubNy.js} +1 -1
- package/dist/{pw-ai-DaxMmaVL.js → pw-ai-D8HJAvv-.js} +1 -1
- package/dist/{register.maintenance-BELfCO_C.js → register.maintenance-CPnm6L-m.js} +1 -1
- package/dist/{register.maintenance-DukWFS_D.js → register.maintenance-D8WmeEaD.js} +1 -1
- package/dist/{register.onboard-Dt7rzAq-.js → register.onboard-BoUicPRh.js} +1 -1
- package/dist/{register.onboard-B9DMNfHE.js → register.onboard-DMfqe2nX.js} +1 -1
- package/dist/{register.setup-CSF-2ImP.js → register.setup-BK6OEvY3.js} +1 -1
- package/dist/{register.setup-BRRVPrx7.js → register.setup-CtcAR3JR.js} +1 -1
- package/dist/{register.subclis-4eDV9jKH.js → register.subclis-Dl6jPPsc.js} +1 -1
- package/dist/{register.subclis-Cr9DoYcv.js → register.subclis-EScCVgbV.js} +1 -1
- package/dist/{run-main-DLcDEJgv.js → run-main-C3lmcvyV.js} +1 -1
- package/dist/{runner-COldX-El.js → runner-CviGu3Nk.js} +3 -3
- package/dist/{tui-DylWbrDx.js → tui-D2sTsa4p.js} +1 -1
- package/dist/{tui-BwWMByVp.js → tui-DY2oYbxk.js} +1 -1
- package/dist/{tui-cli-C_TTgabr.js → tui-cli-GW-qybY6.js} +1 -1
- package/dist/{tui-cli-Bh1V8-w9.js → tui-cli-wn3DmvUG.js} +1 -1
- package/dist/{update-cli-CA3LuuJ7.js → update-cli-CN0oxZ_A.js} +1 -1
- package/dist/{update-cli-DUrUIrYQ.js → update-cli-K5dGZmg8.js} +1 -1
- package/dist/{web-BQPd6gQJ.js → web-DONGrYXq.js} +1 -1
- package/package.json +1 -1
- package/dist/chrome-Brg9KsB9.js +0 -4
- package/dist/plugin-sdk/web-CThgoHQp.js +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{l as normalizeAgentId,n as DEFAULT_AGENT_ID}from"./session-key-5J69DULS.js";import{C as isPlainObject$2,j as resolveUserPath,k as resolveConfigDir,o as normalizeChatChannelId,t as CHANNEL_IDS,w as isRecord}from"./registry-CZHRcH-q.js";import{n as resolveConfigPath,r as resolveDefaultConfigCandidates,s as resolveStateDir,u as resolveRequiredHomeDir}from"./paths-Cb8zTlyG.js";import{At as shouldDeferShellEnvFallback,Ot as loadShellEnvFallback,bt as currentAnthropicModelId,ht as DEFAULT_CONTEXT_TOKENS,jt as shouldEnableShellEnvFallback,kt as resolveShellEnvFallbackTimeoutMs,u as parseModelRef,vt as ANTHROPIC_FAMILIES}from"./model-selection-BtgvnqB5.js";import{c as resolveDefaultAgentId,s as resolveAgentWorkspaceDir}from"./agent-scope-DgKN27hJ.js";import{createRequire}from"node:module";import path from"node:path";import fs from"node:fs";import os from"node:os";import crypto from"node:crypto";import{fileURLToPath}from"node:url";import JSON5 from"json5";import{z}from"zod";import{isDeepStrictEqual}from"node:util";import dotenv from"dotenv";import AjvPkg from"ajv";const TELEGRAM_COMMAND_NAME_PATTERN=/^[a-z0-9_]{1,32}$/;function normalizeTelegramCommandName(value){let trimmed=value.trim();return trimmed?(trimmed.startsWith(`/`)?trimmed.slice(1):trimmed).trim().toLowerCase().replace(/-/g,`_`):``}function normalizeTelegramCommandDescription(value){return value.trim()}function resolveTelegramCustomCommands(params){let entries=Array.isArray(params.commands)?params.commands:[],reserved=params.reservedCommands??new Set,checkReserved=params.checkReserved!==!1,checkDuplicates=params.checkDuplicates!==!1,seen=new Set,resolved=[],issues=[];for(let index=0;index<entries.length;index+=1){let entry=entries[index],normalized=normalizeTelegramCommandName(String(entry?.command??``));if(!normalized){issues.push({index,field:`command`,message:`Telegram custom command is missing a command name.`});continue}if(!TELEGRAM_COMMAND_NAME_PATTERN.test(normalized)){issues.push({index,field:`command`,message:`Telegram custom command "/${normalized}" is invalid (use a-z, 0-9, underscore; max 32 chars).`});continue}if(checkReserved&&reserved.has(normalized)){issues.push({index,field:`command`,message:`Telegram custom command "/${normalized}" conflicts with a native command.`});continue}if(checkDuplicates&&seen.has(normalized)){issues.push({index,field:`command`,message:`Telegram custom command "/${normalized}" is duplicated.`});continue}let description=normalizeTelegramCommandDescription(String(entry?.description??``));if(!description){issues.push({index,field:`description`,message:`Telegram custom command "/${normalized}" is missing a description.`});continue}checkDuplicates&&seen.add(normalized),resolved.push({command:normalized,description})}return{commands:resolved,issues}}function parseDurationMs(raw,opts){let trimmed=String(raw??``).trim().toLowerCase();if(!trimmed)throw Error(`invalid duration (empty)`);let m=/^(\d+(?:\.\d+)?)(ms|s|m|h|d)?$/.exec(trimmed);if(!m)throw Error(`invalid duration: ${raw}`);let value=Number(m[1]);if(!Number.isFinite(value)||value<0)throw Error(`invalid duration: ${raw}`);let unit=m[2]??opts?.defaultUnit??`ms`,multiplier=unit===`ms`?1:unit===`s`?1e3:unit===`m`?6e4:unit===`h`?36e5:864e5,ms=Math.round(value*multiplier);if(!Number.isFinite(ms))throw Error(`invalid duration: ${raw}`);return ms}const AgentModelSchema=z.union([z.string(),z.object({primary:z.string().optional(),fallbacks:z.array(z.string()).optional()}).strict()]),SHELL_METACHARS=/[;&|`$<>]/,CONTROL_CHARS=/[\r\n]/,QUOTE_CHARS=/["']/,BARE_NAME_PATTERN=/^[A-Za-z0-9._+-]+$/;function isLikelyPath(value){return value.startsWith(`.`)||value.startsWith(`~`)||value.includes(`/`)||value.includes(`\\`)?!0:/^[A-Za-z]:[\\/]/.test(value)}function isSafeExecutableValue(value){if(!value)return!1;let trimmed=value.trim();return!trimmed||trimmed.includes(`\0`)||CONTROL_CHARS.test(trimmed)||SHELL_METACHARS.test(trimmed)||QUOTE_CHARS.test(trimmed)?!1:isLikelyPath(trimmed)?!0:trimmed.startsWith(`-`)?!1:BARE_NAME_PATTERN.test(trimmed)}const AllowDenyActionSchema=z.union([z.literal(`allow`),z.literal(`deny`)]),AllowDenyChatTypeSchema=z.union([z.literal(`direct`),z.literal(`group`),z.literal(`channel`),z.literal(`dm`)]).optional();function createAllowDenyChannelRulesSchema(){return z.object({default:AllowDenyActionSchema.optional(),rules:z.array(z.object({action:AllowDenyActionSchema,match:z.object({channel:z.string().optional(),chatType:AllowDenyChatTypeSchema,keyPrefix:z.string().optional(),rawKeyPrefix:z.string().optional()}).strict().optional()}).strict()).optional()}).strict().optional()}const sensitive=z.registry(),ModelApiSchema=z.union([z.literal(`openai-completions`),z.literal(`openai-responses`),z.literal(`anthropic-messages`),z.literal(`google-generative-ai`),z.literal(`github-copilot`),z.literal(`bedrock-converse-stream`),z.literal(`ollama`),z.literal(`transformers`)]),ModelCompatSchema=z.object({supportsStore:z.boolean().optional(),supportsDeveloperRole:z.boolean().optional(),supportsReasoningEffort:z.boolean().optional(),supportsUsageInStreaming:z.boolean().optional(),supportsStrictMode:z.boolean().optional(),maxTokensField:z.union([z.literal(`max_completion_tokens`),z.literal(`max_tokens`)]).optional(),thinkingFormat:z.union([z.literal(`openai`),z.literal(`zai`),z.literal(`qwen`)]).optional(),requiresToolResultName:z.boolean().optional(),requiresAssistantAfterToolResult:z.boolean().optional(),requiresThinkingAsText:z.boolean().optional(),requiresMistralToolIds:z.boolean().optional()}).strict().optional(),ModelDefinitionSchema=z.object({id:z.string().min(1),name:z.string().min(1),api:ModelApiSchema.optional(),reasoning:z.boolean().optional(),input:z.array(z.union([z.literal(`text`),z.literal(`image`)])).optional(),cost:z.object({input:z.number().optional(),output:z.number().optional(),cacheRead:z.number().optional(),cacheWrite:z.number().optional()}).strict().optional(),contextWindow:z.number().positive().optional(),maxTokens:z.number().positive().optional(),headers:z.record(z.string(),z.string()).optional(),compat:ModelCompatSchema}).strict(),ModelProviderSchema=z.object({baseUrl:z.string().min(1),apiKey:z.string().optional().register(sensitive),auth:z.union([z.literal(`api-key`),z.literal(`aws-sdk`),z.literal(`oauth`),z.literal(`token`)]).optional(),api:ModelApiSchema.optional(),headers:z.record(z.string(),z.string()).optional(),authHeader:z.boolean().optional(),models:z.array(ModelDefinitionSchema)}).strict(),BedrockDiscoverySchema=z.object({enabled:z.boolean().optional(),region:z.string().optional(),providerFilter:z.array(z.string()).optional(),refreshInterval:z.number().int().nonnegative().optional(),defaultContextWindow:z.number().int().positive().optional(),defaultMaxTokens:z.number().int().positive().optional()}).strict().optional(),ModelsConfigSchema=z.object({mode:z.union([z.literal(`merge`),z.literal(`replace`)]).optional(),providers:z.record(z.string(),ModelProviderSchema).optional(),bedrockDiscovery:BedrockDiscoverySchema}).strict().optional(),GroupChatSchema=z.object({mentionPatterns:z.array(z.string()).optional(),historyLimit:z.number().int().positive().optional()}).strict().optional(),DmConfigSchema=z.object({historyLimit:z.number().int().min(0).optional()}).strict(),IdentitySchema=z.object({name:z.string().optional(),theme:z.string().optional(),emoji:z.string().optional(),avatar:z.string().optional()}).strict().optional(),QueueModeSchema=z.union([z.literal(`steer`),z.literal(`followup`),z.literal(`collect`),z.literal(`steer-backlog`),z.literal(`steer+backlog`),z.literal(`queue`),z.literal(`interrupt`)]),QueueDropSchema=z.union([z.literal(`old`),z.literal(`new`),z.literal(`summarize`)]),ReplyToModeSchema=z.union([z.literal(`off`),z.literal(`first`),z.literal(`all`)]),GroupPolicySchema=z.enum([`open`,`disabled`,`allowlist`]),DmPolicySchema=z.enum([`pairing`,`allowlist`,`open`,`disabled`]),BlockStreamingCoalesceSchema=z.object({minChars:z.number().int().positive().optional(),maxChars:z.number().int().positive().optional(),idleMs:z.number().int().nonnegative().optional()}).strict(),BlockStreamingChunkSchema=z.object({minChars:z.number().int().positive().optional(),maxChars:z.number().int().positive().optional(),breakPreference:z.union([z.literal(`paragraph`),z.literal(`newline`),z.literal(`sentence`)]).optional()}).strict(),MarkdownTableModeSchema=z.enum([`off`,`bullets`,`code`]),MarkdownConfigSchema=z.object({tables:MarkdownTableModeSchema.optional()}).strict().optional(),TtsProviderSchema=z.enum([`elevenlabs`,`openai`,`edge`]),TtsModeSchema=z.enum([`final`,`all`]),TtsAutoSchema=z.enum([`off`,`always`,`inbound`,`tagged`]),TtsConfigSchema=z.object({auto:TtsAutoSchema.optional(),enabled:z.boolean().optional(),mode:TtsModeSchema.optional(),provider:TtsProviderSchema.optional(),summaryModel:z.string().optional(),modelOverrides:z.object({enabled:z.boolean().optional(),allowText:z.boolean().optional(),allowProvider:z.boolean().optional(),allowVoice:z.boolean().optional(),allowModelId:z.boolean().optional(),allowVoiceSettings:z.boolean().optional(),allowNormalization:z.boolean().optional(),allowSeed:z.boolean().optional()}).strict().optional(),elevenlabs:z.object({apiKey:z.string().optional().register(sensitive),baseUrl:z.string().optional(),voiceId:z.string().optional(),modelId:z.string().optional(),seed:z.number().int().min(0).max(4294967295).optional(),applyTextNormalization:z.enum([`auto`,`on`,`off`]).optional(),languageCode:z.string().optional(),voiceSettings:z.object({stability:z.number().min(0).max(1).optional(),similarityBoost:z.number().min(0).max(1).optional(),style:z.number().min(0).max(1).optional(),useSpeakerBoost:z.boolean().optional(),speed:z.number().min(.5).max(2).optional()}).strict().optional()}).strict().optional(),openai:z.object({apiKey:z.string().optional().register(sensitive),model:z.string().optional(),voice:z.string().optional()}).strict().optional(),edge:z.object({enabled:z.boolean().optional(),voice:z.string().optional(),lang:z.string().optional(),outputFormat:z.string().optional(),pitch:z.string().optional(),rate:z.string().optional(),volume:z.string().optional(),saveSubtitles:z.boolean().optional(),proxy:z.string().optional(),timeoutMs:z.number().int().min(1e3).max(12e4).optional()}).strict().optional(),prefsPath:z.string().optional(),maxTextLength:z.number().int().min(1).optional(),timeoutMs:z.number().int().min(1e3).max(12e4).optional()}).strict().optional(),HumanDelaySchema=z.object({mode:z.union([z.literal(`off`),z.literal(`natural`),z.literal(`custom`)]).optional(),minMs:z.number().int().nonnegative().optional(),maxMs:z.number().int().nonnegative().optional()}).strict(),CliBackendWatchdogModeSchema=z.object({noOutputTimeoutMs:z.number().int().min(1e3).optional(),noOutputTimeoutRatio:z.number().min(.05).max(.95).optional(),minMs:z.number().int().min(1e3).optional(),maxMs:z.number().int().min(1e3).optional()}).strict().optional(),CliBackendSchema=z.object({command:z.string(),args:z.array(z.string()).optional(),output:z.union([z.literal(`json`),z.literal(`text`),z.literal(`jsonl`)]).optional(),resumeOutput:z.union([z.literal(`json`),z.literal(`text`),z.literal(`jsonl`)]).optional(),input:z.union([z.literal(`arg`),z.literal(`stdin`)]).optional(),maxPromptArgChars:z.number().int().positive().optional(),env:z.record(z.string(),z.string()).optional(),clearEnv:z.array(z.string()).optional(),modelArg:z.string().optional(),modelAliases:z.record(z.string(),z.string()).optional(),sessionArg:z.string().optional(),sessionArgs:z.array(z.string()).optional(),resumeArgs:z.array(z.string()).optional(),sessionMode:z.union([z.literal(`always`),z.literal(`existing`),z.literal(`none`)]).optional(),sessionIdFields:z.array(z.string()).optional(),systemPromptArg:z.string().optional(),systemPromptMode:z.union([z.literal(`append`),z.literal(`replace`)]).optional(),systemPromptWhen:z.union([z.literal(`first`),z.literal(`always`),z.literal(`never`)]).optional(),imageArg:z.string().optional(),imageMode:z.union([z.literal(`repeat`),z.literal(`list`)]).optional(),serialize:z.boolean().optional(),reliability:z.object({watchdog:z.object({fresh:CliBackendWatchdogModeSchema,resume:CliBackendWatchdogModeSchema}).strict().optional()}).strict().optional()}).strict(),normalizeAllowFrom=values=>(values??[]).map(v=>String(v).trim()).filter(Boolean),requireOpenAllowFrom=params=>{params.policy===`open`&&(normalizeAllowFrom(params.allowFrom).includes(`*`)||params.ctx.addIssue({code:z.ZodIssueCode.custom,path:params.path,message:params.message}))},MSTeamsReplyStyleSchema=z.enum([`thread`,`top-level`]),RetryConfigSchema=z.object({attempts:z.number().int().min(1).optional(),minDelayMs:z.number().int().min(0).optional(),maxDelayMs:z.number().int().min(0).optional(),jitter:z.number().min(0).max(1).optional()}).strict().optional(),QueueModeBySurfaceSchema=z.object({whatsapp:QueueModeSchema.optional(),telegram:QueueModeSchema.optional(),discord:QueueModeSchema.optional(),irc:QueueModeSchema.optional(),slack:QueueModeSchema.optional(),mattermost:QueueModeSchema.optional(),signal:QueueModeSchema.optional(),imessage:QueueModeSchema.optional(),msteams:QueueModeSchema.optional(),webchat:QueueModeSchema.optional()}).strict().optional(),DebounceMsBySurfaceSchema=z.record(z.string(),z.number().int().nonnegative()).optional(),QueueSchema=z.object({mode:QueueModeSchema.optional(),byChannel:QueueModeBySurfaceSchema,debounceMs:z.number().int().nonnegative().optional(),debounceMsByChannel:DebounceMsBySurfaceSchema,cap:z.number().int().positive().optional(),drop:QueueDropSchema.optional()}).strict().optional(),InboundDebounceSchema=z.object({debounceMs:z.number().int().nonnegative().optional(),byChannel:DebounceMsBySurfaceSchema}).strict().optional(),TranscribeAudioSchema=z.object({command:z.array(z.string()).superRefine((value,ctx)=>{let executable=value[0];isSafeExecutableValue(executable)||ctx.addIssue({code:z.ZodIssueCode.custom,path:[0],message:`expected safe executable name or path`})}),timeoutSeconds:z.number().int().positive().optional()}).strict().optional(),HexColorSchema=z.string().regex(/^#?[0-9a-fA-F]{6}$/,`expected hex color (RRGGBB)`),ExecutableTokenSchema=z.string().refine(isSafeExecutableValue,`expected safe executable name or path`),MediaUnderstandingScopeSchema=createAllowDenyChannelRulesSchema(),MediaUnderstandingCapabilitiesSchema=z.array(z.union([z.literal(`image`),z.literal(`audio`),z.literal(`video`)])).optional(),MediaUnderstandingAttachmentsSchema=z.object({mode:z.union([z.literal(`first`),z.literal(`all`)]).optional(),maxAttachments:z.number().int().positive().optional(),prefer:z.union([z.literal(`first`),z.literal(`last`),z.literal(`path`),z.literal(`url`)]).optional()}).strict().optional(),DeepgramAudioSchema=z.object({detectLanguage:z.boolean().optional(),punctuate:z.boolean().optional(),smartFormat:z.boolean().optional()}).strict().optional(),ProviderOptionValueSchema=z.union([z.string(),z.number(),z.boolean()]),ProviderOptionsSchema=z.record(z.string(),z.record(z.string(),ProviderOptionValueSchema)).optional(),MediaUnderstandingModelSchema=z.object({provider:z.string().optional(),model:z.string().optional(),capabilities:MediaUnderstandingCapabilitiesSchema,type:z.union([z.literal(`provider`),z.literal(`cli`)]).optional(),command:z.string().optional(),args:z.array(z.string()).optional(),prompt:z.string().optional(),maxChars:z.number().int().positive().optional(),maxBytes:z.number().int().positive().optional(),timeoutSeconds:z.number().int().positive().optional(),language:z.string().optional(),providerOptions:ProviderOptionsSchema,deepgram:DeepgramAudioSchema,baseUrl:z.string().optional(),headers:z.record(z.string(),z.string()).optional(),profile:z.string().optional(),preferredProfile:z.string().optional()}).strict().optional(),ToolsMediaUnderstandingSchema=z.object({enabled:z.boolean().optional(),scope:MediaUnderstandingScopeSchema,maxBytes:z.number().int().positive().optional(),maxChars:z.number().int().positive().optional(),prompt:z.string().optional(),timeoutSeconds:z.number().int().positive().optional(),language:z.string().optional(),providerOptions:ProviderOptionsSchema,deepgram:DeepgramAudioSchema,baseUrl:z.string().optional(),headers:z.record(z.string(),z.string()).optional(),attachments:MediaUnderstandingAttachmentsSchema,models:z.array(MediaUnderstandingModelSchema).optional()}).strict().optional(),ToolsMediaSchema=z.object({models:z.array(MediaUnderstandingModelSchema).optional(),concurrency:z.number().int().positive().optional(),image:ToolsMediaUnderstandingSchema.optional(),audio:ToolsMediaUnderstandingSchema.optional(),video:ToolsMediaUnderstandingSchema.optional()}).strict().optional(),LinkModelSchema=z.object({type:z.literal(`cli`).optional(),command:z.string().min(1),args:z.array(z.string()).optional(),timeoutSeconds:z.number().int().positive().optional()}).strict(),ToolsLinksSchema=z.object({enabled:z.boolean().optional(),scope:MediaUnderstandingScopeSchema,maxLinks:z.number().int().positive().optional(),timeoutSeconds:z.number().int().positive().optional(),models:z.array(LinkModelSchema).optional()}).strict().optional(),NativeCommandsSettingSchema=z.union([z.boolean(),z.literal(`auto`)]),ProviderCommandsSchema=z.object({native:NativeCommandsSettingSchema.optional(),nativeSkills:NativeCommandsSettingSchema.optional()}).strict().optional(),HeartbeatSchema=z.object({every:z.string().optional(),activeHours:z.object({start:z.string().optional(),end:z.string().optional(),timezone:z.string().optional()}).strict().optional(),model:z.string().optional(),session:z.string().optional(),includeReasoning:z.boolean().optional(),target:z.string().optional(),to:z.string().optional(),accountId:z.string().optional(),prompt:z.string().optional(),ackMaxChars:z.number().int().nonnegative().optional(),suppressToolErrorWarnings:z.boolean().optional()}).strict().superRefine((val,ctx)=>{if(!val.every)return;try{parseDurationMs(val.every,{defaultUnit:`m`})}catch{ctx.addIssue({code:z.ZodIssueCode.custom,path:[`every`],message:`invalid duration (use ms, s, m, h)`})}let active=val.activeHours;if(!active)return;let timePattern=/^([01]\d|2[0-3]|24):([0-5]\d)$/,validateTime=(raw,opts,path)=>{if(!raw)return;if(!timePattern.test(raw)){ctx.addIssue({code:z.ZodIssueCode.custom,path:[`activeHours`,path],message:`invalid time (use "HH:MM" 24h format)`});return}let[hourStr,minuteStr]=raw.split(`:`),hour=Number(hourStr),minute=Number(minuteStr);if(hour===24&&minute!==0){ctx.addIssue({code:z.ZodIssueCode.custom,path:[`activeHours`,path],message:`invalid time (24:00 is the only allowed 24:xx value)`});return}hour===24&&!opts.allow24&&ctx.addIssue({code:z.ZodIssueCode.custom,path:[`activeHours`,path],message:`invalid time (start cannot be 24:00)`})};validateTime(active.start,{allow24:!1},`start`),validateTime(active.end,{allow24:!0},`end`)}).optional(),SandboxDockerSchema=z.object({image:z.string().optional(),containerPrefix:z.string().optional(),workdir:z.string().optional(),readOnlyRoot:z.boolean().optional(),tmpfs:z.array(z.string()).optional(),network:z.string().optional(),user:z.string().optional(),capDrop:z.array(z.string()).optional(),env:z.record(z.string(),z.string()).optional(),setupCommand:z.string().optional(),pidsLimit:z.number().int().positive().optional(),memory:z.union([z.string(),z.number()]).optional(),memorySwap:z.union([z.string(),z.number()]).optional(),cpus:z.number().positive().optional(),ulimits:z.record(z.string(),z.union([z.string(),z.number(),z.object({soft:z.number().int().nonnegative().optional(),hard:z.number().int().nonnegative().optional()}).strict()])).optional(),seccompProfile:z.string().optional(),apparmorProfile:z.string().optional(),dns:z.array(z.string()).optional(),extraHosts:z.array(z.string()).optional(),binds:z.array(z.string()).optional()}).strict().superRefine((data,ctx)=>{if(data.binds)for(let i=0;i<data.binds.length;i+=1){let bind=data.binds[i]?.trim()??``;if(!bind){ctx.addIssue({code:z.ZodIssueCode.custom,path:[`binds`,i],message:`Sandbox security: bind mount entry must be a non-empty string.`});continue}let firstColon=bind.indexOf(`:`),source=(firstColon<=0?bind:bind.slice(0,firstColon)).trim();source.startsWith(`/`)||ctx.addIssue({code:z.ZodIssueCode.custom,path:[`binds`,i],message:`Sandbox security: bind mount "${bind}" uses a non-absolute source path "${source}". Only absolute POSIX paths are supported for sandbox binds.`})}data.network?.trim().toLowerCase()===`host`&&ctx.addIssue({code:z.ZodIssueCode.custom,path:[`network`],message:`Sandbox security: network mode "host" is blocked. Use "bridge" or "none" instead.`}),data.seccompProfile?.trim().toLowerCase()===`unconfined`&&ctx.addIssue({code:z.ZodIssueCode.custom,path:[`seccompProfile`],message:`Sandbox security: seccomp profile "unconfined" is blocked. Use a custom seccomp profile file or omit this setting.`}),data.apparmorProfile?.trim().toLowerCase()===`unconfined`&&ctx.addIssue({code:z.ZodIssueCode.custom,path:[`apparmorProfile`],message:`Sandbox security: apparmor profile "unconfined" is blocked. Use a named AppArmor profile or omit this setting.`})}).optional(),SandboxBrowserSchema=z.object({enabled:z.boolean().optional(),image:z.string().optional(),containerPrefix:z.string().optional(),cdpPort:z.number().int().positive().optional(),vncPort:z.number().int().positive().optional(),noVncPort:z.number().int().positive().optional(),headless:z.boolean().optional(),enableNoVnc:z.boolean().optional(),allowHostControl:z.boolean().optional(),autoStart:z.boolean().optional(),autoStartTimeoutMs:z.number().int().positive().optional(),binds:z.array(z.string()).optional()}).strict().optional(),SandboxPruneSchema=z.object({idleHours:z.number().int().nonnegative().optional(),maxAgeDays:z.number().int().nonnegative().optional()}).strict().optional(),ToolPolicySchema=z.object({allow:z.array(z.string()).optional(),alsoAllow:z.array(z.string()).optional(),deny:z.array(z.string()).optional()}).strict().superRefine((value,ctx)=>{value.allow&&value.allow.length>0&&value.alsoAllow&&value.alsoAllow.length>0&&ctx.addIssue({code:z.ZodIssueCode.custom,message:`tools policy cannot set both allow and alsoAllow in the same scope (merge alsoAllow into allow, or remove allow and use profile + alsoAllow)`})}).optional(),ToolsWebSearchSchema=z.object({enabled:z.boolean().optional(),provider:z.union([z.literal(`brave`),z.literal(`perplexity`),z.literal(`grok`),z.literal(`keyless`)]).optional(),apiKey:z.string().optional().register(sensitive),keylessFallback:z.boolean().optional(),keyless:z.object({searxngUrl:z.string().optional()}).strict().optional(),maxResults:z.number().int().positive().optional(),timeoutSeconds:z.number().int().positive().optional(),cacheTtlMinutes:z.number().nonnegative().optional(),perplexity:z.object({apiKey:z.string().optional().register(sensitive),baseUrl:z.string().optional(),model:z.string().optional()}).strict().optional(),grok:z.object({apiKey:z.string().optional().register(sensitive),model:z.string().optional(),inlineCitations:z.boolean().optional()}).strict().optional()}).strict().optional(),ToolsWebFetchSchema=z.object({enabled:z.boolean().optional(),maxChars:z.number().int().positive().optional(),maxCharsCap:z.number().int().positive().optional(),timeoutSeconds:z.number().int().positive().optional(),cacheTtlMinutes:z.number().nonnegative().optional(),maxRedirects:z.number().int().nonnegative().optional(),userAgent:z.string().optional()}).strict().optional(),ToolsWebSchema=z.object({search:ToolsWebSearchSchema,fetch:ToolsWebFetchSchema}).strict().optional(),ToolProfileSchema=z.union([z.literal(`minimal`),z.literal(`coding`),z.literal(`messaging`),z.literal(`full`)]).optional();function addAllowAlsoAllowConflictIssue(value,ctx,message){value.allow&&value.allow.length>0&&value.alsoAllow&&value.alsoAllow.length>0&&ctx.addIssue({code:z.ZodIssueCode.custom,message})}const ToolPolicyWithProfileSchema=z.object({allow:z.array(z.string()).optional(),alsoAllow:z.array(z.string()).optional(),deny:z.array(z.string()).optional(),profile:ToolProfileSchema}).strict().superRefine((value,ctx)=>{addAllowAlsoAllowConflictIssue(value,ctx,`tools.byProvider policy cannot set both allow and alsoAllow in the same scope (merge alsoAllow into allow, or remove allow and use profile + alsoAllow)`)}),ElevatedAllowFromSchema=z.record(z.string(),z.array(z.union([z.string(),z.number()]))).optional(),ToolExecApplyPatchSchema=z.object({enabled:z.boolean().optional(),workspaceOnly:z.boolean().optional(),allowModels:z.array(z.string()).optional()}).strict().optional(),ToolExecBaseShape={host:z.enum([`sandbox`,`gateway`,`node`]).optional(),security:z.enum([`deny`,`allowlist`,`full`]).optional(),ask:z.enum([`off`,`on-miss`,`always`]).optional(),node:z.string().optional(),pathPrepend:z.array(z.string()).optional(),safeBins:z.array(z.string()).optional(),backgroundMs:z.number().int().positive().optional(),timeoutSec:z.number().int().positive().optional(),cleanupMs:z.number().int().positive().optional(),notifyOnExit:z.boolean().optional(),notifyOnExitEmptySuccess:z.boolean().optional(),applyPatch:ToolExecApplyPatchSchema},AgentToolExecSchema=z.object({...ToolExecBaseShape,approvalRunningNoticeMs:z.number().int().nonnegative().optional()}).strict().optional(),ToolExecSchema=z.object(ToolExecBaseShape).strict().optional(),ToolFsSchema=z.object({workspaceOnly:z.boolean().optional(),convergedFileTools:z.boolean().optional()}).strict().optional(),ToolLoopDetectionDetectorSchema=z.object({genericRepeat:z.boolean().optional(),knownPollNoProgress:z.boolean().optional(),pingPong:z.boolean().optional()}).strict().optional(),ToolLoopDetectionSchema=z.object({enabled:z.boolean().optional(),historySize:z.number().int().positive().optional(),warningThreshold:z.number().int().positive().optional(),criticalThreshold:z.number().int().positive().optional(),globalCircuitBreakerThreshold:z.number().int().positive().optional(),detectors:ToolLoopDetectionDetectorSchema}).strict().superRefine((value,ctx)=>{value.warningThreshold!==void 0&&value.criticalThreshold!==void 0&&value.warningThreshold>=value.criticalThreshold&&ctx.addIssue({code:z.ZodIssueCode.custom,path:[`criticalThreshold`],message:`tools.loopDetection.warningThreshold must be lower than criticalThreshold.`}),value.criticalThreshold!==void 0&&value.globalCircuitBreakerThreshold!==void 0&&value.criticalThreshold>=value.globalCircuitBreakerThreshold&&ctx.addIssue({code:z.ZodIssueCode.custom,path:[`globalCircuitBreakerThreshold`],message:`tools.loopDetection.criticalThreshold must be lower than globalCircuitBreakerThreshold.`})}).optional(),AgentSandboxSchema=z.object({mode:z.union([z.literal(`off`),z.literal(`non-main`),z.literal(`all`)]).optional(),workspaceAccess:z.union([z.literal(`none`),z.literal(`ro`),z.literal(`rw`)]).optional(),sessionToolsVisibility:z.union([z.literal(`spawned`),z.literal(`all`)]).optional(),scope:z.union([z.literal(`session`),z.literal(`agent`),z.literal(`shared`)]).optional(),perSession:z.boolean().optional(),workspaceRoot:z.string().optional(),docker:SandboxDockerSchema,browser:SandboxBrowserSchema,prune:SandboxPruneSchema}).strict().optional(),AgentToolsSchema=z.object({profile:ToolProfileSchema,allow:z.array(z.string()).optional(),alsoAllow:z.array(z.string()).optional(),deny:z.array(z.string()).optional(),byProvider:z.record(z.string(),ToolPolicyWithProfileSchema).optional(),elevated:z.object({enabled:z.boolean().optional(),allowFrom:ElevatedAllowFromSchema}).strict().optional(),exec:AgentToolExecSchema,fs:ToolFsSchema,loopDetection:ToolLoopDetectionSchema,sandbox:z.object({tools:ToolPolicySchema}).strict().optional()}).strict().superRefine((value,ctx)=>{addAllowAlsoAllowConflictIssue(value,ctx,`agent tools cannot set both allow and alsoAllow in the same scope (merge alsoAllow into allow, or remove allow and use profile + alsoAllow)`)}).optional(),MemorySearchSchema=z.object({enabled:z.boolean().optional(),sources:z.array(z.union([z.literal(`memory`),z.literal(`sessions`)])).optional(),extraPaths:z.array(z.string()).optional(),experimental:z.object({sessionMemory:z.boolean().optional()}).strict().optional(),provider:z.union([z.literal(`openai`),z.literal(`local`),z.literal(`gemini`),z.literal(`voyage`)]).optional(),remote:z.object({baseUrl:z.string().optional(),apiKey:z.string().optional().register(sensitive),headers:z.record(z.string(),z.string()).optional(),batch:z.object({enabled:z.boolean().optional(),wait:z.boolean().optional(),concurrency:z.number().int().positive().optional(),pollIntervalMs:z.number().int().nonnegative().optional(),timeoutMinutes:z.number().int().positive().optional()}).strict().optional()}).strict().optional(),fallback:z.union([z.literal(`openai`),z.literal(`gemini`),z.literal(`local`),z.literal(`voyage`),z.literal(`none`)]).optional(),model:z.string().optional(),local:z.object({modelPath:z.string().optional(),modelCacheDir:z.string().optional()}).strict().optional(),store:z.object({driver:z.literal(`sqlite`).optional(),path:z.string().optional(),vector:z.object({enabled:z.boolean().optional(),extensionPath:z.string().optional()}).strict().optional()}).strict().optional(),chunking:z.object({tokens:z.number().int().positive().optional(),overlap:z.number().int().nonnegative().optional()}).strict().optional(),sync:z.object({onSessionStart:z.boolean().optional(),onSearch:z.boolean().optional(),watch:z.boolean().optional(),watchDebounceMs:z.number().int().nonnegative().optional(),intervalMinutes:z.number().int().nonnegative().optional(),sessions:z.object({deltaBytes:z.number().int().nonnegative().optional(),deltaMessages:z.number().int().nonnegative().optional()}).strict().optional()}).strict().optional(),query:z.object({maxResults:z.number().int().positive().optional(),minScore:z.number().min(0).max(1).optional(),hybrid:z.object({enabled:z.boolean().optional(),vectorWeight:z.number().min(0).max(1).optional(),textWeight:z.number().min(0).max(1).optional(),candidateMultiplier:z.number().int().positive().optional(),mmr:z.object({enabled:z.boolean().optional(),lambda:z.number().min(0).max(1).optional()}).strict().optional(),temporalDecay:z.object({enabled:z.boolean().optional(),halfLifeDays:z.number().int().positive().optional()}).strict().optional()}).strict().optional()}).strict().optional(),cache:z.object({enabled:z.boolean().optional(),maxEntries:z.number().int().positive().optional()}).strict().optional()}).strict().optional(),AgentEntrySchema=z.object({id:z.string(),default:z.boolean().optional(),name:z.string().optional(),workspace:z.string().optional(),agentDir:z.string().optional(),model:AgentModelSchema.optional(),skills:z.array(z.string()).optional(),memorySearch:MemorySearchSchema,humanDelay:HumanDelaySchema.optional(),heartbeat:HeartbeatSchema,identity:IdentitySchema,groupChat:GroupChatSchema,subagents:z.object({allowAgents:z.array(z.string()).optional(),model:z.union([z.string(),z.object({primary:z.string().optional(),fallbacks:z.array(z.string()).optional()}).strict()]).optional(),thinking:z.string().optional()}).strict().optional(),sandbox:AgentSandboxSchema,tools:AgentToolsSchema}).strict(),ToolsSchema=z.object({profile:ToolProfileSchema,allow:z.array(z.string()).optional(),alsoAllow:z.array(z.string()).optional(),deny:z.array(z.string()).optional(),byProvider:z.record(z.string(),ToolPolicyWithProfileSchema).optional(),web:ToolsWebSchema,media:ToolsMediaSchema,links:ToolsLinksSchema,sessions:z.object({visibility:z.enum([`self`,`tree`,`agent`,`all`]).optional()}).strict().optional(),loopDetection:ToolLoopDetectionSchema,message:z.object({allowCrossContextSend:z.boolean().optional(),crossContext:z.object({allowWithinProvider:z.boolean().optional(),allowAcrossProviders:z.boolean().optional(),marker:z.object({enabled:z.boolean().optional(),prefix:z.string().optional(),suffix:z.string().optional()}).strict().optional()}).strict().optional(),broadcast:z.object({enabled:z.boolean().optional()}).strict().optional()}).strict().optional(),agentToAgent:z.object({enabled:z.boolean().optional(),allow:z.array(z.string()).optional()}).strict().optional(),elevated:z.object({enabled:z.boolean().optional(),allowFrom:ElevatedAllowFromSchema}).strict().optional(),exec:ToolExecSchema,fs:ToolFsSchema,subagents:z.object({tools:ToolPolicySchema}).strict().optional(),sandbox:z.object({tools:ToolPolicySchema}).strict().optional()}).strict().superRefine((value,ctx)=>{addAllowAlsoAllowConflictIssue(value,ctx,`tools cannot set both allow and alsoAllow in the same scope (merge alsoAllow into allow, or remove allow and use profile + alsoAllow)`)}).optional(),ChannelHeartbeatVisibilitySchema=z.object({showOk:z.boolean().optional(),showAlerts:z.boolean().optional(),useIndicator:z.boolean().optional()}).strict().optional(),ToolPolicyBySenderSchema$1=z.record(z.string(),ToolPolicySchema).optional(),DiscordIdSchema=z.union([z.string(),z.number()]).refine(value=>typeof value==`string`,{message:`Discord IDs must be strings (wrap numeric IDs in quotes).`}),DiscordIdListSchema=z.array(DiscordIdSchema),TelegramInlineButtonsScopeSchema=z.enum([`off`,`dm`,`group`,`all`,`allowlist`]),TelegramCapabilitiesSchema=z.union([z.array(z.string()),z.object({inlineButtons:TelegramInlineButtonsScopeSchema.optional()}).strict()]),TelegramTopicSchema=z.object({requireMention:z.boolean().optional(),groupPolicy:GroupPolicySchema.optional(),skills:z.array(z.string()).optional(),enabled:z.boolean().optional(),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),systemPrompt:z.string().optional()}).strict(),TelegramGroupSchema=z.object({requireMention:z.boolean().optional(),groupPolicy:GroupPolicySchema.optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1,skills:z.array(z.string()).optional(),enabled:z.boolean().optional(),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),systemPrompt:z.string().optional(),topics:z.record(z.string(),TelegramTopicSchema.optional()).optional()}).strict(),TelegramCustomCommandSchema=z.object({command:z.string().transform(normalizeTelegramCommandName),description:z.string().transform(normalizeTelegramCommandDescription)}).strict(),validateTelegramCustomCommands=(value,ctx)=>{if(!value.customCommands||value.customCommands.length===0)return;let{issues}=resolveTelegramCustomCommands({commands:value.customCommands,checkReserved:!1,checkDuplicates:!1});for(let issue of issues)ctx.addIssue({code:z.ZodIssueCode.custom,path:[`customCommands`,issue.index,issue.field],message:issue.message})},TelegramAccountSchemaBase=z.object({name:z.string().optional(),capabilities:TelegramCapabilitiesSchema.optional(),markdown:MarkdownConfigSchema,enabled:z.boolean().optional(),commands:ProviderCommandsSchema,customCommands:z.array(TelegramCustomCommandSchema).optional(),configWrites:z.boolean().optional(),dmPolicy:DmPolicySchema.optional().default(`pairing`),botToken:z.string().optional().register(sensitive),tokenFile:z.string().optional(),replyToMode:ReplyToModeSchema.optional(),groups:z.record(z.string(),TelegramGroupSchema.optional()).optional(),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupAllowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),draftChunk:BlockStreamingChunkSchema.optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),streamMode:z.enum([`off`,`partial`,`block`]).optional().default(`partial`),mediaMaxMb:z.number().positive().optional(),timeoutSeconds:z.number().int().positive().optional(),retry:RetryConfigSchema,network:z.object({autoSelectFamily:z.boolean().optional()}).strict().optional(),proxy:z.string().optional(),webhookUrl:z.string().optional(),webhookSecret:z.string().optional().register(sensitive),webhookPath:z.string().optional(),webhookHost:z.string().optional(),actions:z.object({reactions:z.boolean().optional(),sendMessage:z.boolean().optional(),deleteMessage:z.boolean().optional(),sticker:z.boolean().optional()}).strict().optional(),reactionNotifications:z.enum([`off`,`own`,`all`]).optional(),reactionLevel:z.enum([`off`,`ack`,`minimal`,`extensive`]).optional(),heartbeat:ChannelHeartbeatVisibilitySchema,linkPreview:z.boolean().optional(),responsePrefix:z.string().optional(),ackReaction:z.string().optional()}).strict(),TelegramAccountSchema=TelegramAccountSchemaBase.superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.telegram.dmPolicy="open" requires channels.telegram.allowFrom to include "*"`}),validateTelegramCustomCommands(value,ctx)}),TelegramConfigSchema=TelegramAccountSchemaBase.extend({accounts:z.record(z.string(),TelegramAccountSchema.optional()).optional()}).superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.telegram.dmPolicy="open" requires channels.telegram.allowFrom to include "*"`}),validateTelegramCustomCommands(value,ctx);let baseWebhookUrl=typeof value.webhookUrl==`string`?value.webhookUrl.trim():``,baseWebhookSecret=typeof value.webhookSecret==`string`?value.webhookSecret.trim():``;if(baseWebhookUrl&&!baseWebhookSecret&&ctx.addIssue({code:z.ZodIssueCode.custom,message:`channels.telegram.webhookUrl requires channels.telegram.webhookSecret`,path:[`webhookSecret`]}),value.accounts)for(let[accountId,account]of Object.entries(value.accounts))account&&account.enabled!==!1&&typeof account.webhookUrl==`string`&&account.webhookUrl.trim()&&!(typeof account.webhookSecret==`string`&&account.webhookSecret.trim())&&!baseWebhookSecret&&ctx.addIssue({code:z.ZodIssueCode.custom,message:`channels.telegram.accounts.*.webhookUrl requires channels.telegram.webhookSecret or channels.telegram.accounts.*.webhookSecret`,path:[`accounts`,accountId,`webhookSecret`]})}),DiscordDmSchema=z.object({enabled:z.boolean().optional(),policy:DmPolicySchema.optional(),allowFrom:DiscordIdListSchema.optional(),groupEnabled:z.boolean().optional(),groupChannels:DiscordIdListSchema.optional()}).strict(),DiscordGuildChannelSchema=z.object({allow:z.boolean().optional(),requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1,skills:z.array(z.string()).optional(),enabled:z.boolean().optional(),users:DiscordIdListSchema.optional(),roles:DiscordIdListSchema.optional(),systemPrompt:z.string().optional(),includeThreadStarter:z.boolean().optional(),autoThread:z.boolean().optional()}).strict(),DiscordGuildSchema=z.object({slug:z.string().optional(),requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1,reactionNotifications:z.enum([`off`,`own`,`all`,`allowlist`]).optional(),users:DiscordIdListSchema.optional(),roles:DiscordIdListSchema.optional(),channels:z.record(z.string(),DiscordGuildChannelSchema.optional()).optional()}).strict(),DiscordUiSchema=z.object({components:z.object({accentColor:HexColorSchema.optional()}).strict().optional()}).strict().optional(),DiscordAccountSchema=z.object({name:z.string().optional(),capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,enabled:z.boolean().optional(),commands:ProviderCommandsSchema,configWrites:z.boolean().optional(),token:z.string().optional().register(sensitive),proxy:z.string().optional(),allowBots:z.boolean().optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),maxLinesPerMessage:z.number().int().positive().optional(),mediaMaxMb:z.number().positive().optional(),retry:RetryConfigSchema,actions:z.object({reactions:z.boolean().optional(),stickers:z.boolean().optional(),emojiUploads:z.boolean().optional(),stickerUploads:z.boolean().optional(),polls:z.boolean().optional(),permissions:z.boolean().optional(),messages:z.boolean().optional(),threads:z.boolean().optional(),pins:z.boolean().optional(),search:z.boolean().optional(),memberInfo:z.boolean().optional(),roleInfo:z.boolean().optional(),roles:z.boolean().optional(),channelInfo:z.boolean().optional(),voiceStatus:z.boolean().optional(),events:z.boolean().optional(),moderation:z.boolean().optional(),channels:z.boolean().optional(),presence:z.boolean().optional()}).strict().optional(),replyToMode:ReplyToModeSchema.optional(),dmPolicy:DmPolicySchema.optional(),allowFrom:DiscordIdListSchema.optional(),dm:DiscordDmSchema.optional(),guilds:z.record(z.string(),DiscordGuildSchema.optional()).optional(),heartbeat:ChannelHeartbeatVisibilitySchema,execApprovals:z.object({enabled:z.boolean().optional(),approvers:DiscordIdListSchema.optional(),agentFilter:z.array(z.string()).optional(),sessionFilter:z.array(z.string()).optional(),cleanupAfterResolve:z.boolean().optional(),target:z.enum([`dm`,`channel`,`both`]).optional()}).strict().optional(),ui:DiscordUiSchema,intents:z.object({presence:z.boolean().optional(),guildMembers:z.boolean().optional()}).strict().optional(),pluralkit:z.object({enabled:z.boolean().optional(),token:z.string().optional().register(sensitive)}).strict().optional(),responsePrefix:z.string().optional(),ackReaction:z.string().optional(),activity:z.string().optional(),status:z.enum([`online`,`dnd`,`idle`,`invisible`]).optional(),activityType:z.union([z.literal(0),z.literal(1),z.literal(2),z.literal(3),z.literal(4),z.literal(5)]).optional(),activityUrl:z.string().url().optional()}).strict().superRefine((value,ctx)=>{let hasActivity=!!(typeof value.activity==`string`&&value.activity.trim()),hasActivityType=value.activityType!==void 0,hasActivityUrl=!!(typeof value.activityUrl==`string`&&value.activityUrl.trim());(hasActivityType||hasActivityUrl)&&!hasActivity&&ctx.addIssue({code:z.ZodIssueCode.custom,message:`channels.discord.activity is required when activityType or activityUrl is set`,path:[`activity`]}),value.activityType===1&&!hasActivityUrl&&ctx.addIssue({code:z.ZodIssueCode.custom,message:`channels.discord.activityUrl is required when activityType is 1 (Streaming)`,path:[`activityUrl`]}),hasActivityUrl&&value.activityType!==1&&ctx.addIssue({code:z.ZodIssueCode.custom,message:`channels.discord.activityType must be 1 (Streaming) when activityUrl is set`,path:[`activityType`]}),requireOpenAllowFrom({policy:value.dmPolicy??value.dm?.policy??`pairing`,allowFrom:value.allowFrom??value.dm?.allowFrom,ctx,path:[...value.allowFrom===void 0?[`dm`,`allowFrom`]:[`allowFrom`]],message:`channels.discord.dmPolicy="open" requires channels.discord.allowFrom (or channels.discord.dm.allowFrom) to include "*"`})}),DiscordConfigSchema=DiscordAccountSchema.extend({accounts:z.record(z.string(),DiscordAccountSchema.optional()).optional()}),GoogleChatDmSchema=z.object({enabled:z.boolean().optional(),policy:DmPolicySchema.optional().default(`pairing`),allowFrom:z.array(z.union([z.string(),z.number()])).optional()}).strict().superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.policy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.googlechat.dm.policy="open" requires channels.googlechat.dm.allowFrom to include "*"`})}),GoogleChatGroupSchema=z.object({enabled:z.boolean().optional(),allow:z.boolean().optional(),requireMention:z.boolean().optional(),users:z.array(z.union([z.string(),z.number()])).optional(),systemPrompt:z.string().optional()}).strict(),GoogleChatAccountSchema=z.object({name:z.string().optional(),capabilities:z.array(z.string()).optional(),enabled:z.boolean().optional(),configWrites:z.boolean().optional(),allowBots:z.boolean().optional(),requireMention:z.boolean().optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),groupAllowFrom:z.array(z.union([z.string(),z.number()])).optional(),groups:z.record(z.string(),GoogleChatGroupSchema.optional()).optional(),serviceAccount:z.union([z.string(),z.record(z.string(),z.unknown())]).optional(),serviceAccountFile:z.string().optional(),audienceType:z.enum([`app-url`,`project-number`]).optional(),audience:z.string().optional(),webhookPath:z.string().optional(),webhookUrl:z.string().optional(),botUser:z.string().optional(),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),streamMode:z.enum([`replace`,`status_final`,`append`]).optional().default(`replace`),mediaMaxMb:z.number().positive().optional(),replyToMode:ReplyToModeSchema.optional(),actions:z.object({reactions:z.boolean().optional()}).strict().optional(),dm:GoogleChatDmSchema.optional(),typingIndicator:z.enum([`none`,`message`,`reaction`]).optional(),responsePrefix:z.string().optional()}).strict(),GoogleChatConfigSchema=GoogleChatAccountSchema.extend({accounts:z.record(z.string(),GoogleChatAccountSchema.optional()).optional(),defaultAccount:z.string().optional()}),SlackDmSchema=z.object({enabled:z.boolean().optional(),policy:DmPolicySchema.optional(),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupEnabled:z.boolean().optional(),groupChannels:z.array(z.union([z.string(),z.number()])).optional(),replyToMode:ReplyToModeSchema.optional()}).strict(),SlackChannelSchema=z.object({enabled:z.boolean().optional(),allow:z.boolean().optional(),requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1,allowBots:z.boolean().optional(),users:z.array(z.union([z.string(),z.number()])).optional(),skills:z.array(z.string()).optional(),systemPrompt:z.string().optional()}).strict(),SlackThreadSchema=z.object({historyScope:z.enum([`thread`,`channel`]).optional(),inheritParent:z.boolean().optional(),initialHistoryLimit:z.number().int().min(0).optional()}).strict(),SlackReplyToModeByChatTypeSchema=z.object({direct:ReplyToModeSchema.optional(),group:ReplyToModeSchema.optional(),channel:ReplyToModeSchema.optional()}).strict(),SlackAccountSchema=z.object({name:z.string().optional(),mode:z.enum([`socket`,`http`]).optional(),signingSecret:z.string().optional().register(sensitive),webhookPath:z.string().optional(),capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,enabled:z.boolean().optional(),commands:ProviderCommandsSchema,configWrites:z.boolean().optional(),botToken:z.string().optional().register(sensitive),appToken:z.string().optional().register(sensitive),userToken:z.string().optional().register(sensitive),userTokenReadOnly:z.boolean().optional().default(!0),allowBots:z.boolean().optional(),requireMention:z.boolean().optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),streaming:z.boolean().optional(),mediaMaxMb:z.number().positive().optional(),reactionNotifications:z.enum([`off`,`own`,`all`,`allowlist`]).optional(),reactionAllowlist:z.array(z.union([z.string(),z.number()])).optional(),replyToMode:ReplyToModeSchema.optional(),replyToModeByChatType:SlackReplyToModeByChatTypeSchema.optional(),thread:SlackThreadSchema.optional(),actions:z.object({reactions:z.boolean().optional(),messages:z.boolean().optional(),pins:z.boolean().optional(),search:z.boolean().optional(),permissions:z.boolean().optional(),memberInfo:z.boolean().optional(),channelInfo:z.boolean().optional(),emojiList:z.boolean().optional()}).strict().optional(),slashCommand:z.object({enabled:z.boolean().optional(),name:z.string().optional(),sessionPrefix:z.string().optional(),ephemeral:z.boolean().optional()}).strict().optional(),dmPolicy:DmPolicySchema.optional(),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),dm:SlackDmSchema.optional(),channels:z.record(z.string(),SlackChannelSchema.optional()).optional(),heartbeat:ChannelHeartbeatVisibilitySchema,responsePrefix:z.string().optional(),ackReaction:z.string().optional()}).strict().superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy??value.dm?.policy??`pairing`,allowFrom:value.allowFrom??value.dm?.allowFrom,ctx,path:[...value.allowFrom===void 0?[`dm`,`allowFrom`]:[`allowFrom`]],message:`channels.slack.dmPolicy="open" requires channels.slack.allowFrom (or channels.slack.dm.allowFrom) to include "*"`})}),SlackConfigSchema=SlackAccountSchema.safeExtend({mode:z.enum([`socket`,`http`]).optional().default(`socket`),signingSecret:z.string().optional().register(sensitive),webhookPath:z.string().optional().default(`/slack/events`),accounts:z.record(z.string(),SlackAccountSchema.optional()).optional()}).superRefine((value,ctx)=>{let baseMode=value.mode??`socket`;if(baseMode===`http`&&!value.signingSecret&&ctx.addIssue({code:z.ZodIssueCode.custom,message:`channels.slack.mode="http" requires channels.slack.signingSecret`,path:[`signingSecret`]}),value.accounts)for(let[accountId,account]of Object.entries(value.accounts))account&&account.enabled!==!1&&(account.mode??baseMode)===`http`&&((account.signingSecret??value.signingSecret)||ctx.addIssue({code:z.ZodIssueCode.custom,message:`channels.slack.accounts.*.mode="http" requires channels.slack.signingSecret or channels.slack.accounts.*.signingSecret`,path:[`accounts`,accountId,`signingSecret`]}))}),SignalAccountSchemaBase=z.object({name:z.string().optional(),capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,enabled:z.boolean().optional(),configWrites:z.boolean().optional(),account:z.string().optional(),httpUrl:z.string().optional(),httpHost:z.string().optional(),httpPort:z.number().int().positive().optional(),cliPath:ExecutableTokenSchema.optional(),autoStart:z.boolean().optional(),startupTimeoutMs:z.number().int().min(1e3).max(12e4).optional(),receiveMode:z.union([z.literal(`on-start`),z.literal(`manual`)]).optional(),ignoreAttachments:z.boolean().optional(),ignoreStories:z.boolean().optional(),sendReadReceipts:z.boolean().optional(),dmPolicy:DmPolicySchema.optional().default(`pairing`),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupAllowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),mediaMaxMb:z.number().int().positive().optional(),reactionNotifications:z.enum([`off`,`own`,`all`,`allowlist`]).optional(),reactionAllowlist:z.array(z.union([z.string(),z.number()])).optional(),actions:z.object({reactions:z.boolean().optional()}).strict().optional(),reactionLevel:z.enum([`off`,`ack`,`minimal`,`extensive`]).optional(),heartbeat:ChannelHeartbeatVisibilitySchema,responsePrefix:z.string().optional()}).strict(),SignalAccountSchema=SignalAccountSchemaBase.superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.signal.dmPolicy="open" requires channels.signal.allowFrom to include "*"`})}),SignalConfigSchema=SignalAccountSchemaBase.extend({accounts:z.record(z.string(),SignalAccountSchema.optional()).optional()}).superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.signal.dmPolicy="open" requires channels.signal.allowFrom to include "*"`})}),IrcGroupSchema=z.object({requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1,skills:z.array(z.string()).optional(),enabled:z.boolean().optional(),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),systemPrompt:z.string().optional()}).strict(),IrcNickServSchema=z.object({enabled:z.boolean().optional(),service:z.string().optional(),password:z.string().optional().register(sensitive),passwordFile:z.string().optional(),register:z.boolean().optional(),registerEmail:z.string().optional()}).strict(),IrcAccountSchemaBase=z.object({name:z.string().optional(),capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,enabled:z.boolean().optional(),configWrites:z.boolean().optional(),host:z.string().optional(),port:z.number().int().min(1).max(65535).optional(),tls:z.boolean().optional(),nick:z.string().optional(),username:z.string().optional(),realname:z.string().optional(),password:z.string().optional().register(sensitive),passwordFile:z.string().optional(),nickserv:IrcNickServSchema.optional(),channels:z.array(z.string()).optional(),dmPolicy:DmPolicySchema.optional().default(`pairing`),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupAllowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),groups:z.record(z.string(),IrcGroupSchema.optional()).optional(),mentionPatterns:z.array(z.string()).optional(),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),mediaMaxMb:z.number().positive().optional(),heartbeat:ChannelHeartbeatVisibilitySchema,responsePrefix:z.string().optional()}).strict();function refineIrcAllowFromAndNickserv(value,ctx){requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.irc.dmPolicy="open" requires channels.irc.allowFrom to include "*"`}),value.nickserv?.register&&!value.nickserv.registerEmail?.trim()&&ctx.addIssue({code:z.ZodIssueCode.custom,path:[`nickserv`,`registerEmail`],message:`channels.irc.nickserv.register=true requires channels.irc.nickserv.registerEmail`})}const IrcAccountSchema=IrcAccountSchemaBase.superRefine((value,ctx)=>{refineIrcAllowFromAndNickserv(value,ctx)}),IrcConfigSchema=IrcAccountSchemaBase.extend({accounts:z.record(z.string(),IrcAccountSchema.optional()).optional()}).superRefine((value,ctx)=>{refineIrcAllowFromAndNickserv(value,ctx)}),IMessageAccountSchemaBase=z.object({name:z.string().optional(),capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,enabled:z.boolean().optional(),configWrites:z.boolean().optional(),cliPath:ExecutableTokenSchema.optional(),dbPath:z.string().optional(),remoteHost:z.string().optional(),service:z.union([z.literal(`imessage`),z.literal(`sms`),z.literal(`auto`)]).optional(),region:z.string().optional(),dmPolicy:DmPolicySchema.optional().default(`pairing`),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupAllowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),includeAttachments:z.boolean().optional(),mediaMaxMb:z.number().int().positive().optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),groups:z.record(z.string(),z.object({requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1}).strict().optional()).optional(),heartbeat:ChannelHeartbeatVisibilitySchema,responsePrefix:z.string().optional()}).strict(),IMessageAccountSchema=IMessageAccountSchemaBase.superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.imessage.dmPolicy="open" requires channels.imessage.allowFrom to include "*"`})}),IMessageConfigSchema=IMessageAccountSchemaBase.extend({accounts:z.record(z.string(),IMessageAccountSchema.optional()).optional()}).superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.imessage.dmPolicy="open" requires channels.imessage.allowFrom to include "*"`})}),BlueBubblesAllowFromEntry=z.union([z.string(),z.number()]),BlueBubblesActionSchema=z.object({reactions:z.boolean().optional(),edit:z.boolean().optional(),unsend:z.boolean().optional(),reply:z.boolean().optional(),sendWithEffect:z.boolean().optional(),renameGroup:z.boolean().optional(),setGroupIcon:z.boolean().optional(),addParticipant:z.boolean().optional(),removeParticipant:z.boolean().optional(),leaveGroup:z.boolean().optional(),sendAttachment:z.boolean().optional()}).strict().optional(),BlueBubblesGroupConfigSchema=z.object({requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1}).strict(),BlueBubblesAccountSchemaBase=z.object({name:z.string().optional(),capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,configWrites:z.boolean().optional(),enabled:z.boolean().optional(),serverUrl:z.string().optional(),password:z.string().optional().register(sensitive),webhookPath:z.string().optional(),dmPolicy:DmPolicySchema.optional().default(`pairing`),allowFrom:z.array(BlueBubblesAllowFromEntry).optional(),groupAllowFrom:z.array(BlueBubblesAllowFromEntry).optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),mediaMaxMb:z.number().int().positive().optional(),mediaLocalRoots:z.array(z.string()).optional(),sendReadReceipts:z.boolean().optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),groups:z.record(z.string(),BlueBubblesGroupConfigSchema.optional()).optional(),heartbeat:ChannelHeartbeatVisibilitySchema,responsePrefix:z.string().optional()}).strict(),BlueBubblesAccountSchema=BlueBubblesAccountSchemaBase.superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.bluebubbles.accounts.*.dmPolicy="open" requires allowFrom to include "*"`})}),BlueBubblesConfigSchema=BlueBubblesAccountSchemaBase.extend({accounts:z.record(z.string(),BlueBubblesAccountSchema.optional()).optional(),actions:BlueBubblesActionSchema}).superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.bluebubbles.dmPolicy="open" requires channels.bluebubbles.allowFrom to include "*"`})}),MSTeamsChannelSchema=z.object({requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1,replyStyle:MSTeamsReplyStyleSchema.optional()}).strict(),MSTeamsTeamSchema=z.object({requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1,replyStyle:MSTeamsReplyStyleSchema.optional(),channels:z.record(z.string(),MSTeamsChannelSchema.optional()).optional()}).strict(),MSTeamsConfigSchema=z.object({enabled:z.boolean().optional(),capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,configWrites:z.boolean().optional(),appId:z.string().optional(),appPassword:z.string().optional().register(sensitive),tenantId:z.string().optional(),webhook:z.object({port:z.number().int().positive().optional(),path:z.string().optional()}).strict().optional(),dmPolicy:DmPolicySchema.optional().default(`pairing`),allowFrom:z.array(z.string()).optional(),groupAllowFrom:z.array(z.string()).optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),mediaAllowHosts:z.array(z.string()).optional(),mediaAuthAllowHosts:z.array(z.string()).optional(),requireMention:z.boolean().optional(),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),replyStyle:MSTeamsReplyStyleSchema.optional(),teams:z.record(z.string(),MSTeamsTeamSchema.optional()).optional(),mediaMaxMb:z.number().positive().optional(),sharePointSiteId:z.string().optional(),heartbeat:ChannelHeartbeatVisibilitySchema,responsePrefix:z.string().optional()}).strict().superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.msteams.dmPolicy="open" requires channels.msteams.allowFrom to include "*"`})}),ToolPolicyBySenderSchema=z.record(z.string(),ToolPolicySchema).optional(),WhatsAppGroupEntrySchema=z.object({requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema}).strict().optional(),WhatsAppGroupsSchema=z.record(z.string(),WhatsAppGroupEntrySchema).optional(),WhatsAppAckReactionSchema=z.object({emoji:z.string().optional(),direct:z.boolean().optional().default(!0),group:z.enum([`always`,`mentions`,`never`]).optional().default(`mentions`)}).strict().optional(),WhatsAppSharedSchema=z.object({capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,configWrites:z.boolean().optional(),sendReadReceipts:z.boolean().optional(),messagePrefix:z.string().optional(),responsePrefix:z.string().optional(),dmPolicy:DmPolicySchema.optional().default(`pairing`),selfChatMode:z.boolean().optional(),allowFrom:z.array(z.string()).optional(),groupAllowFrom:z.array(z.string()).optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),groups:WhatsAppGroupsSchema,ackReaction:WhatsAppAckReactionSchema,debounceMs:z.number().int().nonnegative().optional().default(0),heartbeat:ChannelHeartbeatVisibilitySchema});function enforceOpenDmPolicyAllowFromStar(params){params.dmPolicy===`open`&&((Array.isArray(params.allowFrom)?params.allowFrom:[]).map(v=>String(v).trim()).filter(Boolean).includes(`*`)||params.ctx.addIssue({code:z.ZodIssueCode.custom,path:[`allowFrom`],message:params.message}))}const WhatsAppAccountSchema=WhatsAppSharedSchema.extend({name:z.string().optional(),enabled:z.boolean().optional(),authDir:z.string().optional(),mediaMaxMb:z.number().int().positive().optional()}).strict().superRefine((value,ctx)=>{enforceOpenDmPolicyAllowFromStar({dmPolicy:value.dmPolicy,allowFrom:value.allowFrom,ctx,message:`channels.whatsapp.accounts.*.dmPolicy="open" requires allowFrom to include "*"`})}),WhatsAppConfigSchema=WhatsAppSharedSchema.extend({accounts:z.record(z.string(),WhatsAppAccountSchema.optional()).optional(),mediaMaxMb:z.number().int().positive().optional().default(50),actions:z.object({reactions:z.boolean().optional(),sendMessage:z.boolean().optional(),polls:z.boolean().optional()}).strict().optional()}).strict().superRefine((value,ctx)=>{enforceOpenDmPolicyAllowFromStar({dmPolicy:value.dmPolicy,allowFrom:value.allowFrom,ctx,message:`channels.whatsapp.dmPolicy="open" requires channels.whatsapp.allowFrom to include "*"`})});function loadDotEnv(opts){let quiet=opts?.quiet??!0;dotenv.config({quiet});let globalEnvPath=path.join(resolveConfigDir(process.env),`.env`);fs.existsSync(globalEnvPath)&&dotenv.config({quiet,path:globalEnvPath,override:!1})}const PACKAGE_JSON_CANDIDATES=[`../package.json`,`../../package.json`,`../../../package.json`,`./package.json`],BUILD_INFO_CANDIDATES=[`../build-info.json`,`../../build-info.json`,`./build-info.json`];function readVersionFromJsonCandidates(moduleUrl,candidates,opts={}){try{let require=createRequire(moduleUrl);for(let candidate of candidates)try{let parsed=require(candidate),version=parsed.version?.trim();if(!version||opts.requirePackageName&&parsed.name!==`builderforce`)continue;return version}catch{}return null}catch{return null}}function readVersionFromPackageJsonForModuleUrl(moduleUrl){return readVersionFromJsonCandidates(moduleUrl,PACKAGE_JSON_CANDIDATES,{requirePackageName:!0})}function readVersionFromBuildInfoForModuleUrl(moduleUrl){return readVersionFromJsonCandidates(moduleUrl,BUILD_INFO_CANDIDATES)}function resolveVersionFromModuleUrl(moduleUrl){return readVersionFromPackageJsonForModuleUrl(moduleUrl)||readVersionFromBuildInfoForModuleUrl(moduleUrl)}const VERSION=typeof __BUILDERFORCE_AGENTS_VERSION__==`string`&&__BUILDERFORCE_AGENTS_VERSION__||process.env.BUILDERFORCE_AGENTS_BUNDLED_VERSION||resolveVersionFromModuleUrl(import.meta.url)||`0.0.0`;var DuplicateAgentDirError=class extends Error{constructor(duplicates){super(formatDuplicateAgentDirError(duplicates)),this.name=`DuplicateAgentDirError`,this.duplicates=duplicates}};function canonicalizeAgentDir(agentDir){let resolved=path.resolve(agentDir);return process.platform===`darwin`||process.platform===`win32`?resolved.toLowerCase():resolved}function collectReferencedAgentIds(cfg){let ids=new Set,agents=Array.isArray(cfg.agents?.list)?cfg.agents?.list:[],defaultAgentId=agents.find(agent=>agent?.default)?.id??agents[0]?.id??DEFAULT_AGENT_ID;ids.add(normalizeAgentId(defaultAgentId));for(let entry of agents)entry?.id&&ids.add(normalizeAgentId(entry.id));let bindings=cfg.bindings;if(Array.isArray(bindings))for(let binding of bindings){let id=binding?.agentId;typeof id==`string`&&id.trim()&&ids.add(normalizeAgentId(id))}return[...ids]}function resolveEffectiveAgentDir(cfg,agentId,deps){let id=normalizeAgentId(agentId),trimmed=(Array.isArray(cfg.agents?.list)?cfg.agents?.list.find(agent=>normalizeAgentId(agent.id)===id)?.agentDir:void 0)?.trim();if(trimmed)return resolveUserPath(trimmed);let env=deps?.env??process.env,root=resolveStateDir(env,deps?.homedir??(()=>resolveRequiredHomeDir(env,os.homedir)));return path.join(root,`agents`,id,`agent`)}function findDuplicateAgentDirs(cfg,deps){let byDir=new Map;for(let agentId of collectReferencedAgentIds(cfg)){let agentDir=resolveEffectiveAgentDir(cfg,agentId,deps),key=canonicalizeAgentDir(agentDir),entry=byDir.get(key);entry?entry.agentIds.push(agentId):byDir.set(key,{agentDir,agentIds:[agentId]})}return[...byDir.values()].filter(v=>v.agentIds.length>1)}function formatDuplicateAgentDirError(dups){return[`Duplicate agentDir detected (multi-agent config).`,`Each agent must have a unique agentDir; sharing it causes auth/session state collisions and token invalidation.`,``,`Conflicts:`,...dups.map(d=>`- ${d.agentDir}: ${d.agentIds.map(id=>`"${id}"`).join(`, `)}`),``,`Fix: remove the shared agents.list[].agentDir override (or give each agent its own directory).`,`If you want to share credentials, copy auth-profiles.json instead of sharing the entire agentDir.`].join(`
|
|
2
|
-
`)}async function rotateConfigBackups(configPath,ioFs){let backupBase=`${configPath}.bak`;await ioFs.unlink(`${backupBase}.4`).catch(()=>{});for(let index=3;index>=1;--index)await ioFs.rename(`${backupBase}.${index}`,`${backupBase}.${index+1}`).catch(()=>{});await ioFs.rename(backupBase,`${backupBase}.1`).catch(()=>{})}function resolveAgentMaxConcurrent(cfg){let raw=cfg?.agents?.defaults?.maxConcurrent;return typeof raw==`number`&&Number.isFinite(raw)?Math.max(1,Math.floor(raw)):4}function readTalkApiKeyFromProfile(deps={}){let fsImpl=deps.fs??fs,osImpl=deps.os??os,pathImpl=deps.path??path,home=osImpl.homedir(),candidates=[`.profile`,`.zprofile`,`.zshrc`,`.bashrc`].map(name=>pathImpl.join(home,name));for(let candidate of candidates)if(fsImpl.existsSync(candidate))try{let value=fsImpl.readFileSync(candidate,`utf-8`).match(/(?:^|\n)\s*(?:export\s+)?ELEVENLABS_API_KEY\s*=\s*["']?([^\n"']+)["']?/)?.[1]?.trim();if(value)return value}catch{}return null}function resolveTalkApiKey(env=process.env,deps={}){return(env.ELEVENLABS_API_KEY??``).trim()||readTalkApiKeyFromProfile(deps)}let defaultWarnState={warned:!1};const DEFAULT_MODEL_ALIASES={...Object.fromEntries(ANTHROPIC_FAMILIES.map(family=>[family,`anthropic/${currentAnthropicModelId(family)}`])),gpt:`openai/gpt-5.2`,"gpt-mini":`openai/gpt-5-mini`,gemini:`google/gemini-3-pro-preview`,"gemini-flash":`google/gemini-3-flash-preview`},DEFAULT_MODEL_COST={input:0,output:0,cacheRead:0,cacheWrite:0},DEFAULT_MODEL_INPUT=[`text`];function isPositiveNumber(value){return typeof value==`number`&&Number.isFinite(value)&&value>0}function resolveModelCost(raw){return{input:typeof raw?.input==`number`?raw.input:DEFAULT_MODEL_COST.input,output:typeof raw?.output==`number`?raw.output:DEFAULT_MODEL_COST.output,cacheRead:typeof raw?.cacheRead==`number`?raw.cacheRead:DEFAULT_MODEL_COST.cacheRead,cacheWrite:typeof raw?.cacheWrite==`number`?raw.cacheWrite:DEFAULT_MODEL_COST.cacheWrite}}function resolveAnthropicDefaultAuthMode(cfg){let profiles=cfg.auth?.profiles??{},anthropicProfiles=Object.entries(profiles).filter(([,profile])=>profile?.provider===`anthropic`),order=cfg.auth?.order?.anthropic??[];for(let profileId of order){let entry=profiles[profileId];if(!(!entry||entry.provider!==`anthropic`)){if(entry.mode===`api_key`)return`api_key`;if(entry.mode===`oauth`||entry.mode===`token`)return`oauth`}}let hasApiKey=anthropicProfiles.some(([,profile])=>profile?.mode===`api_key`),hasOauth=anthropicProfiles.some(([,profile])=>profile?.mode===`oauth`||profile?.mode===`token`);return hasApiKey&&!hasOauth?`api_key`:hasOauth&&!hasApiKey||process.env.ANTHROPIC_OAUTH_TOKEN?.trim()?`oauth`:process.env.ANTHROPIC_API_KEY?.trim()?`api_key`:null}function resolvePrimaryModelRef(raw){if(!raw||typeof raw!=`string`)return null;let trimmed=raw.trim();return trimmed?DEFAULT_MODEL_ALIASES[trimmed.toLowerCase()]??trimmed:null}function applyMessageDefaults(cfg){let messages=cfg.messages;if(messages?.ackReactionScope!==void 0)return cfg;let nextMessages=messages?{...messages}:{};return nextMessages.ackReactionScope=`group-mentions`,{...cfg,messages:nextMessages}}function applySessionDefaults(cfg,options={}){let session=cfg.session;if(!session||session.mainKey===void 0)return cfg;let trimmed=session.mainKey.trim(),warn=options.warn??console.warn,warnState=options.warnState??defaultWarnState,next={...cfg,session:{...session,mainKey:`main`}};return trimmed&&trimmed!==`main`&&!warnState.warned&&(warnState.warned=!0,warn(`session.mainKey is ignored; main session is always "main".`)),next}function applyTalkApiKey(config){let resolved=resolveTalkApiKey();return!resolved||config.talk?.apiKey?.trim()?config:{...config,talk:{...config.talk,apiKey:resolved}}}function applyModelDefaults(cfg){let mutated=!1,nextCfg=cfg,providerConfig=nextCfg.models?.providers;if(providerConfig){let nextProviders={...providerConfig};for(let[providerId,provider]of Object.entries(providerConfig)){let models=provider.models;if(!Array.isArray(models)||models.length===0)continue;let providerMutated=!1,nextModels=models.map(model=>{let raw=model,modelMutated=!1,reasoning=typeof raw.reasoning==`boolean`?raw.reasoning:!1;raw.reasoning!==reasoning&&(modelMutated=!0);let input=raw.input??[...DEFAULT_MODEL_INPUT];raw.input===void 0&&(modelMutated=!0);let cost=resolveModelCost(raw.cost);(!raw.cost||raw.cost.input!==cost.input||raw.cost.output!==cost.output||raw.cost.cacheRead!==cost.cacheRead||raw.cost.cacheWrite!==cost.cacheWrite)&&(modelMutated=!0);let contextWindow=isPositiveNumber(raw.contextWindow)?raw.contextWindow:DEFAULT_CONTEXT_TOKENS;raw.contextWindow!==contextWindow&&(modelMutated=!0);let defaultMaxTokens=Math.min(8192,contextWindow),rawMaxTokens=isPositiveNumber(raw.maxTokens)?raw.maxTokens:defaultMaxTokens,maxTokens=Math.min(rawMaxTokens,contextWindow);return raw.maxTokens!==maxTokens&&(modelMutated=!0),modelMutated?(providerMutated=!0,{...raw,reasoning,input,cost,contextWindow,maxTokens}):model});providerMutated&&(nextProviders[providerId]={...provider,models:nextModels},mutated=!0)}mutated&&(nextCfg={...nextCfg,models:{...nextCfg.models,providers:nextProviders}})}let existingAgent=nextCfg.agents?.defaults;if(!existingAgent)return mutated?nextCfg:cfg;let existingModels=existingAgent.models??{};if(Object.keys(existingModels).length===0)return mutated?nextCfg:cfg;let nextModels={...existingModels};for(let[alias,target]of Object.entries(DEFAULT_MODEL_ALIASES)){let entry=nextModels[target];entry&&entry.alias===void 0&&(nextModels[target]={...entry,alias},mutated=!0)}return mutated?{...nextCfg,agents:{...nextCfg.agents,defaults:{...existingAgent,models:nextModels}}}:cfg}function applyAgentDefaults(cfg){let agents=cfg.agents,defaults=agents?.defaults,hasMax=typeof defaults?.maxConcurrent==`number`&&Number.isFinite(defaults.maxConcurrent),hasSubMax=typeof defaults?.subagents?.maxConcurrent==`number`&&Number.isFinite(defaults.subagents.maxConcurrent);if(hasMax&&hasSubMax)return cfg;let mutated=!1,nextDefaults=defaults?{...defaults}:{};hasMax||(nextDefaults.maxConcurrent=4,mutated=!0);let nextSubagents=defaults?.subagents?{...defaults.subagents}:{};return hasSubMax||(nextSubagents.maxConcurrent=8,mutated=!0),mutated?{...cfg,agents:{...agents,defaults:{...nextDefaults,subagents:nextSubagents}}}:cfg}function applyLoggingDefaults(cfg){let logging=cfg.logging;return!logging||logging.redactSensitive?cfg:{...cfg,logging:{...logging,redactSensitive:`tools`}}}function applyContextPruningDefaults(cfg){let defaults=cfg.agents?.defaults;if(!defaults)return cfg;let authMode=resolveAnthropicDefaultAuthMode(cfg);if(!authMode)return cfg;let mutated=!1,nextDefaults={...defaults},contextPruning=defaults.contextPruning??{},heartbeat=defaults.heartbeat??{};if(defaults.contextPruning?.mode===void 0&&(nextDefaults.contextPruning={...contextPruning,mode:`cache-ttl`,ttl:defaults.contextPruning?.ttl??`1h`},mutated=!0),defaults.heartbeat?.every===void 0&&(nextDefaults.heartbeat={...heartbeat,every:authMode===`oauth`?`1h`:`30m`},mutated=!0),authMode===`api_key`){let nextModels=defaults.models?{...defaults.models}:{},modelsMutated=!1;for(let[key,entry]of Object.entries(nextModels)){let parsed=parseModelRef(key,`anthropic`);if(!parsed||parsed.provider!==`anthropic`)continue;let current=entry??{},params=current.params??{};typeof params.cacheRetention!=`string`&&(nextModels[key]={...current,params:{...params,cacheRetention:`short`}},modelsMutated=!0)}let primary=resolvePrimaryModelRef(defaults.model?.primary??void 0);if(primary){let parsedPrimary=parseModelRef(primary,`anthropic`);if(parsedPrimary?.provider===`anthropic`){let key=`${parsedPrimary.provider}/${parsedPrimary.model}`,current=nextModels[key]??{},params=current.params??{};typeof params.cacheRetention!=`string`&&(nextModels[key]={...current,params:{...params,cacheRetention:`short`}},modelsMutated=!0)}}modelsMutated&&(nextDefaults.models=nextModels,mutated=!0)}return mutated?{...cfg,agents:{...cfg.agents,defaults:nextDefaults}}:cfg}function applyCompactionDefaults(cfg){let defaults=cfg.agents?.defaults;if(!defaults)return cfg;let compaction=defaults?.compaction;return compaction?.mode?cfg:{...cfg,agents:{...cfg.agents,defaults:{...defaults,compaction:{...compaction,mode:`safeguard`}}}}}const ENV_VAR_NAME_PATTERN=/^[A-Z_][A-Z0-9_]*$/;var MissingEnvVarError=class extends Error{constructor(varName,configPath){super(`Missing env var "${varName}" referenced at config path: ${configPath}`),this.varName=varName,this.configPath=configPath,this.name=`MissingEnvVarError`}};function parseEnvTokenAt(value,index){if(value[index]!==`$`)return null;let next=value[index+1],afterNext=value[index+2];if(next===`$`&&afterNext===`{`){let start=index+3,end=value.indexOf(`}`,start);if(end!==-1){let name=value.slice(start,end);if(ENV_VAR_NAME_PATTERN.test(name))return{kind:`escaped`,name,end}}}if(next===`{`){let start=index+2,end=value.indexOf(`}`,start);if(end!==-1){let name=value.slice(start,end);if(ENV_VAR_NAME_PATTERN.test(name))return{kind:`substitution`,name,end}}}return null}function resolveEnvVarsInString(value,env,onMissing,configPath=``){if(!value.includes(`$`))return value;let chunks=[];for(let i=0;i<value.length;i+=1){let char=value[i];if(char!==`$`){chunks.push(char);continue}let token=parseEnvTokenAt(value,i);if(token?.kind===`escaped`){chunks.push(`\${${token.name}}`),i=token.end;continue}if(token?.kind===`substitution`){let envValue=env[token.name];if(envValue===void 0||envValue===``){if(onMissing===`throw`)throw new MissingEnvVarError(token.name,configPath);return null}chunks.push(envValue),i=token.end;continue}chunks.push(char)}return chunks.join(``)}function substituteString(value,env,configPath){return resolveEnvVarsInString(value,env,`throw`,configPath)}function containsEnvVarReference(value){if(!value.includes(`$`))return!1;for(let i=0;i<value.length;i+=1){if(value[i]!==`$`)continue;let token=parseEnvTokenAt(value,i);if(token?.kind===`escaped`){i=token.end;continue}if(token?.kind===`substitution`)return!0}return!1}function substituteAny(value,env,path){if(typeof value==`string`)return substituteString(value,env,path);if(Array.isArray(value))return value.map((item,index)=>substituteAny(item,env,`${path}[${index}]`));if(isPlainObject$2(value)){let result={};for(let[key,val]of Object.entries(value))result[key]=substituteAny(val,env,path?`${path}.${key}`:key);return result}return value}function resolveConfigEnvVars(obj,env=process.env){return substituteAny(obj,env,``)}function isPlainObject$1(value){return typeof value==`object`&&!!value&&!Array.isArray(value)&&Object.prototype.toString.call(value)===`[object Object]`}function restoreEnvVarRefs(incoming,parsed,env=process.env){if(parsed==null)return incoming;if(typeof incoming==`string`&&typeof parsed==`string`)return resolveEnvVarsInString(parsed,env,`null`)===incoming?parsed:incoming;if(Array.isArray(incoming)&&Array.isArray(parsed))return incoming.map((item,i)=>i<parsed.length?restoreEnvVarRefs(item,parsed[i],env):item);if(isPlainObject$1(incoming)&&isPlainObject$1(parsed)){let result={};for(let[key,value]of Object.entries(incoming))key in parsed?result[key]=restoreEnvVarRefs(value,parsed[key],env):result[key]=value;return result}return incoming}function collectConfigEnvVars(cfg){let envConfig=cfg?.env;if(!envConfig)return{};let entries={};if(envConfig.vars)for(let[key,value]of Object.entries(envConfig.vars))value&&(entries[key]=value);for(let[key,value]of Object.entries(envConfig))key===`shellEnv`||key===`vars`||typeof value!=`string`||!value.trim()||(entries[key]=value);return entries}function applyConfigEnvVars(cfg,env=process.env){let entries=collectConfigEnvVars(cfg);for(let[key,value]of Object.entries(entries))env[key]?.trim()||(env[key]=value)}function isPathInside(basePath,candidatePath){let base=path.resolve(basePath),candidate=path.resolve(candidatePath),rel=path.relative(base,candidate);return rel===``||!rel.startsWith(`..${path.sep}`)&&rel!==`..`&&!path.isAbsolute(rel)}const INCLUDE_KEY=`$include`;var ConfigIncludeError=class extends Error{constructor(message,includePath,cause){super(message),this.includePath=includePath,this.cause=cause,this.name=`ConfigIncludeError`}},CircularIncludeError=class extends ConfigIncludeError{constructor(chain){super(`Circular include detected: ${chain.join(` -> `)}`,chain[chain.length-1]),this.chain=chain,this.name=`CircularIncludeError`}};function deepMerge(target,source){if(Array.isArray(target)&&Array.isArray(source))return[...target,...source];if(isPlainObject$2(target)&&isPlainObject$2(source)){let result={...target};for(let key of Object.keys(source))result[key]=key in result?deepMerge(result[key],source[key]):source[key];return result}return source}var IncludeProcessor=class IncludeProcessor{constructor(basePath,resolver,rootDir){this.basePath=basePath,this.resolver=resolver,this.visited=new Set,this.depth=0,this.visited.add(path.normalize(basePath)),this.rootDir=path.normalize(rootDir??path.dirname(basePath)),this.rootRealDir=path.normalize(safeRealpath(this.rootDir))}process(obj){return Array.isArray(obj)?obj.map(item=>this.process(item)):isPlainObject$2(obj)?INCLUDE_KEY in obj?this.processInclude(obj):this.processObject(obj):obj}processObject(obj){let result={};for(let[key,value]of Object.entries(obj))result[key]=this.process(value);return result}processInclude(obj){let includeValue=obj[INCLUDE_KEY],otherKeys=Object.keys(obj).filter(k=>k!==INCLUDE_KEY),included=this.resolveInclude(includeValue);if(otherKeys.length===0)return included;if(!isPlainObject$2(included))throw new ConfigIncludeError(`Sibling keys require included content to be an object`,typeof includeValue==`string`?includeValue:INCLUDE_KEY);let rest={};for(let key of otherKeys)rest[key]=this.process(obj[key]);return deepMerge(included,rest)}resolveInclude(value){if(typeof value==`string`)return this.loadFile(value);if(Array.isArray(value))return value.reduce((merged,item)=>{if(typeof item!=`string`)throw new ConfigIncludeError(`Invalid $include array item: expected string, got ${typeof item}`,String(item));return deepMerge(merged,this.loadFile(item))},{});throw new ConfigIncludeError(`Invalid $include value: expected string or array of strings, got ${typeof value}`,String(value))}loadFile(includePath){let resolvedPath=this.resolvePath(includePath);this.checkCircular(resolvedPath),this.checkDepth(includePath);let raw=this.readFile(includePath,resolvedPath),parsed=this.parseFile(includePath,resolvedPath,raw);return this.processNested(resolvedPath,parsed)}resolvePath(includePath){let configDir=path.dirname(this.basePath),resolved=path.isAbsolute(includePath)?includePath:path.resolve(configDir,includePath),normalized=path.normalize(resolved);if(!isPathInside(this.rootDir,normalized))throw new ConfigIncludeError(`Include path escapes config directory: ${includePath} (root: ${this.rootDir})`,includePath);try{let real=fs.realpathSync(normalized);if(!isPathInside(this.rootRealDir,real))throw new ConfigIncludeError(`Include path resolves outside config directory (symlink): ${includePath} (root: ${this.rootDir})`,includePath)}catch(err){if(err instanceof ConfigIncludeError)throw err}return normalized}checkCircular(resolvedPath){if(this.visited.has(resolvedPath))throw new CircularIncludeError([...this.visited,resolvedPath])}checkDepth(includePath){if(this.depth>=10)throw new ConfigIncludeError(`Maximum include depth (10) exceeded at: ${includePath}`,includePath)}readFile(includePath,resolvedPath){try{return this.resolver.readFile(resolvedPath)}catch(err){throw new ConfigIncludeError(`Failed to read include file: ${includePath} (resolved: ${resolvedPath})`,includePath,err instanceof Error?err:void 0)}}parseFile(includePath,resolvedPath,raw){try{return this.resolver.parseJson(raw)}catch(err){throw new ConfigIncludeError(`Failed to parse include file: ${includePath} (resolved: ${resolvedPath})`,includePath,err instanceof Error?err:void 0)}}processNested(resolvedPath,parsed){let nested=new IncludeProcessor(resolvedPath,this.resolver,this.rootDir);return nested.visited=new Set([...this.visited,resolvedPath]),nested.depth=this.depth+1,nested.process(parsed)}};function safeRealpath(target){try{return fs.realpathSync(target)}catch{return target}}const defaultResolver={readFile:p=>fs.readFileSync(p,`utf-8`),parseJson:raw=>JSON5.parse(raw)};function resolveConfigIncludes(obj,configPath,resolver=defaultResolver){return new IncludeProcessor(configPath,resolver).process(obj)}const getRecord=value=>isRecord(value)?value:null,ensureRecord=(root,key)=>{let existing=root[key];if(isRecord(existing))return existing;let next={};return root[key]=next,next},mergeMissing=(target,source)=>{for(let[key,value]of Object.entries(source)){if(value===void 0)continue;let existing=target[key];if(existing===void 0){target[key]=value;continue}isRecord(existing)&&isRecord(value)&&mergeMissing(existing,value)}},mapLegacyAudioTranscription=value=>{let transcriber=getRecord(value),command=Array.isArray(transcriber?.command)?transcriber?.command:null;if(!command||command.length===0||typeof command[0]!=`string`||!command.every(part=>typeof part==`string`))return null;let rawExecutable=command[0].trim();if(!rawExecutable||!isSafeExecutableValue(rawExecutable))return null;let args=command.slice(1),timeoutSeconds=typeof transcriber?.timeoutSeconds==`number`?transcriber?.timeoutSeconds:void 0,result={command:rawExecutable,type:`cli`};return args.length>0&&(result.args=args),timeoutSeconds!==void 0&&(result.timeoutSeconds=timeoutSeconds),result},getAgentsList=agents=>{let list=agents?.list;return Array.isArray(list)?list:[]},resolveDefaultAgentIdFromRaw=raw=>{let list=getAgentsList(getRecord(raw.agents)),defaultEntry=list.find(entry=>isRecord(entry)&&entry.default===!0&&typeof entry.id==`string`&&entry.id.trim()!==``);if(defaultEntry)return defaultEntry.id.trim();let routing=getRecord(raw.routing),routingDefault=typeof routing?.defaultAgentId==`string`?routing.defaultAgentId.trim():``;if(routingDefault)return routingDefault;let firstEntry=list.find(entry=>isRecord(entry)&&typeof entry.id==`string`&&entry.id.trim()!==``);return firstEntry?firstEntry.id.trim():`main`},ensureAgentEntry=(list,id)=>{let normalized=id.trim(),existing=list.find(entry=>isRecord(entry)&&typeof entry.id==`string`&&entry.id.trim()===normalized);if(existing)return existing;let created={id:normalized};return list.push(created),created};function migrateBindings(raw,changes,changeNote,mutator){let bindings=Array.isArray(raw.bindings)?raw.bindings:null;if(!bindings)return;let touched=!1;for(let entry of bindings){if(!isRecord(entry))continue;let match=getRecord(entry.match);match&&mutator(match)&&(entry.match=match,touched=!0)}touched&&(raw.bindings=bindings,changes.push(changeNote))}function ensureDefaultGroupEntry(section){let groups=isRecord(section.groups)?section.groups:{};return{groups,entry:isRecord(groups[`*`])?groups[`*`]:{}}}const LEGACY_CONFIG_MIGRATIONS_PART_1=[{id:`bindings.match.provider->bindings.match.channel`,describe:`Move bindings[].match.provider to bindings[].match.channel`,apply:(raw,changes)=>{migrateBindings(raw,changes,`Moved bindings[].match.provider → bindings[].match.channel.`,match=>{if(typeof match.channel==`string`&&match.channel.trim())return!1;let provider=typeof match.provider==`string`?match.provider.trim():``;return provider?(match.channel=provider,delete match.provider,!0):!1})}},{id:`bindings.match.accountID->bindings.match.accountId`,describe:`Move bindings[].match.accountID to bindings[].match.accountId`,apply:(raw,changes)=>{migrateBindings(raw,changes,`Moved bindings[].match.accountID → bindings[].match.accountId.`,match=>{if(match.accountId!==void 0)return!1;let accountID=typeof match.accountID==`string`?match.accountID.trim():match.accountID;return accountID?(match.accountId=accountID,delete match.accountID,!0):!1})}},{id:`session.sendPolicy.rules.match.provider->match.channel`,describe:`Move session.sendPolicy.rules[].match.provider to match.channel`,apply:(raw,changes)=>{let session=getRecord(raw.session);if(!session)return;let sendPolicy=getRecord(session.sendPolicy);if(!sendPolicy)return;let rules=Array.isArray(sendPolicy.rules)?sendPolicy.rules:null;if(!rules)return;let touched=!1;for(let rule of rules){if(!isRecord(rule))continue;let match=getRecord(rule.match);if(!match||typeof match.channel==`string`&&match.channel.trim())continue;let provider=typeof match.provider==`string`?match.provider.trim():``;provider&&(match.channel=provider,delete match.provider,rule.match=match,touched=!0)}touched&&(sendPolicy.rules=rules,session.sendPolicy=sendPolicy,raw.session=session,changes.push(`Moved session.sendPolicy.rules[].match.provider → match.channel.`))}},{id:`messages.queue.byProvider->byChannel`,describe:`Move messages.queue.byProvider to messages.queue.byChannel`,apply:(raw,changes)=>{let messages=getRecord(raw.messages);if(!messages)return;let queue=getRecord(messages.queue);queue&&queue.byProvider!==void 0&&(queue.byChannel===void 0?(queue.byChannel=queue.byProvider,changes.push(`Moved messages.queue.byProvider → messages.queue.byChannel.`)):changes.push(`Removed messages.queue.byProvider (messages.queue.byChannel already set).`),delete queue.byProvider,messages.queue=queue,raw.messages=messages)}},{id:`providers->channels`,describe:`Move provider config sections to channels.*`,apply:(raw,changes)=>{let legacyEntries=[`whatsapp`,`telegram`,`discord`,`slack`,`signal`,`imessage`,`msteams`].filter(key=>isRecord(raw[key]));if(legacyEntries.length===0)return;let channels=ensureRecord(raw,`channels`);for(let key of legacyEntries){let legacy=getRecord(raw[key]);if(!legacy)continue;let channelEntry=ensureRecord(channels,key),hadEntries=Object.keys(channelEntry).length>0;mergeMissing(channelEntry,legacy),channels[key]=channelEntry,delete raw[key],changes.push(hadEntries?`Merged ${key} → channels.${key}.`:`Moved ${key} → channels.${key}.`)}raw.channels=channels}},{id:`routing.allowFrom->channels.whatsapp.allowFrom`,describe:`Move routing.allowFrom to channels.whatsapp.allowFrom`,apply:(raw,changes)=>{let routing=raw.routing;if(!routing||typeof routing!=`object`)return;let allowFrom=routing.allowFrom;if(allowFrom===void 0)return;let channels=getRecord(raw.channels),whatsapp=channels?getRecord(channels.whatsapp):null;if(!whatsapp){delete routing.allowFrom,Object.keys(routing).length===0&&delete raw.routing,changes.push(`Removed routing.allowFrom (channels.whatsapp not configured).`);return}whatsapp.allowFrom===void 0?(whatsapp.allowFrom=allowFrom,changes.push(`Moved routing.allowFrom → channels.whatsapp.allowFrom.`)):changes.push(`Removed routing.allowFrom (channels.whatsapp.allowFrom already set).`),delete routing.allowFrom,Object.keys(routing).length===0&&delete raw.routing,channels.whatsapp=whatsapp,raw.channels=channels}},{id:`routing.groupChat.requireMention->groups.*.requireMention`,describe:`Move routing.groupChat.requireMention to channels.whatsapp/telegram/imessage groups`,apply:(raw,changes)=>{let routing=raw.routing;if(!routing||typeof routing!=`object`)return;let groupChat=routing.groupChat&&typeof routing.groupChat==`object`?routing.groupChat:null;if(!groupChat)return;let requireMention=groupChat.requireMention;if(requireMention===void 0)return;let channels=ensureRecord(raw,`channels`),applyTo=(key,options)=>{if(options?.requireExisting&&!isRecord(channels[key]))return;let section=channels[key]&&typeof channels[key]==`object`?channels[key]:{},{groups,entry}=ensureDefaultGroupEntry(section);entry.requireMention===void 0?(entry.requireMention=requireMention,groups[`*`]=entry,section.groups=groups,channels[key]=section,changes.push(`Moved routing.groupChat.requireMention → channels.${key}.groups."*".requireMention.`)):changes.push(`Removed routing.groupChat.requireMention (channels.${key}.groups."*" already set).`)};applyTo(`whatsapp`,{requireExisting:!0}),applyTo(`telegram`),applyTo(`imessage`),delete groupChat.requireMention,Object.keys(groupChat).length===0&&delete routing.groupChat,Object.keys(routing).length===0&&delete raw.routing,raw.channels=channels}},{id:`gateway.token->gateway.auth.token`,describe:`Move gateway.token to gateway.auth.token`,apply:(raw,changes)=>{let gateway=raw.gateway;if(!gateway||typeof gateway!=`object`)return;let token=gateway.token;if(token===void 0)return;let gatewayObj=gateway,auth=gatewayObj.auth&&typeof gatewayObj.auth==`object`?gatewayObj.auth:{};auth.token===void 0?(auth.token=token,auth.mode||=`token`,changes.push(`Moved gateway.token → gateway.auth.token.`)):changes.push(`Removed gateway.token (gateway.auth.token already set).`),delete gatewayObj.token,Object.keys(auth).length>0&&(gatewayObj.auth=auth),raw.gateway=gatewayObj}},{id:`telegram.requireMention->channels.telegram.groups.*.requireMention`,describe:`Move telegram.requireMention to channels.telegram.groups.*.requireMention`,apply:(raw,changes)=>{let channels=ensureRecord(raw,`channels`),telegram=channels.telegram;if(!telegram||typeof telegram!=`object`)return;let requireMention=telegram.requireMention;if(requireMention===void 0)return;let{groups,entry}=ensureDefaultGroupEntry(telegram);entry.requireMention===void 0?(entry.requireMention=requireMention,groups[`*`]=entry,telegram.groups=groups,changes.push(`Moved telegram.requireMention → channels.telegram.groups."*".requireMention.`)):changes.push(`Removed telegram.requireMention (channels.telegram.groups."*" already set).`),delete telegram.requireMention,channels.telegram=telegram,raw.channels=channels}}];function applyLegacyAudioTranscriptionModel(params){let mapped=mapLegacyAudioTranscription(params.source);if(!mapped){params.changes.push(params.invalidMessage);return}let mediaAudio=ensureRecord(ensureRecord(ensureRecord(params.raw,`tools`),`media`),`audio`);if((Array.isArray(mediaAudio.models)?mediaAudio.models:[]).length===0){mediaAudio.enabled=!0,mediaAudio.models=[mapped],params.changes.push(params.movedMessage);return}params.changes.push(params.alreadySetMessage)}const LEGACY_CONFIG_MIGRATIONS_PART_2=[{id:`agent.model-config-v2`,describe:`Migrate legacy agent.model/allowedModels/modelAliases/modelFallbacks/imageModelFallbacks to agent.models + model lists`,apply:(raw,changes)=>{let agentRoot=getRecord(raw.agent),defaults=getRecord(getRecord(raw.agents)?.defaults),agent=agentRoot??defaults;if(!agent)return;let label=agentRoot?`agent`:`agents.defaults`,legacyModel=typeof agent.model==`string`?String(agent.model):void 0,legacyImageModel=typeof agent.imageModel==`string`?String(agent.imageModel):void 0,legacyAllowed=Array.isArray(agent.allowedModels)?agent.allowedModels.map(String):[],legacyModelFallbacks=Array.isArray(agent.modelFallbacks)?agent.modelFallbacks.map(String):[],legacyImageModelFallbacks=Array.isArray(agent.imageModelFallbacks)?agent.imageModelFallbacks.map(String):[],legacyAliases=agent.modelAliases&&typeof agent.modelAliases==`object`?agent.modelAliases:{};if(!(legacyModel||legacyImageModel||legacyAllowed.length>0||legacyModelFallbacks.length>0||legacyImageModelFallbacks.length>0||Object.keys(legacyAliases).length>0))return;let models=agent.models&&typeof agent.models==`object`?agent.models:{},ensureModel=rawKey=>{if(typeof rawKey!=`string`)return;let key=rawKey.trim();key&&(models[key]||(models[key]={}))};ensureModel(legacyModel),ensureModel(legacyImageModel);for(let key of legacyAllowed)ensureModel(key);for(let key of legacyModelFallbacks)ensureModel(key);for(let key of legacyImageModelFallbacks)ensureModel(key);for(let target of Object.values(legacyAliases))typeof target==`string`&&ensureModel(target);for(let[alias,targetRaw]of Object.entries(legacyAliases)){if(typeof targetRaw!=`string`)continue;let target=targetRaw.trim();if(!target)continue;let entry=models[target]&&typeof models[target]==`object`?models[target]:{};`alias`in entry||(entry.alias=alias,models[target]=entry)}let currentModel=agent.model&&typeof agent.model==`object`?agent.model:null;currentModel?(!currentModel.primary&&legacyModel&&(currentModel.primary=legacyModel),legacyModelFallbacks.length>0&&(!Array.isArray(currentModel.fallbacks)||currentModel.fallbacks.length===0)&&(currentModel.fallbacks=legacyModelFallbacks),agent.model=currentModel):(legacyModel||legacyModelFallbacks.length>0)&&(agent.model={primary:legacyModel,fallbacks:legacyModelFallbacks.length?legacyModelFallbacks:[]});let currentImageModel=agent.imageModel&&typeof agent.imageModel==`object`?agent.imageModel:null;currentImageModel?(!currentImageModel.primary&&legacyImageModel&&(currentImageModel.primary=legacyImageModel),legacyImageModelFallbacks.length>0&&(!Array.isArray(currentImageModel.fallbacks)||currentImageModel.fallbacks.length===0)&&(currentImageModel.fallbacks=legacyImageModelFallbacks),agent.imageModel=currentImageModel):(legacyImageModel||legacyImageModelFallbacks.length>0)&&(agent.imageModel={primary:legacyImageModel,fallbacks:legacyImageModelFallbacks.length?legacyImageModelFallbacks:[]}),agent.models=models,legacyModel!==void 0&&changes.push(`Migrated ${label}.model string → ${label}.model.primary.`),legacyModelFallbacks.length>0&&changes.push(`Migrated ${label}.modelFallbacks → ${label}.model.fallbacks.`),legacyImageModel!==void 0&&changes.push(`Migrated ${label}.imageModel string → ${label}.imageModel.primary.`),legacyImageModelFallbacks.length>0&&changes.push(`Migrated ${label}.imageModelFallbacks → ${label}.imageModel.fallbacks.`),legacyAllowed.length>0&&changes.push(`Migrated ${label}.allowedModels → ${label}.models.`),Object.keys(legacyAliases).length>0&&changes.push(`Migrated ${label}.modelAliases → ${label}.models.*.alias.`),delete agent.allowedModels,delete agent.modelAliases,delete agent.modelFallbacks,delete agent.imageModelFallbacks}},{id:`routing.agents-v2`,describe:`Move routing.agents/defaultAgentId to agents.list`,apply:(raw,changes)=>{let routing=getRecord(raw.routing);if(!routing)return;let routingAgents=getRecord(routing.agents),agents=ensureRecord(raw,`agents`),list=getAgentsList(agents);if(routingAgents){for(let[rawId,entryRaw]of Object.entries(routingAgents)){let agentId=String(rawId??``).trim(),entry=getRecord(entryRaw);if(!agentId||!entry)continue;let target=ensureAgentEntry(list,agentId),entryCopy={...entry};if(`mentionPatterns`in entryCopy){let mentionPatterns=entryCopy.mentionPatterns,groupChat=ensureRecord(target,`groupChat`);groupChat.mentionPatterns===void 0?(groupChat.mentionPatterns=mentionPatterns,changes.push(`Moved routing.agents.${agentId}.mentionPatterns → agents.list (id "${agentId}").groupChat.mentionPatterns.`)):changes.push(`Removed routing.agents.${agentId}.mentionPatterns (agents.list groupChat mentionPatterns already set).`),delete entryCopy.mentionPatterns}let legacyGroupChat=getRecord(entryCopy.groupChat);legacyGroupChat&&(mergeMissing(ensureRecord(target,`groupChat`),legacyGroupChat),delete entryCopy.groupChat);let legacySandbox=getRecord(entryCopy.sandbox);if(legacySandbox){let sandboxTools=getRecord(legacySandbox.tools);sandboxTools&&(mergeMissing(ensureRecord(ensureRecord(ensureRecord(target,`tools`),`sandbox`),`tools`),sandboxTools),delete legacySandbox.tools,changes.push(`Moved routing.agents.${agentId}.sandbox.tools → agents.list (id "${agentId}").tools.sandbox.tools.`)),entryCopy.sandbox=legacySandbox}mergeMissing(target,entryCopy)}delete routing.agents,changes.push(`Moved routing.agents → agents.list.`)}let defaultAgentId=typeof routing.defaultAgentId==`string`?routing.defaultAgentId.trim():``;if(defaultAgentId){if(list.some(entry=>isRecord(entry)&&entry.default===!0))changes.push(`Removed routing.defaultAgentId (agents.list default already set).`);else{let entry=ensureAgentEntry(list,defaultAgentId);entry.default=!0,changes.push(`Moved routing.defaultAgentId → agents.list (id "${defaultAgentId}").default.`)}delete routing.defaultAgentId}list.length>0&&(agents.list=list),Object.keys(routing).length===0&&delete raw.routing}},{id:`routing.config-v2`,describe:`Move routing bindings/groupChat/queue/agentToAgent/transcribeAudio`,apply:(raw,changes)=>{let routing=getRecord(raw.routing);if(!routing)return;if(routing.bindings!==void 0&&(raw.bindings===void 0?(raw.bindings=routing.bindings,changes.push(`Moved routing.bindings → bindings.`)):changes.push(`Removed routing.bindings (bindings already set).`),delete routing.bindings),routing.agentToAgent!==void 0){let tools=ensureRecord(raw,`tools`);tools.agentToAgent===void 0?(tools.agentToAgent=routing.agentToAgent,changes.push(`Moved routing.agentToAgent → tools.agentToAgent.`)):changes.push(`Removed routing.agentToAgent (tools.agentToAgent already set).`),delete routing.agentToAgent}if(routing.queue!==void 0){let messages=ensureRecord(raw,`messages`);messages.queue===void 0?(messages.queue=routing.queue,changes.push(`Moved routing.queue → messages.queue.`)):changes.push(`Removed routing.queue (messages.queue already set).`),delete routing.queue}let groupChat=getRecord(routing.groupChat);if(groupChat){let historyLimit=groupChat.historyLimit;if(historyLimit!==void 0){let messagesGroup=ensureRecord(ensureRecord(raw,`messages`),`groupChat`);messagesGroup.historyLimit===void 0?(messagesGroup.historyLimit=historyLimit,changes.push(`Moved routing.groupChat.historyLimit → messages.groupChat.historyLimit.`)):changes.push(`Removed routing.groupChat.historyLimit (messages.groupChat.historyLimit already set).`),delete groupChat.historyLimit}let mentionPatterns=groupChat.mentionPatterns;if(mentionPatterns!==void 0){let messagesGroup=ensureRecord(ensureRecord(raw,`messages`),`groupChat`);messagesGroup.mentionPatterns===void 0?(messagesGroup.mentionPatterns=mentionPatterns,changes.push(`Moved routing.groupChat.mentionPatterns → messages.groupChat.mentionPatterns.`)):changes.push(`Removed routing.groupChat.mentionPatterns (messages.groupChat.mentionPatterns already set).`),delete groupChat.mentionPatterns}Object.keys(groupChat).length===0?delete routing.groupChat:routing.groupChat=groupChat}routing.transcribeAudio!==void 0&&(applyLegacyAudioTranscriptionModel({raw,source:routing.transcribeAudio,changes,movedMessage:`Moved routing.transcribeAudio → tools.media.audio.models.`,alreadySetMessage:`Removed routing.transcribeAudio (tools.media.audio.models already set).`,invalidMessage:`Removed routing.transcribeAudio (invalid or empty command).`}),delete routing.transcribeAudio),Object.keys(routing).length===0&&delete raw.routing}},{id:`audio.transcription-v2`,describe:`Move audio.transcription to tools.media.audio.models`,apply:(raw,changes)=>{let audio=getRecord(raw.audio);audio?.transcription!==void 0&&(applyLegacyAudioTranscriptionModel({raw,source:audio.transcription,changes,movedMessage:`Moved audio.transcription → tools.media.audio.models.`,alreadySetMessage:`Removed audio.transcription (tools.media.audio.models already set).`,invalidMessage:`Removed audio.transcription (invalid or empty command).`}),delete audio.transcription,Object.keys(audio).length===0?delete raw.audio:raw.audio=audio)}}],LEGACY_CONFIG_MIGRATIONS_PART_3=[{id:`memorySearch->agents.defaults.memorySearch`,describe:`Move top-level memorySearch to agents.defaults.memorySearch`,apply:(raw,changes)=>{let legacyMemorySearch=getRecord(raw.memorySearch);if(!legacyMemorySearch)return;let agents=ensureRecord(raw,`agents`),defaults=ensureRecord(agents,`defaults`),existing=getRecord(defaults.memorySearch);if(!existing)defaults.memorySearch=legacyMemorySearch,changes.push(`Moved memorySearch → agents.defaults.memorySearch.`);else{let merged=structuredClone(existing);mergeMissing(merged,legacyMemorySearch),defaults.memorySearch=merged,changes.push(`Merged memorySearch → agents.defaults.memorySearch (filled missing fields from legacy; kept explicit agents.defaults values).`)}agents.defaults=defaults,raw.agents=agents,delete raw.memorySearch}},{id:`auth.anthropic-claude-cli-mode-oauth`,describe:`Switch anthropic:claude-cli auth profile mode to oauth`,apply:(raw,changes)=>{let profiles=getRecord(getRecord(raw.auth)?.profiles);if(!profiles)return;let claudeCli=getRecord(profiles[`anthropic:claude-cli`]);claudeCli&&claudeCli.mode===`token`&&(claudeCli.mode=`oauth`,changes.push(`Updated auth.profiles["anthropic:claude-cli"].mode → "oauth".`))}},{id:`tools.bash->tools.exec`,describe:`Move tools.bash to tools.exec`,apply:(raw,changes)=>{let tools=ensureRecord(raw,`tools`),bash=getRecord(tools.bash);bash&&(tools.exec===void 0?(tools.exec=bash,changes.push(`Moved tools.bash → tools.exec.`)):changes.push(`Removed tools.bash (tools.exec already set).`),delete tools.bash)}},{id:`messages.tts.enabled->auto`,describe:`Move messages.tts.enabled to messages.tts.auto`,apply:(raw,changes)=>{let tts=getRecord(getRecord(raw.messages)?.tts);if(tts){if(tts.auto!==void 0){`enabled`in tts&&(delete tts.enabled,changes.push(`Removed messages.tts.enabled (messages.tts.auto already set).`));return}typeof tts.enabled==`boolean`&&(tts.auto=tts.enabled?`always`:`off`,delete tts.enabled,changes.push(`Moved messages.tts.enabled → messages.tts.auto (${String(tts.auto)}).`))}}},{id:`agent.defaults-v2`,describe:`Move agent config to agents.defaults and tools`,apply:(raw,changes)=>{let agent=getRecord(raw.agent);if(!agent)return;let agents=ensureRecord(raw,`agents`),defaults=getRecord(agents.defaults)??{},tools=ensureRecord(raw,`tools`),agentTools=getRecord(agent.tools);agentTools&&(tools.allow===void 0&&agentTools.allow!==void 0&&(tools.allow=agentTools.allow,changes.push(`Moved agent.tools.allow → tools.allow.`)),tools.deny===void 0&&agentTools.deny!==void 0&&(tools.deny=agentTools.deny,changes.push(`Moved agent.tools.deny → tools.deny.`)));let elevated=getRecord(agent.elevated);elevated&&(tools.elevated===void 0?(tools.elevated=elevated,changes.push(`Moved agent.elevated → tools.elevated.`)):changes.push(`Removed agent.elevated (tools.elevated already set).`));let bash=getRecord(agent.bash);bash&&(tools.exec===void 0?(tools.exec=bash,changes.push(`Moved agent.bash → tools.exec.`)):changes.push(`Removed agent.bash (tools.exec already set).`));let sandbox=getRecord(agent.sandbox);if(sandbox){let sandboxTools=getRecord(sandbox.tools);sandboxTools&&(mergeMissing(ensureRecord(ensureRecord(tools,`sandbox`),`tools`),sandboxTools),delete sandbox.tools,changes.push(`Moved agent.sandbox.tools → tools.sandbox.tools.`))}let subagents=getRecord(agent.subagents);if(subagents){let subagentTools=getRecord(subagents.tools);subagentTools&&(mergeMissing(ensureRecord(ensureRecord(tools,`subagents`),`tools`),subagentTools),delete subagents.tools,changes.push(`Moved agent.subagents.tools → tools.subagents.tools.`))}let agentCopy=structuredClone(agent);delete agentCopy.tools,delete agentCopy.elevated,delete agentCopy.bash,isRecord(agentCopy.sandbox)&&delete agentCopy.sandbox.tools,isRecord(agentCopy.subagents)&&delete agentCopy.subagents.tools,mergeMissing(defaults,agentCopy),agents.defaults=defaults,raw.agents=agents,delete raw.agent,changes.push(`Moved agent → agents.defaults.`)}},{id:`identity->agents.list`,describe:`Move identity to agents.list[].identity`,apply:(raw,changes)=>{let identity=getRecord(raw.identity);if(!identity)return;let agents=ensureRecord(raw,`agents`),list=getAgentsList(agents),defaultId=resolveDefaultAgentIdFromRaw(raw),entry=ensureAgentEntry(list,defaultId);entry.identity===void 0?(entry.identity=identity,changes.push(`Moved identity → agents.list (id "${defaultId}").identity.`)):changes.push(`Removed identity (agents.list identity already set).`),agents.list=list,raw.agents=agents,delete raw.identity}}];[...LEGACY_CONFIG_MIGRATIONS_PART_1,...LEGACY_CONFIG_MIGRATIONS_PART_2,...LEGACY_CONFIG_MIGRATIONS_PART_3];const LEGACY_CONFIG_RULES=[{path:[`whatsapp`],message:`whatsapp config moved to channels.whatsapp (auto-migrated on load).`},{path:[`telegram`],message:`telegram config moved to channels.telegram (auto-migrated on load).`},{path:[`discord`],message:`discord config moved to channels.discord (auto-migrated on load).`},{path:[`slack`],message:`slack config moved to channels.slack (auto-migrated on load).`},{path:[`signal`],message:`signal config moved to channels.signal (auto-migrated on load).`},{path:[`imessage`],message:`imessage config moved to channels.imessage (auto-migrated on load).`},{path:[`msteams`],message:`msteams config moved to channels.msteams (auto-migrated on load).`},{path:[`routing`,`allowFrom`],message:`routing.allowFrom was removed; use channels.whatsapp.allowFrom instead (auto-migrated on load).`},{path:[`routing`,`bindings`],message:`routing.bindings was moved; use top-level bindings instead (auto-migrated on load).`},{path:[`routing`,`agents`],message:`routing.agents was moved; use agents.list instead (auto-migrated on load).`},{path:[`routing`,`defaultAgentId`],message:`routing.defaultAgentId was moved; use agents.list[].default instead (auto-migrated on load).`},{path:[`routing`,`agentToAgent`],message:`routing.agentToAgent was moved; use tools.agentToAgent instead (auto-migrated on load).`},{path:[`routing`,`groupChat`,`requireMention`],message:`routing.groupChat.requireMention was removed; use channels.whatsapp/telegram/imessage groups defaults (e.g. channels.whatsapp.groups."*".requireMention) instead (auto-migrated on load).`},{path:[`routing`,`groupChat`,`mentionPatterns`],message:`routing.groupChat.mentionPatterns was moved; use agents.list[].groupChat.mentionPatterns or messages.groupChat.mentionPatterns instead (auto-migrated on load).`},{path:[`routing`,`queue`],message:`routing.queue was moved; use messages.queue instead (auto-migrated on load).`},{path:[`routing`,`transcribeAudio`],message:`routing.transcribeAudio was moved; use tools.media.audio.models instead (auto-migrated on load).`},{path:[`telegram`,`requireMention`],message:`telegram.requireMention was removed; use channels.telegram.groups."*".requireMention instead (auto-migrated on load).`},{path:[`identity`],message:`identity was moved; use agents.list[].identity instead (auto-migrated on load).`},{path:[`agent`],message:`agent.* was moved; use agents.defaults (and tools.* for tool/elevated/exec settings) instead (auto-migrated on load).`},{path:[`memorySearch`],message:`top-level memorySearch was moved; use agents.defaults.memorySearch instead (auto-migrated on load).`},{path:[`tools`,`bash`],message:`tools.bash was removed; use tools.exec instead (auto-migrated on load).`},{path:[`agent`,`model`],message:`agent.model string was replaced by agents.defaults.model.primary/fallbacks and agents.defaults.models (auto-migrated on load).`,match:value=>typeof value==`string`},{path:[`agent`,`imageModel`],message:`agent.imageModel string was replaced by agents.defaults.imageModel.primary/fallbacks (auto-migrated on load).`,match:value=>typeof value==`string`},{path:[`agent`,`allowedModels`],message:`agent.allowedModels was replaced by agents.defaults.models (auto-migrated on load).`},{path:[`agent`,`modelAliases`],message:`agent.modelAliases was replaced by agents.defaults.models.*.alias (auto-migrated on load).`},{path:[`agent`,`modelFallbacks`],message:`agent.modelFallbacks was replaced by agents.defaults.model.fallbacks (auto-migrated on load).`},{path:[`agent`,`imageModelFallbacks`],message:`agent.imageModelFallbacks was replaced by agents.defaults.imageModel.fallbacks (auto-migrated on load).`},{path:[`messages`,`tts`,`enabled`],message:`messages.tts.enabled was replaced by messages.tts.auto (auto-migrated on load).`},{path:[`gateway`,`token`],message:`gateway.token is ignored; use gateway.auth.token instead (auto-migrated on load).`}];function findLegacyConfigIssues(raw){if(!raw||typeof raw!=`object`)return[];let root=raw,issues=[];for(let rule of LEGACY_CONFIG_RULES){let cursor=root;for(let key of rule.path){if(!cursor||typeof cursor!=`object`){cursor=void 0;break}cursor=cursor[key]}cursor!==void 0&&(!rule.match||rule.match(cursor,root))&&issues.push({path:rule.path.join(`.`),message:rule.message})}return issues}function isObjectWithStringId(value){return isPlainObject$2(value)?typeof value.id==`string`&&value.id.length>0:!1}function mergeObjectArraysById(base,patch,options){if(!base.every(isObjectWithStringId))return;let merged=[...base],indexById=new Map;for(let[index,entry]of merged.entries()){if(!isObjectWithStringId(entry))return;indexById.set(entry.id,index)}for(let patchEntry of patch){if(!isObjectWithStringId(patchEntry)){merged.push(structuredClone(patchEntry));continue}let existingIndex=indexById.get(patchEntry.id);if(existingIndex===void 0){merged.push(structuredClone(patchEntry)),indexById.set(patchEntry.id,merged.length-1);continue}merged[existingIndex]=applyMergePatch(merged[existingIndex],patchEntry,options)}return merged}function applyMergePatch(base,patch,options={}){if(!isPlainObject$2(patch))return patch;let result=isPlainObject$2(base)?{...base}:{};for(let[key,value]of Object.entries(patch)){if(value===null){delete result[key];continue}if(options.mergeObjectArraysById&&Array.isArray(result[key])&&Array.isArray(value)){let mergedArray=mergeObjectArraysById(result[key],value,options);if(mergedArray){result[key]=mergedArray;continue}}if(isPlainObject$2(value)){let baseValue=result[key];result[key]=applyMergePatch(isPlainObject$2(baseValue)?baseValue:{},value,options);continue}result[key]=value}return result}const PATH_VALUE_RE=/^~(?=$|[\\/])/,PATH_KEY_RE=/(dir|path|paths|file|root|workspace)$/i,PATH_LIST_KEYS=new Set([`paths`,`pathPrepend`]);function normalizeStringValue(key,value){return!PATH_VALUE_RE.test(value.trim())||!key?value:PATH_KEY_RE.test(key)||PATH_LIST_KEYS.has(key)?resolveUserPath(value):value}function normalizeAny(key,value){if(typeof value==`string`)return normalizeStringValue(key,value);if(Array.isArray(value)){let normalizeChildren=!!(key&&PATH_LIST_KEYS.has(key));return value.map(entry=>typeof entry==`string`?normalizeChildren?normalizeStringValue(key,entry):entry:Array.isArray(entry)||isPlainObject$2(entry)?normalizeAny(void 0,entry):entry)}if(!isPlainObject$2(value))return value;for(let[childKey,childValue]of Object.entries(value)){let next=normalizeAny(childKey,childValue);next!==childValue&&(value[childKey]=next)}return value}function normalizeConfigPaths(cfg){return!cfg||typeof cfg!=`object`||normalizeAny(void 0,cfg),cfg}const BLOCKED_KEYS=new Set([`__proto__`,`prototype`,`constructor`]);function parseConfigPath(raw){let trimmed=raw.trim();if(!trimmed)return{ok:!1,error:`Invalid path. Use dot notation (e.g. foo.bar).`};let parts=trimmed.split(`.`).map(part=>part.trim());return parts.some(part=>!part)?{ok:!1,error:`Invalid path. Use dot notation (e.g. foo.bar).`}:parts.some(part=>BLOCKED_KEYS.has(part))?{ok:!1,error:`Invalid path segment.`}:{ok:!0,path:parts}}function setConfigValueAtPath(root,path,value){let cursor=root;for(let idx=0;idx<path.length-1;idx+=1){let key=path[idx],next=cursor[key];isPlainObject$2(next)||(cursor[key]={}),cursor=cursor[key]}cursor[path[path.length-1]]=value}function unsetConfigValueAtPath(root,path){let stack=[],cursor=root;for(let idx=0;idx<path.length-1;idx+=1){let key=path[idx],next=cursor[key];if(!isPlainObject$2(next))return!1;stack.push({node:cursor,key}),cursor=next}let leafKey=path[path.length-1];if(!(leafKey in cursor))return!1;delete cursor[leafKey];for(let idx=stack.length-1;idx>=0;--idx){let{node,key}=stack[idx],child=node[key];if(isPlainObject$2(child)&&Object.keys(child).length===0)delete node[key];else break}return!0}function getConfigValueAtPath(root,path){let cursor=root;for(let key of path){if(!isPlainObject$2(cursor))return;cursor=cursor[key]}return cursor}let overrides={};function mergeOverrides(base,override){if(!isPlainObject$2(base)||!isPlainObject$2(override))return override;let next={...base};for(let[key,value]of Object.entries(override))value!==void 0&&(next[key]=mergeOverrides(base[key],value));return next}function getConfigOverrides(){return overrides}function resetConfigOverrides(){overrides={}}function setConfigOverride(pathRaw,value){let parsed=parseConfigPath(pathRaw);return!parsed.ok||!parsed.path?{ok:!1,error:parsed.error??`Invalid path.`}:(setConfigValueAtPath(overrides,parsed.path,value),{ok:!0})}function unsetConfigOverride(pathRaw){let parsed=parseConfigPath(pathRaw);return!parsed.ok||!parsed.path?{ok:!1,removed:!1,error:parsed.error??`Invalid path.`}:{ok:!0,removed:unsetConfigValueAtPath(overrides,parsed.path)}}function applyConfigOverrides(cfg){return!overrides||Object.keys(overrides).length===0?cfg:mergeOverrides(cfg,overrides)}const DEFAULT_SLOT_BY_KEY={memory:`memory-core`};function defaultSlotIdForKey(slotKey){return DEFAULT_SLOT_BY_KEY[slotKey]}const BUNDLED_ENABLED_BY_DEFAULT=new Set([`device-pair`,`phone-control`,`talk-voice`]),normalizeList=value=>Array.isArray(value)?value.map(entry=>typeof entry==`string`?entry.trim():``).filter(Boolean):[],normalizeSlotValue=value=>{if(typeof value!=`string`)return;let trimmed=value.trim();if(trimmed)return trimmed.toLowerCase()===`none`?null:trimmed},normalizePluginEntries=entries=>{if(!entries||typeof entries!=`object`||Array.isArray(entries))return{};let normalized={};for(let[key,value]of Object.entries(entries)){if(!key.trim())continue;if(!value||typeof value!=`object`||Array.isArray(value)){normalized[key]={};continue}let entry=value;normalized[key]={enabled:typeof entry.enabled==`boolean`?entry.enabled:void 0,config:`config`in entry?entry.config:void 0}}return normalized},normalizePluginsConfig=config=>{let memorySlot=normalizeSlotValue(config?.slots?.memory);return{enabled:config?.enabled!==!1,allow:normalizeList(config?.allow),deny:normalizeList(config?.deny),loadPaths:normalizeList(config?.load?.paths),slots:{memory:memorySlot===void 0?defaultSlotIdForKey(`memory`):memorySlot},entries:normalizePluginEntries(config?.entries)}},hasExplicitMemorySlot=plugins=>!!(plugins?.slots&&Object.prototype.hasOwnProperty.call(plugins.slots,`memory`)),hasExplicitMemoryEntry=plugins=>!!(plugins?.entries&&Object.prototype.hasOwnProperty.call(plugins.entries,`memory-core`)),hasExplicitPluginConfig=plugins=>plugins?!!(typeof plugins.enabled==`boolean`||Array.isArray(plugins.allow)&&plugins.allow.length>0||Array.isArray(plugins.deny)&&plugins.deny.length>0||plugins.load?.paths&&Array.isArray(plugins.load.paths)&&plugins.load.paths.length>0||plugins.slots&&Object.keys(plugins.slots).length>0||plugins.entries&&Object.keys(plugins.entries).length>0):!1;function applyTestPluginDefaults(cfg,env=process.env){if(!env.VITEST)return cfg;let plugins=cfg.plugins;return hasExplicitPluginConfig(plugins)?hasExplicitMemorySlot(plugins)||hasExplicitMemoryEntry(plugins)?cfg:{...cfg,plugins:{...plugins,slots:{...plugins?.slots,memory:`none`}}}:{...cfg,plugins:{...plugins,enabled:!1,slots:{...plugins?.slots,memory:`none`}}}}function resolveEnableState(id,origin,config){if(!config.enabled)return{enabled:!1,reason:`plugins disabled`};if(config.deny.includes(id))return{enabled:!1,reason:`blocked by denylist`};if(config.allow.length>0&&!config.allow.includes(id))return{enabled:!1,reason:`not in allowlist`};if(config.slots.memory===id)return{enabled:!0};let entry=config.entries[id];return entry?.enabled===!0?{enabled:!0}:entry?.enabled===!1?{enabled:!1,reason:`disabled in config`}:origin===`bundled`&&BUNDLED_ENABLED_BY_DEFAULT.has(id)?{enabled:!0}:origin===`bundled`?{enabled:!1,reason:`bundled (disabled by default)`}:{enabled:!0}}function resolveMemorySlotDecision(params){return params.kind===`memory`?params.slot===null?{enabled:!1,reason:`memory slot disabled`}:typeof params.slot==`string`?params.slot===params.id?{enabled:!0,selected:!0}:{enabled:!1,reason:`memory slot set to "${params.slot}"`}:params.selectedId&¶ms.selectedId!==params.id?{enabled:!1,reason:`memory slot already filled by "${params.selectedId}"`}:{enabled:!0,selected:!0}:{enabled:!0}}function resolveBundledPluginsDir(){let override=process.env.BUILDERFORCE_AGENTS_BUNDLED_PLUGINS_DIR?.trim();if(override)return override;try{let execDir=path.dirname(process.execPath),sibling=path.join(execDir,`extensions`);if(fs.existsSync(sibling))return sibling}catch{}try{let cursor=path.dirname(fileURLToPath(import.meta.url));for(let i=0;i<6;i+=1){let candidate=path.join(cursor,`extensions`);if(fs.existsSync(candidate))return candidate;let parent=path.dirname(cursor);if(parent===cursor)break;cursor=parent}}catch{}}const LEGACY_PROJECT_NAMES=[`builderforce`],MANIFEST_KEY=`builderforce`,LEGACY_MANIFEST_KEYS=LEGACY_PROJECT_NAMES,PLUGIN_MANIFEST_FILENAME=`builderforce.plugin.json`,PLUGIN_MANIFEST_FILENAMES=[PLUGIN_MANIFEST_FILENAME];function normalizeStringList(value){return Array.isArray(value)?value.map(entry=>typeof entry==`string`?entry.trim():``).filter(Boolean):[]}function resolvePluginManifestPath(rootDir){for(let filename of PLUGIN_MANIFEST_FILENAMES){let candidate=path.join(rootDir,filename);if(fs.existsSync(candidate))return candidate}return path.join(rootDir,PLUGIN_MANIFEST_FILENAME)}function loadPluginManifest(rootDir){let manifestPath=resolvePluginManifestPath(rootDir);if(!fs.existsSync(manifestPath))return{ok:!1,error:`plugin manifest not found: ${manifestPath}`,manifestPath};let raw;try{raw=JSON.parse(fs.readFileSync(manifestPath,`utf-8`))}catch(err){return{ok:!1,error:`failed to parse plugin manifest: ${String(err)}`,manifestPath}}if(!isRecord(raw))return{ok:!1,error:`plugin manifest must be an object`,manifestPath};let id=typeof raw.id==`string`?raw.id.trim():``;if(!id)return{ok:!1,error:`plugin manifest requires id`,manifestPath};let configSchema=isRecord(raw.configSchema)?raw.configSchema:null;if(!configSchema)return{ok:!1,error:`plugin manifest requires configSchema`,manifestPath};let kind=typeof raw.kind==`string`?raw.kind:void 0,name=typeof raw.name==`string`?raw.name.trim():void 0,description=typeof raw.description==`string`?raw.description.trim():void 0,version=typeof raw.version==`string`?raw.version.trim():void 0,channels=normalizeStringList(raw.channels),providers=normalizeStringList(raw.providers),skills=normalizeStringList(raw.skills),hooks=normalizeStringList(raw.hooks),uiHints;return isRecord(raw.uiHints)&&(uiHints=raw.uiHints),{ok:!0,manifest:{id,configSchema,kind,channels,providers,skills,hooks,name,description,version,uiHints},manifestPath}}function getPackageManifestMetadata(manifest){if(!manifest)return;let current=manifest[MANIFEST_KEY];if(current!==void 0)return current;for(let legacyKey of LEGACY_MANIFEST_KEYS){let legacy=manifest[legacyKey];if(legacy!==void 0)return legacy}}const EXTENSION_EXTS=new Set([`.ts`,`.js`,`.mts`,`.cts`,`.mjs`,`.cjs`]);function isExtensionFile(filePath){let ext=path.extname(filePath);return EXTENSION_EXTS.has(ext)?!filePath.endsWith(`.d.ts`):!1}function readPackageManifest(dir){let manifestPath=path.join(dir,`package.json`);if(!fs.existsSync(manifestPath))return null;try{let raw=fs.readFileSync(manifestPath,`utf-8`);return JSON.parse(raw)}catch{return null}}function resolvePackageExtensions(manifest){let raw=getPackageManifestMetadata(manifest)?.extensions;return Array.isArray(raw)?raw.map(entry=>typeof entry==`string`?entry.trim():``).filter(Boolean):[]}function deriveIdHint(params){let base=path.basename(params.filePath,path.extname(params.filePath)),rawPackageName=params.packageName?.trim();if(!rawPackageName)return base;let unscoped=rawPackageName.includes(`/`)?rawPackageName.split(`/`).pop()??rawPackageName:rawPackageName;return params.hasMultipleExtensions?`${unscoped}/${base}`:unscoped}function addCandidate(params){let resolved=path.resolve(params.source);if(params.seen.has(resolved))return;params.seen.add(resolved);let manifest=params.manifest??null;params.candidates.push({idHint:params.idHint,source:resolved,rootDir:path.resolve(params.rootDir),origin:params.origin,workspaceDir:params.workspaceDir,packageName:manifest?.name?.trim()||void 0,packageVersion:manifest?.version?.trim()||void 0,packageDescription:manifest?.description?.trim()||void 0,packageDir:params.packageDir,packageManifest:getPackageManifestMetadata(manifest??void 0)})}function discoverInDirectory(params){if(!fs.existsSync(params.dir))return;let entries=[];try{entries=fs.readdirSync(params.dir,{withFileTypes:!0})}catch(err){params.diagnostics.push({level:`warn`,message:`failed to read extensions dir: ${params.dir} (${String(err)})`,source:params.dir});return}for(let entry of entries){let fullPath=path.join(params.dir,entry.name);if(entry.isFile()){if(!isExtensionFile(fullPath))continue;addCandidate({candidates:params.candidates,seen:params.seen,idHint:path.basename(entry.name,path.extname(entry.name)),source:fullPath,rootDir:path.dirname(fullPath),origin:params.origin,workspaceDir:params.workspaceDir})}if(!entry.isDirectory())continue;let manifest=readPackageManifest(fullPath),extensions=manifest?resolvePackageExtensions(manifest):[];if(extensions.length>0){for(let extPath of extensions){let resolved=path.resolve(fullPath,extPath);addCandidate({candidates:params.candidates,seen:params.seen,idHint:deriveIdHint({filePath:resolved,packageName:manifest?.name,hasMultipleExtensions:extensions.length>1}),source:resolved,rootDir:fullPath,origin:params.origin,workspaceDir:params.workspaceDir,manifest,packageDir:fullPath})}continue}let indexFile=[`index.ts`,`index.js`,`index.mjs`,`index.cjs`].map(candidate=>path.join(fullPath,candidate)).find(candidate=>fs.existsSync(candidate));indexFile&&isExtensionFile(indexFile)&&addCandidate({candidates:params.candidates,seen:params.seen,idHint:entry.name,source:indexFile,rootDir:fullPath,origin:params.origin,workspaceDir:params.workspaceDir,manifest,packageDir:fullPath})}}function discoverFromPath(params){let resolved=resolveUserPath(params.rawPath);if(!fs.existsSync(resolved)){params.diagnostics.push({level:`error`,message:`plugin path not found: ${resolved}`,source:resolved});return}let stat=fs.statSync(resolved);if(stat.isFile()){if(!isExtensionFile(resolved)){params.diagnostics.push({level:`error`,message:`plugin path is not a supported file: ${resolved}`,source:resolved});return}addCandidate({candidates:params.candidates,seen:params.seen,idHint:path.basename(resolved,path.extname(resolved)),source:resolved,rootDir:path.dirname(resolved),origin:params.origin,workspaceDir:params.workspaceDir});return}if(stat.isDirectory()){let manifest=readPackageManifest(resolved),extensions=manifest?resolvePackageExtensions(manifest):[];if(extensions.length>0){for(let extPath of extensions){let source=path.resolve(resolved,extPath);addCandidate({candidates:params.candidates,seen:params.seen,idHint:deriveIdHint({filePath:source,packageName:manifest?.name,hasMultipleExtensions:extensions.length>1}),source,rootDir:resolved,origin:params.origin,workspaceDir:params.workspaceDir,manifest,packageDir:resolved})}return}let indexFile=[`index.ts`,`index.js`,`index.mjs`,`index.cjs`].map(candidate=>path.join(resolved,candidate)).find(candidate=>fs.existsSync(candidate));if(indexFile&&isExtensionFile(indexFile)){addCandidate({candidates:params.candidates,seen:params.seen,idHint:path.basename(resolved),source:indexFile,rootDir:resolved,origin:params.origin,workspaceDir:params.workspaceDir,manifest,packageDir:resolved});return}discoverInDirectory({dir:resolved,origin:params.origin,workspaceDir:params.workspaceDir,candidates:params.candidates,diagnostics:params.diagnostics,seen:params.seen});return}}function discoverBuilderForceAgentsPlugins(params){let candidates=[],diagnostics=[],seen=new Set,workspaceDir=params.workspaceDir?.trim(),extra=params.extraPaths??[];for(let extraPath of extra){if(typeof extraPath!=`string`)continue;let trimmed=extraPath.trim();trimmed&&discoverFromPath({rawPath:trimmed,origin:`config`,workspaceDir:workspaceDir?.trim()||void 0,candidates,diagnostics,seen})}if(workspaceDir){let workspaceRoot=resolveUserPath(workspaceDir),workspaceExtDirs=[path.join(workspaceRoot,`.builderforce`,`extensions`)];for(let dir of workspaceExtDirs)discoverInDirectory({dir,origin:`workspace`,workspaceDir:workspaceRoot,candidates,diagnostics,seen})}discoverInDirectory({dir:path.join(resolveConfigDir(),`extensions`),origin:`global`,candidates,diagnostics,seen});let bundledDir=resolveBundledPluginsDir();return bundledDir&&discoverInDirectory({dir:bundledDir,origin:`bundled`,candidates,diagnostics,seen}),{candidates,diagnostics}}const PLUGIN_ORIGIN_RANK={config:0,workspace:1,global:2,bundled:3};function safeRealpathSync(rootDir,cache){let cached=cache.get(rootDir);if(cached)return cached;try{let resolved=fs.realpathSync(rootDir);return cache.set(rootDir,resolved),resolved}catch{return null}}const registryCache=new Map;function resolveManifestCacheMs(env){let raw=env.BUILDERFORCE_AGENTS_PLUGIN_MANIFEST_CACHE_MS?.trim();if(raw===``||raw===`0`)return 0;if(!raw)return 200;let parsed=Number.parseInt(raw,10);return Number.isFinite(parsed)?Math.max(0,parsed):200}function shouldUseManifestCache(env){return env.BUILDERFORCE_AGENTS_DISABLE_PLUGIN_MANIFEST_CACHE?.trim()?!1:resolveManifestCacheMs(env)>0}function buildCacheKey(params){let workspaceKey=params.workspaceDir?resolveUserPath(params.workspaceDir):``,loadPaths=params.plugins.loadPaths.map(p=>resolveUserPath(p)).map(p=>p.trim()).filter(Boolean).toSorted();return`${workspaceKey}::${JSON.stringify(loadPaths)}`}function safeStatMtimeMs(filePath){try{return fs.statSync(filePath).mtimeMs}catch{return null}}function normalizeManifestLabel(raw){return raw?.trim()||void 0}function buildRecord(params){return{id:params.manifest.id,name:normalizeManifestLabel(params.manifest.name)??params.candidate.packageName,description:normalizeManifestLabel(params.manifest.description)??params.candidate.packageDescription,version:normalizeManifestLabel(params.manifest.version)??params.candidate.packageVersion,kind:params.manifest.kind,channels:params.manifest.channels??[],providers:params.manifest.providers??[],skills:params.manifest.skills??[],hooks:params.manifest.hooks??[],origin:params.candidate.origin,workspaceDir:params.candidate.workspaceDir,rootDir:params.candidate.rootDir,source:params.candidate.source,manifestPath:params.manifestPath,schemaCacheKey:params.schemaCacheKey,configSchema:params.configSchema,configUiHints:params.manifest.uiHints}}function loadPluginManifestRegistry(params){let normalized=normalizePluginsConfig((params.config??{}).plugins),cacheKey=buildCacheKey({workspaceDir:params.workspaceDir,plugins:normalized}),env=params.env??process.env,cacheEnabled=params.cache!==!1&&shouldUseManifestCache(env);if(cacheEnabled){let cached=registryCache.get(cacheKey);if(cached&&cached.expiresAt>Date.now())return cached.registry}let discovery=params.candidates?{candidates:params.candidates,diagnostics:params.diagnostics??[]}:discoverBuilderForceAgentsPlugins({workspaceDir:params.workspaceDir,extraPaths:normalized.loadPaths}),diagnostics=[...discovery.diagnostics],candidates=discovery.candidates,records=[],seenIds=new Map,realpathCache=new Map;for(let candidate of candidates){let manifestRes=loadPluginManifest(candidate.rootDir);if(!manifestRes.ok){diagnostics.push({level:`error`,message:manifestRes.error,source:manifestRes.manifestPath});continue}let manifest=manifestRes.manifest;candidate.idHint&&candidate.idHint!==manifest.id&&diagnostics.push({level:`warn`,pluginId:manifest.id,source:candidate.source,message:`plugin id mismatch (manifest uses "${manifest.id}", entry hints "${candidate.idHint}")`});let configSchema=manifest.configSchema,manifestMtime=safeStatMtimeMs(manifestRes.manifestPath),schemaCacheKey=manifestMtime?`${manifestRes.manifestPath}:${manifestMtime}`:manifestRes.manifestPath,existing=seenIds.get(manifest.id);if(existing){let existingReal=safeRealpathSync(existing.candidate.rootDir,realpathCache),candidateReal=safeRealpathSync(candidate.rootDir,realpathCache);if(existingReal&&candidateReal&&existingReal===candidateReal){PLUGIN_ORIGIN_RANK[candidate.origin]<PLUGIN_ORIGIN_RANK[existing.candidate.origin]&&(records[existing.recordIndex]=buildRecord({manifest,candidate,manifestPath:manifestRes.manifestPath,schemaCacheKey,configSchema}),seenIds.set(manifest.id,{candidate,recordIndex:existing.recordIndex}));continue}diagnostics.push({level:`warn`,pluginId:manifest.id,source:candidate.source,message:`duplicate plugin id detected; later plugin may be overridden (${candidate.source})`})}else seenIds.set(manifest.id,{candidate,recordIndex:records.length});records.push(buildRecord({manifest,candidate,manifestPath:manifestRes.manifestPath,schemaCacheKey,configSchema}))}let registry={plugins:records,diagnostics};if(cacheEnabled){let ttl=resolveManifestCacheMs(env);ttl>0&®istryCache.set(cacheKey,{expiresAt:Date.now()+ttl,registry})}return registry}const ajv=new AjvPkg({allErrors:!0,strict:!1,removeAdditional:!1}),schemaCache=new Map;function formatAjvErrors(errors){return!errors||errors.length===0?[`invalid config`]:errors.map(error=>`${error.instancePath?.replace(/^\//,``).replace(/\//g,`.`)||`<root>`}: ${error.message??`invalid`}`)}function validateJsonSchemaValue(params){let cached=schemaCache.get(params.cacheKey);return(!cached||cached.schema!==params.schema)&&(cached={validate:ajv.compile(params.schema),schema:params.schema},schemaCache.set(params.cacheKey,cached)),cached.validate(params.value)?{ok:!0}:{ok:!1,errors:formatAjvErrors(cached.validate.errors)}}const AgentDefaultsSchema=z.object({model:z.object({primary:z.string().optional(),fallbacks:z.array(z.string()).optional()}).strict().optional(),imageModel:z.object({primary:z.string().optional(),fallbacks:z.array(z.string()).optional()}).strict().optional(),models:z.record(z.string(),z.object({alias:z.string().optional(),params:z.record(z.string(),z.unknown()).optional(),streaming:z.boolean().optional()}).strict()).optional(),workspace:z.string().optional(),repoRoot:z.string().optional(),skipBootstrap:z.boolean().optional(),bootstrapMaxChars:z.number().int().positive().optional(),bootstrapTotalMaxChars:z.number().int().positive().optional(),userTimezone:z.string().optional(),timeFormat:z.union([z.literal(`auto`),z.literal(`12`),z.literal(`24`)]).optional(),envelopeTimezone:z.string().optional(),envelopeTimestamp:z.union([z.literal(`on`),z.literal(`off`)]).optional(),envelopeElapsed:z.union([z.literal(`on`),z.literal(`off`)]).optional(),contextTokens:z.number().int().positive().optional(),cliBackends:z.record(z.string(),CliBackendSchema).optional(),memorySearch:MemorySearchSchema,contextPruning:z.object({mode:z.union([z.literal(`off`),z.literal(`cache-ttl`)]).optional(),ttl:z.string().optional(),keepLastAssistants:z.number().int().nonnegative().optional(),softTrimRatio:z.number().min(0).max(1).optional(),hardClearRatio:z.number().min(0).max(1).optional(),minPrunableToolChars:z.number().int().nonnegative().optional(),tools:z.object({allow:z.array(z.string()).optional(),deny:z.array(z.string()).optional()}).strict().optional(),softTrim:z.object({maxChars:z.number().int().nonnegative().optional(),headChars:z.number().int().nonnegative().optional(),tailChars:z.number().int().nonnegative().optional()}).strict().optional(),hardClear:z.object({enabled:z.boolean().optional(),placeholder:z.string().optional()}).strict().optional()}).strict().optional(),compaction:z.object({mode:z.union([z.literal(`default`),z.literal(`safeguard`)]).optional(),reserveTokensFloor:z.number().int().nonnegative().optional(),maxHistoryShare:z.number().min(.1).max(.9).optional(),memoryFlush:z.object({enabled:z.boolean().optional(),softThresholdTokens:z.number().int().nonnegative().optional(),prompt:z.string().optional(),systemPrompt:z.string().optional()}).strict().optional()}).strict().optional(),thinkingDefault:z.union([z.literal(`off`),z.literal(`minimal`),z.literal(`low`),z.literal(`medium`),z.literal(`high`),z.literal(`xhigh`)]).optional(),verboseDefault:z.union([z.literal(`off`),z.literal(`on`),z.literal(`full`)]).optional(),elevatedDefault:z.union([z.literal(`off`),z.literal(`on`),z.literal(`ask`),z.literal(`full`)]).optional(),blockStreamingDefault:z.union([z.literal(`off`),z.literal(`on`)]).optional(),blockStreamingBreak:z.union([z.literal(`text_end`),z.literal(`message_end`)]).optional(),blockStreamingChunk:BlockStreamingChunkSchema.optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),humanDelay:HumanDelaySchema.optional(),timeoutSeconds:z.number().int().positive().optional(),maxAutoContinueNudges:z.number().int().positive().optional(),mediaMaxMb:z.number().positive().optional(),imageMaxDimensionPx:z.number().int().positive().optional(),typingIntervalSeconds:z.number().int().positive().optional(),typingMode:z.union([z.literal(`never`),z.literal(`instant`),z.literal(`thinking`),z.literal(`message`)]).optional(),heartbeat:HeartbeatSchema,maxConcurrent:z.number().int().positive().optional(),subagents:z.object({maxConcurrent:z.number().int().positive().optional(),maxSpawnDepth:z.number().int().min(1).max(5).optional().describe(`Maximum nesting depth for sub-agent spawning. 1 = no nesting (default), 2 = sub-agents can spawn sub-sub-agents.`),maxChildrenPerAgent:z.number().int().min(1).max(20).optional().describe(`Maximum number of active children a single agent session can spawn (default: 5).`),archiveAfterMinutes:z.number().int().positive().optional(),model:AgentModelSchema.optional(),thinking:z.string().optional()}).strict().optional(),sandbox:AgentSandboxSchema}).strict().optional(),AgentsSchema=z.object({defaults:z.lazy(()=>AgentDefaultsSchema).optional(),list:z.array(AgentEntrySchema).optional()}).strict().optional(),BindingsSchema=z.array(z.object({agentId:z.string(),match:z.object({channel:z.string(),accountId:z.string().optional(),peer:z.object({kind:z.union([z.literal(`direct`),z.literal(`group`),z.literal(`channel`),z.literal(`dm`)]),id:z.string()}).strict().optional(),guildId:z.string().optional(),teamId:z.string().optional(),roles:z.array(z.string()).optional()}).strict()}).strict()).optional(),BroadcastStrategySchema=z.enum([`parallel`,`sequential`]),BroadcastSchema=z.object({strategy:BroadcastStrategySchema.optional()}).catchall(z.array(z.string())).optional(),AudioSchema=z.object({transcription:TranscribeAudioSchema}).strict().optional(),ExecApprovalForwardTargetSchema=z.object({channel:z.string().min(1),to:z.string().min(1),accountId:z.string().optional(),threadId:z.union([z.string(),z.number()]).optional()}).strict(),ExecApprovalForwardingSchema=z.object({enabled:z.boolean().optional(),mode:z.union([z.literal(`session`),z.literal(`targets`),z.literal(`both`)]).optional(),agentFilter:z.array(z.string()).optional(),sessionFilter:z.array(z.string()).optional(),targets:z.array(ExecApprovalForwardTargetSchema).optional()}).strict().optional(),ApprovalsSchema=z.object({exec:ExecApprovalForwardingSchema}).strict().optional(),InstallRecordShape={source:z.union([z.literal(`npm`),z.literal(`archive`),z.literal(`path`)]),spec:z.string().optional(),sourcePath:z.string().optional(),installPath:z.string().optional(),version:z.string().optional(),installedAt:z.string().optional()};function isSafeRelativeModulePath(raw){let value=raw.trim();return!(!value||path.isAbsolute(value)||value.startsWith(`~`)||value.includes(`:`)||value.split(/[\\/]+/g).some(part=>part===`..`))}const SafeRelativeModulePathSchema=z.string().refine(isSafeRelativeModulePath,`module must be a safe relative path (no absolute paths)`),HookMappingSchema=z.object({id:z.string().optional(),match:z.object({path:z.string().optional(),source:z.string().optional()}).optional(),action:z.union([z.literal(`wake`),z.literal(`agent`)]).optional(),wakeMode:z.union([z.literal(`now`),z.literal(`next-heartbeat`)]).optional(),name:z.string().optional(),agentId:z.string().optional(),sessionKey:z.string().optional().register(sensitive),messageTemplate:z.string().optional(),textTemplate:z.string().optional(),deliver:z.boolean().optional(),allowUnsafeExternalContent:z.boolean().optional(),channel:z.union([z.literal(`last`),z.literal(`whatsapp`),z.literal(`telegram`),z.literal(`discord`),z.literal(`irc`),z.literal(`slack`),z.literal(`signal`),z.literal(`imessage`),z.literal(`msteams`)]).optional(),to:z.string().optional(),model:z.string().optional(),thinking:z.string().optional(),timeoutSeconds:z.number().int().positive().optional(),transform:z.object({module:SafeRelativeModulePathSchema,export:z.string().optional()}).strict().optional()}).strict().optional(),InternalHookHandlerSchema=z.object({event:z.string(),module:SafeRelativeModulePathSchema,export:z.string().optional()}).strict(),HookConfigSchema=z.object({enabled:z.boolean().optional(),env:z.record(z.string(),z.string()).optional()}).passthrough(),HookInstallRecordSchema=z.object({...InstallRecordShape,hooks:z.array(z.string()).optional()}).strict(),InternalHooksSchema=z.object({enabled:z.boolean().optional(),handlers:z.array(InternalHookHandlerSchema).optional(),entries:z.record(z.string(),HookConfigSchema).optional(),load:z.object({extraDirs:z.array(z.string()).optional()}).strict().optional(),installs:z.record(z.string(),HookInstallRecordSchema).optional()}).strict().optional(),HooksGmailSchema=z.object({account:z.string().optional(),label:z.string().optional(),topic:z.string().optional(),subscription:z.string().optional(),pushToken:z.string().optional().register(sensitive),hookUrl:z.string().optional(),includeBody:z.boolean().optional(),maxBytes:z.number().int().positive().optional(),renewEveryMinutes:z.number().int().positive().optional(),allowUnsafeExternalContent:z.boolean().optional(),serve:z.object({bind:z.string().optional(),port:z.number().int().positive().optional(),path:z.string().optional()}).strict().optional(),tailscale:z.object({mode:z.union([z.literal(`off`),z.literal(`serve`),z.literal(`funnel`)]).optional(),path:z.string().optional(),target:z.string().optional()}).strict().optional(),model:z.string().optional(),thinking:z.union([z.literal(`off`),z.literal(`minimal`),z.literal(`low`),z.literal(`medium`),z.literal(`high`)]).optional()}).strict().optional(),ChannelsSchema=z.object({defaults:z.object({groupPolicy:GroupPolicySchema.optional(),heartbeat:ChannelHeartbeatVisibilitySchema}).strict().optional(),whatsapp:WhatsAppConfigSchema.optional(),telegram:TelegramConfigSchema.optional(),discord:DiscordConfigSchema.optional(),irc:IrcConfigSchema.optional(),googlechat:GoogleChatConfigSchema.optional(),slack:SlackConfigSchema.optional(),signal:SignalConfigSchema.optional(),imessage:IMessageConfigSchema.optional(),bluebubbles:BlueBubblesConfigSchema.optional(),msteams:MSTeamsConfigSchema.optional()}).passthrough().optional(),UNIT_MULTIPLIERS={b:1,kb:1024,k:1024,mb:1024**2,m:1024**2,gb:1024**3,g:1024**3,tb:1024**4,t:1024**4};function parseByteSize(raw,opts){let trimmed=String(raw??``).trim().toLowerCase();if(!trimmed)throw Error(`invalid byte size (empty)`);let m=/^(\d+(?:\.\d+)?)([a-z]+)?$/.exec(trimmed);if(!m)throw Error(`invalid byte size: ${raw}`);let value=Number(m[1]);if(!Number.isFinite(value)||value<0)throw Error(`invalid byte size: ${raw}`);let multiplier=UNIT_MULTIPLIERS[(m[2]??opts?.defaultUnit??`b`).toLowerCase()];if(!multiplier)throw Error(`invalid byte size unit: ${raw}`);let bytes=Math.round(value*multiplier);if(!Number.isFinite(bytes))throw Error(`invalid byte size: ${raw}`);return bytes}const SessionResetConfigSchema=z.object({mode:z.union([z.literal(`daily`),z.literal(`idle`)]).optional(),atHour:z.number().int().min(0).max(23).optional(),idleMinutes:z.number().int().positive().optional()}).strict(),SessionSendPolicySchema=createAllowDenyChannelRulesSchema(),SessionSchema=z.object({scope:z.union([z.literal(`per-sender`),z.literal(`global`)]).optional(),dmScope:z.union([z.literal(`main`),z.literal(`per-peer`),z.literal(`per-channel-peer`),z.literal(`per-account-channel-peer`)]).optional(),identityLinks:z.record(z.string(),z.array(z.string())).optional(),resetTriggers:z.array(z.string()).optional(),idleMinutes:z.number().int().positive().optional(),reset:SessionResetConfigSchema.optional(),resetByType:z.object({direct:SessionResetConfigSchema.optional(),dm:SessionResetConfigSchema.optional(),group:SessionResetConfigSchema.optional(),thread:SessionResetConfigSchema.optional()}).strict().optional(),resetByChannel:z.record(z.string(),SessionResetConfigSchema).optional(),store:z.string().optional(),typingIntervalSeconds:z.number().int().positive().optional(),typingMode:z.union([z.literal(`never`),z.literal(`instant`),z.literal(`thinking`),z.literal(`message`)]).optional(),mainKey:z.string().optional(),sendPolicy:SessionSendPolicySchema.optional(),agentToAgent:z.object({maxPingPongTurns:z.number().int().min(0).max(5).optional()}).strict().optional(),maintenance:z.object({mode:z.enum([`enforce`,`warn`]).optional(),pruneAfter:z.union([z.string(),z.number()]).optional(),pruneDays:z.number().int().positive().optional(),maxEntries:z.number().int().positive().optional(),rotateBytes:z.union([z.string(),z.number()]).optional()}).strict().superRefine((val,ctx)=>{if(val.pruneAfter!==void 0)try{parseDurationMs(String(val.pruneAfter).trim(),{defaultUnit:`d`})}catch{ctx.addIssue({code:z.ZodIssueCode.custom,path:[`pruneAfter`],message:`invalid duration (use ms, s, m, h, d)`})}if(val.rotateBytes!==void 0)try{parseByteSize(String(val.rotateBytes).trim(),{defaultUnit:`b`})}catch{ctx.addIssue({code:z.ZodIssueCode.custom,path:[`rotateBytes`],message:`invalid size (use b, kb, mb, gb, tb)`})}}).optional()}).strict().optional(),MessagesSchema=z.object({messagePrefix:z.string().optional(),responsePrefix:z.string().optional(),groupChat:GroupChatSchema,queue:QueueSchema,inbound:InboundDebounceSchema,ackReaction:z.string().optional(),ackReactionScope:z.enum([`group-mentions`,`group-all`,`direct`,`all`]).optional(),removeAckAfterReply:z.boolean().optional(),suppressToolErrors:z.boolean().optional(),tts:TtsConfigSchema}).strict().optional(),CommandsSchema=z.object({native:NativeCommandsSettingSchema.optional().default(`auto`),nativeSkills:NativeCommandsSettingSchema.optional().default(`auto`),text:z.boolean().optional(),bash:z.boolean().optional(),bashForegroundMs:z.number().int().min(0).max(3e4).optional(),config:z.boolean().optional(),debug:z.boolean().optional(),restart:z.boolean().optional(),useAccessGroups:z.boolean().optional(),ownerAllowFrom:z.array(z.union([z.string(),z.number()])).optional(),allowFrom:ElevatedAllowFromSchema.optional()}).strict().optional().default({native:`auto`,nativeSkills:`auto`}),BrowserSnapshotDefaultsSchema=z.object({mode:z.literal(`efficient`).optional()}).strict().optional(),NodeHostSchema=z.object({browserProxy:z.object({enabled:z.boolean().optional(),allowProfiles:z.array(z.string()).optional()}).strict().optional()}).strict().optional(),MemoryQmdPathSchema=z.object({path:z.string(),name:z.string().optional(),pattern:z.string().optional()}).strict(),MemoryQmdSessionSchema=z.object({enabled:z.boolean().optional(),exportDir:z.string().optional(),retentionDays:z.number().int().nonnegative().optional()}).strict(),MemoryQmdUpdateSchema=z.object({interval:z.string().optional(),debounceMs:z.number().int().nonnegative().optional(),onBoot:z.boolean().optional(),waitForBootSync:z.boolean().optional(),embedInterval:z.string().optional(),commandTimeoutMs:z.number().int().nonnegative().optional(),updateTimeoutMs:z.number().int().nonnegative().optional(),embedTimeoutMs:z.number().int().nonnegative().optional()}).strict(),MemoryQmdLimitsSchema=z.object({maxResults:z.number().int().positive().optional(),maxSnippetChars:z.number().int().positive().optional(),maxInjectedChars:z.number().int().positive().optional(),timeoutMs:z.number().int().nonnegative().optional()}).strict(),MemoryQmdSchema=z.object({command:z.string().optional(),searchMode:z.union([z.literal(`query`),z.literal(`search`),z.literal(`vsearch`)]).optional(),includeDefaultMemory:z.boolean().optional(),paths:z.array(MemoryQmdPathSchema).optional(),sessions:MemoryQmdSessionSchema.optional(),update:MemoryQmdUpdateSchema.optional(),limits:MemoryQmdLimitsSchema.optional(),scope:SessionSendPolicySchema.optional()}).strict(),MemorySchema=z.object({backend:z.union([z.literal(`builtin`),z.literal(`qmd`)]).optional(),citations:z.union([z.literal(`auto`),z.literal(`on`),z.literal(`off`)]).optional(),qmd:MemoryQmdSchema.optional()}).strict().optional(),HttpUrlSchema=z.string().url().refine(value=>{let protocol=new URL(value).protocol;return protocol===`http:`||protocol===`https:`},`Expected http:// or https:// URL`),BuilderForceAgentsSchema=z.object({$schema:z.string().optional(),meta:z.object({lastTouchedVersion:z.string().optional(),lastTouchedAt:z.string().optional()}).strict().optional(),env:z.object({shellEnv:z.object({enabled:z.boolean().optional(),timeoutMs:z.number().int().nonnegative().optional()}).strict().optional(),vars:z.record(z.string(),z.string()).optional()}).catchall(z.string()).optional(),wizard:z.object({lastRunAt:z.string().optional(),lastRunVersion:z.string().optional(),lastRunCommit:z.string().optional(),lastRunCommand:z.string().optional(),lastRunMode:z.union([z.literal(`local`),z.literal(`remote`)]).optional()}).strict().optional(),diagnostics:z.object({enabled:z.boolean().optional(),flags:z.array(z.string()).optional(),otel:z.object({enabled:z.boolean().optional(),endpoint:z.string().optional(),protocol:z.union([z.literal(`http/protobuf`),z.literal(`grpc`)]).optional(),headers:z.record(z.string(),z.string()).optional(),serviceName:z.string().optional(),traces:z.boolean().optional(),metrics:z.boolean().optional(),logs:z.boolean().optional(),sampleRate:z.number().min(0).max(1).optional(),flushIntervalMs:z.number().int().nonnegative().optional()}).strict().optional(),cacheTrace:z.object({enabled:z.boolean().optional(),filePath:z.string().optional(),includeMessages:z.boolean().optional(),includePrompt:z.boolean().optional(),includeSystem:z.boolean().optional()}).strict().optional()}).strict().optional(),logging:z.object({enabled:z.boolean().optional(),format:z.union([z.literal(`json`),z.literal(`text`)]).optional(),level:z.union([z.literal(`silent`),z.literal(`fatal`),z.literal(`error`),z.literal(`warn`),z.literal(`info`),z.literal(`debug`),z.literal(`trace`)]).optional(),file:z.string().optional(),consoleLevel:z.union([z.literal(`silent`),z.literal(`fatal`),z.literal(`error`),z.literal(`warn`),z.literal(`info`),z.literal(`debug`),z.literal(`trace`)]).optional(),consoleStyle:z.union([z.literal(`pretty`),z.literal(`compact`),z.literal(`json`)]).optional(),redactSensitive:z.union([z.literal(`off`),z.literal(`tools`)]).optional(),redactPatterns:z.array(z.string()).optional()}).strict().optional(),update:z.object({channel:z.union([z.literal(`stable`),z.literal(`beta`),z.literal(`dev`)]).optional(),checkOnStart:z.boolean().optional()}).strict().optional(),browser:z.object({enabled:z.boolean().optional(),evaluateEnabled:z.boolean().optional(),cdpUrl:z.string().optional(),remoteCdpTimeoutMs:z.number().int().nonnegative().optional(),remoteCdpHandshakeTimeoutMs:z.number().int().nonnegative().optional(),color:z.string().optional(),executablePath:z.string().optional(),headless:z.boolean().optional(),noSandbox:z.boolean().optional(),attachOnly:z.boolean().optional(),defaultProfile:z.string().optional(),snapshotDefaults:BrowserSnapshotDefaultsSchema,profiles:z.record(z.string().regex(/^[a-z0-9-]+$/,`Profile names must be alphanumeric with hyphens only`),z.object({cdpPort:z.number().int().min(1).max(65535).optional(),cdpUrl:z.string().optional(),driver:z.union([z.literal(`builderforce`),z.literal(`extension`)]).optional(),color:HexColorSchema}).strict().refine(value=>value.cdpPort||value.cdpUrl,{message:`Profile must set cdpPort or cdpUrl`})).optional()}).strict().optional(),ui:z.object({seamColor:HexColorSchema.optional(),assistant:z.object({name:z.string().max(50).optional(),avatar:z.string().max(200).optional()}).strict().optional()}).strict().optional(),auth:z.object({profiles:z.record(z.string(),z.object({provider:z.string(),mode:z.union([z.literal(`api_key`),z.literal(`oauth`),z.literal(`token`)]),email:z.string().optional()}).strict()).optional(),order:z.record(z.string(),z.array(z.string())).optional(),cooldowns:z.object({billingBackoffHours:z.number().positive().optional(),billingBackoffHoursByProvider:z.record(z.string(),z.number().positive()).optional(),billingMaxHours:z.number().positive().optional(),failureWindowHours:z.number().positive().optional()}).strict().optional()}).strict().optional(),models:ModelsConfigSchema,nodeHost:NodeHostSchema,agents:AgentsSchema,tools:ToolsSchema,bindings:BindingsSchema,broadcast:BroadcastSchema,audio:AudioSchema,media:z.object({preserveFilenames:z.boolean().optional()}).strict().optional(),messages:MessagesSchema,commands:CommandsSchema,approvals:ApprovalsSchema,session:SessionSchema,cron:z.object({enabled:z.boolean().optional(),store:z.string().optional(),maxConcurrentRuns:z.number().int().positive().optional(),webhook:HttpUrlSchema.optional(),webhookToken:z.string().optional().register(sensitive),sessionRetention:z.union([z.string(),z.literal(!1)]).optional()}).strict().optional(),hooks:z.object({enabled:z.boolean().optional(),path:z.string().optional(),token:z.string().optional().register(sensitive),defaultSessionKey:z.string().optional(),allowRequestSessionKey:z.boolean().optional(),allowedSessionKeyPrefixes:z.array(z.string()).optional(),allowedAgentIds:z.array(z.string()).optional(),maxBodyBytes:z.number().int().positive().optional(),presets:z.array(z.string()).optional(),transformsDir:z.string().optional(),mappings:z.array(HookMappingSchema).optional(),gmail:HooksGmailSchema,internal:InternalHooksSchema}).strict().optional(),web:z.object({enabled:z.boolean().optional(),heartbeatSeconds:z.number().int().positive().optional(),reconnect:z.object({initialMs:z.number().positive().optional(),maxMs:z.number().positive().optional(),factor:z.number().positive().optional(),jitter:z.number().min(0).max(1).optional(),maxAttempts:z.number().int().min(0).optional()}).strict().optional()}).strict().optional(),channels:ChannelsSchema,discovery:z.object({wideArea:z.object({enabled:z.boolean().optional()}).strict().optional(),mdns:z.object({mode:z.enum([`off`,`minimal`,`full`]).optional()}).strict().optional()}).strict().optional(),canvasHost:z.object({enabled:z.boolean().optional(),root:z.string().optional(),port:z.number().int().positive().optional(),liveReload:z.boolean().optional()}).strict().optional(),talk:z.object({voiceId:z.string().optional(),voiceAliases:z.record(z.string(),z.string()).optional(),modelId:z.string().optional(),outputFormat:z.string().optional(),apiKey:z.string().optional().register(sensitive),interruptOnSpeech:z.boolean().optional()}).strict().optional(),gateway:z.object({port:z.number().int().positive().optional(),mode:z.union([z.literal(`local`),z.literal(`remote`)]).optional(),bind:z.union([z.literal(`auto`),z.literal(`lan`),z.literal(`loopback`),z.literal(`custom`),z.literal(`tailnet`)]).optional(),controlUi:z.object({enabled:z.boolean().optional(),basePath:z.string().optional(),root:z.string().optional(),allowedOrigins:z.array(z.string()).optional(),allowInsecureAuth:z.boolean().optional(),dangerouslyDisableDeviceAuth:z.boolean().optional()}).strict().optional(),auth:z.object({mode:z.union([z.literal(`token`),z.literal(`password`),z.literal(`trusted-proxy`)]).optional(),token:z.string().optional().register(sensitive),password:z.string().optional().register(sensitive),allowTailscale:z.boolean().optional(),rateLimit:z.object({maxAttempts:z.number().optional(),windowMs:z.number().optional(),lockoutMs:z.number().optional(),exemptLoopback:z.boolean().optional()}).strict().optional(),trustedProxy:z.object({userHeader:z.string().min(1,`userHeader is required for trusted-proxy mode`),requiredHeaders:z.array(z.string()).optional(),allowUsers:z.array(z.string()).optional()}).strict().optional()}).strict().optional(),trustedProxies:z.array(z.string()).optional(),tools:z.object({deny:z.array(z.string()).optional(),allow:z.array(z.string()).optional()}).strict().optional(),channelHealthCheckMinutes:z.number().int().min(0).optional(),tailscale:z.object({mode:z.union([z.literal(`off`),z.literal(`serve`),z.literal(`funnel`)]).optional(),resetOnExit:z.boolean().optional()}).strict().optional(),remote:z.object({url:z.string().optional(),transport:z.union([z.literal(`ssh`),z.literal(`direct`)]).optional(),token:z.string().optional().register(sensitive),password:z.string().optional().register(sensitive),tlsFingerprint:z.string().optional(),sshTarget:z.string().optional(),sshIdentity:z.string().optional()}).strict().optional(),reload:z.object({mode:z.union([z.literal(`off`),z.literal(`restart`),z.literal(`hot`),z.literal(`hybrid`)]).optional(),debounceMs:z.number().int().min(0).optional()}).strict().optional(),tls:z.object({enabled:z.boolean().optional(),autoGenerate:z.boolean().optional(),certPath:z.string().optional(),keyPath:z.string().optional(),caPath:z.string().optional()}).optional(),http:z.object({endpoints:z.object({chatCompletions:z.object({enabled:z.boolean().optional()}).strict().optional(),responses:z.object({enabled:z.boolean().optional(),maxBodyBytes:z.number().int().positive().optional(),maxUrlParts:z.number().int().nonnegative().optional(),files:z.object({allowUrl:z.boolean().optional(),urlAllowlist:z.array(z.string()).optional(),allowedMimes:z.array(z.string()).optional(),maxBytes:z.number().int().positive().optional(),maxChars:z.number().int().positive().optional(),maxRedirects:z.number().int().nonnegative().optional(),timeoutMs:z.number().int().positive().optional(),pdf:z.object({maxPages:z.number().int().positive().optional(),maxPixels:z.number().int().positive().optional(),minTextChars:z.number().int().nonnegative().optional()}).strict().optional()}).strict().optional(),images:z.object({allowUrl:z.boolean().optional(),urlAllowlist:z.array(z.string()).optional(),allowedMimes:z.array(z.string()).optional(),maxBytes:z.number().int().positive().optional(),maxRedirects:z.number().int().nonnegative().optional(),timeoutMs:z.number().int().positive().optional()}).strict().optional()}).strict().optional()}).strict().optional()}).strict().optional(),nodes:z.object({browser:z.object({mode:z.union([z.literal(`auto`),z.literal(`manual`),z.literal(`off`)]).optional(),node:z.string().optional()}).strict().optional(),allowCommands:z.array(z.string()).optional(),denyCommands:z.array(z.string()).optional()}).strict().optional()}).strict().optional(),memory:MemorySchema,skills:z.object({allowBundled:z.array(z.string()).optional(),load:z.object({extraDirs:z.array(z.string()).optional(),watch:z.boolean().optional(),watchDebounceMs:z.number().int().min(0).optional()}).strict().optional(),install:z.object({preferBrew:z.boolean().optional(),nodeManager:z.union([z.literal(`npm`),z.literal(`pnpm`),z.literal(`yarn`),z.literal(`bun`)]).optional()}).strict().optional(),limits:z.object({maxCandidatesPerRoot:z.number().int().min(1).optional(),maxSkillsLoadedPerSource:z.number().int().min(1).optional(),maxSkillsInPrompt:z.number().int().min(0).optional(),maxSkillsPromptChars:z.number().int().min(0).optional(),maxSkillFileBytes:z.number().int().min(0).optional()}).strict().optional(),registry:z.object({url:z.string().url().optional(),cli:z.string().optional()}).strict().optional(),entries:z.record(z.string(),z.object({enabled:z.boolean().optional(),apiKey:z.string().optional().register(sensitive),env:z.record(z.string(),z.string()).optional(),config:z.record(z.string(),z.unknown()).optional()}).strict()).optional()}).strict().optional(),plugins:z.object({enabled:z.boolean().optional(),allow:z.array(z.string()).optional(),deny:z.array(z.string()).optional(),load:z.object({paths:z.array(z.string()).optional()}).strict().optional(),slots:z.object({memory:z.string().optional()}).strict().optional(),entries:z.record(z.string(),z.object({enabled:z.boolean().optional(),config:z.record(z.string(),z.unknown()).optional()}).strict()).optional(),installs:z.record(z.string(),z.object({...InstallRecordShape}).strict()).optional()}).strict().optional(),localBrain:z.object({enabled:z.boolean().optional(),models:z.object({amygdala:z.object({modelId:z.string().optional(),dtype:z.string().optional()}).strict().optional(),hippocampus:z.object({modelId:z.string().optional(),dtype:z.string().optional()}).strict().optional()}).strict().optional()}).strict().optional()}).strict().superRefine((cfg,ctx)=>{let agents=cfg.agents?.list??[];if(agents.length===0)return;let agentIds=new Set(agents.map(agent=>agent.id)),broadcast=cfg.broadcast;if(broadcast){for(let[peerId,ids]of Object.entries(broadcast))if(peerId!==`strategy`&&Array.isArray(ids))for(let idx=0;idx<ids.length;idx+=1){let agentId=ids[idx];agentIds.has(agentId)||ctx.addIssue({code:z.ZodIssueCode.custom,path:[`broadcast`,peerId,idx],message:`Unknown agent id "${agentId}" (not in agents.list).`})}}}),AVATAR_SCHEME_RE=/^[a-z][a-z0-9+.-]*:/i,AVATAR_DATA_RE=/^data:/i,AVATAR_HTTP_RE=/^https?:\/\//i,WINDOWS_ABS_RE=/^[a-zA-Z]:[\\/]/;function isWorkspaceAvatarPath(value,workspaceDir){let workspaceRoot=path.resolve(workspaceDir),resolved=path.resolve(workspaceRoot,value),relative=path.relative(workspaceRoot,resolved);return relative===``?!0:relative.startsWith(`..`)?!1:!path.isAbsolute(relative)}function validateIdentityAvatar(config){let agents=config.agents?.list;if(!Array.isArray(agents)||agents.length===0)return[];let issues=[];for(let[index,entry]of agents.entries()){if(!entry||typeof entry!=`object`)continue;let avatarRaw=entry.identity?.avatar;if(typeof avatarRaw!=`string`)continue;let avatar=avatarRaw.trim();if(avatar&&!(AVATAR_DATA_RE.test(avatar)||AVATAR_HTTP_RE.test(avatar))){if(avatar.startsWith(`~`)){issues.push({path:`agents.list.${index}.identity.avatar`,message:`identity.avatar must be a workspace-relative path, http(s) URL, or data URI.`});continue}if(AVATAR_SCHEME_RE.test(avatar)&&!WINDOWS_ABS_RE.test(avatar)){issues.push({path:`agents.list.${index}.identity.avatar`,message:`identity.avatar must be a workspace-relative path, http(s) URL, or data URI.`});continue}isWorkspaceAvatarPath(avatar,resolveAgentWorkspaceDir(config,entry.id??resolveDefaultAgentId(config)))||issues.push({path:`agents.list.${index}.identity.avatar`,message:`identity.avatar must stay within the agent workspace.`})}}return issues}function validateConfigObjectRaw(raw){let legacyIssues=findLegacyConfigIssues(raw);if(legacyIssues.length>0)return{ok:!1,issues:legacyIssues.map(iss=>({path:iss.path,message:iss.message}))};let validated=BuilderForceAgentsSchema.safeParse(raw);if(!validated.success)return{ok:!1,issues:validated.error.issues.map(iss=>({path:iss.path.join(`.`),message:iss.message}))};let duplicates=findDuplicateAgentDirs(validated.data);if(duplicates.length>0)return{ok:!1,issues:[{path:`agents.list`,message:formatDuplicateAgentDirError(duplicates)}]};let avatarIssues=validateIdentityAvatar(validated.data);return avatarIssues.length>0?{ok:!1,issues:avatarIssues}:{ok:!0,config:validated.data}}function validateConfigObject(raw){let result=validateConfigObjectRaw(raw);return result.ok?{ok:!0,config:applyModelDefaults(applyAgentDefaults(applySessionDefaults(result.config)))}:result}function validateConfigObjectWithPlugins(raw){return validateConfigObjectWithPluginsBase(raw,{applyDefaults:!0})}function validateConfigObjectRawWithPlugins(raw){return validateConfigObjectWithPluginsBase(raw,{applyDefaults:!1})}function validateConfigObjectWithPluginsBase(raw,opts){let base=opts.applyDefaults?validateConfigObject(raw):validateConfigObjectRaw(raw);if(!base.ok)return{ok:!1,issues:base.issues,warnings:[]};let config=base.config,issues=[],warnings=[],hasExplicitPluginsConfig=isRecord(raw)&&Object.prototype.hasOwnProperty.call(raw,`plugins`),registryInfo=null,ensureRegistry=()=>{if(registryInfo)return registryInfo;let registry=loadPluginManifestRegistry({config,workspaceDir:resolveAgentWorkspaceDir(config,resolveDefaultAgentId(config))??void 0}),knownIds=new Set(registry.plugins.map(record=>record.id)),normalizedPlugins=normalizePluginsConfig(config.plugins);for(let diag of registry.diagnostics){let path=diag.pluginId?`plugins.entries.${diag.pluginId}`:`plugins`;!diag.pluginId&&diag.message.includes(`plugin path not found`)&&(path=`plugins.load.paths`);let message=`${diag.pluginId?`plugin ${diag.pluginId}`:`plugin`}: ${diag.message}`;diag.level===`error`?issues.push({path,message}):warnings.push({path,message})}return registryInfo={registry,knownIds,normalizedPlugins},registryInfo},allowedChannels=new Set([`defaults`,...CHANNEL_IDS]);if(config.channels&&isRecord(config.channels))for(let key of Object.keys(config.channels)){let trimmed=key.trim();if(trimmed){if(!allowedChannels.has(trimmed)){let{registry}=ensureRegistry();for(let record of registry.plugins)for(let channelId of record.channels)allowedChannels.add(channelId)}allowedChannels.has(trimmed)||issues.push({path:`channels.${trimmed}`,message:`unknown channel id: ${trimmed}`})}}let heartbeatChannelIds=new Set;for(let channelId of CHANNEL_IDS)heartbeatChannelIds.add(channelId.toLowerCase());let validateHeartbeatTarget=(target,path)=>{if(typeof target!=`string`)return;let trimmed=target.trim();if(!trimmed){issues.push({path,message:`heartbeat target must not be empty`});return}let normalized=trimmed.toLowerCase();if(!(normalized===`last`||normalized===`none`)&&!normalizeChatChannelId(trimmed)){if(!heartbeatChannelIds.has(normalized)){let{registry}=ensureRegistry();for(let record of registry.plugins)for(let channelId of record.channels){let pluginChannel=channelId.trim();pluginChannel&&heartbeatChannelIds.add(pluginChannel.toLowerCase())}}heartbeatChannelIds.has(normalized)||issues.push({path,message:`unknown heartbeat target: ${target}`})}};if(validateHeartbeatTarget(config.agents?.defaults?.heartbeat?.target,`agents.defaults.heartbeat.target`),Array.isArray(config.agents?.list))for(let[index,entry]of config.agents.list.entries())validateHeartbeatTarget(entry?.heartbeat?.target,`agents.list.${index}.heartbeat.target`);if(!hasExplicitPluginsConfig)return issues.length>0?{ok:!1,issues,warnings}:{ok:!0,config,warnings};let{registry,knownIds,normalizedPlugins}=ensureRegistry(),pluginsConfig=config.plugins,entries=pluginsConfig?.entries;if(entries&&isRecord(entries))for(let pluginId of Object.keys(entries))knownIds.has(pluginId)||issues.push({path:`plugins.entries.${pluginId}`,message:`plugin not found: ${pluginId}`});let allow=pluginsConfig?.allow??[];for(let pluginId of allow)typeof pluginId!=`string`||!pluginId.trim()||knownIds.has(pluginId)||issues.push({path:`plugins.allow`,message:`plugin not found: ${pluginId}`});let deny=pluginsConfig?.deny??[];for(let pluginId of deny)typeof pluginId!=`string`||!pluginId.trim()||knownIds.has(pluginId)||issues.push({path:`plugins.deny`,message:`plugin not found: ${pluginId}`});let memorySlot=normalizedPlugins.slots.memory;typeof memorySlot==`string`&&memorySlot.trim()&&!knownIds.has(memorySlot)&&issues.push({path:`plugins.slots.memory`,message:`plugin not found: ${memorySlot}`});let selectedMemoryPluginId=null,seenPlugins=new Set;for(let record of registry.plugins){let pluginId=record.id;if(seenPlugins.has(pluginId))continue;seenPlugins.add(pluginId);let entry=normalizedPlugins.entries[pluginId],entryHasConfig=!!entry?.config,enableState=resolveEnableState(pluginId,record.origin,normalizedPlugins),enabled=enableState.enabled,reason=enableState.reason;if(enabled){let memoryDecision=resolveMemorySlotDecision({id:pluginId,kind:record.kind,slot:memorySlot,selectedId:selectedMemoryPluginId});memoryDecision.enabled||(enabled=!1,reason=memoryDecision.reason),memoryDecision.selected&&record.kind===`memory`&&(selectedMemoryPluginId=pluginId)}if(enabled||entryHasConfig)if(record.configSchema){let res=validateJsonSchemaValue({schema:record.configSchema,cacheKey:record.schemaCacheKey??record.manifestPath??pluginId,value:entry?.config??{}});if(!res.ok)for(let error of res.errors)issues.push({path:`plugins.entries.${pluginId}.config`,message:`invalid config: ${error}`})}else issues.push({path:`plugins.entries.${pluginId}`,message:`plugin schema missing for ${pluginId}`});!enabled&&entryHasConfig&&warnings.push({path:`plugins.entries.${pluginId}`,message:`plugin disabled (${reason??`disabled`}) but config is present`})}return issues.length>0?{ok:!1,issues,warnings}:{ok:!0,config,warnings}}const VERSION_RE=/^v?(\d+)\.(\d+)\.(\d+)(?:-(\d+))?/;function parseBuilderForceAgentsVersion(raw){if(!raw)return null;let match=raw.trim().match(VERSION_RE);if(!match)return null;let[,major,minor,patch,revision]=match;return{major:Number.parseInt(major,10),minor:Number.parseInt(minor,10),patch:Number.parseInt(patch,10),revision:revision?Number.parseInt(revision,10):0}}function compareBuilderForceAgentsVersions(a,b){let parsedA=parseBuilderForceAgentsVersion(a),parsedB=parseBuilderForceAgentsVersion(b);return!parsedA||!parsedB?null:parsedA.major===parsedB.major?parsedA.minor===parsedB.minor?parsedA.patch===parsedB.patch?parsedA.revision===parsedB.revision?0:parsedA.revision<parsedB.revision?-1:1:parsedA.patch<parsedB.patch?-1:1:parsedA.minor<parsedB.minor?-1:1:parsedA.major<parsedB.major?-1:1}const SHELL_ENV_EXPECTED_KEYS=[`OPENAI_API_KEY`,`ANTHROPIC_API_KEY`,`ANTHROPIC_OAUTH_TOKEN`,`GEMINI_API_KEY`,`ZAI_API_KEY`,`OPENROUTER_API_KEY`,`AI_GATEWAY_API_KEY`,`MINIMAX_API_KEY`,`SYNTHETIC_API_KEY`,`ELEVENLABS_API_KEY`,`TELEGRAM_BOT_TOKEN`,`DISCORD_BOT_TOKEN`,`SLACK_BOT_TOKEN`,`SLACK_APP_TOKEN`,`BUILDERFORCE_AGENTS_GATEWAY_TOKEN`,`BUILDERFORCE_AGENTS_GATEWAY_PASSWORD`],loggedInvalidConfigs=new Set;function hashConfigRaw(raw){return crypto.createHash(`sha256`).update(raw??``).digest(`hex`)}function resolveConfigSnapshotHash(snapshot){if(typeof snapshot.hash==`string`){let trimmed=snapshot.hash.trim();if(trimmed)return trimmed}return typeof snapshot.raw==`string`?hashConfigRaw(snapshot.raw):null}function coerceConfig(value){return!value||typeof value!=`object`||Array.isArray(value)?{}:value}function isPlainObject(value){return typeof value==`object`&&!!value&&!Array.isArray(value)}function hasConfigMeta(value){if(!isPlainObject(value))return!1;let meta=value.meta;return isPlainObject(meta)}function resolveGatewayMode(value){if(!isPlainObject(value))return null;let gateway=value.gateway;if(!isPlainObject(gateway)||typeof gateway.mode!=`string`)return null;let trimmed=gateway.mode.trim();return trimmed.length>0?trimmed:null}function cloneUnknown(value){return structuredClone(value)}function createMergePatch(base,target){if(!isPlainObject(base)||!isPlainObject(target))return cloneUnknown(target);let patch={},keys=new Set([...Object.keys(base),...Object.keys(target)]);for(let key of keys){let hasBase=key in base;if(!(key in target)){patch[key]=null;continue}let targetValue=target[key];if(!hasBase){patch[key]=cloneUnknown(targetValue);continue}let baseValue=base[key];if(isPlainObject(baseValue)&&isPlainObject(targetValue)){let childPatch=createMergePatch(baseValue,targetValue);if(isPlainObject(childPatch)&&Object.keys(childPatch).length===0)continue;patch[key]=childPatch;continue}isDeepStrictEqual(baseValue,targetValue)||(patch[key]=cloneUnknown(targetValue))}return patch}function collectEnvRefPaths(value,path,output){if(typeof value==`string`){containsEnvVarReference(value)&&output.set(path,value);return}if(Array.isArray(value)){value.forEach((item,index)=>{collectEnvRefPaths(item,`${path}[${index}]`,output)});return}if(isPlainObject(value))for(let[key,child]of Object.entries(value))collectEnvRefPaths(child,path?`${path}.${key}`:key,output)}function collectChangedPaths(base,target,path,output){if(Array.isArray(base)&&Array.isArray(target)){let max=Math.max(base.length,target.length);for(let index=0;index<max;index+=1){let childPath=path?`${path}[${index}]`:`[${index}]`;if(index>=base.length||index>=target.length){output.add(childPath);continue}collectChangedPaths(base[index],target[index],childPath,output)}return}if(isPlainObject(base)&&isPlainObject(target)){let keys=new Set([...Object.keys(base),...Object.keys(target)]);for(let key of keys){let childPath=path?`${path}.${key}`:key,hasBase=key in base;if(!(key in target)||!hasBase){output.add(childPath);continue}collectChangedPaths(base[key],target[key],childPath,output)}return}isDeepStrictEqual(base,target)||output.add(path)}function parentPath(value){if(!value)return``;if(value.endsWith(`]`)){let index=value.lastIndexOf(`[`);return index>0?value.slice(0,index):``}let index=value.lastIndexOf(`.`);return index>=0?value.slice(0,index):``}function isPathChanged(path,changedPaths){if(changedPaths.has(path))return!0;let current=parentPath(path);for(;current;){if(changedPaths.has(current))return!0;current=parentPath(current)}return changedPaths.has(``)}function restoreEnvRefsFromMap(value,path,envRefMap,changedPaths){if(typeof value==`string`){if(!isPathChanged(path,changedPaths)){let original=envRefMap.get(path);if(original!==void 0)return original}return value}if(Array.isArray(value)){let changed=!1,next=value.map((item,index)=>{let updated=restoreEnvRefsFromMap(item,`${path}[${index}]`,envRefMap,changedPaths);return updated!==item&&(changed=!0),updated});return changed?next:value}if(isPlainObject(value)){let changed=!1,next={};for(let[key,child]of Object.entries(value)){let updated=restoreEnvRefsFromMap(child,path?`${path}.${key}`:key,envRefMap,changedPaths);updated!==child&&(changed=!0),next[key]=updated}return changed?next:value}return value}function resolveConfigAuditLogPath(env,homedir){return path.join(resolveStateDir(env,homedir),`logs`,`config-audit.jsonl`)}function resolveConfigWriteSuspiciousReasons(params){let reasons=[];return params.existsBefore?(typeof params.previousBytes==`number`&&typeof params.nextBytes==`number`&¶ms.previousBytes>=512&¶ms.nextBytes<Math.floor(params.previousBytes*.5)&&reasons.push(`size-drop:${params.previousBytes}->${params.nextBytes}`),params.hasMetaBefore||reasons.push(`missing-meta-before-write`),params.gatewayModeBefore&&!params.gatewayModeAfter&&reasons.push(`gateway-mode-removed`),reasons):reasons}async function appendConfigWriteAuditRecord(deps,record){try{let auditPath=resolveConfigAuditLogPath(deps.env,deps.homedir);await deps.fs.promises.mkdir(path.dirname(auditPath),{recursive:!0,mode:448}),await deps.fs.promises.appendFile(auditPath,`${JSON.stringify(record)}\n`,{encoding:`utf-8`,mode:384})}catch{}}function warnOnConfigMiskeys(raw,logger){if(!raw||typeof raw!=`object`)return;let gateway=raw.gateway;!gateway||typeof gateway!=`object`||`token`in gateway&&logger.warn(`Config uses "gateway.token". This key is ignored; use "gateway.auth.token" instead.`)}function stampConfigVersion(cfg){let now=new Date().toISOString();return{...cfg,meta:{...cfg.meta,lastTouchedVersion:VERSION,lastTouchedAt:now}}}function warnIfConfigFromFuture(cfg,logger){let touched=cfg.meta?.lastTouchedVersion;if(!touched)return;let cmp=compareBuilderForceAgentsVersions(VERSION,touched);cmp!==null&&cmp<0&&logger.warn(`Config was last written by a newer BuilderForceAgents (${touched}); current version is ${VERSION}.`)}function resolveConfigPathForDeps(deps){return deps.configPath?deps.configPath:resolveConfigPath(deps.env,resolveStateDir(deps.env,deps.homedir))}function normalizeDeps(overrides={}){return{fs:overrides.fs??fs,json5:overrides.json5??JSON5,env:overrides.env??process.env,homedir:overrides.homedir??(()=>resolveRequiredHomeDir(overrides.env??process.env,os.homedir)),configPath:overrides.configPath??``,logger:overrides.logger??console}}function maybeLoadDotEnvForConfig(env){env===process.env&&loadDotEnv({quiet:!0})}function parseConfigJson5(raw,json5=JSON5){try{return{ok:!0,parsed:json5.parse(raw)}}catch(err){return{ok:!1,error:String(err)}}}function resolveConfigIncludesForRead(parsed,configPath,deps){return resolveConfigIncludes(parsed,configPath,{readFile:candidate=>deps.fs.readFileSync(candidate,`utf-8`),parseJson:raw=>deps.json5.parse(raw)})}function resolveConfigForRead(resolvedIncludes,env){return resolvedIncludes&&typeof resolvedIncludes==`object`&&`env`in resolvedIncludes&&applyConfigEnvVars(resolvedIncludes,env),{resolvedConfigRaw:resolveConfigEnvVars(resolvedIncludes,env),envSnapshotForRestore:{...env}}}function createConfigIO(overrides={}){let deps=normalizeDeps(overrides),requestedConfigPath=resolveConfigPathForDeps(deps),configPath=(deps.configPath?[requestedConfigPath]:resolveDefaultConfigCandidates(deps.env,deps.homedir)).find(candidate=>deps.fs.existsSync(candidate))??requestedConfigPath;function loadConfig(){try{if(maybeLoadDotEnvForConfig(deps.env),!deps.fs.existsSync(configPath))return shouldEnableShellEnvFallback(deps.env)&&!shouldDeferShellEnvFallback(deps.env)&&loadShellEnvFallback({enabled:!0,env:deps.env,expectedKeys:SHELL_ENV_EXPECTED_KEYS,logger:deps.logger,timeoutMs:resolveShellEnvFallbackTimeoutMs(deps.env)}),{};let raw=deps.fs.readFileSync(configPath,`utf-8`),{resolvedConfigRaw:resolvedConfig}=resolveConfigForRead(resolveConfigIncludesForRead(deps.json5.parse(raw),configPath,deps),deps.env);if(warnOnConfigMiskeys(resolvedConfig,deps.logger),typeof resolvedConfig!=`object`||!resolvedConfig)return{};let preValidationDuplicates=findDuplicateAgentDirs(resolvedConfig,{env:deps.env,homedir:deps.homedir});if(preValidationDuplicates.length>0)throw new DuplicateAgentDirError(preValidationDuplicates);let validated=validateConfigObjectWithPlugins(resolvedConfig);if(!validated.ok){let details=validated.issues.map(iss=>`- ${iss.path||`<root>`}: ${iss.message}`).join(`
|
|
1
|
+
import{l as normalizeAgentId,n as DEFAULT_AGENT_ID}from"./session-key-5J69DULS.js";import{C as isPlainObject$2,j as resolveUserPath,k as resolveConfigDir,o as normalizeChatChannelId,t as CHANNEL_IDS,w as isRecord}from"./registry-DJq2Cvo9.js";import{n as resolveConfigPath,r as resolveDefaultConfigCandidates,s as resolveStateDir,u as resolveRequiredHomeDir}from"./paths-Cb8zTlyG.js";import{At as shouldDeferShellEnvFallback,Ot as loadShellEnvFallback,bt as currentAnthropicModelId,ht as DEFAULT_CONTEXT_TOKENS,jt as shouldEnableShellEnvFallback,kt as resolveShellEnvFallbackTimeoutMs,u as parseModelRef,vt as ANTHROPIC_FAMILIES}from"./model-selection-K82MAGlL.js";import{c as resolveDefaultAgentId,s as resolveAgentWorkspaceDir}from"./agent-scope-BQByW0cD.js";import{createRequire}from"node:module";import path from"node:path";import fs from"node:fs";import os from"node:os";import crypto from"node:crypto";import{fileURLToPath}from"node:url";import json5 from"json5";import{z}from"zod";import{isDeepStrictEqual}from"node:util";import dotenv from"dotenv";import AjvPkg from"ajv";const TELEGRAM_COMMAND_NAME_PATTERN=/^[a-z0-9_]{1,32}$/;function normalizeTelegramCommandName(value){let trimmed=value.trim();return trimmed?(trimmed.startsWith(`/`)?trimmed.slice(1):trimmed).trim().toLowerCase().replace(/-/g,`_`):``}function normalizeTelegramCommandDescription(value){return value.trim()}function resolveTelegramCustomCommands(params){let entries=Array.isArray(params.commands)?params.commands:[],reserved=params.reservedCommands??new Set,checkReserved=params.checkReserved!==!1,checkDuplicates=params.checkDuplicates!==!1,seen=new Set,resolved=[],issues=[];for(let index=0;index<entries.length;index+=1){let entry=entries[index],normalized=normalizeTelegramCommandName(String(entry?.command??``));if(!normalized){issues.push({index,field:`command`,message:`Telegram custom command is missing a command name.`});continue}if(!TELEGRAM_COMMAND_NAME_PATTERN.test(normalized)){issues.push({index,field:`command`,message:`Telegram custom command "/${normalized}" is invalid (use a-z, 0-9, underscore; max 32 chars).`});continue}if(checkReserved&&reserved.has(normalized)){issues.push({index,field:`command`,message:`Telegram custom command "/${normalized}" conflicts with a native command.`});continue}if(checkDuplicates&&seen.has(normalized)){issues.push({index,field:`command`,message:`Telegram custom command "/${normalized}" is duplicated.`});continue}let description=normalizeTelegramCommandDescription(String(entry?.description??``));if(!description){issues.push({index,field:`description`,message:`Telegram custom command "/${normalized}" is missing a description.`});continue}checkDuplicates&&seen.add(normalized),resolved.push({command:normalized,description})}return{commands:resolved,issues}}function parseDurationMs(raw,opts){let trimmed=String(raw??``).trim().toLowerCase();if(!trimmed)throw Error(`invalid duration (empty)`);let m=/^(\d+(?:\.\d+)?)(ms|s|m|h|d)?$/.exec(trimmed);if(!m)throw Error(`invalid duration: ${raw}`);let value=Number(m[1]);if(!Number.isFinite(value)||value<0)throw Error(`invalid duration: ${raw}`);let unit=m[2]??opts?.defaultUnit??`ms`,multiplier=unit===`ms`?1:unit===`s`?1e3:unit===`m`?6e4:unit===`h`?36e5:864e5,ms=Math.round(value*multiplier);if(!Number.isFinite(ms))throw Error(`invalid duration: ${raw}`);return ms}const AgentModelSchema=z.union([z.string(),z.object({primary:z.string().optional(),fallbacks:z.array(z.string()).optional()}).strict()]),SHELL_METACHARS=/[;&|`$<>]/,CONTROL_CHARS=/[\r\n]/,QUOTE_CHARS=/["']/,BARE_NAME_PATTERN=/^[A-Za-z0-9._+-]+$/;function isLikelyPath(value){return value.startsWith(`.`)||value.startsWith(`~`)||value.includes(`/`)||value.includes(`\\`)?!0:/^[A-Za-z]:[\\/]/.test(value)}function isSafeExecutableValue(value){if(!value)return!1;let trimmed=value.trim();return!trimmed||trimmed.includes(`\0`)||CONTROL_CHARS.test(trimmed)||SHELL_METACHARS.test(trimmed)||QUOTE_CHARS.test(trimmed)?!1:isLikelyPath(trimmed)?!0:trimmed.startsWith(`-`)?!1:BARE_NAME_PATTERN.test(trimmed)}const AllowDenyActionSchema=z.union([z.literal(`allow`),z.literal(`deny`)]),AllowDenyChatTypeSchema=z.union([z.literal(`direct`),z.literal(`group`),z.literal(`channel`),z.literal(`dm`)]).optional();function createAllowDenyChannelRulesSchema(){return z.object({default:AllowDenyActionSchema.optional(),rules:z.array(z.object({action:AllowDenyActionSchema,match:z.object({channel:z.string().optional(),chatType:AllowDenyChatTypeSchema,keyPrefix:z.string().optional(),rawKeyPrefix:z.string().optional()}).strict().optional()}).strict()).optional()}).strict().optional()}const sensitive=z.registry(),ModelApiSchema=z.union([z.literal(`openai-completions`),z.literal(`openai-responses`),z.literal(`anthropic-messages`),z.literal(`google-generative-ai`),z.literal(`github-copilot`),z.literal(`bedrock-converse-stream`),z.literal(`ollama`),z.literal(`transformers`)]),ModelCompatSchema=z.object({supportsStore:z.boolean().optional(),supportsDeveloperRole:z.boolean().optional(),supportsReasoningEffort:z.boolean().optional(),supportsUsageInStreaming:z.boolean().optional(),supportsStrictMode:z.boolean().optional(),maxTokensField:z.union([z.literal(`max_completion_tokens`),z.literal(`max_tokens`)]).optional(),thinkingFormat:z.union([z.literal(`openai`),z.literal(`zai`),z.literal(`qwen`)]).optional(),requiresToolResultName:z.boolean().optional(),requiresAssistantAfterToolResult:z.boolean().optional(),requiresThinkingAsText:z.boolean().optional(),requiresMistralToolIds:z.boolean().optional()}).strict().optional(),ModelDefinitionSchema=z.object({id:z.string().min(1),name:z.string().min(1),api:ModelApiSchema.optional(),reasoning:z.boolean().optional(),input:z.array(z.union([z.literal(`text`),z.literal(`image`)])).optional(),cost:z.object({input:z.number().optional(),output:z.number().optional(),cacheRead:z.number().optional(),cacheWrite:z.number().optional()}).strict().optional(),contextWindow:z.number().positive().optional(),maxTokens:z.number().positive().optional(),headers:z.record(z.string(),z.string()).optional(),compat:ModelCompatSchema}).strict(),ModelProviderSchema=z.object({baseUrl:z.string().min(1),apiKey:z.string().optional().register(sensitive),auth:z.union([z.literal(`api-key`),z.literal(`aws-sdk`),z.literal(`oauth`),z.literal(`token`)]).optional(),api:ModelApiSchema.optional(),headers:z.record(z.string(),z.string()).optional(),authHeader:z.boolean().optional(),models:z.array(ModelDefinitionSchema)}).strict(),BedrockDiscoverySchema=z.object({enabled:z.boolean().optional(),region:z.string().optional(),providerFilter:z.array(z.string()).optional(),refreshInterval:z.number().int().nonnegative().optional(),defaultContextWindow:z.number().int().positive().optional(),defaultMaxTokens:z.number().int().positive().optional()}).strict().optional(),ModelsConfigSchema=z.object({mode:z.union([z.literal(`merge`),z.literal(`replace`)]).optional(),providers:z.record(z.string(),ModelProviderSchema).optional(),bedrockDiscovery:BedrockDiscoverySchema}).strict().optional(),GroupChatSchema=z.object({mentionPatterns:z.array(z.string()).optional(),historyLimit:z.number().int().positive().optional()}).strict().optional(),DmConfigSchema=z.object({historyLimit:z.number().int().min(0).optional()}).strict(),IdentitySchema=z.object({name:z.string().optional(),theme:z.string().optional(),emoji:z.string().optional(),avatar:z.string().optional()}).strict().optional(),QueueModeSchema=z.union([z.literal(`steer`),z.literal(`followup`),z.literal(`collect`),z.literal(`steer-backlog`),z.literal(`steer+backlog`),z.literal(`queue`),z.literal(`interrupt`)]),QueueDropSchema=z.union([z.literal(`old`),z.literal(`new`),z.literal(`summarize`)]),ReplyToModeSchema=z.union([z.literal(`off`),z.literal(`first`),z.literal(`all`)]),GroupPolicySchema=z.enum([`open`,`disabled`,`allowlist`]),DmPolicySchema=z.enum([`pairing`,`allowlist`,`open`,`disabled`]),BlockStreamingCoalesceSchema=z.object({minChars:z.number().int().positive().optional(),maxChars:z.number().int().positive().optional(),idleMs:z.number().int().nonnegative().optional()}).strict(),BlockStreamingChunkSchema=z.object({minChars:z.number().int().positive().optional(),maxChars:z.number().int().positive().optional(),breakPreference:z.union([z.literal(`paragraph`),z.literal(`newline`),z.literal(`sentence`)]).optional()}).strict(),MarkdownTableModeSchema=z.enum([`off`,`bullets`,`code`]),MarkdownConfigSchema=z.object({tables:MarkdownTableModeSchema.optional()}).strict().optional(),TtsProviderSchema=z.enum([`elevenlabs`,`openai`,`edge`]),TtsModeSchema=z.enum([`final`,`all`]),TtsAutoSchema=z.enum([`off`,`always`,`inbound`,`tagged`]),TtsConfigSchema=z.object({auto:TtsAutoSchema.optional(),enabled:z.boolean().optional(),mode:TtsModeSchema.optional(),provider:TtsProviderSchema.optional(),summaryModel:z.string().optional(),modelOverrides:z.object({enabled:z.boolean().optional(),allowText:z.boolean().optional(),allowProvider:z.boolean().optional(),allowVoice:z.boolean().optional(),allowModelId:z.boolean().optional(),allowVoiceSettings:z.boolean().optional(),allowNormalization:z.boolean().optional(),allowSeed:z.boolean().optional()}).strict().optional(),elevenlabs:z.object({apiKey:z.string().optional().register(sensitive),baseUrl:z.string().optional(),voiceId:z.string().optional(),modelId:z.string().optional(),seed:z.number().int().min(0).max(4294967295).optional(),applyTextNormalization:z.enum([`auto`,`on`,`off`]).optional(),languageCode:z.string().optional(),voiceSettings:z.object({stability:z.number().min(0).max(1).optional(),similarityBoost:z.number().min(0).max(1).optional(),style:z.number().min(0).max(1).optional(),useSpeakerBoost:z.boolean().optional(),speed:z.number().min(.5).max(2).optional()}).strict().optional()}).strict().optional(),openai:z.object({apiKey:z.string().optional().register(sensitive),model:z.string().optional(),voice:z.string().optional()}).strict().optional(),edge:z.object({enabled:z.boolean().optional(),voice:z.string().optional(),lang:z.string().optional(),outputFormat:z.string().optional(),pitch:z.string().optional(),rate:z.string().optional(),volume:z.string().optional(),saveSubtitles:z.boolean().optional(),proxy:z.string().optional(),timeoutMs:z.number().int().min(1e3).max(12e4).optional()}).strict().optional(),prefsPath:z.string().optional(),maxTextLength:z.number().int().min(1).optional(),timeoutMs:z.number().int().min(1e3).max(12e4).optional()}).strict().optional(),HumanDelaySchema=z.object({mode:z.union([z.literal(`off`),z.literal(`natural`),z.literal(`custom`)]).optional(),minMs:z.number().int().nonnegative().optional(),maxMs:z.number().int().nonnegative().optional()}).strict(),CliBackendWatchdogModeSchema=z.object({noOutputTimeoutMs:z.number().int().min(1e3).optional(),noOutputTimeoutRatio:z.number().min(.05).max(.95).optional(),minMs:z.number().int().min(1e3).optional(),maxMs:z.number().int().min(1e3).optional()}).strict().optional(),CliBackendSchema=z.object({command:z.string(),args:z.array(z.string()).optional(),output:z.union([z.literal(`json`),z.literal(`text`),z.literal(`jsonl`)]).optional(),resumeOutput:z.union([z.literal(`json`),z.literal(`text`),z.literal(`jsonl`)]).optional(),input:z.union([z.literal(`arg`),z.literal(`stdin`)]).optional(),maxPromptArgChars:z.number().int().positive().optional(),env:z.record(z.string(),z.string()).optional(),clearEnv:z.array(z.string()).optional(),modelArg:z.string().optional(),modelAliases:z.record(z.string(),z.string()).optional(),sessionArg:z.string().optional(),sessionArgs:z.array(z.string()).optional(),resumeArgs:z.array(z.string()).optional(),sessionMode:z.union([z.literal(`always`),z.literal(`existing`),z.literal(`none`)]).optional(),sessionIdFields:z.array(z.string()).optional(),systemPromptArg:z.string().optional(),systemPromptMode:z.union([z.literal(`append`),z.literal(`replace`)]).optional(),systemPromptWhen:z.union([z.literal(`first`),z.literal(`always`),z.literal(`never`)]).optional(),imageArg:z.string().optional(),imageMode:z.union([z.literal(`repeat`),z.literal(`list`)]).optional(),serialize:z.boolean().optional(),reliability:z.object({watchdog:z.object({fresh:CliBackendWatchdogModeSchema,resume:CliBackendWatchdogModeSchema}).strict().optional()}).strict().optional()}).strict(),normalizeAllowFrom=values=>(values??[]).map(v=>String(v).trim()).filter(Boolean),requireOpenAllowFrom=params=>{params.policy===`open`&&(normalizeAllowFrom(params.allowFrom).includes(`*`)||params.ctx.addIssue({code:z.ZodIssueCode.custom,path:params.path,message:params.message}))},MSTeamsReplyStyleSchema=z.enum([`thread`,`top-level`]),RetryConfigSchema=z.object({attempts:z.number().int().min(1).optional(),minDelayMs:z.number().int().min(0).optional(),maxDelayMs:z.number().int().min(0).optional(),jitter:z.number().min(0).max(1).optional()}).strict().optional(),QueueModeBySurfaceSchema=z.object({whatsapp:QueueModeSchema.optional(),telegram:QueueModeSchema.optional(),discord:QueueModeSchema.optional(),irc:QueueModeSchema.optional(),slack:QueueModeSchema.optional(),mattermost:QueueModeSchema.optional(),signal:QueueModeSchema.optional(),imessage:QueueModeSchema.optional(),msteams:QueueModeSchema.optional(),webchat:QueueModeSchema.optional()}).strict().optional(),DebounceMsBySurfaceSchema=z.record(z.string(),z.number().int().nonnegative()).optional(),QueueSchema=z.object({mode:QueueModeSchema.optional(),byChannel:QueueModeBySurfaceSchema,debounceMs:z.number().int().nonnegative().optional(),debounceMsByChannel:DebounceMsBySurfaceSchema,cap:z.number().int().positive().optional(),drop:QueueDropSchema.optional()}).strict().optional(),InboundDebounceSchema=z.object({debounceMs:z.number().int().nonnegative().optional(),byChannel:DebounceMsBySurfaceSchema}).strict().optional(),TranscribeAudioSchema=z.object({command:z.array(z.string()).superRefine((value,ctx)=>{let executable=value[0];isSafeExecutableValue(executable)||ctx.addIssue({code:z.ZodIssueCode.custom,path:[0],message:`expected safe executable name or path`})}),timeoutSeconds:z.number().int().positive().optional()}).strict().optional(),HexColorSchema=z.string().regex(/^#?[0-9a-fA-F]{6}$/,`expected hex color (RRGGBB)`),ExecutableTokenSchema=z.string().refine(isSafeExecutableValue,`expected safe executable name or path`),MediaUnderstandingScopeSchema=createAllowDenyChannelRulesSchema(),MediaUnderstandingCapabilitiesSchema=z.array(z.union([z.literal(`image`),z.literal(`audio`),z.literal(`video`)])).optional(),MediaUnderstandingAttachmentsSchema=z.object({mode:z.union([z.literal(`first`),z.literal(`all`)]).optional(),maxAttachments:z.number().int().positive().optional(),prefer:z.union([z.literal(`first`),z.literal(`last`),z.literal(`path`),z.literal(`url`)]).optional()}).strict().optional(),DeepgramAudioSchema=z.object({detectLanguage:z.boolean().optional(),punctuate:z.boolean().optional(),smartFormat:z.boolean().optional()}).strict().optional(),ProviderOptionValueSchema=z.union([z.string(),z.number(),z.boolean()]),ProviderOptionsSchema=z.record(z.string(),z.record(z.string(),ProviderOptionValueSchema)).optional(),MediaUnderstandingModelSchema=z.object({provider:z.string().optional(),model:z.string().optional(),capabilities:MediaUnderstandingCapabilitiesSchema,type:z.union([z.literal(`provider`),z.literal(`cli`)]).optional(),command:z.string().optional(),args:z.array(z.string()).optional(),prompt:z.string().optional(),maxChars:z.number().int().positive().optional(),maxBytes:z.number().int().positive().optional(),timeoutSeconds:z.number().int().positive().optional(),language:z.string().optional(),providerOptions:ProviderOptionsSchema,deepgram:DeepgramAudioSchema,baseUrl:z.string().optional(),headers:z.record(z.string(),z.string()).optional(),profile:z.string().optional(),preferredProfile:z.string().optional()}).strict().optional(),ToolsMediaUnderstandingSchema=z.object({enabled:z.boolean().optional(),scope:MediaUnderstandingScopeSchema,maxBytes:z.number().int().positive().optional(),maxChars:z.number().int().positive().optional(),prompt:z.string().optional(),timeoutSeconds:z.number().int().positive().optional(),language:z.string().optional(),providerOptions:ProviderOptionsSchema,deepgram:DeepgramAudioSchema,baseUrl:z.string().optional(),headers:z.record(z.string(),z.string()).optional(),attachments:MediaUnderstandingAttachmentsSchema,models:z.array(MediaUnderstandingModelSchema).optional()}).strict().optional(),ToolsMediaSchema=z.object({models:z.array(MediaUnderstandingModelSchema).optional(),concurrency:z.number().int().positive().optional(),image:ToolsMediaUnderstandingSchema.optional(),audio:ToolsMediaUnderstandingSchema.optional(),video:ToolsMediaUnderstandingSchema.optional()}).strict().optional(),LinkModelSchema=z.object({type:z.literal(`cli`).optional(),command:z.string().min(1),args:z.array(z.string()).optional(),timeoutSeconds:z.number().int().positive().optional()}).strict(),ToolsLinksSchema=z.object({enabled:z.boolean().optional(),scope:MediaUnderstandingScopeSchema,maxLinks:z.number().int().positive().optional(),timeoutSeconds:z.number().int().positive().optional(),models:z.array(LinkModelSchema).optional()}).strict().optional(),NativeCommandsSettingSchema=z.union([z.boolean(),z.literal(`auto`)]),ProviderCommandsSchema=z.object({native:NativeCommandsSettingSchema.optional(),nativeSkills:NativeCommandsSettingSchema.optional()}).strict().optional(),HeartbeatSchema=z.object({every:z.string().optional(),activeHours:z.object({start:z.string().optional(),end:z.string().optional(),timezone:z.string().optional()}).strict().optional(),model:z.string().optional(),session:z.string().optional(),includeReasoning:z.boolean().optional(),target:z.string().optional(),to:z.string().optional(),accountId:z.string().optional(),prompt:z.string().optional(),ackMaxChars:z.number().int().nonnegative().optional(),suppressToolErrorWarnings:z.boolean().optional()}).strict().superRefine((val,ctx)=>{if(!val.every)return;try{parseDurationMs(val.every,{defaultUnit:`m`})}catch{ctx.addIssue({code:z.ZodIssueCode.custom,path:[`every`],message:`invalid duration (use ms, s, m, h)`})}let active=val.activeHours;if(!active)return;let timePattern=/^([01]\d|2[0-3]|24):([0-5]\d)$/,validateTime=(raw,opts,path)=>{if(!raw)return;if(!timePattern.test(raw)){ctx.addIssue({code:z.ZodIssueCode.custom,path:[`activeHours`,path],message:`invalid time (use "HH:MM" 24h format)`});return}let[hourStr,minuteStr]=raw.split(`:`),hour=Number(hourStr),minute=Number(minuteStr);if(hour===24&&minute!==0){ctx.addIssue({code:z.ZodIssueCode.custom,path:[`activeHours`,path],message:`invalid time (24:00 is the only allowed 24:xx value)`});return}hour===24&&!opts.allow24&&ctx.addIssue({code:z.ZodIssueCode.custom,path:[`activeHours`,path],message:`invalid time (start cannot be 24:00)`})};validateTime(active.start,{allow24:!1},`start`),validateTime(active.end,{allow24:!0},`end`)}).optional(),SandboxDockerSchema=z.object({image:z.string().optional(),containerPrefix:z.string().optional(),workdir:z.string().optional(),readOnlyRoot:z.boolean().optional(),tmpfs:z.array(z.string()).optional(),network:z.string().optional(),user:z.string().optional(),capDrop:z.array(z.string()).optional(),env:z.record(z.string(),z.string()).optional(),setupCommand:z.string().optional(),pidsLimit:z.number().int().positive().optional(),memory:z.union([z.string(),z.number()]).optional(),memorySwap:z.union([z.string(),z.number()]).optional(),cpus:z.number().positive().optional(),ulimits:z.record(z.string(),z.union([z.string(),z.number(),z.object({soft:z.number().int().nonnegative().optional(),hard:z.number().int().nonnegative().optional()}).strict()])).optional(),seccompProfile:z.string().optional(),apparmorProfile:z.string().optional(),dns:z.array(z.string()).optional(),extraHosts:z.array(z.string()).optional(),binds:z.array(z.string()).optional()}).strict().superRefine((data,ctx)=>{if(data.binds)for(let i=0;i<data.binds.length;i+=1){let bind=data.binds[i]?.trim()??``;if(!bind){ctx.addIssue({code:z.ZodIssueCode.custom,path:[`binds`,i],message:`Sandbox security: bind mount entry must be a non-empty string.`});continue}let firstColon=bind.indexOf(`:`),source=(firstColon<=0?bind:bind.slice(0,firstColon)).trim();source.startsWith(`/`)||ctx.addIssue({code:z.ZodIssueCode.custom,path:[`binds`,i],message:`Sandbox security: bind mount "${bind}" uses a non-absolute source path "${source}". Only absolute POSIX paths are supported for sandbox binds.`})}data.network?.trim().toLowerCase()===`host`&&ctx.addIssue({code:z.ZodIssueCode.custom,path:[`network`],message:`Sandbox security: network mode "host" is blocked. Use "bridge" or "none" instead.`}),data.seccompProfile?.trim().toLowerCase()===`unconfined`&&ctx.addIssue({code:z.ZodIssueCode.custom,path:[`seccompProfile`],message:`Sandbox security: seccomp profile "unconfined" is blocked. Use a custom seccomp profile file or omit this setting.`}),data.apparmorProfile?.trim().toLowerCase()===`unconfined`&&ctx.addIssue({code:z.ZodIssueCode.custom,path:[`apparmorProfile`],message:`Sandbox security: apparmor profile "unconfined" is blocked. Use a named AppArmor profile or omit this setting.`})}).optional(),SandboxBrowserSchema=z.object({enabled:z.boolean().optional(),image:z.string().optional(),containerPrefix:z.string().optional(),cdpPort:z.number().int().positive().optional(),vncPort:z.number().int().positive().optional(),noVncPort:z.number().int().positive().optional(),headless:z.boolean().optional(),enableNoVnc:z.boolean().optional(),allowHostControl:z.boolean().optional(),autoStart:z.boolean().optional(),autoStartTimeoutMs:z.number().int().positive().optional(),binds:z.array(z.string()).optional()}).strict().optional(),SandboxPruneSchema=z.object({idleHours:z.number().int().nonnegative().optional(),maxAgeDays:z.number().int().nonnegative().optional()}).strict().optional(),ToolPolicySchema=z.object({allow:z.array(z.string()).optional(),alsoAllow:z.array(z.string()).optional(),deny:z.array(z.string()).optional()}).strict().superRefine((value,ctx)=>{value.allow&&value.allow.length>0&&value.alsoAllow&&value.alsoAllow.length>0&&ctx.addIssue({code:z.ZodIssueCode.custom,message:`tools policy cannot set both allow and alsoAllow in the same scope (merge alsoAllow into allow, or remove allow and use profile + alsoAllow)`})}).optional(),ToolsWebSearchSchema=z.object({enabled:z.boolean().optional(),provider:z.union([z.literal(`brave`),z.literal(`perplexity`),z.literal(`grok`),z.literal(`keyless`)]).optional(),apiKey:z.string().optional().register(sensitive),keylessFallback:z.boolean().optional(),keyless:z.object({searxngUrl:z.string().optional()}).strict().optional(),maxResults:z.number().int().positive().optional(),timeoutSeconds:z.number().int().positive().optional(),cacheTtlMinutes:z.number().nonnegative().optional(),perplexity:z.object({apiKey:z.string().optional().register(sensitive),baseUrl:z.string().optional(),model:z.string().optional()}).strict().optional(),grok:z.object({apiKey:z.string().optional().register(sensitive),model:z.string().optional(),inlineCitations:z.boolean().optional()}).strict().optional()}).strict().optional(),ToolsWebFetchSchema=z.object({enabled:z.boolean().optional(),maxChars:z.number().int().positive().optional(),maxCharsCap:z.number().int().positive().optional(),timeoutSeconds:z.number().int().positive().optional(),cacheTtlMinutes:z.number().nonnegative().optional(),maxRedirects:z.number().int().nonnegative().optional(),userAgent:z.string().optional()}).strict().optional(),ToolsWebSchema=z.object({search:ToolsWebSearchSchema,fetch:ToolsWebFetchSchema}).strict().optional(),ToolProfileSchema=z.union([z.literal(`minimal`),z.literal(`coding`),z.literal(`messaging`),z.literal(`full`)]).optional();function addAllowAlsoAllowConflictIssue(value,ctx,message){value.allow&&value.allow.length>0&&value.alsoAllow&&value.alsoAllow.length>0&&ctx.addIssue({code:z.ZodIssueCode.custom,message})}const ToolPolicyWithProfileSchema=z.object({allow:z.array(z.string()).optional(),alsoAllow:z.array(z.string()).optional(),deny:z.array(z.string()).optional(),profile:ToolProfileSchema}).strict().superRefine((value,ctx)=>{addAllowAlsoAllowConflictIssue(value,ctx,`tools.byProvider policy cannot set both allow and alsoAllow in the same scope (merge alsoAllow into allow, or remove allow and use profile + alsoAllow)`)}),ElevatedAllowFromSchema=z.record(z.string(),z.array(z.union([z.string(),z.number()]))).optional(),ToolExecApplyPatchSchema=z.object({enabled:z.boolean().optional(),workspaceOnly:z.boolean().optional(),allowModels:z.array(z.string()).optional()}).strict().optional(),ToolExecBaseShape={host:z.enum([`sandbox`,`gateway`,`node`]).optional(),security:z.enum([`deny`,`allowlist`,`full`]).optional(),ask:z.enum([`off`,`on-miss`,`always`]).optional(),node:z.string().optional(),pathPrepend:z.array(z.string()).optional(),safeBins:z.array(z.string()).optional(),backgroundMs:z.number().int().positive().optional(),timeoutSec:z.number().int().positive().optional(),cleanupMs:z.number().int().positive().optional(),notifyOnExit:z.boolean().optional(),notifyOnExitEmptySuccess:z.boolean().optional(),applyPatch:ToolExecApplyPatchSchema},AgentToolExecSchema=z.object({...ToolExecBaseShape,approvalRunningNoticeMs:z.number().int().nonnegative().optional()}).strict().optional(),ToolExecSchema=z.object(ToolExecBaseShape).strict().optional(),ToolFsSchema=z.object({workspaceOnly:z.boolean().optional(),convergedFileTools:z.boolean().optional()}).strict().optional(),ToolLoopDetectionDetectorSchema=z.object({genericRepeat:z.boolean().optional(),knownPollNoProgress:z.boolean().optional(),pingPong:z.boolean().optional()}).strict().optional(),ToolLoopDetectionSchema=z.object({enabled:z.boolean().optional(),historySize:z.number().int().positive().optional(),warningThreshold:z.number().int().positive().optional(),criticalThreshold:z.number().int().positive().optional(),globalCircuitBreakerThreshold:z.number().int().positive().optional(),detectors:ToolLoopDetectionDetectorSchema}).strict().superRefine((value,ctx)=>{value.warningThreshold!==void 0&&value.criticalThreshold!==void 0&&value.warningThreshold>=value.criticalThreshold&&ctx.addIssue({code:z.ZodIssueCode.custom,path:[`criticalThreshold`],message:`tools.loopDetection.warningThreshold must be lower than criticalThreshold.`}),value.criticalThreshold!==void 0&&value.globalCircuitBreakerThreshold!==void 0&&value.criticalThreshold>=value.globalCircuitBreakerThreshold&&ctx.addIssue({code:z.ZodIssueCode.custom,path:[`globalCircuitBreakerThreshold`],message:`tools.loopDetection.criticalThreshold must be lower than globalCircuitBreakerThreshold.`})}).optional(),AgentSandboxSchema=z.object({mode:z.union([z.literal(`off`),z.literal(`non-main`),z.literal(`all`)]).optional(),workspaceAccess:z.union([z.literal(`none`),z.literal(`ro`),z.literal(`rw`)]).optional(),sessionToolsVisibility:z.union([z.literal(`spawned`),z.literal(`all`)]).optional(),scope:z.union([z.literal(`session`),z.literal(`agent`),z.literal(`shared`)]).optional(),perSession:z.boolean().optional(),workspaceRoot:z.string().optional(),docker:SandboxDockerSchema,browser:SandboxBrowserSchema,prune:SandboxPruneSchema}).strict().optional(),AgentToolsSchema=z.object({profile:ToolProfileSchema,allow:z.array(z.string()).optional(),alsoAllow:z.array(z.string()).optional(),deny:z.array(z.string()).optional(),byProvider:z.record(z.string(),ToolPolicyWithProfileSchema).optional(),elevated:z.object({enabled:z.boolean().optional(),allowFrom:ElevatedAllowFromSchema}).strict().optional(),exec:AgentToolExecSchema,fs:ToolFsSchema,loopDetection:ToolLoopDetectionSchema,sandbox:z.object({tools:ToolPolicySchema}).strict().optional()}).strict().superRefine((value,ctx)=>{addAllowAlsoAllowConflictIssue(value,ctx,`agent tools cannot set both allow and alsoAllow in the same scope (merge alsoAllow into allow, or remove allow and use profile + alsoAllow)`)}).optional(),MemorySearchSchema=z.object({enabled:z.boolean().optional(),sources:z.array(z.union([z.literal(`memory`),z.literal(`sessions`)])).optional(),extraPaths:z.array(z.string()).optional(),experimental:z.object({sessionMemory:z.boolean().optional()}).strict().optional(),provider:z.union([z.literal(`openai`),z.literal(`local`),z.literal(`gemini`),z.literal(`voyage`)]).optional(),remote:z.object({baseUrl:z.string().optional(),apiKey:z.string().optional().register(sensitive),headers:z.record(z.string(),z.string()).optional(),batch:z.object({enabled:z.boolean().optional(),wait:z.boolean().optional(),concurrency:z.number().int().positive().optional(),pollIntervalMs:z.number().int().nonnegative().optional(),timeoutMinutes:z.number().int().positive().optional()}).strict().optional()}).strict().optional(),fallback:z.union([z.literal(`openai`),z.literal(`gemini`),z.literal(`local`),z.literal(`voyage`),z.literal(`none`)]).optional(),model:z.string().optional(),local:z.object({modelPath:z.string().optional(),modelCacheDir:z.string().optional()}).strict().optional(),store:z.object({driver:z.literal(`sqlite`).optional(),path:z.string().optional(),vector:z.object({enabled:z.boolean().optional(),extensionPath:z.string().optional()}).strict().optional()}).strict().optional(),chunking:z.object({tokens:z.number().int().positive().optional(),overlap:z.number().int().nonnegative().optional()}).strict().optional(),sync:z.object({onSessionStart:z.boolean().optional(),onSearch:z.boolean().optional(),watch:z.boolean().optional(),watchDebounceMs:z.number().int().nonnegative().optional(),intervalMinutes:z.number().int().nonnegative().optional(),sessions:z.object({deltaBytes:z.number().int().nonnegative().optional(),deltaMessages:z.number().int().nonnegative().optional()}).strict().optional()}).strict().optional(),query:z.object({maxResults:z.number().int().positive().optional(),minScore:z.number().min(0).max(1).optional(),hybrid:z.object({enabled:z.boolean().optional(),vectorWeight:z.number().min(0).max(1).optional(),textWeight:z.number().min(0).max(1).optional(),candidateMultiplier:z.number().int().positive().optional(),mmr:z.object({enabled:z.boolean().optional(),lambda:z.number().min(0).max(1).optional()}).strict().optional(),temporalDecay:z.object({enabled:z.boolean().optional(),halfLifeDays:z.number().int().positive().optional()}).strict().optional()}).strict().optional()}).strict().optional(),cache:z.object({enabled:z.boolean().optional(),maxEntries:z.number().int().positive().optional()}).strict().optional()}).strict().optional(),AgentEntrySchema=z.object({id:z.string(),default:z.boolean().optional(),name:z.string().optional(),workspace:z.string().optional(),agentDir:z.string().optional(),model:AgentModelSchema.optional(),skills:z.array(z.string()).optional(),memorySearch:MemorySearchSchema,humanDelay:HumanDelaySchema.optional(),heartbeat:HeartbeatSchema,identity:IdentitySchema,groupChat:GroupChatSchema,subagents:z.object({allowAgents:z.array(z.string()).optional(),model:z.union([z.string(),z.object({primary:z.string().optional(),fallbacks:z.array(z.string()).optional()}).strict()]).optional(),thinking:z.string().optional()}).strict().optional(),sandbox:AgentSandboxSchema,tools:AgentToolsSchema}).strict(),ToolsSchema=z.object({profile:ToolProfileSchema,allow:z.array(z.string()).optional(),alsoAllow:z.array(z.string()).optional(),deny:z.array(z.string()).optional(),byProvider:z.record(z.string(),ToolPolicyWithProfileSchema).optional(),web:ToolsWebSchema,media:ToolsMediaSchema,links:ToolsLinksSchema,sessions:z.object({visibility:z.enum([`self`,`tree`,`agent`,`all`]).optional()}).strict().optional(),loopDetection:ToolLoopDetectionSchema,message:z.object({allowCrossContextSend:z.boolean().optional(),crossContext:z.object({allowWithinProvider:z.boolean().optional(),allowAcrossProviders:z.boolean().optional(),marker:z.object({enabled:z.boolean().optional(),prefix:z.string().optional(),suffix:z.string().optional()}).strict().optional()}).strict().optional(),broadcast:z.object({enabled:z.boolean().optional()}).strict().optional()}).strict().optional(),agentToAgent:z.object({enabled:z.boolean().optional(),allow:z.array(z.string()).optional()}).strict().optional(),elevated:z.object({enabled:z.boolean().optional(),allowFrom:ElevatedAllowFromSchema}).strict().optional(),exec:ToolExecSchema,fs:ToolFsSchema,subagents:z.object({tools:ToolPolicySchema}).strict().optional(),sandbox:z.object({tools:ToolPolicySchema}).strict().optional()}).strict().superRefine((value,ctx)=>{addAllowAlsoAllowConflictIssue(value,ctx,`tools cannot set both allow and alsoAllow in the same scope (merge alsoAllow into allow, or remove allow and use profile + alsoAllow)`)}).optional(),ChannelHeartbeatVisibilitySchema=z.object({showOk:z.boolean().optional(),showAlerts:z.boolean().optional(),useIndicator:z.boolean().optional()}).strict().optional(),ToolPolicyBySenderSchema$1=z.record(z.string(),ToolPolicySchema).optional(),DiscordIdSchema=z.union([z.string(),z.number()]).refine(value=>typeof value==`string`,{message:`Discord IDs must be strings (wrap numeric IDs in quotes).`}),DiscordIdListSchema=z.array(DiscordIdSchema),TelegramInlineButtonsScopeSchema=z.enum([`off`,`dm`,`group`,`all`,`allowlist`]),TelegramCapabilitiesSchema=z.union([z.array(z.string()),z.object({inlineButtons:TelegramInlineButtonsScopeSchema.optional()}).strict()]),TelegramTopicSchema=z.object({requireMention:z.boolean().optional(),groupPolicy:GroupPolicySchema.optional(),skills:z.array(z.string()).optional(),enabled:z.boolean().optional(),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),systemPrompt:z.string().optional()}).strict(),TelegramGroupSchema=z.object({requireMention:z.boolean().optional(),groupPolicy:GroupPolicySchema.optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1,skills:z.array(z.string()).optional(),enabled:z.boolean().optional(),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),systemPrompt:z.string().optional(),topics:z.record(z.string(),TelegramTopicSchema.optional()).optional()}).strict(),TelegramCustomCommandSchema=z.object({command:z.string().transform(normalizeTelegramCommandName),description:z.string().transform(normalizeTelegramCommandDescription)}).strict(),validateTelegramCustomCommands=(value,ctx)=>{if(!value.customCommands||value.customCommands.length===0)return;let{issues}=resolveTelegramCustomCommands({commands:value.customCommands,checkReserved:!1,checkDuplicates:!1});for(let issue of issues)ctx.addIssue({code:z.ZodIssueCode.custom,path:[`customCommands`,issue.index,issue.field],message:issue.message})},TelegramAccountSchemaBase=z.object({name:z.string().optional(),capabilities:TelegramCapabilitiesSchema.optional(),markdown:MarkdownConfigSchema,enabled:z.boolean().optional(),commands:ProviderCommandsSchema,customCommands:z.array(TelegramCustomCommandSchema).optional(),configWrites:z.boolean().optional(),dmPolicy:DmPolicySchema.optional().default(`pairing`),botToken:z.string().optional().register(sensitive),tokenFile:z.string().optional(),replyToMode:ReplyToModeSchema.optional(),groups:z.record(z.string(),TelegramGroupSchema.optional()).optional(),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupAllowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),draftChunk:BlockStreamingChunkSchema.optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),streamMode:z.enum([`off`,`partial`,`block`]).optional().default(`partial`),mediaMaxMb:z.number().positive().optional(),timeoutSeconds:z.number().int().positive().optional(),retry:RetryConfigSchema,network:z.object({autoSelectFamily:z.boolean().optional()}).strict().optional(),proxy:z.string().optional(),webhookUrl:z.string().optional(),webhookSecret:z.string().optional().register(sensitive),webhookPath:z.string().optional(),webhookHost:z.string().optional(),actions:z.object({reactions:z.boolean().optional(),sendMessage:z.boolean().optional(),deleteMessage:z.boolean().optional(),sticker:z.boolean().optional()}).strict().optional(),reactionNotifications:z.enum([`off`,`own`,`all`]).optional(),reactionLevel:z.enum([`off`,`ack`,`minimal`,`extensive`]).optional(),heartbeat:ChannelHeartbeatVisibilitySchema,linkPreview:z.boolean().optional(),responsePrefix:z.string().optional(),ackReaction:z.string().optional()}).strict(),TelegramAccountSchema=TelegramAccountSchemaBase.superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.telegram.dmPolicy="open" requires channels.telegram.allowFrom to include "*"`}),validateTelegramCustomCommands(value,ctx)}),TelegramConfigSchema=TelegramAccountSchemaBase.extend({accounts:z.record(z.string(),TelegramAccountSchema.optional()).optional()}).superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.telegram.dmPolicy="open" requires channels.telegram.allowFrom to include "*"`}),validateTelegramCustomCommands(value,ctx);let baseWebhookUrl=typeof value.webhookUrl==`string`?value.webhookUrl.trim():``,baseWebhookSecret=typeof value.webhookSecret==`string`?value.webhookSecret.trim():``;if(baseWebhookUrl&&!baseWebhookSecret&&ctx.addIssue({code:z.ZodIssueCode.custom,message:`channels.telegram.webhookUrl requires channels.telegram.webhookSecret`,path:[`webhookSecret`]}),value.accounts)for(let[accountId,account]of Object.entries(value.accounts))account&&account.enabled!==!1&&typeof account.webhookUrl==`string`&&account.webhookUrl.trim()&&!(typeof account.webhookSecret==`string`&&account.webhookSecret.trim())&&!baseWebhookSecret&&ctx.addIssue({code:z.ZodIssueCode.custom,message:`channels.telegram.accounts.*.webhookUrl requires channels.telegram.webhookSecret or channels.telegram.accounts.*.webhookSecret`,path:[`accounts`,accountId,`webhookSecret`]})}),DiscordDmSchema=z.object({enabled:z.boolean().optional(),policy:DmPolicySchema.optional(),allowFrom:DiscordIdListSchema.optional(),groupEnabled:z.boolean().optional(),groupChannels:DiscordIdListSchema.optional()}).strict(),DiscordGuildChannelSchema=z.object({allow:z.boolean().optional(),requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1,skills:z.array(z.string()).optional(),enabled:z.boolean().optional(),users:DiscordIdListSchema.optional(),roles:DiscordIdListSchema.optional(),systemPrompt:z.string().optional(),includeThreadStarter:z.boolean().optional(),autoThread:z.boolean().optional()}).strict(),DiscordGuildSchema=z.object({slug:z.string().optional(),requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1,reactionNotifications:z.enum([`off`,`own`,`all`,`allowlist`]).optional(),users:DiscordIdListSchema.optional(),roles:DiscordIdListSchema.optional(),channels:z.record(z.string(),DiscordGuildChannelSchema.optional()).optional()}).strict(),DiscordUiSchema=z.object({components:z.object({accentColor:HexColorSchema.optional()}).strict().optional()}).strict().optional(),DiscordAccountSchema=z.object({name:z.string().optional(),capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,enabled:z.boolean().optional(),commands:ProviderCommandsSchema,configWrites:z.boolean().optional(),token:z.string().optional().register(sensitive),proxy:z.string().optional(),allowBots:z.boolean().optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),maxLinesPerMessage:z.number().int().positive().optional(),mediaMaxMb:z.number().positive().optional(),retry:RetryConfigSchema,actions:z.object({reactions:z.boolean().optional(),stickers:z.boolean().optional(),emojiUploads:z.boolean().optional(),stickerUploads:z.boolean().optional(),polls:z.boolean().optional(),permissions:z.boolean().optional(),messages:z.boolean().optional(),threads:z.boolean().optional(),pins:z.boolean().optional(),search:z.boolean().optional(),memberInfo:z.boolean().optional(),roleInfo:z.boolean().optional(),roles:z.boolean().optional(),channelInfo:z.boolean().optional(),voiceStatus:z.boolean().optional(),events:z.boolean().optional(),moderation:z.boolean().optional(),channels:z.boolean().optional(),presence:z.boolean().optional()}).strict().optional(),replyToMode:ReplyToModeSchema.optional(),dmPolicy:DmPolicySchema.optional(),allowFrom:DiscordIdListSchema.optional(),dm:DiscordDmSchema.optional(),guilds:z.record(z.string(),DiscordGuildSchema.optional()).optional(),heartbeat:ChannelHeartbeatVisibilitySchema,execApprovals:z.object({enabled:z.boolean().optional(),approvers:DiscordIdListSchema.optional(),agentFilter:z.array(z.string()).optional(),sessionFilter:z.array(z.string()).optional(),cleanupAfterResolve:z.boolean().optional(),target:z.enum([`dm`,`channel`,`both`]).optional()}).strict().optional(),ui:DiscordUiSchema,intents:z.object({presence:z.boolean().optional(),guildMembers:z.boolean().optional()}).strict().optional(),pluralkit:z.object({enabled:z.boolean().optional(),token:z.string().optional().register(sensitive)}).strict().optional(),responsePrefix:z.string().optional(),ackReaction:z.string().optional(),activity:z.string().optional(),status:z.enum([`online`,`dnd`,`idle`,`invisible`]).optional(),activityType:z.union([z.literal(0),z.literal(1),z.literal(2),z.literal(3),z.literal(4),z.literal(5)]).optional(),activityUrl:z.string().url().optional()}).strict().superRefine((value,ctx)=>{let hasActivity=!!(typeof value.activity==`string`&&value.activity.trim()),hasActivityType=value.activityType!==void 0,hasActivityUrl=!!(typeof value.activityUrl==`string`&&value.activityUrl.trim());(hasActivityType||hasActivityUrl)&&!hasActivity&&ctx.addIssue({code:z.ZodIssueCode.custom,message:`channels.discord.activity is required when activityType or activityUrl is set`,path:[`activity`]}),value.activityType===1&&!hasActivityUrl&&ctx.addIssue({code:z.ZodIssueCode.custom,message:`channels.discord.activityUrl is required when activityType is 1 (Streaming)`,path:[`activityUrl`]}),hasActivityUrl&&value.activityType!==1&&ctx.addIssue({code:z.ZodIssueCode.custom,message:`channels.discord.activityType must be 1 (Streaming) when activityUrl is set`,path:[`activityType`]}),requireOpenAllowFrom({policy:value.dmPolicy??value.dm?.policy??`pairing`,allowFrom:value.allowFrom??value.dm?.allowFrom,ctx,path:[...value.allowFrom===void 0?[`dm`,`allowFrom`]:[`allowFrom`]],message:`channels.discord.dmPolicy="open" requires channels.discord.allowFrom (or channels.discord.dm.allowFrom) to include "*"`})}),DiscordConfigSchema=DiscordAccountSchema.extend({accounts:z.record(z.string(),DiscordAccountSchema.optional()).optional()}),GoogleChatDmSchema=z.object({enabled:z.boolean().optional(),policy:DmPolicySchema.optional().default(`pairing`),allowFrom:z.array(z.union([z.string(),z.number()])).optional()}).strict().superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.policy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.googlechat.dm.policy="open" requires channels.googlechat.dm.allowFrom to include "*"`})}),GoogleChatGroupSchema=z.object({enabled:z.boolean().optional(),allow:z.boolean().optional(),requireMention:z.boolean().optional(),users:z.array(z.union([z.string(),z.number()])).optional(),systemPrompt:z.string().optional()}).strict(),GoogleChatAccountSchema=z.object({name:z.string().optional(),capabilities:z.array(z.string()).optional(),enabled:z.boolean().optional(),configWrites:z.boolean().optional(),allowBots:z.boolean().optional(),requireMention:z.boolean().optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),groupAllowFrom:z.array(z.union([z.string(),z.number()])).optional(),groups:z.record(z.string(),GoogleChatGroupSchema.optional()).optional(),serviceAccount:z.union([z.string(),z.record(z.string(),z.unknown())]).optional(),serviceAccountFile:z.string().optional(),audienceType:z.enum([`app-url`,`project-number`]).optional(),audience:z.string().optional(),webhookPath:z.string().optional(),webhookUrl:z.string().optional(),botUser:z.string().optional(),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),streamMode:z.enum([`replace`,`status_final`,`append`]).optional().default(`replace`),mediaMaxMb:z.number().positive().optional(),replyToMode:ReplyToModeSchema.optional(),actions:z.object({reactions:z.boolean().optional()}).strict().optional(),dm:GoogleChatDmSchema.optional(),typingIndicator:z.enum([`none`,`message`,`reaction`]).optional(),responsePrefix:z.string().optional()}).strict(),GoogleChatConfigSchema=GoogleChatAccountSchema.extend({accounts:z.record(z.string(),GoogleChatAccountSchema.optional()).optional(),defaultAccount:z.string().optional()}),SlackDmSchema=z.object({enabled:z.boolean().optional(),policy:DmPolicySchema.optional(),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupEnabled:z.boolean().optional(),groupChannels:z.array(z.union([z.string(),z.number()])).optional(),replyToMode:ReplyToModeSchema.optional()}).strict(),SlackChannelSchema=z.object({enabled:z.boolean().optional(),allow:z.boolean().optional(),requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1,allowBots:z.boolean().optional(),users:z.array(z.union([z.string(),z.number()])).optional(),skills:z.array(z.string()).optional(),systemPrompt:z.string().optional()}).strict(),SlackThreadSchema=z.object({historyScope:z.enum([`thread`,`channel`]).optional(),inheritParent:z.boolean().optional(),initialHistoryLimit:z.number().int().min(0).optional()}).strict(),SlackReplyToModeByChatTypeSchema=z.object({direct:ReplyToModeSchema.optional(),group:ReplyToModeSchema.optional(),channel:ReplyToModeSchema.optional()}).strict(),SlackAccountSchema=z.object({name:z.string().optional(),mode:z.enum([`socket`,`http`]).optional(),signingSecret:z.string().optional().register(sensitive),webhookPath:z.string().optional(),capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,enabled:z.boolean().optional(),commands:ProviderCommandsSchema,configWrites:z.boolean().optional(),botToken:z.string().optional().register(sensitive),appToken:z.string().optional().register(sensitive),userToken:z.string().optional().register(sensitive),userTokenReadOnly:z.boolean().optional().default(!0),allowBots:z.boolean().optional(),requireMention:z.boolean().optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),streaming:z.boolean().optional(),mediaMaxMb:z.number().positive().optional(),reactionNotifications:z.enum([`off`,`own`,`all`,`allowlist`]).optional(),reactionAllowlist:z.array(z.union([z.string(),z.number()])).optional(),replyToMode:ReplyToModeSchema.optional(),replyToModeByChatType:SlackReplyToModeByChatTypeSchema.optional(),thread:SlackThreadSchema.optional(),actions:z.object({reactions:z.boolean().optional(),messages:z.boolean().optional(),pins:z.boolean().optional(),search:z.boolean().optional(),permissions:z.boolean().optional(),memberInfo:z.boolean().optional(),channelInfo:z.boolean().optional(),emojiList:z.boolean().optional()}).strict().optional(),slashCommand:z.object({enabled:z.boolean().optional(),name:z.string().optional(),sessionPrefix:z.string().optional(),ephemeral:z.boolean().optional()}).strict().optional(),dmPolicy:DmPolicySchema.optional(),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),dm:SlackDmSchema.optional(),channels:z.record(z.string(),SlackChannelSchema.optional()).optional(),heartbeat:ChannelHeartbeatVisibilitySchema,responsePrefix:z.string().optional(),ackReaction:z.string().optional()}).strict().superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy??value.dm?.policy??`pairing`,allowFrom:value.allowFrom??value.dm?.allowFrom,ctx,path:[...value.allowFrom===void 0?[`dm`,`allowFrom`]:[`allowFrom`]],message:`channels.slack.dmPolicy="open" requires channels.slack.allowFrom (or channels.slack.dm.allowFrom) to include "*"`})}),SlackConfigSchema=SlackAccountSchema.safeExtend({mode:z.enum([`socket`,`http`]).optional().default(`socket`),signingSecret:z.string().optional().register(sensitive),webhookPath:z.string().optional().default(`/slack/events`),accounts:z.record(z.string(),SlackAccountSchema.optional()).optional()}).superRefine((value,ctx)=>{let baseMode=value.mode??`socket`;if(baseMode===`http`&&!value.signingSecret&&ctx.addIssue({code:z.ZodIssueCode.custom,message:`channels.slack.mode="http" requires channels.slack.signingSecret`,path:[`signingSecret`]}),value.accounts)for(let[accountId,account]of Object.entries(value.accounts))account&&account.enabled!==!1&&(account.mode??baseMode)===`http`&&((account.signingSecret??value.signingSecret)||ctx.addIssue({code:z.ZodIssueCode.custom,message:`channels.slack.accounts.*.mode="http" requires channels.slack.signingSecret or channels.slack.accounts.*.signingSecret`,path:[`accounts`,accountId,`signingSecret`]}))}),SignalAccountSchemaBase=z.object({name:z.string().optional(),capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,enabled:z.boolean().optional(),configWrites:z.boolean().optional(),account:z.string().optional(),httpUrl:z.string().optional(),httpHost:z.string().optional(),httpPort:z.number().int().positive().optional(),cliPath:ExecutableTokenSchema.optional(),autoStart:z.boolean().optional(),startupTimeoutMs:z.number().int().min(1e3).max(12e4).optional(),receiveMode:z.union([z.literal(`on-start`),z.literal(`manual`)]).optional(),ignoreAttachments:z.boolean().optional(),ignoreStories:z.boolean().optional(),sendReadReceipts:z.boolean().optional(),dmPolicy:DmPolicySchema.optional().default(`pairing`),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupAllowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),mediaMaxMb:z.number().int().positive().optional(),reactionNotifications:z.enum([`off`,`own`,`all`,`allowlist`]).optional(),reactionAllowlist:z.array(z.union([z.string(),z.number()])).optional(),actions:z.object({reactions:z.boolean().optional()}).strict().optional(),reactionLevel:z.enum([`off`,`ack`,`minimal`,`extensive`]).optional(),heartbeat:ChannelHeartbeatVisibilitySchema,responsePrefix:z.string().optional()}).strict(),SignalAccountSchema=SignalAccountSchemaBase.superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.signal.dmPolicy="open" requires channels.signal.allowFrom to include "*"`})}),SignalConfigSchema=SignalAccountSchemaBase.extend({accounts:z.record(z.string(),SignalAccountSchema.optional()).optional()}).superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.signal.dmPolicy="open" requires channels.signal.allowFrom to include "*"`})}),IrcGroupSchema=z.object({requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1,skills:z.array(z.string()).optional(),enabled:z.boolean().optional(),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),systemPrompt:z.string().optional()}).strict(),IrcNickServSchema=z.object({enabled:z.boolean().optional(),service:z.string().optional(),password:z.string().optional().register(sensitive),passwordFile:z.string().optional(),register:z.boolean().optional(),registerEmail:z.string().optional()}).strict(),IrcAccountSchemaBase=z.object({name:z.string().optional(),capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,enabled:z.boolean().optional(),configWrites:z.boolean().optional(),host:z.string().optional(),port:z.number().int().min(1).max(65535).optional(),tls:z.boolean().optional(),nick:z.string().optional(),username:z.string().optional(),realname:z.string().optional(),password:z.string().optional().register(sensitive),passwordFile:z.string().optional(),nickserv:IrcNickServSchema.optional(),channels:z.array(z.string()).optional(),dmPolicy:DmPolicySchema.optional().default(`pairing`),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupAllowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),groups:z.record(z.string(),IrcGroupSchema.optional()).optional(),mentionPatterns:z.array(z.string()).optional(),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),mediaMaxMb:z.number().positive().optional(),heartbeat:ChannelHeartbeatVisibilitySchema,responsePrefix:z.string().optional()}).strict();function refineIrcAllowFromAndNickserv(value,ctx){requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.irc.dmPolicy="open" requires channels.irc.allowFrom to include "*"`}),value.nickserv?.register&&!value.nickserv.registerEmail?.trim()&&ctx.addIssue({code:z.ZodIssueCode.custom,path:[`nickserv`,`registerEmail`],message:`channels.irc.nickserv.register=true requires channels.irc.nickserv.registerEmail`})}const IrcAccountSchema=IrcAccountSchemaBase.superRefine((value,ctx)=>{refineIrcAllowFromAndNickserv(value,ctx)}),IrcConfigSchema=IrcAccountSchemaBase.extend({accounts:z.record(z.string(),IrcAccountSchema.optional()).optional()}).superRefine((value,ctx)=>{refineIrcAllowFromAndNickserv(value,ctx)}),IMessageAccountSchemaBase=z.object({name:z.string().optional(),capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,enabled:z.boolean().optional(),configWrites:z.boolean().optional(),cliPath:ExecutableTokenSchema.optional(),dbPath:z.string().optional(),remoteHost:z.string().optional(),service:z.union([z.literal(`imessage`),z.literal(`sms`),z.literal(`auto`)]).optional(),region:z.string().optional(),dmPolicy:DmPolicySchema.optional().default(`pairing`),allowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupAllowFrom:z.array(z.union([z.string(),z.number()])).optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),includeAttachments:z.boolean().optional(),mediaMaxMb:z.number().int().positive().optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),groups:z.record(z.string(),z.object({requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1}).strict().optional()).optional(),heartbeat:ChannelHeartbeatVisibilitySchema,responsePrefix:z.string().optional()}).strict(),IMessageAccountSchema=IMessageAccountSchemaBase.superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.imessage.dmPolicy="open" requires channels.imessage.allowFrom to include "*"`})}),IMessageConfigSchema=IMessageAccountSchemaBase.extend({accounts:z.record(z.string(),IMessageAccountSchema.optional()).optional()}).superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.imessage.dmPolicy="open" requires channels.imessage.allowFrom to include "*"`})}),BlueBubblesAllowFromEntry=z.union([z.string(),z.number()]),BlueBubblesActionSchema=z.object({reactions:z.boolean().optional(),edit:z.boolean().optional(),unsend:z.boolean().optional(),reply:z.boolean().optional(),sendWithEffect:z.boolean().optional(),renameGroup:z.boolean().optional(),setGroupIcon:z.boolean().optional(),addParticipant:z.boolean().optional(),removeParticipant:z.boolean().optional(),leaveGroup:z.boolean().optional(),sendAttachment:z.boolean().optional()}).strict().optional(),BlueBubblesGroupConfigSchema=z.object({requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1}).strict(),BlueBubblesAccountSchemaBase=z.object({name:z.string().optional(),capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,configWrites:z.boolean().optional(),enabled:z.boolean().optional(),serverUrl:z.string().optional(),password:z.string().optional().register(sensitive),webhookPath:z.string().optional(),dmPolicy:DmPolicySchema.optional().default(`pairing`),allowFrom:z.array(BlueBubblesAllowFromEntry).optional(),groupAllowFrom:z.array(BlueBubblesAllowFromEntry).optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),mediaMaxMb:z.number().int().positive().optional(),mediaLocalRoots:z.array(z.string()).optional(),sendReadReceipts:z.boolean().optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),groups:z.record(z.string(),BlueBubblesGroupConfigSchema.optional()).optional(),heartbeat:ChannelHeartbeatVisibilitySchema,responsePrefix:z.string().optional()}).strict(),BlueBubblesAccountSchema=BlueBubblesAccountSchemaBase.superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.bluebubbles.accounts.*.dmPolicy="open" requires allowFrom to include "*"`})}),BlueBubblesConfigSchema=BlueBubblesAccountSchemaBase.extend({accounts:z.record(z.string(),BlueBubblesAccountSchema.optional()).optional(),actions:BlueBubblesActionSchema}).superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.bluebubbles.dmPolicy="open" requires channels.bluebubbles.allowFrom to include "*"`})}),MSTeamsChannelSchema=z.object({requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1,replyStyle:MSTeamsReplyStyleSchema.optional()}).strict(),MSTeamsTeamSchema=z.object({requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema$1,replyStyle:MSTeamsReplyStyleSchema.optional(),channels:z.record(z.string(),MSTeamsChannelSchema.optional()).optional()}).strict(),MSTeamsConfigSchema=z.object({enabled:z.boolean().optional(),capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,configWrites:z.boolean().optional(),appId:z.string().optional(),appPassword:z.string().optional().register(sensitive),tenantId:z.string().optional(),webhook:z.object({port:z.number().int().positive().optional(),path:z.string().optional()}).strict().optional(),dmPolicy:DmPolicySchema.optional().default(`pairing`),allowFrom:z.array(z.string()).optional(),groupAllowFrom:z.array(z.string()).optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),mediaAllowHosts:z.array(z.string()).optional(),mediaAuthAllowHosts:z.array(z.string()).optional(),requireMention:z.boolean().optional(),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),replyStyle:MSTeamsReplyStyleSchema.optional(),teams:z.record(z.string(),MSTeamsTeamSchema.optional()).optional(),mediaMaxMb:z.number().positive().optional(),sharePointSiteId:z.string().optional(),heartbeat:ChannelHeartbeatVisibilitySchema,responsePrefix:z.string().optional()}).strict().superRefine((value,ctx)=>{requireOpenAllowFrom({policy:value.dmPolicy,allowFrom:value.allowFrom,ctx,path:[`allowFrom`],message:`channels.msteams.dmPolicy="open" requires channels.msteams.allowFrom to include "*"`})}),ToolPolicyBySenderSchema=z.record(z.string(),ToolPolicySchema).optional(),WhatsAppGroupEntrySchema=z.object({requireMention:z.boolean().optional(),tools:ToolPolicySchema,toolsBySender:ToolPolicyBySenderSchema}).strict().optional(),WhatsAppGroupsSchema=z.record(z.string(),WhatsAppGroupEntrySchema).optional(),WhatsAppAckReactionSchema=z.object({emoji:z.string().optional(),direct:z.boolean().optional().default(!0),group:z.enum([`always`,`mentions`,`never`]).optional().default(`mentions`)}).strict().optional(),WhatsAppSharedSchema=z.object({capabilities:z.array(z.string()).optional(),markdown:MarkdownConfigSchema,configWrites:z.boolean().optional(),sendReadReceipts:z.boolean().optional(),messagePrefix:z.string().optional(),responsePrefix:z.string().optional(),dmPolicy:DmPolicySchema.optional().default(`pairing`),selfChatMode:z.boolean().optional(),allowFrom:z.array(z.string()).optional(),groupAllowFrom:z.array(z.string()).optional(),groupPolicy:GroupPolicySchema.optional().default(`allowlist`),historyLimit:z.number().int().min(0).optional(),dmHistoryLimit:z.number().int().min(0).optional(),dms:z.record(z.string(),DmConfigSchema.optional()).optional(),textChunkLimit:z.number().int().positive().optional(),chunkMode:z.enum([`length`,`newline`]).optional(),blockStreaming:z.boolean().optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),groups:WhatsAppGroupsSchema,ackReaction:WhatsAppAckReactionSchema,debounceMs:z.number().int().nonnegative().optional().default(0),heartbeat:ChannelHeartbeatVisibilitySchema});function enforceOpenDmPolicyAllowFromStar(params){params.dmPolicy===`open`&&((Array.isArray(params.allowFrom)?params.allowFrom:[]).map(v=>String(v).trim()).filter(Boolean).includes(`*`)||params.ctx.addIssue({code:z.ZodIssueCode.custom,path:[`allowFrom`],message:params.message}))}const WhatsAppAccountSchema=WhatsAppSharedSchema.extend({name:z.string().optional(),enabled:z.boolean().optional(),authDir:z.string().optional(),mediaMaxMb:z.number().int().positive().optional()}).strict().superRefine((value,ctx)=>{enforceOpenDmPolicyAllowFromStar({dmPolicy:value.dmPolicy,allowFrom:value.allowFrom,ctx,message:`channels.whatsapp.accounts.*.dmPolicy="open" requires allowFrom to include "*"`})}),WhatsAppConfigSchema=WhatsAppSharedSchema.extend({accounts:z.record(z.string(),WhatsAppAccountSchema.optional()).optional(),mediaMaxMb:z.number().int().positive().optional().default(50),actions:z.object({reactions:z.boolean().optional(),sendMessage:z.boolean().optional(),polls:z.boolean().optional()}).strict().optional()}).strict().superRefine((value,ctx)=>{enforceOpenDmPolicyAllowFromStar({dmPolicy:value.dmPolicy,allowFrom:value.allowFrom,ctx,message:`channels.whatsapp.dmPolicy="open" requires channels.whatsapp.allowFrom to include "*"`})});function loadDotEnv(opts){let quiet=opts?.quiet??!0;dotenv.config({quiet});let globalEnvPath=path.join(resolveConfigDir(process.env),`.env`);fs.existsSync(globalEnvPath)&&dotenv.config({quiet,path:globalEnvPath,override:!1})}const PACKAGE_JSON_CANDIDATES=[`../package.json`,`../../package.json`,`../../../package.json`,`./package.json`],BUILD_INFO_CANDIDATES=[`../build-info.json`,`../../build-info.json`,`./build-info.json`];function readVersionFromJsonCandidates(moduleUrl,candidates,opts={}){try{let require=createRequire(moduleUrl);for(let candidate of candidates)try{let parsed=require(candidate),version=parsed.version?.trim();if(!version||opts.requirePackageName&&parsed.name!==`builderforce`)continue;return version}catch{}return null}catch{return null}}function readVersionFromPackageJsonForModuleUrl(moduleUrl){return readVersionFromJsonCandidates(moduleUrl,PACKAGE_JSON_CANDIDATES,{requirePackageName:!0})}function readVersionFromBuildInfoForModuleUrl(moduleUrl){return readVersionFromJsonCandidates(moduleUrl,BUILD_INFO_CANDIDATES)}function resolveVersionFromModuleUrl(moduleUrl){return readVersionFromPackageJsonForModuleUrl(moduleUrl)||readVersionFromBuildInfoForModuleUrl(moduleUrl)}const VERSION=typeof __BUILDERFORCE_AGENTS_VERSION__==`string`&&__BUILDERFORCE_AGENTS_VERSION__||process.env.BUILDERFORCE_AGENTS_BUNDLED_VERSION||resolveVersionFromModuleUrl(import.meta.url)||`0.0.0`;var DuplicateAgentDirError=class extends Error{constructor(duplicates){super(formatDuplicateAgentDirError(duplicates)),this.name=`DuplicateAgentDirError`,this.duplicates=duplicates}};function canonicalizeAgentDir(agentDir){let resolved=path.resolve(agentDir);return process.platform===`darwin`||process.platform===`win32`?resolved.toLowerCase():resolved}function collectReferencedAgentIds(cfg){let ids=new Set,agents=Array.isArray(cfg.agents?.list)?cfg.agents?.list:[],defaultAgentId=agents.find(agent=>agent?.default)?.id??agents[0]?.id??DEFAULT_AGENT_ID;ids.add(normalizeAgentId(defaultAgentId));for(let entry of agents)entry?.id&&ids.add(normalizeAgentId(entry.id));let bindings=cfg.bindings;if(Array.isArray(bindings))for(let binding of bindings){let id=binding?.agentId;typeof id==`string`&&id.trim()&&ids.add(normalizeAgentId(id))}return[...ids]}function resolveEffectiveAgentDir(cfg,agentId,deps){let id=normalizeAgentId(agentId),trimmed=(Array.isArray(cfg.agents?.list)?cfg.agents?.list.find(agent=>normalizeAgentId(agent.id)===id)?.agentDir:void 0)?.trim();if(trimmed)return resolveUserPath(trimmed);let env=deps?.env??process.env,root=resolveStateDir(env,deps?.homedir??(()=>resolveRequiredHomeDir(env,os.homedir)));return path.join(root,`agents`,id,`agent`)}function findDuplicateAgentDirs(cfg,deps){let byDir=new Map;for(let agentId of collectReferencedAgentIds(cfg)){let agentDir=resolveEffectiveAgentDir(cfg,agentId,deps),key=canonicalizeAgentDir(agentDir),entry=byDir.get(key);entry?entry.agentIds.push(agentId):byDir.set(key,{agentDir,agentIds:[agentId]})}return[...byDir.values()].filter(v=>v.agentIds.length>1)}function formatDuplicateAgentDirError(dups){return[`Duplicate agentDir detected (multi-agent config).`,`Each agent must have a unique agentDir; sharing it causes auth/session state collisions and token invalidation.`,``,`Conflicts:`,...dups.map(d=>`- ${d.agentDir}: ${d.agentIds.map(id=>`"${id}"`).join(`, `)}`),``,`Fix: remove the shared agents.list[].agentDir override (or give each agent its own directory).`,`If you want to share credentials, copy auth-profiles.json instead of sharing the entire agentDir.`].join(`
|
|
2
|
+
`)}async function rotateConfigBackups(configPath,ioFs){let backupBase=`${configPath}.bak`;await ioFs.unlink(`${backupBase}.4`).catch(()=>{});for(let index=3;index>=1;--index)await ioFs.rename(`${backupBase}.${index}`,`${backupBase}.${index+1}`).catch(()=>{});await ioFs.rename(backupBase,`${backupBase}.1`).catch(()=>{})}function resolveAgentMaxConcurrent(cfg){let raw=cfg?.agents?.defaults?.maxConcurrent;return typeof raw==`number`&&Number.isFinite(raw)?Math.max(1,Math.floor(raw)):4}function readTalkApiKeyFromProfile(deps={}){let fsImpl=deps.fs??fs,osImpl=deps.os??os,pathImpl=deps.path??path,home=osImpl.homedir(),candidates=[`.profile`,`.zprofile`,`.zshrc`,`.bashrc`].map(name=>pathImpl.join(home,name));for(let candidate of candidates)if(fsImpl.existsSync(candidate))try{let value=fsImpl.readFileSync(candidate,`utf-8`).match(/(?:^|\n)\s*(?:export\s+)?ELEVENLABS_API_KEY\s*=\s*["']?([^\n"']+)["']?/)?.[1]?.trim();if(value)return value}catch{}return null}function resolveTalkApiKey(env=process.env,deps={}){return(env.ELEVENLABS_API_KEY??``).trim()||readTalkApiKeyFromProfile(deps)}let defaultWarnState={warned:!1};const DEFAULT_MODEL_ALIASES={...Object.fromEntries(ANTHROPIC_FAMILIES.map(family=>[family,`anthropic/${currentAnthropicModelId(family)}`])),gpt:`openai/gpt-5.2`,"gpt-mini":`openai/gpt-5-mini`,gemini:`google/gemini-3-pro-preview`,"gemini-flash":`google/gemini-3-flash-preview`},DEFAULT_MODEL_COST={input:0,output:0,cacheRead:0,cacheWrite:0},DEFAULT_MODEL_INPUT=[`text`];function isPositiveNumber(value){return typeof value==`number`&&Number.isFinite(value)&&value>0}function resolveModelCost(raw){return{input:typeof raw?.input==`number`?raw.input:DEFAULT_MODEL_COST.input,output:typeof raw?.output==`number`?raw.output:DEFAULT_MODEL_COST.output,cacheRead:typeof raw?.cacheRead==`number`?raw.cacheRead:DEFAULT_MODEL_COST.cacheRead,cacheWrite:typeof raw?.cacheWrite==`number`?raw.cacheWrite:DEFAULT_MODEL_COST.cacheWrite}}function resolveAnthropicDefaultAuthMode(cfg){let profiles=cfg.auth?.profiles??{},anthropicProfiles=Object.entries(profiles).filter(([,profile])=>profile?.provider===`anthropic`),order=cfg.auth?.order?.anthropic??[];for(let profileId of order){let entry=profiles[profileId];if(!(!entry||entry.provider!==`anthropic`)){if(entry.mode===`api_key`)return`api_key`;if(entry.mode===`oauth`||entry.mode===`token`)return`oauth`}}let hasApiKey=anthropicProfiles.some(([,profile])=>profile?.mode===`api_key`),hasOauth=anthropicProfiles.some(([,profile])=>profile?.mode===`oauth`||profile?.mode===`token`);return hasApiKey&&!hasOauth?`api_key`:hasOauth&&!hasApiKey||process.env.ANTHROPIC_OAUTH_TOKEN?.trim()?`oauth`:process.env.ANTHROPIC_API_KEY?.trim()?`api_key`:null}function resolvePrimaryModelRef(raw){if(!raw||typeof raw!=`string`)return null;let trimmed=raw.trim();return trimmed?DEFAULT_MODEL_ALIASES[trimmed.toLowerCase()]??trimmed:null}function applyMessageDefaults(cfg){let messages=cfg.messages;if(messages?.ackReactionScope!==void 0)return cfg;let nextMessages=messages?{...messages}:{};return nextMessages.ackReactionScope=`group-mentions`,{...cfg,messages:nextMessages}}function applySessionDefaults(cfg,options={}){let session=cfg.session;if(!session||session.mainKey===void 0)return cfg;let trimmed=session.mainKey.trim(),warn=options.warn??console.warn,warnState=options.warnState??defaultWarnState,next={...cfg,session:{...session,mainKey:`main`}};return trimmed&&trimmed!==`main`&&!warnState.warned&&(warnState.warned=!0,warn(`session.mainKey is ignored; main session is always "main".`)),next}function applyTalkApiKey(config){let resolved=resolveTalkApiKey();return!resolved||config.talk?.apiKey?.trim()?config:{...config,talk:{...config.talk,apiKey:resolved}}}function applyModelDefaults(cfg){let mutated=!1,nextCfg=cfg,providerConfig=nextCfg.models?.providers;if(providerConfig){let nextProviders={...providerConfig};for(let[providerId,provider]of Object.entries(providerConfig)){let models=provider.models;if(!Array.isArray(models)||models.length===0)continue;let providerMutated=!1,nextModels=models.map(model=>{let raw=model,modelMutated=!1,reasoning=typeof raw.reasoning==`boolean`?raw.reasoning:!1;raw.reasoning!==reasoning&&(modelMutated=!0);let input=raw.input??[...DEFAULT_MODEL_INPUT];raw.input===void 0&&(modelMutated=!0);let cost=resolveModelCost(raw.cost);(!raw.cost||raw.cost.input!==cost.input||raw.cost.output!==cost.output||raw.cost.cacheRead!==cost.cacheRead||raw.cost.cacheWrite!==cost.cacheWrite)&&(modelMutated=!0);let contextWindow=isPositiveNumber(raw.contextWindow)?raw.contextWindow:DEFAULT_CONTEXT_TOKENS;raw.contextWindow!==contextWindow&&(modelMutated=!0);let defaultMaxTokens=Math.min(8192,contextWindow),rawMaxTokens=isPositiveNumber(raw.maxTokens)?raw.maxTokens:defaultMaxTokens,maxTokens=Math.min(rawMaxTokens,contextWindow);return raw.maxTokens!==maxTokens&&(modelMutated=!0),modelMutated?(providerMutated=!0,{...raw,reasoning,input,cost,contextWindow,maxTokens}):model});providerMutated&&(nextProviders[providerId]={...provider,models:nextModels},mutated=!0)}mutated&&(nextCfg={...nextCfg,models:{...nextCfg.models,providers:nextProviders}})}let existingAgent=nextCfg.agents?.defaults;if(!existingAgent)return mutated?nextCfg:cfg;let existingModels=existingAgent.models??{};if(Object.keys(existingModels).length===0)return mutated?nextCfg:cfg;let nextModels={...existingModels};for(let[alias,target]of Object.entries(DEFAULT_MODEL_ALIASES)){let entry=nextModels[target];entry&&entry.alias===void 0&&(nextModels[target]={...entry,alias},mutated=!0)}return mutated?{...nextCfg,agents:{...nextCfg.agents,defaults:{...existingAgent,models:nextModels}}}:cfg}function applyAgentDefaults(cfg){let agents=cfg.agents,defaults=agents?.defaults,hasMax=typeof defaults?.maxConcurrent==`number`&&Number.isFinite(defaults.maxConcurrent),hasSubMax=typeof defaults?.subagents?.maxConcurrent==`number`&&Number.isFinite(defaults.subagents.maxConcurrent);if(hasMax&&hasSubMax)return cfg;let mutated=!1,nextDefaults=defaults?{...defaults}:{};hasMax||(nextDefaults.maxConcurrent=4,mutated=!0);let nextSubagents=defaults?.subagents?{...defaults.subagents}:{};return hasSubMax||(nextSubagents.maxConcurrent=8,mutated=!0),mutated?{...cfg,agents:{...agents,defaults:{...nextDefaults,subagents:nextSubagents}}}:cfg}function applyLoggingDefaults(cfg){let logging=cfg.logging;return!logging||logging.redactSensitive?cfg:{...cfg,logging:{...logging,redactSensitive:`tools`}}}function applyContextPruningDefaults(cfg){let defaults=cfg.agents?.defaults;if(!defaults)return cfg;let authMode=resolveAnthropicDefaultAuthMode(cfg);if(!authMode)return cfg;let mutated=!1,nextDefaults={...defaults},contextPruning=defaults.contextPruning??{},heartbeat=defaults.heartbeat??{};if(defaults.contextPruning?.mode===void 0&&(nextDefaults.contextPruning={...contextPruning,mode:`cache-ttl`,ttl:defaults.contextPruning?.ttl??`1h`},mutated=!0),defaults.heartbeat?.every===void 0&&(nextDefaults.heartbeat={...heartbeat,every:authMode===`oauth`?`1h`:`30m`},mutated=!0),authMode===`api_key`){let nextModels=defaults.models?{...defaults.models}:{},modelsMutated=!1;for(let[key,entry]of Object.entries(nextModels)){let parsed=parseModelRef(key,`anthropic`);if(!parsed||parsed.provider!==`anthropic`)continue;let current=entry??{},params=current.params??{};typeof params.cacheRetention!=`string`&&(nextModels[key]={...current,params:{...params,cacheRetention:`short`}},modelsMutated=!0)}let primary=resolvePrimaryModelRef(defaults.model?.primary??void 0);if(primary){let parsedPrimary=parseModelRef(primary,`anthropic`);if(parsedPrimary?.provider===`anthropic`){let key=`${parsedPrimary.provider}/${parsedPrimary.model}`,current=nextModels[key]??{},params=current.params??{};typeof params.cacheRetention!=`string`&&(nextModels[key]={...current,params:{...params,cacheRetention:`short`}},modelsMutated=!0)}}modelsMutated&&(nextDefaults.models=nextModels,mutated=!0)}return mutated?{...cfg,agents:{...cfg.agents,defaults:nextDefaults}}:cfg}function applyCompactionDefaults(cfg){let defaults=cfg.agents?.defaults;if(!defaults)return cfg;let compaction=defaults?.compaction;return compaction?.mode?cfg:{...cfg,agents:{...cfg.agents,defaults:{...defaults,compaction:{...compaction,mode:`safeguard`}}}}}const ENV_VAR_NAME_PATTERN=/^[A-Z_][A-Z0-9_]*$/;var MissingEnvVarError=class extends Error{constructor(varName,configPath){super(`Missing env var "${varName}" referenced at config path: ${configPath}`),this.varName=varName,this.configPath=configPath,this.name=`MissingEnvVarError`}};function parseEnvTokenAt(value,index){if(value[index]!==`$`)return null;let next=value[index+1],afterNext=value[index+2];if(next===`$`&&afterNext===`{`){let start=index+3,end=value.indexOf(`}`,start);if(end!==-1){let name=value.slice(start,end);if(ENV_VAR_NAME_PATTERN.test(name))return{kind:`escaped`,name,end}}}if(next===`{`){let start=index+2,end=value.indexOf(`}`,start);if(end!==-1){let name=value.slice(start,end);if(ENV_VAR_NAME_PATTERN.test(name))return{kind:`substitution`,name,end}}}return null}function resolveEnvVarsInString(value,env,onMissing,configPath=``){if(!value.includes(`$`))return value;let chunks=[];for(let i=0;i<value.length;i+=1){let char=value[i];if(char!==`$`){chunks.push(char);continue}let token=parseEnvTokenAt(value,i);if(token?.kind===`escaped`){chunks.push(`\${${token.name}}`),i=token.end;continue}if(token?.kind===`substitution`){let envValue=env[token.name];if(envValue===void 0||envValue===``){if(onMissing===`throw`)throw new MissingEnvVarError(token.name,configPath);return null}chunks.push(envValue),i=token.end;continue}chunks.push(char)}return chunks.join(``)}function substituteString(value,env,configPath){return resolveEnvVarsInString(value,env,`throw`,configPath)}function containsEnvVarReference(value){if(!value.includes(`$`))return!1;for(let i=0;i<value.length;i+=1){if(value[i]!==`$`)continue;let token=parseEnvTokenAt(value,i);if(token?.kind===`escaped`){i=token.end;continue}if(token?.kind===`substitution`)return!0}return!1}function substituteAny(value,env,path){if(typeof value==`string`)return substituteString(value,env,path);if(Array.isArray(value))return value.map((item,index)=>substituteAny(item,env,`${path}[${index}]`));if(isPlainObject$2(value)){let result={};for(let[key,val]of Object.entries(value))result[key]=substituteAny(val,env,path?`${path}.${key}`:key);return result}return value}function resolveConfigEnvVars(obj,env=process.env){return substituteAny(obj,env,``)}function isPlainObject$1(value){return typeof value==`object`&&!!value&&!Array.isArray(value)&&Object.prototype.toString.call(value)===`[object Object]`}function restoreEnvVarRefs(incoming,parsed,env=process.env){if(parsed==null)return incoming;if(typeof incoming==`string`&&typeof parsed==`string`)return resolveEnvVarsInString(parsed,env,`null`)===incoming?parsed:incoming;if(Array.isArray(incoming)&&Array.isArray(parsed))return incoming.map((item,i)=>i<parsed.length?restoreEnvVarRefs(item,parsed[i],env):item);if(isPlainObject$1(incoming)&&isPlainObject$1(parsed)){let result={};for(let[key,value]of Object.entries(incoming))key in parsed?result[key]=restoreEnvVarRefs(value,parsed[key],env):result[key]=value;return result}return incoming}function collectConfigEnvVars(cfg){let envConfig=cfg?.env;if(!envConfig)return{};let entries={};if(envConfig.vars)for(let[key,value]of Object.entries(envConfig.vars))value&&(entries[key]=value);for(let[key,value]of Object.entries(envConfig))key===`shellEnv`||key===`vars`||typeof value!=`string`||!value.trim()||(entries[key]=value);return entries}function applyConfigEnvVars(cfg,env=process.env){let entries=collectConfigEnvVars(cfg);for(let[key,value]of Object.entries(entries))env[key]?.trim()||(env[key]=value)}function isPathInside(basePath,candidatePath){let base=path.resolve(basePath),candidate=path.resolve(candidatePath),rel=path.relative(base,candidate);return rel===``||!rel.startsWith(`..${path.sep}`)&&rel!==`..`&&!path.isAbsolute(rel)}const INCLUDE_KEY=`$include`;var ConfigIncludeError=class extends Error{constructor(message,includePath,cause){super(message),this.includePath=includePath,this.cause=cause,this.name=`ConfigIncludeError`}},CircularIncludeError=class extends ConfigIncludeError{constructor(chain){super(`Circular include detected: ${chain.join(` -> `)}`,chain[chain.length-1]),this.chain=chain,this.name=`CircularIncludeError`}};function deepMerge(target,source){if(Array.isArray(target)&&Array.isArray(source))return[...target,...source];if(isPlainObject$2(target)&&isPlainObject$2(source)){let result={...target};for(let key of Object.keys(source))result[key]=key in result?deepMerge(result[key],source[key]):source[key];return result}return source}var IncludeProcessor=class IncludeProcessor{constructor(basePath,resolver,rootDir){this.basePath=basePath,this.resolver=resolver,this.visited=new Set,this.depth=0,this.visited.add(path.normalize(basePath)),this.rootDir=path.normalize(rootDir??path.dirname(basePath)),this.rootRealDir=path.normalize(safeRealpath(this.rootDir))}process(obj){return Array.isArray(obj)?obj.map(item=>this.process(item)):isPlainObject$2(obj)?INCLUDE_KEY in obj?this.processInclude(obj):this.processObject(obj):obj}processObject(obj){let result={};for(let[key,value]of Object.entries(obj))result[key]=this.process(value);return result}processInclude(obj){let includeValue=obj[INCLUDE_KEY],otherKeys=Object.keys(obj).filter(k=>k!==INCLUDE_KEY),included=this.resolveInclude(includeValue);if(otherKeys.length===0)return included;if(!isPlainObject$2(included))throw new ConfigIncludeError(`Sibling keys require included content to be an object`,typeof includeValue==`string`?includeValue:INCLUDE_KEY);let rest={};for(let key of otherKeys)rest[key]=this.process(obj[key]);return deepMerge(included,rest)}resolveInclude(value){if(typeof value==`string`)return this.loadFile(value);if(Array.isArray(value))return value.reduce((merged,item)=>{if(typeof item!=`string`)throw new ConfigIncludeError(`Invalid $include array item: expected string, got ${typeof item}`,String(item));return deepMerge(merged,this.loadFile(item))},{});throw new ConfigIncludeError(`Invalid $include value: expected string or array of strings, got ${typeof value}`,String(value))}loadFile(includePath){let resolvedPath=this.resolvePath(includePath);this.checkCircular(resolvedPath),this.checkDepth(includePath);let raw=this.readFile(includePath,resolvedPath),parsed=this.parseFile(includePath,resolvedPath,raw);return this.processNested(resolvedPath,parsed)}resolvePath(includePath){let configDir=path.dirname(this.basePath),resolved=path.isAbsolute(includePath)?includePath:path.resolve(configDir,includePath),normalized=path.normalize(resolved);if(!isPathInside(this.rootDir,normalized))throw new ConfigIncludeError(`Include path escapes config directory: ${includePath} (root: ${this.rootDir})`,includePath);try{let real=fs.realpathSync(normalized);if(!isPathInside(this.rootRealDir,real))throw new ConfigIncludeError(`Include path resolves outside config directory (symlink): ${includePath} (root: ${this.rootDir})`,includePath)}catch(err){if(err instanceof ConfigIncludeError)throw err}return normalized}checkCircular(resolvedPath){if(this.visited.has(resolvedPath))throw new CircularIncludeError([...this.visited,resolvedPath])}checkDepth(includePath){if(this.depth>=10)throw new ConfigIncludeError(`Maximum include depth (10) exceeded at: ${includePath}`,includePath)}readFile(includePath,resolvedPath){try{return this.resolver.readFile(resolvedPath)}catch(err){throw new ConfigIncludeError(`Failed to read include file: ${includePath} (resolved: ${resolvedPath})`,includePath,err instanceof Error?err:void 0)}}parseFile(includePath,resolvedPath,raw){try{return this.resolver.parseJson(raw)}catch(err){throw new ConfigIncludeError(`Failed to parse include file: ${includePath} (resolved: ${resolvedPath})`,includePath,err instanceof Error?err:void 0)}}processNested(resolvedPath,parsed){let nested=new IncludeProcessor(resolvedPath,this.resolver,this.rootDir);return nested.visited=new Set([...this.visited,resolvedPath]),nested.depth=this.depth+1,nested.process(parsed)}};function safeRealpath(target){try{return fs.realpathSync(target)}catch{return target}}const defaultResolver={readFile:p=>fs.readFileSync(p,`utf-8`),parseJson:raw=>json5.parse(raw)};function resolveConfigIncludes(obj,configPath,resolver=defaultResolver){return new IncludeProcessor(configPath,resolver).process(obj)}const getRecord=value=>isRecord(value)?value:null,ensureRecord=(root,key)=>{let existing=root[key];if(isRecord(existing))return existing;let next={};return root[key]=next,next},mergeMissing=(target,source)=>{for(let[key,value]of Object.entries(source)){if(value===void 0)continue;let existing=target[key];if(existing===void 0){target[key]=value;continue}isRecord(existing)&&isRecord(value)&&mergeMissing(existing,value)}},mapLegacyAudioTranscription=value=>{let transcriber=getRecord(value),command=Array.isArray(transcriber?.command)?transcriber?.command:null;if(!command||command.length===0||typeof command[0]!=`string`||!command.every(part=>typeof part==`string`))return null;let rawExecutable=command[0].trim();if(!rawExecutable||!isSafeExecutableValue(rawExecutable))return null;let args=command.slice(1),timeoutSeconds=typeof transcriber?.timeoutSeconds==`number`?transcriber?.timeoutSeconds:void 0,result={command:rawExecutable,type:`cli`};return args.length>0&&(result.args=args),timeoutSeconds!==void 0&&(result.timeoutSeconds=timeoutSeconds),result},getAgentsList=agents=>{let list=agents?.list;return Array.isArray(list)?list:[]},resolveDefaultAgentIdFromRaw=raw=>{let list=getAgentsList(getRecord(raw.agents)),defaultEntry=list.find(entry=>isRecord(entry)&&entry.default===!0&&typeof entry.id==`string`&&entry.id.trim()!==``);if(defaultEntry)return defaultEntry.id.trim();let routing=getRecord(raw.routing),routingDefault=typeof routing?.defaultAgentId==`string`?routing.defaultAgentId.trim():``;if(routingDefault)return routingDefault;let firstEntry=list.find(entry=>isRecord(entry)&&typeof entry.id==`string`&&entry.id.trim()!==``);return firstEntry?firstEntry.id.trim():`main`},ensureAgentEntry=(list,id)=>{let normalized=id.trim(),existing=list.find(entry=>isRecord(entry)&&typeof entry.id==`string`&&entry.id.trim()===normalized);if(existing)return existing;let created={id:normalized};return list.push(created),created};function migrateBindings(raw,changes,changeNote,mutator){let bindings=Array.isArray(raw.bindings)?raw.bindings:null;if(!bindings)return;let touched=!1;for(let entry of bindings){if(!isRecord(entry))continue;let match=getRecord(entry.match);match&&mutator(match)&&(entry.match=match,touched=!0)}touched&&(raw.bindings=bindings,changes.push(changeNote))}function ensureDefaultGroupEntry(section){let groups=isRecord(section.groups)?section.groups:{};return{groups,entry:isRecord(groups[`*`])?groups[`*`]:{}}}const LEGACY_CONFIG_MIGRATIONS_PART_1=[{id:`bindings.match.provider->bindings.match.channel`,describe:`Move bindings[].match.provider to bindings[].match.channel`,apply:(raw,changes)=>{migrateBindings(raw,changes,`Moved bindings[].match.provider → bindings[].match.channel.`,match=>{if(typeof match.channel==`string`&&match.channel.trim())return!1;let provider=typeof match.provider==`string`?match.provider.trim():``;return provider?(match.channel=provider,delete match.provider,!0):!1})}},{id:`bindings.match.accountID->bindings.match.accountId`,describe:`Move bindings[].match.accountID to bindings[].match.accountId`,apply:(raw,changes)=>{migrateBindings(raw,changes,`Moved bindings[].match.accountID → bindings[].match.accountId.`,match=>{if(match.accountId!==void 0)return!1;let accountID=typeof match.accountID==`string`?match.accountID.trim():match.accountID;return accountID?(match.accountId=accountID,delete match.accountID,!0):!1})}},{id:`session.sendPolicy.rules.match.provider->match.channel`,describe:`Move session.sendPolicy.rules[].match.provider to match.channel`,apply:(raw,changes)=>{let session=getRecord(raw.session);if(!session)return;let sendPolicy=getRecord(session.sendPolicy);if(!sendPolicy)return;let rules=Array.isArray(sendPolicy.rules)?sendPolicy.rules:null;if(!rules)return;let touched=!1;for(let rule of rules){if(!isRecord(rule))continue;let match=getRecord(rule.match);if(!match||typeof match.channel==`string`&&match.channel.trim())continue;let provider=typeof match.provider==`string`?match.provider.trim():``;provider&&(match.channel=provider,delete match.provider,rule.match=match,touched=!0)}touched&&(sendPolicy.rules=rules,session.sendPolicy=sendPolicy,raw.session=session,changes.push(`Moved session.sendPolicy.rules[].match.provider → match.channel.`))}},{id:`messages.queue.byProvider->byChannel`,describe:`Move messages.queue.byProvider to messages.queue.byChannel`,apply:(raw,changes)=>{let messages=getRecord(raw.messages);if(!messages)return;let queue=getRecord(messages.queue);queue&&queue.byProvider!==void 0&&(queue.byChannel===void 0?(queue.byChannel=queue.byProvider,changes.push(`Moved messages.queue.byProvider → messages.queue.byChannel.`)):changes.push(`Removed messages.queue.byProvider (messages.queue.byChannel already set).`),delete queue.byProvider,messages.queue=queue,raw.messages=messages)}},{id:`providers->channels`,describe:`Move provider config sections to channels.*`,apply:(raw,changes)=>{let legacyEntries=[`whatsapp`,`telegram`,`discord`,`slack`,`signal`,`imessage`,`msteams`].filter(key=>isRecord(raw[key]));if(legacyEntries.length===0)return;let channels=ensureRecord(raw,`channels`);for(let key of legacyEntries){let legacy=getRecord(raw[key]);if(!legacy)continue;let channelEntry=ensureRecord(channels,key),hadEntries=Object.keys(channelEntry).length>0;mergeMissing(channelEntry,legacy),channels[key]=channelEntry,delete raw[key],changes.push(hadEntries?`Merged ${key} → channels.${key}.`:`Moved ${key} → channels.${key}.`)}raw.channels=channels}},{id:`routing.allowFrom->channels.whatsapp.allowFrom`,describe:`Move routing.allowFrom to channels.whatsapp.allowFrom`,apply:(raw,changes)=>{let routing=raw.routing;if(!routing||typeof routing!=`object`)return;let allowFrom=routing.allowFrom;if(allowFrom===void 0)return;let channels=getRecord(raw.channels),whatsapp=channels?getRecord(channels.whatsapp):null;if(!whatsapp){delete routing.allowFrom,Object.keys(routing).length===0&&delete raw.routing,changes.push(`Removed routing.allowFrom (channels.whatsapp not configured).`);return}whatsapp.allowFrom===void 0?(whatsapp.allowFrom=allowFrom,changes.push(`Moved routing.allowFrom → channels.whatsapp.allowFrom.`)):changes.push(`Removed routing.allowFrom (channels.whatsapp.allowFrom already set).`),delete routing.allowFrom,Object.keys(routing).length===0&&delete raw.routing,channels.whatsapp=whatsapp,raw.channels=channels}},{id:`routing.groupChat.requireMention->groups.*.requireMention`,describe:`Move routing.groupChat.requireMention to channels.whatsapp/telegram/imessage groups`,apply:(raw,changes)=>{let routing=raw.routing;if(!routing||typeof routing!=`object`)return;let groupChat=routing.groupChat&&typeof routing.groupChat==`object`?routing.groupChat:null;if(!groupChat)return;let requireMention=groupChat.requireMention;if(requireMention===void 0)return;let channels=ensureRecord(raw,`channels`),applyTo=(key,options)=>{if(options?.requireExisting&&!isRecord(channels[key]))return;let section=channels[key]&&typeof channels[key]==`object`?channels[key]:{},{groups,entry}=ensureDefaultGroupEntry(section);entry.requireMention===void 0?(entry.requireMention=requireMention,groups[`*`]=entry,section.groups=groups,channels[key]=section,changes.push(`Moved routing.groupChat.requireMention → channels.${key}.groups."*".requireMention.`)):changes.push(`Removed routing.groupChat.requireMention (channels.${key}.groups."*" already set).`)};applyTo(`whatsapp`,{requireExisting:!0}),applyTo(`telegram`),applyTo(`imessage`),delete groupChat.requireMention,Object.keys(groupChat).length===0&&delete routing.groupChat,Object.keys(routing).length===0&&delete raw.routing,raw.channels=channels}},{id:`gateway.token->gateway.auth.token`,describe:`Move gateway.token to gateway.auth.token`,apply:(raw,changes)=>{let gateway=raw.gateway;if(!gateway||typeof gateway!=`object`)return;let token=gateway.token;if(token===void 0)return;let gatewayObj=gateway,auth=gatewayObj.auth&&typeof gatewayObj.auth==`object`?gatewayObj.auth:{};auth.token===void 0?(auth.token=token,auth.mode||=`token`,changes.push(`Moved gateway.token → gateway.auth.token.`)):changes.push(`Removed gateway.token (gateway.auth.token already set).`),delete gatewayObj.token,Object.keys(auth).length>0&&(gatewayObj.auth=auth),raw.gateway=gatewayObj}},{id:`telegram.requireMention->channels.telegram.groups.*.requireMention`,describe:`Move telegram.requireMention to channels.telegram.groups.*.requireMention`,apply:(raw,changes)=>{let channels=ensureRecord(raw,`channels`),telegram=channels.telegram;if(!telegram||typeof telegram!=`object`)return;let requireMention=telegram.requireMention;if(requireMention===void 0)return;let{groups,entry}=ensureDefaultGroupEntry(telegram);entry.requireMention===void 0?(entry.requireMention=requireMention,groups[`*`]=entry,telegram.groups=groups,changes.push(`Moved telegram.requireMention → channels.telegram.groups."*".requireMention.`)):changes.push(`Removed telegram.requireMention (channels.telegram.groups."*" already set).`),delete telegram.requireMention,channels.telegram=telegram,raw.channels=channels}}];function applyLegacyAudioTranscriptionModel(params){let mapped=mapLegacyAudioTranscription(params.source);if(!mapped){params.changes.push(params.invalidMessage);return}let mediaAudio=ensureRecord(ensureRecord(ensureRecord(params.raw,`tools`),`media`),`audio`);if((Array.isArray(mediaAudio.models)?mediaAudio.models:[]).length===0){mediaAudio.enabled=!0,mediaAudio.models=[mapped],params.changes.push(params.movedMessage);return}params.changes.push(params.alreadySetMessage)}const LEGACY_CONFIG_MIGRATIONS_PART_2=[{id:`agent.model-config-v2`,describe:`Migrate legacy agent.model/allowedModels/modelAliases/modelFallbacks/imageModelFallbacks to agent.models + model lists`,apply:(raw,changes)=>{let agentRoot=getRecord(raw.agent),defaults=getRecord(getRecord(raw.agents)?.defaults),agent=agentRoot??defaults;if(!agent)return;let label=agentRoot?`agent`:`agents.defaults`,legacyModel=typeof agent.model==`string`?String(agent.model):void 0,legacyImageModel=typeof agent.imageModel==`string`?String(agent.imageModel):void 0,legacyAllowed=Array.isArray(agent.allowedModels)?agent.allowedModels.map(String):[],legacyModelFallbacks=Array.isArray(agent.modelFallbacks)?agent.modelFallbacks.map(String):[],legacyImageModelFallbacks=Array.isArray(agent.imageModelFallbacks)?agent.imageModelFallbacks.map(String):[],legacyAliases=agent.modelAliases&&typeof agent.modelAliases==`object`?agent.modelAliases:{};if(!(legacyModel||legacyImageModel||legacyAllowed.length>0||legacyModelFallbacks.length>0||legacyImageModelFallbacks.length>0||Object.keys(legacyAliases).length>0))return;let models=agent.models&&typeof agent.models==`object`?agent.models:{},ensureModel=rawKey=>{if(typeof rawKey!=`string`)return;let key=rawKey.trim();key&&(models[key]||(models[key]={}))};ensureModel(legacyModel),ensureModel(legacyImageModel);for(let key of legacyAllowed)ensureModel(key);for(let key of legacyModelFallbacks)ensureModel(key);for(let key of legacyImageModelFallbacks)ensureModel(key);for(let target of Object.values(legacyAliases))typeof target==`string`&&ensureModel(target);for(let[alias,targetRaw]of Object.entries(legacyAliases)){if(typeof targetRaw!=`string`)continue;let target=targetRaw.trim();if(!target)continue;let entry=models[target]&&typeof models[target]==`object`?models[target]:{};`alias`in entry||(entry.alias=alias,models[target]=entry)}let currentModel=agent.model&&typeof agent.model==`object`?agent.model:null;currentModel?(!currentModel.primary&&legacyModel&&(currentModel.primary=legacyModel),legacyModelFallbacks.length>0&&(!Array.isArray(currentModel.fallbacks)||currentModel.fallbacks.length===0)&&(currentModel.fallbacks=legacyModelFallbacks),agent.model=currentModel):(legacyModel||legacyModelFallbacks.length>0)&&(agent.model={primary:legacyModel,fallbacks:legacyModelFallbacks.length?legacyModelFallbacks:[]});let currentImageModel=agent.imageModel&&typeof agent.imageModel==`object`?agent.imageModel:null;currentImageModel?(!currentImageModel.primary&&legacyImageModel&&(currentImageModel.primary=legacyImageModel),legacyImageModelFallbacks.length>0&&(!Array.isArray(currentImageModel.fallbacks)||currentImageModel.fallbacks.length===0)&&(currentImageModel.fallbacks=legacyImageModelFallbacks),agent.imageModel=currentImageModel):(legacyImageModel||legacyImageModelFallbacks.length>0)&&(agent.imageModel={primary:legacyImageModel,fallbacks:legacyImageModelFallbacks.length?legacyImageModelFallbacks:[]}),agent.models=models,legacyModel!==void 0&&changes.push(`Migrated ${label}.model string → ${label}.model.primary.`),legacyModelFallbacks.length>0&&changes.push(`Migrated ${label}.modelFallbacks → ${label}.model.fallbacks.`),legacyImageModel!==void 0&&changes.push(`Migrated ${label}.imageModel string → ${label}.imageModel.primary.`),legacyImageModelFallbacks.length>0&&changes.push(`Migrated ${label}.imageModelFallbacks → ${label}.imageModel.fallbacks.`),legacyAllowed.length>0&&changes.push(`Migrated ${label}.allowedModels → ${label}.models.`),Object.keys(legacyAliases).length>0&&changes.push(`Migrated ${label}.modelAliases → ${label}.models.*.alias.`),delete agent.allowedModels,delete agent.modelAliases,delete agent.modelFallbacks,delete agent.imageModelFallbacks}},{id:`routing.agents-v2`,describe:`Move routing.agents/defaultAgentId to agents.list`,apply:(raw,changes)=>{let routing=getRecord(raw.routing);if(!routing)return;let routingAgents=getRecord(routing.agents),agents=ensureRecord(raw,`agents`),list=getAgentsList(agents);if(routingAgents){for(let[rawId,entryRaw]of Object.entries(routingAgents)){let agentId=String(rawId??``).trim(),entry=getRecord(entryRaw);if(!agentId||!entry)continue;let target=ensureAgentEntry(list,agentId),entryCopy={...entry};if(`mentionPatterns`in entryCopy){let mentionPatterns=entryCopy.mentionPatterns,groupChat=ensureRecord(target,`groupChat`);groupChat.mentionPatterns===void 0?(groupChat.mentionPatterns=mentionPatterns,changes.push(`Moved routing.agents.${agentId}.mentionPatterns → agents.list (id "${agentId}").groupChat.mentionPatterns.`)):changes.push(`Removed routing.agents.${agentId}.mentionPatterns (agents.list groupChat mentionPatterns already set).`),delete entryCopy.mentionPatterns}let legacyGroupChat=getRecord(entryCopy.groupChat);legacyGroupChat&&(mergeMissing(ensureRecord(target,`groupChat`),legacyGroupChat),delete entryCopy.groupChat);let legacySandbox=getRecord(entryCopy.sandbox);if(legacySandbox){let sandboxTools=getRecord(legacySandbox.tools);sandboxTools&&(mergeMissing(ensureRecord(ensureRecord(ensureRecord(target,`tools`),`sandbox`),`tools`),sandboxTools),delete legacySandbox.tools,changes.push(`Moved routing.agents.${agentId}.sandbox.tools → agents.list (id "${agentId}").tools.sandbox.tools.`)),entryCopy.sandbox=legacySandbox}mergeMissing(target,entryCopy)}delete routing.agents,changes.push(`Moved routing.agents → agents.list.`)}let defaultAgentId=typeof routing.defaultAgentId==`string`?routing.defaultAgentId.trim():``;if(defaultAgentId){if(list.some(entry=>isRecord(entry)&&entry.default===!0))changes.push(`Removed routing.defaultAgentId (agents.list default already set).`);else{let entry=ensureAgentEntry(list,defaultAgentId);entry.default=!0,changes.push(`Moved routing.defaultAgentId → agents.list (id "${defaultAgentId}").default.`)}delete routing.defaultAgentId}list.length>0&&(agents.list=list),Object.keys(routing).length===0&&delete raw.routing}},{id:`routing.config-v2`,describe:`Move routing bindings/groupChat/queue/agentToAgent/transcribeAudio`,apply:(raw,changes)=>{let routing=getRecord(raw.routing);if(!routing)return;if(routing.bindings!==void 0&&(raw.bindings===void 0?(raw.bindings=routing.bindings,changes.push(`Moved routing.bindings → bindings.`)):changes.push(`Removed routing.bindings (bindings already set).`),delete routing.bindings),routing.agentToAgent!==void 0){let tools=ensureRecord(raw,`tools`);tools.agentToAgent===void 0?(tools.agentToAgent=routing.agentToAgent,changes.push(`Moved routing.agentToAgent → tools.agentToAgent.`)):changes.push(`Removed routing.agentToAgent (tools.agentToAgent already set).`),delete routing.agentToAgent}if(routing.queue!==void 0){let messages=ensureRecord(raw,`messages`);messages.queue===void 0?(messages.queue=routing.queue,changes.push(`Moved routing.queue → messages.queue.`)):changes.push(`Removed routing.queue (messages.queue already set).`),delete routing.queue}let groupChat=getRecord(routing.groupChat);if(groupChat){let historyLimit=groupChat.historyLimit;if(historyLimit!==void 0){let messagesGroup=ensureRecord(ensureRecord(raw,`messages`),`groupChat`);messagesGroup.historyLimit===void 0?(messagesGroup.historyLimit=historyLimit,changes.push(`Moved routing.groupChat.historyLimit → messages.groupChat.historyLimit.`)):changes.push(`Removed routing.groupChat.historyLimit (messages.groupChat.historyLimit already set).`),delete groupChat.historyLimit}let mentionPatterns=groupChat.mentionPatterns;if(mentionPatterns!==void 0){let messagesGroup=ensureRecord(ensureRecord(raw,`messages`),`groupChat`);messagesGroup.mentionPatterns===void 0?(messagesGroup.mentionPatterns=mentionPatterns,changes.push(`Moved routing.groupChat.mentionPatterns → messages.groupChat.mentionPatterns.`)):changes.push(`Removed routing.groupChat.mentionPatterns (messages.groupChat.mentionPatterns already set).`),delete groupChat.mentionPatterns}Object.keys(groupChat).length===0?delete routing.groupChat:routing.groupChat=groupChat}routing.transcribeAudio!==void 0&&(applyLegacyAudioTranscriptionModel({raw,source:routing.transcribeAudio,changes,movedMessage:`Moved routing.transcribeAudio → tools.media.audio.models.`,alreadySetMessage:`Removed routing.transcribeAudio (tools.media.audio.models already set).`,invalidMessage:`Removed routing.transcribeAudio (invalid or empty command).`}),delete routing.transcribeAudio),Object.keys(routing).length===0&&delete raw.routing}},{id:`audio.transcription-v2`,describe:`Move audio.transcription to tools.media.audio.models`,apply:(raw,changes)=>{let audio=getRecord(raw.audio);audio?.transcription!==void 0&&(applyLegacyAudioTranscriptionModel({raw,source:audio.transcription,changes,movedMessage:`Moved audio.transcription → tools.media.audio.models.`,alreadySetMessage:`Removed audio.transcription (tools.media.audio.models already set).`,invalidMessage:`Removed audio.transcription (invalid or empty command).`}),delete audio.transcription,Object.keys(audio).length===0?delete raw.audio:raw.audio=audio)}}],LEGACY_CONFIG_MIGRATIONS_PART_3=[{id:`memorySearch->agents.defaults.memorySearch`,describe:`Move top-level memorySearch to agents.defaults.memorySearch`,apply:(raw,changes)=>{let legacyMemorySearch=getRecord(raw.memorySearch);if(!legacyMemorySearch)return;let agents=ensureRecord(raw,`agents`),defaults=ensureRecord(agents,`defaults`),existing=getRecord(defaults.memorySearch);if(!existing)defaults.memorySearch=legacyMemorySearch,changes.push(`Moved memorySearch → agents.defaults.memorySearch.`);else{let merged=structuredClone(existing);mergeMissing(merged,legacyMemorySearch),defaults.memorySearch=merged,changes.push(`Merged memorySearch → agents.defaults.memorySearch (filled missing fields from legacy; kept explicit agents.defaults values).`)}agents.defaults=defaults,raw.agents=agents,delete raw.memorySearch}},{id:`auth.anthropic-claude-cli-mode-oauth`,describe:`Switch anthropic:claude-cli auth profile mode to oauth`,apply:(raw,changes)=>{let profiles=getRecord(getRecord(raw.auth)?.profiles);if(!profiles)return;let claudeCli=getRecord(profiles[`anthropic:claude-cli`]);claudeCli&&claudeCli.mode===`token`&&(claudeCli.mode=`oauth`,changes.push(`Updated auth.profiles["anthropic:claude-cli"].mode → "oauth".`))}},{id:`tools.bash->tools.exec`,describe:`Move tools.bash to tools.exec`,apply:(raw,changes)=>{let tools=ensureRecord(raw,`tools`),bash=getRecord(tools.bash);bash&&(tools.exec===void 0?(tools.exec=bash,changes.push(`Moved tools.bash → tools.exec.`)):changes.push(`Removed tools.bash (tools.exec already set).`),delete tools.bash)}},{id:`messages.tts.enabled->auto`,describe:`Move messages.tts.enabled to messages.tts.auto`,apply:(raw,changes)=>{let tts=getRecord(getRecord(raw.messages)?.tts);if(tts){if(tts.auto!==void 0){`enabled`in tts&&(delete tts.enabled,changes.push(`Removed messages.tts.enabled (messages.tts.auto already set).`));return}typeof tts.enabled==`boolean`&&(tts.auto=tts.enabled?`always`:`off`,delete tts.enabled,changes.push(`Moved messages.tts.enabled → messages.tts.auto (${String(tts.auto)}).`))}}},{id:`agent.defaults-v2`,describe:`Move agent config to agents.defaults and tools`,apply:(raw,changes)=>{let agent=getRecord(raw.agent);if(!agent)return;let agents=ensureRecord(raw,`agents`),defaults=getRecord(agents.defaults)??{},tools=ensureRecord(raw,`tools`),agentTools=getRecord(agent.tools);agentTools&&(tools.allow===void 0&&agentTools.allow!==void 0&&(tools.allow=agentTools.allow,changes.push(`Moved agent.tools.allow → tools.allow.`)),tools.deny===void 0&&agentTools.deny!==void 0&&(tools.deny=agentTools.deny,changes.push(`Moved agent.tools.deny → tools.deny.`)));let elevated=getRecord(agent.elevated);elevated&&(tools.elevated===void 0?(tools.elevated=elevated,changes.push(`Moved agent.elevated → tools.elevated.`)):changes.push(`Removed agent.elevated (tools.elevated already set).`));let bash=getRecord(agent.bash);bash&&(tools.exec===void 0?(tools.exec=bash,changes.push(`Moved agent.bash → tools.exec.`)):changes.push(`Removed agent.bash (tools.exec already set).`));let sandbox=getRecord(agent.sandbox);if(sandbox){let sandboxTools=getRecord(sandbox.tools);sandboxTools&&(mergeMissing(ensureRecord(ensureRecord(tools,`sandbox`),`tools`),sandboxTools),delete sandbox.tools,changes.push(`Moved agent.sandbox.tools → tools.sandbox.tools.`))}let subagents=getRecord(agent.subagents);if(subagents){let subagentTools=getRecord(subagents.tools);subagentTools&&(mergeMissing(ensureRecord(ensureRecord(tools,`subagents`),`tools`),subagentTools),delete subagents.tools,changes.push(`Moved agent.subagents.tools → tools.subagents.tools.`))}let agentCopy=structuredClone(agent);delete agentCopy.tools,delete agentCopy.elevated,delete agentCopy.bash,isRecord(agentCopy.sandbox)&&delete agentCopy.sandbox.tools,isRecord(agentCopy.subagents)&&delete agentCopy.subagents.tools,mergeMissing(defaults,agentCopy),agents.defaults=defaults,raw.agents=agents,delete raw.agent,changes.push(`Moved agent → agents.defaults.`)}},{id:`identity->agents.list`,describe:`Move identity to agents.list[].identity`,apply:(raw,changes)=>{let identity=getRecord(raw.identity);if(!identity)return;let agents=ensureRecord(raw,`agents`),list=getAgentsList(agents),defaultId=resolveDefaultAgentIdFromRaw(raw),entry=ensureAgentEntry(list,defaultId);entry.identity===void 0?(entry.identity=identity,changes.push(`Moved identity → agents.list (id "${defaultId}").identity.`)):changes.push(`Removed identity (agents.list identity already set).`),agents.list=list,raw.agents=agents,delete raw.identity}}];[...LEGACY_CONFIG_MIGRATIONS_PART_1,...LEGACY_CONFIG_MIGRATIONS_PART_2,...LEGACY_CONFIG_MIGRATIONS_PART_3];const LEGACY_CONFIG_RULES=[{path:[`whatsapp`],message:`whatsapp config moved to channels.whatsapp (auto-migrated on load).`},{path:[`telegram`],message:`telegram config moved to channels.telegram (auto-migrated on load).`},{path:[`discord`],message:`discord config moved to channels.discord (auto-migrated on load).`},{path:[`slack`],message:`slack config moved to channels.slack (auto-migrated on load).`},{path:[`signal`],message:`signal config moved to channels.signal (auto-migrated on load).`},{path:[`imessage`],message:`imessage config moved to channels.imessage (auto-migrated on load).`},{path:[`msteams`],message:`msteams config moved to channels.msteams (auto-migrated on load).`},{path:[`routing`,`allowFrom`],message:`routing.allowFrom was removed; use channels.whatsapp.allowFrom instead (auto-migrated on load).`},{path:[`routing`,`bindings`],message:`routing.bindings was moved; use top-level bindings instead (auto-migrated on load).`},{path:[`routing`,`agents`],message:`routing.agents was moved; use agents.list instead (auto-migrated on load).`},{path:[`routing`,`defaultAgentId`],message:`routing.defaultAgentId was moved; use agents.list[].default instead (auto-migrated on load).`},{path:[`routing`,`agentToAgent`],message:`routing.agentToAgent was moved; use tools.agentToAgent instead (auto-migrated on load).`},{path:[`routing`,`groupChat`,`requireMention`],message:`routing.groupChat.requireMention was removed; use channels.whatsapp/telegram/imessage groups defaults (e.g. channels.whatsapp.groups."*".requireMention) instead (auto-migrated on load).`},{path:[`routing`,`groupChat`,`mentionPatterns`],message:`routing.groupChat.mentionPatterns was moved; use agents.list[].groupChat.mentionPatterns or messages.groupChat.mentionPatterns instead (auto-migrated on load).`},{path:[`routing`,`queue`],message:`routing.queue was moved; use messages.queue instead (auto-migrated on load).`},{path:[`routing`,`transcribeAudio`],message:`routing.transcribeAudio was moved; use tools.media.audio.models instead (auto-migrated on load).`},{path:[`telegram`,`requireMention`],message:`telegram.requireMention was removed; use channels.telegram.groups."*".requireMention instead (auto-migrated on load).`},{path:[`identity`],message:`identity was moved; use agents.list[].identity instead (auto-migrated on load).`},{path:[`agent`],message:`agent.* was moved; use agents.defaults (and tools.* for tool/elevated/exec settings) instead (auto-migrated on load).`},{path:[`memorySearch`],message:`top-level memorySearch was moved; use agents.defaults.memorySearch instead (auto-migrated on load).`},{path:[`tools`,`bash`],message:`tools.bash was removed; use tools.exec instead (auto-migrated on load).`},{path:[`agent`,`model`],message:`agent.model string was replaced by agents.defaults.model.primary/fallbacks and agents.defaults.models (auto-migrated on load).`,match:value=>typeof value==`string`},{path:[`agent`,`imageModel`],message:`agent.imageModel string was replaced by agents.defaults.imageModel.primary/fallbacks (auto-migrated on load).`,match:value=>typeof value==`string`},{path:[`agent`,`allowedModels`],message:`agent.allowedModels was replaced by agents.defaults.models (auto-migrated on load).`},{path:[`agent`,`modelAliases`],message:`agent.modelAliases was replaced by agents.defaults.models.*.alias (auto-migrated on load).`},{path:[`agent`,`modelFallbacks`],message:`agent.modelFallbacks was replaced by agents.defaults.model.fallbacks (auto-migrated on load).`},{path:[`agent`,`imageModelFallbacks`],message:`agent.imageModelFallbacks was replaced by agents.defaults.imageModel.fallbacks (auto-migrated on load).`},{path:[`messages`,`tts`,`enabled`],message:`messages.tts.enabled was replaced by messages.tts.auto (auto-migrated on load).`},{path:[`gateway`,`token`],message:`gateway.token is ignored; use gateway.auth.token instead (auto-migrated on load).`}];function findLegacyConfigIssues(raw){if(!raw||typeof raw!=`object`)return[];let root=raw,issues=[];for(let rule of LEGACY_CONFIG_RULES){let cursor=root;for(let key of rule.path){if(!cursor||typeof cursor!=`object`){cursor=void 0;break}cursor=cursor[key]}cursor!==void 0&&(!rule.match||rule.match(cursor,root))&&issues.push({path:rule.path.join(`.`),message:rule.message})}return issues}function isObjectWithStringId(value){return isPlainObject$2(value)?typeof value.id==`string`&&value.id.length>0:!1}function mergeObjectArraysById(base,patch,options){if(!base.every(isObjectWithStringId))return;let merged=[...base],indexById=new Map;for(let[index,entry]of merged.entries()){if(!isObjectWithStringId(entry))return;indexById.set(entry.id,index)}for(let patchEntry of patch){if(!isObjectWithStringId(patchEntry)){merged.push(structuredClone(patchEntry));continue}let existingIndex=indexById.get(patchEntry.id);if(existingIndex===void 0){merged.push(structuredClone(patchEntry)),indexById.set(patchEntry.id,merged.length-1);continue}merged[existingIndex]=applyMergePatch(merged[existingIndex],patchEntry,options)}return merged}function applyMergePatch(base,patch,options={}){if(!isPlainObject$2(patch))return patch;let result=isPlainObject$2(base)?{...base}:{};for(let[key,value]of Object.entries(patch)){if(value===null){delete result[key];continue}if(options.mergeObjectArraysById&&Array.isArray(result[key])&&Array.isArray(value)){let mergedArray=mergeObjectArraysById(result[key],value,options);if(mergedArray){result[key]=mergedArray;continue}}if(isPlainObject$2(value)){let baseValue=result[key];result[key]=applyMergePatch(isPlainObject$2(baseValue)?baseValue:{},value,options);continue}result[key]=value}return result}const PATH_VALUE_RE=/^~(?=$|[\\/])/,PATH_KEY_RE=/(dir|path|paths|file|root|workspace)$/i,PATH_LIST_KEYS=new Set([`paths`,`pathPrepend`]);function normalizeStringValue(key,value){return!PATH_VALUE_RE.test(value.trim())||!key?value:PATH_KEY_RE.test(key)||PATH_LIST_KEYS.has(key)?resolveUserPath(value):value}function normalizeAny(key,value){if(typeof value==`string`)return normalizeStringValue(key,value);if(Array.isArray(value)){let normalizeChildren=!!(key&&PATH_LIST_KEYS.has(key));return value.map(entry=>typeof entry==`string`?normalizeChildren?normalizeStringValue(key,entry):entry:Array.isArray(entry)||isPlainObject$2(entry)?normalizeAny(void 0,entry):entry)}if(!isPlainObject$2(value))return value;for(let[childKey,childValue]of Object.entries(value)){let next=normalizeAny(childKey,childValue);next!==childValue&&(value[childKey]=next)}return value}function normalizeConfigPaths(cfg){return!cfg||typeof cfg!=`object`||normalizeAny(void 0,cfg),cfg}const BLOCKED_KEYS=new Set([`__proto__`,`prototype`,`constructor`]);function parseConfigPath(raw){let trimmed=raw.trim();if(!trimmed)return{ok:!1,error:`Invalid path. Use dot notation (e.g. foo.bar).`};let parts=trimmed.split(`.`).map(part=>part.trim());return parts.some(part=>!part)?{ok:!1,error:`Invalid path. Use dot notation (e.g. foo.bar).`}:parts.some(part=>BLOCKED_KEYS.has(part))?{ok:!1,error:`Invalid path segment.`}:{ok:!0,path:parts}}function setConfigValueAtPath(root,path,value){let cursor=root;for(let idx=0;idx<path.length-1;idx+=1){let key=path[idx],next=cursor[key];isPlainObject$2(next)||(cursor[key]={}),cursor=cursor[key]}cursor[path[path.length-1]]=value}function unsetConfigValueAtPath(root,path){let stack=[],cursor=root;for(let idx=0;idx<path.length-1;idx+=1){let key=path[idx],next=cursor[key];if(!isPlainObject$2(next))return!1;stack.push({node:cursor,key}),cursor=next}let leafKey=path[path.length-1];if(!(leafKey in cursor))return!1;delete cursor[leafKey];for(let idx=stack.length-1;idx>=0;--idx){let{node,key}=stack[idx],child=node[key];if(isPlainObject$2(child)&&Object.keys(child).length===0)delete node[key];else break}return!0}function getConfigValueAtPath(root,path){let cursor=root;for(let key of path){if(!isPlainObject$2(cursor))return;cursor=cursor[key]}return cursor}let overrides={};function mergeOverrides(base,override){if(!isPlainObject$2(base)||!isPlainObject$2(override))return override;let next={...base};for(let[key,value]of Object.entries(override))value!==void 0&&(next[key]=mergeOverrides(base[key],value));return next}function getConfigOverrides(){return overrides}function resetConfigOverrides(){overrides={}}function setConfigOverride(pathRaw,value){let parsed=parseConfigPath(pathRaw);return!parsed.ok||!parsed.path?{ok:!1,error:parsed.error??`Invalid path.`}:(setConfigValueAtPath(overrides,parsed.path,value),{ok:!0})}function unsetConfigOverride(pathRaw){let parsed=parseConfigPath(pathRaw);return!parsed.ok||!parsed.path?{ok:!1,removed:!1,error:parsed.error??`Invalid path.`}:{ok:!0,removed:unsetConfigValueAtPath(overrides,parsed.path)}}function applyConfigOverrides(cfg){return!overrides||Object.keys(overrides).length===0?cfg:mergeOverrides(cfg,overrides)}const DEFAULT_SLOT_BY_KEY={memory:`memory-core`};function defaultSlotIdForKey(slotKey){return DEFAULT_SLOT_BY_KEY[slotKey]}const BUNDLED_ENABLED_BY_DEFAULT=new Set([`device-pair`,`phone-control`,`talk-voice`]),normalizeList=value=>Array.isArray(value)?value.map(entry=>typeof entry==`string`?entry.trim():``).filter(Boolean):[],normalizeSlotValue=value=>{if(typeof value!=`string`)return;let trimmed=value.trim();if(trimmed)return trimmed.toLowerCase()===`none`?null:trimmed},normalizePluginEntries=entries=>{if(!entries||typeof entries!=`object`||Array.isArray(entries))return{};let normalized={};for(let[key,value]of Object.entries(entries)){if(!key.trim())continue;if(!value||typeof value!=`object`||Array.isArray(value)){normalized[key]={};continue}let entry=value;normalized[key]={enabled:typeof entry.enabled==`boolean`?entry.enabled:void 0,config:`config`in entry?entry.config:void 0}}return normalized},normalizePluginsConfig=config=>{let memorySlot=normalizeSlotValue(config?.slots?.memory);return{enabled:config?.enabled!==!1,allow:normalizeList(config?.allow),deny:normalizeList(config?.deny),loadPaths:normalizeList(config?.load?.paths),slots:{memory:memorySlot===void 0?defaultSlotIdForKey(`memory`):memorySlot},entries:normalizePluginEntries(config?.entries)}},hasExplicitMemorySlot=plugins=>!!(plugins?.slots&&Object.prototype.hasOwnProperty.call(plugins.slots,`memory`)),hasExplicitMemoryEntry=plugins=>!!(plugins?.entries&&Object.prototype.hasOwnProperty.call(plugins.entries,`memory-core`)),hasExplicitPluginConfig=plugins=>plugins?!!(typeof plugins.enabled==`boolean`||Array.isArray(plugins.allow)&&plugins.allow.length>0||Array.isArray(plugins.deny)&&plugins.deny.length>0||plugins.load?.paths&&Array.isArray(plugins.load.paths)&&plugins.load.paths.length>0||plugins.slots&&Object.keys(plugins.slots).length>0||plugins.entries&&Object.keys(plugins.entries).length>0):!1;function applyTestPluginDefaults(cfg,env=process.env){if(!env.VITEST)return cfg;let plugins=cfg.plugins;return hasExplicitPluginConfig(plugins)?hasExplicitMemorySlot(plugins)||hasExplicitMemoryEntry(plugins)?cfg:{...cfg,plugins:{...plugins,slots:{...plugins?.slots,memory:`none`}}}:{...cfg,plugins:{...plugins,enabled:!1,slots:{...plugins?.slots,memory:`none`}}}}function resolveEnableState(id,origin,config){if(!config.enabled)return{enabled:!1,reason:`plugins disabled`};if(config.deny.includes(id))return{enabled:!1,reason:`blocked by denylist`};if(config.allow.length>0&&!config.allow.includes(id))return{enabled:!1,reason:`not in allowlist`};if(config.slots.memory===id)return{enabled:!0};let entry=config.entries[id];return entry?.enabled===!0?{enabled:!0}:entry?.enabled===!1?{enabled:!1,reason:`disabled in config`}:origin===`bundled`&&BUNDLED_ENABLED_BY_DEFAULT.has(id)?{enabled:!0}:origin===`bundled`?{enabled:!1,reason:`bundled (disabled by default)`}:{enabled:!0}}function resolveMemorySlotDecision(params){return params.kind===`memory`?params.slot===null?{enabled:!1,reason:`memory slot disabled`}:typeof params.slot==`string`?params.slot===params.id?{enabled:!0,selected:!0}:{enabled:!1,reason:`memory slot set to "${params.slot}"`}:params.selectedId&¶ms.selectedId!==params.id?{enabled:!1,reason:`memory slot already filled by "${params.selectedId}"`}:{enabled:!0,selected:!0}:{enabled:!0}}function resolveBundledPluginsDir(){let override=process.env.BUILDERFORCE_AGENTS_BUNDLED_PLUGINS_DIR?.trim();if(override)return override;try{let execDir=path.dirname(process.execPath),sibling=path.join(execDir,`extensions`);if(fs.existsSync(sibling))return sibling}catch{}try{let cursor=path.dirname(fileURLToPath(import.meta.url));for(let i=0;i<6;i+=1){let candidate=path.join(cursor,`extensions`);if(fs.existsSync(candidate))return candidate;let parent=path.dirname(cursor);if(parent===cursor)break;cursor=parent}}catch{}}const LEGACY_PROJECT_NAMES=[`builderforce`],MANIFEST_KEY=`builderforce`,LEGACY_MANIFEST_KEYS=LEGACY_PROJECT_NAMES,PLUGIN_MANIFEST_FILENAME=`builderforce.plugin.json`,PLUGIN_MANIFEST_FILENAMES=[PLUGIN_MANIFEST_FILENAME];function normalizeStringList(value){return Array.isArray(value)?value.map(entry=>typeof entry==`string`?entry.trim():``).filter(Boolean):[]}function resolvePluginManifestPath(rootDir){for(let filename of PLUGIN_MANIFEST_FILENAMES){let candidate=path.join(rootDir,filename);if(fs.existsSync(candidate))return candidate}return path.join(rootDir,PLUGIN_MANIFEST_FILENAME)}function loadPluginManifest(rootDir){let manifestPath=resolvePluginManifestPath(rootDir);if(!fs.existsSync(manifestPath))return{ok:!1,error:`plugin manifest not found: ${manifestPath}`,manifestPath};let raw;try{raw=JSON.parse(fs.readFileSync(manifestPath,`utf-8`))}catch(err){return{ok:!1,error:`failed to parse plugin manifest: ${String(err)}`,manifestPath}}if(!isRecord(raw))return{ok:!1,error:`plugin manifest must be an object`,manifestPath};let id=typeof raw.id==`string`?raw.id.trim():``;if(!id)return{ok:!1,error:`plugin manifest requires id`,manifestPath};let configSchema=isRecord(raw.configSchema)?raw.configSchema:null;if(!configSchema)return{ok:!1,error:`plugin manifest requires configSchema`,manifestPath};let kind=typeof raw.kind==`string`?raw.kind:void 0,name=typeof raw.name==`string`?raw.name.trim():void 0,description=typeof raw.description==`string`?raw.description.trim():void 0,version=typeof raw.version==`string`?raw.version.trim():void 0,channels=normalizeStringList(raw.channels),providers=normalizeStringList(raw.providers),skills=normalizeStringList(raw.skills),hooks=normalizeStringList(raw.hooks),uiHints;return isRecord(raw.uiHints)&&(uiHints=raw.uiHints),{ok:!0,manifest:{id,configSchema,kind,channels,providers,skills,hooks,name,description,version,uiHints},manifestPath}}function getPackageManifestMetadata(manifest){if(!manifest)return;let current=manifest[MANIFEST_KEY];if(current!==void 0)return current;for(let legacyKey of LEGACY_MANIFEST_KEYS){let legacy=manifest[legacyKey];if(legacy!==void 0)return legacy}}const EXTENSION_EXTS=new Set([`.ts`,`.js`,`.mts`,`.cts`,`.mjs`,`.cjs`]);function isExtensionFile(filePath){let ext=path.extname(filePath);return EXTENSION_EXTS.has(ext)?!filePath.endsWith(`.d.ts`):!1}function readPackageManifest(dir){let manifestPath=path.join(dir,`package.json`);if(!fs.existsSync(manifestPath))return null;try{let raw=fs.readFileSync(manifestPath,`utf-8`);return JSON.parse(raw)}catch{return null}}function resolvePackageExtensions(manifest){let raw=getPackageManifestMetadata(manifest)?.extensions;return Array.isArray(raw)?raw.map(entry=>typeof entry==`string`?entry.trim():``).filter(Boolean):[]}function deriveIdHint(params){let base=path.basename(params.filePath,path.extname(params.filePath)),rawPackageName=params.packageName?.trim();if(!rawPackageName)return base;let unscoped=rawPackageName.includes(`/`)?rawPackageName.split(`/`).pop()??rawPackageName:rawPackageName;return params.hasMultipleExtensions?`${unscoped}/${base}`:unscoped}function addCandidate(params){let resolved=path.resolve(params.source);if(params.seen.has(resolved))return;params.seen.add(resolved);let manifest=params.manifest??null;params.candidates.push({idHint:params.idHint,source:resolved,rootDir:path.resolve(params.rootDir),origin:params.origin,workspaceDir:params.workspaceDir,packageName:manifest?.name?.trim()||void 0,packageVersion:manifest?.version?.trim()||void 0,packageDescription:manifest?.description?.trim()||void 0,packageDir:params.packageDir,packageManifest:getPackageManifestMetadata(manifest??void 0)})}function discoverInDirectory(params){if(!fs.existsSync(params.dir))return;let entries=[];try{entries=fs.readdirSync(params.dir,{withFileTypes:!0})}catch(err){params.diagnostics.push({level:`warn`,message:`failed to read extensions dir: ${params.dir} (${String(err)})`,source:params.dir});return}for(let entry of entries){let fullPath=path.join(params.dir,entry.name);if(entry.isFile()){if(!isExtensionFile(fullPath))continue;addCandidate({candidates:params.candidates,seen:params.seen,idHint:path.basename(entry.name,path.extname(entry.name)),source:fullPath,rootDir:path.dirname(fullPath),origin:params.origin,workspaceDir:params.workspaceDir})}if(!entry.isDirectory())continue;let manifest=readPackageManifest(fullPath),extensions=manifest?resolvePackageExtensions(manifest):[];if(extensions.length>0){for(let extPath of extensions){let resolved=path.resolve(fullPath,extPath);addCandidate({candidates:params.candidates,seen:params.seen,idHint:deriveIdHint({filePath:resolved,packageName:manifest?.name,hasMultipleExtensions:extensions.length>1}),source:resolved,rootDir:fullPath,origin:params.origin,workspaceDir:params.workspaceDir,manifest,packageDir:fullPath})}continue}let indexFile=[`index.ts`,`index.js`,`index.mjs`,`index.cjs`].map(candidate=>path.join(fullPath,candidate)).find(candidate=>fs.existsSync(candidate));indexFile&&isExtensionFile(indexFile)&&addCandidate({candidates:params.candidates,seen:params.seen,idHint:entry.name,source:indexFile,rootDir:fullPath,origin:params.origin,workspaceDir:params.workspaceDir,manifest,packageDir:fullPath})}}function discoverFromPath(params){let resolved=resolveUserPath(params.rawPath);if(!fs.existsSync(resolved)){params.diagnostics.push({level:`error`,message:`plugin path not found: ${resolved}`,source:resolved});return}let stat=fs.statSync(resolved);if(stat.isFile()){if(!isExtensionFile(resolved)){params.diagnostics.push({level:`error`,message:`plugin path is not a supported file: ${resolved}`,source:resolved});return}addCandidate({candidates:params.candidates,seen:params.seen,idHint:path.basename(resolved,path.extname(resolved)),source:resolved,rootDir:path.dirname(resolved),origin:params.origin,workspaceDir:params.workspaceDir});return}if(stat.isDirectory()){let manifest=readPackageManifest(resolved),extensions=manifest?resolvePackageExtensions(manifest):[];if(extensions.length>0){for(let extPath of extensions){let source=path.resolve(resolved,extPath);addCandidate({candidates:params.candidates,seen:params.seen,idHint:deriveIdHint({filePath:source,packageName:manifest?.name,hasMultipleExtensions:extensions.length>1}),source,rootDir:resolved,origin:params.origin,workspaceDir:params.workspaceDir,manifest,packageDir:resolved})}return}let indexFile=[`index.ts`,`index.js`,`index.mjs`,`index.cjs`].map(candidate=>path.join(resolved,candidate)).find(candidate=>fs.existsSync(candidate));if(indexFile&&isExtensionFile(indexFile)){addCandidate({candidates:params.candidates,seen:params.seen,idHint:path.basename(resolved),source:indexFile,rootDir:resolved,origin:params.origin,workspaceDir:params.workspaceDir,manifest,packageDir:resolved});return}discoverInDirectory({dir:resolved,origin:params.origin,workspaceDir:params.workspaceDir,candidates:params.candidates,diagnostics:params.diagnostics,seen:params.seen});return}}function discoverBuilderForceAgentsPlugins(params){let candidates=[],diagnostics=[],seen=new Set,workspaceDir=params.workspaceDir?.trim(),extra=params.extraPaths??[];for(let extraPath of extra){if(typeof extraPath!=`string`)continue;let trimmed=extraPath.trim();trimmed&&discoverFromPath({rawPath:trimmed,origin:`config`,workspaceDir:workspaceDir?.trim()||void 0,candidates,diagnostics,seen})}if(workspaceDir){let workspaceRoot=resolveUserPath(workspaceDir),workspaceExtDirs=[path.join(workspaceRoot,`.builderforce`,`extensions`)];for(let dir of workspaceExtDirs)discoverInDirectory({dir,origin:`workspace`,workspaceDir:workspaceRoot,candidates,diagnostics,seen})}discoverInDirectory({dir:path.join(resolveConfigDir(),`extensions`),origin:`global`,candidates,diagnostics,seen});let bundledDir=resolveBundledPluginsDir();return bundledDir&&discoverInDirectory({dir:bundledDir,origin:`bundled`,candidates,diagnostics,seen}),{candidates,diagnostics}}const PLUGIN_ORIGIN_RANK={config:0,workspace:1,global:2,bundled:3};function safeRealpathSync(rootDir,cache){let cached=cache.get(rootDir);if(cached)return cached;try{let resolved=fs.realpathSync(rootDir);return cache.set(rootDir,resolved),resolved}catch{return null}}const registryCache=new Map;function resolveManifestCacheMs(env){let raw=env.BUILDERFORCE_AGENTS_PLUGIN_MANIFEST_CACHE_MS?.trim();if(raw===``||raw===`0`)return 0;if(!raw)return 200;let parsed=Number.parseInt(raw,10);return Number.isFinite(parsed)?Math.max(0,parsed):200}function shouldUseManifestCache(env){return env.BUILDERFORCE_AGENTS_DISABLE_PLUGIN_MANIFEST_CACHE?.trim()?!1:resolveManifestCacheMs(env)>0}function buildCacheKey(params){let workspaceKey=params.workspaceDir?resolveUserPath(params.workspaceDir):``,loadPaths=params.plugins.loadPaths.map(p=>resolveUserPath(p)).map(p=>p.trim()).filter(Boolean).toSorted();return`${workspaceKey}::${JSON.stringify(loadPaths)}`}function safeStatMtimeMs(filePath){try{return fs.statSync(filePath).mtimeMs}catch{return null}}function normalizeManifestLabel(raw){return raw?.trim()||void 0}function buildRecord(params){return{id:params.manifest.id,name:normalizeManifestLabel(params.manifest.name)??params.candidate.packageName,description:normalizeManifestLabel(params.manifest.description)??params.candidate.packageDescription,version:normalizeManifestLabel(params.manifest.version)??params.candidate.packageVersion,kind:params.manifest.kind,channels:params.manifest.channels??[],providers:params.manifest.providers??[],skills:params.manifest.skills??[],hooks:params.manifest.hooks??[],origin:params.candidate.origin,workspaceDir:params.candidate.workspaceDir,rootDir:params.candidate.rootDir,source:params.candidate.source,manifestPath:params.manifestPath,schemaCacheKey:params.schemaCacheKey,configSchema:params.configSchema,configUiHints:params.manifest.uiHints}}function loadPluginManifestRegistry(params){let normalized=normalizePluginsConfig((params.config??{}).plugins),cacheKey=buildCacheKey({workspaceDir:params.workspaceDir,plugins:normalized}),env=params.env??process.env,cacheEnabled=params.cache!==!1&&shouldUseManifestCache(env);if(cacheEnabled){let cached=registryCache.get(cacheKey);if(cached&&cached.expiresAt>Date.now())return cached.registry}let discovery=params.candidates?{candidates:params.candidates,diagnostics:params.diagnostics??[]}:discoverBuilderForceAgentsPlugins({workspaceDir:params.workspaceDir,extraPaths:normalized.loadPaths}),diagnostics=[...discovery.diagnostics],candidates=discovery.candidates,records=[],seenIds=new Map,realpathCache=new Map;for(let candidate of candidates){let manifestRes=loadPluginManifest(candidate.rootDir);if(!manifestRes.ok){diagnostics.push({level:`error`,message:manifestRes.error,source:manifestRes.manifestPath});continue}let manifest=manifestRes.manifest;candidate.idHint&&candidate.idHint!==manifest.id&&diagnostics.push({level:`warn`,pluginId:manifest.id,source:candidate.source,message:`plugin id mismatch (manifest uses "${manifest.id}", entry hints "${candidate.idHint}")`});let configSchema=manifest.configSchema,manifestMtime=safeStatMtimeMs(manifestRes.manifestPath),schemaCacheKey=manifestMtime?`${manifestRes.manifestPath}:${manifestMtime}`:manifestRes.manifestPath,existing=seenIds.get(manifest.id);if(existing){let existingReal=safeRealpathSync(existing.candidate.rootDir,realpathCache),candidateReal=safeRealpathSync(candidate.rootDir,realpathCache);if(existingReal&&candidateReal&&existingReal===candidateReal){PLUGIN_ORIGIN_RANK[candidate.origin]<PLUGIN_ORIGIN_RANK[existing.candidate.origin]&&(records[existing.recordIndex]=buildRecord({manifest,candidate,manifestPath:manifestRes.manifestPath,schemaCacheKey,configSchema}),seenIds.set(manifest.id,{candidate,recordIndex:existing.recordIndex}));continue}diagnostics.push({level:`warn`,pluginId:manifest.id,source:candidate.source,message:`duplicate plugin id detected; later plugin may be overridden (${candidate.source})`})}else seenIds.set(manifest.id,{candidate,recordIndex:records.length});records.push(buildRecord({manifest,candidate,manifestPath:manifestRes.manifestPath,schemaCacheKey,configSchema}))}let registry={plugins:records,diagnostics};if(cacheEnabled){let ttl=resolveManifestCacheMs(env);ttl>0&®istryCache.set(cacheKey,{expiresAt:Date.now()+ttl,registry})}return registry}const ajv=new AjvPkg({allErrors:!0,strict:!1,removeAdditional:!1}),schemaCache=new Map;function formatAjvErrors(errors){return!errors||errors.length===0?[`invalid config`]:errors.map(error=>`${error.instancePath?.replace(/^\//,``).replace(/\//g,`.`)||`<root>`}: ${error.message??`invalid`}`)}function validateJsonSchemaValue(params){let cached=schemaCache.get(params.cacheKey);return(!cached||cached.schema!==params.schema)&&(cached={validate:ajv.compile(params.schema),schema:params.schema},schemaCache.set(params.cacheKey,cached)),cached.validate(params.value)?{ok:!0}:{ok:!1,errors:formatAjvErrors(cached.validate.errors)}}const AgentDefaultsSchema=z.object({model:z.object({primary:z.string().optional(),fallbacks:z.array(z.string()).optional()}).strict().optional(),imageModel:z.object({primary:z.string().optional(),fallbacks:z.array(z.string()).optional()}).strict().optional(),models:z.record(z.string(),z.object({alias:z.string().optional(),params:z.record(z.string(),z.unknown()).optional(),streaming:z.boolean().optional()}).strict()).optional(),workspace:z.string().optional(),repoRoot:z.string().optional(),skipBootstrap:z.boolean().optional(),bootstrapMaxChars:z.number().int().positive().optional(),bootstrapTotalMaxChars:z.number().int().positive().optional(),userTimezone:z.string().optional(),timeFormat:z.union([z.literal(`auto`),z.literal(`12`),z.literal(`24`)]).optional(),envelopeTimezone:z.string().optional(),envelopeTimestamp:z.union([z.literal(`on`),z.literal(`off`)]).optional(),envelopeElapsed:z.union([z.literal(`on`),z.literal(`off`)]).optional(),contextTokens:z.number().int().positive().optional(),cliBackends:z.record(z.string(),CliBackendSchema).optional(),memorySearch:MemorySearchSchema,contextPruning:z.object({mode:z.union([z.literal(`off`),z.literal(`cache-ttl`)]).optional(),ttl:z.string().optional(),keepLastAssistants:z.number().int().nonnegative().optional(),softTrimRatio:z.number().min(0).max(1).optional(),hardClearRatio:z.number().min(0).max(1).optional(),minPrunableToolChars:z.number().int().nonnegative().optional(),tools:z.object({allow:z.array(z.string()).optional(),deny:z.array(z.string()).optional()}).strict().optional(),softTrim:z.object({maxChars:z.number().int().nonnegative().optional(),headChars:z.number().int().nonnegative().optional(),tailChars:z.number().int().nonnegative().optional()}).strict().optional(),hardClear:z.object({enabled:z.boolean().optional(),placeholder:z.string().optional()}).strict().optional()}).strict().optional(),compaction:z.object({mode:z.union([z.literal(`default`),z.literal(`safeguard`)]).optional(),reserveTokensFloor:z.number().int().nonnegative().optional(),maxHistoryShare:z.number().min(.1).max(.9).optional(),memoryFlush:z.object({enabled:z.boolean().optional(),softThresholdTokens:z.number().int().nonnegative().optional(),prompt:z.string().optional(),systemPrompt:z.string().optional()}).strict().optional()}).strict().optional(),thinkingDefault:z.union([z.literal(`off`),z.literal(`minimal`),z.literal(`low`),z.literal(`medium`),z.literal(`high`),z.literal(`xhigh`)]).optional(),verboseDefault:z.union([z.literal(`off`),z.literal(`on`),z.literal(`full`)]).optional(),elevatedDefault:z.union([z.literal(`off`),z.literal(`on`),z.literal(`ask`),z.literal(`full`)]).optional(),blockStreamingDefault:z.union([z.literal(`off`),z.literal(`on`)]).optional(),blockStreamingBreak:z.union([z.literal(`text_end`),z.literal(`message_end`)]).optional(),blockStreamingChunk:BlockStreamingChunkSchema.optional(),blockStreamingCoalesce:BlockStreamingCoalesceSchema.optional(),humanDelay:HumanDelaySchema.optional(),timeoutSeconds:z.number().int().positive().optional(),maxAutoContinueNudges:z.number().int().positive().optional(),mediaMaxMb:z.number().positive().optional(),imageMaxDimensionPx:z.number().int().positive().optional(),typingIntervalSeconds:z.number().int().positive().optional(),typingMode:z.union([z.literal(`never`),z.literal(`instant`),z.literal(`thinking`),z.literal(`message`)]).optional(),heartbeat:HeartbeatSchema,maxConcurrent:z.number().int().positive().optional(),subagents:z.object({maxConcurrent:z.number().int().positive().optional(),maxSpawnDepth:z.number().int().min(1).max(5).optional().describe(`Maximum nesting depth for sub-agent spawning. 1 = no nesting (default), 2 = sub-agents can spawn sub-sub-agents.`),maxChildrenPerAgent:z.number().int().min(1).max(20).optional().describe(`Maximum number of active children a single agent session can spawn (default: 5).`),archiveAfterMinutes:z.number().int().positive().optional(),model:AgentModelSchema.optional(),thinking:z.string().optional()}).strict().optional(),sandbox:AgentSandboxSchema}).strict().optional(),AgentsSchema=z.object({defaults:z.lazy(()=>AgentDefaultsSchema).optional(),list:z.array(AgentEntrySchema).optional()}).strict().optional(),BindingsSchema=z.array(z.object({agentId:z.string(),match:z.object({channel:z.string(),accountId:z.string().optional(),peer:z.object({kind:z.union([z.literal(`direct`),z.literal(`group`),z.literal(`channel`),z.literal(`dm`)]),id:z.string()}).strict().optional(),guildId:z.string().optional(),teamId:z.string().optional(),roles:z.array(z.string()).optional()}).strict()}).strict()).optional(),BroadcastStrategySchema=z.enum([`parallel`,`sequential`]),BroadcastSchema=z.object({strategy:BroadcastStrategySchema.optional()}).catchall(z.array(z.string())).optional(),AudioSchema=z.object({transcription:TranscribeAudioSchema}).strict().optional(),ExecApprovalForwardTargetSchema=z.object({channel:z.string().min(1),to:z.string().min(1),accountId:z.string().optional(),threadId:z.union([z.string(),z.number()]).optional()}).strict(),ExecApprovalForwardingSchema=z.object({enabled:z.boolean().optional(),mode:z.union([z.literal(`session`),z.literal(`targets`),z.literal(`both`)]).optional(),agentFilter:z.array(z.string()).optional(),sessionFilter:z.array(z.string()).optional(),targets:z.array(ExecApprovalForwardTargetSchema).optional()}).strict().optional(),ApprovalsSchema=z.object({exec:ExecApprovalForwardingSchema}).strict().optional(),InstallRecordShape={source:z.union([z.literal(`npm`),z.literal(`archive`),z.literal(`path`)]),spec:z.string().optional(),sourcePath:z.string().optional(),installPath:z.string().optional(),version:z.string().optional(),installedAt:z.string().optional()};function isSafeRelativeModulePath(raw){let value=raw.trim();return!(!value||path.isAbsolute(value)||value.startsWith(`~`)||value.includes(`:`)||value.split(/[\\/]+/g).some(part=>part===`..`))}const SafeRelativeModulePathSchema=z.string().refine(isSafeRelativeModulePath,`module must be a safe relative path (no absolute paths)`),HookMappingSchema=z.object({id:z.string().optional(),match:z.object({path:z.string().optional(),source:z.string().optional()}).optional(),action:z.union([z.literal(`wake`),z.literal(`agent`)]).optional(),wakeMode:z.union([z.literal(`now`),z.literal(`next-heartbeat`)]).optional(),name:z.string().optional(),agentId:z.string().optional(),sessionKey:z.string().optional().register(sensitive),messageTemplate:z.string().optional(),textTemplate:z.string().optional(),deliver:z.boolean().optional(),allowUnsafeExternalContent:z.boolean().optional(),channel:z.union([z.literal(`last`),z.literal(`whatsapp`),z.literal(`telegram`),z.literal(`discord`),z.literal(`irc`),z.literal(`slack`),z.literal(`signal`),z.literal(`imessage`),z.literal(`msteams`)]).optional(),to:z.string().optional(),model:z.string().optional(),thinking:z.string().optional(),timeoutSeconds:z.number().int().positive().optional(),transform:z.object({module:SafeRelativeModulePathSchema,export:z.string().optional()}).strict().optional()}).strict().optional(),InternalHookHandlerSchema=z.object({event:z.string(),module:SafeRelativeModulePathSchema,export:z.string().optional()}).strict(),HookConfigSchema=z.object({enabled:z.boolean().optional(),env:z.record(z.string(),z.string()).optional()}).passthrough(),HookInstallRecordSchema=z.object({...InstallRecordShape,hooks:z.array(z.string()).optional()}).strict(),InternalHooksSchema=z.object({enabled:z.boolean().optional(),handlers:z.array(InternalHookHandlerSchema).optional(),entries:z.record(z.string(),HookConfigSchema).optional(),load:z.object({extraDirs:z.array(z.string()).optional()}).strict().optional(),installs:z.record(z.string(),HookInstallRecordSchema).optional()}).strict().optional(),HooksGmailSchema=z.object({account:z.string().optional(),label:z.string().optional(),topic:z.string().optional(),subscription:z.string().optional(),pushToken:z.string().optional().register(sensitive),hookUrl:z.string().optional(),includeBody:z.boolean().optional(),maxBytes:z.number().int().positive().optional(),renewEveryMinutes:z.number().int().positive().optional(),allowUnsafeExternalContent:z.boolean().optional(),serve:z.object({bind:z.string().optional(),port:z.number().int().positive().optional(),path:z.string().optional()}).strict().optional(),tailscale:z.object({mode:z.union([z.literal(`off`),z.literal(`serve`),z.literal(`funnel`)]).optional(),path:z.string().optional(),target:z.string().optional()}).strict().optional(),model:z.string().optional(),thinking:z.union([z.literal(`off`),z.literal(`minimal`),z.literal(`low`),z.literal(`medium`),z.literal(`high`)]).optional()}).strict().optional(),ChannelsSchema=z.object({defaults:z.object({groupPolicy:GroupPolicySchema.optional(),heartbeat:ChannelHeartbeatVisibilitySchema}).strict().optional(),whatsapp:WhatsAppConfigSchema.optional(),telegram:TelegramConfigSchema.optional(),discord:DiscordConfigSchema.optional(),irc:IrcConfigSchema.optional(),googlechat:GoogleChatConfigSchema.optional(),slack:SlackConfigSchema.optional(),signal:SignalConfigSchema.optional(),imessage:IMessageConfigSchema.optional(),bluebubbles:BlueBubblesConfigSchema.optional(),msteams:MSTeamsConfigSchema.optional()}).passthrough().optional(),UNIT_MULTIPLIERS={b:1,kb:1024,k:1024,mb:1024**2,m:1024**2,gb:1024**3,g:1024**3,tb:1024**4,t:1024**4};function parseByteSize(raw,opts){let trimmed=String(raw??``).trim().toLowerCase();if(!trimmed)throw Error(`invalid byte size (empty)`);let m=/^(\d+(?:\.\d+)?)([a-z]+)?$/.exec(trimmed);if(!m)throw Error(`invalid byte size: ${raw}`);let value=Number(m[1]);if(!Number.isFinite(value)||value<0)throw Error(`invalid byte size: ${raw}`);let multiplier=UNIT_MULTIPLIERS[(m[2]??opts?.defaultUnit??`b`).toLowerCase()];if(!multiplier)throw Error(`invalid byte size unit: ${raw}`);let bytes=Math.round(value*multiplier);if(!Number.isFinite(bytes))throw Error(`invalid byte size: ${raw}`);return bytes}const SessionResetConfigSchema=z.object({mode:z.union([z.literal(`daily`),z.literal(`idle`)]).optional(),atHour:z.number().int().min(0).max(23).optional(),idleMinutes:z.number().int().positive().optional()}).strict(),SessionSendPolicySchema=createAllowDenyChannelRulesSchema(),SessionSchema=z.object({scope:z.union([z.literal(`per-sender`),z.literal(`global`)]).optional(),dmScope:z.union([z.literal(`main`),z.literal(`per-peer`),z.literal(`per-channel-peer`),z.literal(`per-account-channel-peer`)]).optional(),identityLinks:z.record(z.string(),z.array(z.string())).optional(),resetTriggers:z.array(z.string()).optional(),idleMinutes:z.number().int().positive().optional(),reset:SessionResetConfigSchema.optional(),resetByType:z.object({direct:SessionResetConfigSchema.optional(),dm:SessionResetConfigSchema.optional(),group:SessionResetConfigSchema.optional(),thread:SessionResetConfigSchema.optional()}).strict().optional(),resetByChannel:z.record(z.string(),SessionResetConfigSchema).optional(),store:z.string().optional(),typingIntervalSeconds:z.number().int().positive().optional(),typingMode:z.union([z.literal(`never`),z.literal(`instant`),z.literal(`thinking`),z.literal(`message`)]).optional(),mainKey:z.string().optional(),sendPolicy:SessionSendPolicySchema.optional(),agentToAgent:z.object({maxPingPongTurns:z.number().int().min(0).max(5).optional()}).strict().optional(),maintenance:z.object({mode:z.enum([`enforce`,`warn`]).optional(),pruneAfter:z.union([z.string(),z.number()]).optional(),pruneDays:z.number().int().positive().optional(),maxEntries:z.number().int().positive().optional(),rotateBytes:z.union([z.string(),z.number()]).optional()}).strict().superRefine((val,ctx)=>{if(val.pruneAfter!==void 0)try{parseDurationMs(String(val.pruneAfter).trim(),{defaultUnit:`d`})}catch{ctx.addIssue({code:z.ZodIssueCode.custom,path:[`pruneAfter`],message:`invalid duration (use ms, s, m, h, d)`})}if(val.rotateBytes!==void 0)try{parseByteSize(String(val.rotateBytes).trim(),{defaultUnit:`b`})}catch{ctx.addIssue({code:z.ZodIssueCode.custom,path:[`rotateBytes`],message:`invalid size (use b, kb, mb, gb, tb)`})}}).optional()}).strict().optional(),MessagesSchema=z.object({messagePrefix:z.string().optional(),responsePrefix:z.string().optional(),groupChat:GroupChatSchema,queue:QueueSchema,inbound:InboundDebounceSchema,ackReaction:z.string().optional(),ackReactionScope:z.enum([`group-mentions`,`group-all`,`direct`,`all`]).optional(),removeAckAfterReply:z.boolean().optional(),suppressToolErrors:z.boolean().optional(),tts:TtsConfigSchema}).strict().optional(),CommandsSchema=z.object({native:NativeCommandsSettingSchema.optional().default(`auto`),nativeSkills:NativeCommandsSettingSchema.optional().default(`auto`),text:z.boolean().optional(),bash:z.boolean().optional(),bashForegroundMs:z.number().int().min(0).max(3e4).optional(),config:z.boolean().optional(),debug:z.boolean().optional(),restart:z.boolean().optional(),useAccessGroups:z.boolean().optional(),ownerAllowFrom:z.array(z.union([z.string(),z.number()])).optional(),allowFrom:ElevatedAllowFromSchema.optional()}).strict().optional().default({native:`auto`,nativeSkills:`auto`}),BrowserSnapshotDefaultsSchema=z.object({mode:z.literal(`efficient`).optional()}).strict().optional(),NodeHostSchema=z.object({browserProxy:z.object({enabled:z.boolean().optional(),allowProfiles:z.array(z.string()).optional()}).strict().optional()}).strict().optional(),MemoryQmdPathSchema=z.object({path:z.string(),name:z.string().optional(),pattern:z.string().optional()}).strict(),MemoryQmdSessionSchema=z.object({enabled:z.boolean().optional(),exportDir:z.string().optional(),retentionDays:z.number().int().nonnegative().optional()}).strict(),MemoryQmdUpdateSchema=z.object({interval:z.string().optional(),debounceMs:z.number().int().nonnegative().optional(),onBoot:z.boolean().optional(),waitForBootSync:z.boolean().optional(),embedInterval:z.string().optional(),commandTimeoutMs:z.number().int().nonnegative().optional(),updateTimeoutMs:z.number().int().nonnegative().optional(),embedTimeoutMs:z.number().int().nonnegative().optional()}).strict(),MemoryQmdLimitsSchema=z.object({maxResults:z.number().int().positive().optional(),maxSnippetChars:z.number().int().positive().optional(),maxInjectedChars:z.number().int().positive().optional(),timeoutMs:z.number().int().nonnegative().optional()}).strict(),MemoryQmdSchema=z.object({command:z.string().optional(),searchMode:z.union([z.literal(`query`),z.literal(`search`),z.literal(`vsearch`)]).optional(),includeDefaultMemory:z.boolean().optional(),paths:z.array(MemoryQmdPathSchema).optional(),sessions:MemoryQmdSessionSchema.optional(),update:MemoryQmdUpdateSchema.optional(),limits:MemoryQmdLimitsSchema.optional(),scope:SessionSendPolicySchema.optional()}).strict(),MemorySchema=z.object({backend:z.union([z.literal(`builtin`),z.literal(`qmd`)]).optional(),citations:z.union([z.literal(`auto`),z.literal(`on`),z.literal(`off`)]).optional(),qmd:MemoryQmdSchema.optional()}).strict().optional(),HttpUrlSchema=z.string().url().refine(value=>{let protocol=new URL(value).protocol;return protocol===`http:`||protocol===`https:`},`Expected http:// or https:// URL`),BuilderForceAgentsSchema=z.object({$schema:z.string().optional(),meta:z.object({lastTouchedVersion:z.string().optional(),lastTouchedAt:z.string().optional()}).strict().optional(),env:z.object({shellEnv:z.object({enabled:z.boolean().optional(),timeoutMs:z.number().int().nonnegative().optional()}).strict().optional(),vars:z.record(z.string(),z.string()).optional()}).catchall(z.string()).optional(),wizard:z.object({lastRunAt:z.string().optional(),lastRunVersion:z.string().optional(),lastRunCommit:z.string().optional(),lastRunCommand:z.string().optional(),lastRunMode:z.union([z.literal(`local`),z.literal(`remote`)]).optional()}).strict().optional(),diagnostics:z.object({enabled:z.boolean().optional(),flags:z.array(z.string()).optional(),otel:z.object({enabled:z.boolean().optional(),endpoint:z.string().optional(),protocol:z.union([z.literal(`http/protobuf`),z.literal(`grpc`)]).optional(),headers:z.record(z.string(),z.string()).optional(),serviceName:z.string().optional(),traces:z.boolean().optional(),metrics:z.boolean().optional(),logs:z.boolean().optional(),sampleRate:z.number().min(0).max(1).optional(),flushIntervalMs:z.number().int().nonnegative().optional()}).strict().optional(),cacheTrace:z.object({enabled:z.boolean().optional(),filePath:z.string().optional(),includeMessages:z.boolean().optional(),includePrompt:z.boolean().optional(),includeSystem:z.boolean().optional()}).strict().optional()}).strict().optional(),logging:z.object({enabled:z.boolean().optional(),format:z.union([z.literal(`json`),z.literal(`text`)]).optional(),level:z.union([z.literal(`silent`),z.literal(`fatal`),z.literal(`error`),z.literal(`warn`),z.literal(`info`),z.literal(`debug`),z.literal(`trace`)]).optional(),file:z.string().optional(),consoleLevel:z.union([z.literal(`silent`),z.literal(`fatal`),z.literal(`error`),z.literal(`warn`),z.literal(`info`),z.literal(`debug`),z.literal(`trace`)]).optional(),consoleStyle:z.union([z.literal(`pretty`),z.literal(`compact`),z.literal(`json`)]).optional(),redactSensitive:z.union([z.literal(`off`),z.literal(`tools`)]).optional(),redactPatterns:z.array(z.string()).optional()}).strict().optional(),update:z.object({channel:z.union([z.literal(`stable`),z.literal(`beta`),z.literal(`dev`)]).optional(),checkOnStart:z.boolean().optional()}).strict().optional(),browser:z.object({enabled:z.boolean().optional(),evaluateEnabled:z.boolean().optional(),cdpUrl:z.string().optional(),remoteCdpTimeoutMs:z.number().int().nonnegative().optional(),remoteCdpHandshakeTimeoutMs:z.number().int().nonnegative().optional(),color:z.string().optional(),executablePath:z.string().optional(),headless:z.boolean().optional(),noSandbox:z.boolean().optional(),attachOnly:z.boolean().optional(),defaultProfile:z.string().optional(),snapshotDefaults:BrowserSnapshotDefaultsSchema,profiles:z.record(z.string().regex(/^[a-z0-9-]+$/,`Profile names must be alphanumeric with hyphens only`),z.object({cdpPort:z.number().int().min(1).max(65535).optional(),cdpUrl:z.string().optional(),driver:z.union([z.literal(`builderforce`),z.literal(`extension`)]).optional(),color:HexColorSchema}).strict().refine(value=>value.cdpPort||value.cdpUrl,{message:`Profile must set cdpPort or cdpUrl`})).optional()}).strict().optional(),ui:z.object({seamColor:HexColorSchema.optional(),assistant:z.object({name:z.string().max(50).optional(),avatar:z.string().max(200).optional()}).strict().optional()}).strict().optional(),auth:z.object({profiles:z.record(z.string(),z.object({provider:z.string(),mode:z.union([z.literal(`api_key`),z.literal(`oauth`),z.literal(`token`)]),email:z.string().optional()}).strict()).optional(),order:z.record(z.string(),z.array(z.string())).optional(),cooldowns:z.object({billingBackoffHours:z.number().positive().optional(),billingBackoffHoursByProvider:z.record(z.string(),z.number().positive()).optional(),billingMaxHours:z.number().positive().optional(),failureWindowHours:z.number().positive().optional()}).strict().optional()}).strict().optional(),models:ModelsConfigSchema,nodeHost:NodeHostSchema,agents:AgentsSchema,tools:ToolsSchema,bindings:BindingsSchema,broadcast:BroadcastSchema,audio:AudioSchema,media:z.object({preserveFilenames:z.boolean().optional()}).strict().optional(),messages:MessagesSchema,commands:CommandsSchema,approvals:ApprovalsSchema,session:SessionSchema,cron:z.object({enabled:z.boolean().optional(),store:z.string().optional(),maxConcurrentRuns:z.number().int().positive().optional(),webhook:HttpUrlSchema.optional(),webhookToken:z.string().optional().register(sensitive),sessionRetention:z.union([z.string(),z.literal(!1)]).optional()}).strict().optional(),hooks:z.object({enabled:z.boolean().optional(),path:z.string().optional(),token:z.string().optional().register(sensitive),defaultSessionKey:z.string().optional(),allowRequestSessionKey:z.boolean().optional(),allowedSessionKeyPrefixes:z.array(z.string()).optional(),allowedAgentIds:z.array(z.string()).optional(),maxBodyBytes:z.number().int().positive().optional(),presets:z.array(z.string()).optional(),transformsDir:z.string().optional(),mappings:z.array(HookMappingSchema).optional(),gmail:HooksGmailSchema,internal:InternalHooksSchema}).strict().optional(),web:z.object({enabled:z.boolean().optional(),heartbeatSeconds:z.number().int().positive().optional(),reconnect:z.object({initialMs:z.number().positive().optional(),maxMs:z.number().positive().optional(),factor:z.number().positive().optional(),jitter:z.number().min(0).max(1).optional(),maxAttempts:z.number().int().min(0).optional()}).strict().optional()}).strict().optional(),channels:ChannelsSchema,discovery:z.object({wideArea:z.object({enabled:z.boolean().optional()}).strict().optional(),mdns:z.object({mode:z.enum([`off`,`minimal`,`full`]).optional()}).strict().optional()}).strict().optional(),canvasHost:z.object({enabled:z.boolean().optional(),root:z.string().optional(),port:z.number().int().positive().optional(),liveReload:z.boolean().optional()}).strict().optional(),talk:z.object({voiceId:z.string().optional(),voiceAliases:z.record(z.string(),z.string()).optional(),modelId:z.string().optional(),outputFormat:z.string().optional(),apiKey:z.string().optional().register(sensitive),interruptOnSpeech:z.boolean().optional()}).strict().optional(),gateway:z.object({port:z.number().int().positive().optional(),mode:z.union([z.literal(`local`),z.literal(`remote`)]).optional(),bind:z.union([z.literal(`auto`),z.literal(`lan`),z.literal(`loopback`),z.literal(`custom`),z.literal(`tailnet`)]).optional(),controlUi:z.object({enabled:z.boolean().optional(),basePath:z.string().optional(),root:z.string().optional(),allowedOrigins:z.array(z.string()).optional(),allowInsecureAuth:z.boolean().optional(),dangerouslyDisableDeviceAuth:z.boolean().optional()}).strict().optional(),auth:z.object({mode:z.union([z.literal(`token`),z.literal(`password`),z.literal(`trusted-proxy`)]).optional(),token:z.string().optional().register(sensitive),password:z.string().optional().register(sensitive),allowTailscale:z.boolean().optional(),rateLimit:z.object({maxAttempts:z.number().optional(),windowMs:z.number().optional(),lockoutMs:z.number().optional(),exemptLoopback:z.boolean().optional()}).strict().optional(),trustedProxy:z.object({userHeader:z.string().min(1,`userHeader is required for trusted-proxy mode`),requiredHeaders:z.array(z.string()).optional(),allowUsers:z.array(z.string()).optional()}).strict().optional()}).strict().optional(),trustedProxies:z.array(z.string()).optional(),tools:z.object({deny:z.array(z.string()).optional(),allow:z.array(z.string()).optional()}).strict().optional(),channelHealthCheckMinutes:z.number().int().min(0).optional(),tailscale:z.object({mode:z.union([z.literal(`off`),z.literal(`serve`),z.literal(`funnel`)]).optional(),resetOnExit:z.boolean().optional()}).strict().optional(),remote:z.object({url:z.string().optional(),transport:z.union([z.literal(`ssh`),z.literal(`direct`)]).optional(),token:z.string().optional().register(sensitive),password:z.string().optional().register(sensitive),tlsFingerprint:z.string().optional(),sshTarget:z.string().optional(),sshIdentity:z.string().optional()}).strict().optional(),reload:z.object({mode:z.union([z.literal(`off`),z.literal(`restart`),z.literal(`hot`),z.literal(`hybrid`)]).optional(),debounceMs:z.number().int().min(0).optional()}).strict().optional(),tls:z.object({enabled:z.boolean().optional(),autoGenerate:z.boolean().optional(),certPath:z.string().optional(),keyPath:z.string().optional(),caPath:z.string().optional()}).optional(),http:z.object({endpoints:z.object({chatCompletions:z.object({enabled:z.boolean().optional()}).strict().optional(),responses:z.object({enabled:z.boolean().optional(),maxBodyBytes:z.number().int().positive().optional(),maxUrlParts:z.number().int().nonnegative().optional(),files:z.object({allowUrl:z.boolean().optional(),urlAllowlist:z.array(z.string()).optional(),allowedMimes:z.array(z.string()).optional(),maxBytes:z.number().int().positive().optional(),maxChars:z.number().int().positive().optional(),maxRedirects:z.number().int().nonnegative().optional(),timeoutMs:z.number().int().positive().optional(),pdf:z.object({maxPages:z.number().int().positive().optional(),maxPixels:z.number().int().positive().optional(),minTextChars:z.number().int().nonnegative().optional()}).strict().optional()}).strict().optional(),images:z.object({allowUrl:z.boolean().optional(),urlAllowlist:z.array(z.string()).optional(),allowedMimes:z.array(z.string()).optional(),maxBytes:z.number().int().positive().optional(),maxRedirects:z.number().int().nonnegative().optional(),timeoutMs:z.number().int().positive().optional()}).strict().optional()}).strict().optional()}).strict().optional()}).strict().optional(),nodes:z.object({browser:z.object({mode:z.union([z.literal(`auto`),z.literal(`manual`),z.literal(`off`)]).optional(),node:z.string().optional()}).strict().optional(),allowCommands:z.array(z.string()).optional(),denyCommands:z.array(z.string()).optional()}).strict().optional()}).strict().optional(),memory:MemorySchema,skills:z.object({allowBundled:z.array(z.string()).optional(),load:z.object({extraDirs:z.array(z.string()).optional(),watch:z.boolean().optional(),watchDebounceMs:z.number().int().min(0).optional()}).strict().optional(),install:z.object({preferBrew:z.boolean().optional(),nodeManager:z.union([z.literal(`npm`),z.literal(`pnpm`),z.literal(`yarn`),z.literal(`bun`)]).optional()}).strict().optional(),limits:z.object({maxCandidatesPerRoot:z.number().int().min(1).optional(),maxSkillsLoadedPerSource:z.number().int().min(1).optional(),maxSkillsInPrompt:z.number().int().min(0).optional(),maxSkillsPromptChars:z.number().int().min(0).optional(),maxSkillFileBytes:z.number().int().min(0).optional()}).strict().optional(),registry:z.object({url:z.string().url().optional(),cli:z.string().optional()}).strict().optional(),entries:z.record(z.string(),z.object({enabled:z.boolean().optional(),apiKey:z.string().optional().register(sensitive),env:z.record(z.string(),z.string()).optional(),config:z.record(z.string(),z.unknown()).optional()}).strict()).optional()}).strict().optional(),plugins:z.object({enabled:z.boolean().optional(),allow:z.array(z.string()).optional(),deny:z.array(z.string()).optional(),load:z.object({paths:z.array(z.string()).optional()}).strict().optional(),slots:z.object({memory:z.string().optional()}).strict().optional(),entries:z.record(z.string(),z.object({enabled:z.boolean().optional(),config:z.record(z.string(),z.unknown()).optional()}).strict()).optional(),installs:z.record(z.string(),z.object({...InstallRecordShape}).strict()).optional()}).strict().optional(),localBrain:z.object({enabled:z.boolean().optional(),models:z.object({amygdala:z.object({modelId:z.string().optional(),dtype:z.string().optional()}).strict().optional(),hippocampus:z.object({modelId:z.string().optional(),dtype:z.string().optional()}).strict().optional()}).strict().optional()}).strict().optional()}).strict().superRefine((cfg,ctx)=>{let agents=cfg.agents?.list??[];if(agents.length===0)return;let agentIds=new Set(agents.map(agent=>agent.id)),broadcast=cfg.broadcast;if(broadcast){for(let[peerId,ids]of Object.entries(broadcast))if(peerId!==`strategy`&&Array.isArray(ids))for(let idx=0;idx<ids.length;idx+=1){let agentId=ids[idx];agentIds.has(agentId)||ctx.addIssue({code:z.ZodIssueCode.custom,path:[`broadcast`,peerId,idx],message:`Unknown agent id "${agentId}" (not in agents.list).`})}}}),AVATAR_SCHEME_RE=/^[a-z][a-z0-9+.-]*:/i,AVATAR_DATA_RE=/^data:/i,AVATAR_HTTP_RE=/^https?:\/\//i,WINDOWS_ABS_RE=/^[a-zA-Z]:[\\/]/;function isWorkspaceAvatarPath(value,workspaceDir){let workspaceRoot=path.resolve(workspaceDir),resolved=path.resolve(workspaceRoot,value),relative=path.relative(workspaceRoot,resolved);return relative===``?!0:relative.startsWith(`..`)?!1:!path.isAbsolute(relative)}function validateIdentityAvatar(config){let agents=config.agents?.list;if(!Array.isArray(agents)||agents.length===0)return[];let issues=[];for(let[index,entry]of agents.entries()){if(!entry||typeof entry!=`object`)continue;let avatarRaw=entry.identity?.avatar;if(typeof avatarRaw!=`string`)continue;let avatar=avatarRaw.trim();if(avatar&&!(AVATAR_DATA_RE.test(avatar)||AVATAR_HTTP_RE.test(avatar))){if(avatar.startsWith(`~`)){issues.push({path:`agents.list.${index}.identity.avatar`,message:`identity.avatar must be a workspace-relative path, http(s) URL, or data URI.`});continue}if(AVATAR_SCHEME_RE.test(avatar)&&!WINDOWS_ABS_RE.test(avatar)){issues.push({path:`agents.list.${index}.identity.avatar`,message:`identity.avatar must be a workspace-relative path, http(s) URL, or data URI.`});continue}isWorkspaceAvatarPath(avatar,resolveAgentWorkspaceDir(config,entry.id??resolveDefaultAgentId(config)))||issues.push({path:`agents.list.${index}.identity.avatar`,message:`identity.avatar must stay within the agent workspace.`})}}return issues}function validateConfigObjectRaw(raw){let legacyIssues=findLegacyConfigIssues(raw);if(legacyIssues.length>0)return{ok:!1,issues:legacyIssues.map(iss=>({path:iss.path,message:iss.message}))};let validated=BuilderForceAgentsSchema.safeParse(raw);if(!validated.success)return{ok:!1,issues:validated.error.issues.map(iss=>({path:iss.path.join(`.`),message:iss.message}))};let duplicates=findDuplicateAgentDirs(validated.data);if(duplicates.length>0)return{ok:!1,issues:[{path:`agents.list`,message:formatDuplicateAgentDirError(duplicates)}]};let avatarIssues=validateIdentityAvatar(validated.data);return avatarIssues.length>0?{ok:!1,issues:avatarIssues}:{ok:!0,config:validated.data}}function validateConfigObject(raw){let result=validateConfigObjectRaw(raw);return result.ok?{ok:!0,config:applyModelDefaults(applyAgentDefaults(applySessionDefaults(result.config)))}:result}function validateConfigObjectWithPlugins(raw){return validateConfigObjectWithPluginsBase(raw,{applyDefaults:!0})}function validateConfigObjectRawWithPlugins(raw){return validateConfigObjectWithPluginsBase(raw,{applyDefaults:!1})}function validateConfigObjectWithPluginsBase(raw,opts){let base=opts.applyDefaults?validateConfigObject(raw):validateConfigObjectRaw(raw);if(!base.ok)return{ok:!1,issues:base.issues,warnings:[]};let config=base.config,issues=[],warnings=[],hasExplicitPluginsConfig=isRecord(raw)&&Object.prototype.hasOwnProperty.call(raw,`plugins`),registryInfo=null,ensureRegistry=()=>{if(registryInfo)return registryInfo;let registry=loadPluginManifestRegistry({config,workspaceDir:resolveAgentWorkspaceDir(config,resolveDefaultAgentId(config))??void 0}),knownIds=new Set(registry.plugins.map(record=>record.id)),normalizedPlugins=normalizePluginsConfig(config.plugins);for(let diag of registry.diagnostics){let path=diag.pluginId?`plugins.entries.${diag.pluginId}`:`plugins`;!diag.pluginId&&diag.message.includes(`plugin path not found`)&&(path=`plugins.load.paths`);let message=`${diag.pluginId?`plugin ${diag.pluginId}`:`plugin`}: ${diag.message}`;diag.level===`error`?issues.push({path,message}):warnings.push({path,message})}return registryInfo={registry,knownIds,normalizedPlugins},registryInfo},allowedChannels=new Set([`defaults`,...CHANNEL_IDS]);if(config.channels&&isRecord(config.channels))for(let key of Object.keys(config.channels)){let trimmed=key.trim();if(trimmed){if(!allowedChannels.has(trimmed)){let{registry}=ensureRegistry();for(let record of registry.plugins)for(let channelId of record.channels)allowedChannels.add(channelId)}allowedChannels.has(trimmed)||issues.push({path:`channels.${trimmed}`,message:`unknown channel id: ${trimmed}`})}}let heartbeatChannelIds=new Set;for(let channelId of CHANNEL_IDS)heartbeatChannelIds.add(channelId.toLowerCase());let validateHeartbeatTarget=(target,path)=>{if(typeof target!=`string`)return;let trimmed=target.trim();if(!trimmed){issues.push({path,message:`heartbeat target must not be empty`});return}let normalized=trimmed.toLowerCase();if(!(normalized===`last`||normalized===`none`)&&!normalizeChatChannelId(trimmed)){if(!heartbeatChannelIds.has(normalized)){let{registry}=ensureRegistry();for(let record of registry.plugins)for(let channelId of record.channels){let pluginChannel=channelId.trim();pluginChannel&&heartbeatChannelIds.add(pluginChannel.toLowerCase())}}heartbeatChannelIds.has(normalized)||issues.push({path,message:`unknown heartbeat target: ${target}`})}};if(validateHeartbeatTarget(config.agents?.defaults?.heartbeat?.target,`agents.defaults.heartbeat.target`),Array.isArray(config.agents?.list))for(let[index,entry]of config.agents.list.entries())validateHeartbeatTarget(entry?.heartbeat?.target,`agents.list.${index}.heartbeat.target`);if(!hasExplicitPluginsConfig)return issues.length>0?{ok:!1,issues,warnings}:{ok:!0,config,warnings};let{registry,knownIds,normalizedPlugins}=ensureRegistry(),pluginsConfig=config.plugins,entries=pluginsConfig?.entries;if(entries&&isRecord(entries))for(let pluginId of Object.keys(entries))knownIds.has(pluginId)||issues.push({path:`plugins.entries.${pluginId}`,message:`plugin not found: ${pluginId}`});let allow=pluginsConfig?.allow??[];for(let pluginId of allow)typeof pluginId!=`string`||!pluginId.trim()||knownIds.has(pluginId)||issues.push({path:`plugins.allow`,message:`plugin not found: ${pluginId}`});let deny=pluginsConfig?.deny??[];for(let pluginId of deny)typeof pluginId!=`string`||!pluginId.trim()||knownIds.has(pluginId)||issues.push({path:`plugins.deny`,message:`plugin not found: ${pluginId}`});let memorySlot=normalizedPlugins.slots.memory;typeof memorySlot==`string`&&memorySlot.trim()&&!knownIds.has(memorySlot)&&issues.push({path:`plugins.slots.memory`,message:`plugin not found: ${memorySlot}`});let selectedMemoryPluginId=null,seenPlugins=new Set;for(let record of registry.plugins){let pluginId=record.id;if(seenPlugins.has(pluginId))continue;seenPlugins.add(pluginId);let entry=normalizedPlugins.entries[pluginId],entryHasConfig=!!entry?.config,enableState=resolveEnableState(pluginId,record.origin,normalizedPlugins),enabled=enableState.enabled,reason=enableState.reason;if(enabled){let memoryDecision=resolveMemorySlotDecision({id:pluginId,kind:record.kind,slot:memorySlot,selectedId:selectedMemoryPluginId});memoryDecision.enabled||(enabled=!1,reason=memoryDecision.reason),memoryDecision.selected&&record.kind===`memory`&&(selectedMemoryPluginId=pluginId)}if(enabled||entryHasConfig)if(record.configSchema){let res=validateJsonSchemaValue({schema:record.configSchema,cacheKey:record.schemaCacheKey??record.manifestPath??pluginId,value:entry?.config??{}});if(!res.ok)for(let error of res.errors)issues.push({path:`plugins.entries.${pluginId}.config`,message:`invalid config: ${error}`})}else issues.push({path:`plugins.entries.${pluginId}`,message:`plugin schema missing for ${pluginId}`});!enabled&&entryHasConfig&&warnings.push({path:`plugins.entries.${pluginId}`,message:`plugin disabled (${reason??`disabled`}) but config is present`})}return issues.length>0?{ok:!1,issues,warnings}:{ok:!0,config,warnings}}const VERSION_RE=/^v?(\d+)\.(\d+)\.(\d+)(?:-(\d+))?/;function parseBuilderForceAgentsVersion(raw){if(!raw)return null;let match=raw.trim().match(VERSION_RE);if(!match)return null;let[,major,minor,patch,revision]=match;return{major:Number.parseInt(major,10),minor:Number.parseInt(minor,10),patch:Number.parseInt(patch,10),revision:revision?Number.parseInt(revision,10):0}}function compareBuilderForceAgentsVersions(a,b){let parsedA=parseBuilderForceAgentsVersion(a),parsedB=parseBuilderForceAgentsVersion(b);return!parsedA||!parsedB?null:parsedA.major===parsedB.major?parsedA.minor===parsedB.minor?parsedA.patch===parsedB.patch?parsedA.revision===parsedB.revision?0:parsedA.revision<parsedB.revision?-1:1:parsedA.patch<parsedB.patch?-1:1:parsedA.minor<parsedB.minor?-1:1:parsedA.major<parsedB.major?-1:1}const SHELL_ENV_EXPECTED_KEYS=[`OPENAI_API_KEY`,`ANTHROPIC_API_KEY`,`ANTHROPIC_OAUTH_TOKEN`,`GEMINI_API_KEY`,`ZAI_API_KEY`,`OPENROUTER_API_KEY`,`AI_GATEWAY_API_KEY`,`MINIMAX_API_KEY`,`SYNTHETIC_API_KEY`,`ELEVENLABS_API_KEY`,`TELEGRAM_BOT_TOKEN`,`DISCORD_BOT_TOKEN`,`SLACK_BOT_TOKEN`,`SLACK_APP_TOKEN`,`BUILDERFORCE_AGENTS_GATEWAY_TOKEN`,`BUILDERFORCE_AGENTS_GATEWAY_PASSWORD`],loggedInvalidConfigs=new Set;function hashConfigRaw(raw){return crypto.createHash(`sha256`).update(raw??``).digest(`hex`)}function resolveConfigSnapshotHash(snapshot){if(typeof snapshot.hash==`string`){let trimmed=snapshot.hash.trim();if(trimmed)return trimmed}return typeof snapshot.raw==`string`?hashConfigRaw(snapshot.raw):null}function coerceConfig(value){return!value||typeof value!=`object`||Array.isArray(value)?{}:value}function isPlainObject(value){return typeof value==`object`&&!!value&&!Array.isArray(value)}function hasConfigMeta(value){if(!isPlainObject(value))return!1;let meta=value.meta;return isPlainObject(meta)}function resolveGatewayMode(value){if(!isPlainObject(value))return null;let gateway=value.gateway;if(!isPlainObject(gateway)||typeof gateway.mode!=`string`)return null;let trimmed=gateway.mode.trim();return trimmed.length>0?trimmed:null}function cloneUnknown(value){return structuredClone(value)}function createMergePatch(base,target){if(!isPlainObject(base)||!isPlainObject(target))return cloneUnknown(target);let patch={},keys=new Set([...Object.keys(base),...Object.keys(target)]);for(let key of keys){let hasBase=key in base;if(!(key in target)){patch[key]=null;continue}let targetValue=target[key];if(!hasBase){patch[key]=cloneUnknown(targetValue);continue}let baseValue=base[key];if(isPlainObject(baseValue)&&isPlainObject(targetValue)){let childPatch=createMergePatch(baseValue,targetValue);if(isPlainObject(childPatch)&&Object.keys(childPatch).length===0)continue;patch[key]=childPatch;continue}isDeepStrictEqual(baseValue,targetValue)||(patch[key]=cloneUnknown(targetValue))}return patch}function collectEnvRefPaths(value,path,output){if(typeof value==`string`){containsEnvVarReference(value)&&output.set(path,value);return}if(Array.isArray(value)){value.forEach((item,index)=>{collectEnvRefPaths(item,`${path}[${index}]`,output)});return}if(isPlainObject(value))for(let[key,child]of Object.entries(value))collectEnvRefPaths(child,path?`${path}.${key}`:key,output)}function collectChangedPaths(base,target,path,output){if(Array.isArray(base)&&Array.isArray(target)){let max=Math.max(base.length,target.length);for(let index=0;index<max;index+=1){let childPath=path?`${path}[${index}]`:`[${index}]`;if(index>=base.length||index>=target.length){output.add(childPath);continue}collectChangedPaths(base[index],target[index],childPath,output)}return}if(isPlainObject(base)&&isPlainObject(target)){let keys=new Set([...Object.keys(base),...Object.keys(target)]);for(let key of keys){let childPath=path?`${path}.${key}`:key,hasBase=key in base;if(!(key in target)||!hasBase){output.add(childPath);continue}collectChangedPaths(base[key],target[key],childPath,output)}return}isDeepStrictEqual(base,target)||output.add(path)}function parentPath(value){if(!value)return``;if(value.endsWith(`]`)){let index=value.lastIndexOf(`[`);return index>0?value.slice(0,index):``}let index=value.lastIndexOf(`.`);return index>=0?value.slice(0,index):``}function isPathChanged(path,changedPaths){if(changedPaths.has(path))return!0;let current=parentPath(path);for(;current;){if(changedPaths.has(current))return!0;current=parentPath(current)}return changedPaths.has(``)}function restoreEnvRefsFromMap(value,path,envRefMap,changedPaths){if(typeof value==`string`){if(!isPathChanged(path,changedPaths)){let original=envRefMap.get(path);if(original!==void 0)return original}return value}if(Array.isArray(value)){let changed=!1,next=value.map((item,index)=>{let updated=restoreEnvRefsFromMap(item,`${path}[${index}]`,envRefMap,changedPaths);return updated!==item&&(changed=!0),updated});return changed?next:value}if(isPlainObject(value)){let changed=!1,next={};for(let[key,child]of Object.entries(value)){let updated=restoreEnvRefsFromMap(child,path?`${path}.${key}`:key,envRefMap,changedPaths);updated!==child&&(changed=!0),next[key]=updated}return changed?next:value}return value}function resolveConfigAuditLogPath(env,homedir){return path.join(resolveStateDir(env,homedir),`logs`,`config-audit.jsonl`)}function resolveConfigWriteSuspiciousReasons(params){let reasons=[];return params.existsBefore?(typeof params.previousBytes==`number`&&typeof params.nextBytes==`number`&¶ms.previousBytes>=512&¶ms.nextBytes<Math.floor(params.previousBytes*.5)&&reasons.push(`size-drop:${params.previousBytes}->${params.nextBytes}`),params.hasMetaBefore||reasons.push(`missing-meta-before-write`),params.gatewayModeBefore&&!params.gatewayModeAfter&&reasons.push(`gateway-mode-removed`),reasons):reasons}async function appendConfigWriteAuditRecord(deps,record){try{let auditPath=resolveConfigAuditLogPath(deps.env,deps.homedir);await deps.fs.promises.mkdir(path.dirname(auditPath),{recursive:!0,mode:448}),await deps.fs.promises.appendFile(auditPath,`${JSON.stringify(record)}\n`,{encoding:`utf-8`,mode:384})}catch{}}function warnOnConfigMiskeys(raw,logger){if(!raw||typeof raw!=`object`)return;let gateway=raw.gateway;!gateway||typeof gateway!=`object`||`token`in gateway&&logger.warn(`Config uses "gateway.token". This key is ignored; use "gateway.auth.token" instead.`)}function stampConfigVersion(cfg){let now=new Date().toISOString();return{...cfg,meta:{...cfg.meta,lastTouchedVersion:VERSION,lastTouchedAt:now}}}function warnIfConfigFromFuture(cfg,logger){let touched=cfg.meta?.lastTouchedVersion;if(!touched)return;let cmp=compareBuilderForceAgentsVersions(VERSION,touched);cmp!==null&&cmp<0&&logger.warn(`Config was last written by a newer BuilderForceAgents (${touched}); current version is ${VERSION}.`)}function resolveConfigPathForDeps(deps){return deps.configPath?deps.configPath:resolveConfigPath(deps.env,resolveStateDir(deps.env,deps.homedir))}function normalizeDeps(overrides={}){return{fs:overrides.fs??fs,json5:overrides.json5??json5,env:overrides.env??process.env,homedir:overrides.homedir??(()=>resolveRequiredHomeDir(overrides.env??process.env,os.homedir)),configPath:overrides.configPath??``,logger:overrides.logger??console}}function maybeLoadDotEnvForConfig(env){env===process.env&&loadDotEnv({quiet:!0})}function parseConfigJson5(raw,json5$1=json5){try{return{ok:!0,parsed:json5$1.parse(raw)}}catch(err){return{ok:!1,error:String(err)}}}function resolveConfigIncludesForRead(parsed,configPath,deps){return resolveConfigIncludes(parsed,configPath,{readFile:candidate=>deps.fs.readFileSync(candidate,`utf-8`),parseJson:raw=>deps.json5.parse(raw)})}function resolveConfigForRead(resolvedIncludes,env){return resolvedIncludes&&typeof resolvedIncludes==`object`&&`env`in resolvedIncludes&&applyConfigEnvVars(resolvedIncludes,env),{resolvedConfigRaw:resolveConfigEnvVars(resolvedIncludes,env),envSnapshotForRestore:{...env}}}function createConfigIO(overrides={}){let deps=normalizeDeps(overrides),requestedConfigPath=resolveConfigPathForDeps(deps),configPath=(deps.configPath?[requestedConfigPath]:resolveDefaultConfigCandidates(deps.env,deps.homedir)).find(candidate=>deps.fs.existsSync(candidate))??requestedConfigPath;function loadConfig(){try{if(maybeLoadDotEnvForConfig(deps.env),!deps.fs.existsSync(configPath))return shouldEnableShellEnvFallback(deps.env)&&!shouldDeferShellEnvFallback(deps.env)&&loadShellEnvFallback({enabled:!0,env:deps.env,expectedKeys:SHELL_ENV_EXPECTED_KEYS,logger:deps.logger,timeoutMs:resolveShellEnvFallbackTimeoutMs(deps.env)}),{};let raw=deps.fs.readFileSync(configPath,`utf-8`),{resolvedConfigRaw:resolvedConfig}=resolveConfigForRead(resolveConfigIncludesForRead(deps.json5.parse(raw),configPath,deps),deps.env);if(warnOnConfigMiskeys(resolvedConfig,deps.logger),typeof resolvedConfig!=`object`||!resolvedConfig)return{};let preValidationDuplicates=findDuplicateAgentDirs(resolvedConfig,{env:deps.env,homedir:deps.homedir});if(preValidationDuplicates.length>0)throw new DuplicateAgentDirError(preValidationDuplicates);let validated=validateConfigObjectWithPlugins(resolvedConfig);if(!validated.ok){let details=validated.issues.map(iss=>`- ${iss.path||`<root>`}: ${iss.message}`).join(`
|
|
3
3
|
`);loggedInvalidConfigs.has(configPath)||(loggedInvalidConfigs.add(configPath),deps.logger.error(`Invalid config at ${configPath}:\\n${details}`));let error=Error(`Invalid config`);throw error.code=`INVALID_CONFIG`,error.details=details,error}if(validated.warnings.length>0){let details=validated.warnings.map(iss=>`- ${iss.path||`<root>`}: ${iss.message}`).join(`
|
|
4
4
|
`);deps.logger.warn(`Config warnings:\\n${details}`)}warnIfConfigFromFuture(validated.config,deps.logger);let cfg=applyModelDefaults(applyCompactionDefaults(applyContextPruningDefaults(applyAgentDefaults(applySessionDefaults(applyLoggingDefaults(applyMessageDefaults(validated.config)))))));normalizeConfigPaths(cfg);let duplicates=findDuplicateAgentDirs(cfg,{env:deps.env,homedir:deps.homedir});if(duplicates.length>0)throw new DuplicateAgentDirError(duplicates);return applyConfigEnvVars(cfg,deps.env),(shouldEnableShellEnvFallback(deps.env)||cfg.env?.shellEnv?.enabled===!0)&&!shouldDeferShellEnvFallback(deps.env)&&loadShellEnvFallback({enabled:!0,env:deps.env,expectedKeys:SHELL_ENV_EXPECTED_KEYS,logger:deps.logger,timeoutMs:cfg.env?.shellEnv?.timeoutMs??resolveShellEnvFallbackTimeoutMs(deps.env)}),applyConfigOverrides(cfg)}catch(err){if(err instanceof DuplicateAgentDirError)throw deps.logger.error(err.message),err;return err?.code===`INVALID_CONFIG`||deps.logger.error(`Failed to read config at ${configPath}`,err),{}}}async function readConfigFileSnapshotInternal(){if(maybeLoadDotEnvForConfig(deps.env),!deps.fs.existsSync(configPath)){let hash=hashConfigRaw(null);return{snapshot:{path:configPath,exists:!1,raw:null,parsed:{},resolved:{},valid:!0,config:applyTalkApiKey(applyModelDefaults(applyCompactionDefaults(applyContextPruningDefaults(applyAgentDefaults(applySessionDefaults(applyMessageDefaults({}))))))),hash,issues:[],warnings:[],legacyIssues:[]}}}try{let raw=deps.fs.readFileSync(configPath,`utf-8`),hash=hashConfigRaw(raw),parsedRes=parseConfigJson5(raw,deps.json5);if(!parsedRes.ok)return{snapshot:{path:configPath,exists:!0,raw,parsed:{},resolved:{},valid:!1,config:{},hash,issues:[{path:``,message:`JSON5 parse failed: ${parsedRes.error}`}],warnings:[],legacyIssues:[]}};let resolved;try{resolved=resolveConfigIncludesForRead(parsedRes.parsed,configPath,deps)}catch(err){let message=err instanceof ConfigIncludeError?err.message:`Include resolution failed: ${String(err)}`;return{snapshot:{path:configPath,exists:!0,raw,parsed:parsedRes.parsed,resolved:coerceConfig(parsedRes.parsed),valid:!1,config:coerceConfig(parsedRes.parsed),hash,issues:[{path:``,message}],warnings:[],legacyIssues:[]}}}let readResolution;try{readResolution=resolveConfigForRead(resolved,deps.env)}catch(err){let message=err instanceof MissingEnvVarError?err.message:`Env var substitution failed: ${String(err)}`;return{snapshot:{path:configPath,exists:!0,raw,parsed:parsedRes.parsed,resolved:coerceConfig(resolved),valid:!1,config:coerceConfig(resolved),hash,issues:[{path:``,message}],warnings:[],legacyIssues:[]}}}let resolvedConfigRaw=readResolution.resolvedConfigRaw,legacyIssues=findLegacyConfigIssues(resolvedConfigRaw),validated=validateConfigObjectWithPlugins(resolvedConfigRaw);return validated.ok?(warnIfConfigFromFuture(validated.config,deps.logger),{snapshot:{path:configPath,exists:!0,raw,parsed:parsedRes.parsed,resolved:coerceConfig(resolvedConfigRaw),valid:!0,config:normalizeConfigPaths(applyTalkApiKey(applyModelDefaults(applyAgentDefaults(applySessionDefaults(applyLoggingDefaults(applyMessageDefaults(validated.config))))))),hash,issues:[],warnings:validated.warnings,legacyIssues},envSnapshotForRestore:readResolution.envSnapshotForRestore}):{snapshot:{path:configPath,exists:!0,raw,parsed:parsedRes.parsed,resolved:coerceConfig(resolvedConfigRaw),valid:!1,config:coerceConfig(resolvedConfigRaw),hash,issues:validated.issues,warnings:validated.warnings,legacyIssues}}}catch(err){return{snapshot:{path:configPath,exists:!0,raw:null,parsed:{},resolved:{},valid:!1,config:{},hash:hashConfigRaw(null),issues:[{path:``,message:`read failed: ${String(err)}`}],warnings:[],legacyIssues:[]}}}}async function readConfigFileSnapshot(){return(await readConfigFileSnapshotInternal()).snapshot}async function readConfigFileSnapshotForWrite(){let result=await readConfigFileSnapshotInternal();return{snapshot:result.snapshot,writeOptions:{envSnapshotForRestore:result.envSnapshotForRestore,expectedConfigPath:configPath}}}async function writeConfigFile(cfg,options={}){clearConfigCache();let persistCandidate=cfg,{snapshot}=await readConfigFileSnapshotInternal(),envRefMap=null,changedPaths=null;if(snapshot.valid&&snapshot.exists){let patch=createMergePatch(snapshot.config,cfg);persistCandidate=applyMergePatch(snapshot.resolved,patch);try{let resolvedIncludes=resolveConfigIncludes(snapshot.parsed,configPath,{readFile:candidate=>deps.fs.readFileSync(candidate,`utf-8`),parseJson:raw=>deps.json5.parse(raw)}),collected=new Map;collectEnvRefPaths(resolvedIncludes,``,collected),collected.size>0&&(envRefMap=collected,changedPaths=new Set,collectChangedPaths(snapshot.config,cfg,``,changedPaths))}catch{envRefMap=null}}let validated=validateConfigObjectRawWithPlugins(persistCandidate);if(!validated.ok){let issue=validated.issues[0],pathLabel=issue?.path?issue.path:`<root>`;throw Error(`Config validation failed: ${pathLabel}: ${issue?.message??`invalid`}`)}if(validated.warnings.length>0){let details=validated.warnings.map(warning=>`- ${warning.path}: ${warning.message}`).join(`
|
|
5
5
|
`);deps.logger.warn(`Config warnings:\n${details}`)}let cfgToWrite=validated.config;try{if(deps.fs.existsSync(configPath)){let parsedRes=parseConfigJson5(await deps.fs.promises.readFile(configPath,`utf-8`),deps.json5);if(parsedRes.ok){let envForRestore=options.envSnapshotForRestore??deps.env;cfgToWrite=restoreEnvVarRefs(cfgToWrite,parsedRes.parsed,envForRestore)}}}catch{}let dir=path.dirname(configPath);await deps.fs.promises.mkdir(dir,{recursive:!0,mode:448});let stampedOutputConfig=stampConfigVersion(envRefMap&&changedPaths?restoreEnvRefsFromMap(cfgToWrite,``,envRefMap,changedPaths):cfgToWrite),json=JSON.stringify(stampedOutputConfig,null,2).trimEnd().concat(`
|