@roll-agent/core 0.19.0 → 0.20.0

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.
Files changed (46) hide show
  1. package/dist/cli/chat/ink/app.d.ts +1 -1
  2. package/dist/cli/chat/ink/app.js +1 -1
  3. package/dist/cli/chat/ink/commands.d.ts +4 -12
  4. package/dist/cli/chat/ink/commands.js +1 -1
  5. package/dist/cli/chat/ink/history-from-messages.js +1 -1
  6. package/dist/cli/chat/ink/history-item.js +1 -1
  7. package/dist/cli/chat/ink/input-history.d.ts +2 -0
  8. package/dist/cli/chat/ink/input-history.js +1 -0
  9. package/dist/cli/chat/ink/line-buffer.d.ts +2 -0
  10. package/dist/cli/chat/ink/line-buffer.js +1 -1
  11. package/dist/cli/chat/ink/live-region.d.ts +2 -0
  12. package/dist/cli/chat/ink/live-region.js +1 -1
  13. package/dist/cli/chat/ink/reasoning-block.d.ts +4 -0
  14. package/dist/cli/chat/ink/reasoning-block.js +1 -0
  15. package/dist/cli/chat/ink/spinner.d.ts +3 -1
  16. package/dist/cli/chat/ink/spinner.js +1 -1
  17. package/dist/cli/chat/ink/state.d.ts +26 -3
  18. package/dist/cli/chat/ink/state.js +1 -1
  19. package/dist/cli/chat/ink/text-prompt.d.ts +3 -1
  20. package/dist/cli/chat/ink/text-prompt.js +1 -1
  21. package/dist/cli/chat/ink/turn-activity.d.ts +19 -0
  22. package/dist/cli/chat/ink/turn-activity.js +1 -0
  23. package/dist/cli/chat/ink/turn-status-line.d.ts +14 -0
  24. package/dist/cli/chat/ink/turn-status-line.js +1 -0
  25. package/dist/cli/chat/ink/use-session.js +1 -1
  26. package/dist/cli/commands/chat.d.ts +28 -0
  27. package/dist/cli/commands/chat.js +1 -1
  28. package/dist/cli/commands/config.js +1 -1
  29. package/dist/cli/utils/chat-renderer.js +1 -1
  30. package/dist/cli/utils/current-cli-shim.d.ts +14 -0
  31. package/dist/cli/utils/current-cli-shim.js +1 -0
  32. package/dist/cli/utils/debug-format.d.ts +4 -0
  33. package/dist/cli/utils/debug-format.js +1 -0
  34. package/dist/config/defaults.d.ts +2 -1
  35. package/dist/config/defaults.js +1 -1
  36. package/dist/config/guidance.d.ts +23 -1
  37. package/dist/config/guidance.js +1 -1
  38. package/dist/config/schema.d.ts +52 -7
  39. package/dist/config/schema.js +1 -1
  40. package/dist/llm/providers.d.ts +6 -4
  41. package/dist/llm/providers.js +1 -1
  42. package/dist/registry/install.js +1 -1
  43. package/dist/skills/invocation.d.ts +27 -0
  44. package/dist/skills/invocation.js +1 -0
  45. package/dist/types/chat.d.ts +3 -0
  46. package/package.json +3 -2
@@ -1 +1 @@
1
- import t from"chalk";import{isCancel as s,select as e}from"@clack/prompts";import{createSpinner as n,log as o}from"./output.js";import{GLYPHS as a}from"./glyphs.js";import{computeUsageParts as i,formatUsageLine as r}from"./token-format.js";import{formatToolInput as p,formatApprovalDetails as l}from"./tool-format.js";export const clackConfirm=async t=>{const n=await e({message:t,options:[{value:"yes",label:"Yes"},{value:"no",label:"No"}],initialValue:"no"});return!s(n)&&"yes"===n};function c(t){const s=[`chat.${t.stage}`,t.message];return void 0!==t.elapsedMs&&s.push(`${String(t.elapsedMs)}ms`),void 0!==t.data&&s.push(JSON.stringify(t.data)),s.join(" · ")}export class ChatRenderer{confirm;contextWindow;spinners=new Map;toolLabels=new Map;compactionSpinner;messageSpinner;streaming=!1;constructor(t,s){this.confirm=t,this.contextWindow=s}async handle(s,e){switch(s.type){case"debug":o.debug(c(s));break;case"message-start":this.startMessageSpinner();break;case"text-delta":this.stopMessageSpinner(),process.stdout.write(s.delta),this.streaming=!0;break;case"tool-call":{this.stopMessageSpinner(),this.flushLine();const e=`${s.agentName}.${s.toolName}`,o=n(`${t.cyan(e)} ${t.gray(p(s.input))}`);o.start(),this.spinners.set(s.toolCallId,o),this.toolLabels.set(s.toolCallId,e);break}case"tool-output-delta":{const e=this.spinners.get(s.toolCallId),n=this.toolLabels.get(s.toolCallId);if(e&&n){const o=s.delta.split("\n").map(t=>t.trim()).filter(t=>t.length>0).at(-1);if(o){const s=o.length>80?`${o.slice(0,79)}…`:o;e.text=`${t.cyan(n)} ${t.gray(s)}`}}break}case"tool-result":{const t=this.spinners.get(s.toolCallId);t&&(s.isError?t.fail():t.succeed(),this.spinners.delete(s.toolCallId)),this.toolLabels.delete(s.toolCallId);break}case"confirmation-required":{this.stopMessageSpinner(),this.flushLine();const t=s.reason?`(${s.reason})`:"",n=l(s.input),o=`执行 ${s.agentName}.${s.toolName}${t}?`;await this.confirm(n?`${o}\n${n}`:o)?e.approve(s.approvalId):e.reject(s.approvalId,"用户取消");break}case"compaction-start":this.stopMessageSpinner(),this.flushLine(),this.compactionSpinner=n(t.gray("压缩上下文中…")),this.compactionSpinner.start();break;case"context-compacted":{this.stopCompactionSpinner(),this.flushLine();const e="auto"===s.reason?"自动压缩":"手动压缩",n=s.truncatedTools?`,精简 ${String(s.truncatedTools)} 个工具结果`:"",o=0!==s.removed||s.truncatedTools?`${a.compact} ${e}(${s.strategy}):移除 ${String(s.removed)} 条 → 保留 ${String(s.kept)} 条${n}`:`${a.compact} ${e}:无需压缩`;process.stderr.write(`${t.gray(o)}\n`);break}case"turn-cancelled":this.stopMessageSpinner(),this.stopCompactionSpinner(),this.flushLine();for(const s of this.spinners.values())s.warn(`${s.text} ${t.yellow("已中断")}`);this.spinners.clear(),this.toolLabels.clear(),o.warn(s.message);break;case"error":this.stopMessageSpinner(),this.stopCompactionSpinner(),this.flushLine(),o.error(s.message);break;case"message-finish":{this.stopMessageSpinner(),this.flushLine(),0===s.text.length&&(s.totalUsage?.outputTokens??0)>0&&o.warn("模型本轮只返回了 thinking/reasoning,没有生成可见回复"),s.stoppedAtStepLimit&&o.warn("已达单轮最大工具步数,任务可能未完成 — 继续追问即可接着做,或调高 runtime.max-steps");const e=r(i(s.totalUsage,s.sessionUsage,this.contextWindow,s.contextInputTokens));e&&process.stderr.write(`${t.gray(e)}\n`);break}}}stopCompactionSpinner(){this.compactionSpinner&&(this.compactionSpinner.stop(),this.compactionSpinner=void 0)}startMessageSpinner(){this.stopMessageSpinner(),this.messageSpinner=n(t.gray("思考中…")),this.messageSpinner.start()}stopMessageSpinner(){this.messageSpinner&&(this.messageSpinner.stop(),this.messageSpinner=void 0)}flushLine(){this.streaming&&(process.stdout.write("\n"),this.streaming=!1)}}
1
+ import e from"chalk";import{isCancel as t,select as s}from"@clack/prompts";import{createSpinner as o,log as n}from"./output.js";import{GLYPHS as a}from"./glyphs.js";import{computeUsageParts as i,formatUsageLine as r}from"./token-format.js";import{formatToolInput as p,formatApprovalDetails as l}from"./tool-format.js";import{formatDebugEvent as c}from"./debug-format.js";export const clackConfirm=async e=>{const o=await s({message:e,options:[{value:"yes",label:"Yes"},{value:"no",label:"No"}],initialValue:"no"});return!t(o)&&"yes"===o};export class ChatRenderer{confirm;contextWindow;spinners=new Map;toolLabels=new Map;compactionSpinner;messageSpinner;streaming=!1;constructor(e,t){this.confirm=e,this.contextWindow=t}async handle(t,s){switch(t.type){case"debug":n.debug(c(t));break;case"message-start":this.startMessageSpinner();break;case"text-delta":this.stopMessageSpinner(),process.stdout.write(t.delta),this.streaming=!0;break;case"tool-call":{this.stopMessageSpinner(),this.flushLine();const s=`${t.agentName}.${t.toolName}`,n=o(`${e.cyan(s)} ${e.gray(p(t.input))}`);n.start(),this.spinners.set(t.toolCallId,n),this.toolLabels.set(t.toolCallId,s);break}case"tool-output-delta":{const s=this.spinners.get(t.toolCallId),o=this.toolLabels.get(t.toolCallId);if(s&&o){const n=t.delta.split("\n").map(e=>e.trim()).filter(e=>e.length>0).at(-1);if(n){const t=n.length>80?`${n.slice(0,79)}…`:n;s.text=`${e.cyan(o)} ${e.gray(t)}`}}break}case"tool-result":{const e=this.spinners.get(t.toolCallId);e&&(t.isError?e.fail():e.succeed(),this.spinners.delete(t.toolCallId)),this.toolLabels.delete(t.toolCallId);break}case"confirmation-required":{this.stopMessageSpinner(),this.flushLine();const e=t.reason?`(${t.reason})`:"",o=l(t.input),n=`执行 ${t.agentName}.${t.toolName}${e}?`;await this.confirm(o?`${n}\n${o}`:n)?s.approve(t.approvalId):s.reject(t.approvalId,"用户取消");break}case"compaction-start":this.stopMessageSpinner(),this.flushLine(),this.compactionSpinner=o(e.gray("压缩上下文中…")),this.compactionSpinner.start();break;case"context-compacted":{this.stopCompactionSpinner(),this.flushLine();const s="auto"===t.reason?"自动压缩":"手动压缩",o=t.truncatedTools?`,精简 ${String(t.truncatedTools)} 个工具结果`:"",n=0!==t.removed||t.truncatedTools?`${a.compact} ${s}(${t.strategy}):移除 ${String(t.removed)} 条 → 保留 ${String(t.kept)} 条${o}`:`${a.compact} ${s}:无需压缩`;process.stderr.write(`${e.gray(n)}\n`);break}case"turn-cancelled":this.stopMessageSpinner(),this.stopCompactionSpinner(),this.flushLine();for(const t of this.spinners.values())t.warn(`${t.text} ${e.yellow("已中断")}`);this.spinners.clear(),this.toolLabels.clear(),"user"===t.reason?process.stderr.write(`${e.gray(`■ ${t.message}`)}\n`):"timeout"===t.reason?n.warn(t.message):n.error(t.message);break;case"error":this.stopMessageSpinner(),this.stopCompactionSpinner(),this.flushLine(),n.error(t.message);break;case"message-finish":{this.stopMessageSpinner(),this.flushLine(),0===t.text.length&&(t.totalUsage?.outputTokens??0)>0&&n.warn("模型本轮只返回了 thinking/reasoning,没有生成可见回复"),t.stoppedAtStepLimit&&n.warn("已达单轮最大工具步数,任务可能未完成 — 继续追问即可接着做,或调高 runtime.max-steps");const s=r(i(t.totalUsage,t.sessionUsage,this.contextWindow,t.contextInputTokens));s&&process.stderr.write(`${e.gray(s)}\n`);break}}}stopCompactionSpinner(){this.compactionSpinner&&(this.compactionSpinner.stop(),this.compactionSpinner=void 0)}startMessageSpinner(){this.stopMessageSpinner(),this.messageSpinner=o(e.gray("思考中…")),this.messageSpinner.start()}stopMessageSpinner(){this.messageSpinner&&(this.messageSpinner.stop(),this.messageSpinner=void 0)}flushLine(){this.streaming&&(process.stdout.write("\n"),this.streaming=!1)}}
@@ -0,0 +1,14 @@
1
+ export interface CurrentCliShim {
2
+ readonly path: string;
3
+ dispose(): void;
4
+ }
5
+ export interface InstallCurrentCliShimOptions {
6
+ readonly env: NodeJS.ProcessEnv;
7
+ readonly executable?: string;
8
+ readonly execArgv?: readonly string[];
9
+ readonly entryPath?: string;
10
+ readonly launchCwd?: string;
11
+ readonly platform?: NodeJS.Platform;
12
+ readonly tempRoot?: string;
13
+ }
14
+ export declare function installCurrentCliShim(options: InstallCurrentCliShimOptions): CurrentCliShim;
@@ -0,0 +1 @@
1
+ import{chmodSync as e,mkdtempSync as t,rmSync as n,writeFileSync as r}from"node:fs";import{tmpdir as o}from"node:os";import{join as i,resolve as s}from"node:path";const c="ROLL_CURRENT_CLI",a=/^--inspect/u,l=["--require","-r","--import","--loader","--experimental-loader"],p=new WeakMap;function u(e){return`'${e.replaceAll("'","'\\''")}'`}function h(e){return`"${e.replaceAll("%","%%").replaceAll('"','\\"')}"`}function f(e,t){return/^\.{1,2}[\\/]/u.test(e)?s(t,e):e}function d(e,t){const n=[];for(let r=0;r<e.length;r+=1){const o=e[r];if(void 0===o||a.test(o))continue;if(void 0!==l.find(e=>e===o)){n.push(o);const i=e[r+1];void 0!==i&&(n.push(f(i,t)),r+=1);continue}const i=l.find(e=>o.startsWith(`${e}=`));if(void 0!==i){const e=o.slice(i.length+1);n.push(`${i}=${f(e,t)}`);continue}n.push(o)}return n}function v(e,t){return"win32"!==t?"PATH":Object.keys(e).find(e=>"path"===e.toLowerCase())??"Path"}function m(e){return`#!/bin/sh\nexec ${e.map(u).join(" ")} "$@"\n`}function C(e){return["@echo off",`${e.map(h).join(" ")} %*`,"exit /b %ERRORLEVEL%",""].join("\r\n")}export function installCurrentCliShim(s){const a=s.executable??process.execPath,l=s.entryPath??process.argv[1];if(!l)throw new Error("无法确定当前 Roll CLI 入口");const u=s.platform??process.platform,h=s.env,f="win32"===u?";":":";let w,$;try{w=t(i(s.tempRoot??o(),"roll-current-cli-")),e(w,448),$=i(w,"win32"===u?"roll.cmd":"roll");const n=[a,...d(s.execArgv??process.execArgv,s.launchCwd??process.cwd()),l],c="win32"===u?C(n):m(n);r($,c,{encoding:"utf8",mode:448})}catch(e){throw void 0!==w&&n(w,{recursive:!0,force:!0}),e}const b=v(h,u),x=p.get(h),y=x??{pathKey:b,basePath:h[b],baseCurrentCli:h[c],entries:[]};void 0===x&&p.set(h,y);const g={directory:w,path:$,active:!0};y.entries.push(g);const L=h[b];h[b]=L?`${w}${f}${L}`:w,h[c]=$;const R=()=>{n(w,{recursive:!0,force:!0})};process.once("exit",R);let P=!1;return{path:$,dispose(){if(P)return;P=!0,process.removeListener("exit",R),g.active=!1;const e=y.entries.filter(e=>e.active);if(0===e.length)void 0===y.basePath?delete h[y.pathKey]:h[y.pathKey]=y.basePath,void 0===y.baseCurrentCli?delete h[c]:h[c]=y.baseCurrentCli,p.delete(h);else{const t=h[y.pathKey];void 0!==t&&(h[y.pathKey]=t.split(f).filter(e=>e!==w).join(f)),y.entries.some(e=>e.path===h[c])&&(h[c]=e.at(-1)?.path)}R()}}}
@@ -0,0 +1,4 @@
1
+ import type { SessionEvent } from "@roll-agent/runtime";
2
+ export declare function formatDebugEvent(event: Extract<SessionEvent, {
3
+ type: "debug";
4
+ }>): string;
@@ -0,0 +1 @@
1
+ export function formatDebugEvent(s){const t=[`chat.${s.stage}`,s.message];return void 0!==s.elapsedMs&&t.push(`${String(s.elapsedMs)}ms`),void 0!==s.data&&t.push(JSON.stringify(s.data)),t.join(" · ")}
@@ -1,5 +1,5 @@
1
1
  import { type RollConfig } from "./schema.ts";
