@roll-agent/core 0.10.1 → 0.12.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 (64) hide show
  1. package/bin/roll.js +56 -1
  2. package/dist/cli/chat/ink/app.d.ts +15 -0
  3. package/dist/cli/chat/ink/app.js +1 -0
  4. package/dist/cli/chat/ink/commands.d.ts +6 -0
  5. package/dist/cli/chat/ink/commands.js +1 -0
  6. package/dist/cli/chat/ink/confirm-select.d.ts +6 -0
  7. package/dist/cli/chat/ink/confirm-select.js +1 -0
  8. package/dist/cli/chat/ink/history-from-messages.d.ts +3 -0
  9. package/dist/cli/chat/ink/history-from-messages.js +1 -0
  10. package/dist/cli/chat/ink/history-item.d.ts +5 -0
  11. package/dist/cli/chat/ink/history-item.js +1 -0
  12. package/dist/cli/chat/ink/live-region.d.ts +5 -0
  13. package/dist/cli/chat/ink/live-region.js +1 -0
  14. package/dist/cli/chat/ink/markdown.d.ts +4 -0
  15. package/dist/cli/chat/ink/markdown.js +1 -0
  16. package/dist/cli/chat/ink/run-ink-repl.d.ts +13 -0
  17. package/dist/cli/chat/ink/run-ink-repl.js +1 -0
  18. package/dist/cli/chat/ink/slash-popup.d.ts +7 -0
  19. package/dist/cli/chat/ink/slash-popup.js +1 -0
  20. package/dist/cli/chat/ink/spinner.d.ts +2 -0
  21. package/dist/cli/chat/ink/spinner.js +1 -0
  22. package/dist/cli/chat/ink/state.d.ts +95 -0
  23. package/dist/cli/chat/ink/state.js +1 -0
  24. package/dist/cli/chat/ink/status-line.d.ts +5 -0
  25. package/dist/cli/chat/ink/status-line.js +1 -0
  26. package/dist/cli/chat/ink/text-prompt.d.ts +12 -0
  27. package/dist/cli/chat/ink/text-prompt.js +1 -0
  28. package/dist/cli/chat/ink/thinking-text.d.ts +9 -0
  29. package/dist/cli/chat/ink/thinking-text.js +1 -0
  30. package/dist/cli/chat/ink/thinking.d.ts +3 -0
  31. package/dist/cli/chat/ink/thinking.js +1 -0
  32. package/dist/cli/chat/ink/tool-label.d.ts +4 -0
  33. package/dist/cli/chat/ink/tool-label.js +1 -0
  34. package/dist/cli/chat/ink/use-session.d.ts +20 -0
  35. package/dist/cli/chat/ink/use-session.js +1 -0
  36. package/dist/cli/chat/title.d.ts +1 -0
  37. package/dist/cli/chat/title.js +1 -0
  38. package/dist/cli/commands/browser-stop.d.ts +4 -4
  39. package/dist/cli/commands/chat.d.ts +27 -0
  40. package/dist/cli/commands/chat.js +1 -1
  41. package/dist/cli/commands/config-guidance.d.ts +12 -0
  42. package/dist/cli/commands/config-guidance.js +1 -1
  43. package/dist/cli/utils/chat-renderer.d.ts +21 -0
  44. package/dist/cli/utils/chat-renderer.js +1 -0
  45. package/dist/cli/utils/output.d.ts +1 -0
  46. package/dist/cli/utils/output.js +1 -1
  47. package/dist/cli/utils/package-manager.d.ts +5 -0
  48. package/dist/cli/utils/package-manager.js +1 -1
  49. package/dist/cli/utils/token-format.d.ts +18 -0
  50. package/dist/cli/utils/token-format.js +1 -0
  51. package/dist/cli/utils/tool-format.d.ts +1 -0
  52. package/dist/cli/utils/tool-format.js +1 -0
  53. package/dist/config/defaults.js +1 -1
  54. package/dist/config/key-codec.js +1 -1
  55. package/dist/config/loader.js +1 -1
  56. package/dist/config/runtime-env.d.ts +16 -16
  57. package/dist/config/schema.d.ts +246 -22
  58. package/dist/config/schema.js +1 -1
  59. package/dist/llm/providers.d.ts +5 -2
  60. package/dist/llm/providers.js +1 -1
  61. package/dist/mcp/client-manager.d.ts +2 -0
  62. package/dist/mcp/client-manager.js +1 -1
  63. package/dist/types/chat.d.ts +23 -0
  64. package/package.json +40 -6
@@ -76,4 +76,9 @@ export declare function formatPackageManagerCommand(spec: PackageManagerRunSpec)
76
76
  export declare function isLikelyNetworkError(error: unknown): boolean;
77
77
  /** 网络/超时类错误才值得对整条命令重试。 */
78
78
  export declare function isRetryablePackageManagerError(error: unknown): boolean;
79
+ /**
80
+ * npm 新 package / 新 scoped package 发布后,registry edge 有时会短暂返回 package
81
+ * metadata 404。只对 @roll-agent scope 放行重试,避免把普通包名写错也当成网络问题。
82
+ */
83
+ export declare function isLikelyRollAgentRegistryPropagationError(error: unknown): boolean;
79
84
  export declare function formatPackageManagerError(spec: PackageManagerRunSpec, error: unknown, platform?: NodeJS.Platform): string;
