@orcha-ai/runtime-bridge 0.1.40 → 0.1.41

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/README.md CHANGED
@@ -76,11 +76,11 @@ npm run build
76
76
 
77
77
  Build produces `bin/orcha-runtime-bridge.js` and the clean npm package in `dist/package`, including the OpenClaw plugin. Bridge is distributed through npm; backend images do not bundle a separate browser download.
78
78
 
79
- Version 0.1.40 ships the OpenClaw native Orcha Channel adapter and bundled Gateway plugin, including channel delivery, active messages/files and authorized background runs. Bridge and the bundled plugin now share the release version. It retains the device pairing and ordinary-directory Codex execution from 0.1.39 and keeps `orcha-runtime-node.v2` unchanged. Deploying Orcha does not publish npm or upgrade connected devices automatically. Build and validate the release tarball before publishing:
79
+ Version 0.1.41 fixes native Channel reply classification against the OpenClaw 2026.7.1 SDK and propagates delivery failures through the HTTP request instead of throwing from the host queue's error observer. It retains the native Channel adapter, active messages/files and authorized background runs from 0.1.40. Bridge and the bundled plugin share the release version; `orcha-runtime-node.v2` is unchanged. Deploying Orcha does not publish npm or upgrade connected devices automatically. Build and validate the release tarball before publishing:
80
80
 
81
81
  ```bash
82
82
  npm run pack:local
83
- npm publish ./dist/orcha-ai-runtime-bridge-0.1.40.tgz --access public --registry=https://registry.npmjs.org
83
+ npm publish ./dist/orcha-ai-runtime-bridge-0.1.41.tgz --access public --registry=https://registry.npmjs.org
84
84
  ```
85
85
 
86
86
  After updating the npm package on a device, run `orcha-runtime-bridge reload --url ...` to switch the existing background process to the installed version. The earlier manually downloaded foreground process must be stopped before connecting with npm to avoid duplicate connections.
@@ -89,6 +89,8 @@ For native OpenClaw Channel use, also update the bundled OpenClaw plugin using t
89
89
 
90
90
  Tests cover discovery errors, paths, public-field filtering, immutable commands, exact OpenClaw IDs, atomic configuration, capacity, reconnect, MCP lifecycle and cancellation. The live Codex model test is opt-in; fixtures do not certify a real vendor account or OpenClaw Gateway version.
91
91
 
92
+ To check reply classification against the real SDK without installing or starting a Gateway, extract the official `openclaw@2026.7.1` npm tarball and run `npm run test:openclaw-sdk -- /absolute/path/to/extracted/package`. This check imports the actual SDK functions, covering final text/media, reasoning, commentary, status/progress notices and TTS supplements; it does not replace a live host/model acceptance test.
93
+
92
94
  ## Delegated group member tools
93
95
 
