{"repo": "525300887039/bareagent", "files": {"src/bareagent/config.toml": {"3430902466441c3b90bc8403f9ebefbb2b30f2d3": {"t": 1786068459.0555289, "n": 14438, "h": "1f057fffc4a206b9", "c": "# Tip: run `bareagent init` for an interactive provider setup wizard that writes\n# config.local.toml for you (DeepSeek / OpenAI / Anthropic / Qwen / GLM / Gemini / custom).\n#\n# 配置热重载(ROADMAP 4.3):改完本文件 / config.local.toml 后,REPL 内 `/reload`\n# 可热重载 `[ui] theme` 与 `[permission] mode/allow/deny`(改完即生效,无需重启);\n# 其余配置(provider / mcp / lsp / hooks 等 boot 时固化的连接/客户端)仅报告\n# “需重启”,重启 BareAgent 后才生效。改坏 TOML 时 `/reload` 报错并保持当前配置。\n[provider]\nname = \"openai\"\nmodel = \"gpt-4.1\"\napi_key_env = \"OPENAI_API_KEY\"\n# Gemini 走 OpenAI 兼容端点(preset 已内置 base_url,无需手填):\n# name = \"gemini\"\n# model = \"gemini-2.5-pro\" # 或 gemini-2.5-flash\n# api_key_env = \"GEMINI_API_KEY\"\n# 自动前缀缓存,命中走标准 cached_tokens 用量;缓存模式见 /cost 的 \"Cache mode\" 行。\n\n[permission]\nmode = \"default\"\n\n[ui]\nstream = true\ntheme = \"catppuccin-mocha\"\n\n[subagent]\nmax_depth = 3\ndefault_type = \"general-purpose\"\n# 可续跑前台子代理上下文的软上限(session 级、内存态)。subagent 跑完会注册一份\n# 可续跑上下文,LLM 用返回的 agent id 经 subagent_send 续跑;超过此数按最旧淘汰。\n# 仅前台、isolation=\"none\" 的子代理可续跑(后台 / worktree 不注册)。restart-required。\nmax_resumable = 20\n\n[thinking]\nmode = \"adaptive\"\nbudget_tokens = 10000\n\n[debug]\nenabled = false\nlog_dir = \".logs\"\nviewer_port = 8321\npretty = true\n\n[tracing]\n# langfuse = false # 或设 LANGFUSE_PUBLIC_KEY 环境变量自动启用\n# opentelemetry = false # 或设 OTEL_EXPORTER_OTLP_ENDPOINT 自动启用\n# content_enabled = true # 是否上报消息内容(PII 敏感场景可关闭)\n\n# --- MCP (Model Context Protocol) ----------------------------------------\n# 在 [[mcp.servers]] 中声明外部 MCP server,BareAgent 启动时会并发拉起并把远端工具\n# 按 `mcp____` 命名注入到工具列表;声明 resources capability 的 server\n# 额外得到 `mcp____resource_list` / `mcp____resource_read`;prompts 可\n# 通过 REPL slash 命令 `/mcp::` 触发。REPL 命令:`/mcp status|list|reload `。\n[mcp]\n# 单个 server initialize 握手超时(秒);超时后该 server 标 UNHEALTHY 并跳过,\n# 不阻塞 REPL boot。\n# start_timeout = 10\n# 单次 tool result 文本字节上限(UTF-8),超出会被截断并追加\n# `[truncated, original size: N bytes]` 后缀。256 KiB 对应主流 LLM context 友好范围。\n# max_result_text_bytes = 262144\n# 单个 image / embedded_resource binary 字节上限(base64 解码后估算),超出会被\n# 替换为 `[Resource omitted: too large (N bytes)]` 占位文本。\n# max_result_binary_bytes = 5242880\n\n# 示例 1:stdio 子进程模式(mcp-server-fetch via uvx)。\n# [[mcp.servers]]\n# name = \"fetch\"\n# transport = \"stdio\"\n# command = \"uvx\"\n# args = [\"mcp-server-fetch\"]\n# # env = { FETCH_USER_AGENT = \"BareAgent/0.1\" }\n# # cwd = \"/path/to/workspace\"\n\n# 示例 2:HTTP Streamable (MCP 2025-03-26) 远端服务。\n# [[mcp.servers]]\n# name = \"team-knowledge\"\n# transport = \"http_streamable\"\n# url = \"https://mcp.example.com/mcp\"\n# headers = { Authorization = \"Bearer ${KNOWLEDGE_TOKEN}\" }\n# # transport 也可设为 \"http_legacy\"(MCP 2024-11-05 双端点)以兼容旧 server。\n\n# --- LSP (Language Server Protocol) --------------------------------------\n# 通过 multilspy 接入成熟 Language Server。MVP 暴露 4 个 Tier-1 工具:\n# `lsp_outline` / `lsp_definition` / `lsp_references` / `lsp_diagnostics`。需安装可选 extra:\n# uv pip install -e \".[lsp]\"\n# multilspy 0.0.15 内置语言适配:Python → jedi-language-server(非 pyright;jedi 走\n# 符号导航强、类型诊断弱),TypeScript → typescript-language-server,Rust → rust-analyzer。\n# REPL 命令:`/lsp status|list|reload `。\n[lsp]\n# Hybrid auto-diagnostics-on-edit:edit_file / write_file 成功后自动调 LSP\n# 拿最新诊断,与编辑前的快照按 (file, line, col, severity, message) 五元组\n# 做 diff,将**新增**诊断追加到 tool result 末尾,格式:\n# Newly introduced diagnostics in :\n# - [pyright Error] Line N:C — \n# 默认 OFF:保持 edit/write 体验与原版一致;启用前请确认 LSP server 已正常\n# 起来(pyright 第一次全项目分析 5-15s)。\n# auto_diagnostics_on_edit = false\n# 单个 server handshake + initial analysis 超时(秒)。超时标 UNHEALTHY 并跳过,\n# 不阻塞 REPL boot。pyright 通常 5-15s,rust-analyzer 项目较大时可能更久。\n# start_timeout = 15.0\n\n# 示例 1:Python(multilspy 默认走 jedi-language-server,不是 pyright)。\n# [[lsp.servers]]\n# language = \"python\" # multilspy code_language(→ JediServer)\n# extensions = [\".py\", \".pyi\"] # 文件扩展名 → 路由到此 server\n# # initialization_options 透传给 LSP server(透传 LSP-specific 配置):\n# # initialization_options = { python = { pythonPath = \".venv/bin/python\" } }\n\n# 示例 2:TypeScript / JavaScript(typescript-language-server)。\n# [[lsp.servers]]\n# language = \"typescript\"\n# extensions = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mts\", \".cts\", \".mjs\", \".cjs\"]\n\n# 示例 3:Rust(rust-analyzer)。\n# [[lsp.servers]]\n# language = \"rust\"\n# extensions = [\".rs\"]\n\n# --- Persistent Memory ---------------------------------------------------\n# 文件式跨会话记忆:一条记忆 = 一个带 frontmatter 的 .md 文件,MEMORY.md 作索引。\n# 智能体通过单个 `memory` 工具(命令 view/create/str_replace/insert/delete/rename,\n# 契约对齐 Anthropic memory tool,但注册为普通 client tool,全 provider 可用)读写受限的\n# 记忆目录;会话开局把 MEMORY.md 索引 + MEMORY PROTOCOL 注入 system prompt。\n# REPL 命令:`/remember <文本>`、`/forget <文本>`。子代理(explore/plan/code-review)只读。\n[memory]\n# 关闭后不注入记忆、不暴露可用的 memory 工具(调用返回 disabled 错误)。\nenabled = true\n# 记忆根目录。留空 = 每个项目独立目录 ~/.bareagent/projects//memory/\n# (不污染项目 git)。相对路径相对 workspace,绝对路径原样使用。\n# dir = \"\"\n# 会话开局注入 system prompt 的 MEMORY.md 索引最大行数。\n# max_index_lines = 200\n# 每轮按用户消息相关性召回并注入的记忆条数(0 = 关闭召回,仅保留开局索引注入)。\n# recall_k = 5\n# 语义/向量召回(task 06-08-semantic-memory-recall):默认 false = 词法召回(行为不变)。\n# 开启后按 embedding 余弦相似度召回(换了措辞也能命中),embedding 不可用时自动回退词法。\n# 走 env 覆盖 BAREAGENT_MEMORY_SEMANTIC_RECALL,restart-required。\n# semantic_recall = false\n# embedding backend:openai(复用 openai client,可指向独立 embeddings 端点)| local(fastembed,需装 [embeddings] extra)。\n# embedding_backend = \"openai\"\n# 模型,留空 = backend 默认(openai: text-embedding-3-small;local: BAAI/bge-small-en-v1.5)。\n# embedding_model = \"\"\n# openai backend 的端点/密钥,留空则复用会话 provider 的 base_url / api_key。\n# embedding_base_url = \"\"\n# embedding_api_key = \"\"\n\n# --- Hooks (工具调用前后用户自定义钩子) ----------------------------------\n# 在 [[hooks]] 中声明:在工具调用前后触发自定义 shell 命令。仅在主循环触发,\n# 子代理不触发(隔离)。权限闸(PermissionGuard)仍是安全边界,hooks 是用户自配的\n# 便利层(trust-the-config)。每个 hook 收到一行 JSON stdin(字段对齐 Claude Code):\n# PreToolUse: {\"event\",\"tool_name\",\"tool_input\",\"session_id\",\"cwd\"}\n# PostToolUse: 追加 {\"tool_output\",\"is_error\"}\n# 控制协议(exit code,对齐 Claude Code):\n# - PreToolUse exit 2 = 拦截:跳过 handler,stderr 作拒绝理由回灌 LLM(error result)。\n# - exit 0 = 放行;其他非 0 = 非阻塞警告 + 放行。\n# - PostToolUse 退出码不影响工具结果(仅非 0 时警告)。\n# 失败模式 = fail-open:hook spawn 失败 / 超时 → 警告 + 放行,不挂主循环。\n# 字段:event(必填,PreToolUse|PostToolUse)、command(必填 shell 命令)、\n# tool(可选,精确工具名;省略 = 匹配所有工具)、timeout(可选,秒,默认 30)。\n# 默认全部注释掉(不启用任何 hook)。\n#\n# 注意:BareAgent 始终用 UTF-8 把 JSON 写入 hook 的 stdin。务必用\n# json.load(sys.stdin.buffer)(二进制流 + 隐式 UTF-8 解码)读取,不要用\n# json.load(sys.stdin)——后者按 OS locale 解码(中文 Windows 控制台是 GBK),\n# 会把非 ASCII 的 tool_input(如中文文件路径)解成乱码。\n\n# 示例 1:PreToolUse —— 挡危险,bash 命令含 \"rm -rf\" 时 exit 2 拦截。\n# [[hooks]]\n# event = \"PreToolUse\"\n# tool = \"bash\"\n# command = \"python -c \\\"import sys,json; cmd=json.load(sys.stdin.buffer)['tool_input'].get('command',''); (sys.stderr.write('blocked: rm -rf'), sys.exit(2)) if 'rm -rf' in cmd else sys.exit(0)\\\"\"\n\n# 示例 2:PostToolUse —— write_file 之后自动 ruff format 写入的文件。\n# [[hooks]]\n# event = \"PostToolUse\"\n# tool = \"write_file\"\n# command = \"python -c \\\"import sys,json,subprocess; d=json.load(sys.stdin.buffer); p=d['tool_input'].get('file_path'); p and subprocess.run(['ruff','format',p])\\\"\"\n# timeout = 60\n\n[cost]\n# Token 用量与成本估算(/cost 命令展示当前会话累计)。\n# 默认内置 Claude Opus/Sonnet/Haiku 4.x 的参考价;其余 model 只显 token 不显 $。\n# [cost.prices] 可覆盖内置价或为任意 model 新增价,单位均为「每百万 token 美元」。\n# 价格可能变动,以 [cost.prices] 覆盖为准。\n# [cost.prices.\"claude-opus-4-8\"]\n# input = 15.0\n# output = 75.0\n# [cost.prices.\"deepseek-chat\"]\n# input = 0.27\n# output = 1.10\n\n# --- Retry (LLM 调用重试策略) --------------------------------------------\n# 瞬时性失败(rate limit / 网络超时 / 5xx / overloaded)自动指数退避重试;\n# 不可重试错误(认证失败 / 400 bad request / 模型不存在 / 未知异常)立即上抛,\n# 不掩盖真正的配置错误。app 层(src/core/retry.py)独占重试,已禁用 SDK 自带重试\n# (anthropic / openai client 均 max_retries=0),避免 2×N 复合放大。\n# 可重试状态码:408 / 409 / 429 / 500 / 502 / 503 / 504 / 529 + 连接/超时类异常。\n# 不可重试状态码:400 / 401 / 403 / 404 / 413 / 422 + 未知异常(保守 fail-fast)。\n# 退避:delay = min(max_delay_sec, base_delay_sec × multiplier^(attempt-1)),\n# jitter=true 时再叠 full jitter(uniform(0, delay))。\n# 环境变量覆盖:BAREAGENT_RETRY_ENABLED、BAREAGENT_RETRY_MAX_ATTEMPTS。\n[retry]\n# 关闭后完全无重试(含 SDK,因为 client 始终 max_retries=0)。\nenabled = true\n# 总尝试次数(含首次),<=1 等效关闭重试。\nmax_attempts = 3\n# 首次重试前的基础等待秒数。\nbase_delay_sec = 1.0\n# 单次退避上限秒数(封顶)。\nmax_delay_sec = 30.0\n# 指数退避倍率。\nmultiplier = 2.0\n# 是否叠加 full jitter(uniform(0, delay))打散并发重试。\njitter = true\n\n# --- Prompt caching (Anthropic 显式 cache_control 断点) --------------------\n# 给静态前缀(tools + system)和增长的对话历史前缀打 cache_control 断点,让多轮\n# agent loop 反复重发的大块上下文走缓存读(约 0.1× 输入价),显著降本提速。\n# 命名 provider 中立,但当前仅 Anthropic provider 生效(需显式打断点);\n# OpenAI/DeepSeek 自动缓存、无请求侧旋钮,此开关对它们为 no-op(其命中量仍计入 /cost)。\n# 关闭(enabled=false)时 Anthropic 请求体与未接缓存前字节级一致(向后兼容)。\n# 注意:Opus 4.5+ 最小可缓存前缀为 4096 token,低于阈值静默 no-op(不报错)。\n# 缓存读写 token 计入 /cost:写 1.25×(5m)、读 0.1×(claude)。\n# 环境变量覆盖:BAREAGENT_CACHE_ENABLED。\n# 改 [cache] 需重启生效(boot 时固化进 provider,不在 /reload 热重载集内)。\n[cache]\n# 是否启用 prompt caching(默认开启)。\nenabled = true\n# 缓存 TTL:\"5m\"(默认,交互式 agent 甜区)或 \"1h\"(写 2×,适合长时间挂起)。\nttl = \"5m\"\n\n[skills]\n# 经验式技能生成:复杂的多轮任务收尾后,agent 自动把工作流起草成可复用 skill\n# 草稿(落 pending 区),用户用 /skill keep 提升到可加载。env 覆盖:\n# BAREAGENT_SKILLS_AUTO_GENERATE。关闭即全链路短路(无额外反思 LLM 调用)。\nauto_generate = true\n# 触发为双条件 AND(自会话开始/上次起草后累计):工具调用数 + 用户回复数同时达标。\nmin_tool_calls = 5\nmin_user_replies = 3\n# pending 草稿数量软上限,超出按最旧裁剪(<=0 关闭裁剪)。\nmax_pending = 10\n# 生成 skill 根目录覆盖(留空 = ~/.bareagent/projects//skills/,\n# 与仓库 checked-in 的 skills/ 正典分离,项目隔离,不进版本控制)。\ndir = \"\"\n\n[goal]\n# 完成条件循环:/goal [--max-turns N] 让 agent 自驱动一轮接一轮地工作,\n# 每轮由一个独立评估器(只看对话 transcript)判定条件是否满足,未达标把理由回灌继续,\n# 达标或触达 max_turns 即停。安全语义:/goal 尊重当前权限模式、绝不自动升级——\n# DEFAULT 下写操作仍每轮弹确认(命令会提示用 /auto 切到无人值守);循环命令同步阻塞\n# REPL,Esc 可中断。\n# 轮数上限(防止评估器一直判不达标导致无限循环 + 失控成本)。env 覆盖:\n# BAREAGENT_GOAL_MAX_TURNS;行内 --max-turns N 覆盖单次调用。\nmax_turns = 25\n# 评估器模型(可选)。留空 = 复用会话 provider/模型(开箱即用、不依赖某家 provider);\n# 填一个更便宜的 model id(如 claude-haiku-4-5)则经 factory 单独构造评估 provider,\n# 省下每轮用主模型判定\"是/否\"的开销。boot 固化,改动 restart-required。\nevaluator_model = \"\"\n\n[workflow]\n# 确定性多智能体编排(task 06-06-workflow-deterministic-orchestration,对标 Claude Code\n# Workflow):LLM 经一个「主循环专属」的 workflow 工具临场产出一张静态 DAG(nodes +\n# depends_on),相互独立的节点并发跑、依赖就绪才跑,上游产物经 {{node_id}} 占位喂给下游,\n# 收尾把每个节点 done/failed/skipped + 产物结构化聚合回灌 LLM。节点执行复用 run_subagent。\n# 安全语义:节点子代理 fail-closed 无人值守运行(worker 线程不弹确认,与后台子代理 / /loop\n# 一脉相承)——DEFAULT 下写操作被拒、AUTO 下自动放行、PLAN 下只读;workflow 工具不进全局\n# 工具集、子代理拿不到(无嵌套);同步阻塞调用、Esc 可中断。失败语义:单节点失败 = 其传递\n# 下游 skip、独立分支继续。\n# 扩展(task 06-08-workflow-background-panel-resume-budget):workflow 工具新增三个可选字段——\n# run_in_background(后台 daemon 跑、立即返回 run id、完成后完整 summary 在下个 turn 回灌 LLM)、\n# resume_from(给上次 run id,复用未变的已完成节点、只重跑变更/失败/新增节点及其下游)、\n# token_budget(软上限,层间检查,超限后剩余节点 skip)。REPL 配套面板 /workflows(list | \n# | clear)。run 记录内存级、会话作用域(/new·/resume·/import clear、/compact 保留)。\n# MVP 不做循环/条件/动态 fan-out、不做落盘跨重启 resume、不做取消运行中 workflow、不做\n# worktree per-node 隔离(均为后续扩展位)。\n# 总开关:false 时 workflow 工具压根不注入,整特性短路。env 覆盖:BAREAGENT_WORKFLOW_ENABLED。\nenabled = true\n# 并发上限:同时运行的节点数(每个节点是一个完整子代理,保守取值)。\nmax_concurrency = 8\n# 单张 DAG 的节点数上限,防止 LLM 产出超大图打爆线程池。\nmax_nodes = 20\n# 缺省 token 预算:workflow 调用未带 token_budget 时的兜底上限,0 = 不限;per-call 字段优先。\n# env 覆盖:BAREAGENT_WORKFLOW_DEFAULT_TOKEN_BUDGET。\ndefault_token_budget = 0\n# 保留的 run 记录数(面板历史 + resume 来源)上限,FIFO 超出裁剪最旧(优先裁已完成的)。\n# env 覆盖:BAREAGENT_WORKFLOW_MAX_RUNS。\nmax_runs = 50\n\n[team]\n# 多智能体队友协调(task 06-06-team-subsystem-completion):把 team 子系统补到\n# 「LLM 真正能用的协作闭环」。team_send 现在阻塞等队友回复并把回复作为工具结果回灌 LLM\n# (队友未运行 / 目标为 main 则立即返回,不干等超时);迟到 / 未经请求的回复经邮箱 drain\n# 回灌到下一个 user turn。队友请求处理异常被隔离(回 error response、守护线程存活);\n# team_shutdown 可单独停一个队友;team_list 经后台线程存活探测反映真实运行状态。\n# 安全语义:队友以 fail-closed 权限无人值守运行(与后台子代理 / /loop 一脉相承)。\n# 两个字段均为 config-only 正数,boot 固化 -> 改动需重启(restart-required)。\n# 队友守护循环空闲时每隔 poll_interval 秒醒来扫一次待办任务(收到消息会立即唤醒)。\npoll_interval = 1.0\n# 阻塞式 team_send 等待队友回复的超时秒数;超时返回提示,迟到回复仍会在后续 turn 浮现。\nresponse_timeout = 60.0\n# 队友有状态记忆(task 06-08-team-stateful-memory):开启后队友跨 request 保留对话上下文\n# (连续 team_send 续在同一条会话上,注入 per-teammate Compactor 按 token 阈值压缩防无界增长);\n# 自认领的 task 仍逐个无状态执行。关掉则回退到逐请求无状态的旧行为。\n# 走 env 覆盖 BAREAGENT_TEAM_MEMORY_ENABLED,boot 固化 -> restart-required。\nmemory_enabled = true\n\n[code_search]\n# 语义代码检索(task 06-19-repo-map-lsp-documentsymbol-embedding):code_search 工具按\n# 自然语言描述(一个概念/行为/特性)用 embedding 相似度召回最相关的代码块,省 token、\n# 比盲读整文件/反复 grep 更准,与 grep 互补(grep 找精确符号/字符串、code_search 找想法)。\n# 分块 = 固定行窗(语言无关、零解析器依赖);索引 = 首次调用懒构建 + 内容 hash 增量 embed +\n# 余弦 top-K;缓存独立落项目目录(~/.bareagent/projects//code-index.json)。\n# embedder 复用 [memory] 的 embedding 配置(backend/model/base_url/key),与 semantic_recall\n# 开关解耦——只要能建出 embedder 就可用。enabled 仅决定是否「可用」;boot 检测不到可用 embedder\n# 时工具仍不暴露(仿 MCP/LSP「配好才出现」),LLM 不会看到死工具。读操作,不弹权限确认。\n# 走 env 覆盖 BAREAGENT_CODE_SEARCH_ENABLED,boot 固化 -> restart-required。\nenabled = true\n# 默认返回的代码块数(per-call k 覆盖)。\nk = 8\n# 固定行窗分块:每块 chunk_lines 行、相邻块重叠 chunk_overlap 行。\nchunk_lines = 50\nchunk_overlap = 10\n# 超过该字节数的文件跳过(同 grep 策略)。\nmax_file_bytes = 1048576\n\n[repo_map]\n# Repo Map(task 06-20-repo-map):repo_map 工具用 tree-sitter 抽取整库的「符号骨架」\n# (类/函数/方法的真实签名行,剥实现体),按 PageRank(文件引用图 + 偏向最近读/改文件)排序、\n# 贴 token 预算,给 LLM 一张结构全景。与 code_search(按想法找相关代码块)、grep(精确匹配)互补:\n# repo_map 给「结构」。每个符号带行号,便于续跳 read_file/lsp_outline。\n# 来源 = tree-sitter(需可选 extra:uv pip install -e \".[repo-map]\",含 tree-sitter +\n# python/javascript/rust/go/java 语法包);查询是自带的最小 .scm(drop-in:加文件 + 扩展名映射\n# = 加语言)。缓存独立落项目目录(~/.bareagent/projects//repo-map-cache.json)。\n# enabled 仅决定是否「可用」;boot 检测不到 tree-sitter 时工具仍不暴露(仿 MCP/LSP「配好才出现」),\n# LLM 不会看到死工具。只读操作,不弹权限确认。\n# 走 env 覆盖 BAREAGENT_REPO_MAP_ENABLED,boot 固化 -> restart-required。\nenabled = true\n# 渲染地图的默认 token 预算(per-call max_tokens 覆盖)。\nmax_tokens = 1024\n# 超过该字节数的文件跳过(同 grep / code_search 策略)。\nmax_file_bytes = 1048576\n# 自动作为 PageRank focus 注入的「最近读/改文件」条数。\nrecent_files = 5\n\n[capabilities]\n# 模型输入模态能力(task 07-14-multimodal)。vision 是「模型」属性(同一 OpenAI\n# provider 既服务 gpt-4o 也服务 deepseek-chat),故不套 provider ClassVar,用\n# provider/capabilities.py 的静态前缀表 + 此处覆盖。\n# image_in 三态:留空/注释掉 = auto(查已知 vision 前缀表,未知模型默认拒绝,\n# read_file 读图返友好 Error 而非撞 API);true = 强制放行;false = 强制拒绝。\n# 走 env 覆盖 BAREAGENT_MODEL_IMAGE_IN(1/true/on 或 0/false/off),boot 固化 -> restart-required。\n# image_in = true\n# pdf_in 三态:留空 = auto(原生 base64 PDF document block 是 Anthropic 特性,仅 Anthropic\n# provider + Claude 家族默认放行,其余回退 pypdf 文本);true/false 仅覆盖模型判断,不能\n# 绕过 provider 传输格式门控。\n# 走 env 覆盖 BAREAGENT_MODEL_PDF_IN。显式传 pages 或超 20MB 时恒走 pypdf 文本路径。\n# pdf_in = true\n"}}}}