@@ -1 +1 @@
1
- import{execFile as e}from"node:child_process";import{existsSync as r,readFileSync as n}from"node:fs";import{resolve as t}from"node:path";import{promisify as o}from"node:util";const a=o(e),i=67108864;export const PACKAGE_MANAGER_COMMANDS=["bun","npm","pnpm","yarn"];export function detectInstallCommand(e){const n=t(e,"package.json");if(r(n)){const e=g(n);if(e)return{command:e,args:["install"]}}const o=[["pnpm-lock.yaml","pnpm"],["package-lock.json","npm"],["npm-shrinkwrap.json","npm"],["yarn.lock","yarn"],["bun.lock","bun"],["bun.lockb","bun"]];for(const[n,a]of o)if(r(t(e,n)))return{command:a,args:["install"]}}export function createInstallCommand(e="pnpm"){return{command:e,args:["install"]}}export async function runPackageManager(e,r={}){const{platform:n,...t}=r,o=createPackageManagerExecInvocation(e,n??process.platform),s=await a(o.file,[...o.args],{maxBuffer:i,...t,encoding:"utf-8",...o.shell?{shell:o.shell}:{}});return{stdout:s.stdout,stderr:s.stderr}}function s(e){return new Promise(r=>setTimeout(r,e))}export async function runPackageManagerWithRetry(e,r={},n){const t=Math.max(1,n.attempts),o=n.isRetryable??isRetryablePackageManagerError;let a;for(let i=1;i<=t;i+=1)try{return await runPackageManager(e,r)}catch(e){a=e;if(!(i<t)||!o(e))throw e;const r=n.backoffMs??[],c=r[i-1]??r[r.length-1]??2e3;n.onRetry?.({attempt:i,error:e,delayMs:c}),await s(c)}throw a}export function buildNpmRetryPolicy(e){const r=Math.min(Math.max(e,0)+1,3);return{attempts:r,backoffMs:[2e3,5e3].slice(0,Math.max(r-1,0)),isRetryable:isRetryablePackageManagerError}}export function createPackageManagerExecInvocation(e,r=process.platform){return shouldRunPackageManagerViaShell(r)?{file:c(),args:["/d","/s","/c",E(e)],shell:!1}:{file:e.command,args:e.args,shell:!1}}export function shouldRunPackageManagerViaShell(e){return"win32"===e}function c(){const e=process.env.ComSpec??process.env.COMSPEC;return e&&e.trim().length>0?e:"cmd.exe"}export function npmInstallNetworkArgs(e={}){const r=["--no-audit","--no-fund"];return e.registry&&r.push(`--registry=${e.registry}`),void 0!==e.fetchRetries&&r.push(`--fetch-retries=${String(e.fetchRetries)}`),e.preferOffline&&r.push("--prefer-offline"),r}export function npmViewNetworkArgs(e={}){const r=[];return e.registry&&r.push(`--registry=${e.registry}`),void 0!==e.fetchRetries&&r.push(`--fetch-retries=${String(e.fetchRetries)}`),r}export function formatPackageManagerCommand(e){return[e.command,...e.args].map(d).join(" ")}const u="疑似网络或 npm 源不稳定。可在 roll.config.yaml 配置 `install.registry` 指向可用镜像(如 https://registry.npmmirror.com),或检查 VPN / 代理后重试。",l=new Set(["ETIMEDOUT","ECONNRESET","ECONNREFUSED","ENOTFOUND","EAI_AGAIN","ENETUNREACH","EHOSTUNREACH","EPIPE","ERR_SOCKET_TIMEOUT","UND_ERR_CONNECT_TIMEOUT","UND_ERR_HEADERS_TIMEOUT"]),f=[/\bnetwork\b/i,/ETIMEDOUT/i,/ECONNRESET/i,/ECONNREFUSED/i,/ENOTFOUND/i,/EAI_AGAIN/i,/socket hang up/i,/fetch failed/i,/getaddrinfo/i,/tunneling socket could not be established/i,/request to .+ failed/i,/npm\s+(?:error|ERR!)\s+code\s+E429/i,/\bregistry\b.*\b(timeout|timed out|unreachable)\b/i,/\bproxy\b/i];function m(e){if("object"!=typeof e||null===e)return!1;const r="killed"in e&&!0===e.killed,n="signal"in e&&"SIGTERM"===e.signal,t=!("code"in e)||null===e.code||void 0===e.code;return r&&n&&t}export function isLikelyNetworkError(e){const r=M(e);if(r&&l.has(r))return!0;const n=N(e);return f.some(e=>e.test(n))}export function isRetryablePackageManagerError(e){return m(e)||isLikelyNetworkError(e)}export function formatPackageManagerError(e,r,n=process.platform){const t=formatPackageManagerCommand(e);if(y(e.command,r,n))return[`未找到 ${e.command},无法执行 \`${t}\`。`,"win32"===n?`请确认 ${e.command}.cmd 位于 PATH 中;npm 全局目录通常是 C:\\Users\\<you>\\AppData\\Roaming\\npm。`:`请确认已安装 ${e.command},并且当前 shell 的 PATH 可以访问它。`].join("");if(m(r))return`\`${t}\` 执行超时被终止。${u}`;if(isLikelyNetworkError(r)){return`\`${t}\` 执行失败:${r instanceof Error?r.message:String(r)}\n${u}`}return r instanceof Error?r.message:String(r)}function g(e){try{const r=JSON.parse(n(e,"utf-8"));if("string"!=typeof r.packageManager||0===r.packageManager.length)return;const[t]=r.packageManager.split("@",1);if(!t)return;return p(t)?t:void 0}catch{return}}function p(e){return PACKAGE_MANAGER_COMMANDS.some(r=>r===e)}function d(e){return/\s/.test(e)?JSON.stringify(e):e}function E(e){return[e.command,...e.args].map(h).join(" ")}function h(e){if(0===e.length)return'""';if(/["\r\n]/.test(e))throw new Error(`Unsupported Windows shell argument: ${e}`);return/[\s"&|<>^()%!]/.test(e)?`"${k(e)}"`:e}function k(e){return e.replace(/[\^&|<>%!]/g,e=>`^${e}`)}function y(e,r,n){if("ENOENT"===M(r))return!0;if("win32"!==n)return!1;const t=N(r).toLowerCase();return t.includes(`'${e}' is not recognized`)||t.includes(`"${e}" is not recognized`)||t.includes(`${e} is not recognized`)||t.includes(`'${e}' 不是内部或外部命令`)||t.includes(`"${e}" 不是内部或外部命令`)||t.includes(`${e} 不是内部或外部命令`)}function M(e){if("object"==typeof e&&null!==e&&"code"in e)return"string"==typeof e.code?e.code:void 0}function N(e){return e instanceof Error?e.message:String(e)}
1
+ import{execFile as r}from"node:child_process";import{existsSync as e,readFileSync as n}from"node:fs";import{resolve as t}from"node:path";import{promisify as o}from"node:util";const i=o(r),a=67108864;export const PACKAGE_MANAGER_COMMANDS=["bun","npm","pnpm","yarn"];export function detectInstallCommand(r){const n=t(r,"package.json");if(e(n)){const r=m(n);if(r)return{command:r,args:["install"]}}const o=[["pnpm-lock.yaml","pnpm"],["package-lock.json","npm"],["npm-shrinkwrap.json","npm"],["yarn.lock","yarn"],["bun.lock","bun"],["bun.lockb","bun"]];for(const[n,i]of o)if(e(t(r,n)))return{command:i,args:["install"]}}export function createInstallCommand(r="pnpm"){return{command:r,args:["install"]}}export async function runPackageManager(r,e={}){const{platform:n,...t}=e,o=createPackageManagerExecInvocation(r,n??process.platform),s=await i(o.file,[...o.args],{maxBuffer:a,...t,encoding:"utf-8",...o.shell?{shell:o.shell}:{}});return{stdout:s.stdout,stderr:s.stderr}}function s(r){return new Promise(e=>setTimeout(e,r))}export async function runPackageManagerWithRetry(r,e={},n){const t=Math.max(1,n.attempts),o=n.isRetryable??isRetryablePackageManagerError;let i;for(let a=1;a<=t;a+=1)try{return await runPackageManager(r,e)}catch(r){i=r;if(!(a<t)||!o(r))throw r;const e=n.backoffMs??[],c=e[a-1]??e[e.length-1]??2e3;n.onRetry?.({attempt:a,error:r,delayMs:c}),await s(c)}throw i}export function buildNpmRetryPolicy(r){const e=Math.min(Math.max(r,0)+1,3);return{attempts:e,backoffMs:[2e3,5e3].slice(0,Math.max(e-1,0)),isRetryable:isRetryablePackageManagerError}}export function createPackageManagerExecInvocation(r,e=process.platform){return shouldRunPackageManagerViaShell(e)?{file:c(),args:["/d","/s","/c",E(r)],shell:!1}:{file:r.command,args:r.args,shell:!1}}export function shouldRunPackageManagerViaShell(r){return"win32"===r}function c(){const r=process.env.ComSpec??process.env.COMSPEC;return r&&r.trim().length>0?r:"cmd.exe"}export function npmInstallNetworkArgs(r={}){const e=["--no-audit","--no-fund"];return r.registry&&e.push(`--registry=${r.registry}`),void 0!==r.fetchRetries&&e.push(`--fetch-retries=${String(r.fetchRetries)}`),r.preferOffline&&e.push("--prefer-offline"),e}export function npmViewNetworkArgs(r={}){const e=[];return r.registry&&e.push(`--registry=${r.registry}`),void 0!==r.fetchRetries&&e.push(`--fetch-retries=${String(r.fetchRetries)}`),e}export function formatPackageManagerCommand(r){return[r.command,...r.args].map(d).join(" ")}const u="疑似网络或 npm 源不稳定。可在 roll.config.yaml 配置 `install.registry` 指向可用镜像(如 https://registry.npmmirror.com),或检查 VPN / 代理后重试。",l=new Set(["ETIMEDOUT","ECONNRESET","ECONNREFUSED","ENOTFOUND","EAI_AGAIN","ENETUNREACH","EHOSTUNREACH","EPIPE","ERR_SOCKET_TIMEOUT","UND_ERR_CONNECT_TIMEOUT","UND_ERR_HEADERS_TIMEOUT"]),f=[/\bnetwork\b/i,/ETIMEDOUT/i,/ECONNRESET/i,/ECONNREFUSED/i,/ENOTFOUND/i,/EAI_AGAIN/i,/socket hang up/i,/fetch failed/i,/getaddrinfo/i,/tunneling socket could not be established/i,/request to .+ failed/i,/npm\s+(?:error|ERR!)\s+code\s+E429/i,/\bregistry\b.*\b(timeout|timed out|unreachable)\b/i,/\bproxy\b/i];function g(r){if("object"!=typeof r||null===r)return!1;const e="killed"in r&&!0===r.killed,n="signal"in r&&"SIGTERM"===r.signal,t=!("code"in r)||null===r.code||void 0===r.code;return e&&n&&t}export function isLikelyNetworkError(r){const e=R(r);if(e&&l.has(e))return!0;const n=N(r);return f.some(r=>r.test(n))}export function isRetryablePackageManagerError(r){return g(r)||isLikelyNetworkError(r)||isLikelyRollAgentRegistryPropagationError(r)}export function isLikelyRollAgentRegistryPropagationError(r){const e=N(r);return/\bnpm\s+(?:error|ERR!)\s+code\s+E404\b/i.test(e)&&/(?:@roll-agent%2f|@roll-agent\/)[a-z0-9._-]+/i.test(e)&&/(?:Not Found - GET|is not in this registry)/i.test(e)}export function formatPackageManagerError(r,e,n=process.platform){const t=formatPackageManagerCommand(r);if(k(r.command,e,n))return[`未找到 ${r.command},无法执行 \`${t}\`。`,"win32"===n?`请确认 ${r.command}.cmd 位于 PATH 中;npm 全局目录通常是 C:\\Users\\<you>\\AppData\\Roaming\\npm。`:`请确认已安装 ${r.command},并且当前 shell 的 PATH 可以访问它。`].join("");if(g(e))return`\`${t}\` 执行超时被终止。${u}`;if(isLikelyNetworkError(e)){return`\`${t}\` 执行失败:${e instanceof Error?e.message:String(e)}\n${u}`}return e instanceof Error?e.message:String(e)}function m(r){try{const e=JSON.parse(n(r,"utf-8"));if("string"!=typeof e.packageManager||0===e.packageManager.length)return;const[t]=e.packageManager.split("@",1);if(!t)return;return p(t)?t:void 0}catch{return}}function p(r){return PACKAGE_MANAGER_COMMANDS.some(e=>e===r)}function d(r){return/\s/.test(r)?JSON.stringify(r):r}function E(r){return[r.command,...r.args].map(h).join(" ")}function h(r){if(0===r.length)return'""';if(/["\r\n]/.test(r))throw new Error(`Unsupported Windows shell argument: ${r}`);return/[\s"&|<>^()%!]/.test(r)?`"${y(r)}"`:r}function y(r){return r.replace(/[\^&|<>%!]/g,r=>`^${r}`)}function k(r,e,n){if("ENOENT"===R(e))return!0;if("win32"!==n)return!1;const t=N(e).toLowerCase();return t.includes(`'${r}' is not recognized`)||t.includes(`"${r}" is not recognized`)||t.includes(`${r} is not recognized`)||t.includes(`'${r}' 不是内部或外部命令`)||t.includes(`"${r}" 不是内部或外部命令`)||t.includes(`${r} 不是内部或外部命令`)}function R(r){if("object"==typeof r&&null!==r&&"code"in r)return"string"==typeof r.code?r.code:void 0}function N(r){return r instanceof Error?r.message:String(r)}
@@ -0,0 +1,18 @@
1
+ import type { SessionTokenUsage } from "@roll-agent/runtime";
2
+ export interface UsageLineParts {
3
+ readonly inputTokens?: number;
4
+ readonly outputTokens?: number;
5
+ readonly sessionTokens?: number;
6
+ readonly cachedInputTokens?: number;
7
+ readonly reasoningTokens?: number;
8
+ readonly percentLeft?: number;
9
+ readonly usedTokens?: number;
10
+ readonly contextWindow?: number;
11
+ }
12
+ export interface UsagePartsOptions {
13
+ readonly baselineHeadroom?: number;
14
+ }
15
+ export declare function formatTokens(value: number): string;
16
+ export declare function sessionTotal(usage: SessionTokenUsage): number;
17
+ export declare function computeUsageParts(turn: SessionTokenUsage | undefined, session: SessionTokenUsage | undefined, contextWindow: number | undefined, contextInputTokens: number | undefined, options?: UsagePartsOptions): UsageLineParts;
18
+ export declare function formatUsageLine(parts: UsageLineParts): string | undefined;
@@ -0,0 +1 @@
1
+ const o=12e3,n=.2;export function formatTokens(o){return o>=1e3?`${(o/1e3).toFixed(1)}k`:String(o)}export function sessionTotal(o){return void 0!==o.totalTokens&&o.totalTokens>0?o.totalTokens:(o.inputTokens??0)+(o.outputTokens??0)}function e(o,e,t){const s=Math.min(t,Math.floor(e*n)),i=Math.max(e-s,1),u=Math.max(o-s,0),a=Math.max(i-u,0);return Math.min(Math.max(Math.round(a/i*100),0),100)}export function computeUsageParts(n,t,s,i,u){const a=i??n?.inputTokens,T=u?.baselineHeadroom??o,k=n?.cachedInputTokens,r=n?.reasoningTokens;return{...void 0!==n?.inputTokens?{inputTokens:n.inputTokens}:{},...void 0!==n?.outputTokens?{outputTokens:n.outputTokens}:{},...t?{sessionTokens:sessionTotal(t)}:{},...void 0!==k&&k>0?{cachedInputTokens:k}:{},...void 0!==r&&r>0?{reasoningTokens:r}:{},...void 0!==s&&void 0!==a?{percentLeft:e(a,s,T),usedTokens:a,contextWindow:s}:{}}}export function formatUsageLine(o){const n=[];if(void 0!==o.inputTokens){const e=void 0!==o.cachedInputTokens?` (+${formatTokens(o.cachedInputTokens)} cached)`:"";n.push(`in ${formatTokens(o.inputTokens)}${e}`)}if(void 0!==o.outputTokens){const e=void 0!==o.reasoningTokens?` (+${formatTokens(o.reasoningTokens)} reasoning)`:"";n.push(`out ${formatTokens(o.outputTokens)}${e}`)}return void 0!==o.sessionTokens&&n.push(`session ${formatTokens(o.sessionTokens)}`),void 0!==o.percentLeft&&void 0!==o.usedTokens&&void 0!==o.contextWindow&&n.push(`${String(o.percentLeft)}% left (${formatTokens(o.usedTokens)}/${formatTokens(o.contextWindow)})`),n.length>0?`↳ ${n.join(" · ")}`:void 0}
@@ -0,0 +1 @@
1
+ export declare function formatToolInput(input: unknown): string;
@@ -0,0 +1 @@
1
+ import{redactToolArgsForLog as t}from"./output.js";export function formatToolInput(o){const n=JSON.stringify(t(o))??"";return n.length>80?`${n.slice(0,79)}…`:n}
@@ -1 +1 @@
1
- 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"};export const DEFAULT_CONFIG={llm:{defaultProvider:"anthropic",defaultModel:DEFAULT_LLM_MODELS.anthropic,providers:{}},ask:{},agents:{dataDir:"~/.roll-agent/agents"},install:{fetchRetries:3,preferOffline:!1,networkTimeoutMs:12e4},browser:{instances:{}}};export const CONFIG_FILE_NAMES=["roll.config.yaml","roll.config.yml"];
1
+ 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"};export const DEFAULT_CONFIG={llm:{defaultProvider:"anthropic",defaultModel:DEFAULT_LLM_MODELS.anthropic,providers:{}},ask:{},runtime:{maxSteps:80,turnTimeoutMs:3e5,threadsDir:"~/.roll-agent/threads",thinkingLevel:"medium",approval:{default:"guarded",overrides:{}},compaction:{enabled:!0,strategy:"summarize",threshold:.75,keepRecentTurns:4,keepRecentTokens:32e3}},agents:{dataDir:"~/.roll-agent/agents"},install:{fetchRetries:3,preferOffline:!1,networkTimeoutMs:12e4},browser:{instances:{}}};export const CONFIG_FILE_NAMES=["roll.config.yaml","roll.config.yml"];
@@ -1 +1 @@
1
- const e={kind:"leaf"},r={kind:"object",fields:{apiKey:e,baseUrl:e}},o={kind:"object",fields:{platform:e,mode:e,headless:e,cdpUrl:e,cdpHost:e,cdpPort:e,channel:e,executablePath:e,userDataDir:e,sessionsDir:e,args:e,profileName:e,profileColor:e,windowBounds:{kind:"object",fields:{x:e,y:e,width:e,height:e}},trackingAgentId:e}};export const CONFIG_KEY_CODEC={kind:"object",fields:{llm:{kind:"object",fields:{defaultProvider:e,defaultModel:e,providers:{kind:"record",value:r}}},ask:{kind:"object",fields:{llmModel:e,confirmThreshold:e}},agents:{kind:"object",fields:{dataDir:e,env:{kind:"record",value:{kind:"record",value:e}}}},install:{kind:"object",fields:{registry:e,fetchRetries:e,preferOffline:e,networkTimeoutMs:e}},browser:{kind:"object",fields:{defaultInstance:e,instances:{kind:"record",value:o}}}}};export function kebabToCamel(e){return e.replace(/-([a-z])/g,(e,r)=>r.toUpperCase())}export function camelToKebab(e){return e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}function t(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}export function decodeFromYaml(r,o=CONFIG_KEY_CODEC){if(Array.isArray(r))return r.map(e=>decodeFromYaml(e,o));if(!t(r))return r;if("object"===o.kind){const t={};for(const[n,i]of Object.entries(r)){const r=kebabToCamel(n),d=o.fields[r]??e;t[r]=decodeFromYaml(i,d)}return t}if("record"===o.kind){const e={};for(const[t,n]of Object.entries(r))e[t]=decodeFromYaml(n,o.value);return e}return r}function n(r,o){const t=[];let n=CONFIG_KEY_CODEC;for(const i of r)if("object"===n.kind){const r=kebabToCamel(i),d=n.fields[r];d?(t.push("camel"===o?r:camelToKebab(r)),n=d):(t.push(i),n=e)}else"record"===n.kind?(t.push(i),n=n.value):t.push(i);return t}export function encodePathToYaml(e){return n(e,"kebab")}export function normalizeUserPath(e){return n(e,"camel")}
1
+ const e={kind:"leaf"},r={kind:"object",fields:{apiKey:e,baseUrl:e}},o={kind:"object",fields:{platform:e,mode:e,headless:e,cdpUrl:e,cdpHost:e,cdpPort:e,channel:e,executablePath:e,userDataDir:e,sessionsDir:e,args:e,profileName:e,profileColor:e,windowBounds:{kind:"object",fields:{x:e,y:e,width:e,height:e}},trackingAgentId:e}};export const CONFIG_KEY_CODEC={kind:"object",fields:{llm:{kind:"object",fields:{defaultProvider:e,defaultModel:e,providers:{kind:"record",value:r}}},ask:{kind:"object",fields:{llmModel:e,confirmThreshold:e}},runtime:{kind:"object",fields:{provider:e,model:e,maxSteps:e,turnTimeoutMs:e,threadsDir:e,contextWindow:e,thinkingLevel:e,approval:{kind:"object",fields:{default:e,overrides:{kind:"record",value:e}}},compaction:{kind:"object",fields:{enabled:e,strategy:e,threshold:e,keepRecentTurns:e,keepRecentTokens:e}}}},agents:{kind:"object",fields:{dataDir:e,env:{kind:"record",value:{kind:"record",value:e}}}},install:{kind:"object",fields:{registry:e,fetchRetries:e,preferOffline:e,networkTimeoutMs:e}},browser:{kind:"object",fields:{defaultInstance:e,instances:{kind:"record",value:o}}}}};export function kebabToCamel(e){return e.replace(/-([a-z])/g,(e,r)=>r.toUpperCase())}export function camelToKebab(e){return e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}function t(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}export function decodeFromYaml(r,o=CONFIG_KEY_CODEC){if(Array.isArray(r))return r.map(e=>decodeFromYaml(e,o));if(!t(r))return r;if("object"===o.kind){const t={};for(const[n,i]of Object.entries(r)){const r=kebabToCamel(n),d=o.fields[r]??e;t[r]=decodeFromYaml(i,d)}return t}if("record"===o.kind){const e={};for(const[t,n]of Object.entries(r))e[t]=decodeFromYaml(n,o.value);return e}return r}function n(r,o){const t=[];let n=CONFIG_KEY_CODEC;for(const i of r)if("object"===n.kind){const r=kebabToCamel(i),d=n.fields[r];d?(t.push("camel"===o?r:camelToKebab(r)),n=d):(t.push(i),n=e)}else"record"===n.kind?(t.push(i),n=n.value):t.push(i);return t}export function encodePathToYaml(e){return n(e,"kebab")}export function normalizeUserPath(e){return n(e,"camel")}
@@ -1 +1 @@
1
- import{readFileSync as n,existsSync as r}from"node:fs";import{resolve as t}from"node:path";import{parse as o}from"yaml";import{agentsConfigSchema as e,installConfigSchema as i,rollConfigSchema as s}from"./schema.js";import{DEFAULT_CONFIG as a,CONFIG_FILE_NAMES as f}from"./defaults.js";import{decodeFromYaml as c}from"./key-codec.js";import{detectKnownConfigMigrations as u,formatConfigMigrationError as l}from"./migration.js";function g(n){if("string"==typeof n)return n.replace(/\$\{([^}]+)\}/g,(n,r)=>process.env[r]??n);if(Array.isArray(n))return n.map(g);if(d(n)){const r={};for(const[t,o]of Object.entries(n))r[t]=g(o);return r}return n}function d(n){return"object"==typeof n&&null!==n&&!Array.isArray(n)}function p(n){return d(n)&&"number"==typeof n.line&&"number"==typeof n.col}function h(n){return n instanceof Error&&"linePos"in n&&Array.isArray(n.linePos)&&n.linePos.length>0&&n.linePos.every(p)}function m(n,r){const t=`Invalid YAML syntax in config file: ${n}`;if(!(r instanceof Error))return`${t}\n${String(r)}`;if(h(r)){const[n]=r.linePos;if(n)return`${t} at line ${n.line}, column ${n.col}\n${r.message}`}return`${t}\n${r.message}`}function w(n){let o=t(n);const e=t("/");for(;o!==e;){for(const n of f){const e=t(o,n);if(r(e))return e}const n=t(o,"..");if(n===o)break;o=n}}function v(n){if(n.startsWith("~/")){const r=process.env.HOME??process.env.USERPROFILE??"";return t(r,n.slice(2))}return n}function $(n){return{...n,agents:{...n.agents,dataDir:v(n.agents.dataDir)},browser:{...n.browser,instances:Object.fromEntries(Object.entries(n.browser.instances).map(([n,r])=>[n,{...r,userDataDir:v(r.userDataDir),...void 0!==r.sessionsDir?{sessionsDir:v(r.sessionsDir)}:{}}]))}}}const C={notFound:"not-found",valid:"valid",needsMigration:"needs-migration",invalid:"invalid"};export function parseConfigDocument(n,r){let t;try{t=o(n)}catch(n){throw new Error(m(r,n),{cause:n instanceof Error?n:void 0})}if(!d(t))throw new Error(`Invalid config file: ${r} (expected YAML object)`);return t}function P(n,r,t={}){const o=parseConfigDocument(n,r),e=u(o,t);if(e.needsMigration)throw new Error(l(r,e));return o}export function validateConfigText(n,r){const t=P(n,r),o=g(c(t));if(!d(o))throw new Error(`Invalid config file: ${r} (expected YAML object)`);const e=j(a,o),i=s.safeParse(e);if(!i.success){const n=i.error.issues.map(n=>` - ${n.path.join(".")}: ${n.message}`).join("\n");throw new Error(`Config validation failed (${r}):\n${n}`)}return $(i.data)}function E(n,r){const t=P(n,r,{scope:"agents"}),o=g(c(t));if(!d(o))throw new Error(`Invalid config file: ${r} (expected YAML object)`);const i=d(o.agents)?o.agents:{},s=j(a.agents,i),f=e.safeParse(s);if(!f.success){const n=f.error.issues.map(n=>` - agents.${n.path.join(".")}: ${n.message}`).join("\n");throw new Error(`Config validation failed (${r}):\n${n}`)}return{...f.data,dataDir:v(f.data.dataDir)}}function y(n,r){const t=parseConfigDocument(n,r),o=g(c(t));if(!d(o))throw new Error(`Invalid config file: ${r} (expected YAML object)`);const e=d(o.install)?o.install:{},s=j(a.install,e),f=i.safeParse(s);if(!f.success){const n=f.error.issues.map(n=>` - install.${n.path.join(".")}: ${n.message}`).join("\n");throw new Error(`Config validation failed (${r}):\n${n}`)}return f.data}export function loadInstallConfig(t={}){const o=resolveConfigPath(t);if(!o)return{installConfig:a.install,configPath:void 0};if(!r(o))throw new Error(`Config file not found: ${o}`);return{installConfig:y(n(o,"utf-8"),o),configPath:o}}export function loadConfig(t={}){const o=resolveConfigPath(t);if(!o)return{config:$(a),configPath:void 0};if(!r(o))throw new Error(`Config file not found: ${o}`);return{config:validateConfigText(n(o,"utf-8"),o),configPath:o}}export function loadAgentsConfig(t={}){const o=resolveConfigPath(t);if(!o)return{agentsConfig:{...a.agents,dataDir:v(a.agents.dataDir)},configPath:void 0};if(!r(o))throw new Error(`Config file not found: ${o}`);return{agentsConfig:E(n(o,"utf-8"),o),configPath:o}}export function resolveConfigPath(n={}){const{configPath:r,cwd:t=process.cwd()}=n;return r??w(t)}export function inspectConfigFile(t={}){const o=resolveConfigPath(t);if(!o)return{status:C.notFound,configPath:void 0};if(!r(o))return{status:C.invalid,configPath:o,raw:"",error:new Error(`Config file not found: ${o}`)};const e=n(o,"utf-8");let i;try{i=parseConfigDocument(e,o)}catch(n){return{status:C.invalid,configPath:o,raw:e,error:n instanceof Error?n:new Error(String(n))}}const s=u(i);if(s.needsMigration)return{status:C.needsMigration,configPath:o,raw:e,report:s};try{return{status:C.valid,configPath:o,config:validateConfigText(e,o)}}catch(n){return{status:C.invalid,configPath:o,raw:e,error:n instanceof Error?n:new Error(String(n))}}}function j(n,r){const t={...n};for(const[o,e]of Object.entries(r)){const r=n[o];"object"!=typeof e||null===e||Array.isArray(e)||"object"!=typeof r||null===r||Array.isArray(r)?t[o]=e:t[o]=j(r,e)}return t}
1
+ import{readFileSync as n,existsSync as r}from"node:fs";import{resolve as t}from"node:path";import{parse as o}from"yaml";import{agentsConfigSchema as e,installConfigSchema as i,rollConfigSchema as s}from"./schema.js";import{DEFAULT_CONFIG as a,CONFIG_FILE_NAMES as f}from"./defaults.js";import{decodeFromYaml as c}from"./key-codec.js";import{detectKnownConfigMigrations as u,formatConfigMigrationError as l}from"./migration.js";function g(n){if("string"==typeof n)return n.replace(/\$\{([^}]+)\}/g,(n,r)=>process.env[r]??n);if(Array.isArray(n))return n.map(g);if(d(n)){const r={};for(const[t,o]of Object.entries(n))r[t]=g(o);return r}return n}function d(n){return"object"==typeof n&&null!==n&&!Array.isArray(n)}function p(n){return d(n)&&"number"==typeof n.line&&"number"==typeof n.col}function h(n){return n instanceof Error&&"linePos"in n&&Array.isArray(n.linePos)&&n.linePos.length>0&&n.linePos.every(p)}function m(n,r){const t=`Invalid YAML syntax in config file: ${n}`;if(!(r instanceof Error))return`${t}\n${String(r)}`;if(h(r)){const[n]=r.linePos;if(n)return`${t} at line ${n.line}, column ${n.col}\n${r.message}`}return`${t}\n${r.message}`}function w(n){let o=t(n);const e=t("/");for(;o!==e;){for(const n of f){const e=t(o,n);if(r(e))return e}const n=t(o,"..");if(n===o)break;o=n}}function v(n){if(n.startsWith("~/")){const r=process.env.HOME??process.env.USERPROFILE??"";return t(r,n.slice(2))}return n}function $(n){return{...n,agents:{...n.agents,dataDir:v(n.agents.dataDir)},runtime:{...n.runtime,threadsDir:v(n.runtime.threadsDir)},browser:{...n.browser,instances:Object.fromEntries(Object.entries(n.browser.instances).map(([n,r])=>[n,{...r,userDataDir:v(r.userDataDir),...void 0!==r.sessionsDir?{sessionsDir:v(r.sessionsDir)}:{}}]))}}}const C={notFound:"not-found",valid:"valid",needsMigration:"needs-migration",invalid:"invalid"};export function parseConfigDocument(n,r){let t;try{t=o(n)}catch(n){throw new Error(m(r,n),{cause:n instanceof Error?n:void 0})}if(!d(t))throw new Error(`Invalid config file: ${r} (expected YAML object)`);return t}function P(n,r,t={}){const o=parseConfigDocument(n,r),e=u(o,t);if(e.needsMigration)throw new Error(l(r,e));return o}export function validateConfigText(n,r){const t=P(n,r),o=g(c(t));if(!d(o))throw new Error(`Invalid config file: ${r} (expected YAML object)`);const e=j(a,o),i=s.safeParse(e);if(!i.success){const n=i.error.issues.map(n=>` - ${n.path.join(".")}: ${n.message}`).join("\n");throw new Error(`Config validation failed (${r}):\n${n}`)}return $(i.data)}function E(n,r){const t=P(n,r,{scope:"agents"}),o=g(c(t));if(!d(o))throw new Error(`Invalid config file: ${r} (expected YAML object)`);const i=d(o.agents)?o.agents:{},s=j(a.agents,i),f=e.safeParse(s);if(!f.success){const n=f.error.issues.map(n=>` - agents.${n.path.join(".")}: ${n.message}`).join("\n");throw new Error(`Config validation failed (${r}):\n${n}`)}return{...f.data,dataDir:v(f.data.dataDir)}}function y(n,r){const t=parseConfigDocument(n,r),o=g(c(t));if(!d(o))throw new Error(`Invalid config file: ${r} (expected YAML object)`);const e=d(o.install)?o.install:{},s=j(a.install,e),f=i.safeParse(s);if(!f.success){const n=f.error.issues.map(n=>` - install.${n.path.join(".")}: ${n.message}`).join("\n");throw new Error(`Config validation failed (${r}):\n${n}`)}return f.data}export function loadInstallConfig(t={}){const o=resolveConfigPath(t);if(!o)return{installConfig:a.install,configPath:void 0};if(!r(o))throw new Error(`Config file not found: ${o}`);return{installConfig:y(n(o,"utf-8"),o),configPath:o}}export function loadConfig(t={}){const o=resolveConfigPath(t);if(!o)return{config:$(a),configPath:void 0};if(!r(o))throw new Error(`Config file not found: ${o}`);return{config:validateConfigText(n(o,"utf-8"),o),configPath:o}}export function loadAgentsConfig(t={}){const o=resolveConfigPath(t);if(!o)return{agentsConfig:{...a.agents,dataDir:v(a.agents.dataDir)},configPath:void 0};if(!r(o))throw new Error(`Config file not found: ${o}`);return{agentsConfig:E(n(o,"utf-8"),o),configPath:o}}export function resolveConfigPath(n={}){const{configPath:r,cwd:t=process.cwd()}=n;return r??w(t)}export function inspectConfigFile(t={}){const o=resolveConfigPath(t);if(!o)return{status:C.notFound,configPath:void 0};if(!r(o))return{status:C.invalid,configPath:o,raw:"",error:new Error(`Config file not found: ${o}`)};const e=n(o,"utf-8");let i;try{i=parseConfigDocument(e,o)}catch(n){return{status:C.invalid,configPath:o,raw:e,error:n instanceof Error?n:new Error(String(n))}}const s=u(i);if(s.needsMigration)return{status:C.needsMigration,configPath:o,raw:e,report:s};try{return{status:C.valid,configPath:o,config:validateConfigText(e,o)}}catch(n){return{status:C.invalid,configPath:o,raw:e,error:n instanceof Error?n:new Error(String(n))}}}function j(n,r){const t={...n};for(const[o,e]of Object.entries(r)){const r=n[o];"object"!=typeof e||null===e||Array.isArray(e)||"object"!=typeof r||null===r||Array.isArray(r)?t[o]=e:t[o]=j(r,e)}return t}
@@ -22,13 +22,13 @@ export declare const BrowserSecurityDiagnosticSchema: z.ZodObject<{
22
22
  domainAllowlist: string[];
23
23
  maxPageContentBytes: number;
24
24
  maxSnapshotNodes: number;
25
- actionPolicy: "log" | "deny" | "confirm";
25
+ actionPolicy: "deny" | "confirm" | "log";
26
26
  foregroundPolicy: "never" | "when-minimized" | "always";
27
27
  }, {
28
28
  domainAllowlist: string[];
29
29
  maxPageContentBytes: number;
30
30
  maxSnapshotNodes: number;
31
- actionPolicy: "log" | "deny" | "confirm";
31
+ actionPolicy: "deny" | "confirm" | "log";
32
32
  foregroundPolicy?: "never" | "when-minimized" | "always" | undefined;
33
33
  }>;