2
- export declare const LLM_PROVIDER_OPTIONS: readonly ["anthropic", "openai", "qwen", "deepseek"];
2
+ export declare const LLM_PROVIDER_OPTIONS: readonly ["anthropic", "openai", "qwen", "deepseek", "xai"];
3
3
  export type LlmProviderOption = (typeof LLM_PROVIDER_OPTIONS)[number];
4
4
  export declare const DEFAULT_LLM_PROVIDER: LlmProviderOption;
5
5
  export declare const DEFAULT_LLM_MODELS: {
@@ -7,6 +7,7 @@ export declare const DEFAULT_LLM_MODELS: {
7
7
  readonly openai: "gpt-5.5";
8
8
  readonly qwen: "qwen3.6-plus";
9
9
  readonly deepseek: "deepseek-v4-flash";
10
+ readonly xai: "grok-4.5";
10
11
  };
11
12
  /** 默认配置值;除上述必填 seed 外,全部由 rollConfigSchema 的默认值生成。 */
12
13
  export declare const DEFAULT_CONFIG: RollConfig;
@@ -1 +1 @@
1
- import{rollConfigSchema as e}from"./schema.js";export const LLM_PROVIDER_OPTIONS=["anthropic","openai","qwen","deepseek"];export const DEFAULT_LLM_PROVIDER="anthropic";export const DEFAULT_LLM_MODELS={anthropic:"claude-sonnet-4-6",openai:"gpt-5.5",qwen:"qwen3.6-plus",deepseek:"deepseek-v4-flash"};const o={llm:{defaultProvider:"anthropic",defaultModel:DEFAULT_LLM_MODELS.anthropic,providers:{}},ask:{},agents:{dataDir:"~/.roll-agent/agents"}};export const DEFAULT_CONFIG=e.parse(o);export const CONFIG_FILE_NAMES=["roll.config.yaml","roll.config.yml"];
1
+ import{rollConfigSchema as e}from"./schema.js";export const LLM_PROVIDER_OPTIONS=["anthropic","openai","qwen","deepseek","xai"];export const DEFAULT_LLM_PROVIDER="anthropic";export const DEFAULT_LLM_MODELS={anthropic:"claude-sonnet-4-6",openai:"gpt-5.5",qwen:"qwen3.6-plus",deepseek:"deepseek-v4-flash",xai:"grok-4.5"};const o={llm:{defaultProvider:"anthropic",defaultModel:DEFAULT_LLM_MODELS.anthropic,providers:{}},ask:{},agents:{dataDir:"~/.roll-agent/agents"}};export const DEFAULT_CONFIG=e.parse(o);export const CONFIG_FILE_NAMES=["roll.config.yaml","roll.config.yml"];
@@ -176,8 +176,30 @@ export declare const CONFIG_GUIDANCE_ENTRIES: readonly [{
176
176
  readonly path: "runtime.compaction.strategy";
177
177
  readonly title: "上下文压缩策略";
178
178
  readonly purpose: "选择 `summarize` 生成交接摘要,或用 `truncate` 直接移除较早消息。";
179
- readonly defaultBehavior: "默认值为 `summarize`;摘要失败时自动退回 `truncate`。" | "默认值为 `truncate`;摘要失败时自动退回 `truncate`。";
179
+ readonly defaultBehavior: "默认值为 `summarize`;结构化输出无效或过长时退回 `truncate`,Provider、网络或超时错误则保留原上下文。" | "默认值为 `truncate`;结构化输出无效或过长时退回 `truncate`,Provider、网络或超时错误则保留原上下文。";
180
180
  readonly example: "runtime:\n compaction:\n strategy: summarize" | "runtime:\n compaction:\n strategy: truncate";
181
+ }, {
182
+ readonly path: "runtime.compaction.timeout-ms";
183
+ readonly title: "压缩模型超时";
184
+ readonly purpose: "限制结构化 Checkpoint 模型请求的总等待时间,不包含本地证据整理和持久化。";
185
+ readonly defaultBehavior: `\u9ED8\u8BA4\u503C\u4E3A \`${string}\` \u6BEB\u79D2\uFF1B\u8D85\u65F6\u4FDD\u6301\u539F\u4E0A\u4E0B\u6587\uFF0C\u4E0D\u81EA\u52A8\u622A\u65AD\u3002`;
186
+ readonly example: `runtime:
187
+ compaction:
188
+ timeout-ms: ${string}`;
189
+ }, {
190
+ readonly path: "runtime.compaction.thinking-level";
191
+ readonly title: "压缩推理强度";
192
+ readonly purpose: "覆盖结构化 Checkpoint 生成的推理强度;使用 AI SDK 的统一 reasoning 语义映射到当前 Provider。";
193
+ readonly defaultBehavior: "默认不单独设置并继承 `runtime.thinking-level`;Qwen 结构化输出仍会强制关闭 thinking,不支持关闭推理的模型会在调用前报错。";
194
+ readonly example: "runtime:\n compaction:\n thinking-level: high";
195
+ }, {
196
+ readonly path: "runtime.compaction.max-output-tokens";
197
+ readonly title: "压缩输出 Token 上限";
198
+ readonly purpose: "限制结构化 Checkpoint 请求的 AI SDK 输出 token 预算。";
199
+ readonly defaultBehavior: `\u9ED8\u8BA4\u503C\u4E3A \`${string}\`\uFF1BProvider \u7684 reasoning token \u4E5F\u53EF\u80FD\u5360\u7528\u8BE5\u9884\u7B97\u3002`;
200
+ readonly example: `runtime:
201
+ compaction:
202
+ max-output-tokens: ${string}`;
181
203
  }, {
182
204
  readonly path: "runtime.compaction.threshold";
183
205
  readonly title: "自动压缩触发比例";
@@ -1 +1 @@
1
- import{DEFAULT_CONFIG as e}from"./defaults.js";import{normalizeUserPath as t}from"./key-codec.js";export const INSTALL_SCENARIOS=["default-network","china-dev","private-registry","advanced"];export const CONFIG_GUIDANCE_ENTRIES=[{path:"llm",title:"LLM 与模型",purpose:"集中设置 Roll 默认使用的模型提供商、模型名称和各 Provider 连接信息。",defaultBehavior:"默认使用内置的 Anthropic Provider 与默认模型;实际调用仍需要可用的认证信息。",example:`llm:\n default-provider: ${e.llm.defaultProvider}\n default-model: ${e.llm.defaultModel}\n providers: {}`,setupCommand:"roll config setup llm"},{path:"llm.default-provider",title:"默认 LLM 提供商",purpose:"选择 `roll ask`、`roll run` 的 MCP sampling,以及未单独覆盖时 `roll chat` 使用的模型提供商。",defaultBehavior:`默认值为 \`${e.llm.defaultProvider}\`。`,example:`llm:\n default-provider: ${e.llm.defaultProvider}`,setupCommand:"roll config setup llm"},{path:"llm.default-model",title:"默认 LLM 模型",purpose:"指定 Ask 的默认路由与 sampling 模型、Run 的 sampling 模型,以及 Chat 未单独覆盖时的模型。",defaultBehavior:`默认值为 \`${e.llm.defaultModel}\`。`,example:`llm:\n default-model: ${e.llm.defaultModel}`,setupCommand:"roll config setup llm"},{path:"llm.providers",title:"LLM Provider 配置",purpose:"按 Provider 名称保存认证密钥和可选的自定义 API 地址。",defaultBehavior:"默认没有 Provider 连接条目;只需添加实际会使用的 Provider。",example:"llm:\n providers:\n anthropic:\n api-key: ${ANTHROPIC_API_KEY}",setupCommand:"roll config setup llm"},{path:"llm.providers.<provider>",title:"单个 LLM Provider",purpose:"配置一个由名称标识的模型服务连接,例如 `anthropic`、`openai` 或兼容网关。",defaultBehavior:"新增条目后必须提供 API 密钥;API 地址可留空并使用 Provider 默认值。",example:"llm:\n providers:\n openai:\n api-key: ${OPENAI_API_KEY}",setupCommand:"roll config setup llm"},{path:"llm.providers.<provider>.api-key",title:"Provider API 密钥",purpose:"为一个 LLM provider 提供 API key(认证密钥);推荐使用 `${ENV_VAR}` 引用,避免明文落盘。",defaultBehavior:"无默认值;新增 provider 配置后必须填写,否则配置校验失败。",example:"llm:\n providers:\n anthropic:\n api-key: ${ANTHROPIC_API_KEY}",setupCommand:"roll config setup llm"},{path:"llm.providers.<provider>.base-url",title:"Provider API 地址",purpose:"把指定 provider 指向代理、兼容网关或私有部署的 API 根地址。",defaultBehavior:"不配置时使用各 provider 的内置地址;Qwen 使用 DashScope OpenAI 兼容地址。",example:"llm:\n providers:\n openai:\n base-url: https://api.openai.com/v1",setupCommand:"roll config setup llm"},{path:"ask",title:"Ask 智能路由",purpose:"只覆盖 `roll ask` 的路由模型和低置信度确认阈值。",defaultBehavior:"不设置覆盖时沿用全局 LLM 模型与内置确认阈值。",example:"ask:\n confirm-threshold: 0.5"},{path:"ask.llm-model",title:"Ask 路由模型",purpose:"仅为 `roll ask` 的意图路由和参数提取指定模型,不改变 `roll chat` 模型。",defaultBehavior:"不配置时使用 `llm.default-model`。",example:"ask:\n llm-model: gpt-5.4-mini"},{path:"ask.confirm-threshold",title:"Ask 执行阈值",purpose:"路由置信度低于此值时停止自动执行,并返回需要确认的结果。",defaultBehavior:"不配置时使用内置阈值 `0.5`。",example:"ask:\n confirm-threshold: 0.5"},{path:"runtime",title:"Chat 运行时",purpose:"控制 `roll chat` 的模型、单轮限制、审批、上下文压缩和 Shell 工具。",defaultBehavior:"所有子项都有安全默认值;只有需要覆盖默认行为时才写入配置。",example:`runtime:\n max-steps: ${e.runtime.maxSteps}\n turn-timeout-ms: ${e.runtime.turnTimeoutMs}`},{path:"runtime.provider",title:"Chat 模型提供商",purpose:"仅覆盖 `roll chat` 使用的模型提供商,便于让 Ask 与 Chat 使用不同服务。",defaultBehavior:"不配置时使用 `llm.default-provider`。",example:"runtime:\n provider: openai"},{path:"runtime.model",title:"Chat 模型",purpose:"仅覆盖 `roll chat` 的主模型;子 Agent 的 sampling 也复用该模型。",defaultBehavior:"不配置时使用 `llm.default-model`。",example:"runtime:\n model: gpt-5.5"},{path:"runtime.max-steps",title:"单轮最大步骤数",purpose:"限制 `roll chat` 单轮中模型继续推理和调用工具的最大步骤数。",defaultBehavior:`默认值为 \`${e.runtime.maxSteps}\`;达到上限后本轮停止继续调用工具。`,example:`runtime:\n max-steps: ${e.runtime.maxSteps}`},{path:"runtime.turn-timeout-ms",title:"单轮超时时间",purpose:"限制 `roll chat` 一整轮从开始到结束可占用的总时间,单位毫秒。",defaultBehavior:`默认值为 \`${e.runtime.turnTimeoutMs}\`,即 5 分钟。`,example:`runtime:\n turn-timeout-ms: ${e.runtime.turnTimeoutMs}`},{path:"runtime.threads-dir",title:"会话存储目录",purpose:"保存 `roll chat` 会话元数据和消息记录,供会话恢复与列表命令读取。",defaultBehavior:`默认值为 \`${e.runtime.threadsDir}\`;加载时会展开 \`~/\`。`,example:`runtime:\n threads-dir: ${e.runtime.threadsDir}`},{path:"runtime.context-window",title:"上下文窗口",purpose:"手动声明当前 Chat 模型的上下文 token 容量,用于计算自动压缩触发点。",defaultBehavior:"不配置时按模型名查询内置容量表;无法识别时不按占用比例触发压缩。",example:"runtime:\n context-window: 200000"},{path:"runtime.thinking-level",title:"推理强度",purpose:"控制 Chat 与 MCP sampling 的推理强度;可选 `off`、`low`、`medium`、`high`。",defaultBehavior:`默认值为 \`${e.runtime.thinkingLevel}\`;具体预算由 provider 适配层映射。`,example:`runtime:\n thinking-level: ${e.runtime.thinkingLevel}`},{path:"runtime.approval",title:"工具审批",purpose:"控制 Chat 调用工具时的默认授权方式,并允许按工具精确覆盖。",defaultBehavior:"默认采用 `"+e.runtime.approval.default+"`,优先保护有副作用的操作。",example:`runtime:\n approval:\n default: ${e.runtime.approval.default}\n overrides: {}`},{path:"runtime.approval.default",title:"工具默认审批策略",purpose:"决定 `roll chat` 未被单独覆盖的工具如何审批:`guarded` 按风险判断,`auto` 放行非破坏性操作,`deny` 拒绝。",defaultBehavior:`默认值为 \`${e.runtime.approval.default}\`。此配置不影响 \`roll ask\`。`,example:`runtime:\n approval:\n default: ${e.runtime.approval.default}`},{path:"runtime.approval.overrides",title:"单个工具审批规则",purpose:"按完整 `agentName.toolName` 为特定工具设置例外规则。",defaultBehavior:"默认为空;未命中的工具回退到 `runtime.approval.default`。",example:"runtime:\n approval:\n overrides:\n browser-use-agent.zhipin_send_prepared_reply: confirm\n browser-use-agent.browser_status: auto"},{path:"runtime.approval.overrides.<tool>",title:"单个工具审批策略",purpose:"为一个完整 `agentName.toolName` 选择 `auto`、`confirm` 或 `deny`。",defaultBehavior:"不配置该工具时回退到 `runtime.approval.default`。",example:"runtime:\n approval:\n overrides:\n browser-use-agent.browser_status: auto"},{path:"runtime.compaction",title:"上下文压缩",purpose:"在长对话接近模型上下文容量时,控制何时压缩以及保留多少近期内容。",defaultBehavior:"默认开启摘要压缩,并保留近期轮次与 token 预算。",example:`runtime:\n compaction:\n enabled: true\n strategy: ${e.runtime.compaction.strategy}`},{path:"runtime.compaction.enabled",title:"自动压缩上下文",purpose:"允许 Chat 在上下文接近容量或收到上下文超限错误时压缩早期消息。",defaultBehavior:`默认值为 \`${String(e.runtime.compaction.enabled)}\`。`,example:`runtime:\n compaction:\n enabled: ${String(e.runtime.compaction.enabled)}`},{path:"runtime.compaction.strategy",title:"上下文压缩策略",purpose:"选择 `summarize` 生成交接摘要,或用 `truncate` 直接移除较早消息。",defaultBehavior:`默认值为 \`${e.runtime.compaction.strategy}\`;摘要失败时自动退回 \`truncate\`。`,example:`runtime:\n compaction:\n strategy: ${e.runtime.compaction.strategy}`},{path:"runtime.compaction.threshold",title:"自动压缩触发比例",purpose:"当最近一次输入 token 占上下文窗口的比例达到此值时,在下一轮前压缩。",defaultBehavior:`默认值为 \`${e.runtime.compaction.threshold}\`。`,example:`runtime:\n compaction:\n threshold: ${e.runtime.compaction.threshold}`},{path:"runtime.compaction.keep-recent-turns",title:"保留最近对话轮数",purpose:"压缩时至少保留最近的用户对话轮,避免当前任务细节过早进入摘要。",defaultBehavior:`默认值为 \`${e.runtime.compaction.keepRecentTurns}\` 轮。`,example:`runtime:\n compaction:\n keep-recent-turns: ${e.runtime.compaction.keepRecentTurns}`},{path:"runtime.compaction.keep-recent-tokens",title:"保留最近 Token 预算",purpose:"压缩时用于保留近期完整对话的近似 token 预算,并与保留轮数共同取更保守边界。",defaultBehavior:`默认值为 \`${e.runtime.compaction.keepRecentTokens}\`。`,example:`runtime:\n compaction:\n keep-recent-tokens: ${e.runtime.compaction.keepRecentTokens}`},{path:"runtime.shell",title:"Shell 工具",purpose:"控制 Chat 是否可执行本地命令,以及一次性命令和后台会话的安全限制。",defaultBehavior:"默认关闭;开启后仍受工具审批策略、超时和输出上限约束。",example:"runtime:\n shell:\n enabled: true",setupCommand:"roll config setup shell"},{path:"runtime.shell.enabled",title:"Chat 内建 shell 工具",purpose:"在 `roll chat` 中注册命令工具:macOS/Linux 使用 `roll__bash`,Windows 使用 `roll__powershell`。",defaultBehavior:`默认值为 \`${String(e.runtime.shell.enabled)}\`(关闭);Windows 还需要 PowerShell 7+。`,example:"runtime:\n shell:\n enabled: true",setupCommand:"roll config setup shell"},{path:"runtime.shell.auto-approve-safe",title:"只读命令免确认",purpose:"让 POSIX shell 中已识别的安全只读命令免确认;危险或无法识别的命令仍需审批。",defaultBehavior:`默认值为 \`${String(e.runtime.shell.autoApproveSafe)}\`;Windows PowerShell 命令目前仍按未知操作处理。`,example:"runtime:\n shell:\n enabled: true\n auto-approve-safe: false",setupCommand:"roll config setup shell"},{path:"runtime.shell.default-timeout-ms",title:"Shell 默认超时时间",purpose:"为未显式传入超时的一次性 shell 命令设置执行上限,单位毫秒。",defaultBehavior:`默认值为 \`${e.runtime.shell.defaultTimeoutMs}\`;还会受最大超时和单轮超时限制。`,example:`runtime:\n shell:\n default-timeout-ms: ${e.runtime.shell.defaultTimeoutMs}`,setupCommand:"roll config setup shell"},{path:"runtime.shell.max-timeout-ms",title:"Shell 最大超时时间",purpose:"限制模型为一次性 shell 命令请求的最长执行时间,单位毫秒。",defaultBehavior:`默认值为 \`${e.runtime.shell.maxTimeoutMs}\`;实际时限仍不会超过单轮超时。`,example:`runtime:\n shell:\n max-timeout-ms: ${e.runtime.shell.maxTimeoutMs}`,setupCommand:"roll config setup shell"},{path:"runtime.shell.max-capture-bytes",title:"Shell 输出捕获上限",purpose:"限制 shell 标准输出与错误输出的内存捕获量,并限制后台会话输出缓冲区。",defaultBehavior:`默认值为 \`${e.runtime.shell.maxCaptureBytes}\` 字节。`,example:`runtime:\n shell:\n max-capture-bytes: ${e.runtime.shell.maxCaptureBytes}`,setupCommand:"roll config setup shell"},{path:"runtime.shell.max-model-output-chars",title:"Shell 模型输出上限",purpose:"限制一次性 shell 工具返回给模型的 stdout 与 stderr 总字符数。",defaultBehavior:`默认值为 \`${e.runtime.shell.maxModelOutputChars}\` 个字符;超出部分会截断并标记。`,example:`runtime:\n shell:\n max-model-output-chars: ${e.runtime.shell.maxModelOutputChars}`,setupCommand:"roll config setup shell"},{path:"runtime.shell.session",title:"后台命令会话",purpose:"让长命令跨 Chat 轮次继续运行,并通过轮询读取增量输出和退出状态。",defaultBehavior:"默认关闭;必须同时开启 Shell 工具,且会话随当前 Chat 进程退出。",example:"runtime:\n shell:\n enabled: true\n session:\n enabled: true",setupCommand:"roll config setup shell"},{path:"runtime.shell.session.enabled",title:"Chat 会话式长命令执行",purpose:"在 macOS/Linux 与 Windows PowerShell 7+ 中注册 `roll__exec_command`、`roll__exec_poll`、`roll__exec_list`,让长命令在后台跨轮运行。",defaultBehavior:`默认值为 \`${String(e.runtime.shell.session.enabled)}\`(关闭);仅长驻 Chat 模式可用且需开启 \`runtime.shell.enabled\`,\`--server\` 还需显式放行 \`roll.exec_command\`。`,example:"runtime:\n shell:\n enabled: true\n session:\n enabled: true\n approval:\n overrides:\n roll.exec_command: auto",setupCommand:"roll config setup shell"},{path:"runtime.shell.session.max-sessions",title:"后台命令会话上限",purpose:"限制同一 `roll chat` 进程中可保留的运行中或待领取结果的后台命令会话数。",defaultBehavior:`默认值为 \`${e.runtime.shell.session.maxSessions}\` 个会话。`,example:`runtime:\n shell:\n session:\n max-sessions: ${e.runtime.shell.session.maxSessions}`,setupCommand:"roll config setup shell"},{path:"runtime.shell.session.default-yield-ms",title:"后台命令默认等待时间",purpose:"设置 `exec_command` 首次返回前以及后续轮询通常等待的时间,单位毫秒。",defaultBehavior:`默认值为 \`${e.runtime.shell.session.defaultYieldMs}\`;调用方仍可在工具参数中覆盖。`,example:`runtime:\n shell:\n session:\n default-yield-ms: ${e.runtime.shell.session.defaultYieldMs}`,setupCommand:"roll config setup shell"},{path:"runtime.shell.session.max-output-tokens",title:"后台命令单次输出上限",purpose:"限制 `exec_command` / `exec_poll` 每次返回给模型的新输出量,以近似 token 数计。",defaultBehavior:`默认值为 \`${e.runtime.shell.session.maxOutputTokens}\`;运行中的会话不会因输出截断而停止。`,example:`runtime:\n shell:\n session:\n max-output-tokens: ${e.runtime.shell.session.maxOutputTokens}`,setupCommand:"roll config setup shell"},{path:"skills",title:"Skills 发现",purpose:"补充 `roll chat` 自动发现范围之外的 Skill 目录。",defaultBehavior:"标准项目级、用户级和已注册 Agent Skills 始终自动发现。",example:"skills:\n dirs: []"},{path:"skills.dirs",title:"Chat 额外 skill 目录",purpose:"`roll chat` 会自动发现项目级、用户级和已注册 Agent 的 Skill。这里只填写标准范围之外的额外目录,例如团队共享目录;目录可以直接包含 `SKILL.md`,也可以包含多个 Skill 子目录。",defaultBehavior:"默认为空;`<项目>/.agents/skills`、`~/.agents/skills`,以及通过 `npx skills add` 安装到标准位置的 Skill 都会自动发现,无需重复填写。",example:"skills:\n dirs:\n - ./openclaw-roll-core-skill-template"},{path:"skills.dirs.<item>",title:"额外 Skill 目录路径",purpose:"添加一个额外搜索目录;它可以直接含 `SKILL.md`,也可以包含多个 skill 子目录。",defaultBehavior:"默认没有额外目录;项目级、用户级和已注册 Agent 的 skills 仍会自动发现。",example:"skills:\n dirs:\n - ./skills/team-shared"},{path:"agents",title:"Agent 管理",purpose:"设置 Roll 的 Agent 数据目录,并为子 Agent 声明额外环境变量。",defaultBehavior:"使用默认数据目录;未写入的环境变量继续从 Roll 进程环境继承。",example:`agents:\n data-dir: ${e.agents.dataDir}`},{path:"agents.data-dir",title:"Agent 数据目录",purpose:"保存已注册 Agent、PID、日志和 runtime sidecar 等 Roll 管理数据。",defaultBehavior:`默认值为 \`${e.agents.dataDir}\`;加载时会展开 \`~/\`。`,example:`agents:\n data-dir: ${e.agents.dataDir}`},{path:"agents.env",title:"其他 Agent 环境变量",purpose:"为未在独立 Agent 页面中展示的 Agent 或自定义变量提供通用键值配置入口。",defaultBehavior:"默认没有额外注入;已声明的注册 Agent 优先在各自页面配置。",example:"agents:\n env:\n custom-agent:\n FEATURE_FLAG: enabled",setupCommand:"roll config setup agent <agent-name>"},{path:"agents.env.<agent-name>",title:"Agent 环境变量组",purpose:"按 Agent 名称组织需要注入子进程的环境变量。",defaultBehavior:"默认没有额外注入;子进程仍继承当前 Roll 进程环境。",example:"agents:\n env:\n browser-use-agent:\n REPLY_AUTHORITY_URL: https://example.com",setupCommand:"roll config setup agent <agent-name>"},{path:"agents.env.<agent-name>.<variable>",title:"Agent 环境变量",purpose:"为一个 Agent 注入单个字符串环境变量;同名值会覆盖父进程继承值。",defaultBehavior:"不配置时沿用 Roll 进程中的同名环境变量;core-managed Agent 需重启后生效。",example:"agents:\n env:\n browser-use-agent:\n REPLY_AUTHORITY_URL: https://example.com",setupCommand:"roll config setup agent <agent-name>"},{path:"install",title:"安装与更新",purpose:"控制 Agent 安装和 Roll 更新时使用的 npm 软件源、重试、缓存与超时。",defaultBehavior:"默认使用 npm 自身的软件源,并采用 Roll 的安全网络默认值。",example:`install:\n fetch-retries: ${e.install.fetchRetries}\n prefer-offline: false`,setupCommand:"roll config setup install"},{path:"install.registry",title:"npm Registry 地址",purpose:"指定 `roll agent install` 与 `roll update` 查询和安装 npm 包时使用的软件源。",defaultBehavior:"不配置时使用 npm 自身默认源;Roll 不做隐式镜像 fallback。",example:"install:\n registry: https://registry.npmmirror.com",setupCommand:"roll config setup install"},{path:"install.fetch-retries",title:"安装下载重试次数",purpose:"设置 npm `--fetch-retries`,同时作为 Roll 安装网络操作的整体重试次数。",defaultBehavior:`默认值为 \`${e.install.fetchRetries}\` 次。`,example:`install:\n fetch-retries: ${e.install.fetchRetries}`,setupCommand:"roll config setup install"},{path:"install.prefer-offline",title:"优先使用本地缓存",purpose:"决定 npm 安装时是否附加 `--prefer-offline`,优先复用本地缓存元数据。",defaultBehavior:`默认值为 \`${String(e.install.preferOffline)}\`,优先获取新鲜元数据。`,example:`install:\n prefer-offline: ${String(e.install.preferOffline)}`,setupCommand:"roll config setup install"},{path:"install.network-timeout-ms",title:"安装网络超时时间",purpose:"限制单次 npm install 命令的等待时间,单位毫秒。",defaultBehavior:`默认值为 \`${e.install.networkTimeoutMs}\`,即 120 秒。`,example:`install:\n network-timeout-ms: ${e.install.networkTimeoutMs}`,setupCommand:"roll config setup install"},{path:"browser",title:"浏览器实例",purpose:"管理 browser-use-agent 可以连接或启动的浏览器实例及默认选择。",defaultBehavior:"未声明实例时继续使用 legacy 单实例环境变量配置。",example:"browser:\n instances: {}"},{path:"browser.default-instance",title:"默认浏览器实例",purpose:"指定工具未传 `browserInstance` 时优先选择的已声明实例。",defaultBehavior:"不配置且只有一个实例时自动选择;有多个实例时必须由调用方指定。",example:"browser:\n default-instance: boss-a"},{path:"browser.instances",title:"浏览器实例声明",purpose:"声明 browser-use-agent 可使用的浏览器 profile、CDP 端口、会话目录和业务归因信息。",defaultBehavior:"不配置时 browser-use-agent 使用 legacy 单实例环境变量路径。",example:"browser:\n instances:\n boss-a:\n platform: zhipin\n mode: managed-cdp\n cdp-port: 9222\n user-data-dir: ~/.roll-agent/browser/boss-a"},{path:"browser.instances.<instance>",title:"单个浏览器实例",purpose:"用一个稳定名称描述浏览器连接方式、Profile、窗口和业务归属。",defaultBehavior:"默认使用本地托管 Chrome;仍必须为每个实例设置独占 Profile 目录和 CDP 端口。",example:"browser:\n instances:\n boss-a:\n mode: managed-cdp\n cdp-port: 9222\n user-data-dir: ~/.roll-agent/browser/boss-a"},{path:"browser.instances.<instance>.platform",title:"业务平台",purpose:"标记该浏览器实例属于 BOSS 直聘(`zhipin`)还是鱼泡(`yupao`),用于平台匹配校验。",defaultBehavior:"不配置时实例不限定业务平台,平台专用工具不会做实例平台冲突校验。",example:"browser:\n instances:\n boss-a:\n platform: zhipin"},{path:"browser.instances.<instance>.mode",title:"浏览器连接模式",purpose:"选择本地托管浏览器、远程 CDP,或连接用户已启动浏览器会话。",defaultBehavior:"默认值为 `managed-cdp`。",example:"browser:\n instances:\n boss-a:\n mode: managed-cdp"},{path:"browser.instances.<instance>.headless",title:"无头运行",purpose:"控制 `managed-cdp` 启动的浏览器是否隐藏窗口;其他连接模式不使用此项。",defaultBehavior:"不配置时继承 browser-use-agent 全局设置,默认显示浏览器窗口。",example:"browser:\n instances:\n boss-a:\n headless: false"},{path:"browser.instances.<instance>.cdp-url",title:"CDP 连接地址",purpose:"提供 `remote-cdp` 或 `existing-session` 模式要连接的 HTTP(S) / WebSocket CDP 地址。",defaultBehavior:"这两种模式下无默认值且必须填写;`managed-cdp` 使用 host 与 port 生成地址。",example:"browser:\n instances:\n chrome-open:\n mode: existing-session\n cdp-url: http://127.0.0.1:9222"},{path:"browser.instances.<instance>.cdp-host",title:"本地 CDP 主机",purpose:"指定 `managed-cdp` 启动后用于健康检查和连接的 CDP 主机地址。",defaultBehavior:"默认值为 `127.0.0.1`;远程与已有会话模式不使用此项。",example:"browser:\n instances:\n boss-a:\n cdp-host: 127.0.0.1"},{path:"browser.instances.<instance>.cdp-port",title:"本地 CDP 端口",purpose:"指定 `managed-cdp` 浏览器的远程调试端口;每个实例必须使用不同端口。",defaultBehavior:"`managed-cdp` 实例无默认值且必须填写;其他模式不使用此项。",example:"browser:\n instances:\n boss-a:\n cdp-port: 9222"},{path:"browser.instances.<instance>.channel",title:"浏览器类型",purpose:"选择 `managed-cdp` 启动系统 Chrome、Playwright Chromium 或 Microsoft Edge。",defaultBehavior:"默认值为 `chrome`;配置 `executable-path` 后此项会被忽略。",example:"browser:\n instances:\n boss-a:\n channel: chrome"},{path:"browser.instances.<instance>.executable-path",title:"浏览器程序路径",purpose:"为 `managed-cdp` 指定浏览器可执行文件,适合非标准安装位置或定制版本。",defaultBehavior:"不配置时按 `channel` 查找系统浏览器;配置后优先使用此路径。",example:"browser:\n instances:\n boss-a:\n executable-path: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome"},{path:"browser.instances.<instance>.user-data-dir",title:"浏览器 Profile 目录",purpose:"为实例声明独占的 Profile 目录;`managed-cdp` 在此保存登录态,状态检查也会检查其可写性。",defaultBehavior:"无默认值;每个已声明实例都必须填写。",example:"browser:\n instances:\n boss-a:\n user-data-dir: ~/.roll-agent/browser/boss-a"},{path:"browser.instances.<instance>.sessions-dir",title:"浏览器会话目录",purpose:"保存 Roll 的页面会话快照,与浏览器自身的 Profile 数据分开存放。",defaultBehavior:"不配置时使用 `~/.roll-agent/browser/sessions/<instance-id>`。",example:"browser:\n instances:\n boss-a:\n sessions-dir: ~/.roll-agent/browser/sessions/boss-a"},{path:"browser.instances.<instance>.args",title:"浏览器启动参数列表",purpose:"仅为本地托管浏览器追加确有必要的命令行开关。",defaultBehavior:"默认使用 browser-use-agent 内置启动参数,不追加自定义值。",example:"browser:\n instances:\n boss-a:\n args:\n - --lang=zh-CN"},{path:"browser.instances.<instance>.args.<item>",title:"浏览器启动参数",purpose:"向 `managed-cdp` 浏览器追加一个命令行参数;仅添加确实需要的开关。",defaultBehavior:"默认不追加自定义参数;远程与已有会话模式不使用此项。",example:"browser:\n instances:\n boss-a:\n args:\n - --lang=zh-CN"},{path:"browser.instances.<instance>.profile-name",title:"浏览器 Profile 名称",purpose:"设置托管 Chrome 窗口显示的 Profile 名称,帮助区分多个业务账号。",defaultBehavior:"不配置时使用浏览器实例 ID。",example:"browser:\n instances:\n boss-a:\n profile-name: BOSS 主账号"},{path:"browser.instances.<instance>.profile-color",title:"浏览器 Profile 颜色",purpose:"用六位十六进制颜色标记托管 Chrome Profile,帮助肉眼区分多个窗口。",defaultBehavior:"不配置时按实例顺序自动分配不同颜色。",example:'browser:\n instances:\n boss-a:\n profile-color: "#2563EB"'},{path:"browser.instances.<instance>.window-bounds",title:"窗口位置与大小",purpose:"可选地固定托管浏览器窗口的屏幕位置和尺寸。",defaultBehavior:"整组留空时,多实例可视模式会自动排布窗口。",example:"browser:\n instances:\n boss-a:\n window-bounds:\n x: 0\n y: 0\n width: 960\n height: 900"},{path:"browser.instances.<instance>.window-bounds.x",title:"窗口横向位置",purpose:"设置托管浏览器窗口左上角距主屏左侧的像素数。",defaultBehavior:"整个 `window-bounds` 未设置时,多实例可视模式会自动排布;否则交由系统决定。",example:"browser:\n instances:\n boss-a:\n window-bounds:\n x: 0"},{path:"browser.instances.<instance>.window-bounds.y",title:"窗口纵向位置",purpose:"设置托管浏览器窗口左上角距主屏顶部的像素数。",defaultBehavior:"整个 `window-bounds` 未设置时,多实例可视模式会自动排布;否则交由系统决定。",example:"browser:\n instances:\n boss-a:\n window-bounds:\n y: 0"},{path:"browser.instances.<instance>.window-bounds.width",title:"窗口宽度",purpose:"设置托管浏览器窗口宽度,单位像素,必须大于 0。",defaultBehavior:"整个 `window-bounds` 未设置时,多实例可视模式会自动排布;否则交由系统决定。",example:"browser:\n instances:\n boss-a:\n window-bounds:\n width: 960"},{path:"browser.instances.<instance>.window-bounds.height",title:"窗口高度",purpose:"设置托管浏览器窗口高度,单位像素,必须大于 0。",defaultBehavior:"整个 `window-bounds` 未设置时,多实例可视模式会自动排布;否则交由系统决定。",example:"browser:\n instances:\n boss-a:\n window-bounds:\n height: 900"},{path:"browser.instances.<instance>.tracking-agent-id",title:"招聘事件 Agent ID",purpose:"为该浏览器实例上报的招聘事件指定归因 Agent ID。",defaultBehavior:"不配置时回退到 `RECRUITMENT_EVENTS_DEFAULT_AGENT_ID`;两者都没有时状态标记为未配置。",example:"browser:\n instances:\n boss-a:\n tracking-agent-id: zhipin-boss-a"}];export function listConfigGuidanceEntries(){return CONFIG_GUIDANCE_ENTRIES}export function findConfigGuidance(e){const a=t(e.split("."));return CONFIG_GUIDANCE_ENTRIES.find(e=>n(e.path,a))}function n(e,n){const a=t(e.split("."));return a.length===n.length&&a.every((e,t)=>e.startsWith("<")||e===n[t])}export function flattenAgentEnvDeclarations(e){return[...(e?.required??[]).map(e=>({...e,required:!0})),...(e?.optional??[]).map(e=>({...e,required:!1}))]}export function isSecretEnvDeclaration(e){return e.secret??!0}
1
+ import{DEFAULT_CONFIG as e}from"./defaults.js";import{normalizeUserPath as t}from"./key-codec.js";export const INSTALL_SCENARIOS=["default-network","china-dev","private-registry","advanced"];export const CONFIG_GUIDANCE_ENTRIES=[{path:"llm",title:"LLM 与模型",purpose:"集中设置 Roll 默认使用的模型提供商、模型名称和各 Provider 连接信息。",defaultBehavior:"默认使用内置的 Anthropic Provider 与默认模型;实际调用仍需要可用的认证信息。",example:`llm:\n default-provider: ${e.llm.defaultProvider}\n default-model: ${e.llm.defaultModel}\n providers: {}`,setupCommand:"roll config setup llm"},{path:"llm.default-provider",title:"默认 LLM 提供商",purpose:"选择 `roll ask`、`roll run` 的 MCP sampling,以及未单独覆盖时 `roll chat` 使用的模型提供商。",defaultBehavior:`默认值为 \`${e.llm.defaultProvider}\`。`,example:`llm:\n default-provider: ${e.llm.defaultProvider}`,setupCommand:"roll config setup llm"},{path:"llm.default-model",title:"默认 LLM 模型",purpose:"指定 Ask 的默认路由与 sampling 模型、Run 的 sampling 模型,以及 Chat 未单独覆盖时的模型。",defaultBehavior:`默认值为 \`${e.llm.defaultModel}\`。`,example:`llm:\n default-model: ${e.llm.defaultModel}`,setupCommand:"roll config setup llm"},{path:"llm.providers",title:"LLM Provider 配置",purpose:"按 Provider 名称保存认证密钥和可选的自定义 API 地址。",defaultBehavior:"默认没有 Provider 连接条目;只需添加实际会使用的 Provider。",example:"llm:\n providers:\n anthropic:\n api-key: ${ANTHROPIC_API_KEY}",setupCommand:"roll config setup llm"},{path:"llm.providers.<provider>",title:"单个 LLM Provider",purpose:"配置一个由名称标识的模型服务连接,例如 `anthropic`、`openai` 或兼容网关。",defaultBehavior:"新增条目后必须提供 API 密钥;API 地址可留空并使用 Provider 默认值。",example:"llm:\n providers:\n openai:\n api-key: ${OPENAI_API_KEY}",setupCommand:"roll config setup llm"},{path:"llm.providers.<provider>.api-key",title:"Provider API 密钥",purpose:"为一个 LLM provider 提供 API key(认证密钥);推荐使用 `${ENV_VAR}` 引用,避免明文落盘。",defaultBehavior:"无默认值;新增 provider 配置后必须填写,否则配置校验失败。",example:"llm:\n providers:\n anthropic:\n api-key: ${ANTHROPIC_API_KEY}",setupCommand:"roll config setup llm"},{path:"llm.providers.<provider>.base-url",title:"Provider API 地址",purpose:"把指定 provider 指向代理、兼容网关或私有部署的 API 根地址。",defaultBehavior:"不配置时使用各 provider 的内置地址;Qwen 使用 DashScope OpenAI 兼容地址。",example:"llm:\n providers:\n openai:\n base-url: https://api.openai.com/v1",setupCommand:"roll config setup llm"},{path:"ask",title:"Ask 智能路由",purpose:"只覆盖 `roll ask` 的路由模型和低置信度确认阈值。",defaultBehavior:"不设置覆盖时沿用全局 LLM 模型与内置确认阈值。",example:"ask:\n confirm-threshold: 0.5"},{path:"ask.llm-model",title:"Ask 路由模型",purpose:"仅为 `roll ask` 的意图路由和参数提取指定模型,不改变 `roll chat` 模型。",defaultBehavior:"不配置时使用 `llm.default-model`。",example:"ask:\n llm-model: gpt-5.4-mini"},{path:"ask.confirm-threshold",title:"Ask 执行阈值",purpose:"路由置信度低于此值时停止自动执行,并返回需要确认的结果。",defaultBehavior:"不配置时使用内置阈值 `0.5`。",example:"ask:\n confirm-threshold: 0.5"},{path:"runtime",title:"Chat 运行时",purpose:"控制 `roll chat` 的模型、单轮限制、审批、上下文压缩和 Shell 工具。",defaultBehavior:"所有子项都有安全默认值;只有需要覆盖默认行为时才写入配置。",example:`runtime:\n max-steps: ${e.runtime.maxSteps}\n turn-timeout-ms: ${e.runtime.turnTimeoutMs}`},{path:"runtime.provider",title:"Chat 模型提供商",purpose:"仅覆盖 `roll chat` 使用的模型提供商,便于让 Ask 与 Chat 使用不同服务。",defaultBehavior:"不配置时使用 `llm.default-provider`。",example:"runtime:\n provider: openai"},{path:"runtime.model",title:"Chat 模型",purpose:"仅覆盖 `roll chat` 的主模型;子 Agent 的 sampling 也复用该模型。",defaultBehavior:"不配置时使用 `llm.default-model`。",example:"runtime:\n model: gpt-5.5"},{path:"runtime.max-steps",title:"单轮最大步骤数",purpose:"限制 `roll chat` 单轮中模型继续推理和调用工具的最大步骤数。",defaultBehavior:`默认值为 \`${e.runtime.maxSteps}\`;达到上限后本轮停止继续调用工具。`,example:`runtime:\n max-steps: ${e.runtime.maxSteps}`},{path:"runtime.turn-timeout-ms",title:"单轮超时时间",purpose:"限制 `roll chat` 一整轮从开始到结束可占用的总时间,单位毫秒。",defaultBehavior:`默认值为 \`${e.runtime.turnTimeoutMs}\`,即 5 分钟。`,example:`runtime:\n turn-timeout-ms: ${e.runtime.turnTimeoutMs}`},{path:"runtime.threads-dir",title:"会话存储目录",purpose:"保存 `roll chat` 会话元数据和消息记录,供会话恢复与列表命令读取。",defaultBehavior:`默认值为 \`${e.runtime.threadsDir}\`;加载时会展开 \`~/\`。`,example:`runtime:\n threads-dir: ${e.runtime.threadsDir}`},{path:"runtime.context-window",title:"上下文窗口",purpose:"手动声明当前 Chat 模型的上下文 token 容量,用于计算自动压缩触发点。",defaultBehavior:"不配置时按模型名查询内置容量表;无法识别时不按占用比例触发压缩。",example:"runtime:\n context-window: 200000"},{path:"runtime.thinking-level",title:"推理强度",purpose:"控制 Chat 与 MCP sampling 的推理强度;可选 `off`、`low`、`medium`、`high`。",defaultBehavior:`默认值为 \`${e.runtime.thinkingLevel}\`;具体预算由 provider 适配层映射。`,example:`runtime:\n thinking-level: ${e.runtime.thinkingLevel}`},{path:"runtime.approval",title:"工具审批",purpose:"控制 Chat 调用工具时的默认授权方式,并允许按工具精确覆盖。",defaultBehavior:"默认采用 `"+e.runtime.approval.default+"`,优先保护有副作用的操作。",example:`runtime:\n approval:\n default: ${e.runtime.approval.default}\n overrides: {}`},{path:"runtime.approval.default",title:"工具默认审批策略",purpose:"决定 `roll chat` 未被单独覆盖的工具如何审批:`guarded` 按风险判断,`auto` 放行非破坏性操作,`deny` 拒绝。",defaultBehavior:`默认值为 \`${e.runtime.approval.default}\`。此配置不影响 \`roll ask\`。`,example:`runtime:\n approval:\n default: ${e.runtime.approval.default}`},{path:"runtime.approval.overrides",title:"单个工具审批规则",purpose:"按完整 `agentName.toolName` 为特定工具设置例外规则。",defaultBehavior:"默认为空;未命中的工具回退到 `runtime.approval.default`。",example:"runtime:\n approval:\n overrides:\n browser-use-agent.zhipin_send_prepared_reply: confirm\n browser-use-agent.browser_status: auto"},{path:"runtime.approval.overrides.<tool>",title:"单个工具审批策略",purpose:"为一个完整 `agentName.toolName` 选择 `auto`、`confirm` 或 `deny`。",defaultBehavior:"不配置该工具时回退到 `runtime.approval.default`。",example:"runtime:\n approval:\n overrides:\n browser-use-agent.browser_status: auto"},{path:"runtime.compaction",title:"上下文压缩",purpose:"在长对话接近模型上下文容量时,控制何时压缩以及保留多少近期内容。",defaultBehavior:"默认开启摘要压缩,并保留近期轮次与 token 预算。",example:`runtime:\n compaction:\n enabled: true\n strategy: ${e.runtime.compaction.strategy}`},{path:"runtime.compaction.enabled",title:"自动压缩上下文",purpose:"允许 Chat 在上下文接近容量或收到上下文超限错误时压缩早期消息。",defaultBehavior:`默认值为 \`${String(e.runtime.compaction.enabled)}\`。`,example:`runtime:\n compaction:\n enabled: ${String(e.runtime.compaction.enabled)}`},{path:"runtime.compaction.strategy",title:"上下文压缩策略",purpose:"选择 `summarize` 生成交接摘要,或用 `truncate` 直接移除较早消息。",defaultBehavior:`默认值为 \`${e.runtime.compaction.strategy}\`;结构化输出无效或过长时退回 \`truncate\`,Provider、网络或超时错误则保留原上下文。`,example:`runtime:\n compaction:\n strategy: ${e.runtime.compaction.strategy}`},{path:"runtime.compaction.timeout-ms",title:"压缩模型超时",purpose:"限制结构化 Checkpoint 模型请求的总等待时间,不包含本地证据整理和持久化。",defaultBehavior:`默认值为 \`${String(e.runtime.compaction.timeoutMs)}\` 毫秒;超时保持原上下文,不自动截断。`,example:`runtime:\n compaction:\n timeout-ms: ${String(e.runtime.compaction.timeoutMs)}`},{path:"runtime.compaction.thinking-level",title:"压缩推理强度",purpose:"覆盖结构化 Checkpoint 生成的推理强度;使用 AI SDK 的统一 reasoning 语义映射到当前 Provider。",defaultBehavior:"默认不单独设置并继承 `runtime.thinking-level`;Qwen 结构化输出仍会强制关闭 thinking,不支持关闭推理的模型会在调用前报错。",example:"runtime:\n compaction:\n thinking-level: high"},{path:"runtime.compaction.max-output-tokens",title:"压缩输出 Token 上限",purpose:"限制结构化 Checkpoint 请求的 AI SDK 输出 token 预算。",defaultBehavior:`默认值为 \`${String(e.runtime.compaction.maxOutputTokens)}\`;Provider 的 reasoning token 也可能占用该预算。`,example:`runtime:\n compaction:\n max-output-tokens: ${String(e.runtime.compaction.maxOutputTokens)}`},{path:"runtime.compaction.threshold",title:"自动压缩触发比例",purpose:"当最近一次输入 token 占上下文窗口的比例达到此值时,在下一轮前压缩。",defaultBehavior:`默认值为 \`${e.runtime.compaction.threshold}\`。`,example:`runtime:\n compaction:\n threshold: ${e.runtime.compaction.threshold}`},{path:"runtime.compaction.keep-recent-turns",title:"保留最近对话轮数",purpose:"压缩时至少保留最近的用户对话轮,避免当前任务细节过早进入摘要。",defaultBehavior:`默认值为 \`${e.runtime.compaction.keepRecentTurns}\` 轮。`,example:`runtime:\n compaction:\n keep-recent-turns: ${e.runtime.compaction.keepRecentTurns}`},{path:"runtime.compaction.keep-recent-tokens",title:"保留最近 Token 预算",purpose:"压缩时用于保留近期完整对话的近似 token 预算,并与保留轮数共同取更保守边界。",defaultBehavior:`默认值为 \`${e.runtime.compaction.keepRecentTokens}\`。`,example:`runtime:\n compaction:\n keep-recent-tokens: ${e.runtime.compaction.keepRecentTokens}`},{path:"runtime.shell",title:"Shell 工具",purpose:"控制 Chat 是否可执行本地命令,以及一次性命令和后台会话的安全限制。",defaultBehavior:"默认关闭;开启后仍受工具审批策略、超时和输出上限约束。",example:"runtime:\n shell:\n enabled: true",setupCommand:"roll config setup shell"},{path:"runtime.shell.enabled",title:"Chat 内建 shell 工具",purpose:"在 `roll chat` 中注册命令工具:macOS/Linux 使用 `roll__bash`,Windows 使用 `roll__powershell`。",defaultBehavior:`默认值为 \`${String(e.runtime.shell.enabled)}\`(关闭);Windows 还需要 PowerShell 7+。`,example:"runtime:\n shell:\n enabled: true",setupCommand:"roll config setup shell"},{path:"runtime.shell.auto-approve-safe",title:"只读命令免确认",purpose:"让 POSIX shell 中已识别的安全只读命令免确认;危险或无法识别的命令仍需审批。",defaultBehavior:`默认值为 \`${String(e.runtime.shell.autoApproveSafe)}\`;Windows PowerShell 命令目前仍按未知操作处理。`,example:"runtime:\n shell:\n enabled: true\n auto-approve-safe: false",setupCommand:"roll config setup shell"},{path:"runtime.shell.default-timeout-ms",title:"Shell 默认超时时间",purpose:"为未显式传入超时的一次性 shell 命令设置执行上限,单位毫秒。",defaultBehavior:`默认值为 \`${e.runtime.shell.defaultTimeoutMs}\`;还会受最大超时和单轮超时限制。`,example:`runtime:\n shell:\n default-timeout-ms: ${e.runtime.shell.defaultTimeoutMs}`,setupCommand:"roll config setup shell"},{path:"runtime.shell.max-timeout-ms",title:"Shell 最大超时时间",purpose:"限制模型为一次性 shell 命令请求的最长执行时间,单位毫秒。",defaultBehavior:`默认值为 \`${e.runtime.shell.maxTimeoutMs}\`;实际时限仍不会超过单轮超时。`,example:`runtime:\n shell:\n max-timeout-ms: ${e.runtime.shell.maxTimeoutMs}`,setupCommand:"roll config setup shell"},{path:"runtime.shell.max-capture-bytes",title:"Shell 输出捕获上限",purpose:"限制 shell 标准输出与错误输出的内存捕获量,并限制后台会话输出缓冲区。",defaultBehavior:`默认值为 \`${e.runtime.shell.maxCaptureBytes}\` 字节。`,example:`runtime:\n shell:\n max-capture-bytes: ${e.runtime.shell.maxCaptureBytes}`,setupCommand:"roll config setup shell"},{path:"runtime.shell.max-model-output-chars",title:"Shell 模型输出上限",purpose:"限制一次性 shell 工具返回给模型的 stdout 与 stderr 总字符数。",defaultBehavior:`默认值为 \`${e.runtime.shell.maxModelOutputChars}\` 个字符;超出部分会截断并标记。`,example:`runtime:\n shell:\n max-model-output-chars: ${e.runtime.shell.maxModelOutputChars}`,setupCommand:"roll config setup shell"},{path:"runtime.shell.session",title:"后台命令会话",purpose:"让长命令跨 Chat 轮次继续运行,并通过轮询读取增量输出和退出状态。",defaultBehavior:"默认关闭;必须同时开启 Shell 工具,且会话随当前 Chat 进程退出。",example:"runtime:\n shell:\n enabled: true\n session:\n enabled: true",setupCommand:"roll config setup shell"},{path:"runtime.shell.session.enabled",title:"Chat 会话式长命令执行",purpose:"在 macOS/Linux 与 Windows PowerShell 7+ 中注册 `roll__exec_command`、`roll__exec_poll`、`roll__exec_list`,让长命令在后台跨轮运行。",defaultBehavior:`默认值为 \`${String(e.runtime.shell.session.enabled)}\`(关闭);仅长驻 Chat 模式可用且需开启 \`runtime.shell.enabled\`,\`--server\` 还需显式放行 \`roll.exec_command\`。`,example:"runtime:\n shell:\n enabled: true\n session:\n enabled: true\n approval:\n overrides:\n roll.exec_command: auto",setupCommand:"roll config setup shell"},{path:"runtime.shell.session.max-sessions",title:"后台命令会话上限",purpose:"限制同一 `roll chat` 进程中可保留的运行中或待领取结果的后台命令会话数。",defaultBehavior:`默认值为 \`${e.runtime.shell.session.maxSessions}\` 个会话。`,example:`runtime:\n shell:\n session:\n max-sessions: ${e.runtime.shell.session.maxSessions}`,setupCommand:"roll config setup shell"},{path:"runtime.shell.session.default-yield-ms",title:"后台命令默认等待时间",purpose:"设置 `exec_command` 首次返回前以及后续轮询通常等待的时间,单位毫秒。",defaultBehavior:`默认值为 \`${e.runtime.shell.session.defaultYieldMs}\`;调用方仍可在工具参数中覆盖。`,example:`runtime:\n shell:\n session:\n default-yield-ms: ${e.runtime.shell.session.defaultYieldMs}`,setupCommand:"roll config setup shell"},{path:"runtime.shell.session.max-output-tokens",title:"后台命令单次输出上限",purpose:"限制 `exec_command` / `exec_poll` 每次返回给模型的新输出量,以近似 token 数计。",defaultBehavior:`默认值为 \`${e.runtime.shell.session.maxOutputTokens}\`;运行中的会话不会因输出截断而停止。`,example:`runtime:\n shell:\n session:\n max-output-tokens: ${e.runtime.shell.session.maxOutputTokens}`,setupCommand:"roll config setup shell"},{path:"skills",title:"Skills 发现",purpose:"补充 `roll chat` 自动发现范围之外的 Skill 目录。",defaultBehavior:"标准项目级、用户级和已注册 Agent Skills 始终自动发现。",example:"skills:\n dirs: []"},{path:"skills.dirs",title:"Chat 额外 skill 目录",purpose:"`roll chat` 会自动发现项目级、用户级和已注册 Agent 的 Skill。这里只填写标准范围之外的额外目录,例如团队共享目录;目录可以直接包含 `SKILL.md`,也可以包含多个 Skill 子目录。",defaultBehavior:"默认为空;`<项目>/.agents/skills`、`~/.agents/skills`,以及通过 `npx skills add` 安装到标准位置的 Skill 都会自动发现,无需重复填写。",example:"skills:\n dirs:\n - ./openclaw-roll-core-skill-template"},{path:"skills.dirs.<item>",title:"额外 Skill 目录路径",purpose:"添加一个额外搜索目录;它可以直接含 `SKILL.md`,也可以包含多个 skill 子目录。",defaultBehavior:"默认没有额外目录;项目级、用户级和已注册 Agent 的 skills 仍会自动发现。",example:"skills:\n dirs:\n - ./skills/team-shared"},{path:"agents",title:"Agent 管理",purpose:"设置 Roll 的 Agent 数据目录,并为子 Agent 声明额外环境变量。",defaultBehavior:"使用默认数据目录;未写入的环境变量继续从 Roll 进程环境继承。",example:`agents:\n data-dir: ${e.agents.dataDir}`},{path:"agents.data-dir",title:"Agent 数据目录",purpose:"保存已注册 Agent、PID、日志和 runtime sidecar 等 Roll 管理数据。",defaultBehavior:`默认值为 \`${e.agents.dataDir}\`;加载时会展开 \`~/\`。`,example:`agents:\n data-dir: ${e.agents.dataDir}`},{path:"agents.env",title:"其他 Agent 环境变量",purpose:"为未在独立 Agent 页面中展示的 Agent 或自定义变量提供通用键值配置入口。",defaultBehavior:"默认没有额外注入;已声明的注册 Agent 优先在各自页面配置。",example:"agents:\n env:\n custom-agent:\n FEATURE_FLAG: enabled",setupCommand:"roll config setup agent <agent-name>"},{path:"agents.env.<agent-name>",title:"Agent 环境变量组",purpose:"按 Agent 名称组织需要注入子进程的环境变量。",defaultBehavior:"默认没有额外注入;子进程仍继承当前 Roll 进程环境。",example:"agents:\n env:\n browser-use-agent:\n REPLY_AUTHORITY_URL: https://example.com",setupCommand:"roll config setup agent <agent-name>"},{path:"agents.env.<agent-name>.<variable>",title:"Agent 环境变量",purpose:"为一个 Agent 注入单个字符串环境变量;同名值会覆盖父进程继承值。",defaultBehavior:"不配置时沿用 Roll 进程中的同名环境变量;core-managed Agent 需重启后生效。",example:"agents:\n env:\n browser-use-agent:\n REPLY_AUTHORITY_URL: https://example.com",setupCommand:"roll config setup agent <agent-name>"},{path:"install",title:"安装与更新",purpose:"控制 Agent 安装和 Roll 更新时使用的 npm 软件源、重试、缓存与超时。",defaultBehavior:"默认使用 npm 自身的软件源,并采用 Roll 的安全网络默认值。",example:`install:\n fetch-retries: ${e.install.fetchRetries}\n prefer-offline: false`,setupCommand:"roll config setup install"},{path:"install.registry",title:"npm Registry 地址",purpose:"指定 `roll agent install` 与 `roll update` 查询和安装 npm 包时使用的软件源。",defaultBehavior:"不配置时使用 npm 自身默认源;Roll 不做隐式镜像 fallback。",example:"install:\n registry: https://registry.npmmirror.com",setupCommand:"roll config setup install"},{path:"install.fetch-retries",title:"安装下载重试次数",purpose:"设置 npm `--fetch-retries`,同时作为 Roll 安装网络操作的整体重试次数。",defaultBehavior:`默认值为 \`${e.install.fetchRetries}\` 次。`,example:`install:\n fetch-retries: ${e.install.fetchRetries}`,setupCommand:"roll config setup install"},{path:"install.prefer-offline",title:"优先使用本地缓存",purpose:"决定 npm 安装时是否附加 `--prefer-offline`,优先复用本地缓存元数据。",defaultBehavior:`默认值为 \`${String(e.install.preferOffline)}\`,优先获取新鲜元数据。`,example:`install:\n prefer-offline: ${String(e.install.preferOffline)}`,setupCommand:"roll config setup install"},{path:"install.network-timeout-ms",title:"安装网络超时时间",purpose:"限制单次 npm install 命令的等待时间,单位毫秒。",defaultBehavior:`默认值为 \`${e.install.networkTimeoutMs}\`,即 120 秒。`,example:`install:\n network-timeout-ms: ${e.install.networkTimeoutMs}`,setupCommand:"roll config setup install"},{path:"browser",title:"浏览器实例",purpose:"管理 browser-use-agent 可以连接或启动的浏览器实例及默认选择。",defaultBehavior:"未声明实例时继续使用 legacy 单实例环境变量配置。",example:"browser:\n instances: {}"},{path:"browser.default-instance",title:"默认浏览器实例",purpose:"指定工具未传 `browserInstance` 时优先选择的已声明实例。",defaultBehavior:"不配置且只有一个实例时自动选择;有多个实例时必须由调用方指定。",example:"browser:\n default-instance: boss-a"},{path:"browser.instances",title:"浏览器实例声明",purpose:"声明 browser-use-agent 可使用的浏览器 profile、CDP 端口、会话目录和业务归因信息。",defaultBehavior:"不配置时 browser-use-agent 使用 legacy 单实例环境变量路径。",example:"browser:\n instances:\n boss-a:\n platform: zhipin\n mode: managed-cdp\n cdp-port: 9222\n user-data-dir: ~/.roll-agent/browser/boss-a"},{path:"browser.instances.<instance>",title:"单个浏览器实例",purpose:"用一个稳定名称描述浏览器连接方式、Profile、窗口和业务归属。",defaultBehavior:"默认使用本地托管 Chrome;仍必须为每个实例设置独占 Profile 目录和 CDP 端口。",example:"browser:\n instances:\n boss-a:\n mode: managed-cdp\n cdp-port: 9222\n user-data-dir: ~/.roll-agent/browser/boss-a"},{path:"browser.instances.<instance>.platform",title:"业务平台",purpose:"标记该浏览器实例属于 BOSS 直聘(`zhipin`)还是鱼泡(`yupao`),用于平台匹配校验。",defaultBehavior:"不配置时实例不限定业务平台,平台专用工具不会做实例平台冲突校验。",example:"browser:\n instances:\n boss-a:\n platform: zhipin"},{path:"browser.instances.<instance>.mode",title:"浏览器连接模式",purpose:"选择本地托管浏览器、远程 CDP,或连接用户已启动浏览器会话。",defaultBehavior:"默认值为 `managed-cdp`。",example:"browser:\n instances:\n boss-a:\n mode: managed-cdp"},{path:"browser.instances.<instance>.headless",title:"无头运行",purpose:"控制 `managed-cdp` 启动的浏览器是否隐藏窗口;其他连接模式不使用此项。",defaultBehavior:"不配置时继承 browser-use-agent 全局设置,默认显示浏览器窗口。",example:"browser:\n instances:\n boss-a:\n headless: false"},{path:"browser.instances.<instance>.cdp-url",title:"CDP 连接地址",purpose:"提供 `remote-cdp` 或 `existing-session` 模式要连接的 HTTP(S) / WebSocket CDP 地址。",defaultBehavior:"这两种模式下无默认值且必须填写;`managed-cdp` 使用 host 与 port 生成地址。",example:"browser:\n instances:\n chrome-open:\n mode: existing-session\n cdp-url: http://127.0.0.1:9222"},{path:"browser.instances.<instance>.cdp-host",title:"本地 CDP 主机",purpose:"指定 `managed-cdp` 启动后用于健康检查和连接的 CDP 主机地址。",defaultBehavior:"默认值为 `127.0.0.1`;远程与已有会话模式不使用此项。",example:"browser:\n instances:\n boss-a:\n cdp-host: 127.0.0.1"},{path:"browser.instances.<instance>.cdp-port",title:"本地 CDP 端口",purpose:"指定 `managed-cdp` 浏览器的远程调试端口;每个实例必须使用不同端口。",defaultBehavior:"`managed-cdp` 实例无默认值且必须填写;其他模式不使用此项。",example:"browser:\n instances:\n boss-a:\n cdp-port: 9222"},{path:"browser.instances.<instance>.channel",title:"浏览器类型",purpose:"选择 `managed-cdp` 启动系统 Chrome、Playwright Chromium 或 Microsoft Edge。",defaultBehavior:"默认值为 `chrome`;配置 `executable-path` 后此项会被忽略。",example:"browser:\n instances:\n boss-a:\n channel: chrome"},{path:"browser.instances.<instance>.executable-path",title:"浏览器程序路径",purpose:"为 `managed-cdp` 指定浏览器可执行文件,适合非标准安装位置或定制版本。",defaultBehavior:"不配置时按 `channel` 查找系统浏览器;配置后优先使用此路径。",example:"browser:\n instances:\n boss-a:\n executable-path: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome"},{path:"browser.instances.<instance>.user-data-dir",title:"浏览器 Profile 目录",purpose:"为实例声明独占的 Profile 目录;`managed-cdp` 在此保存登录态,状态检查也会检查其可写性。",defaultBehavior:"无默认值;每个已声明实例都必须填写。",example:"browser:\n instances:\n boss-a:\n user-data-dir: ~/.roll-agent/browser/boss-a"},{path:"browser.instances.<instance>.sessions-dir",title:"浏览器会话目录",purpose:"保存 Roll 的页面会话快照,与浏览器自身的 Profile 数据分开存放。",defaultBehavior:"不配置时使用 `~/.roll-agent/browser/sessions/<instance-id>`。",example:"browser:\n instances:\n boss-a:\n sessions-dir: ~/.roll-agent/browser/sessions/boss-a"},{path:"browser.instances.<instance>.args",title:"浏览器启动参数列表",purpose:"仅为本地托管浏览器追加确有必要的命令行开关。",defaultBehavior:"默认使用 browser-use-agent 内置启动参数,不追加自定义值。",example:"browser:\n instances:\n boss-a:\n args:\n - --lang=zh-CN"},{path:"browser.instances.<instance>.args.<item>",title:"浏览器启动参数",purpose:"向 `managed-cdp` 浏览器追加一个命令行参数;仅添加确实需要的开关。",defaultBehavior:"默认不追加自定义参数;远程与已有会话模式不使用此项。",example:"browser:\n instances:\n boss-a:\n args:\n - --lang=zh-CN"},{path:"browser.instances.<instance>.profile-name",title:"浏览器 Profile 名称",purpose:"设置托管 Chrome 窗口显示的 Profile 名称,帮助区分多个业务账号。",defaultBehavior:"不配置时使用浏览器实例 ID。",example:"browser:\n instances:\n boss-a:\n profile-name: BOSS 主账号"},{path:"browser.instances.<instance>.profile-color",title:"浏览器 Profile 颜色",purpose:"用六位十六进制颜色标记托管 Chrome Profile,帮助肉眼区分多个窗口。",defaultBehavior:"不配置时按实例顺序自动分配不同颜色。",example:'browser:\n instances:\n boss-a:\n profile-color: "#2563EB"'},{path:"browser.instances.<instance>.window-bounds",title:"窗口位置与大小",purpose:"可选地固定托管浏览器窗口的屏幕位置和尺寸。",defaultBehavior:"整组留空时,多实例可视模式会自动排布窗口。",example:"browser:\n instances:\n boss-a:\n window-bounds:\n x: 0\n y: 0\n width: 960\n height: 900"},{path:"browser.instances.<instance>.window-bounds.x",title:"窗口横向位置",purpose:"设置托管浏览器窗口左上角距主屏左侧的像素数。",defaultBehavior:"整个 `window-bounds` 未设置时,多实例可视模式会自动排布;否则交由系统决定。",example:"browser:\n instances:\n boss-a:\n window-bounds:\n x: 0"},{path:"browser.instances.<instance>.window-bounds.y",title:"窗口纵向位置",purpose:"设置托管浏览器窗口左上角距主屏顶部的像素数。",defaultBehavior:"整个 `window-bounds` 未设置时,多实例可视模式会自动排布;否则交由系统决定。",example:"browser:\n instances:\n boss-a:\n window-bounds:\n y: 0"},{path:"browser.instances.<instance>.window-bounds.width",title:"窗口宽度",purpose:"设置托管浏览器窗口宽度,单位像素,必须大于 0。",defaultBehavior:"整个 `window-bounds` 未设置时,多实例可视模式会自动排布;否则交由系统决定。",example:"browser:\n instances:\n boss-a:\n window-bounds:\n width: 960"},{path:"browser.instances.<instance>.window-bounds.height",title:"窗口高度",purpose:"设置托管浏览器窗口高度,单位像素,必须大于 0。",defaultBehavior:"整个 `window-bounds` 未设置时,多实例可视模式会自动排布;否则交由系统决定。",example:"browser:\n instances:\n boss-a:\n window-bounds:\n height: 900"},{path:"browser.instances.<instance>.tracking-agent-id",title:"招聘事件 Agent ID",purpose:"为该浏览器实例上报的招聘事件指定归因 Agent ID。",defaultBehavior:"不配置时回退到 `RECRUITMENT_EVENTS_DEFAULT_AGENT_ID`;两者都没有时状态标记为未配置。",example:"browser:\n instances:\n boss-a:\n tracking-agent-id: zhipin-boss-a"}];export function listConfigGuidanceEntries(){return CONFIG_GUIDANCE_ENTRIES}export function findConfigGuidance(e){const a=t(e.split("."));return CONFIG_GUIDANCE_ENTRIES.find(e=>n(e.path,a))}function n(e,n){const a=t(e.split("."));return a.length===n.length&&a.every((e,t)=>e.startsWith("<")||e===n[t])}export function flattenAgentEnvDeclarations(e){return[...(e?.required??[]).map(e=>({...e,required:!0})),...(e?.optional??[]).map(e=>({...e,required:!1}))]}export function isSecretEnvDeclaration(e){return e.secret??!0}
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ export declare const runtimeThinkingLevels: readonly ["off", "low", "medium", "high"];
2
3
  export declare const browserWindowBoundsSchema: z.ZodObject<{
3
4
  x: z.ZodOptional<z.ZodNumber>;
4
5
  y: z.ZodOptional<z.ZodNumber>;
@@ -76,23 +77,31 @@ export declare const runtimeApprovalConfigSchema: z.ZodObject<{
76
77
  export declare const runtimeCompactionConfigSchema: z.ZodObject<{
77
78
  enabled: z.ZodDefault<z.ZodBoolean>;
78
79
  strategy: z.ZodDefault<z.ZodEnum<["summarize", "truncate"]>>;
80
+ timeoutMs: z.ZodDefault<z.ZodNumber>;
81
+ thinkingLevel: z.ZodOptional<z.ZodEnum<["off", "low", "medium", "high"]>>;
82
+ maxOutputTokens: z.ZodDefault<z.ZodNumber>;
79
83
  threshold: z.ZodDefault<z.ZodNumber>;
80
84
  keepRecentTurns: z.ZodDefault<z.ZodNumber>;
81
85
  keepRecentTokens: z.ZodDefault<z.ZodNumber>;
82
86
  }, "strip", z.ZodTypeAny, {
87
+ maxOutputTokens: number;
83
88
  enabled: boolean;
84
89
  strategy: "summarize" | "truncate";
90
+ timeoutMs: number;
85
91
  threshold: number;
86
92
  keepRecentTurns: number;
87
93
  keepRecentTokens: number;
94
+ thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
88
95
  }, {
96
+ maxOutputTokens?: number | undefined;
89
97
  enabled?: boolean | undefined;
90
98
  strategy?: "summarize" | "truncate" | undefined;
99
+ timeoutMs?: number | undefined;
100
+ thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
91
101
  threshold?: number | undefined;
92
102
  keepRecentTurns?: number | undefined;
93
103
  keepRecentTokens?: number | undefined;
94
104
  }>;
95
- export declare const runtimeThinkingLevels: readonly ["off", "low", "medium", "high"];
96
105
  export declare const runtimeShellSessionConfigSchema: z.ZodObject<{
97
106
  enabled: z.ZodDefault<z.ZodBoolean>;
98
107
  maxSessions: z.ZodDefault<z.ZodNumber>;
@@ -180,18 +189,27 @@ export declare const runtimeConfigSchema: z.ZodObject<{
180
189
  compaction: z.ZodDefault<z.ZodObject<{
181
190
  enabled: z.ZodDefault<z.ZodBoolean>;
182
191
  strategy: z.ZodDefault<z.ZodEnum<["summarize", "truncate"]>>;
192
+ timeoutMs: z.ZodDefault<z.ZodNumber>;
193
+ thinkingLevel: z.ZodOptional<z.ZodEnum<["off", "low", "medium", "high"]>>;
194
+ maxOutputTokens: z.ZodDefault<z.ZodNumber>;
183
195
  threshold: z.ZodDefault<z.ZodNumber>;
184
196
  keepRecentTurns: z.ZodDefault<z.ZodNumber>;
185
197
  keepRecentTokens: z.ZodDefault<z.ZodNumber>;
186
198
  }, "strip", z.ZodTypeAny, {
199
+ maxOutputTokens: number;
187
200
  enabled: boolean;
188
201
  strategy: "summarize" | "truncate";
202
+ timeoutMs: number;
189
203
  threshold: number;
190
204
  keepRecentTurns: number;
191
205
  keepRecentTokens: number;
206
+ thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
192
207
  }, {
208
+ maxOutputTokens?: number | undefined;
193
209
  enabled?: boolean | undefined;
194
210
  strategy?: "summarize" | "truncate" | undefined;
211
+ timeoutMs?: number | undefined;
212
+ thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
195
213
  threshold?: number | undefined;
196
214
  keepRecentTurns?: number | undefined;
197
215
  keepRecentTokens?: number | undefined;
@@ -261,20 +279,23 @@ export declare const runtimeConfigSchema: z.ZodObject<{
261
279
  defaultYieldMs: number;
262
280
  };
263
281
  };
282
+ thinkingLevel: "off" | "low" | "medium" | "high";
264
283
  maxSteps: number;
265
284
  turnTimeoutMs: number;
266
285
  threadsDir: string;
267
- thinkingLevel: "off" | "low" | "medium" | "high";
268
286
  approval: {
269
287
  default: "auto" | "guarded" | "deny";
270
288
  overrides: Record<string, "auto" | "deny" | "confirm">;
271
289
  };
272
290
  compaction: {
291
+ maxOutputTokens: number;
273
292
  enabled: boolean;
274
293
  strategy: "summarize" | "truncate";
294
+ timeoutMs: number;
275
295
  threshold: number;
276
296
  keepRecentTurns: number;
277
297
  keepRecentTokens: number;
298
+ thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
278
299
  };
279
300
  model?: string | undefined;
280
301
  provider?: string | undefined;
@@ -296,18 +317,21 @@ export declare const runtimeConfigSchema: z.ZodObject<{
296
317
  } | undefined;
297
318
  model?: string | undefined;
298
319
  provider?: string | undefined;
320
+ thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
299
321
  maxSteps?: number | undefined;
300
322
  turnTimeoutMs?: number | undefined;
301
323
  threadsDir?: string | undefined;
302
324
  contextWindow?: number | undefined;
303
- thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
304
325
  approval?: {
305
326
  default?: "auto" | "guarded" | "deny" | undefined;
306
327
  overrides?: Record<string, "auto" | "deny" | "confirm"> | undefined;
307
328
  } | undefined;
308
329
  compaction?: {
330
+ maxOutputTokens?: number | undefined;
309
331
  enabled?: boolean | undefined;
310
332
  strategy?: "summarize" | "truncate" | undefined;
333
+ timeoutMs?: number | undefined;
334
+ thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
311
335
  threshold?: number | undefined;
312
336
  keepRecentTurns?: number | undefined;
313
337
  keepRecentTokens?: number | undefined;
@@ -749,18 +773,27 @@ export declare const rollConfigSchema: z.ZodObject<{
749
773
  compaction: z.ZodDefault<z.ZodObject<{
750
774
  enabled: z.ZodDefault<z.ZodBoolean>;
751
775
  strategy: z.ZodDefault<z.ZodEnum<["summarize", "truncate"]>>;
776
+ timeoutMs: z.ZodDefault<z.ZodNumber>;
777
+ thinkingLevel: z.ZodOptional<z.ZodEnum<["off", "low", "medium", "high"]>>;
778
+ maxOutputTokens: z.ZodDefault<z.ZodNumber>;
752
779
  threshold: z.ZodDefault<z.ZodNumber>;
753
780
  keepRecentTurns: z.ZodDefault<z.ZodNumber>;
754
781
  keepRecentTokens: z.ZodDefault<z.ZodNumber>;
755
782
  }, "strip", z.ZodTypeAny, {
783
+ maxOutputTokens: number;
756
784
  enabled: boolean;
757
785
  strategy: "summarize" | "truncate";
786
+ timeoutMs: number;
758
787
  threshold: number;
759
788
  keepRecentTurns: number;
760
789
  keepRecentTokens: number;
790
+ thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
761
791
  }, {
792
+ maxOutputTokens?: number | undefined;
762
793
  enabled?: boolean | undefined;
763
794
  strategy?: "summarize" | "truncate" | undefined;
795
+ timeoutMs?: number | undefined;
796
+ thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
764
797
  threshold?: number | undefined;
765
798
  keepRecentTurns?: number | undefined;
766
799
  keepRecentTokens?: number | undefined;
@@ -830,20 +863,23 @@ export declare const rollConfigSchema: z.ZodObject<{
830
863
  defaultYieldMs: number;
831
864
  };
832
865
  };
866
+ thinkingLevel: "off" | "low" | "medium" | "high";
833
867
  maxSteps: number;
834
868
  turnTimeoutMs: number;
835
869
  threadsDir: string;
836
- thinkingLevel: "off" | "low" | "medium" | "high";
837
870
  approval: {
838
871
  default: "auto" | "guarded" | "deny";
839
872
  overrides: Record<string, "auto" | "deny" | "confirm">;
840
873
  };
841
874
  compaction: {
875
+ maxOutputTokens: number;
842
876
  enabled: boolean;
843
877
  strategy: "summarize" | "truncate";
878
+ timeoutMs: number;
844
879
  threshold: number;
845
880
  keepRecentTurns: number;
846
881
  keepRecentTokens: number;
882
+ thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
847
883
  };
848
884
  model?: string | undefined;
849
885
  provider?: string | undefined;
@@ -865,18 +901,21 @@ export declare const rollConfigSchema: z.ZodObject<{
865
901
  } | undefined;
866
902
  model?: string | undefined;
867
903
  provider?: string | undefined;
904
+ thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
868
905
  maxSteps?: number | undefined;
869
906
  turnTimeoutMs?: number | undefined;
870
907
  threadsDir?: string | undefined;
871
908
  contextWindow?: number | undefined;
872
- thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
873
909
  approval?: {
874
910
  default?: "auto" | "guarded" | "deny" | undefined;
875
911
  overrides?: Record<string, "auto" | "deny" | "confirm"> | undefined;
876
912
  } | undefined;
877
913
  compaction?: {
914
+ maxOutputTokens?: number | undefined;
878
915
  enabled?: boolean | undefined;
879
916
  strategy?: "summarize" | "truncate" | undefined;
917
+ timeoutMs?: number | undefined;
918
+ thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
880
919
  threshold?: number | undefined;
881
920
  keepRecentTurns?: number | undefined;
882
921
  keepRecentTokens?: number | undefined;
@@ -1198,20 +1237,23 @@ export declare const rollConfigSchema: z.ZodObject<{
1198
1237
  defaultYieldMs: number;
1199
1238
  };
1200
1239
  };
1240
+ thinkingLevel: "off" | "low" | "medium" | "high";
1201
1241
  maxSteps: number;
1202
1242
  turnTimeoutMs: number;
1203
1243
  threadsDir: string;
1204
- thinkingLevel: "off" | "low" | "medium" | "high";
1205
1244
  approval: {
1206
1245
  default: "auto" | "guarded" | "deny";
1207
1246
  overrides: Record<string, "auto" | "deny" | "confirm">;
1208
1247
  };
1209
1248
  compaction: {
1249
+ maxOutputTokens: number;
1210
1250
  enabled: boolean;
1211
1251
  strategy: "summarize" | "truncate";
1252
+ timeoutMs: number;
1212
1253
  threshold: number;
1213
1254
  keepRecentTurns: number;
1214
1255
  keepRecentTokens: number;
1256
+ thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
1215
1257
  };
1216
1258
  model?: string | undefined;
1217
1259
  provider?: string | undefined;
@@ -1289,18 +1331,21 @@ export declare const rollConfigSchema: z.ZodObject<{
1289
1331
  } | undefined;
1290
1332
  model?: string | undefined;
1291
1333
  provider?: string | undefined;
1334
+ thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
1292
1335
  maxSteps?: number | undefined;
1293
1336
  turnTimeoutMs?: number | undefined;
1294
1337
  threadsDir?: string | undefined;
1295
1338
  contextWindow?: number | undefined;
1296
- thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
1297
1339
  approval?: {
1298
1340
  default?: "auto" | "guarded" | "deny" | undefined;
1299
1341
  overrides?: Record<string, "auto" | "deny" | "confirm"> | undefined;
1300
1342
  } | undefined;
1301
1343
  compaction?: {
1344
+ maxOutputTokens?: number | undefined;
1302
1345
  enabled?: boolean | undefined;
1303
1346
  strategy?: "summarize" | "truncate" | undefined;
1347
+ timeoutMs?: number | undefined;
1348
+ thinkingLevel?: "off" | "low" | "medium" | "high" | undefined;
1304
1349
  threshold?: number | undefined;
1305
1350
  keepRecentTurns?: number | undefined;
1306
1351
  keepRecentTokens?: number | undefined;
@@ -1 +1 @@
1
- import{z as e}from"zod";const t=["zhipin","yupao"],n=["managed-cdp","remote-cdp","existing-session"],o=["chrome","chromium","msedge"],i=["guarded","auto","deny"],a=["auto","confirm","deny"],r=["summarize","truncate"],s=e.string().trim().regex(/^#[\da-fA-F]{6}$/,"profileColor must be a hex RGB color such as #2563EB").transform(e=>e.toUpperCase());export const browserWindowBoundsSchema=e.object({x:e.number().int().optional(),y:e.number().int().optional(),width:e.number().int().positive().optional(),height:e.number().int().positive().optional()});export const providerConfigSchema=e.object({apiKey:e.string(),baseUrl:e.string().optional()});export const llmConfigSchema=e.object({defaultProvider:e.string(),defaultModel:e.string(),providers:e.record(e.string(),providerConfigSchema)});export const askConfigSchema=e.object({llmModel:e.string().optional(),confirmThreshold:e.number().optional()});export const runtimeApprovalConfigSchema=e.object({default:e.enum(i).default("guarded"),overrides:e.record(e.string(),e.enum(a)).default({})});export const runtimeCompactionConfigSchema=e.object({enabled:e.boolean().default(!0),strategy:e.enum(r).default("summarize"),threshold:e.number().min(.1).max(.95).default(.75),keepRecentTurns:e.number().int().min(1).default(4),keepRecentTokens:e.number().int().min(1).default(32e3)});export const runtimeThinkingLevels=["off","low","medium","high"];export const runtimeShellSessionConfigSchema=e.object({enabled:e.boolean().default(!1),maxSessions:e.number().int().min(1).max(64).default(8),defaultYieldMs:e.number().int().min(250).max(3e4).default(1e4),maxOutputTokens:e.number().int().min(256).default(1e4)});export const runtimeShellConfigSchema=e.object({enabled:e.boolean().default(!1),autoApproveSafe:e.boolean().default(!0),defaultTimeoutMs:e.number().int().min(1e3).max(6e5).default(1e4),maxTimeoutMs:e.number().int().min(1e3).max(6e5).default(6e5),maxCaptureBytes:e.number().int().min(16384).default(1048576),maxModelOutputChars:e.number().int().min(1e3).default(16e3),session:runtimeShellSessionConfigSchema.default({})});export const runtimeConfigSchema=e.object({provider:e.string().optional(),model:e.string().optional(),maxSteps:e.number().int().min(1).default(80),turnTimeoutMs:e.number().int().min(1e4).default(3e5),threadsDir:e.string().default("~/.roll-agent/threads"),contextWindow:e.number().int().min(1).optional(),thinkingLevel:e.enum(runtimeThinkingLevels).default("medium"),approval:runtimeApprovalConfigSchema.default({}),compaction:runtimeCompactionConfigSchema.default({}),shell:runtimeShellConfigSchema.default({})});export const skillsConfigSchema=e.object({dirs:e.array(e.string().trim().min(1)).default([])});export const agentsConfigSchema=e.object({dataDir:e.string(),env:e.record(e.string(),e.record(e.string(),e.string())).optional()});export const installConfigSchema=e.object({registry:e.string().trim().url().optional(),fetchRetries:e.number().int().min(0).max(10).default(3),preferOffline:e.boolean().default(!1),networkTimeoutMs:e.number().int().min(1e4).default(12e4)});export const browserInstanceConfigSchema=e.object({platform:e.enum(t).optional(),mode:e.enum(n).default("managed-cdp"),headless:e.boolean().optional(),cdpUrl:e.string().optional(),cdpHost:e.string().default("127.0.0.1"),cdpPort:e.number().int().min(1).max(65535).optional(),channel:e.enum(o).default("chrome"),executablePath:e.string().optional(),userDataDir:e.string().trim().min(1),sessionsDir:e.string().trim().min(1).optional(),args:e.array(e.string()).optional(),profileName:e.string().trim().min(1).optional(),profileColor:s.optional(),windowBounds:browserWindowBoundsSchema.optional(),trackingAgentId:e.string().trim().min(1).optional()}).superRefine((t,n)=>{"managed-cdp"===t.mode&&void 0===t.cdpPort&&n.addIssue({code:e.ZodIssueCode.custom,path:["cdpPort"],message:"managed-cdp browser instance requires cdpPort"}),"remote-cdp"!==t.mode&&"existing-session"!==t.mode||void 0!==t.cdpUrl||n.addIssue({code:e.ZodIssueCode.custom,path:["cdpUrl"],message:`${t.mode} browser instance requires cdpUrl`})});export const browserConfigSchema=e.object({defaultInstance:e.string().trim().min(1).optional(),instances:e.record(e.string(),browserInstanceConfigSchema).default({})}).superRefine((t,n)=>{const o=Object.entries(t.instances);void 0!==t.defaultInstance&&void 0===t.instances[t.defaultInstance]&&n.addIssue({code:e.ZodIssueCode.custom,path:["defaultInstance"],message:`defaultInstance "${t.defaultInstance}" is not declared in browser.instances`});const i=new Map,a=new Map;for(const[t,r]of o){if(void 0!==r.cdpPort){const o=i.get(r.cdpPort);void 0!==o?n.addIssue({code:e.ZodIssueCode.custom,path:["instances",t,"cdpPort"],message:`cdpPort ${String(r.cdpPort)} is already used by browser instance "${o}"`}):i.set(r.cdpPort,t)}const o=a.get(r.userDataDir);void 0!==o?n.addIssue({code:e.ZodIssueCode.custom,path:["instances",t,"userDataDir"],message:`userDataDir is already used by browser instance "${o}"`}):a.set(r.userDataDir,t)}});export const rollConfigSchema=e.object({llm:llmConfigSchema,ask:askConfigSchema,runtime:runtimeConfigSchema.default({}),skills:skillsConfigSchema.default({}),agents:agentsConfigSchema,install:installConfigSchema.default({}),browser:browserConfigSchema.default({})});
1
+ import{z as e}from"zod";const t=["zhipin","yupao"],n=["managed-cdp","remote-cdp","existing-session"],o=["chrome","chromium","msedge"],i=["guarded","auto","deny"],a=["auto","confirm","deny"],r=["summarize","truncate"];export const runtimeThinkingLevels=["off","low","medium","high"];const s=e.string().trim().regex(/^#[\da-fA-F]{6}$/,"profileColor must be a hex RGB color such as #2563EB").transform(e=>e.toUpperCase());export const browserWindowBoundsSchema=e.object({x:e.number().int().optional(),y:e.number().int().optional(),width:e.number().int().positive().optional(),height:e.number().int().positive().optional()});export const providerConfigSchema=e.object({apiKey:e.string(),baseUrl:e.string().optional()});export const llmConfigSchema=e.object({defaultProvider:e.string(),defaultModel:e.string(),providers:e.record(e.string(),providerConfigSchema)});export const askConfigSchema=e.object({llmModel:e.string().optional(),confirmThreshold:e.number().optional()});export const runtimeApprovalConfigSchema=e.object({default:e.enum(i).default("guarded"),overrides:e.record(e.string(),e.enum(a)).default({})});export const runtimeCompactionConfigSchema=e.object({enabled:e.boolean().default(!0),strategy:e.enum(r).default("summarize"),timeoutMs:e.number().int().min(1e4).max(6e5).default(12e4),thinkingLevel:e.enum(runtimeThinkingLevels).optional(),maxOutputTokens:e.number().int().min(2048).max(32768).default(8192),threshold:e.number().min(.1).max(.95).default(.75),keepRecentTurns:e.number().int().min(1).default(4),keepRecentTokens:e.number().int().min(1).default(32e3)});export const runtimeShellSessionConfigSchema=e.object({enabled:e.boolean().default(!1),maxSessions:e.number().int().min(1).max(64).default(8),defaultYieldMs:e.number().int().min(250).max(3e4).default(1e4),maxOutputTokens:e.number().int().min(256).default(1e4)});export const runtimeShellConfigSchema=e.object({enabled:e.boolean().default(!1),autoApproveSafe:e.boolean().default(!0),defaultTimeoutMs:e.number().int().min(1e3).max(6e5).default(1e4),maxTimeoutMs:e.number().int().min(1e3).max(6e5).default(6e5),maxCaptureBytes:e.number().int().min(16384).default(1048576),maxModelOutputChars:e.number().int().min(1e3).default(16e3),session:runtimeShellSessionConfigSchema.default({})});export const runtimeConfigSchema=e.object({provider:e.string().optional(),model:e.string().optional(),maxSteps:e.number().int().min(1).default(80),turnTimeoutMs:e.number().int().min(1e4).default(3e5),threadsDir:e.string().default("~/.roll-agent/threads"),contextWindow:e.number().int().min(1).optional(),thinkingLevel:e.enum(runtimeThinkingLevels).default("medium"),approval:runtimeApprovalConfigSchema.default({}),compaction:runtimeCompactionConfigSchema.default({}),shell:runtimeShellConfigSchema.default({})});export const skillsConfigSchema=e.object({dirs:e.array(e.string().trim().min(1)).default([])});export const agentsConfigSchema=e.object({dataDir:e.string(),env:e.record(e.string(),e.record(e.string(),e.string())).optional()});export const installConfigSchema=e.object({registry:e.string().trim().url().optional(),fetchRetries:e.number().int().min(0).max(10).default(3),preferOffline:e.boolean().default(!1),networkTimeoutMs:e.number().int().min(1e4).default(12e4)});export const browserInstanceConfigSchema=e.object({platform:e.enum(t).optional(),mode:e.enum(n).default("managed-cdp"),headless:e.boolean().optional(),cdpUrl:e.string().optional(),cdpHost:e.string().default("127.0.0.1"),cdpPort:e.number().int().min(1).max(65535).optional(),channel:e.enum(o).default("chrome"),executablePath:e.string().optional(),userDataDir:e.string().trim().min(1),sessionsDir:e.string().trim().min(1).optional(),args:e.array(e.string()).optional(),profileName:e.string().trim().min(1).optional(),profileColor:s.optional(),windowBounds:browserWindowBoundsSchema.optional(),trackingAgentId:e.string().trim().min(1).optional()}).superRefine((t,n)=>{"managed-cdp"===t.mode&&void 0===t.cdpPort&&n.addIssue({code:e.ZodIssueCode.custom,path:["cdpPort"],message:"managed-cdp browser instance requires cdpPort"}),"remote-cdp"!==t.mode&&"existing-session"!==t.mode||void 0!==t.cdpUrl||n.addIssue({code:e.ZodIssueCode.custom,path:["cdpUrl"],message:`${t.mode} browser instance requires cdpUrl`})});export const browserConfigSchema=e.object({defaultInstance:e.string().trim().min(1).optional(),instances:e.record(e.string(),browserInstanceConfigSchema).default({})}).superRefine((t,n)=>{const o=Object.entries(t.instances);void 0!==t.defaultInstance&&void 0===t.instances[t.defaultInstance]&&n.addIssue({code:e.ZodIssueCode.custom,path:["defaultInstance"],message:`defaultInstance "${t.defaultInstance}" is not declared in browser.instances`});const i=new Map,a=new Map;for(const[t,r]of o){if(void 0!==r.cdpPort){const o=i.get(r.cdpPort);void 0!==o?n.addIssue({code:e.ZodIssueCode.custom,path:["instances",t,"cdpPort"],message:`cdpPort ${String(r.cdpPort)} is already used by browser instance "${o}"`}):i.set(r.cdpPort,t)}const o=a.get(r.userDataDir);void 0!==o?n.addIssue({code:e.ZodIssueCode.custom,path:["instances",t,"userDataDir"],message:`userDataDir is already used by browser instance "${o}"`}):a.set(r.userDataDir,t)}});export const rollConfigSchema=e.object({llm:llmConfigSchema,ask:askConfigSchema,runtime:runtimeConfigSchema.default({}),skills:skillsConfigSchema.default({}),agents:agentsConfigSchema,install:installConfigSchema.default({}),browser:browserConfigSchema.default({})});
@@ -1,11 +1,12 @@
1
- import type { LanguageModelV4, SharedV4ProviderOptions } from "@ai-sdk/provider";
1
+ import type { LanguageModelV4, LanguageModelV4CallOptions, SharedV4ProviderOptions } from "@ai-sdk/provider";
2
2
  import { runtimeThinkingLevels } from "../config/schema.ts";
3
3
  export type ThinkingLevel = (typeof runtimeThinkingLevels)[number];
4
+ export type UnifiedReasoning = NonNullable<LanguageModelV4CallOptions["reasoning"]>;
4
5
  export declare function thinkingProviderOptions(providerName: string, modelName: string, level: ThinkingLevel): SharedV4ProviderOptions | undefined;
5
6
  /**
6
7
  * 根据 provider 名称创建 AI SDK LanguageModel 实例。
7
8
  *
8
- * 支持: anthropic, openai, deepseek, qwen
9
+ * 支持: anthropic, openai, deepseek, qwen, xai
9
10
  */
10
11
  export declare function createProviderModel(providerName: string, modelName: string, apiKey: string, baseURL?: string): LanguageModelV4;
11
12
  /** generateText 调用目的 */
@@ -13,6 +14,7 @@ export type LLMCallPurpose = "structured-output" | "text" | "sampling" | "chat";
13
14
  /** resolveLLMCall 的返回值 */
14
15
  export interface ResolvedLLMCall {
15
16
  readonly model: LanguageModelV4;
17
+ readonly reasoning?: UnifiedReasoning;
16
18
  readonly providerOptions?: SharedV4ProviderOptions;
17
19
  }
18
20
  /**
@@ -27,8 +29,8 @@ export declare function toSamplingConnectOptions(call: ResolvedLLMCall | undefin
27
29
  /**
28
30
  * 按 provider + 调用目的解析 generateText 的完整调用上下文。
29
31
  *
30
- * structured-output 场景下,对 qwen provider 自动注入 enableThinking: false,
31
- * 因为阿里云 thinking mode 不支持 structured output
32
+ * structured-output 场景优先使用 AI SDK 顶层 reasoning 统一语义;qwen 是例外,
33
+ * 因为阿里云 thinking mode 不支持 structured output,必须通过 providerOptions 强制关闭。
32
34
  *
33
35
  * chat 与 sampling 场景下都是纯文本 generateText 调用,复用同一套
34
36
  * thinkingProviderOptions 映射注入 reasoning/thinking effort。
@@ -1 +1 @@
1
- import{createAlibaba as e}from"@ai-sdk/alibaba";import{createAnthropic as i}from"@ai-sdk/anthropic";import{createOpenAI as o}from"@ai-sdk/openai";import{createDeepSeek as n}from"@ai-sdk/deepseek";import{runtimeThinkingLevels as t}from"../config/schema.js";const r={low:2048,medium:8192,high:16384},a=["gpt-5.1","gpt-5.2","gpt-5.3","gpt-5.4"];function p(e){return a.some(i=>e.startsWith(i))}function s(e){const i=/^claude-[a-z]+-(\d+)(?:-(\d+))?(?:\b|-)/.exec(e),o=i?.[1];if(!o)return!1;const n=Number(o),t=i?.[2],r=void 0!==t&&t.length<=2?Number(t):0;return n>4||4===n&&r>=6}export function thinkingProviderOptions(e,i,o){return"openai"===e?"off"===o?p(i)?{openai:{reasoningEffort:"none"}}:void 0:{openai:{reasoningEffort:o}}:"anthropic"===e?"off"===o?{anthropic:{thinking:{type:"disabled"}}}:s(i)?{anthropic:{thinking:{type:"adaptive"},effort:o}}:{anthropic:{thinking:{type:"enabled",budgetTokens:r[o]}}}:"qwen"===e?"off"===o?{alibaba:{enableThinking:!1}}:{alibaba:{enableThinking:!0,thinkingBudget:r[o]}}:"deepseek"===e?{deepseek:{thinking:{type:"off"===o?"disabled":"enabled"}}}:void 0}const d="https://dashscope.aliyuncs.com/compatible-mode/v1",c={anthropic:(e,{apiKey:o,baseURL:n})=>i({apiKey:o,...n?{baseURL:n}:{}})(e),openai:(e,{apiKey:i,baseURL:n})=>o({apiKey:i,...n?{baseURL:n}:{}})(e),deepseek:(e,{apiKey:i,baseURL:o})=>n({apiKey:i,...o?{baseURL:o}:{}})(e),qwen:(i,{apiKey:o,baseURL:n})=>e({apiKey:o,baseURL:n??d})(i)};export function createProviderModel(e,i,o,n){const t=c[e];if(!t){const i=Object.keys(c).join(", ");throw new Error(`Unknown LLM provider "${e}". Supported: ${i}`)}return t(i,{apiKey:o,baseURL:n})}export function toSamplingConnectOptions(e){return e?{samplingModel:e.model,...e.providerOptions?{samplingProviderOptions:e.providerOptions}:{}}:{}}export function resolveLLMCall(e,i,o,n,t,r="medium"){const a=createProviderModel(e,i,o,t);if("structured-output"===n&&"qwen"===e)return{model:a,providerOptions:{alibaba:{enableThinking:!1}}};if("chat"===n||"sampling"===n){const o=thinkingProviderOptions(e,i,r);return"openai"===e&&t?{model:a,providerOptions:{...o??{},openai:{...o?.openai??{},store:!1}}}:o?{model:a,providerOptions:o}:{model:a}}return{model:a}}
1
+ import{createAlibaba as e}from"@ai-sdk/alibaba";import{createAnthropic as n}from"@ai-sdk/anthropic";import{createOpenAI as o}from"@ai-sdk/openai";import{createDeepSeek as i}from"@ai-sdk/deepseek";import{createXai as t}from"@ai-sdk/xai";import{runtimeThinkingLevels as r}from"../config/schema.js";const a={low:2048,medium:8192,high:16384},s=["gpt-5.1","gpt-5.2","gpt-5.3","gpt-5.4","gpt-5.5"],p=["o1","o3","o4-mini"],u="grok-4.20",f="-multi-agent";function d(e){return s.some(n=>e.startsWith(n))}function c(e){return p.some(n=>e.startsWith(n))||e.startsWith("gpt-5")&&!e.startsWith("gpt-5-chat")}function l(e){const n=/^claude-[a-z]+-(\d+)(?:-(\d+))?(?:\b|-)/.exec(e),o=n?.[1];if(!o)return!1;const i=Number(o),t=n?.[2],r=void 0!==t&&t.length<=2?Number(t):0;return i>4||4===i&&r>=6}function m(e){return"grok-3"===e||"grok-4-1"===e||e.includes("-non-reasoning")}function g(e){return!h(e)}function h(e){return e.startsWith(u)&&!e.includes(f)}function b(e){return"grok-4.5"===e||e.includes(f)||h(e)&&!m(e)}export function thinkingProviderOptions(e,n,o){if("openai"===e)return"off"===o?d(n)?{openai:{reasoningEffort:"none"}}:void 0:{openai:{reasoningEffort:o}};if("anthropic"===e)return"off"===o?{anthropic:{thinking:{type:"disabled"}}}:l(n)?{anthropic:{thinking:{type:"adaptive"},effort:o}}:{anthropic:{thinking:{type:"enabled",budgetTokens:a[o]}}};if("qwen"===e)return"off"===o?{alibaba:{enableThinking:!1}}:{alibaba:{enableThinking:!0,thinkingBudget:a[o]}};if("xai"===e){if(m(n))return;return g(n)?"off"===o?{xai:{reasoningEffort:"none"}}:{xai:{reasoningEffort:o,reasoningSummary:"auto"}}:"off"===o?void 0:{xai:{reasoningSummary:"auto"}}}return"deepseek"===e?{deepseek:{thinking:{type:"off"===o?"disabled":"enabled"}}}:void 0}const k="https://dashscope.aliyuncs.com/compatible-mode/v1",v={anthropic:(e,{apiKey:o,baseURL:i})=>n({apiKey:o,...i?{baseURL:i}:{}})(e),openai:(e,{apiKey:n,baseURL:i})=>o({apiKey:n,...i?{baseURL:i}:{}})(e),deepseek:(e,{apiKey:n,baseURL:o})=>i({apiKey:n,...o?{baseURL:o}:{}})(e),qwen:(n,{apiKey:o,baseURL:i})=>e({apiKey:o,baseURL:i??k})(n),xai:(e,{apiKey:n,baseURL:o})=>t({apiKey:n,...o?{baseURL:o}:{}})(e)};export function createProviderModel(e,n,o,i){const t=v[e];if(!t){const n=Object.keys(v).join(", ");throw new Error(`Unknown LLM provider "${e}". Supported: ${n}`)}return t(n,{apiKey:o,baseURL:i})}function y(e){return"off"===e?"none":e}function w(e,n,o){if("openai"===e){if(!c(n))return;if("off"!==o)return y(o);if(d(n))return"none";throw new Error(`OpenAI model "${n}" cannot disable reasoning for structured output; set runtime.compaction.thinking-level to low or higher`)}if("xai"===e){if(m(n))return;if(h(n)){if("off"===o)throw new Error(`xAI model "${n}" cannot disable reasoning for structured output; set runtime.compaction.thinking-level to low or higher`);return}if("off"===o&&b(n))throw new Error(`xAI model "${n}" cannot disable reasoning for structured output; set runtime.compaction.thinking-level to low or higher`)}return y(o)}export function toSamplingConnectOptions(e){return e?{samplingModel:e.model,...e.providerOptions?{samplingProviderOptions:e.providerOptions}:{}}:{}}export function resolveLLMCall(e,n,o,i,t,r="medium"){const a=createProviderModel(e,n,o,t);if("structured-output"===i){if("qwen"===e)return{model:a,providerOptions:{alibaba:{enableThinking:!1}}};const o=w(e,n,r);return o?{model:a,reasoning:o}:{model:a}}if("chat"===i||"sampling"===i){const o=thinkingProviderOptions(e,n,r);return"openai"===e&&t?{model:a,providerOptions:{...o??{},openai:{...o?.openai??{},store:!1}}}:o?{model:a,providerOptions:o}:{model:a}}return{model:a}}