94
96
  Codex supports task-scoped Orcha MCP through the existing local transport adapter. OpenClaw additionally requires the bundled Gateway plugin, a trusted binding endpoint and Gateway authentication. Discovery/import does not install the plugin or configure these credentials. Claude Code's delegated dynamic MCP adapter remains unsupported and returns an explicit error.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{spawn as Ua}from"node:child_process";import{closeSync as Pa,existsSync as zn,mkdirSync as ka,openSync as La,readFileSync as or,rmSync as va,statSync as Bn,writeFileSync as Vn}from"node:fs";import{dirname as Da,resolve as ur}from"node:path";import{fileURLToPath as Ha}from"node:url";import{createHash as Tr}from"node:crypto";import{mkdir as cs,readFile as us,writeFile as ls,rename as ds}from"node:fs/promises";import{join as _r}from"node:path";import{homedir as fs,hostname as ps}from"node:os";import{execFile as es}from"node:child_process";import{access as rs,realpath as ns}from"node:fs/promises";import{constants as ss}from"node:fs";import{delimiter as is,join as hr,isAbsolute as mr}from"node:path";import{homedir as pr}from"node:os";async function os(e,t=process.env){let r=process.platform==="win32"?[".exe",".cmd",".bat",""]:[""];for(let n of(t.PATH||"").split(is).filter(mr))for(let s of r){let i=hr(n,`${e}${s}`);try{return await rs(i,ss.X_OK),i}catch{}}return null}function as(e,t){return new Promise(r=>es(e,t,{timeout:8e3,maxBuffer:1024*1024,windowsHide:!0},(n,s)=>r({code:n?n.code:0,stdout:String(s||"")})))}async function ie(e){let t=e==="~"?pr():e.startsWith("~/")?hr(pr(),e.slice(2)):e;if(!mr(t))throw new Error("\u5DE5\u4F5C\u76EE\u5F55\u5FC5\u987B\u662F\u8BBE\u5907\u4E0A\u7684\u7EDD\u5BF9\u8DEF\u5F84\u6216 ~/ \u5F00\u5934\u7684\u8DEF\u5F84");let r=await ns(t),{stat:n}=await import("node:fs/promises");if(!(await n(r)).isDirectory())throw new Error("\u5DE5\u4F5C\u76EE\u5F55\u4E0D\u662F\u6587\u4EF6\u5939");return r}async function gr({find:e=os,run:t=as,cwd:r=process.cwd()}={}){return(await Promise.all(["codex","claude","openclaw"].map(async s=>{let i=await e(s);if(!i)return[];let o={codex:"Codex",claude:"Claude Code",openclaw:"OpenClaw"}[s],c=await t(i,["--version"]),u=c.code===0&&c.stdout.match(/\d+\.\d+\.\d+[^\s]*/)?.[0]||"",d={id:s,name:o,framework:s,version:u,workspace:r,managed:!1};if(c.code!==0)return[{...d,status:"error",message:"\u7A0B\u5E8F\u65E0\u6CD5\u542F\u52A8\uFF0C\u8BF7\u5728\u672C\u673A\u68C0\u67E5\u5B89\u88C5"}];if(s==="openclaw"){let h=await t(i,["agents","list","--json"]),g;try{g=JSON.parse(h.stdout)}catch{}if(h.code!==0||!Array.isArray(g))return[{...d,status:"error",message:"\u65E0\u6CD5\u8BFB\u53D6 OpenClaw \u667A\u80FD\u4F53\uFF0C\u8BF7\u68C0\u67E5\u672C\u673A\u914D\u7F6E"}];let y=await t(i,["health","--json"]);return g.filter(R=>typeof R.id=="string"&&typeof R.workspace=="string").slice(0,32).map(R=>({...d,id:`openclaw:${R.id}`,name:R.name||R.identityName||R.id,workspace:R.workspace,managed:!0,localAgentId:R.id,command:i,status:y.code===0?"ready":"needs_setup",message:y.code===0?"":"\u8BF7\u5148\u5728\u672C\u673A\u542F\u52A8\u5E76\u914D\u7F6E OpenClaw Gateway"}))}let f=await t(i,s==="codex"?["login","status"]:["auth","status"]),p=f.code===0?"ready":f.code===1?"needs_login":"error";return[{...d,command:i,status:p,message:p==="needs_login"?`\u8BF7\u5728\u672C\u673A\u8FD0\u884C ${s} ${s==="codex"?"login":"auth login"}`:p==="error"?"\u767B\u5F55\u72B6\u6001\u68C0\u6D4B\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5 CLI \u7248\u672C":""}]}))).flat()}async function yr(e,t){let r=`${e}.${process.pid}.tmp`;await ls(r,JSON.stringify(t),{mode:384}),await ds(r,e)}function ae(e){let t=new URL(e);if(t.username||t.password||t.search||t.hash||t.protocol!=="https:"&&!(t.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(t.hostname)))throw new Error("\u8FDE\u63A5\u5730\u5740\u5FC5\u987B\u4F7F\u7528 HTTPS\uFF1B\u4EC5\u672C\u673A\u5F00\u53D1\u5141\u8BB8 HTTP");let r=_r(fs(),".orcha","devices"),n=_r(r,Tr("sha256").update(t.toString()).digest("hex").slice(0,20));return{address:t,root:r,profile:`${n}.json`,pidFile:`${n}.pid`,logFile:`${n}.log`}}async function Et(e,{url:t,pairCode:r}){let{address:n,root:s,profile:i}=ae(t||e.orchaUrl);await cs(s,{recursive:!0,mode:448});let o;if(r){let c=await fetch(new URL("api/agent-devices/pairings/exchange",`${n.toString().replace(/\/+$/,"")}/`),{method:"POST",redirect:"error",headers:{"content-type":"application/json"},signal:AbortSignal.timeout(15e3),body:JSON.stringify({code:r,name:ps()})}),u=await c.json();if(!c.ok||!u.success)throw new Error(u.message||u.detail||"\u8BBE\u5907\u8FDE\u63A5\u5931\u8D25");o={...u.data,targets:{}},await yr(i,o)}else try{o=JSON.parse(await us(i,"utf8"))}catch{throw new Error("\u6CA1\u6709\u5DF2\u8FDE\u63A5\u8BBE\u5907\uFF0C\u8BF7\u4ECE\u667A\u80FD\u4F53\u9875\u9762\u751F\u6210\u8FDE\u63A5\u7801")}e.orchaUrl=n.toString().replace(/\/+$/,""),e.mode="node",e.nodeId=o.nodeCode,e.nodeName=o.nodeName,e.nodeToken=o.token,e.targets=o.targets,e.defaultTargetCode="",e.deviceConnection=new oe(e,o,async()=>yr(i,o))}var oe=class{constructor(t,r,n,s=gr){this.config=t,this.profile=r,this.persist=n,this.discover=s}async candidates(){return{candidates:(await this.discover()).map(({command:r,localAgentId:n,...s})=>s)}}async configure(t,r){if(!Array.isArray(t.selections)||!t.selections.length||t.selections.length>32)throw new Error("\u6DFB\u52A0\u9879\u65E0\u6548");let n=new Map((await this.discover()).map(u=>[u.id,u])),s={...r.targets},i=[],o=new Set;for(let u of t.selections){let d=n.get(u.candidateId);if(!d||d.status!=="ready"||o.has(d.id))throw new Error("\u53D1\u73B0\u7ED3\u679C\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u68C0\u6D4B");o.add(d.id);let f=String(u.name||"").trim();if(!f||f.length>128)throw new Error("\u667A\u80FD\u4F53\u540D\u79F0\u65E0\u6548");let p=await ie(String(u.workspace||""));if(d.managed&&p!==await ie(d.workspace))throw new Error("\u5DF2\u6709\u667A\u80FD\u4F53\u5FC5\u987B\u6CBF\u7528\u672C\u673A\u5DE5\u4F5C\u76EE\u5F55");let h=`${this.config.nodeId}:${Tr("sha256").update(d.id).digest("hex").slice(0,20)}`;if([...r.sessions.values()].some(g=>g.targetCode===h))throw new Error("\u6B64\u667A\u80FD\u4F53\u4ECD\u6709\u4F1A\u8BDD\uFF0C\u8BF7\u5148\u7ED3\u675F\u4F1A\u8BDD\u518D\u4FEE\u6539\u63A5\u5165");s[h]={name:f,workspace:p,command:d.command,type:d.managed?"openclaw":"cli",...d.managed?{openclawAgentId:d.localAgentId}:d.framework==="codex"?{terminalProtocol:"codex",args:["exec","--skip-git-repo-check","--json"],promptMode:"stdin",outputMode:"json-lines",captureLastMessage:!0}:{terminalProtocol:"claude",args:["-p","--output-format","json","--no-session-persistence"],promptMode:"args",outputMode:"json-lines"}},i.push({candidateId:d.id,name:f,workspace:p,targetCode:h,framework:d.framework})}let c=this.profile.targets;this.profile.targets=s;try{await this.persist()}catch(u){throw this.profile.targets=c,u}return r.targets=s,this.config.targets=s,r.notifyCapacityChanged(),{agents:i}}};import{createHash as Ao,randomUUID as Vt}from"node:crypto";var tt="0.1.40";function ft(){return new Date().toISOString()}function U(e,t=2){return String(e).padStart(t,"0")}function wr(e){let t=e>=0?"+":"-",r=Math.abs(e);return`${t}${U(Math.floor(r/60))}:${U(r%60)}`}function hs(e){let t=-e.getTimezoneOffset();return[`${e.getFullYear()}-${U(e.getMonth()+1)}-${U(e.getDate())}`,`T${U(e.getHours())}:${U(e.getMinutes())}:${U(e.getSeconds())}.${U(e.getMilliseconds(),3)}`,wr(t)].join("")}function ms(e,t){let r=new Intl.DateTimeFormat("en-US",{timeZone:t,hourCycle:"h23",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}),n={};for(let s of r.formatToParts(e))s.type!=="literal"&&(n[s.type]=Number(s.value));return n}function gs(e,t){let r=ms(e,t),n=Date.UTC(r.year,r.month-1,r.day,r.hour,r.minute,r.second,e.getMilliseconds()),s=Math.round((n-e.getTime())/6e4);return[`${r.year}-${U(r.month)}-${U(r.day)}`,`T${U(r.hour)}:${U(r.minute)}:${U(r.second)}.${U(e.getMilliseconds(),3)}`,wr(s)].join("")}function _s(e=new Date){let t=a(process.env.ORCHA_RUNTIME_LOG_TIMEZONE||process.env.TZ||"Asia/Shanghai");try{return gs(e,t)}catch{return hs(e)}}function l(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function a(e){return String(e??"").trim()}function _(e,t){let r=Number.parseInt(String(e??""),10);return Number.isFinite(r)?r:t}function b(e){return Array.isArray(e)?e.map(String):[]}function et(e,t,r=process.cwd()){let n=l(e)?e:{};return a(n.cwd)||a(n.workspace)||a(t)||a(r)||process.cwd()}var Ot="[redacted]",ys=/(authorization|api[_-]?key|credential|password|secret|token)/i;function It(e){return ys.test(a(e))}function Rr(e,t=[]){let r=String(e??"");for(let n of t){let s=String(n??"");s.length>=4&&(r=r.split(s).join(Ot))}return r.replace(/((?:authorization|api[_-]?key|credential|password|secret|token)\s*[:=]\s*)(?:"[^"]*"|'[^']*'|[^\s,;]+)/gi,`$1${Ot}`).replace(/([?&](?:api[_-]?key|credential|password|secret|token)=)[^&\s]+/gi,`$1${Ot}`)}function V(e,t=new WeakSet){if(e==null)return e;if(typeof e=="bigint")return e.toString();if(typeof e!="object")return e;if(e instanceof Date)return e.toISOString();if(e instanceof Error){if(t.has(e))return"[circular]";t.add(e);let s={name:e.name,message:e.message};e.stack&&(s.stack=e.stack);for(let i of Object.keys(e))s[i]=V(e[i],t);return t.delete(e),s}if(t.has(e))return"[circular]";if(t.add(e),Array.isArray(e)){let s=e.map(i=>V(i,t));return t.delete(e),s}let r={},n=It(e.name||e.key);for(let[s,i]of Object.entries(e))r[s]=It(s)||n&&s.toLowerCase()==="value"?Ot:V(i,t);return t.delete(e),r}function Sr(e,t=4e3){let r=JSON.stringify(V(e))??String(e);return!Number.isFinite(t)||r.length<=t?r:`${r.slice(0,t)}...`}function m(e,t,r,n={}){let s={ts:_s(),level:e,module:t,msg:r,...l(n)?V(n):{}};console.error(JSON.stringify(s))}function xt(e){return Array.isArray(e)?e.map(t=>l(t)?t.type==="text"?a(t.text):t.type==="file"?a(t.uri):t.type==="image"?a(t.uri):"":"").filter(Boolean).join(`
2
+ import{spawn as Ua}from"node:child_process";import{closeSync as Pa,existsSync as zn,mkdirSync as ka,openSync as La,readFileSync as or,rmSync as va,statSync as Bn,writeFileSync as Vn}from"node:fs";import{dirname as Da,resolve as ur}from"node:path";import{fileURLToPath as Ha}from"node:url";import{createHash as Tr}from"node:crypto";import{mkdir as cs,readFile as us,writeFile as ls,rename as ds}from"node:fs/promises";import{join as _r}from"node:path";import{homedir as fs,hostname as ps}from"node:os";import{execFile as es}from"node:child_process";import{access as rs,realpath as ns}from"node:fs/promises";import{constants as ss}from"node:fs";import{delimiter as is,join as hr,isAbsolute as mr}from"node:path";import{homedir as pr}from"node:os";async function os(e,t=process.env){let r=process.platform==="win32"?[".exe",".cmd",".bat",""]:[""];for(let n of(t.PATH||"").split(is).filter(mr))for(let s of r){let i=hr(n,`${e}${s}`);try{return await rs(i,ss.X_OK),i}catch{}}return null}function as(e,t){return new Promise(r=>es(e,t,{timeout:8e3,maxBuffer:1024*1024,windowsHide:!0},(n,s)=>r({code:n?n.code:0,stdout:String(s||"")})))}async function ie(e){let t=e==="~"?pr():e.startsWith("~/")?hr(pr(),e.slice(2)):e;if(!mr(t))throw new Error("\u5DE5\u4F5C\u76EE\u5F55\u5FC5\u987B\u662F\u8BBE\u5907\u4E0A\u7684\u7EDD\u5BF9\u8DEF\u5F84\u6216 ~/ \u5F00\u5934\u7684\u8DEF\u5F84");let r=await ns(t),{stat:n}=await import("node:fs/promises");if(!(await n(r)).isDirectory())throw new Error("\u5DE5\u4F5C\u76EE\u5F55\u4E0D\u662F\u6587\u4EF6\u5939");return r}async function gr({find:e=os,run:t=as,cwd:r=process.cwd()}={}){return(await Promise.all(["codex","claude","openclaw"].map(async s=>{let i=await e(s);if(!i)return[];let o={codex:"Codex",claude:"Claude Code",openclaw:"OpenClaw"}[s],c=await t(i,["--version"]),u=c.code===0&&c.stdout.match(/\d+\.\d+\.\d+[^\s]*/)?.[0]||"",d={id:s,name:o,framework:s,version:u,workspace:r,managed:!1};if(c.code!==0)return[{...d,status:"error",message:"\u7A0B\u5E8F\u65E0\u6CD5\u542F\u52A8\uFF0C\u8BF7\u5728\u672C\u673A\u68C0\u67E5\u5B89\u88C5"}];if(s==="openclaw"){let h=await t(i,["agents","list","--json"]),g;try{g=JSON.parse(h.stdout)}catch{}if(h.code!==0||!Array.isArray(g))return[{...d,status:"error",message:"\u65E0\u6CD5\u8BFB\u53D6 OpenClaw \u667A\u80FD\u4F53\uFF0C\u8BF7\u68C0\u67E5\u672C\u673A\u914D\u7F6E"}];let y=await t(i,["health","--json"]);return g.filter(R=>typeof R.id=="string"&&typeof R.workspace=="string").slice(0,32).map(R=>({...d,id:`openclaw:${R.id}`,name:R.name||R.identityName||R.id,workspace:R.workspace,managed:!0,localAgentId:R.id,command:i,status:y.code===0?"ready":"needs_setup",message:y.code===0?"":"\u8BF7\u5148\u5728\u672C\u673A\u542F\u52A8\u5E76\u914D\u7F6E OpenClaw Gateway"}))}let f=await t(i,s==="codex"?["login","status"]:["auth","status"]),p=f.code===0?"ready":f.code===1?"needs_login":"error";return[{...d,command:i,status:p,message:p==="needs_login"?`\u8BF7\u5728\u672C\u673A\u8FD0\u884C ${s} ${s==="codex"?"login":"auth login"}`:p==="error"?"\u767B\u5F55\u72B6\u6001\u68C0\u6D4B\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5 CLI \u7248\u672C":""}]}))).flat()}async function yr(e,t){let r=`${e}.${process.pid}.tmp`;await ls(r,JSON.stringify(t),{mode:384}),await ds(r,e)}function ae(e){let t=new URL(e);if(t.username||t.password||t.search||t.hash||t.protocol!=="https:"&&!(t.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(t.hostname)))throw new Error("\u8FDE\u63A5\u5730\u5740\u5FC5\u987B\u4F7F\u7528 HTTPS\uFF1B\u4EC5\u672C\u673A\u5F00\u53D1\u5141\u8BB8 HTTP");let r=_r(fs(),".orcha","devices"),n=_r(r,Tr("sha256").update(t.toString()).digest("hex").slice(0,20));return{address:t,root:r,profile:`${n}.json`,pidFile:`${n}.pid`,logFile:`${n}.log`}}async function Et(e,{url:t,pairCode:r}){let{address:n,root:s,profile:i}=ae(t||e.orchaUrl);await cs(s,{recursive:!0,mode:448});let o;if(r){let c=await fetch(new URL("api/agent-devices/pairings/exchange",`${n.toString().replace(/\/+$/,"")}/`),{method:"POST",redirect:"error",headers:{"content-type":"application/json"},signal:AbortSignal.timeout(15e3),body:JSON.stringify({code:r,name:ps()})}),u=await c.json();if(!c.ok||!u.success)throw new Error(u.message||u.detail||"\u8BBE\u5907\u8FDE\u63A5\u5931\u8D25");o={...u.data,targets:{}},await yr(i,o)}else try{o=JSON.parse(await us(i,"utf8"))}catch{throw new Error("\u6CA1\u6709\u5DF2\u8FDE\u63A5\u8BBE\u5907\uFF0C\u8BF7\u4ECE\u667A\u80FD\u4F53\u9875\u9762\u751F\u6210\u8FDE\u63A5\u7801")}e.orchaUrl=n.toString().replace(/\/+$/,""),e.mode="node",e.nodeId=o.nodeCode,e.nodeName=o.nodeName,e.nodeToken=o.token,e.targets=o.targets,e.defaultTargetCode="",e.deviceConnection=new oe(e,o,async()=>yr(i,o))}var oe=class{constructor(t,r,n,s=gr){this.config=t,this.profile=r,this.persist=n,this.discover=s}async candidates(){return{candidates:(await this.discover()).map(({command:r,localAgentId:n,...s})=>s)}}async configure(t,r){if(!Array.isArray(t.selections)||!t.selections.length||t.selections.length>32)throw new Error("\u6DFB\u52A0\u9879\u65E0\u6548");let n=new Map((await this.discover()).map(u=>[u.id,u])),s={...r.targets},i=[],o=new Set;for(let u of t.selections){let d=n.get(u.candidateId);if(!d||d.status!=="ready"||o.has(d.id))throw new Error("\u53D1\u73B0\u7ED3\u679C\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u68C0\u6D4B");o.add(d.id);let f=String(u.name||"").trim();if(!f||f.length>128)throw new Error("\u667A\u80FD\u4F53\u540D\u79F0\u65E0\u6548");let p=await ie(String(u.workspace||""));if(d.managed&&p!==await ie(d.workspace))throw new Error("\u5DF2\u6709\u667A\u80FD\u4F53\u5FC5\u987B\u6CBF\u7528\u672C\u673A\u5DE5\u4F5C\u76EE\u5F55");let h=`${this.config.nodeId}:${Tr("sha256").update(d.id).digest("hex").slice(0,20)}`;if([...r.sessions.values()].some(g=>g.targetCode===h))throw new Error("\u6B64\u667A\u80FD\u4F53\u4ECD\u6709\u4F1A\u8BDD\uFF0C\u8BF7\u5148\u7ED3\u675F\u4F1A\u8BDD\u518D\u4FEE\u6539\u63A5\u5165");s[h]={name:f,workspace:p,command:d.command,type:d.managed?"openclaw":"cli",...d.managed?{openclawAgentId:d.localAgentId}:d.framework==="codex"?{terminalProtocol:"codex",args:["exec","--skip-git-repo-check","--json"],promptMode:"stdin",outputMode:"json-lines",captureLastMessage:!0}:{terminalProtocol:"claude",args:["-p","--output-format","json","--no-session-persistence"],promptMode:"args",outputMode:"json-lines"}},i.push({candidateId:d.id,name:f,workspace:p,targetCode:h,framework:d.framework})}let c=this.profile.targets;this.profile.targets=s;try{await this.persist()}catch(u){throw this.profile.targets=c,u}return r.targets=s,this.config.targets=s,r.notifyCapacityChanged(),{agents:i}}};import{createHash as Ao,randomUUID as Vt}from"node:crypto";var tt="0.1.41";function ft(){return new Date().toISOString()}function U(e,t=2){return String(e).padStart(t,"0")}function wr(e){let t=e>=0?"+":"-",r=Math.abs(e);return`${t}${U(Math.floor(r/60))}:${U(r%60)}`}function hs(e){let t=-e.getTimezoneOffset();return[`${e.getFullYear()}-${U(e.getMonth()+1)}-${U(e.getDate())}`,`T${U(e.getHours())}:${U(e.getMinutes())}:${U(e.getSeconds())}.${U(e.getMilliseconds(),3)}`,wr(t)].join("")}function ms(e,t){let r=new Intl.DateTimeFormat("en-US",{timeZone:t,hourCycle:"h23",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}),n={};for(let s of r.formatToParts(e))s.type!=="literal"&&(n[s.type]=Number(s.value));return n}function gs(e,t){let r=ms(e,t),n=Date.UTC(r.year,r.month-1,r.day,r.hour,r.minute,r.second,e.getMilliseconds()),s=Math.round((n-e.getTime())/6e4);return[`${r.year}-${U(r.month)}-${U(r.day)}`,`T${U(r.hour)}:${U(r.minute)}:${U(r.second)}.${U(e.getMilliseconds(),3)}`,wr(s)].join("")}function _s(e=new Date){let t=a(process.env.ORCHA_RUNTIME_LOG_TIMEZONE||process.env.TZ||"Asia/Shanghai");try{return gs(e,t)}catch{return hs(e)}}function l(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function a(e){return String(e??"").trim()}function _(e,t){let r=Number.parseInt(String(e??""),10);return Number.isFinite(r)?r:t}function b(e){return Array.isArray(e)?e.map(String):[]}function et(e,t,r=process.cwd()){let n=l(e)?e:{};return a(n.cwd)||a(n.workspace)||a(t)||a(r)||process.cwd()}var Ot="[redacted]",ys=/(authorization|api[_-]?key|credential|password|secret|token)/i;function It(e){return ys.test(a(e))}function Rr(e,t=[]){let r=String(e??"");for(let n of t){let s=String(n??"");s.length>=4&&(r=r.split(s).join(Ot))}return r.replace(/((?:authorization|api[_-]?key|credential|password|secret|token)\s*[:=]\s*)(?:"[^"]*"|'[^']*'|[^\s,;]+)/gi,`$1${Ot}`).replace(/([?&](?:api[_-]?key|credential|password|secret|token)=)[^&\s]+/gi,`$1${Ot}`)}function V(e,t=new WeakSet){if(e==null)return e;if(typeof e=="bigint")return e.toString();if(typeof e!="object")return e;if(e instanceof Date)return e.toISOString();if(e instanceof Error){if(t.has(e))return"[circular]";t.add(e);let s={name:e.name,message:e.message};e.stack&&(s.stack=e.stack);for(let i of Object.keys(e))s[i]=V(e[i],t);return t.delete(e),s}if(t.has(e))return"[circular]";if(t.add(e),Array.isArray(e)){let s=e.map(i=>V(i,t));return t.delete(e),s}let r={},n=It(e.name||e.key);for(let[s,i]of Object.entries(e))r[s]=It(s)||n&&s.toLowerCase()==="value"?Ot:V(i,t);return t.delete(e),r}function Sr(e,t=4e3){let r=JSON.stringify(V(e))??String(e);return!Number.isFinite(t)||r.length<=t?r:`${r.slice(0,t)}...`}function m(e,t,r,n={}){let s={ts:_s(),level:e,module:t,msg:r,...l(n)?V(n):{}};console.error(JSON.stringify(s))}function xt(e){return Array.isArray(e)?e.map(t=>l(t)?t.type==="text"?a(t.text):t.type==="file"?a(t.uri):t.type==="image"?a(t.uri):"":"").filter(Boolean).join(`
3
3
  `):""}var Ct=class{constructor(t){this.agent=t,this.sessionCounter=0}async sessionNew(){return this.sessionCounter+=1,{sessionId:`echo-${this.agent.agentId}-${this.sessionCounter}`}}async sessionPrompt(t,r){let n=xt(t.prompt);return r({sessionId:t.sessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:n?`Echo runtime received: ${n}`:"Echo runtime received an empty prompt."}}}),{stopReason:"end_turn"}}async sessionCancel(){return{ok:!0}}};import{spawn as Ts}from"node:child_process";var pt="2.0",ce=3e4,ws=4e3;function bt(e,t){let r=Object.entries(l(t)?t:{}).filter(([n])=>It(n)).map(([,n])=>n);return Rr(e,r)}function Rs(e){return{code:Number.isInteger(e?.code)?e.code:-32e3,message:a(e?.message)||String(e),data:l(e?.data)?e.data:void 0}}function Ss(e){if(!l(e))return new Error(String(e||"runtime error"));let t=a(e.message)||"runtime error",r="data"in e?Sr(e.data,4e3):"",n=new Error(r?`${t}; data=${r}`:t);return n.rpcCode=e.code,n.data=e.data,n}function Es(e){return l(e)&&"id"in e&&!("method"in e)}function Os(e){return l(e)&&typeof e.method=="string"&&"id"in e}function Is(e){return l(e)&&typeof e.method=="string"&&!("id"in e)}var At=class{constructor({command:t,args:r=[],cwd:n,env:s,label:i,framing:o="line",detached:c=!0}){this.command=t,this.args=Array.isArray(r)?r.map(String):[],this.cwd=n||process.cwd(),this.env=l(s)?{...s}:{...process.env},this.label=i||t,this.framing=o==="content-length"?"content-length":"line",this.detached=c!==!1,this.child=null,this.exited=!1,this.exitCode=null,this.exitSignal=null,this.stopPromise=null,this.stderrTail="",this.spawnError=null,this.lineBuffer="",this.headerBuffer=Buffer.alloc(0),this.seq=0,this.pending=new Map,this.notificationHandlers=new Map,this.requestHandlers=new Map,this.exitHandlers=new Set}async start({initialize:t=!0,initializeParams:r={},initializeTimeoutMs:n=ce}={}){if(!(this.child&&!this.exited)&&(this.exited=!1,this.exitCode=null,this.exitSignal=null,this.stderrTail="",this.spawnError=null,this.child=Ts(this.command,this.args,{cwd:this.cwd,env:this.env,stdio:["pipe","pipe","pipe"],detached:this.detached}),this.child.stdout.on("data",s=>this.onStdout(s)),this.child.stderr.setEncoding("utf8"),this.child.stderr.on("data",s=>{this.stderrTail=`${this.stderrTail}${s}`.slice(-ws);let i=bt(s.trimEnd(),this.env);i&&m("debug","runtime.stderr","runtime stderr",{target:this.label,text:i})}),this.child.on("exit",(s,i)=>this.handleExit(s,i)),this.child.on("error",s=>{this.spawnError=s,this.rejectAll(s)}),t)){let s=Math.max(1,_(n,ce));try{await this.call("initialize",{protocolVersion:1,clientCapabilities:{},...r},s)}catch(i){let o=this.startupFailureDetail(),c=bt(i?.message||i,this.env);m("warn","runtime.initialize","runtime initialize failed",{target:this.label,timeoutMs:s,cause:c,...o}),await this.stop("initialize failed",{termTimeoutMs:1e3,killTimeoutMs:1e3});let u=o.stderr?`; stderr: ${o.stderr}`:`; command=${o.command}; cwd=${o.cwd}`;throw Object.assign(new Error(`runtime initialize failed: ${c}${u}`,{cause:i}),{code:"RUNTIME_INITIALIZE_FAILED",detail:o})}}}startupFailureDetail(){return{command:this.command,cwd:this.cwd,exited:this.exited,exitCode:this.exitCode,exitSignal:this.exitSignal,...this.spawnError?{spawnError:bt(this.spawnError.message,this.env)}:{},...this.stderrTail.trim()?{stderr:bt(this.stderrTail.trim(),this.env)}:{}}}onStdout(t){if(this.framing==="content-length"){this.onContentLengthData(Buffer.isBuffer(t)?t:Buffer.from(t));return}this.onLineData(t.toString("utf8"))}onLineData(t){this.lineBuffer+=t;let r=this.lineBuffer.split(/\r?\n/);this.lineBuffer=r.pop()||"";for(let n of r){let s=n.trim();s&&this.dispatchRaw(s)}}onContentLengthData(t){for(this.headerBuffer=Buffer.concat([this.headerBuffer,t]);this.headerBuffer.length>0;){let r=this.headerBuffer.indexOf(`\r
4
4
  \r
5
5
  `);if(r<0)return;let s=this.headerBuffer.subarray(0,r).toString("utf8").match(/content-length:\s*(\d+)/i);if(!s){m("warn","runtime.protocol","missing Content-Length header",{target:this.label}),this.headerBuffer=Buffer.alloc(0);return}let i=Number.parseInt(s[1],10),o=r+4,c=o+i;if(this.headerBuffer.length<c)return;let u=this.headerBuffer.subarray(o,c).toString("utf8");this.headerBuffer=this.headerBuffer.subarray(c),this.dispatchRaw(u)}}dispatchRaw(t){let r;try{r=JSON.parse(t)}catch(n){m("warn","runtime.protocol","invalid JSON frame",{target:this.label,error:String(n)});return}this.dispatch(r)}dispatch(t){if(Es(t)){this.resolveResponse(t);return}if(Os(t)){this.handleRequest(t);return}Is(t)&&this.handleNotification(t)}resolveResponse(t){let r=String(t.id),n=this.pending.get(r);n&&(clearTimeout(n.timer),this.pending.delete(r),t.error?(m("warn","runtime.protocol","runtime rpc error",{target:this.label,method:n.method,requestId:r,error:t.error}),n.reject(Ss(t.error))):n.resolve(t.result))}async handleRequest(t){let r=this.requestHandlers.get(t.method);if(!r){this.writeFrame({jsonrpc:pt,id:t.id,error:{code:-32601,message:`method not found: ${t.method}`}});return}try{let n=await r(l(t.params)?t.params:{},t);this.writeFrame({jsonrpc:pt,id:t.id,result:n??{}})}catch(n){this.writeFrame({jsonrpc:pt,id:t.id,error:Rs(n)})}}handleNotification(t){let r=this.notificationHandlers.get(t.method);if(r)for(let n of r)n(l(t.params)?t.params:{},t)}call(t,r={},n=ce){if(!this.child||!this.child.stdin||this.exited)return Promise.reject(new Error("runtime process is not running"));let s=`${t}_${++this.seq}`,i={jsonrpc:pt,id:s,method:t,params:r};return new Promise((o,c)=>{let u=setTimeout(()=>{this.pending.delete(s),c(new Error(`${t} timed out after ${n}ms`))},n);this.pending.set(s,{resolve:o,reject:c,timer:u,method:t}),this.writeFrame(i,d=>{d&&(clearTimeout(u),this.pending.delete(s),c(d))})})}notify(t,r={}){this.writeFrame({jsonrpc:pt,method:t,params:r})}writeFrame(t,r){if(!this.child?.stdin||this.exited){r?.(new Error("runtime process is not running"));return}let n=JSON.stringify(t),s=this.framing==="content-length"?`Content-Length: ${Buffer.byteLength(n,"utf8")}\r
@@ -1,5 +1,5 @@
1
- import{getPluginRuntimeGatewayRequestScope as me}from"openclaw/plugin-sdk/plugin-runtime";import{isReplyPayloadTerminalContent as ge}from"openclaw/plugin-sdk/reply-payload";import{loadOutboundMediaFromUrl as we}from"openclaw/plugin-sdk/outbound-media";var k={controlTools:["find_capabilities_and_skills","describe_capability","inspect_result","execute_capability"],residentTools:["search_orcha_docs"]};var J=Object.freeze([...k.controlTools,...k.residentTools]),ie=new Set(J),se=8*1024*1024;function V(t,r){if(!Array.isArray(t)||t.length!==1)throw new Error("one task-scoped Orcha MCP server is required");let p=t[0],d=new URL(p.url);if(p.name!=="orcha"||p.type!=="http"||!["http:","https:"].includes(d.protocol)||d.username||d.password||d.hash||r&&d.href!==new URL(r).href)throw new Error("Orcha MCP server does not match the trusted binding");let u=Object.fromEntries((p.headers||[]).map(({name:f,value:h})=>[f.toLowerCase(),h]));if(!String(u.authorization||"").startsWith("Bearer "))throw new Error("Orcha MCP task credentials are missing");return{url:d.href,headers:{...u,"content-type":"application/json",accept:"application/json"}}}async function R(t){let r=0,p=[];for await(let d of t){if(r+=d.length,r>se)throw new Error("MCP payload exceeds the size limit");p.push(Buffer.from(d))}return JSON.parse(Buffer.concat(p).toString("utf8"))}async function z(t,r,p){let d=await fetch(t.url,{method:"POST",headers:t.headers,body:JSON.stringify(r),redirect:"error",signal:AbortSignal.any([AbortSignal.timeout(36e5),...p?[p]:[]])});if(!d.ok)throw new Error(`Orcha MCP request failed (${d.status})`);if(d.status===202||d.status===204)return null;let u=await R(d.body);if(!u||u.jsonrpc!=="2.0"||u.id!==r.id)throw new Error("Orcha MCP response identity mismatch");return u}async function Y(t,r){let p=await z(t,{jsonrpc:"2.0",id:"orcha-bind-tools",method:"tools/list"},r),d=p?.result?.tools;if(p?.error)throw new Error("Orcha MCP tool discovery failed");return ce(d)}function ce(t){if(!Array.isArray(t)||t.some(r=>!r||!ie.has(r.name)||r.inputSchema?.type!=="object"||typeof r.description!="string")||new Set(t.map(r=>r.name)).size!==t.length||t.length&&k.controlTools.some(r=>!t.some(p=>p.name===r)))throw new Error("Orcha MCP returned an unsupported or invalid authorized tool catalog");return t}function X(t,r){let p=u=>Array.isArray(u)?u.map(p):u&&typeof u=="object"?Object.fromEntries(Object.keys(u).sort().map(f=>[f,p(u[f])])):u,d=u=>u.map(({name:f,inputSchema:h})=>({name:f,inputSchema:h})).sort((f,h)=>f.name.localeCompare(h.name));return JSON.stringify(p(d(t)))===JSON.stringify(p(d(r)))}var F=t=>Object.assign(new Error(t),{status:409});function Z(t){let r=new Map,p=t.pluginConfig?.allowedOrchaMcpUrl;if(!p)throw new Error("Orcha plugin requires allowedOrchaMcpUrl");function d(h,l=r.get(h)){!l||r.get(h)!==l||(l.lifetime.abort(),clearTimeout(l.timer),r.delete(h))}function u(h){let l=r.get(h);return l&&l.deadline<=Date.now()?(d(h,l),null):l}async function f(h,{refresh:l=!1}={}){let{runId:c,sessionKey:g,agentCode:v,expiresAt:M,mcpServer:E}=h,S=Date.parse(M);if(typeof c!="string"||!c||typeof g!="string"||!g||typeof v!="string"||!v||!g.startsWith(`agent:${v}:`)||!Number.isFinite(S)||S<=Date.now()||S>Date.now()+24*36e5)throw new Error("invalid_binding_scope");let T=u(g);if(l&&!T||T&&(T.runId!==c||T.agentCode!==v||T.deadline!==S))throw F("original_binding_unavailable_or_changed");let N=V([E],p),D=T?.lifetime||new AbortController,e=await Y(N,D.signal);if(u(g)!==T)throw F("binding_changed");if(T){if(!X(T.tools,e))throw F("frozen_tool_catalog_changed");T.upstream=N}else{let o={runId:c,agentCode:v,deadline:S,upstream:N,tools:e,lifetime:D};o.timer=setTimeout(()=>d(g,o),S-Date.now()),o.timer.unref?.(),r.set(g,o)}}return t.registerTool(h=>{let l=u(h.sessionKey);return!l||h.agentId!==l.agentCode?null:l.tools.map(c=>({name:`orcha_${c.name}`,label:`Orcha ${c.name}`,description:c.description,parameters:c.inputSchema,async execute(g,v,M){if(u(h.sessionKey)!==l||h.agentId!==l.agentCode||!g||!l.tools.some(S=>S.name===c.name))throw new Error("Orcha task binding expired or changed");let E=await z(l.upstream,{jsonrpc:"2.0",id:g,method:"tools/call",params:{name:c.name,arguments:v}},AbortSignal.any([l.lifetime.signal,...M?[M]:[]]));if(E?.error||!E?.result)throw new Error("Orcha rejected this task-scoped tool call");return{content:E.result.content,details:E.result.structuredContent,isError:E.result.isError===!0}}}))},{names:J.map(h=>`orcha_${h}`)}),{bind:f,active:u,release:d,allowedUrl:p}}import{createHash as le}from"node:crypto";import{mkdirSync as de,readFileSync as ue,renameSync as pe,writeFileSync as he}from"node:fs";import{join as q}from"node:path";var K=t=>le("sha256").update(JSON.stringify(t)).digest("hex"),I=(t,r=409)=>Object.assign(new Error(t),{status:r,code:t}),B=t=>typeof t=="string"&&/^[1-9]\d{0,18}$/.test(t),fe=t=>new Promise(r=>setTimeout(r,t));function ee(t,r,p,d,u){let f=new Map,h=new Map,l=()=>t.config;function c(e,o=l()){let n=o?.channels?.orcha?.accounts?.[e];if(!B(e)||!n||n.enabled===!1||!n.serviceToken||!n.agentId)throw I("orcha_channel_account_unavailable",403);return{...n,accountId:e}}async function g(e,o,n,{cfg:a,signal:i,method:m="POST"}={}){let s=c(e,a),b=new URL(`/api/agent-channels${o}`,r.allowedUrl),_=n instanceof FormData,w=await fetch(b,{method:m,redirect:"error",signal:AbortSignal.any([AbortSignal.timeout(3e4),...i?[i]:[]]),headers:{authorization:`Bearer ${s.serviceToken}`,..._?{}:{"content-type":"application/json"}},...n!==void 0?{body:_?n:JSON.stringify(n)}:{}}),A=await R(w.body);if(!w.ok||A.success!==!0)throw I(`orcha_channel_request_${w.status}`,w.status);return A.data}function v(e,o="runs"){if(!/^[a-zA-Z0-9_-]{1,128}$/.test(e))throw I("invalid_record_identity",422);let n=q(t.runtime.state.resolveStateDir(),"plugins","orcha-runtime",o);return de(n,{recursive:!0,mode:448}),q(n,`${e}.json`)}function M(e,o){try{return JSON.parse(ue(v(e,o),"utf8"))}catch(n){if(n.code==="ENOENT")return null;throw n}}function E(e,o,n){let a=v(e,n),i=`${a}.pending`;he(i,JSON.stringify(o),{mode:384}),pe(i,a)}async function S(e,o=!1){let n=c(e.delivery?.bindingId),{runId:a,delivery:i}=e;if(!B(a)||!B(i.sessionId)||!B(i.taskContextId)||i.mode!=="channel"||e.agentCode!==n.agentId)throw I("invalid_channel_delivery",422);if(!Array.isArray(e.prompt)||e.prompt.some(y=>!["text","image","file"].includes(y.type)||(y.type==="text"?typeof y.text!="string":typeof y.uri!="string")))throw I("invalid_channel_prompt",422);let m=K({agentCode:e.agentCode,delivery:i,prompt:e.prompt}),s=M(a);if(s&&s.requestHash!==m)throw I("channel_delivery_conflict");if(s?.status==="completed")return s.result;if(s?.status==="failed")throw I(s.error);let b=f.get(a),_=s?.expiresAt||e.expiresAt,w=`agent:${n.agentId}:orcha:${i.bindingId}:${a}`,A=s?.hostRunId||`orcha-${a}`;if(s&&!b||e.attachOnly&&!b&&!s)throw I("RUNTIME_OPERATION_NOT_FOUND");if(b)return await r.bind({runId:a,sessionKey:w,agentCode:n.agentId,expiresAt:_,mcpServer:e.mcpServer},{refresh:!0}),o?{refreshed:!0}:b.promise;if(o)throw I("RUNTIME_OPERATION_NOT_FOUND");let C=new AbortController,P={controller:C,promise:null};return f.set(a,P),P.promise=(async()=>{await r.bind({runId:a,sessionKey:w,agentCode:n.agentId,expiresAt:_,mcpServer:e.mcpServer}),E(a,{requestHash:m,status:"running",sessionKey:w,hostRunId:A,expiresAt:_});let y=[],$=[],L=setTimeout(()=>C.abort(I("run_timeout")),Date.parse(_)-Date.now());try{let j=t.runtime.channel.reply;if(typeof j?.dispatchReplyWithBufferedBlockDispatcher!="function")throw I("OPENCLAW_CHANNEL_RUNTIME_UNAVAILABLE");let U=e.prompt.filter(O=>O.type==="text").map(O=>O.text).join(`
1
+ import{getPluginRuntimeGatewayRequestScope as Oe}from"openclaw/plugin-sdk/plugin-runtime";import{loadOutboundMediaFromUrl as Te}from"openclaw/plugin-sdk/outbound-media";var L={controlTools:["find_capabilities_and_skills","describe_capability","inspect_result","execute_capability"],residentTools:["search_orcha_docs"]};var J=Object.freeze([...L.controlTools,...L.residentTools]),ce=new Set(J),le=8*1024*1024;function V(t,r){if(!Array.isArray(t)||t.length!==1)throw new Error("one task-scoped Orcha MCP server is required");let p=t[0],d=new URL(p.url);if(p.name!=="orcha"||p.type!=="http"||!["http:","https:"].includes(d.protocol)||d.username||d.password||d.hash||r&&d.href!==new URL(r).href)throw new Error("Orcha MCP server does not match the trusted binding");let u=Object.fromEntries((p.headers||[]).map(({name:m,value:h})=>[m.toLowerCase(),h]));if(!String(u.authorization||"").startsWith("Bearer "))throw new Error("Orcha MCP task credentials are missing");return{url:d.href,headers:{...u,"content-type":"application/json",accept:"application/json"}}}async function R(t){let r=0,p=[];for await(let d of t){if(r+=d.length,r>le)throw new Error("MCP payload exceeds the size limit");p.push(Buffer.from(d))}return JSON.parse(Buffer.concat(p).toString("utf8"))}async function F(t,r,p){let d=await fetch(t.url,{method:"POST",headers:t.headers,body:JSON.stringify(r),redirect:"error",signal:AbortSignal.any([AbortSignal.timeout(36e5),...p?[p]:[]])});if(!d.ok)throw new Error(`Orcha MCP request failed (${d.status})`);if(d.status===202||d.status===204)return null;let u=await R(d.body);if(!u||u.jsonrpc!=="2.0"||u.id!==r.id)throw new Error("Orcha MCP response identity mismatch");return u}async function Y(t,r){let p=await F(t,{jsonrpc:"2.0",id:"orcha-bind-tools",method:"tools/list"},r),d=p?.result?.tools;if(p?.error)throw new Error("Orcha MCP tool discovery failed");return de(d)}function de(t){if(!Array.isArray(t)||t.some(r=>!r||!ce.has(r.name)||r.inputSchema?.type!=="object"||typeof r.description!="string")||new Set(t.map(r=>r.name)).size!==t.length||t.length&&L.controlTools.some(r=>!t.some(p=>p.name===r)))throw new Error("Orcha MCP returned an unsupported or invalid authorized tool catalog");return t}function X(t,r){let p=u=>Array.isArray(u)?u.map(p):u&&typeof u=="object"?Object.fromEntries(Object.keys(u).sort().map(m=>[m,p(u[m])])):u,d=u=>u.map(({name:m,inputSchema:h})=>({name:m,inputSchema:h})).sort((m,h)=>m.name.localeCompare(h.name));return JSON.stringify(p(d(t)))===JSON.stringify(p(d(r)))}var z=t=>Object.assign(new Error(t),{status:409});function Z(t){let r=new Map,p=t.pluginConfig?.allowedOrchaMcpUrl;if(!p)throw new Error("Orcha plugin requires allowedOrchaMcpUrl");function d(h,l=r.get(h)){!l||r.get(h)!==l||(l.lifetime.abort(),clearTimeout(l.timer),r.delete(h))}function u(h){let l=r.get(h);return l&&l.deadline<=Date.now()?(d(h,l),null):l}async function m(h,{refresh:l=!1}={}){let{runId:c,sessionKey:g,agentCode:v,expiresAt:M,mcpServer:E}=h,S=Date.parse(M);if(typeof c!="string"||!c||typeof g!="string"||!g||typeof v!="string"||!v||!g.startsWith(`agent:${v}:`)||!Number.isFinite(S)||S<=Date.now()||S>Date.now()+24*36e5)throw new Error("invalid_binding_scope");let b=u(g);if(l&&!b||b&&(b.runId!==c||b.agentCode!==v||b.deadline!==S))throw z("original_binding_unavailable_or_changed");let N=V([E],p),D=b?.lifetime||new AbortController,e=await Y(N,D.signal);if(u(g)!==b)throw z("binding_changed");if(b){if(!X(b.tools,e))throw z("frozen_tool_catalog_changed");b.upstream=N}else{let o={runId:c,agentCode:v,deadline:S,upstream:N,tools:e,lifetime:D};o.timer=setTimeout(()=>d(g,o),S-Date.now()),o.timer.unref?.(),r.set(g,o)}}return t.registerTool(h=>{let l=u(h.sessionKey);return!l||h.agentId!==l.agentCode?null:l.tools.map(c=>({name:`orcha_${c.name}`,label:`Orcha ${c.name}`,description:c.description,parameters:c.inputSchema,async execute(g,v,M){if(u(h.sessionKey)!==l||h.agentId!==l.agentCode||!g||!l.tools.some(S=>S.name===c.name))throw new Error("Orcha task binding expired or changed");let E=await F(l.upstream,{jsonrpc:"2.0",id:g,method:"tools/call",params:{name:c.name,arguments:v}},AbortSignal.any([l.lifetime.signal,...M?[M]:[]]));if(E?.error||!E?.result)throw new Error("Orcha rejected this task-scoped tool call");return{content:E.result.content,details:E.result.structuredContent,isError:E.result.isError===!0}}}))},{names:J.map(h=>`orcha_${h}`)}),{bind:m,active:u,release:d,allowedUrl:p}}import{createHash as ue}from"node:crypto";import{mkdirSync as pe,readFileSync as he,renameSync as me,writeFileSync as fe}from"node:fs";import{join as q}from"node:path";var K=t=>ue("sha256").update(JSON.stringify(t)).digest("hex"),I=(t,r=409)=>Object.assign(new Error(t),{status:r,code:t}),k=t=>typeof t=="string"&&/^[1-9]\d{0,18}$/.test(t),ge=t=>new Promise(r=>setTimeout(r,t));function ee(t,r,p,d,u){let m=new Map,h=new Map,l=()=>t.config;function c(e,o=l()){let n=o?.channels?.orcha?.accounts?.[e];if(!k(e)||!n||n.enabled===!1||!n.serviceToken||!n.agentId)throw I("orcha_channel_account_unavailable",403);return{...n,accountId:e}}async function g(e,o,n,{cfg:a,signal:i,method:f="POST"}={}){let s=c(e,a),T=new URL(`/api/agent-channels${o}`,r.allowedUrl),_=n instanceof FormData,w=await fetch(T,{method:f,redirect:"error",signal:AbortSignal.any([AbortSignal.timeout(3e4),...i?[i]:[]]),headers:{authorization:`Bearer ${s.serviceToken}`,..._?{}:{"content-type":"application/json"}},...n!==void 0?{body:_?n:JSON.stringify(n)}:{}}),A=await R(w.body);if(!w.ok||A.success!==!0)throw I(`orcha_channel_request_${w.status}`,w.status);return A.data}function v(e,o="runs"){if(!/^[a-zA-Z0-9_-]{1,128}$/.test(e))throw I("invalid_record_identity",422);let n=q(t.runtime.state.resolveStateDir(),"plugins","orcha-runtime",o);return pe(n,{recursive:!0,mode:448}),q(n,`${e}.json`)}function M(e,o){try{return JSON.parse(he(v(e,o),"utf8"))}catch(n){if(n.code==="ENOENT")return null;throw n}}function E(e,o,n){let a=v(e,n),i=`${a}.pending`;fe(i,JSON.stringify(o),{mode:384}),me(i,a)}async function S(e,o=!1){let n=c(e.delivery?.bindingId),{runId:a,delivery:i}=e;if(!k(a)||!k(i.sessionId)||!k(i.taskContextId)||i.mode!=="channel"||e.agentCode!==n.agentId)throw I("invalid_channel_delivery",422);if(!Array.isArray(e.prompt)||e.prompt.some(y=>!["text","image","file"].includes(y.type)||(y.type==="text"?typeof y.text!="string":typeof y.uri!="string")))throw I("invalid_channel_prompt",422);let f=K({agentCode:e.agentCode,delivery:i,prompt:e.prompt}),s=M(a);if(s&&s.requestHash!==f)throw I("channel_delivery_conflict");if(s?.status==="completed")return s.result;if(s?.status==="failed")throw I(s.error);let T=m.get(a),_=s?.expiresAt||e.expiresAt,w=`agent:${n.agentId}:orcha:${i.bindingId}:${a}`,A=s?.hostRunId||`orcha-${a}`;if(s&&!T||e.attachOnly&&!T&&!s)throw I("RUNTIME_OPERATION_NOT_FOUND");if(T)return await r.bind({runId:a,sessionKey:w,agentCode:n.agentId,expiresAt:_,mcpServer:e.mcpServer},{refresh:!0}),o?{refreshed:!0}:T.promise;if(o)throw I("RUNTIME_OPERATION_NOT_FOUND");let C=new AbortController,P={controller:C,promise:null};return m.set(a,P),P.promise=(async()=>{await r.bind({runId:a,sessionKey:w,agentCode:n.agentId,expiresAt:_,mcpServer:e.mcpServer}),E(a,{requestHash:f,status:"running",sessionKey:w,hostRunId:A,expiresAt:_});let y=[],$=[],j,ne=setTimeout(()=>C.abort(I("run_timeout")),Date.parse(_)-Date.now());try{let B=t.runtime.channel.reply;if(typeof B?.dispatchReplyWithBufferedBlockDispatcher!="function")throw I("OPENCLAW_CHANNEL_RUNTIME_UNAVAILABLE");let x=e.prompt.filter(O=>O.type==="text").map(O=>O.text).join(`
2
2
 
3
- `),W=e.prompt.filter(O=>O.type!=="text"),re={Body:U,BodyForAgent:U,RawBody:U,From:`orcha:${i.memberId}`,To:`orcha:${i.sessionId}`,SessionKey:w,AccountId:i.bindingId,Provider:"orcha",Surface:"orcha",ChatType:"direct",OriginatingChannel:"orcha",OriginatingTo:i.sessionId,MessageSid:a,MediaUrls:W.map(O=>O.uri),MediaTypes:W.map(O=>O.mimeType||"application/octet-stream"),CommandAuthorized:!1,CommandInterpretationSuppressed:!0,WasMentioned:!0};if(await j.dispatchReplyWithBufferedBlockDispatcher({ctx:re,cfg:l(),replyOptions:{runId:A,abortSignal:C.signal,suppressTyping:!0},dispatcherOptions:{deliver:async(O,ne)=>{if(C.signal.throwIfAborted(),ne.kind==="final"&&d(O)){let oe=O.mediaUrls||(O.mediaUrl?[O.mediaUrl]:[]),x=l(),G=x?.agents?.list?.find(H=>H.id===n.agentId)?.workspace||x?.agents?.defaults?.workspace;for(let H of oe)$.push(await T(i.bindingId,i.sessionId,H,{cfg:x,signal:C.signal,mediaLocalRoots:G?[G]:void 0}));O.text&&y.push(O.text)}},onError:O=>{throw O}}}),C.signal.throwIfAborted(),!y.length&&!$.length)throw I("runtime_node_empty_result");let Q={stopReason:"end_turn",content:y.join(`
3
+ `),W=e.prompt.filter(O=>O.type!=="text"),oe={Body:x,BodyForAgent:x,RawBody:x,From:`orcha:${i.memberId}`,To:`orcha:${i.sessionId}`,SessionKey:w,AccountId:i.bindingId,Provider:"orcha",Surface:"orcha",ChatType:"direct",OriginatingChannel:"orcha",OriginatingTo:i.sessionId,MessageSid:a,MediaUrls:W.map(O=>O.uri),MediaTypes:W.map(O=>O.mimeType||"application/octet-stream"),CommandAuthorized:!1,CommandInterpretationSuppressed:!0,WasMentioned:!0};if(await B.dispatchReplyWithBufferedBlockDispatcher({ctx:oe,cfg:l(),replyOptions:{runId:A,abortSignal:C.signal,suppressTyping:!0},dispatcherOptions:{deliver:async(O,ae)=>{if(C.signal.throwIfAborted(),ae.kind==="final"&&d(O)){let ie=O.mediaUrls||(O.mediaUrl?[O.mediaUrl]:[]),U=l(),G=U?.agents?.list?.find(H=>H.id===n.agentId)?.workspace||U?.agents?.defaults?.workspace;for(let H of ie)$.push(await b(i.bindingId,i.sessionId,H,{cfg:U,signal:C.signal,mediaLocalRoots:G?[G]:void 0}));O.text&&y.push(O.text)}},onError:O=>{j??=O}}}),j)throw j;if(C.signal.throwIfAborted(),!y.length&&!$.length)throw I("runtime_node_empty_result");let Q={stopReason:"end_turn",content:y.join(`
4
4
 
5
- `)||"\u5DF2\u751F\u6210\u9644\u4EF6",inputParts:$,sessionId:w};return E(a,{requestHash:m,status:"completed",sessionKey:w,hostRunId:A,expiresAt:_,result:Q}),Q}catch(j){throw E(a,{requestHash:m,status:"failed",sessionKey:w,hostRunId:A,expiresAt:_,error:j.code||"channel_host_failed"}),j}finally{clearTimeout(L),r.release(w),f.delete(a)}})().catch(y=>{throw r.release(w),f.delete(a),y}),P.promise}async function T(e,o,n,a){let i=await u(n,{maxBytes:33554432,mediaAccess:a.mediaAccess,mediaReadFile:a.mediaReadFile,mediaLocalRoots:a.mediaLocalRoots});a.signal?.throwIfAborted();let m=new FormData;return m.set("sessionId",o),m.set("file",new Blob([i.buffer],{type:i.contentType||"application/octet-stream"}),i.fileName||"attachment"),(await g(e,"/files",m,{cfg:a.cfg,signal:a.signal})).inputPart}async function N(e){e.signal?.throwIfAborted();let o=e.to.replace(/^orcha:/,"");if(!B(o))throw I("invalid_conversation",422);let n=e.preparedMessageId||e.deliveryQueueId&&`${e.deliveryQueueId}:${e.deliveryPartIndex||0}`;if(!n)throw I("OPENCLAW_DURABLE_DELIVERY_ID_REQUIRED");let a=K([e.accountId,n]),i=K([o,e.text,e.mediaUrl,e.replyToId]),m=M(a,"sends");if(m&&m.requestHash!==i)throw I("channel_send_conflict");let s=h.get(a);if(s){if(s.requestHash!==i)throw I("channel_send_conflict");return s.promise}let b=(async()=>{let _=m?.payload;if(!_){let A=e.mediaUrl?[await T(e.accountId,o,e.mediaUrl,e)]:[];_={sourceMessageId:`openclaw:${a}`,sessionId:o,content:e.text||"",inputParts:A,...e.replyToId?{replyToMessageId:e.replyToId}:{}},E(a,{requestHash:i,payload:_},"sends")}return await e.onPlatformSendDispatch?.(),e.assertDirectAdapterHandoff?.(),e.signal?.throwIfAborted(),{channel:"orcha",messageId:(await g(e.accountId,"/messages",_,{cfg:e.cfg,signal:e.signal})).messageId,chatId:o}})().finally(()=>h.delete(a));return h.set(a,{requestHash:i,promise:b}),b}t.registerChannel({plugin:{id:"orcha",meta:{id:"orcha",label:"Orcha",selectionLabel:"Orcha",docsPath:"/channels/orcha",blurb:"Enterprise people and Agent conversations"},capabilities:{chatTypes:["direct","group"],media:!0},config:{listAccountIds:e=>Object.keys(e?.channels?.orcha?.accounts||{}),inspectAccount:(e,o)=>{let n=e?.channels?.orcha?.accounts?.[o];return{enabled:!!(n&&n.enabled!==!1),configured:!!(n?.serviceToken&&n?.agentId),tokenStatus:n?.serviceToken?"available":"missing"}},resolveAccount:(e,o)=>c(o,e),isEnabled:e=>e.enabled!==!1,isConfigured:e=>!!(e.serviceToken&&e.agentId)},outbound:{deliveryMode:"direct",textChunkLimit:1e5,sendText:N,sendMedia:N}}});async function D(e){let{accountId:o,grantId:n,externalInvocationId:a}=e;c(o);let i=await g(o,"/runs",{grantId:n,externalInvocationId:a,input:e.input||{}}),m=i.agentRunId;if(["completed","failed","cancelled","expired"].includes(i.status))return i;let s;do s=await g(o,`/runs/${m}/claim`,{}),s.attemptId||await fe(Math.max(1,s.retryAfterSeconds||2)*1e3);while(!s.attemptId);let b=`agent:${c(o).agentId}:orcha:${o}:${m}`,_,w=!1,A=setInterval(async()=>{if(!w){w=!0;try{let y=await g(o,`/runs/${m}/heartbeat`,{attemptId:s.attemptId});r.active(b)&&await r.bind({runId:m,sessionKey:b,agentCode:c(o).agentId,expiresAt:s.expiresAt,mcpServer:y.mcpServer},{refresh:!0})}catch(y){_=y,f.get(m)?.controller.abort(y),r.release(b)}finally{w=!1}}},Math.max(1,s.heartbeatIntervalSeconds)*1e3),C,P;try{let y;try{y=await S({runId:m,agentCode:c(o).agentId,delivery:s.delivery,prompt:[{type:"text",text:JSON.stringify({task:s.prompt,eventInput:s.input})}],mcpServer:s.mcpServer,expiresAt:s.expiresAt,attachOnly:s.recovery})}catch(L){P=L}if(_)throw _;C=P?{attemptId:s.attemptId,result:P.code||"channel_host_failed",artifacts:[],status:"failed"}:{attemptId:s.attemptId,result:y.content,artifacts:y.inputParts||[],status:"completed"};let $=await g(o,`/runs/${m}/complete`,C);if(P)throw P;return $}finally{clearInterval(A),r.release(b)}}for(let[e,o]of[["deliveries",S],["background",D]])t.registerHttpRoute({path:`/plugins/orcha-runtime/${e}`,auth:"gateway",match:"exact",async handler(n,a){try{if(!["POST","PATCH","DELETE"].includes(n.method))throw I("method_not_allowed",405);let i=await R(n);if(await p(),n.method==="DELETE"){let s=f.get(i.runId);s?.controller.abort(I("RUNTIME_OPERATION_CANCELLED")),a.writeHead(200,{"content-type":"application/json"}).end(JSON.stringify({cancelled:!!s}));return}if(n.method==="PATCH"&&e!=="deliveries")throw I("method_not_allowed",405);let m=await o(i,n.method==="PATCH");await p(),a.writeHead(200,{"content-type":"application/json"}).end(JSON.stringify(m))}catch(i){a.writableEnded||a.writeHead(i.status||500,{"content-type":"application/json"}).end(JSON.stringify({error:i.code||i.message}))}}})}function te(t,r,p){return{id:"orcha-runtime",name:"Orcha Channel and authorized tools",register(d){let u=Z(d);d.registerHttpRoute({path:"/plugins/orcha-runtime/mcp-bindings",auth:"gateway",match:"exact",async handler(f,h){let l=(c,g)=>{h.writeHead(c,{"content-type":"application/json"}),h.end(JSON.stringify(g))};try{if(f.method==="GET"){l(200,{ready:!0});return}if(!["PUT","DELETE"].includes(f.method)){l(405,{error:"method_not_allowed"});return}let c=await R(f);if(await t(),typeof c.runId!="string"||!c.runId||typeof c.sessionKey!="string"||!c.sessionKey){l(422,{error:"invalid_binding_identity"});return}let g=u.active(c.sessionKey);if(f.headers["if-match"]&&f.headers["if-match"]!==c.runId){l(409,{error:"binding_run_conflict"});return}if(g&&g.runId!==c.runId){l(409,{error:"session_already_bound"});return}f.method==="DELETE"?u.release(c.sessionKey):await u.bind(c,{refresh:!!f.headers["if-match"]}),l(200,{[f.method==="DELETE"?"released":"bound"]:!0})}catch(c){h.writableEnded||l(c.status||422,{error:c.message})}}}),ee(d,u,t,r,p)}}}var ke=te(async()=>{await me()?.revalidate?.()},ge,we);export{ke as default};
5
+ `)||"\u5DF2\u751F\u6210\u9644\u4EF6",inputParts:$,sessionId:w};return E(a,{requestHash:f,status:"completed",sessionKey:w,hostRunId:A,expiresAt:_,result:Q}),Q}catch(B){throw E(a,{requestHash:f,status:"failed",sessionKey:w,hostRunId:A,expiresAt:_,error:B.code||"channel_host_failed"}),B}finally{clearTimeout(ne),r.release(w),m.delete(a)}})().catch(y=>{throw r.release(w),m.delete(a),y}),P.promise}async function b(e,o,n,a){let i=await u(n,{maxBytes:33554432,mediaAccess:a.mediaAccess,mediaReadFile:a.mediaReadFile,mediaLocalRoots:a.mediaLocalRoots});a.signal?.throwIfAborted();let f=new FormData;return f.set("sessionId",o),f.set("file",new Blob([i.buffer],{type:i.contentType||"application/octet-stream"}),i.fileName||"attachment"),(await g(e,"/files",f,{cfg:a.cfg,signal:a.signal})).inputPart}async function N(e){e.signal?.throwIfAborted();let o=e.to.replace(/^orcha:/,"");if(!k(o))throw I("invalid_conversation",422);let n=e.preparedMessageId||e.deliveryQueueId&&`${e.deliveryQueueId}:${e.deliveryPartIndex||0}`;if(!n)throw I("OPENCLAW_DURABLE_DELIVERY_ID_REQUIRED");let a=K([e.accountId,n]),i=K([o,e.text,e.mediaUrl,e.replyToId]),f=M(a,"sends");if(f&&f.requestHash!==i)throw I("channel_send_conflict");let s=h.get(a);if(s){if(s.requestHash!==i)throw I("channel_send_conflict");return s.promise}let T=(async()=>{let _=f?.payload;if(!_){let A=e.mediaUrl?[await b(e.accountId,o,e.mediaUrl,e)]:[];_={sourceMessageId:`openclaw:${a}`,sessionId:o,content:e.text||"",inputParts:A,...e.replyToId?{replyToMessageId:e.replyToId}:{}},E(a,{requestHash:i,payload:_},"sends")}return await e.onPlatformSendDispatch?.(),e.assertDirectAdapterHandoff?.(),e.signal?.throwIfAborted(),{channel:"orcha",messageId:(await g(e.accountId,"/messages",_,{cfg:e.cfg,signal:e.signal})).messageId,chatId:o}})().finally(()=>h.delete(a));return h.set(a,{requestHash:i,promise:T}),T}t.registerChannel({plugin:{id:"orcha",meta:{id:"orcha",label:"Orcha",selectionLabel:"Orcha",docsPath:"/channels/orcha",blurb:"Enterprise people and Agent conversations"},capabilities:{chatTypes:["direct","group"],media:!0},config:{listAccountIds:e=>Object.keys(e?.channels?.orcha?.accounts||{}),inspectAccount:(e,o)=>{let n=e?.channels?.orcha?.accounts?.[o];return{enabled:!!(n&&n.enabled!==!1),configured:!!(n?.serviceToken&&n?.agentId),tokenStatus:n?.serviceToken?"available":"missing"}},resolveAccount:(e,o)=>c(o,e),isEnabled:e=>e.enabled!==!1,isConfigured:e=>!!(e.serviceToken&&e.agentId)},outbound:{deliveryMode:"direct",textChunkLimit:1e5,sendText:N,sendMedia:N}}});async function D(e){let{accountId:o,grantId:n,externalInvocationId:a}=e;c(o);let i=await g(o,"/runs",{grantId:n,externalInvocationId:a,input:e.input||{}}),f=i.agentRunId;if(["completed","failed","cancelled","expired"].includes(i.status))return i;let s;do s=await g(o,`/runs/${f}/claim`,{}),s.attemptId||await ge(Math.max(1,s.retryAfterSeconds||2)*1e3);while(!s.attemptId);let T=`agent:${c(o).agentId}:orcha:${o}:${f}`,_,w=!1,A=setInterval(async()=>{if(!w){w=!0;try{let y=await g(o,`/runs/${f}/heartbeat`,{attemptId:s.attemptId});r.active(T)&&await r.bind({runId:f,sessionKey:T,agentCode:c(o).agentId,expiresAt:s.expiresAt,mcpServer:y.mcpServer},{refresh:!0})}catch(y){_=y,m.get(f)?.controller.abort(y),r.release(T)}finally{w=!1}}},Math.max(1,s.heartbeatIntervalSeconds)*1e3),C,P;try{let y;try{y=await S({runId:f,agentCode:c(o).agentId,delivery:s.delivery,prompt:[{type:"text",text:JSON.stringify({task:s.prompt,eventInput:s.input})}],mcpServer:s.mcpServer,expiresAt:s.expiresAt,attachOnly:s.recovery})}catch(j){P=j}if(_)throw _;C=P?{attemptId:s.attemptId,result:P.code||"channel_host_failed",artifacts:[],status:"failed"}:{attemptId:s.attemptId,result:y.content,artifacts:y.inputParts||[],status:"completed"};let $=await g(o,`/runs/${f}/complete`,C);if(P)throw P;return $}finally{clearInterval(A),r.release(T)}}for(let[e,o]of[["deliveries",S],["background",D]])t.registerHttpRoute({path:`/plugins/orcha-runtime/${e}`,auth:"gateway",match:"exact",async handler(n,a){try{if(!["POST","PATCH","DELETE"].includes(n.method))throw I("method_not_allowed",405);let i=await R(n);if(await p(),n.method==="DELETE"){let s=m.get(i.runId);s?.controller.abort(I("RUNTIME_OPERATION_CANCELLED")),a.writeHead(200,{"content-type":"application/json"}).end(JSON.stringify({cancelled:!!s}));return}if(n.method==="PATCH"&&e!=="deliveries")throw I("method_not_allowed",405);let f=await o(i,n.method==="PATCH");await p(),a.writeHead(200,{"content-type":"application/json"}).end(JSON.stringify(f))}catch(i){a.writableEnded||a.writeHead(i.status||500,{"content-type":"application/json"}).end(JSON.stringify({error:i.code||i.message}))}}})}function te(t,r,p){return{id:"orcha-runtime",name:"Orcha Channel and authorized tools",register(d){let u=Z(d);d.registerHttpRoute({path:"/plugins/orcha-runtime/mcp-bindings",auth:"gateway",match:"exact",async handler(m,h){let l=(c,g)=>{h.writeHead(c,{"content-type":"application/json"}),h.end(JSON.stringify(g))};try{if(m.method==="GET"){l(200,{ready:!0});return}if(!["PUT","DELETE"].includes(m.method)){l(405,{error:"method_not_allowed"});return}let c=await R(m);if(await t(),typeof c.runId!="string"||!c.runId||typeof c.sessionKey!="string"||!c.sessionKey){l(422,{error:"invalid_binding_identity"});return}let g=u.active(c.sessionKey);if(m.headers["if-match"]&&m.headers["if-match"]!==c.runId){l(409,{error:"binding_run_conflict"});return}if(g&&g.runId!==c.runId){l(409,{error:"session_already_bound"});return}m.method==="DELETE"?u.release(c.sessionKey):await u.bind(c,{refresh:!!m.headers["if-match"]}),l(200,{[m.method==="DELETE"?"released":"bound"]:!0})}catch(c){h.writableEnded||l(c.status||422,{error:c.message})}}}),ee(d,u,t,r,p)}}}import{isFastModeAutoProgressPayload as we,isReasoningReplyPayload as ye,isReplyPayloadNonTerminalToolErrorWarning as Ie,isReplyPayloadTtsSupplement as _e}from"openclaw/plugin-sdk/reply-payload";function re(t){return!ye(t)&&!t.isCommentary&&!t.isCompactionNotice&&!t.isFallbackNotice&&!t.isStatusNotice&&!we(t)&&!Ie(t)&&!_e(t)}var ze=te(async()=>{await Oe()?.revalidate?.()},re,Te);export{ze as default};
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orcha-ai/openclaw-tools",
3
- "version": "0.1.40",
3
+ "version": "0.1.41",
4
4
  "type": "module",
5
5
  "private": true,
6
6
  "openclaw": { "extensions": ["./index.js"] }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orcha-ai/runtime-bridge",
3
- "version": "0.1.40",
3
+ "version": "0.1.41",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Local Orcha runtime bridge for ACP-compatible agent runtimes.",