34
34
  export declare const BrowserUseToolPolicyDiagnosticSchema: z.ZodObject<{
@@ -36,18 +36,18 @@ export declare const BrowserUseToolPolicyDiagnosticSchema: z.ZodObject<{
36
36
  tools: z.ZodRecord<z.ZodString, z.ZodObject<{
37
37
  policy: z.ZodEnum<["log", "deny", "confirm"]>;
38
38
  }, "strip", z.ZodTypeAny, {
39
- policy: "log" | "deny" | "confirm";
39
+ policy: "deny" | "confirm" | "log";
40
40
  }, {
41
- policy: "log" | "deny" | "confirm";
41
+ policy: "deny" | "confirm" | "log";
42
42
  }>>;
43
43
  }, "strip", z.ZodTypeAny, {
44
44
  tools: Record<string, {
45
- policy: "log" | "deny" | "confirm";
45
+ policy: "deny" | "confirm" | "log";
46
46
  }>;
47
47
  approvalTtlMs: number;
48
48
  }, {
49
49
  tools: Record<string, {
50
- policy: "log" | "deny" | "confirm";
50
+ policy: "deny" | "confirm" | "log";
51
51
  }>;
52
52
  approvalTtlMs: number;
53
53
  }>;
@@ -164,13 +164,13 @@ export declare const AgentRuntimeEnvDiagnosticPayloadSchema: z.ZodObject<{
164
164
  domainAllowlist: string[];
165
165
  maxPageContentBytes: number;
166
166
  maxSnapshotNodes: number;
167
- actionPolicy: "log" | "deny" | "confirm";
167
+ actionPolicy: "deny" | "confirm" | "log";
168
168
  foregroundPolicy: "never" | "when-minimized" | "always";
169
169
  }, {
170
170
  domainAllowlist: string[];
171
171
  maxPageContentBytes: number;
172
172
  maxSnapshotNodes: number;
173
- actionPolicy: "log" | "deny" | "confirm";
173
+ actionPolicy: "deny" | "confirm" | "log";
174
174
  foregroundPolicy?: "never" | "when-minimized" | "always" | undefined;
175
175
  }>>;
176
176
  toolPolicy: z.ZodOptional<z.ZodObject<{
@@ -178,18 +178,18 @@ export declare const AgentRuntimeEnvDiagnosticPayloadSchema: z.ZodObject<{
178
178
  tools: z.ZodRecord<z.ZodString, z.ZodObject<{
179
179
  policy: z.ZodEnum<["log", "deny", "confirm"]>;
180
180
  }, "strip", z.ZodTypeAny, {
181
- policy: "log" | "deny" | "confirm";
181
+ policy: "deny" | "confirm" | "log";
182
182
  }, {
183
- policy: "log" | "deny" | "confirm";
183
+ policy: "deny" | "confirm" | "log";
184
184
  }>>;
185
185
  }, "strip", z.ZodTypeAny, {
186
186
  tools: Record<string, {
187
- policy: "log" | "deny" | "confirm";
187
+ policy: "deny" | "confirm" | "log";
188
188
  }>;
189
189
  approvalTtlMs: number;
190
190
  }, {
191
191
  tools: Record<string, {
192
- policy: "log" | "deny" | "confirm";
192
+ policy: "deny" | "confirm" | "log";
193
193
  }>;
194
194
  approvalTtlMs: number;
195
195
  }>>;
@@ -316,12 +316,12 @@ export declare const AgentRuntimeEnvDiagnosticPayloadSchema: z.ZodObject<{
316
316
  domainAllowlist: string[];
317
317
  maxPageContentBytes: number;
318
318
  maxSnapshotNodes: number;
319
- actionPolicy: "log" | "deny" | "confirm";
319
+ actionPolicy: "deny" | "confirm" | "log";
320
320
  foregroundPolicy: "never" | "when-minimized" | "always";
321
321
  } | undefined;
322
322
  toolPolicy?: {
323
323
  tools: Record<string, {
324
- policy: "log" | "deny" | "confirm";
324
+ policy: "deny" | "confirm" | "log";
325
325
  }>;
326
326
  approvalTtlMs: number;
327
327
  } | undefined;
@@ -360,12 +360,12 @@ export declare const AgentRuntimeEnvDiagnosticPayloadSchema: z.ZodObject<{
360
360
  domainAllowlist: string[];
361
361
  maxPageContentBytes: number;
362
362
  maxSnapshotNodes: number;
363
- actionPolicy: "log" | "deny" | "confirm";
363
+ actionPolicy: "deny" | "confirm" | "log";
364
364
  foregroundPolicy?: "never" | "when-minimized" | "always" | undefined;
365
365
  } | undefined;
366
366
  toolPolicy?: {
367
367
  tools: Record<string, {
368
- policy: "log" | "deny" | "confirm";
368
+ policy: "deny" | "confirm" | "log";
369
369
  }>;
370
370
  approvalTtlMs: number;
371
371
  } | undefined;