@roll-agent/core 0.11.0 → 0.13.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.
- package/bin/roll.js +18 -1
- package/dist/cli/chat/ink/app.d.ts +15 -0
- package/dist/cli/chat/ink/app.js +1 -0
- package/dist/cli/chat/ink/commands.d.ts +6 -0
- package/dist/cli/chat/ink/commands.js +1 -0
- package/dist/cli/chat/ink/confirm-select.d.ts +6 -0
- package/dist/cli/chat/ink/confirm-select.js +1 -0
- package/dist/cli/chat/ink/history-from-messages.d.ts +3 -0
- package/dist/cli/chat/ink/history-from-messages.js +1 -0
- package/dist/cli/chat/ink/history-item.d.ts +5 -0
- package/dist/cli/chat/ink/history-item.js +1 -0
- package/dist/cli/chat/ink/live-region.d.ts +5 -0
- package/dist/cli/chat/ink/live-region.js +1 -0
- package/dist/cli/chat/ink/markdown.d.ts +5 -0
- package/dist/cli/chat/ink/markdown.js +1 -0
- package/dist/cli/chat/ink/run-ink-repl.d.ts +13 -0
- package/dist/cli/chat/ink/run-ink-repl.js +1 -0
- package/dist/cli/chat/ink/slash-popup.d.ts +7 -0
- package/dist/cli/chat/ink/slash-popup.js +1 -0
- package/dist/cli/chat/ink/spinner.d.ts +2 -0
- package/dist/cli/chat/ink/spinner.js +1 -0
- package/dist/cli/chat/ink/state.d.ts +103 -0
- package/dist/cli/chat/ink/state.js +1 -0
- package/dist/cli/chat/ink/status-line.d.ts +16 -0
- package/dist/cli/chat/ink/status-line.js +1 -0
- package/dist/cli/chat/ink/text-prompt.d.ts +12 -0
- package/dist/cli/chat/ink/text-prompt.js +1 -0
- package/dist/cli/chat/ink/thinking-text.d.ts +10 -0
- package/dist/cli/chat/ink/thinking-text.js +1 -0
- package/dist/cli/chat/ink/thinking.d.ts +3 -0
- package/dist/cli/chat/ink/thinking.js +1 -0
- package/dist/cli/chat/ink/tool-label.d.ts +4 -0
- package/dist/cli/chat/ink/tool-label.js +1 -0
- package/dist/cli/chat/ink/use-session.d.ts +20 -0
- package/dist/cli/chat/ink/use-session.js +1 -0
- package/dist/cli/chat/title.d.ts +1 -0
- package/dist/cli/chat/title.js +1 -0
- package/dist/cli/commands/browser-stop.d.ts +4 -4
- package/dist/cli/commands/chat.d.ts +9 -0
- package/dist/cli/commands/chat.js +1 -1
- package/dist/cli/commands/config-guidance.d.ts +2 -2
- package/dist/cli/utils/chat-renderer.d.ts +7 -1
- package/dist/cli/utils/chat-renderer.js +1 -1
- package/dist/cli/utils/output.d.ts +1 -0
- package/dist/cli/utils/output.js +1 -1
- package/dist/cli/utils/package-manager.d.ts +5 -0
- package/dist/cli/utils/package-manager.js +1 -1
- package/dist/cli/utils/token-format.d.ts +23 -0
- package/dist/cli/utils/token-format.js +1 -0
- package/dist/cli/utils/tool-format.d.ts +1 -0
- package/dist/cli/utils/tool-format.js +1 -0
- package/dist/config/defaults.js +1 -1
- package/dist/config/key-codec.js +1 -1
- package/dist/config/schema.d.ts +164 -40
- package/dist/config/schema.js +1 -1
- package/dist/llm/engine.d.ts +1 -1
- package/dist/llm/providers.d.ts +9 -6
- package/dist/llm/providers.js +1 -1
- package/dist/mcp/client-manager.d.ts +4 -2
- package/dist/mcp/client-manager.js +1 -1
- package/dist/mcp/sampling-handler.d.ts +2 -2
- package/dist/router/llm-router.d.ts +2 -2
- package/dist/tool-runtime/argument-extractor.d.ts +2 -2
- package/dist/types/chat.d.ts +12 -0
- package/package.json +15 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
import{execFile as
|
|
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,23 @@
|
|
|
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 cacheWriteTokens?: number;
|
|
8
|
+
readonly reasoningTokens?: number;
|
|
9
|
+
readonly percentLeft?: number;
|
|
10
|
+
readonly usedTokens?: number;
|
|
11
|
+
readonly contextWindow?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface UsagePartsOptions {
|
|
14
|
+
readonly baselineHeadroom?: number;
|
|
15
|
+
}
|
|
16
|
+
export declare function formatTokens(value: number): string;
|
|
17
|
+
export declare function sessionTotal(usage: SessionTokenUsage): number;
|
|
18
|
+
export declare function computeUsageParts(turn: SessionTokenUsage | undefined, session: SessionTokenUsage | undefined, contextWindow: number | undefined, contextInputTokens: number | undefined, options?: UsagePartsOptions): UsageLineParts;
|
|
19
|
+
export declare function formatTurnUsage(parts: UsageLineParts): string | undefined;
|
|
20
|
+
export declare function formatContextUsage(parts: UsageLineParts): string | undefined;
|
|
21
|
+
export declare function formatThroughput(tokensPerSecond: number | undefined): string | undefined;
|
|
22
|
+
export declare function contextPressure(percentLeft: number | undefined): "ok" | "warn" | "critical";
|
|
23
|
+
export declare function formatUsageLine(parts: UsageLineParts): string | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const o=12e3,n=.2;function t(o){return o.endsWith(".0")?o.slice(0,-2):o}export function formatTokens(o){return o>=1e6?`${t((o/1e6).toFixed(1))}M`:o>=1e3?`${t((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,t,e){const s=Math.min(e,Math.floor(t*n)),i=Math.max(t-s,1),r=Math.max(o-s,0),u=Math.max(i-r,0);return Math.min(Math.max(Math.round(u/i*100),0),100)}export function computeUsageParts(n,t,s,i,r){const u=i??n?.inputTokens,a=r?.baselineHeadroom??o,c=n?.cachedInputTokens,T=n?.cacheWriteTokens,k=n?.reasoningTokens;return{...void 0!==n?.inputTokens?{inputTokens:n.inputTokens}:{},...void 0!==n?.outputTokens?{outputTokens:n.outputTokens}:{},...t?{sessionTokens:sessionTotal(t)}:{},...void 0!==c&&c>0?{cachedInputTokens:c}:{},...void 0!==T&&T>0?{cacheWriteTokens:T}:{},...void 0!==k&&k>0?{reasoningTokens:k}:{},...void 0!==s&&void 0!==u?{percentLeft:e(u,s,a),usedTokens:u,contextWindow:s}:{}}}export function formatTurnUsage(o){const n=[];if(void 0!==o.inputTokens){const t=[];void 0!==o.cachedInputTokens&&t.push(`+${formatTokens(o.cachedInputTokens)} cached`),void 0!==o.cacheWriteTokens&&t.push(`+${formatTokens(o.cacheWriteTokens)} cache-write`);const e=t.length>0?` (${t.join(", ")})`:"";n.push(`in ${formatTokens(o.inputTokens)}${e}`)}if(void 0!==o.outputTokens){const t=void 0!==o.reasoningTokens?` (+${formatTokens(o.reasoningTokens)} reasoning)`:"";n.push(`out ${formatTokens(o.outputTokens)}${t}`)}return n.length>0?`turn ${n.join(" ")}`:void 0}export function formatContextUsage(o){if(void 0!==o.percentLeft&&void 0!==o.usedTokens&&void 0!==o.contextWindow)return`ctx ${formatTokens(o.usedTokens)}/${formatTokens(o.contextWindow)} (${String(o.percentLeft)}% left)`}export function formatThroughput(o){if(void 0===o||!Number.isFinite(o)||o<=0)return;const n=o>=10?Math.round(o):o.toFixed(1);return`${String(n)} tok/s`}export function contextPressure(o){return void 0===o||o>25?"ok":o>10?"warn":"critical"}export function formatUsageLine(o){const n=[],t=formatTurnUsage(o);void 0!==t&&n.push(t),void 0!==o.sessionTokens&&n.push(`session ${formatTokens(o.sessionTokens)}`);const e=formatContextUsage(o);return void 0!==e&&n.push(e),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}
|
package/dist/config/defaults.js
CHANGED
|
@@ -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:{},runtime:{maxSteps:
|
|
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"];
|
package/dist/config/key-codec.js
CHANGED
|
@@ -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}},runtime:{kind:"object",fields:{provider:e,model:e,maxSteps:e,threadsDir:e,approval:{kind:"object",fields:{default:e,overrides:{kind:"record",value: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")}
|