@roll-agent/core 0.5.0 → 0.5.1
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{defineCommand as t}from"citty";import{
|
|
1
|
+
import{defineCommand as t}from"citty";import{getAgentEnv as e}from"../../config/helpers.js";import{loadAgentsConfig as r,loadConfig as a}from"../../config/loader.js";import{getAgentLogPath as n,getAgentPid as i,probeAgentEndpoint as s,startAgent as o,stopAgentGracefully as m,waitForAgentReady as p}from"../../registry/process-manager.js";import{AgentStore as l}from"../../registry/store.js";import{log as d}from"../utils/output.js";export default t({meta:{description:"启动 Agent(core-managed HTTP 可由 Roll 托管)"},args:{name:{type:"positional",description:"Agent 名称",required:!0}},async run({args:t}){const{agentsConfig:c}=r(),u=new l(c.dataDir),g=u.findByName(t.name);if(!g)return d.error(`Agent "${t.name}" 未找到`),void(process.exitCode=1);switch(g.runtime.ownership){case"on-demand":return void d.success(`Agent "${t.name}" 为按需模式,无需手动启动。`);case"external-managed":return d.info(`Agent "${t.name}" 由外部服务管理,Roll 不负责启动。`),void("streamable-http"===g.transport.type&&d.info(`端点: ${g.transport.endpoint}`))}const f=i(c.dataDir,g.skill.name);if(void 0!==f)try{return await s(g,{timeoutMs:3e3}),u.updateStatus(g.skill.name,"online"),void d.success(`Agent "${t.name}" 已在运行 (PID: ${String(f)})\n 端点: ${"streamable-http"===g.transport.type?g.transport.endpoint:"n/a"}`)}catch(e){return u.updateStatus(g.skill.name,"error"),d.error(`Agent "${t.name}" 进程存在但不可连接:${e instanceof Error?e.message:String(e)}`),d.info(`日志: ${n(c.dataDir,g.skill.name)}`),void(process.exitCode=1)}let $;u.updateStatus(g.skill.name,"starting");try{const r=e(a().config,g.skill.name);$=o(g,c.dataDir,r),await p(g,{startupTimeoutMs:15e3,probeTimeoutMs:2e3}),u.updateStatus(g.skill.name,"online"),d.success(`Agent "${t.name}" 已启动 (PID: ${String($)})\n 端点: ${"streamable-http"===g.transport.type?g.transport.endpoint:"n/a"}\n 日志: ${n(c.dataDir,g.skill.name)}`)}catch(e){void 0!==$&&await m(c.dataDir,g.skill.name).catch(()=>{}),u.updateStatus(g.skill.name,"error"),d.error(`Agent "${t.name}" 启动失败:${e instanceof Error?e.message:String(e)}`),d.info(`日志: ${n(c.dataDir,g.skill.name)}`),process.exitCode=1}}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{defineCommand as o}from"citty";import{readFileSync as t,writeFileSync as
|
|
1
|
+
import{defineCommand as o}from"citty";import{readFileSync as t,writeFileSync as e,existsSync as r}from"node:fs";import{resolve as n}from"node:path";import{createInterface as i}from"node:readline/promises";import{stringify as s}from"yaml";import{inspectConfigFile as c,loadConfig as a,parseConfigDocument as l,validateConfigText as f}from"../../config/loader.js";import{applyKnownConfigMigrations as d}from"../../config/migration.js";export default o({meta:{description:"管理全局配置"},args:{action:{type:"positional",description:"操作(init/get/set/migrate)",required:!0},key:{type:"positional",description:"配置键(get/set 时使用,点号分隔)",required:!1},value:{type:"positional",description:"配置值(set 时使用)",required:!1}},async run({args:o}){try{if("init"===o.action)return void await m();if("get"===o.action)return void v(o.key);if("set"===o.action)return void w(o.key,o.value);if("migrate"===o.action)return void y();console.error(`✗ 未知操作: ${o.action}。可用: init, get, set, migrate`),process.exitCode=1}catch(o){const t=o instanceof Error?o.message:String(o);console.error(`✗ ${t}`),process.exitCode=1}}});function u(o,t){const e=o?.trim();return e||t}function g({provider:o,model:t,apiKeyEnv:e}){return`llm:\n default-provider: ${o}\n default-model: ${t}\n providers:\n ${o}:\n api-key: \${${e}}\n\nask:\n confirm-threshold: 0.5\n\nagents:\n data-dir: ~/.roll-agent/agents\n`}async function p(){if(!process.stdin.isTTY){const[o,e,r]=t(0,"utf-8").split(/\r?\n/u);return{provider:u(o,"anthropic"),model:u(e,"claude-sonnet-4-20250514"),apiKeyEnv:u(r,"ANTHROPIC_API_KEY")}}const o=i({input:process.stdin,output:process.stderr}),e=u(await o.question("默认 LLM provider (anthropic/openai/qwen) [anthropic]: "),"anthropic"),r=u(await o.question("默认 model [claude-sonnet-4-20250514]: "),"claude-sonnet-4-20250514"),n=u(await o.question("API Key 环境变量名 [ANTHROPIC_API_KEY]: "),"ANTHROPIC_API_KEY");return o.close(),{provider:e,model:r,apiKeyEnv:n}}async function m(){const o=n(process.cwd(),"roll.config.yaml");if(r(o)){const t=c({configPath:o});switch(t.status){case"needs-migration":console.error(`⚠ 现有配置文件需要迁移: ${o}`),console.error(" 建议先运行 `roll config migrate`,再决定是否重新初始化。");break;case"invalid":console.error(`⚠ 现有配置文件存在问题:\n${t.error.message}`)}if(console.error(`⚠ 配置文件已存在: ${o}`),!process.stdin.isTTY)throw new Error("非交互模式下不会覆盖现有配置文件,请手动删除后重试。");const e=i({input:process.stdin,output:process.stderr}),r=await e.question("是否覆盖?(y/N) ");if(e.close(),"y"!==r.toLowerCase())return void console.error("已取消。")}const t=g(await p());f(t,o),e(o,t,"utf-8"),console.log(`✓ 配置文件已创建: ${o}`)}function h(o){const t=new Date;return`${o}.bak.${[t.getFullYear().toString().padStart(4,"0"),(t.getMonth()+1).toString().padStart(2,"0"),t.getDate().toString().padStart(2,"0"),"-",t.getHours().toString().padStart(2,"0"),t.getMinutes().toString().padStart(2,"0"),t.getSeconds().toString().padStart(2,"0")].join("")}`}function y(){const o=c();if("not-found"===o.status)throw new Error("未找到配置文件。请先运行 roll config init");if("valid"===o.status)return void console.log(`✓ 配置文件已是最新格式,无需迁移: ${o.configPath}`);if("invalid"===o.status)throw o.error;const t=l(o.raw,o.configPath),r=d(t);if(!r.ok){const o=r.issues.map(o=>` - ${o.message}`).join("\n");throw new Error(`配置无法自动迁移:\n${o}`)}if(!r.changed)return void console.log(`✓ 配置文件已是最新格式,无需迁移: ${o.configPath}`);const n=h(o.configPath);e(n,o.raw,"utf-8");const i=s(r.document,{lineWidth:0});f(i,o.configPath),e(o.configPath,i,"utf-8"),console.log(`✓ 配置文件已迁移: ${o.configPath}`),console.log(`✓ 已备份原文件: ${n}`);for(const o of r.summary)console.log(` - ${o}`)}function v(o){const{config:t,configPath:e}=a();if(!o)return console.log(JSON.stringify(t,null,2)),void(e&&console.error(`(来源: ${e})`));const r=o.split(".");let n=t;for(const t of r){if("object"!=typeof n||null===n)return console.error(`✗ 配置键 "${o}" 不存在`),void(process.exitCode=1);n=n[t]}if(void 0===n)return console.error(`✗ 配置键 "${o}" 不存在`),void(process.exitCode=1);console.log("object"==typeof n?JSON.stringify(n,null,2):String(n))}function $(o){return/^[A-Z][A-Z0-9_]*$/.test(o)?o:o.replace(/[A-Z]/g,o=>`-${o.toLowerCase()}`)}function w(o,r){if(!o||void 0===r)return console.error("✗ 用法: roll config set <key> <value>"),console.error(" 示例: roll config set ask.confirmThreshold 0.5"),void(process.exitCode=1);const{configPath:n}=a();if(!n)return console.error("✗ 未找到配置文件。请先运行 roll config init"),void(process.exitCode=1);const i=t(n,"utf-8"),c=l(i,n),d=o.split(".");let u=c;for(let o=0;o<d.length-1;o++){const t=$(d[o]),e=u[t];("object"!=typeof e||null===e||Array.isArray(e))&&(u[t]={}),u=u[t]}const g=$(d[d.length-1]);let p=r;"true"===r?p=!0:"false"===r?p=!1:/^\d+(\.\d+)?$/.test(r)&&(p=Number(r)),u[g]=p;const m=s(c,{lineWidth:0});f(m,n),e(n,m,"utf-8"),console.log(`✓ ${o} = ${String(p)}`),console.error(` (已写入: ${n})`)}
|