@roll-agent/core 0.6.1 → 0.6.2

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.
@@ -1 +1 @@
1
- import{readFileSync as o}from"node:fs";import{defineCommand as t}from"citty";import{loadConfig as e}from"../../config/loader.js";import{getAgentEnv as r,getMissingAgentEnvRuntimeIssues as s,inspectAgentEnvRequirements as n}from"../../config/helpers.js";import{AgentStore as i}from"../../registry/store.js";import{McpClientManager as l}from"../../mcp/client-manager.js";import{resolveTransportWithDevSpawnSpec as a}from"../../registry/dev-spawn.js";import{createProviderModel as c}from"../../llm/providers.js";import{formatValidationIssuesMessage as f}from"../../tool-runtime/messages.js";import{preflightToolCall as p}from"../../tool-runtime/preflight.js";import{formatMissingToolMessage as u,normalizeListedTools as m}from"../utils/agent-tools.js";import{extractTextContent as g,formatToolResultForJsonOutput as d,isToolErrorResult as h}from"../utils/tool-results.js";import{log as j,redactToolArgsForLog as v}from"../utils/output.js";import{shouldSkipRuntimeReadinessForTool as y}from"../../config/runtime-env.js";export default t({meta:{description:"声明式调用 Agent 的指定 tool"},args:{agent:{type:"positional",description:"Agent 名称",required:!0},tool:{type:"positional",description:"Tool 名称",required:!0},json:{type:"boolean",description:"JSON 格式输出",default:!1},verbose:{type:"boolean",alias:"v",description:"输出调试日志",default:!1},"input-json":{type:"string",description:"以 JSON 字符串提供完整 tool 输入对象"},"input-file":{type:"string",description:"从 JSON 文件读取完整 tool 输入对象"}},async run({args:o,rawArgs:t}){const{config:w}=e(),S=new i(w.agents.dataDir).findByName(o.agent);if(!S)return j.error(`Agent "${o.agent}" 未注册。使用 \`roll agent list\` 查看已注册 Agent。`),void(process.exitCode=1);let $;try{$=resolveToolArgs(t)}catch(o){return j.error(o instanceof Error?o.message:String(o)),void(process.exitCode=1)}const A=new l;try{const t=w.llm.defaultProvider,e=w.llm.providers[t],i=e?c(t,w.llm.defaultModel,e.apiKey,e.baseUrl):void 0;j.info(`连接 Agent "${S.skill.name}"...`);const l=r(w,S.skill.name),N=a(S),x=await A.connect(S.skill.name,N,S.installPath,{...i?{samplingModel:i}:{},...l?{env:l}:{}}),E=m((await x.listTools()).tools),b=E.find(t=>t.name===o.tool);if(!b)return j.error(u(S.skill.name,o.tool,E)),void(process.exitCode=1);const k=n(S.skill.name,S.skill.env,w.agents.env),T=y(b.name)?[]:s(k),J=p(b,$,{runtimeIssues:T});if(!J.ok)return j.error(f(S.skill.name,o.tool,J.issues,J.runtimeIssues)),void(process.exitCode=1);j.info(`调用 ${S.skill.name}.${o.tool}`),j.debug(`调用参数: ${JSON.stringify(v($))}`);const O=await x.callTool({name:o.tool,arguments:$});if(o.json)console.log(JSON.stringify(d(O),null,2));else for(const o of g(O.content))console.log(o);if(h(O))return j.error("tool 返回 isError=true"),void(process.exitCode=1);j.success("调用完成")}catch(o){const t=o instanceof Error?o.message:String(o),e=o instanceof Error&&o.cause?`\n cause: ${String(o.cause)}`:"";j.error(`${t}${e}`),process.exitCode=1}finally{await A.disconnectAll()}}});const w=new Set(["json","verbose","v","help","h","version"]),S=new Set(["config","input-json","input-file"]);function $(o){return"object"==typeof o&&null!==o&&!Array.isArray(o)}function A(o,t){let e;try{e=JSON.parse(o)}catch(o){throw new Error(`${t} 不是合法 JSON: ${o instanceof Error?o.message:String(o)}`)}if(!$(e))throw new Error(`${t} 必须是 JSON object`);return e}function N(o,t){let e=0;for(;e<o.length&&!o[e]?.startsWith("--");)e++;for(;e<o.length;){if(o[e]!==`--${t}`){e++;continue}const r=o[e+1];if(!r||r.startsWith("--"))throw new Error(`选项 --${t} 需要提供值`);return r}}export function parseExplicitToolInput(t){const e=N(t,"input-json"),r=N(t,"input-file");if(e&&r)throw new Error("不能同时使用 --input-json 和 --input-file");if(e)return A(e,"--input-json");if(r){return A(o(r,"utf-8"),`输入文件 ${r}`)}}export function resolveToolArgs(o){return{...parseExplicitToolInput(o)??{},...parseToolArgs(o)}}export function parseToolArgs(o){const t={};let e=0;for(;e<o.length&&!o[e]?.startsWith("--");)e++;for(;e<o.length;){const r=o[e];if(!r?.startsWith("--")){e++;continue}const s=r.slice(2),n=o[e+1];if(w.has(s))e++;else if(S.has(s))e+=n&&!n.startsWith("--")?2:1;else if(!n||n.startsWith("--"))t[s]=!0,e++;else{const o=Number(n);t[s]=Number.isNaN(o)?n:o,e+=2}}return t}
1
+ import{readFileSync as t}from"node:fs";import{defineCommand as o}from"citty";import{loadConfig as r}from"../../config/loader.js";import{getAgentEnv as e,getMissingAgentEnvRuntimeIssues as n,inspectAgentEnvRequirements as i}from"../../config/helpers.js";import{AgentStore as s}from"../../registry/store.js";import{McpClientManager as l}from"../../mcp/client-manager.js";import{resolveTransportWithDevSpawnSpec as a}from"../../registry/dev-spawn.js";import{createProviderModel as c}from"../../llm/providers.js";import{formatValidationIssuesMessage as f}from"../../tool-runtime/messages.js";import{preflightToolCall as p}from"../../tool-runtime/preflight.js";import{formatMissingToolMessage as u,normalizeListedTools as m}from"../utils/agent-tools.js";import{extractTextContent as g,formatToolResultForJsonOutput as d,isToolErrorResult as h}from"../utils/tool-results.js";import{log as j,redactToolArgsForLog as v}from"../utils/output.js";import{shouldSkipRuntimeReadinessForTool as y}from"../../config/runtime-env.js";export default o({meta:{description:"声明式调用 Agent 的指定 tool"},args:{agent:{type:"positional",description:"Agent 名称",required:!0},tool:{type:"positional",description:"Tool 名称",required:!0},json:{type:"boolean",description:"JSON 格式输出",default:!1},verbose:{type:"boolean",alias:"v",description:"输出调试日志",default:!1},"input-json":{type:"string",description:"以 JSON 字符串提供完整 tool 输入对象"},"input-file":{type:"string",description:"从 JSON 文件读取完整 tool 输入对象"}},async run({args:t,rawArgs:o}){const{config:w}=r(),S=new s(w.agents.dataDir).findByName(t.agent);if(!S)return j.error(`Agent "${t.agent}" 未注册。使用 \`roll agent list\` 查看已注册 Agent。`),void(process.exitCode=1);let N;try{N=resolveToolArgs(o)}catch(t){return j.error(t instanceof Error?t.message:String(t)),void(process.exitCode=1)}const $=new l;try{const o=w.llm.defaultProvider,r=w.llm.providers[o],s=r?c(o,w.llm.defaultModel,r.apiKey,r.baseUrl):void 0;j.info(`连接 Agent "${S.skill.name}"...`);const l=e(w,S.skill.name),A=a(S),b=await $.connect(S.skill.name,A,S.installPath,{...s?{samplingModel:s}:{},...l?{env:l}:{}}),x=m((await b.listTools()).tools),E=x.find(o=>o.name===t.tool);if(!E)return j.error(u(S.skill.name,t.tool,x)),void(process.exitCode=1);const k=i(S.skill.name,S.skill.env,w.agents.env),J=y(E.name)?[]:n(k),O=p(E,N,{runtimeIssues:J});if(!O.ok)return j.error(f(S.skill.name,t.tool,O.issues,O.runtimeIssues)),void(process.exitCode=1);j.info(`调用 ${S.skill.name}.${t.tool}`),j.debug(`调用参数: ${JSON.stringify(v(N))}`);const T=await b.callTool({name:t.tool,arguments:N});if(t.json)console.log(JSON.stringify(d(T),null,2));else for(const t of g(T.content))console.log(t);if(h(T))return j.error("tool 返回 isError=true"),void(process.exitCode=1);j.success("调用完成")}catch(t){const o=t instanceof Error?t.message:String(t),r=t instanceof Error&&t.cause?`\n cause: ${String(t.cause)}`:"";j.error(`${o}${r}`),process.exitCode=1}finally{await $.disconnectAll()}}});const w=new Set(["json","verbose","v","help","h","version"]),S=new Set(["config","input-json","input-file"]);function N(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function $(t,o){let r;try{r=JSON.parse(t)}catch(t){throw new Error(`${o} 不是合法 JSON: ${t instanceof Error?t.message:String(t)}`)}if(!N(r))throw new Error(`${o} 必须是 JSON object`);return r}function A(t,o){let r=0;for(;r<t.length&&!t[r]?.startsWith("--");)r++;for(;r<t.length;){if(t[r]!==`--${o}`){r++;continue}const e=t[r+1];if(!e||e.startsWith("--"))throw new Error(`选项 --${o} 需要提供值`);return e}}export function parseExplicitToolInput(o){const r=A(o,"input-json"),e=A(o,"input-file"),n=b(o);if([r,e,n].filter(t=>void 0!==t).length>1)throw new Error("不能同时使用 positional JSON、--input-json 和 --input-file");if(r)return $(r,"--input-json");if(e){return $(t(e,"utf-8"),`输入文件 ${e}`)}return n?$(n,"positional JSON input"):void 0}function b(t){const o=[];for(const r of t){if(r.startsWith("--"))break;o.push(r)}const r=o.slice(2);if(0!==r.length){if(1===r.length&&r[0]?.trim().startsWith("{"))return r[0];throw new Error("roll run 只接受 agent/tool 两个位置参数;tool 输入请使用 --key value、--input-json、--input-file,或第三个位置参数 JSON object")}}export function resolveToolArgs(t){return{...parseExplicitToolInput(t)??{},...parseToolArgs(t)}}export function parseToolArgs(t){const o={};let r=0;for(;r<t.length&&!t[r]?.startsWith("--");)r++;for(;r<t.length;){const e=t[r];if(!e?.startsWith("--")){r++;continue}const n=e.slice(2),i=t[r+1];if(w.has(n))r++;else if(S.has(n))r+=i&&!i.startsWith("--")?2:1;else if(!i||i.startsWith("--"))o[n]=!0,r++;else{const t=Number(i);o[n]=Number.isNaN(t)?i:t,r+=2}}return o}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@roll-agent/core",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",