@orcha-ai/runtime-bridge 0.1.2 → 0.1.3

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/.env.example CHANGED
@@ -12,6 +12,8 @@ ORCHA_RUNTIME_SESSION_PROMPT_TIMEOUT_MS=3600000
12
12
  ORCHA_RUNTIME_PERMISSION_TIMEOUT_MS=300000
13
13
  ORCHA_RUNTIME_PID_FILE=.orcha-runtime-bridge.pid
14
14
  ORCHA_RUNTIME_LOG_FILE=.orcha-runtime-bridge.log
15
+ ORCHA_RUNTIME_LOG_RETENTION_DAYS=3
16
+ ORCHA_RUNTIME_LOG_CLEANUP_INTERVAL_MS=3600000
15
17
 
16
18
  # Target examples. Keep this JSON on one line.
17
19
  ORCHA_RUNTIME_TARGETS_JSON='{"codex":{"type":"cli","command":"codex","args":["exec","--json"],"promptMode":"stdin","outputMode":"json-lines","captureLastMessage":true},"openclaw":{"type":"openclaw","command":"openclaw"},"claude":{"type":"cli","command":"claude","args":["-p","--output-format","json","--no-session-persistence"],"promptMode":"args","outputMode":"json-lines"}}'
package/README.md CHANGED
@@ -85,6 +85,16 @@ orcha-runtime-bridge start \
85
85
  Running `orcha-runtime-bridge` with no command still runs in the foreground,
86
86
  which is the right mode for systemd, Docker, launchd, and supervised services.
87
87
 
88
+ The built-in daemon keeps Runtime Bridge logs for 3 days by default. It cleans
89
+ `ORCHA_RUNTIME_LOG_FILE` on start and then once per hour, using each JSON log
90
+ line's `ts` field. Non-JSON lines and lines without a parseable timestamp are
91
+ kept. Configure with:
92
+
93
+ ```bash
94
+ ORCHA_RUNTIME_LOG_RETENTION_DAYS=3
95
+ ORCHA_RUNTIME_LOG_CLEANUP_INTERVAL_MS=3600000
96
+ ```
97
+
88
98
  The bridge loads environment variables from `ORCHA_RUNTIME_ENV_FILE` when it is
89
99
  set. Otherwise it reads `.env` from the current working directory. Real process
90
100
  environment variables always win over values from the file.
@@ -114,7 +124,8 @@ Runtime targets are configured with `ORCHA_RUNTIME_TARGETS_JSON`.
114
124
  },
115
125
  "openclaw": {
116
126
  "type": "openclaw",
117
- "command": "openclaw"
127
+ "command": "openclaw",
128
+ "mcpServers": []
118
129
  },
119
130
  "custom-acp": {
120
131
  "type": "stdio-acp",
@@ -135,6 +146,13 @@ Target types:
135
146
  - `cli`: run an independent CLI per prompt and wrap stdout as session updates.
136
147
  - `echo`: local test adapter.
137
148
 
149
+ ACP-compatible targets receive `mcpServers` in `session/new`. When omitted in
150
+ target config, the bridge sends an empty array.
151
+
152
+ OpenClaw targets use request metadata `agentCode` as the local OpenClaw agent
153
+ id, producing sessions like `agent:<agentCode>:<sessionId>`. When `agentCode`
154
+ is missing, the bridge falls back to a plain `orcha-<sessionId>` session.
155
+
138
156
  Supported stdio framing:
139
157
 
140
158
  - `line`: one JSON-RPC frame per line.
@@ -1,18 +1,20 @@
1
1
  #!/usr/bin/env node
2
- import{spawn as Ye}from"node:child_process";import{closeSync as Qe,existsSync as Ze,mkdirSync as tr,openSync as er,readFileSync as rr,rmSync as nr,writeFileSync as sr}from"node:fs";import{dirname as ir,resolve as Vt}from"node:path";import{fileURLToPath as or}from"node:url";import{randomUUID as j}from"node:crypto";var U="0.1.2";function O(){return new Date().toISOString()}function u(r){return r!==null&&typeof r=="object"&&!Array.isArray(r)}function c(r){return String(r??"").trim()}function T(r,t){let e=Number.parseInt(String(r??""),10);return Number.isFinite(e)?e:t}function k(r){return Array.isArray(r)?r.map(String):[]}function h(r,t,e,n={}){let s={ts:O(),level:r,module:t,msg:e,...u(n)?n:{}};console.error(JSON.stringify(s))}function L(r){return Array.isArray(r)?r.map(t=>u(t)?t.type==="text"?c(t.text):t.type==="file"?c(t.uri):t.type==="image"?c(t.uri):"":"").filter(Boolean).join(`
3
- `):""}var D=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,e){let n=L(t.prompt);return e({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 te}from"node:child_process";var C="2.0",ee=3e4;function re(r){return{code:Number.isInteger(r?.code)?r.code:-32e3,message:c(r?.message)||String(r),data:u(r?.data)?r.data:void 0}}function ne(r){return u(r)&&"id"in r&&!("method"in r)}function se(r){return u(r)&&typeof r.method=="string"&&"id"in r}function ie(r){return u(r)&&typeof r.method=="string"&&!("id"in r)}var F=class{constructor({command:t,args:e=[],cwd:n,env:s,label:i,framing:a="line"}){this.command=t,this.args=Array.isArray(e)?e.map(String):[],this.cwd=n||process.cwd(),this.env={...process.env,...u(s)?s:{}},this.label=i||t,this.framing=a==="content-length"?"content-length":"line",this.child=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:e={}}={}){this.child&&!this.child.killed||(this.child=te(this.command,this.args,{cwd:this.cwd,env:this.env,stdio:["pipe","pipe","pipe"]}),this.child.stdout.on("data",n=>this.onStdout(n)),this.child.stderr.setEncoding("utf8"),this.child.stderr.on("data",n=>{let s=n.trimEnd();s&&h("debug","runtime.stderr","runtime stderr",{target:this.label,text:s})}),this.child.on("exit",(n,s)=>this.handleExit(n,s)),this.child.on("error",n=>this.rejectAll(n)),t&&await this.call("initialize",{protocolVersion:1,clientCapabilities:{},...e}).catch(n=>{throw Object.assign(new Error(`runtime initialize failed: ${n.message}`),{code:"RUNTIME_INITIALIZE_FAILED"})}))}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 e=this.lineBuffer.split(/\r?\n/);this.lineBuffer=e.pop()||"";for(let n of e){let s=n.trim();s&&this.dispatchRaw(s)}}onContentLengthData(t){for(this.headerBuffer=Buffer.concat([this.headerBuffer,t]);this.headerBuffer.length>0;){let e=this.headerBuffer.indexOf(`\r
2
+ import{spawn as yr}from"node:child_process";import{closeSync as _r,existsSync as ne,mkdirSync as wr,openSync as Tr,readFileSync as ft,rmSync as Ir,statSync as Zt,writeFileSync as se}from"node:fs";import{dirname as Er,resolve as gt}from"node:path";import{fileURLToPath as Sr}from"node:url";import{randomUUID as J}from"node:crypto";var O="0.1.2";function C(){return new Date().toISOString()}function w(r,t=2){return String(r).padStart(t,"0")}function Rt(r){let t=r>=0?"+":"-",e=Math.abs(r);return`${t}${w(Math.floor(e/60))}:${w(e%60)}`}function le(r){let t=-r.getTimezoneOffset();return[`${r.getFullYear()}-${w(r.getMonth()+1)}-${w(r.getDate())}`,`T${w(r.getHours())}:${w(r.getMinutes())}:${w(r.getSeconds())}.${w(r.getMilliseconds(),3)}`,Rt(t)].join("")}function pe(r,t){let e=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 e.formatToParts(r))s.type!=="literal"&&(n[s.type]=Number(s.value));return n}function fe(r,t){let e=pe(r,t),n=Date.UTC(e.year,e.month-1,e.day,e.hour,e.minute,e.second,r.getMilliseconds()),s=Math.round((n-r.getTime())/6e4);return[`${e.year}-${w(e.month)}-${w(e.day)}`,`T${w(e.hour)}:${w(e.minute)}:${w(e.second)}.${w(r.getMilliseconds(),3)}`,Rt(s)].join("")}function me(r=new Date){let t=c(process.env.ORCHA_RUNTIME_LOG_TIMEZONE||process.env.TZ||"Asia/Shanghai");try{return fe(r,t)}catch{return le(r)}}function d(r){return r!==null&&typeof r=="object"&&!Array.isArray(r)}function c(r){return String(r??"").trim()}function I(r,t){let e=Number.parseInt(String(r??""),10);return Number.isFinite(e)?e:t}function D(r){return Array.isArray(r)?r.map(String):[]}var he="[redacted]",ge=/(authorization|api[_-]?key|credential|password|secret|token)/i;function M(r,t=new WeakSet){if(r==null)return r;if(typeof r=="bigint")return r.toString();if(typeof r!="object")return r;if(r instanceof Date)return r.toISOString();if(r instanceof Error){if(t.has(r))return"[circular]";t.add(r);let n={name:r.name,message:r.message};r.stack&&(n.stack=r.stack);for(let s of Object.keys(r))n[s]=M(r[s],t);return t.delete(r),n}if(t.has(r))return"[circular]";if(t.add(r),Array.isArray(r)){let n=r.map(s=>M(s,t));return t.delete(r),n}let e={};for(let[n,s]of Object.entries(r))e[n]=ge.test(n)?he:M(s,t);return t.delete(r),e}function xt(r,t=4e3){let e=JSON.stringify(M(r))??String(r);return!Number.isFinite(t)||e.length<=t?e:`${e.slice(0,t)}...`}function f(r,t,e,n={}){let s={ts:me(),level:r,module:t,msg:e,...d(n)?M(n):{}};console.error(JSON.stringify(s))}function F(r){return Array.isArray(r)?r.map(t=>d(t)?t.type==="text"?c(t.text):t.type==="file"?c(t.uri):t.type==="image"?c(t.uri):"":"").filter(Boolean).join(`
3
+ `):""}var $=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,e){let n=F(t.prompt);return e({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 ye}from"node:child_process";var b="2.0",_e=3e4;function we(r){return{code:Number.isInteger(r?.code)?r.code:-32e3,message:c(r?.message)||String(r),data:d(r?.data)?r.data:void 0}}function Te(r){if(!d(r))return new Error(String(r||"runtime error"));let t=c(r.message)||"runtime error",e="data"in r?xt(r.data,4e3):"",n=new Error(e?`${t}; data=${e}`:t);return n.rpcCode=r.code,n.data=r.data,n}function Ie(r){return d(r)&&"id"in r&&!("method"in r)}function Ee(r){return d(r)&&typeof r.method=="string"&&"id"in r}function Se(r){return d(r)&&typeof r.method=="string"&&!("id"in r)}var H=class{constructor({command:t,args:e=[],cwd:n,env:s,label:i,framing:a="line"}){this.command=t,this.args=Array.isArray(e)?e.map(String):[],this.cwd=n||process.cwd(),this.env={...process.env,...d(s)?s:{}},this.label=i||t,this.framing=a==="content-length"?"content-length":"line",this.child=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:e={}}={}){this.child&&!this.child.killed||(this.child=ye(this.command,this.args,{cwd:this.cwd,env:this.env,stdio:["pipe","pipe","pipe"]}),this.child.stdout.on("data",n=>this.onStdout(n)),this.child.stderr.setEncoding("utf8"),this.child.stderr.on("data",n=>{let s=n.trimEnd();s&&f("debug","runtime.stderr","runtime stderr",{target:this.label,text:s})}),this.child.on("exit",(n,s)=>this.handleExit(n,s)),this.child.on("error",n=>this.rejectAll(n)),t&&await this.call("initialize",{protocolVersion:1,clientCapabilities:{},...e}).catch(n=>{throw Object.assign(new Error(`runtime initialize failed: ${n.message}`),{code:"RUNTIME_INITIALIZE_FAILED"})}))}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 e=this.lineBuffer.split(/\r?\n/);this.lineBuffer=e.pop()||"";for(let n of e){let s=n.trim();s&&this.dispatchRaw(s)}}onContentLengthData(t){for(this.headerBuffer=Buffer.concat([this.headerBuffer,t]);this.headerBuffer.length>0;){let e=this.headerBuffer.indexOf(`\r
4
4
  \r
5
- `);if(e<0)return;let s=this.headerBuffer.subarray(0,e).toString("utf8").match(/content-length:\s*(\d+)/i);if(!s){h("warn","runtime.protocol","missing Content-Length header",{target:this.label}),this.headerBuffer=Buffer.alloc(0);return}let i=Number.parseInt(s[1],10),a=e+4,o=a+i;if(this.headerBuffer.length<o)return;let d=this.headerBuffer.subarray(a,o).toString("utf8");this.headerBuffer=this.headerBuffer.subarray(o),this.dispatchRaw(d)}}dispatchRaw(t){let e;try{e=JSON.parse(t)}catch(n){h("warn","runtime.protocol","invalid JSON frame",{target:this.label,error:String(n)});return}this.dispatch(e)}dispatch(t){if(ne(t)){this.resolveResponse(t);return}if(se(t)){this.handleRequest(t);return}ie(t)&&this.handleNotification(t)}resolveResponse(t){let e=String(t.id),n=this.pending.get(e);n&&(clearTimeout(n.timer),this.pending.delete(e),t.error?n.reject(new Error(u(t.error)?String(t.error.message||"runtime error"):String(t.error))):n.resolve(t.result))}async handleRequest(t){let e=this.requestHandlers.get(t.method);if(!e){this.writeFrame({jsonrpc:C,id:t.id,error:{code:-32601,message:`method not found: ${t.method}`}});return}try{let n=await e(u(t.params)?t.params:{},t);this.writeFrame({jsonrpc:C,id:t.id,result:n??{}})}catch(n){this.writeFrame({jsonrpc:C,id:t.id,error:re(n)})}}handleNotification(t){let e=this.notificationHandlers.get(t.method);if(e)for(let n of e)n(u(t.params)?t.params:{},t)}call(t,e={},n=ee){if(!this.child||!this.child.stdin||this.child.killed)return Promise.reject(new Error("runtime process is not running"));let s=`${t}_${++this.seq}`,i={jsonrpc:C,id:s,method:t,params:e};return new Promise((a,o)=>{let d=setTimeout(()=>{this.pending.delete(s),o(new Error(`${t} timed out after ${n}ms`))},n);this.pending.set(s,{resolve:a,reject:o,timer:d}),this.writeFrame(i,l=>{l&&(clearTimeout(d),this.pending.delete(s),o(l))})})}notify(t,e={}){this.writeFrame({jsonrpc:C,method:t,params:e})}writeFrame(t,e){if(!this.child?.stdin||this.child.killed){e?.(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
5
+ `);if(e<0)return;let s=this.headerBuffer.subarray(0,e).toString("utf8").match(/content-length:\s*(\d+)/i);if(!s){f("warn","runtime.protocol","missing Content-Length header",{target:this.label}),this.headerBuffer=Buffer.alloc(0);return}let i=Number.parseInt(s[1],10),a=e+4,o=a+i;if(this.headerBuffer.length<o)return;let u=this.headerBuffer.subarray(a,o).toString("utf8");this.headerBuffer=this.headerBuffer.subarray(o),this.dispatchRaw(u)}}dispatchRaw(t){let e;try{e=JSON.parse(t)}catch(n){f("warn","runtime.protocol","invalid JSON frame",{target:this.label,error:String(n)});return}this.dispatch(e)}dispatch(t){if(Ie(t)){this.resolveResponse(t);return}if(Ee(t)){this.handleRequest(t);return}Se(t)&&this.handleNotification(t)}resolveResponse(t){let e=String(t.id),n=this.pending.get(e);n&&(clearTimeout(n.timer),this.pending.delete(e),t.error?(f("warn","runtime.protocol","runtime rpc error",{target:this.label,method:n.method,requestId:e,error:t.error}),n.reject(Te(t.error))):n.resolve(t.result))}async handleRequest(t){let e=this.requestHandlers.get(t.method);if(!e){this.writeFrame({jsonrpc:b,id:t.id,error:{code:-32601,message:`method not found: ${t.method}`}});return}try{let n=await e(d(t.params)?t.params:{},t);this.writeFrame({jsonrpc:b,id:t.id,result:n??{}})}catch(n){this.writeFrame({jsonrpc:b,id:t.id,error:we(n)})}}handleNotification(t){let e=this.notificationHandlers.get(t.method);if(e)for(let n of e)n(d(t.params)?t.params:{},t)}call(t,e={},n=_e){if(!this.child||!this.child.stdin||this.child.killed)return Promise.reject(new Error("runtime process is not running"));let s=`${t}_${++this.seq}`,i={jsonrpc:b,id:s,method:t,params:e};return new Promise((a,o)=>{let u=setTimeout(()=>{this.pending.delete(s),o(new Error(`${t} timed out after ${n}ms`))},n);this.pending.set(s,{resolve:a,reject:o,timer:u,method:t}),this.writeFrame(i,l=>{l&&(clearTimeout(u),this.pending.delete(s),o(l))})})}notify(t,e={}){this.writeFrame({jsonrpc:b,method:t,params:e})}writeFrame(t,e){if(!this.child?.stdin||this.child.killed){e?.(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
6
6
  \r
7
7
  ${n}`:`${n}
8
- `;this.child.stdin.write(s,e)}onNotification(t,e){let n=this.notificationHandlers.get(t)||new Set;return n.add(e),this.notificationHandlers.set(t,n),()=>{n.delete(e),n.size===0&&this.notificationHandlers.delete(t)}}onRequest(t,e){return this.requestHandlers.set(t,e),()=>this.requestHandlers.delete(t)}onExit(t){return this.exitHandlers.add(t),()=>this.exitHandlers.delete(t)}rejectAll(t){for(let e of this.pending.values())clearTimeout(e.timer),e.reject(t);this.pending.clear()}handleExit(t,e){this.rejectAll(new Error(`runtime exited before response (${t}/${e})`));for(let n of this.exitHandlers)n(t,e)}stop(t="stop"){!this.child||this.child.killed||(h("info","runtime","stopping runtime",{target:this.label,reason:t}),this.child.kill("SIGTERM"),setTimeout(()=>{this.child&&!this.child.killed&&this.child.kill("SIGKILL")},5e3).unref())}};import{randomUUID as Tt}from"node:crypto";import{existsSync as oe,readFileSync as ae,statSync as ce}from"node:fs";import{basename as It,extname as Et}from"node:path";var de=25*1024*1024;function St(r,t=""){let e=c(t);if(e)return e;let n=Et(c(r)).toLowerCase();return n===".jpg"||n===".jpeg"?"image/jpeg":n===".webp"?"image/webp":n===".gif"?"image/gif":"image/png"}function Rt(r,t){let e=typeof r=="string"?r.trim():"";return!e||e==="<omitted>"?"":e.startsWith("data:")?e:`data:${t};base64,${e.replace(/\s+/g,"")}`}function tt(r,t){let e=c(r);if(!e||!oe(e))return"";try{let n=ce(e);return!n.isFile()||n.size<=0||n.size>de?"":`data:${t};base64,${ae(e).toString("base64")}`}catch{return""}}function y(...r){for(let t of r){let e=c(t);if(e)return e}return""}function ue(r,t){let e=c(r);return!e||e.startsWith("data:")||/^https?:\/\//i.test(e)?e:tt(e,t)||e}function le(r,t,e,n){let s=e.toLowerCase();if(s==="image"||s==="picture")return!0;let i=y(n,r.previewUrl,r.fileUrl,r.imageUrl,r.dataUrl,r.url,r.uri,t.previewUrl,t.fileUrl,t.imageUrl,t.dataUrl,t.url,t.uri),a=Et(i.split("?",1)[0].split("#",1)[0]).toLowerCase();return[".png",".jpg",".jpeg",".webp",".gif"].includes(a)}function et(r,{source:t="runtime_image_generation_event"}={}){if(!u(r))return null;let e=u(r.payload)?r.payload:{},n=c(r.type),s=c(e.type);if(!(n==="event_msg"&&s==="image_generation_end"||n==="response_item"&&s==="image_generation_call"))return null;let i=y(e.call_id,e.id),a=y(e.saved_path,e.savedPath),o=y(e.revised_prompt,e.revisedPrompt),d=St(a,e.mimeType||e.mime_type),p=Rt(e.result,d)||tt(a,d)||a;if(!p)return null;let m=a?It(a):`${i||Tt()}.png`;return{artifactType:"image",type:"image",title:m||"Generated image",summary:o||"Generated image",content:{prompt:o||void 0,imageUrl:p,previewUrl:p,fileUrl:p,mimeType:d},previewUrl:p,fileUrl:p,metadata:{source:t,eventType:s,callId:i||void 0,savedPath:a||void 0,filename:m,mimeType:d,revisedPrompt:o||void 0}}}function pe(r){let t=u(r)?r:{},e=[];for(let n of["_artifacts","artifacts"]){let s=t[n];Array.isArray(s)&&e.push(...s)}for(let n of["_artifact","artifact"]){let s=t[n];u(s)&&e.push(s)}return e}function fe(r,{source:t="runtime_artifact"}={}){let e=u(r)?r:{};if(!Object.keys(e).length)return null;let n=u(e.content)?{...e.content}:{},s=u(e.metadata)?{...e.metadata}:{},i=y(e.saved_path,e.savedPath,n.saved_path,n.savedPath,s.savedPath),a=y(e.mimeType,e.mime_type,n.mimeType,n.mime_type,s.mimeType),o=y(e.artifactType,e.artifact_type,e.type,e.kind,n.type,i?"image":"file"),d=le(e,n,o,i),l=d?St(i,a):a;if(d){let _=y(e.dataUrl,n.dataUrl),E=y(e.imageUrl,e.previewUrl,e.fileUrl,e.downloadUrl,e.url,e.uri,n.imageUrl,n.previewUrl,n.fileUrl,n.downloadUrl,n.url,n.uri),g=Rt(e.result??n.result,l)||_||tt(i,l)||ue(E,l)||i;g&&(n.imageUrl||=g,n.previewUrl||=g,n.fileUrl||=g,l&&(n.mimeType||=l))}for(let[_,E]of[["prompt","prompt"],["previewUrl","previewUrl"],["fileUrl","fileUrl"],["downloadUrl","downloadUrl"],["imageUrl","imageUrl"],["dataUrl","dataUrl"],["url","url"],["uri","uri"],["mimeType","mimeType"],["mime_type","mimeType"]]){let g=e[_];g!=null&&g!==""&&!(E in n)&&(n[E]=g)}let p=y(e.fileUrl,e.downloadUrl,e.imageUrl,e.dataUrl,e.url,e.uri,n.fileUrl,n.downloadUrl,n.imageUrl,n.dataUrl,n.url,n.uri),m=y(e.previewUrl,e.imageUrl,e.dataUrl,e.url,e.fileUrl,e.uri,n.previewUrl,n.imageUrl,n.dataUrl,n.url,n.fileUrl,n.uri),f=y(e.filename,s.filename,i?It(i):"");return{...e,artifactType:o,type:e.type||o,title:y(e.title,f,"Runtime artifact"),summary:y(e.summary,n.prompt,e.title,f,"Runtime artifact"),content:n,fileUrl:p||void 0,previewUrl:m||void 0,metadata:{...s,source:y(s.source,t),savedPath:i||s.savedPath,filename:f||s.filename,mimeType:l||s.mimeType}}}function H(r,t){if(!t||!r)return;let e=u(t.metadata)?t.metadata:{},n=y(e.savedPath,e.callId,t.previewUrl,t.fileUrl)||Tt(),s=r.get(n);if(!s){r.set(n,t);return}s.content={...u(s.content)?s.content:{},...u(t.content)?t.content:{}},s.metadata={...u(s.metadata)?s.metadata:{},...e},s.previewUrl=t.previewUrl||s.previewUrl,s.fileUrl=t.fileUrl||s.fileUrl,s.summary=t.summary||s.summary,s.title=t.title||s.title}function Z(r,t,e={}){for(let n of pe(r))H(t,fe(n,e))}function rt(r){if(!u(r)||!u(r.payload))return u(r)?r:{value:r};let t=c(r.payload.type);if(t!=="image_generation_end"&&t!=="image_generation_call")return r;let e={...r.payload};return typeof e.result=="string"&&e.result&&(e.result="<omitted>",e.resultLength=r.payload.result.length),{...r,payload:e}}function _t(r,t,e){if(!u(r))return r;let n=u(r.event)?r.event:null;return n?(H(t,et(n,e)),{...r,event:rt(n)}):r}function xt(r,t,e={}){if(!u(r))return r;Z(r,t,e);let n=_t(r,t,e),s=u(n.update)?_t(n.update,t,e):null;return s&&s!==n.update&&(n={...n,update:s}),n}function Ut(r,t,e={}){let n=u(r)?{...r}:{};Z(n,t,e),Z(u(n.output)?n.output:{},t,e);let s=[...t?.values?.()||[]];return s.length&&(n.artifacts=s),n}var A=class{constructor(t,e,n={},s={}){this.agent=t,this.target=e,this.callbacks=n,this.options=s,this.proc=null,this.permissionHandlers=new Map}async ensureStarted(){if(this.proc)return;let t=c(this.target.command);if(!t)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);this.proc=new F({command:t,args:k(this.target.args),cwd:c(this.target.cwd)||this.agent.workspace||process.cwd(),env:u(this.target.env)?this.target.env:{},label:`${this.agent.agentId}:${this.agent.targetCode}`,framing:c(this.target.framing||"line")}),this.proc.onRequest("session/request_permission",e=>this.handlePermissionRequest(e)),this.proc.onRequest("session/requestPermission",e=>this.handlePermissionRequest(e)),await this.proc.start({initialize:this.target.initialize!==!1,initializeParams:{clientInfo:{name:"orcha-runtime-bridge",version:U},...u(this.target.initializeParams)?this.target.initializeParams:{}}})}async sessionNew(t={}){return await this.ensureStarted(),this.proc.call("session/new",t)}async sessionPrompt(t,e){await this.ensureStarted();let n=c(t.sessionId),s=new Map,i={source:this.artifactSource()},a=this.proc.onNotification("session/update",d=>{let l=c(d.sessionId);(!l||l===n)&&e(xt(d,s,i))}),o=async d=>this.callbacks.onPermissionRequest?.({agent:this.agent,runtimeSessionId:n,request:d,emitUpdate:e})||{outcome:"denied",reason:"permission handler is not configured"};n&&this.permissionHandlers.set(n,o),this.permissionHandlers.set("*",o);try{let d=await this.proc.call("session/prompt",t,this.options.sessionPromptTimeoutMs);return Ut(d,s,i)}finally{a(),n&&this.permissionHandlers.delete(n),this.permissionHandlers.delete("*")}}async sessionCancel(t){return await this.ensureStarted(),this.proc.call("session/cancel",t,5e3).catch(()=>({ok:!0}))}async handlePermissionRequest(t){let e=c(t.sessionId),n=this.permissionHandlers.get(e)||this.permissionHandlers.get("*");return n?n(t):{outcome:"denied",reason:"no active Orcha permission handler"}}artifactSource(){return c(this.target.type||"acp")==="openclaw"?"openclaw_image_generation":"acp_runtime_image_generation"}stop(t){this.proc?.stop(t)}};var $=class extends A{constructor(t,e,n,s={},i={}){let a=c(n).replace(/[^A-Za-z0-9._-]+/g,"-")||"default",o=c(e.command)||"openclaw",d=Array.isArray(e.args)?e.args.map(String):[],l=d.length>0?d:["acp","--session",`agent:${t.agentId}:${a}`];super(t,{...e,command:o,args:l},s,i)}};import{spawn as he}from"node:child_process";import{randomUUID as nt}from"node:crypto";import{existsSync as Nt,readdirSync as me,readFileSync as it,statSync as ge,unlinkSync as ye}from"node:fs";import{homedir as we,tmpdir as _e}from"node:os";import{basename as Ct,join as M}from"node:path";var Te=36e5,Ie=5e3,Ee=2*60*1e3,Se=2*60*1e3,Re=12,xe=1e3,B=24*60*60*1e3;function z(r,t){try{r.kill(t)}catch{}}function I(r){if(typeof r=="string")return r;if(Array.isArray(r))return r.map(t=>I(t)).join("");if(!u(r))return"";for(let t of["text","delta","output_text","content","message","output"]){let e=I(r[t]);if(e)return e}return""}function Mt(r){if(!u(r))return"";let t=u(r.payload)?r.payload:{};if(c(r.type)==="event_msg"){if(c(t.type)==="agent_message")return c(t.message);if(c(t.type)==="task_complete")return c(t.last_agent_message)}if(c(r.type)==="response_item"&&c(t.type)==="message"&&c(t.role)==="assistant")return I(t.content)||I(t.message);let e=I(r.delta)||I(r.text)||I(r.content);if(e)return e;let n=u(r.item)?r.item:{};return c(n.role)==="assistant"||c(n.type)==="message"?I(n.content)||I(n.text)||I(n.message):""}function ot(r){return et(r,{source:"codex_cli_image_generation"})}function at(r,t){H(r.artifacts,t)}function bt(r){return rt(r)}function Ue(r,t,e){return e.captureLastMessage===!1||t.includes("--output-last-message")||t.includes("-o")?!1:e.captureLastMessage===!0?!0:Ct(r)==="codex"}function Ot(r,t){return t.collectCodexTranscriptArtifacts===!1?!1:t.collectCodexTranscriptArtifacts===!0?!0:Ct(r)==="codex"}function Oe(r){return Math.max(20,T(r.codexTranscriptPollMs||r.transcriptPollMs,xe))}function Ae(r,t,e){return{target:r,promptText:t,startedAtMs:e,matchedPaths:new Set,processedLines:new Map}}function Ne(r){let t=c(r.codexSessionsRoot||r.codexSessionRoot);if(t)return t;let e=u(r.env)?r.env:{},n=c(r.codexHome||e.CODEX_HOME||process.env.CODEX_HOME)||M(we(),".codex");return M(n,"sessions")}function Ce(r,t){let e=new Date(t),n=String(e.getFullYear()),s=String(e.getMonth()+1).padStart(2,"0"),i=String(e.getDate()).padStart(2,"0");return M(r,n,s,i)}function Me(r,t,e){let n=new Set;for(let s of[t-B,t,t+B,e-B,e,e+B])n.add(Ce(r,s));return[...n].filter(s=>Nt(s))}function vt(r,t,e){let n=Ne(r),s=t-Ee,i=e+Se,a=[];for(let o of Me(n,t,e)){let d=[];try{d=me(o)}catch{continue}for(let l of d){if(!l.endsWith(".jsonl"))continue;let p=M(o,l);try{let m=ge(p);if(!m.isFile()||m.mtimeMs<s||m.mtimeMs>i)continue;a.push({path:p,mtimeMs:m.mtimeMs})}catch{}}}return a.sort((o,d)=>d.mtimeMs-o.mtimeMs).slice(0,Re)}function st(r,t,e=0){if(!(e>8||r===null||r===void 0)){if(typeof r=="string"){r&&t.push(r);return}if(Array.isArray(r)){for(let n of r)st(n,t,e+1);return}if(u(r))for(let n of["payload","item","text","delta","output_text","content","message","output","input","prompt","last_agent_message","revised_prompt"])n in r&&st(r[n],t,e+1)}}function Pt(r){return c(r).replace(/\s+/g," ")}function be(r){let t=Pt(r);if(!t)return[];if(t.length<=200)return[t];let e=160,n=[0,Math.floor((t.length-e)/2),t.length-e],s=new Set,i=[];for(let a of n){let o=t.slice(Math.max(0,a),Math.max(0,a)+e).trim();o.length>=40&&!s.has(o)&&(s.add(o),i.push(o))}return i}function kt(r,t){let e=be(t);if(!e.length)return!1;let n=[];for(let i of r)st(i,n);let s=Pt(n.join(" "));return e.every(i=>s.includes(i))}function Lt(r){let t=[];for(let e of r.split(/\r?\n/)){let n=e.trim();if(n)try{t.push(JSON.parse(n))}catch{}}return t}function ve(r){if(!u(r))return!1;let t=u(r.payload)?r.payload:{},e=c(r.type),n=c(t.type);return e==="event_msg"&&n==="image_generation_end"||e==="response_item"&&n==="image_generation_call"}function Pe(r,t,e,n){let s=Mt(r);if(s&&!t.emittedTexts.has(s)){let i=t.emittedTexts.size?`
8
+ `;this.child.stdin.write(s,e)}onNotification(t,e){let n=this.notificationHandlers.get(t)||new Set;return n.add(e),this.notificationHandlers.set(t,n),()=>{n.delete(e),n.size===0&&this.notificationHandlers.delete(t)}}onRequest(t,e){return this.requestHandlers.set(t,e),()=>this.requestHandlers.delete(t)}onExit(t){return this.exitHandlers.add(t),()=>this.exitHandlers.delete(t)}rejectAll(t){for(let e of this.pending.values())clearTimeout(e.timer),e.reject(t);this.pending.clear()}handleExit(t,e){this.rejectAll(new Error(`runtime exited before response (${t}/${e})`));for(let n of this.exitHandlers)n(t,e)}stop(t="stop"){!this.child||this.child.killed||(f("info","runtime","stopping runtime",{target:this.label,reason:t}),this.child.kill("SIGTERM"),setTimeout(()=>{this.child&&!this.child.killed&&this.child.kill("SIGKILL")},5e3).unref())}};import{randomUUID as Ot}from"node:crypto";import{existsSync as Re,readFileSync as xe,statSync as Ue}from"node:fs";import{basename as At,extname as Nt}from"node:path";var Oe=25*1024*1024;function Mt(r,t=""){let e=c(t);if(e)return e;let n=Nt(c(r)).toLowerCase();return n===".jpg"||n===".jpeg"?"image/jpeg":n===".webp"?"image/webp":n===".gif"?"image/gif":"image/png"}function Ct(r,t){let e=typeof r=="string"?r.trim():"";return!e||e==="<omitted>"?"":e.startsWith("data:")?e:`data:${t};base64,${e.replace(/\s+/g,"")}`}function rt(r,t){let e=c(r);if(!e||!Re(e))return"";try{let n=Ue(e);return!n.isFile()||n.size<=0||n.size>Oe?"":`data:${t};base64,${xe(e).toString("base64")}`}catch{return""}}function y(...r){for(let t of r){let e=c(t);if(e)return e}return""}function Ae(r,t){let e=c(r);return!e||e.startsWith("data:")||/^https?:\/\//i.test(e)?e:rt(e,t)||e}function Ne(r,t,e,n){let s=e.toLowerCase();if(s==="image"||s==="picture")return!0;let i=y(n,r.previewUrl,r.fileUrl,r.imageUrl,r.dataUrl,r.url,r.uri,t.previewUrl,t.fileUrl,t.imageUrl,t.dataUrl,t.url,t.uri),a=Nt(i.split("?",1)[0].split("#",1)[0]).toLowerCase();return[".png",".jpg",".jpeg",".webp",".gif"].includes(a)}function nt(r,{source:t="runtime_image_generation_event"}={}){if(!d(r))return null;let e=d(r.payload)?r.payload:{},n=c(r.type),s=c(e.type);if(!(n==="event_msg"&&s==="image_generation_end"||n==="response_item"&&s==="image_generation_call"))return null;let i=y(e.call_id,e.id),a=y(e.saved_path,e.savedPath),o=y(e.revised_prompt,e.revisedPrompt),u=Mt(a,e.mimeType||e.mime_type),p=Ct(e.result,u)||rt(a,u)||a;if(!p)return null;let h=a?At(a):`${i||Ot()}.png`;return{artifactType:"image",type:"image",title:h||"Generated image",summary:o||"Generated image",content:{prompt:o||void 0,imageUrl:p,previewUrl:p,fileUrl:p,mimeType:u},previewUrl:p,fileUrl:p,metadata:{source:t,eventType:s,callId:i||void 0,savedPath:a||void 0,filename:h,mimeType:u,revisedPrompt:o||void 0}}}function Me(r){let t=d(r)?r:{},e=[];for(let n of["_artifacts","artifacts"]){let s=t[n];Array.isArray(s)&&e.push(...s)}for(let n of["_artifact","artifact"]){let s=t[n];d(s)&&e.push(s)}return e}function Ce(r,{source:t="runtime_artifact"}={}){let e=d(r)?r:{};if(!Object.keys(e).length)return null;let n=d(e.content)?{...e.content}:{},s=d(e.metadata)?{...e.metadata}:{},i=y(e.saved_path,e.savedPath,n.saved_path,n.savedPath,s.savedPath),a=y(e.mimeType,e.mime_type,n.mimeType,n.mime_type,s.mimeType),o=y(e.artifactType,e.artifact_type,e.type,e.kind,n.type,i?"image":"file"),u=Ne(e,n,o,i),l=u?Mt(i,a):a;if(u){let T=y(e.dataUrl,n.dataUrl),S=y(e.imageUrl,e.previewUrl,e.fileUrl,e.downloadUrl,e.url,e.uri,n.imageUrl,n.previewUrl,n.fileUrl,n.downloadUrl,n.url,n.uri),g=Ct(e.result??n.result,l)||T||rt(i,l)||Ae(S,l)||i;g&&(n.imageUrl||=g,n.previewUrl||=g,n.fileUrl||=g,l&&(n.mimeType||=l))}for(let[T,S]of[["prompt","prompt"],["previewUrl","previewUrl"],["fileUrl","fileUrl"],["downloadUrl","downloadUrl"],["imageUrl","imageUrl"],["dataUrl","dataUrl"],["url","url"],["uri","uri"],["mimeType","mimeType"],["mime_type","mimeType"]]){let g=e[T];g!=null&&g!==""&&!(S in n)&&(n[S]=g)}let p=y(e.fileUrl,e.downloadUrl,e.imageUrl,e.dataUrl,e.url,e.uri,n.fileUrl,n.downloadUrl,n.imageUrl,n.dataUrl,n.url,n.uri),h=y(e.previewUrl,e.imageUrl,e.dataUrl,e.url,e.fileUrl,e.uri,n.previewUrl,n.imageUrl,n.dataUrl,n.url,n.fileUrl,n.uri),m=y(e.filename,s.filename,i?At(i):"");return{...e,artifactType:o,type:e.type||o,title:y(e.title,m,"Runtime artifact"),summary:y(e.summary,n.prompt,e.title,m,"Runtime artifact"),content:n,fileUrl:p||void 0,previewUrl:h||void 0,metadata:{...s,source:y(s.source,t),savedPath:i||s.savedPath,filename:m||s.filename,mimeType:l||s.mimeType}}}function B(r,t){if(!t||!r)return;let e=d(t.metadata)?t.metadata:{},n=y(e.savedPath,e.callId,t.previewUrl,t.fileUrl)||Ot(),s=r.get(n);if(!s){r.set(n,t);return}s.content={...d(s.content)?s.content:{},...d(t.content)?t.content:{}},s.metadata={...d(s.metadata)?s.metadata:{},...e},s.previewUrl=t.previewUrl||s.previewUrl,s.fileUrl=t.fileUrl||s.fileUrl,s.summary=t.summary||s.summary,s.title=t.title||s.title}function et(r,t,e={}){for(let n of Me(r))B(t,Ce(n,e))}function st(r){if(!d(r)||!d(r.payload))return d(r)?r:{value:r};let t=c(r.payload.type);if(t!=="image_generation_end"&&t!=="image_generation_call")return r;let e={...r.payload};return typeof e.result=="string"&&e.result&&(e.result="<omitted>",e.resultLength=r.payload.result.length),{...r,payload:e}}function Ut(r,t,e){if(!d(r))return r;let n=d(r.event)?r.event:null;return n?(B(t,nt(n,e)),{...r,event:st(n)}):r}function bt(r,t,e={}){if(!d(r))return r;et(r,t,e);let n=Ut(r,t,e),s=d(n.update)?Ut(n.update,t,e):null;return s&&s!==n.update&&(n={...n,update:s}),n}function kt(r,t,e={}){let n=d(r)?{...r}:{};et(n,t,e),et(d(n.output)?n.output:{},t,e);let s=[...t?.values?.()||[]];return s.length&&(n.artifacts=s),n}var A=class{constructor(t,e,n={},s={}){this.agent=t,this.target=e,this.callbacks=n,this.options=s,this.proc=null,this.permissionHandlers=new Map}async ensureStarted(){if(this.proc)return;let t=c(this.target.command);if(!t)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);this.proc=new H({command:t,args:D(this.target.args),cwd:c(this.target.cwd)||this.agent.workspace||process.cwd(),env:d(this.target.env)?this.target.env:{},label:`${this.agent.agentId}:${this.agent.targetCode}`,framing:c(this.target.framing||"line")}),this.proc.onRequest("session/request_permission",e=>this.handlePermissionRequest(e)),this.proc.onRequest("session/requestPermission",e=>this.handlePermissionRequest(e)),await this.proc.start({initialize:this.target.initialize!==!1,initializeParams:{clientInfo:{name:"orcha-runtime-bridge",version:O},...d(this.target.initializeParams)?this.target.initializeParams:{}}})}async sessionNew(t={}){await this.ensureStarted();let e=Array.isArray(t.mcpServers)?t.mcpServers:Array.isArray(this.target.mcpServers)?this.target.mcpServers:[];return this.proc.call("session/new",{...t,mcpServers:e})}async sessionPrompt(t,e){await this.ensureStarted();let n=c(t.sessionId),s=new Map,i={source:this.artifactSource()},a=this.proc.onNotification("session/update",u=>{let l=c(u.sessionId);(!l||l===n)&&e(bt(u,s,i))}),o=async u=>this.callbacks.onPermissionRequest?.({agent:this.agent,runtimeSessionId:n,request:u,emitUpdate:e})||{outcome:"denied",reason:"permission handler is not configured"};n&&this.permissionHandlers.set(n,o),this.permissionHandlers.set("*",o);try{let u=await this.proc.call("session/prompt",t,this.options.sessionPromptTimeoutMs);return kt(u,s,i)}finally{a(),n&&this.permissionHandlers.delete(n),this.permissionHandlers.delete("*")}}async sessionCancel(t){return await this.ensureStarted(),this.proc.call("session/cancel",t,5e3).catch(()=>({ok:!0}))}async handlePermissionRequest(t){let e=c(t.sessionId),n=this.permissionHandlers.get(e)||this.permissionHandlers.get("*");return n?n(t):{outcome:"denied",reason:"no active Orcha permission handler"}}artifactSource(){return c(this.target.type||"acp")==="openclaw"?"openclaw_image_generation":"acp_runtime_image_generation"}stop(t){this.proc?.stop(t)}};function be(r){let t=d(r.metadata)?r.metadata:{};return c(t.agentCode)}function ke(r,t){let e=be(r);return e?`agent:${e}:${t}`:`orcha-${t}`}var z=class extends A{constructor(t,e,n,s={},i={}){let a=c(n).replace(/[^A-Za-z0-9._-]+/g,"-")||"default",o=c(e.command)||"openclaw",u=Array.isArray(e.args)?e.args.map(String):[],l=u.length>0?u:["acp","--session",ke(t,a)];super(t,{...e,command:o,args:l},s,i)}};import{spawn as Le}from"node:child_process";import{randomUUID as it}from"node:crypto";import{existsSync as vt,readdirSync as Pe,readFileSync as at,statSync as ve,unlinkSync as De}from"node:fs";import{homedir as Fe,tmpdir as $e}from"node:os";import{basename as Dt,join as k}from"node:path";var He=36e5,Be=5e3,ze=2*60*1e3,Ge=2*60*1e3,je=12,qe=1e3,G=24*60*60*1e3;function j(r,t){try{r.kill(t)}catch{}}function E(r){if(typeof r=="string")return r;if(Array.isArray(r))return r.map(t=>E(t)).join("");if(!d(r))return"";for(let t of["text","delta","output_text","content","message","output"]){let e=E(r[t]);if(e)return e}return""}function Ft(r){if(!d(r))return"";let t=d(r.payload)?r.payload:{};if(c(r.type)==="event_msg"){if(c(t.type)==="agent_message")return c(t.message);if(c(t.type)==="task_complete")return c(t.last_agent_message)}if(c(r.type)==="response_item"&&c(t.type)==="message"&&c(t.role)==="assistant")return E(t.content)||E(t.message);let e=E(r.delta)||E(r.text)||E(r.content);if(e)return e;let n=d(r.item)?r.item:{};return c(n.role)==="assistant"||c(n.type)==="message"?E(n.content)||E(n.text)||E(n.message):""}function ct(r){return nt(r,{source:"codex_cli_image_generation"})}function ut(r,t){B(r.artifacts,t)}function $t(r){return st(r)}function Je(r,t,e){return e.captureLastMessage===!1||t.includes("--output-last-message")||t.includes("-o")?!1:e.captureLastMessage===!0?!0:Dt(r)==="codex"}function Lt(r,t){return t.collectCodexTranscriptArtifacts===!1?!1:t.collectCodexTranscriptArtifacts===!0?!0:Dt(r)==="codex"}function Ke(r){return Math.max(20,I(r.codexTranscriptPollMs||r.transcriptPollMs,qe))}function Ve(r,t,e){return{target:r,promptText:t,startedAtMs:e,matchedPaths:new Set,processedLines:new Map}}function We(r){let t=c(r.codexSessionsRoot||r.codexSessionRoot);if(t)return t;let e=d(r.env)?r.env:{},n=c(r.codexHome||e.CODEX_HOME||process.env.CODEX_HOME)||k(Fe(),".codex");return k(n,"sessions")}function Ye(r,t){let e=new Date(t),n=String(e.getFullYear()),s=String(e.getMonth()+1).padStart(2,"0"),i=String(e.getDate()).padStart(2,"0");return k(r,n,s,i)}function Ze(r,t,e){let n=new Set;for(let s of[t-G,t,t+G,e-G,e,e+G])n.add(Ye(r,s));return[...n].filter(s=>vt(s))}function Ht(r,t,e){let n=We(r),s=t-ze,i=e+Ge,a=[];for(let o of Ze(n,t,e)){let u=[];try{u=Pe(o)}catch{continue}for(let l of u){if(!l.endsWith(".jsonl"))continue;let p=k(o,l);try{let h=ve(p);if(!h.isFile()||h.mtimeMs<s||h.mtimeMs>i)continue;a.push({path:p,mtimeMs:h.mtimeMs})}catch{}}}return a.sort((o,u)=>u.mtimeMs-o.mtimeMs).slice(0,je)}function ot(r,t,e=0){if(!(e>8||r===null||r===void 0)){if(typeof r=="string"){r&&t.push(r);return}if(Array.isArray(r)){for(let n of r)ot(n,t,e+1);return}if(d(r))for(let n of["payload","item","text","delta","output_text","content","message","output","input","prompt","last_agent_message","revised_prompt"])n in r&&ot(r[n],t,e+1)}}function Bt(r){return c(r).replace(/\s+/g," ")}function Xe(r){let t=Bt(r);if(!t)return[];if(t.length<=200)return[t];let e=160,n=[0,Math.floor((t.length-e)/2),t.length-e],s=new Set,i=[];for(let a of n){let o=t.slice(Math.max(0,a),Math.max(0,a)+e).trim();o.length>=40&&!s.has(o)&&(s.add(o),i.push(o))}return i}function zt(r,t){let e=Xe(t);if(!e.length)return!1;let n=[];for(let i of r)ot(i,n);let s=Bt(n.join(" "));return e.every(i=>s.includes(i))}function Gt(r){let t=[];for(let e of r.split(/\r?\n/)){let n=e.trim();if(n)try{t.push(JSON.parse(n))}catch{}}return t}function Qe(r){if(!d(r))return!1;let t=d(r.payload)?r.payload:{},e=c(r.type),n=c(t.type);return e==="event_msg"&&n==="image_generation_end"||e==="response_item"&&n==="image_generation_call"}function tr(r,t,e,n){let s=Ft(r);if(s&&!t.emittedTexts.has(s)){let i=t.emittedTexts.size?`
9
9
 
10
- ${s}`:s;t.emittedTexts.add(s),n({sessionId:e,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:i}}})}at(t,ot(r)),ve(r)&&n({sessionId:e,update:{sessionUpdate:"runtime_event",event:bt(r)}})}function At(r,t,e,n,s=Date.now()){if(!t)return{artifactCount:0,transcriptCount:0};let i=r.artifacts.size,a=0;for(let o of vt(t.target,t.startedAtMs,s)){let d="";try{d=it(o.path,"utf8")}catch{continue}let l=Lt(d);if(!t.matchedPaths.has(o.path)){if(!kt(l,t.promptText))continue;t.matchedPaths.add(o.path),h("info","runtime.cli","codex transcript stream attached",{target:t.target.targetCode,sessionId:e})}let p=Math.min(t.processedLines.get(o.path)||0,l.length),m=r.artifacts.size;for(let f of l.slice(p))Pe(f,r,e,n);t.processedLines.set(o.path,l.length),(l.length>p||r.artifacts.size>m)&&(a+=1)}return{artifactCount:r.artifacts.size-i,transcriptCount:a}}function ke(r,{target:t,promptText:e,startedAtMs:n,endedAtMs:s}){let i=r.artifacts.size,a=0;for(let o of vt(t,n,s)){let d="";try{d=it(o.path,"utf8")}catch{continue}let l=Lt(d);if(!kt(l,e))continue;let p=r.artifacts.size;for(let m of l)at(r,ot(m));r.artifacts.size>p&&(a+=1)}return{artifactCount:r.artifacts.size-i,transcriptCount:a}}function Le(r){if(!r||!Nt(r))return"";try{return it(r,"utf8").trim()}catch{return""}finally{try{ye(r)}catch{}}}var G=class{constructor(t,e,n={}){this.agent=t,this.target=e,this.options=n,this.active=new Map}async sessionNew(){return{sessionId:`cli-${this.agent.agentId}-${nt()}`}}async sessionPrompt(t,e){let n=Date.now(),s=c(this.target.command);if(!s)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);let i=c(t.sessionId)||nt(),a=L(t.prompt),o=c(this.target.promptMode||"stdin"),d=this.buildArgs(o,a),l=Ue(s,d,this.target)?M(_e(),`orcha-runtime-last-message-${nt()}.txt`):"";l&&d.push("--output-last-message",l);let p=T(this.target.timeoutMs||this.target.sessionPromptTimeoutMs,T(this.options.sessionPromptTimeoutMs,Te)),m={...process.env,...u(this.target.env)?this.target.env:{},...o==="env"?{ORCHA_RUNTIME_PROMPT:a}:{},ORCHA_AGENT_ID:this.agent.agentId,ORCHA_SESSION_ID:i},f=he(s,d,{cwd:c(this.target.cwd)||this.agent.workspace||process.cwd(),env:m,stdio:["pipe","pipe","pipe"]});this.active.set(i,f),h("info","runtime.cli","runtime prompt started",{target:this.agent.targetCode,sessionId:i,pid:f.pid,timeoutMs:p});let _="",E=c(this.target.outputMode||"text"),g={artifacts:new Map,emittedTexts:new Set,value:""},X=Ot(s,this.target)?Ae({...this.target,targetCode:this.agent.targetCode},a,n):null;return f.stdout.setEncoding("utf8"),f.stdout.on("data",x=>this.handleStdout(x,E,g,i,e)),f.stderr.setEncoding("utf8"),f.stderr.on("data",x=>{_+=x,this.target.emitStderr===!0&&e({sessionId:i,update:{sessionUpdate:"runtime_stderr_chunk",content:{type:"text",text:x}}})}),o==="stdin"?f.stdin.end(a):f.stdin.end(),await new Promise((x,Qt)=>{let b=!1,ht=!1,S=null,Y=X?setInterval(()=>{try{At(g,X,i,e)}catch(w){h("warn","runtime.cli","codex transcript stream poll failed",{target:this.agent.targetCode,sessionId:i,error:String(w?.message||w)})}},Oe(this.target)):null;Y?.unref?.();let mt=setTimeout(()=>{ht=!0,h("warn","runtime.cli","runtime prompt timed out; terminating child",{target:this.agent.targetCode,sessionId:i,pid:f.pid,timeoutMs:p}),z(f,"SIGTERM"),S=setTimeout(()=>{h("warn","runtime.cli","runtime prompt force killing child",{target:this.agent.targetCode,sessionId:i,pid:f.pid}),z(f,"SIGKILL")},Ie),S.unref?.(),yt(Object.assign(new Error(`runtime CLI timed out after ${p}ms`),{code:"RUNTIME_CLI_TIMEOUT"}))},p);mt.unref?.();let gt=()=>{clearTimeout(mt),Y&&clearInterval(Y),S&&!ht&&clearTimeout(S),this.active.delete(i)},Zt=w=>{b||(b=!0,gt(),x(w))},yt=w=>{b||(b=!0,gt(),Qt(w))};f.on("error",w=>{h("warn","runtime.cli","runtime child error",{target:this.agent.targetCode,sessionId:i,pid:f.pid,error:String(w?.message||w)}),yt(w)}),f.on("exit",(w,wt)=>{S&&(clearTimeout(S),S=null),E==="json-lines"&&g.value.trim()&&this.handleStdout(`
11
- `,E,g,i,e),At(g,X,i,e,Date.now());let v=Le(l);if(v&&!g.emittedTexts.has(v)&&(g.emittedTexts.add(v),e({sessionId:i,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:v}}})),Ot(s,this.target)){let Q=ke(g,{target:this.target,promptText:a,startedAtMs:n,endedAtMs:Date.now()});Q.artifactCount>0&&h("info","runtime.cli","codex transcript artifacts collected",{target:this.agent.targetCode,sessionId:i,artifactCount:Q.artifactCount,transcriptCount:Q.transcriptCount})}let P=_.trim();P&&h("debug","runtime.cli","runtime stderr",{target:this.agent.targetCode,sessionId:i,stderr:P}),h("info","runtime.cli","runtime prompt finished",{target:this.agent.targetCode,sessionId:i,pid:f.pid,exitCode:w,signal:wt,artifactCount:g.artifacts.size}),Zt({stopReason:w===0?"end_turn":"error",exitCode:w,signal:wt,artifacts:[...g.artifacts.values()],...P?{stderr:P}:{}})})})}buildArgs(t,e){let n=k(this.target.args);return t==="args"?[...n,e]:n}handleStdout(t,e,n,s,i){if(e!=="json-lines"){i({sessionId:s,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:t}}});return}n.value+=t;let a=n.value.split(/\r?\n/);n.value=a.pop()||"";for(let o of a){let d=o.trim();if(d)try{let l=JSON.parse(d);at(n,ot(l)),i({sessionId:s,update:{sessionUpdate:"runtime_event",event:bt(l)}});let p=Mt(l);p&&!n.emittedTexts.has(p)&&(n.emittedTexts.add(p),i({sessionId:s,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:p}}}))}catch{i({sessionId:s,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`${o}
12
- `}}})}}}async sessionCancel(t){let e=c(t.sessionId),n=this.active.get(e);return n?(h("info","runtime.cli","cancelling runtime child",{target:this.agent.targetCode,sessionId:e,pid:n.pid}),z(n,"SIGTERM"),this.active.delete(e),{ok:!0,cancelled:!0}):{ok:!0,cancelled:!1}}stop(t="stop"){for(let[e,n]of this.active.entries())h("info","runtime.cli","stopping runtime child",{target:this.agent.targetCode,sessionId:e,pid:n.pid,reason:t}),z(n,"SIGTERM");this.active.clear()}};function De(r,t,e){let n=u(r?._meta)?r._meta:{};return{...u(r)?r:{},sessionId:t,update:u(r?.update)?r.update:{},_meta:{...n,orchaAgentId:e.agentId,runtimeSessionId:e.runtimeSessionId,bridgeUpdateId:j()}}}var q=class{constructor(t){this.config=t,this.targets=t.targets||{},this.agents=new Map,this.sessions=new Map,this.runtimeSessionIndex=new Map,this.pendingPermissions=new Map,this.startedAt=O()}targetFor(t){let e=c(t)||this.config.defaultTargetCode,n=this.targets[e];return{code:e,target:u(n)?n:{type:"echo"}}}async createAgent(t){let e=c(t.agentId);if(!e)throw Object.assign(new Error("agentId is required"),{status:400,code:"BAD_REQUEST"});let{code:n,target:s}=this.targetFor(t.targetCode||t.framework),i={agentId:e,targetCode:n,framework:c(t.framework||n),workspace:c(t.workspace),metadata:u(t.metadata)?t.metadata:{},createdAt:O(),runtimeKind:c(s.type||"echo")};return this.agents.set(e,i),{agent:i}}runtimeFor(t,e){let{target:n}=this.targetFor(t.targetCode),s=c(n.type||"echo"),i={onPermissionRequest:o=>this.requestPermission(o)},a={sessionPromptTimeoutMs:this.config.sessionPromptTimeoutMs};return s==="stdio-acp"||s==="acp"?new A(t,n,i,a):s==="openclaw"?new $(t,n,e,i,a):s==="cli"?new G(t,n,a):new D(t)}async prompt(t,e={}){let n=c(t.agentId),s=c(t.sessionId)||j();if(!n)throw Object.assign(new Error("agentId is required"),{status:400,code:"BAD_REQUEST"});let i=this.agents.get(n)||(await this.createAgent({agentId:n,targetCode:t.targetCode,framework:t.framework,workspace:t.workspace,metadata:t.metadata})).agent,a=c(t.workspace);a&&a!==i.workspace&&(i.workspace=a);let o=`${n}:${s}`,d=this.sessions.get(o);if(!d){let f=this.runtimeFor(i,s),_=await f.sessionNew({cwd:i.workspace||process.cwd(),metadata:u(t.metadata)?t.metadata:{}});d={agentId:n,sessionId:s,runtime:f,runtimeSessionId:c(u(_)?_.sessionId:"")||s,createdAt:O()},this.sessions.set(o,d),this.runtimeSessionIndex.set(`${n}:${d.runtimeSessionId}`,d)}let l=[],p=f=>{let _=De(f,s,d);l.push(_),e.onUpdate?.(_)},m=await d.runtime.sessionPrompt({sessionId:d.runtimeSessionId,prompt:Array.isArray(t.prompt)?t.prompt:[],metadata:u(t.metadata)?t.metadata:{}},p);return{sessionId:s,runtimeSessionId:d.runtimeSessionId,result:u(m)?m:{},updates:l}}async cancel(t){let e=c(t.agentId),n=c(t.sessionId),s=this.sessions.get(`${e}:${n}`);return s?(await s.runtime.sessionCancel({sessionId:s.runtimeSessionId}),{cancelled:!0}):{cancelled:!1}}async dispatch(t,e={}){let n=c(t.agentId),s=c(t.taskId),i=c(t.executionId);if(!n||!s)throw Object.assign(new Error("agentId and taskId are required"),{status:400,code:"BAD_REQUEST"});let a=c(t.sessionId)||`dispatch-${i||s}`,o=c(t.instructions),d=[{type:"text",text:["Task dispatch received.",`taskId: ${s}`,i?`executionId: ${i}`:"",o?`instructions: ${o}`:""].filter(Boolean).join(`
13
- `)}];return this.prompt({...t,agentId:n,sessionId:a,prompt:d},e)}async requestPermission({agent:t,runtimeSessionId:e,request:n,emitUpdate:s}){let i=j(),o=this.runtimeSessionIndex.get(`${t.agentId}:${e}`)?.sessionId||e||j(),d={permissionId:i,agentId:t.agentId,sessionId:o,runtimeSessionId:e,request:u(n)?n:{},status:"pending",createdAt:O()};return s?.({sessionId:e,update:{sessionUpdate:"permission_request",permission:d}}),await new Promise(l=>{let p=T(n?.timeoutMs,this.config.permissionRequestTimeoutMs),m=setTimeout(()=>{this.pendingPermissions.delete(i),l({permissionId:i,outcome:"denied",response:{reason:"permission request timed out"}})},p);this.pendingPermissions.set(i,{timer:m,resolve:l,permission:d})})}async respondPermission(t){let e=c(t.permissionId),n=this.pendingPermissions.get(e),s=c(t.outcome||"approved")||"approved";return n?(clearTimeout(n.timer),this.pendingPermissions.delete(e),n.resolve({permissionId:e,outcome:s,response:u(t.response)?t.response:{},userId:c(t.userId),metadata:u(t.metadata)?t.metadata:{}}),{accepted:!0,permissionId:e,outcome:s}):{accepted:!1,permissionId:e,outcome:s}}health(){return{status:"ok",bridgeVersion:U,startedAt:this.startedAt,agents:[...this.agents.values()].map(t=>({agentId:t.agentId,targetCode:t.targetCode,framework:t.framework,runtimeKind:t.runtimeKind})),sessions:this.sessions.size,pendingPermissions:this.pendingPermissions.size,targets:Object.keys(this.targets)}}};import Fe from"node:http";import He from"node:https";import{randomBytes as Dt}from"node:crypto";var J=1,ct=3,K=class{constructor(t){this.url=t,this.readyState=0,this.socket=null,this.buffer=Buffer.alloc(0),this.listeners=new Map,this.connect()}addEventListener(t,e){let n=this.listeners.get(t)||new Set;n.add(e),this.listeners.set(t,n)}emit(t,e={}){let n=this.listeners.get(t);if(n)for(let s of n)s(e)}connect(){let t=new URL(this.url),e=t.protocol==="wss:"?He:Fe,n=Dt(16).toString("base64"),s=e.request({protocol:t.protocol==="wss:"?"https:":"http:",hostname:t.hostname,port:t.port||(t.protocol==="wss:"?443:80),path:`${t.pathname}${t.search}`,method:"GET",headers:{Connection:"Upgrade",Upgrade:"websocket","Sec-WebSocket-Key":n,"Sec-WebSocket-Version":"13"}});s.on("upgrade",(i,a,o)=>{this.socket=a,this.readyState=J,a.on("data",d=>this.onData(d)),a.on("close",()=>this.onClose()),a.on("error",d=>{this.emit("error",{error:d,message:d.message,type:"error"}),this.onClose()}),o?.length&&this.onData(o),this.emit("open")}),s.on("response",i=>{this.emit("error",{message:`websocket upgrade failed: HTTP ${i.statusCode}`,type:"error"}),i.resume(),this.onClose()}),s.on("error",i=>{this.emit("error",{error:i,message:i.message,type:"error"}),this.onClose()}),s.end()}send(t){!this.socket||this.readyState!==J||this.socket.write(dt(1,Buffer.from(String(t),"utf8")))}close(){!this.socket||this.readyState===ct||(this.socket.write(dt(8,Buffer.alloc(0))),this.socket.end(),this.onClose())}onClose(){this.readyState!==ct&&(this.readyState=ct,this.emit("close"))}onData(t){for(this.buffer=Buffer.concat([this.buffer,t]);this.buffer.length>=2;){let e=this.buffer[0],n=this.buffer[1],s=e&15,i=(n&128)!==0,a=n&127,o=2;if(a===126){if(this.buffer.length<o+2)return;a=this.buffer.readUInt16BE(o),o+=2}else if(a===127){if(this.buffer.length<o+8)return;let p=this.buffer.readUInt32BE(o),m=this.buffer.readUInt32BE(o+4);a=p*2**32+m,o+=8}let d=o;if(i&&(o+=4),this.buffer.length<o+a)return;let l=this.buffer.subarray(o,o+a);if(i){let p=this.buffer.subarray(d,d+4);l=Buffer.from(l.map((m,f)=>m^p[f%4]))}this.buffer=this.buffer.subarray(o+a),s===1?this.emit("message",{data:l.toString("utf8")}):s===8?this.close():s===9&&this.socket?.write(dt(10,l))}}};function dt(r,t){let e=t.length,n=2;e>=126&&e<=65535?n+=2:e>65535&&(n+=8);let s=Dt(4),i=Buffer.alloc(n+4+e);i[0]=128|r;let a=2;e<126?i[1]=128|e:e<=65535?(i[1]=254,i.writeUInt16BE(e,a),a+=2):(i[1]=255,i.writeUInt32BE(Math.floor(e/2**32),a),i.writeUInt32BE(e>>>0,a+4),a+=8),s.copy(i,a),a+=4;for(let o=0;o<e;o+=1)i[a+o]=t[o]^s[o%4];return i}function $e(r){let t=new URL(r);if(t.protocol==="http:")t.protocol="ws:";else if(t.protocol==="https:")t.protocol="wss:";else if(t.protocol!=="ws:"&&t.protocol!=="wss:")throw new Error(`unsupported ORCHA_RUNTIME_ORCHA_URL protocol: ${t.protocol}`);return t.pathname=`${t.pathname.replace(/\/+$/,"")}/api/agent-runtime-bridge/ws`,t.search="",t.toString()}function Be(r){return Object.entries(r||{}).map(([t,e])=>({targetCode:t,targetName:c(e?.name||e?.targetName||t),targetType:c(e?.type||"echo"),status:"available",metadata:u(e)?e:{}}))}var W=class{constructor(t,e){this.config=t,this.bridge=e,this.ws=null,this.stopped=!1,this.connected=!1,this.reconnectTimer=null}start(){this.connect()}stop(){this.stopped=!0,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.reconnectTimer=null,this.ws?.close()}connect(){let t=$e(this.config.orchaUrl),e=new K(t);this.ws=e,e.addEventListener("open",()=>this.authenticate()),e.addEventListener("message",n=>this.handleMessage(n.data)),e.addEventListener("close",()=>this.scheduleReconnect("close")),e.addEventListener("error",n=>{h("warn","orcha-client","runtime node websocket error",{error:String(n?.message||n?.type||n)})})}authenticate(){this.send({type:"runtime_node.authenticate",token:this.config.nodeToken,nodeId:this.config.nodeId,nodeName:this.config.nodeName,version:U,protocolVersion:"orcha-runtime-node.v1",defaultTargetCode:this.config.defaultTargetCode,targets:Be(this.config.targets)})}scheduleReconnect(t){this.connected=!1,!this.stopped&&(this.reconnectTimer||(h("info","orcha-client","runtime node disconnected; reconnect scheduled",{reason:t,reconnectMs:this.config.reconnectMs}),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.connect()},this.config.reconnectMs)))}async handleMessage(t){let e;try{e=JSON.parse(String(t))}catch(n){h("warn","orcha-client","invalid Orcha websocket frame",{error:String(n)});return}if(u(e)){if(e.type==="runtime_node.authenticated"){this.connected=!0,h("info","orcha-client","runtime node authenticated",{nodeId:this.config.nodeId,connectionId:e.connectionId});return}if(e.type==="orcha.runtime.request"){await this.handleRequest(e);return}e.type==="runtime_node.ping"&&this.send({type:"runtime_node.pong",ts:new Date().toISOString()})}}async handleRequest(t){let e=c(t.id),n=c(t.method),s=u(t.params)?t.params:{};try{let i=await this.invoke(n,s,e);this.send({type:"orcha.runtime.response",id:e,ok:!0,result:i})}catch(i){this.send({type:"orcha.runtime.response",id:e,ok:!1,error:{code:i.code||"RUNTIME_NODE_ERROR",message:i.message||String(i)}})}}async invoke(t,e,n){if(t==="health")return this.bridge.health();if(t==="agents/create")return this.bridge.createAgent(e);if(t==="agents/dispatch")return this.bridge.dispatch(e,{onUpdate:s=>this.sendUpdate(n,s)});if(t==="sessions/prompt")return this.bridge.prompt(e,{onUpdate:s=>this.sendUpdate(n,s)});if(t==="sessions/cancel")return this.bridge.cancel(e);if(t==="permissions/respond")return this.bridge.respondPermission(e);throw Object.assign(new Error(`unsupported Orcha runtime method: ${t}`),{code:"METHOD_NOT_FOUND"})}sendUpdate(t,e){this.send({type:"orcha.runtime.event",requestId:t,eventType:"runtime.update",payload:e})}send(t){return!this.ws||this.ws.readyState!==J?!1:(this.ws.send(JSON.stringify(t)),!0)}};import{existsSync as ze,readFileSync as Ge}from"node:fs";import{resolve as Ft}from"node:path";var je=/^[A-Za-z_][A-Za-z0-9_]*$/;function Ht(r=process.env,t=process.cwd()){let e=c(r.ORCHA_RUNTIME_ENV_FILE),n=e?Ft(t,e):Ft(t,".env");if(!ze(n))return e&&h("warn","config","runtime env file not found",{path:n}),{loaded:!1,path:n,keys:[]};let s=[],i=Ge(n,"utf8");for(let a of i.split(/\r?\n/)){let o=Je(a);if(!o)continue;let[d,l]=o;Object.prototype.hasOwnProperty.call(r,d)||(r[d]=l,s.push(d))}return h("info","config","runtime env file loaded",{path:n,keyCount:s.length}),{loaded:!0,path:n,keys:s}}function $t(r=process.env){return{mode:c(r.ORCHA_RUNTIME_MODE||(r.ORCHA_RUNTIME_ORCHA_URL?"node":"server")),host:r.ORCHA_RUNTIME_BRIDGE_HOST||"127.0.0.1",port:T(r.ORCHA_RUNTIME_BRIDGE_PORT,5588),token:r.ORCHA_RUNTIME_BRIDGE_TOKEN||"",orchaUrl:c(r.ORCHA_RUNTIME_ORCHA_URL),nodeToken:r.ORCHA_RUNTIME_NODE_TOKEN||r.ORCHA_RUNTIME_BRIDGE_TOKEN||"",nodeId:c(r.ORCHA_RUNTIME_NODE_ID||r.HOSTNAME||"local-runtime-node"),nodeName:c(r.ORCHA_RUNTIME_NODE_NAME||r.ORCHA_RUNTIME_NODE_ID||r.HOSTNAME||"Local Runtime Node"),reconnectMs:T(r.ORCHA_RUNTIME_RECONNECT_MS,3e3),defaultTargetCode:r.ORCHA_RUNTIME_DEFAULT_TARGET||"echo",requestLimitBytes:T(r.ORCHA_RUNTIME_REQUEST_LIMIT_BYTES,1048576),sessionPromptTimeoutMs:T(r.ORCHA_RUNTIME_SESSION_PROMPT_TIMEOUT_MS,36e5),permissionRequestTimeoutMs:T(r.ORCHA_RUNTIME_PERMISSION_TIMEOUT_MS,3e5),targets:qe(r.ORCHA_RUNTIME_TARGETS_JSON||"")}}function qe(r){if(!c(r))return{};try{let t=JSON.parse(r);if(u(t))return t}catch(t){h("warn","config","invalid ORCHA_RUNTIME_TARGETS_JSON",{error:String(t)})}return{}}function Je(r){let t=r.trim();if(!t||t.startsWith("#"))return null;let e=t.startsWith("export ")?t.slice(7).trimStart():t,n=e.indexOf("=");if(n<=0)return null;let s=e.slice(0,n).trim();if(!je.test(s))return null;let i=Ke(e.slice(n+1).trim());return[s,i]}function Ke(r){if(!r)return"";let t=r[0];if((t==='"'||t==="'")&&r.endsWith(t)){let e=r.slice(1,-1);return t==='"'?We(e):e}return Ve(r).trim()}function We(r){return r.replaceAll("\\n",`
14
- `).replaceAll("\\r","\r").replaceAll("\\t"," ").replaceAll('\\"','"').replaceAll("\\\\","\\")}function Ve(r){let t=!1,e=!1;for(let n=0;n<r.length;n+=1){let s=r[n],i=r[n-1];if(s==="'"&&!e)t=!t;else if(s==='"'&&!t&&i!=="\\")e=!e;else if(s==="#"&&!t&&!e&&/\s/.test(i||""))return r.slice(0,n)}return r}import{createServer as Xe}from"node:http";function V(r,t,e){let n=JSON.stringify(e);r.writeHead(t,{"content-type":"application/json; charset=utf-8","content-length":Buffer.byteLength(n)}),r.end(n)}function R(r={}){return{ok:!0,...r}}function ut(r,t,e){return{ok:!1,error:{code:r,message:t,...e===void 0?{}:{detail:e}}}}async function Bt(r,t){let e=[],n=0;for await(let i of r){if(n+=i.length,n>t)throw Object.assign(new Error("request body too large"),{status:413,code:"REQUEST_TOO_LARGE"});e.push(i)}if(e.length===0)return{};let s=Buffer.concat(e).toString("utf8");if(!s.trim())return{};try{let i=JSON.parse(s);if(!u(i))throw Object.assign(new Error("JSON body must be an object"),{status:400,code:"BAD_JSON"});return i}catch(i){throw i.status?i:Object.assign(new Error(`invalid JSON body: ${i.message}`),{status:400,code:"BAD_JSON"})}}function zt(r,t){if(!t)return;if((r.headers.authorization||"")!==`Bearer ${t}`)throw Object.assign(new Error("runtime bridge token is invalid"),{status:401,code:"UNAUTHORIZED"})}function Gt(r,t){let e={"GET /health":async()=>R(t.health()),"POST /agents/create":async n=>R(await t.createAgent(n)),"POST /agents/dispatch":async n=>R(await t.dispatch(n)),"POST /sessions/prompt":async n=>R(await t.prompt(n)),"POST /sessions/cancel":async n=>R(await t.cancel(n)),"POST /permissions/respond":async n=>R(await t.respondPermission(n))};return Xe(async(n,s)=>{let i=new URL(n.url||"/",`http://${n.headers.host||`${r.host}:${r.port}`}`),a=`${n.method||"GET"} ${i.pathname}`,o=e[a];if(!o){V(s,404,ut("NOT_FOUND",`No route for ${a}`));return}try{zt(n,r.token);let d=n.method==="GET"?{}:await Bt(n,r.requestLimitBytes);V(s,200,await o(d))}catch(d){let l=d.status||500,p=d.code||"BRIDGE_INTERNAL";V(s,l,ut(p,d.message||String(d)))}})}var ar=or(import.meta.url),cr=".orcha-runtime-bridge.pid",dr=".orcha-runtime-bridge.log",{command:ur,options:Xt}=hr(process.argv.slice(2));mr(Xt);Ht();var lr=$t();await pr(ur,lr,Xt);async function pr(r,t,e){switch(r){case"run":case"foreground":jt(t);return;case"start":if(e.foreground){jt(t);return}qt();return;case"reload":case"restart":await Jt({quiet:!0}),qt();return;case"stop":await Jt();return;case"status":fr();return;case"help":case"--help":case"-h":gr();return;default:throw new Error(`Unknown command: ${r}`)}}function jt(r){let t=new q(r);if(r.mode==="server"){Gt(r,t).listen(r.port,r.host,()=>{h("info","runtime-bridge","Orcha runtime bridge HTTP server started",{host:r.host,port:r.port,targets:Object.keys(t.targets)})});return}if(!r.orchaUrl)throw new Error("ORCHA_RUNTIME_ORCHA_URL is required in runtime node mode");new W(r,t).start(),h("info","runtime-bridge","Orcha runtime node started",{nodeId:r.nodeId,nodeName:r.nodeName,orchaUrl:r.orchaUrl,targets:Object.keys(t.targets)})}function qt(){let r=pt(),t=Yt(),e=ft(r);if(e&&N(e)){console.log(JSON.stringify({status:"already_running",pid:e,pidFile:r,logFile:t}));return}e&&lt(r),Wt(r),Wt(t);let n=er(t,"a"),s=Ye(process.execPath,[ar,"run"],{cwd:process.cwd(),detached:!0,env:process.env,stdio:["ignore",n,n]});s.unref(),Qe(n),sr(r,`${s.pid}
15
- `),console.log(JSON.stringify({status:"started",pid:s.pid,pidFile:r,logFile:t}))}async function Jt({quiet:r=!1}={}){let t=pt(),e=ft(t);if(!e){r||console.log(JSON.stringify({status:"not_running",pidFile:t}));return}if(!N(e)){lt(t),r||console.log(JSON.stringify({status:"not_running",pid:e,pidFile:t}));return}process.kill(e,"SIGTERM"),!await Kt(e,1e4)&&N(e)&&(process.kill(e,"SIGKILL"),await Kt(e,3e3)),lt(t),r||console.log(JSON.stringify({status:"stopped",pid:e,pidFile:t}))}function fr(){let r=pt(),t=Yt(),e=ft(r),n=!!(e&&N(e));console.log(JSON.stringify({status:n?"running":"not_running",running:n,pid:n?e:null,pidFile:r,logFile:t}))}function hr(r){let t=[],e={};for(let s=0;s<r.length;s+=1){let i=r[s];i==="--daemon"?e.daemon=!0:i==="--foreground"?e.foreground=!0:i==="--env-file"?e.envFile=r[++s]:i==="--pid-file"?e.pidFile=r[++s]:i==="--log-file"?e.logFile=r[++s]:t.push(i)}return{command:t[0]||"run",options:e}}function mr(r){r.envFile&&(process.env.ORCHA_RUNTIME_ENV_FILE=r.envFile),r.pidFile&&(process.env.ORCHA_RUNTIME_PID_FILE=r.pidFile),r.logFile&&(process.env.ORCHA_RUNTIME_LOG_FILE=r.logFile)}function pt(){return Vt(process.cwd(),process.env.ORCHA_RUNTIME_PID_FILE||cr)}function Yt(){return Vt(process.cwd(),process.env.ORCHA_RUNTIME_LOG_FILE||dr)}function ft(r){if(!Ze(r))return null;let t=Number.parseInt(rr(r,"utf8").trim(),10);return Number.isInteger(t)&&t>0?t:null}function N(r){try{return process.kill(r,0),!0}catch(t){return t?.code==="EPERM"}}async function Kt(r,t){let e=Date.now();for(;Date.now()-e<t;){if(!N(r))return!0;await new Promise(n=>setTimeout(n,100))}return!N(r)}function Wt(r){tr(ir(r),{recursive:!0})}function lt(r){try{nr(r,{force:!0})}catch{}}function gr(){console.log(`Usage: orcha-runtime-bridge [command] [options]
10
+ ${s}`:s;t.emittedTexts.add(s),n({sessionId:e,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:i}}})}ut(t,ct(r)),Qe(r)&&n({sessionId:e,update:{sessionUpdate:"runtime_event",event:$t(r)}})}function Pt(r,t,e,n,s=Date.now()){if(!t)return{artifactCount:0,transcriptCount:0};let i=r.artifacts.size,a=0;for(let o of Ht(t.target,t.startedAtMs,s)){let u="";try{u=at(o.path,"utf8")}catch{continue}let l=Gt(u);if(!t.matchedPaths.has(o.path)){if(!zt(l,t.promptText))continue;t.matchedPaths.add(o.path),f("info","runtime.cli","codex transcript stream attached",{target:t.target.targetCode,sessionId:e})}let p=Math.min(t.processedLines.get(o.path)||0,l.length),h=r.artifacts.size;for(let m of l.slice(p))tr(m,r,e,n);t.processedLines.set(o.path,l.length),(l.length>p||r.artifacts.size>h)&&(a+=1)}return{artifactCount:r.artifacts.size-i,transcriptCount:a}}function er(r,{target:t,promptText:e,startedAtMs:n,endedAtMs:s}){let i=r.artifacts.size,a=0;for(let o of Ht(t,n,s)){let u="";try{u=at(o.path,"utf8")}catch{continue}let l=Gt(u);if(!zt(l,e))continue;let p=r.artifacts.size;for(let h of l)ut(r,ct(h));r.artifacts.size>p&&(a+=1)}return{artifactCount:r.artifacts.size-i,transcriptCount:a}}function rr(r){if(!r||!vt(r))return"";try{return at(r,"utf8").trim()}catch{return""}finally{try{De(r)}catch{}}}var q=class{constructor(t,e,n={}){this.agent=t,this.target=e,this.options=n,this.active=new Map}async sessionNew(){return{sessionId:`cli-${this.agent.agentId}-${it()}`}}async sessionPrompt(t,e){let n=Date.now(),s=c(this.target.command);if(!s)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);let i=c(t.sessionId)||it(),a=F(t.prompt),o=c(this.target.promptMode||"stdin"),u=this.buildArgs(o,a),l=Je(s,u,this.target)?k($e(),`orcha-runtime-last-message-${it()}.txt`):"";l&&u.push("--output-last-message",l);let p=I(this.target.timeoutMs||this.target.sessionPromptTimeoutMs,I(this.options.sessionPromptTimeoutMs,He)),h={...process.env,...d(this.target.env)?this.target.env:{},...o==="env"?{ORCHA_RUNTIME_PROMPT:a}:{},ORCHA_AGENT_ID:this.agent.agentId,ORCHA_SESSION_ID:i},m=Le(s,u,{cwd:c(this.target.cwd)||this.agent.workspace||process.cwd(),env:h,stdio:["pipe","pipe","pipe"]});this.active.set(i,m),f("info","runtime.cli","runtime prompt started",{target:this.agent.targetCode,sessionId:i,pid:m.pid,timeoutMs:p});let T="",S=c(this.target.outputMode||"text"),g={artifacts:new Map,emittedTexts:new Set,value:""},X=Lt(s,this.target)?Ve({...this.target,targetCode:this.agent.targetCode},a,n):null;return m.stdout.setEncoding("utf8"),m.stdout.on("data",U=>this.handleStdout(U,S,g,i,e)),m.stderr.setEncoding("utf8"),m.stderr.on("data",U=>{T+=U,this.target.emitStderr===!0&&e({sessionId:i,update:{sessionUpdate:"runtime_stderr_chunk",content:{type:"text",text:U}}})}),o==="stdin"?m.stdin.end(a):m.stdin.end(),await new Promise((U,ue)=>{let L=!1,wt=!1,R=null,Q=X?setInterval(()=>{try{Pt(g,X,i,e)}catch(_){f("warn","runtime.cli","codex transcript stream poll failed",{target:this.agent.targetCode,sessionId:i,error:String(_?.message||_)})}},Ke(this.target)):null;Q?.unref?.();let Tt=setTimeout(()=>{wt=!0,f("warn","runtime.cli","runtime prompt timed out; terminating child",{target:this.agent.targetCode,sessionId:i,pid:m.pid,timeoutMs:p}),j(m,"SIGTERM"),R=setTimeout(()=>{f("warn","runtime.cli","runtime prompt force killing child",{target:this.agent.targetCode,sessionId:i,pid:m.pid}),j(m,"SIGKILL")},Be),R.unref?.(),Et(Object.assign(new Error(`runtime CLI timed out after ${p}ms`),{code:"RUNTIME_CLI_TIMEOUT"}))},p);Tt.unref?.();let It=()=>{clearTimeout(Tt),Q&&clearInterval(Q),R&&!wt&&clearTimeout(R),this.active.delete(i)},de=_=>{L||(L=!0,It(),U(_))},Et=_=>{L||(L=!0,It(),ue(_))};m.on("error",_=>{f("warn","runtime.cli","runtime child error",{target:this.agent.targetCode,sessionId:i,pid:m.pid,error:String(_?.message||_)}),Et(_)}),m.on("exit",(_,St)=>{R&&(clearTimeout(R),R=null),S==="json-lines"&&g.value.trim()&&this.handleStdout(`
11
+ `,S,g,i,e),Pt(g,X,i,e,Date.now());let P=rr(l);if(P&&!g.emittedTexts.has(P)&&(g.emittedTexts.add(P),e({sessionId:i,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:P}}})),Lt(s,this.target)){let tt=er(g,{target:this.target,promptText:a,startedAtMs:n,endedAtMs:Date.now()});tt.artifactCount>0&&f("info","runtime.cli","codex transcript artifacts collected",{target:this.agent.targetCode,sessionId:i,artifactCount:tt.artifactCount,transcriptCount:tt.transcriptCount})}let v=T.trim();v&&f("debug","runtime.cli","runtime stderr",{target:this.agent.targetCode,sessionId:i,stderr:v}),f("info","runtime.cli","runtime prompt finished",{target:this.agent.targetCode,sessionId:i,pid:m.pid,exitCode:_,signal:St,artifactCount:g.artifacts.size}),de({stopReason:_===0?"end_turn":"error",exitCode:_,signal:St,artifacts:[...g.artifacts.values()],...v?{stderr:v}:{}})})})}buildArgs(t,e){let n=D(this.target.args);return t==="args"?[...n,e]:n}handleStdout(t,e,n,s,i){if(e!=="json-lines"){i({sessionId:s,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:t}}});return}n.value+=t;let a=n.value.split(/\r?\n/);n.value=a.pop()||"";for(let o of a){let u=o.trim();if(u)try{let l=JSON.parse(u);ut(n,ct(l)),i({sessionId:s,update:{sessionUpdate:"runtime_event",event:$t(l)}});let p=Ft(l);p&&!n.emittedTexts.has(p)&&(n.emittedTexts.add(p),i({sessionId:s,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:p}}}))}catch{i({sessionId:s,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`${o}
12
+ `}}})}}}async sessionCancel(t){let e=c(t.sessionId),n=this.active.get(e);return n?(f("info","runtime.cli","cancelling runtime child",{target:this.agent.targetCode,sessionId:e,pid:n.pid}),j(n,"SIGTERM"),this.active.delete(e),{ok:!0,cancelled:!0}):{ok:!0,cancelled:!1}}stop(t="stop"){for(let[e,n]of this.active.entries())f("info","runtime.cli","stopping runtime child",{target:this.agent.targetCode,sessionId:e,pid:n.pid,reason:t}),j(n,"SIGTERM");this.active.clear()}};function nr(r,t,e){let n=d(r?._meta)?r._meta:{};return{...d(r)?r:{},sessionId:t,update:d(r?.update)?r.update:{},_meta:{...n,orchaAgentId:e.agentId,runtimeSessionId:e.runtimeSessionId,bridgeUpdateId:J()}}}var K=class{constructor(t){this.config=t,this.targets=t.targets||{},this.agents=new Map,this.sessions=new Map,this.runtimeSessionIndex=new Map,this.pendingPermissions=new Map,this.startedAt=C()}targetFor(t){let e=c(t)||this.config.defaultTargetCode,n=this.targets[e];return{code:e,target:d(n)?n:{type:"echo"}}}async createAgent(t){let e=c(t.agentId);if(!e)throw Object.assign(new Error("agentId is required"),{status:400,code:"BAD_REQUEST"});let{code:n,target:s}=this.targetFor(t.targetCode||t.framework),i={agentId:e,targetCode:n,framework:c(t.framework||n),workspace:c(t.workspace),metadata:d(t.metadata)?t.metadata:{},createdAt:C(),runtimeKind:c(s.type||"echo")};return this.agents.set(e,i),{agent:i}}runtimeFor(t,e){let{target:n}=this.targetFor(t.targetCode),s=c(n.type||"echo"),i={onPermissionRequest:o=>this.requestPermission(o)},a={sessionPromptTimeoutMs:this.config.sessionPromptTimeoutMs};return s==="stdio-acp"||s==="acp"?new A(t,n,i,a):s==="openclaw"?new z(t,n,e,i,a):s==="cli"?new q(t,n,a):new $(t)}async prompt(t,e={}){let n=c(t.agentId),s=c(t.sessionId)||J();if(!n)throw Object.assign(new Error("agentId is required"),{status:400,code:"BAD_REQUEST"});let i=this.agents.get(n)||(await this.createAgent({agentId:n,targetCode:t.targetCode,framework:t.framework,workspace:t.workspace,metadata:t.metadata})).agent,a=c(t.workspace);a&&a!==i.workspace&&(i.workspace=a);let o=`${n}:${s}`,u=this.sessions.get(o);if(!u){let m=this.runtimeFor(i,s),T=await m.sessionNew({cwd:i.workspace||process.cwd(),metadata:d(t.metadata)?t.metadata:{}});u={agentId:n,sessionId:s,runtime:m,runtimeSessionId:c(d(T)?T.sessionId:"")||s,createdAt:C()},this.sessions.set(o,u),this.runtimeSessionIndex.set(`${n}:${u.runtimeSessionId}`,u)}let l=[],p=m=>{let T=nr(m,s,u);l.push(T),e.onUpdate?.(T)},h=await u.runtime.sessionPrompt({sessionId:u.runtimeSessionId,prompt:Array.isArray(t.prompt)?t.prompt:[],metadata:d(t.metadata)?t.metadata:{}},p);return{sessionId:s,runtimeSessionId:u.runtimeSessionId,result:d(h)?h:{},updates:l}}async cancel(t){let e=c(t.agentId),n=c(t.sessionId),s=this.sessions.get(`${e}:${n}`);return s?(await s.runtime.sessionCancel({sessionId:s.runtimeSessionId}),{cancelled:!0}):{cancelled:!1}}async dispatch(t,e={}){let n=c(t.agentId),s=c(t.taskId),i=c(t.executionId);if(!n||!s)throw Object.assign(new Error("agentId and taskId are required"),{status:400,code:"BAD_REQUEST"});let a=c(t.sessionId)||`dispatch-${i||s}`,o=c(t.instructions),u=[{type:"text",text:["Task dispatch received.",`taskId: ${s}`,i?`executionId: ${i}`:"",o?`instructions: ${o}`:""].filter(Boolean).join(`
13
+ `)}];return this.prompt({...t,agentId:n,sessionId:a,prompt:u},e)}async requestPermission({agent:t,runtimeSessionId:e,request:n,emitUpdate:s}){let i=J(),o=this.runtimeSessionIndex.get(`${t.agentId}:${e}`)?.sessionId||e||J(),u={permissionId:i,agentId:t.agentId,sessionId:o,runtimeSessionId:e,request:d(n)?n:{},status:"pending",createdAt:C()};return s?.({sessionId:e,update:{sessionUpdate:"permission_request",permission:u}}),await new Promise(l=>{let p=I(n?.timeoutMs,this.config.permissionRequestTimeoutMs),h=setTimeout(()=>{this.pendingPermissions.delete(i),l({permissionId:i,outcome:"denied",response:{reason:"permission request timed out"}})},p);this.pendingPermissions.set(i,{timer:h,resolve:l,permission:u})})}async respondPermission(t){let e=c(t.permissionId),n=this.pendingPermissions.get(e),s=c(t.outcome||"approved")||"approved";return n?(clearTimeout(n.timer),this.pendingPermissions.delete(e),n.resolve({permissionId:e,outcome:s,response:d(t.response)?t.response:{},userId:c(t.userId),metadata:d(t.metadata)?t.metadata:{}}),{accepted:!0,permissionId:e,outcome:s}):{accepted:!1,permissionId:e,outcome:s}}health(){return{status:"ok",bridgeVersion:O,startedAt:this.startedAt,agents:[...this.agents.values()].map(t=>({agentId:t.agentId,targetCode:t.targetCode,framework:t.framework,runtimeKind:t.runtimeKind})),sessions:this.sessions.size,pendingPermissions:this.pendingPermissions.size,targets:Object.keys(this.targets)}}};import sr from"node:http";import ir from"node:https";import{randomBytes as jt}from"node:crypto";var V=1,dt=3,W=class{constructor(t){this.url=t,this.readyState=0,this.socket=null,this.buffer=Buffer.alloc(0),this.listeners=new Map,this.connect()}addEventListener(t,e){let n=this.listeners.get(t)||new Set;n.add(e),this.listeners.set(t,n)}emit(t,e={}){let n=this.listeners.get(t);if(n)for(let s of n)s(e)}connect(){let t=new URL(this.url),e=t.protocol==="wss:"?ir:sr,n=jt(16).toString("base64"),s=e.request({protocol:t.protocol==="wss:"?"https:":"http:",hostname:t.hostname,port:t.port||(t.protocol==="wss:"?443:80),path:`${t.pathname}${t.search}`,method:"GET",headers:{Connection:"Upgrade",Upgrade:"websocket","Sec-WebSocket-Key":n,"Sec-WebSocket-Version":"13"}});s.on("upgrade",(i,a,o)=>{this.socket=a,this.readyState=V,a.on("data",u=>this.onData(u)),a.on("close",()=>this.onClose()),a.on("error",u=>{this.emit("error",{error:u,message:u.message,type:"error"}),this.onClose()}),o?.length&&this.onData(o),this.emit("open")}),s.on("response",i=>{this.emit("error",{message:`websocket upgrade failed: HTTP ${i.statusCode}`,type:"error"}),i.resume(),this.onClose()}),s.on("error",i=>{this.emit("error",{error:i,message:i.message,type:"error"}),this.onClose()}),s.end()}send(t){!this.socket||this.readyState!==V||this.socket.write(lt(1,Buffer.from(String(t),"utf8")))}close(){!this.socket||this.readyState===dt||(this.socket.write(lt(8,Buffer.alloc(0))),this.socket.end(),this.onClose())}onClose(){this.readyState!==dt&&(this.readyState=dt,this.emit("close"))}onData(t){for(this.buffer=Buffer.concat([this.buffer,t]);this.buffer.length>=2;){let e=this.buffer[0],n=this.buffer[1],s=e&15,i=(n&128)!==0,a=n&127,o=2;if(a===126){if(this.buffer.length<o+2)return;a=this.buffer.readUInt16BE(o),o+=2}else if(a===127){if(this.buffer.length<o+8)return;let p=this.buffer.readUInt32BE(o),h=this.buffer.readUInt32BE(o+4);a=p*2**32+h,o+=8}let u=o;if(i&&(o+=4),this.buffer.length<o+a)return;let l=this.buffer.subarray(o,o+a);if(i){let p=this.buffer.subarray(u,u+4);l=Buffer.from(l.map((h,m)=>h^p[m%4]))}this.buffer=this.buffer.subarray(o+a),s===1?this.emit("message",{data:l.toString("utf8")}):s===8?this.close():s===9&&this.socket?.write(lt(10,l))}}};function lt(r,t){let e=t.length,n=2;e>=126&&e<=65535?n+=2:e>65535&&(n+=8);let s=jt(4),i=Buffer.alloc(n+4+e);i[0]=128|r;let a=2;e<126?i[1]=128|e:e<=65535?(i[1]=254,i.writeUInt16BE(e,a),a+=2):(i[1]=255,i.writeUInt32BE(Math.floor(e/2**32),a),i.writeUInt32BE(e>>>0,a+4),a+=8),s.copy(i,a),a+=4;for(let o=0;o<e;o+=1)i[a+o]=t[o]^s[o%4];return i}function or(r){let t=new URL(r);if(t.protocol==="http:")t.protocol="ws:";else if(t.protocol==="https:")t.protocol="wss:";else if(t.protocol!=="ws:"&&t.protocol!=="wss:")throw new Error(`unsupported ORCHA_RUNTIME_ORCHA_URL protocol: ${t.protocol}`);return t.pathname=`${t.pathname.replace(/\/+$/,"")}/api/agent-runtime-bridge/ws`,t.search="",t.toString()}function ar(r){return Object.entries(r||{}).map(([t,e])=>({targetCode:t,targetName:c(e?.name||e?.targetName||t),targetType:c(e?.type||"echo"),status:"available",metadata:d(e)?e:{}}))}var Y=class{constructor(t,e){this.config=t,this.bridge=e,this.ws=null,this.stopped=!1,this.connected=!1,this.reconnectTimer=null}start(){this.connect()}stop(){this.stopped=!0,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.reconnectTimer=null,this.ws?.close()}connect(){let t=or(this.config.orchaUrl),e=new W(t);this.ws=e,e.addEventListener("open",()=>this.authenticate()),e.addEventListener("message",n=>this.handleMessage(n.data)),e.addEventListener("close",()=>this.scheduleReconnect("close")),e.addEventListener("error",n=>{f("warn","orcha-client","runtime node websocket error",{error:String(n?.message||n?.type||n)})})}authenticate(){this.send({type:"runtime_node.authenticate",token:this.config.nodeToken,nodeId:this.config.nodeId,nodeName:this.config.nodeName,version:O,protocolVersion:"orcha-runtime-node.v1",defaultTargetCode:this.config.defaultTargetCode,targets:ar(this.config.targets)})}scheduleReconnect(t){this.connected=!1,!this.stopped&&(this.reconnectTimer||(f("info","orcha-client","runtime node disconnected; reconnect scheduled",{reason:t,reconnectMs:this.config.reconnectMs}),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.connect()},this.config.reconnectMs)))}async handleMessage(t){let e;try{e=JSON.parse(String(t))}catch(n){f("warn","orcha-client","invalid Orcha websocket frame",{error:String(n)});return}if(d(e)){if(e.type==="runtime_node.authenticated"){this.connected=!0,f("info","orcha-client","runtime node authenticated",{nodeId:this.config.nodeId,connectionId:e.connectionId});return}if(e.type==="orcha.runtime.request"){await this.handleRequest(e);return}e.type==="runtime_node.ping"&&this.send({type:"runtime_node.pong",ts:new Date().toISOString()})}}async handleRequest(t){let e=c(t.id),n=c(t.method),s=d(t.params)?t.params:{};try{let i=await this.invoke(n,s,e);this.send({type:"orcha.runtime.response",id:e,ok:!0,result:i})}catch(i){this.send({type:"orcha.runtime.response",id:e,ok:!1,error:{code:i.code||"RUNTIME_NODE_ERROR",message:i.message||String(i)}})}}async invoke(t,e,n){if(t==="health")return this.bridge.health();if(t==="agents/create")return this.bridge.createAgent(e);if(t==="agents/dispatch")return this.bridge.dispatch(e,{onUpdate:s=>this.sendUpdate(n,s)});if(t==="sessions/prompt")return this.bridge.prompt(e,{onUpdate:s=>this.sendUpdate(n,s)});if(t==="sessions/cancel")return this.bridge.cancel(e);if(t==="permissions/respond")return this.bridge.respondPermission(e);throw Object.assign(new Error(`unsupported Orcha runtime method: ${t}`),{code:"METHOD_NOT_FOUND"})}sendUpdate(t,e){this.send({type:"orcha.runtime.event",requestId:t,eventType:"runtime.update",payload:e})}send(t){return!this.ws||this.ws.readyState!==V?!1:(this.ws.send(JSON.stringify(t)),!0)}};import{existsSync as cr,readFileSync as ur}from"node:fs";import{resolve as qt}from"node:path";var dr=/^[A-Za-z_][A-Za-z0-9_]*$/;function Jt(r=process.env,t=process.cwd()){let e=c(r.ORCHA_RUNTIME_ENV_FILE),n=e?qt(t,e):qt(t,".env");if(!cr(n))return e&&f("warn","config","runtime env file not found",{path:n}),{loaded:!1,path:n,keys:[]};let s=[],i=ur(n,"utf8");for(let a of i.split(/\r?\n/)){let o=pr(a);if(!o)continue;let[u,l]=o;Object.prototype.hasOwnProperty.call(r,u)||(r[u]=l,s.push(u))}return f("info","config","runtime env file loaded",{path:n,keyCount:s.length}),{loaded:!0,path:n,keys:s}}function Kt(r=process.env){return{mode:c(r.ORCHA_RUNTIME_MODE||(r.ORCHA_RUNTIME_ORCHA_URL?"node":"server")),host:r.ORCHA_RUNTIME_BRIDGE_HOST||"127.0.0.1",port:I(r.ORCHA_RUNTIME_BRIDGE_PORT,5588),token:r.ORCHA_RUNTIME_BRIDGE_TOKEN||"",orchaUrl:c(r.ORCHA_RUNTIME_ORCHA_URL),nodeToken:r.ORCHA_RUNTIME_NODE_TOKEN||r.ORCHA_RUNTIME_BRIDGE_TOKEN||"",nodeId:c(r.ORCHA_RUNTIME_NODE_ID||r.HOSTNAME||"local-runtime-node"),nodeName:c(r.ORCHA_RUNTIME_NODE_NAME||r.ORCHA_RUNTIME_NODE_ID||r.HOSTNAME||"Local Runtime Node"),reconnectMs:I(r.ORCHA_RUNTIME_RECONNECT_MS,3e3),defaultTargetCode:r.ORCHA_RUNTIME_DEFAULT_TARGET||"echo",requestLimitBytes:I(r.ORCHA_RUNTIME_REQUEST_LIMIT_BYTES,1048576),sessionPromptTimeoutMs:I(r.ORCHA_RUNTIME_SESSION_PROMPT_TIMEOUT_MS,36e5),permissionRequestTimeoutMs:I(r.ORCHA_RUNTIME_PERMISSION_TIMEOUT_MS,3e5),targets:lr(r.ORCHA_RUNTIME_TARGETS_JSON||"")}}function lr(r){if(!c(r))return{};try{let t=JSON.parse(r);if(d(t))return t}catch(t){f("warn","config","invalid ORCHA_RUNTIME_TARGETS_JSON",{error:String(t)})}return{}}function pr(r){let t=r.trim();if(!t||t.startsWith("#"))return null;let e=t.startsWith("export ")?t.slice(7).trimStart():t,n=e.indexOf("=");if(n<=0)return null;let s=e.slice(0,n).trim();if(!dr.test(s))return null;let i=fr(e.slice(n+1).trim());return[s,i]}function fr(r){if(!r)return"";let t=r[0];if((t==='"'||t==="'")&&r.endsWith(t)){let e=r.slice(1,-1);return t==='"'?mr(e):e}return hr(r).trim()}function mr(r){return r.replaceAll("\\n",`
14
+ `).replaceAll("\\r","\r").replaceAll("\\t"," ").replaceAll('\\"','"').replaceAll("\\\\","\\")}function hr(r){let t=!1,e=!1;for(let n=0;n<r.length;n+=1){let s=r[n],i=r[n-1];if(s==="'"&&!e)t=!t;else if(s==='"'&&!t&&i!=="\\")e=!e;else if(s==="#"&&!t&&!e&&/\s/.test(i||""))return r.slice(0,n)}return r}import{createServer as gr}from"node:http";function Z(r,t,e){let n=JSON.stringify(e);r.writeHead(t,{"content-type":"application/json; charset=utf-8","content-length":Buffer.byteLength(n)}),r.end(n)}function x(r={}){return{ok:!0,...r}}function pt(r,t,e){return{ok:!1,error:{code:r,message:t,...e===void 0?{}:{detail:e}}}}async function Vt(r,t){let e=[],n=0;for await(let i of r){if(n+=i.length,n>t)throw Object.assign(new Error("request body too large"),{status:413,code:"REQUEST_TOO_LARGE"});e.push(i)}if(e.length===0)return{};let s=Buffer.concat(e).toString("utf8");if(!s.trim())return{};try{let i=JSON.parse(s);if(!d(i))throw Object.assign(new Error("JSON body must be an object"),{status:400,code:"BAD_JSON"});return i}catch(i){throw i.status?i:Object.assign(new Error(`invalid JSON body: ${i.message}`),{status:400,code:"BAD_JSON"})}}function Wt(r,t){if(!t)return;if((r.headers.authorization||"")!==`Bearer ${t}`)throw Object.assign(new Error("runtime bridge token is invalid"),{status:401,code:"UNAUTHORIZED"})}function Yt(r,t){let e={"GET /health":async()=>x(t.health()),"POST /agents/create":async n=>x(await t.createAgent(n)),"POST /agents/dispatch":async n=>x(await t.dispatch(n)),"POST /sessions/prompt":async n=>x(await t.prompt(n)),"POST /sessions/cancel":async n=>x(await t.cancel(n)),"POST /permissions/respond":async n=>x(await t.respondPermission(n))};return gr(async(n,s)=>{let i=new URL(n.url||"/",`http://${n.headers.host||`${r.host}:${r.port}`}`),a=`${n.method||"GET"} ${i.pathname}`,o=e[a];if(!o){Z(s,404,pt("NOT_FOUND",`No route for ${a}`));return}try{Wt(n,r.token);let u=n.method==="GET"?{}:await Vt(n,r.requestLimitBytes);Z(s,200,await o(u))}catch(u){let l=u.status||500,p=u.code||"BRIDGE_INTERNAL";Z(s,l,pt(p,u.message||String(u)))}})}var Rr=Sr(import.meta.url),xr=".orcha-runtime-bridge.pid",Ur=".orcha-runtime-bridge.log",Or=3,Ar=36e5,{command:Nr,options:ie}=kr(process.argv.slice(2));Lr(ie);Jt();var Mr=Kt();await Cr(Nr,Mr,ie);async function Cr(r,t,e){switch(r){case"run":case"foreground":Xt(t);return;case"start":if(e.foreground){Xt(t);return}Qt();return;case"reload":case"restart":await te({quiet:!0}),Qt();return;case"stop":await te();return;case"status":br();return;case"help":case"--help":case"-h":Fr();return;default:throw new Error(`Unknown command: ${r}`)}}function Xt(r){Pr();let t=new K(r);if(r.mode==="server"){Yt(r,t).listen(r.port,r.host,()=>{f("info","runtime-bridge","Orcha runtime bridge HTTP server started",{host:r.host,port:r.port,targets:Object.keys(t.targets)})});return}if(!r.orchaUrl)throw new Error("ORCHA_RUNTIME_ORCHA_URL is required in runtime node mode");new Y(r,t).start(),f("info","runtime-bridge","Orcha runtime node started",{nodeId:r.nodeId,nodeName:r.nodeName,orchaUrl:r.orchaUrl,targets:Object.keys(t.targets)})}function Qt(){let r=yt(),t=oe(),e=_t(r);if(e&&N(e)){console.log(JSON.stringify({status:"already_running",pid:e,pidFile:r,logFile:t}));return}e&&ht(r),re(r),re(t),mt(t);let n=Tr(t,"a"),s={...process.env,ORCHA_RUNTIME_PID_FILE:r,ORCHA_RUNTIME_LOG_FILE:t},i=yr(process.execPath,[Rr,"run"],{cwd:process.cwd(),detached:!0,env:s,stdio:["ignore",n,n]});i.unref(),_r(n),se(r,`${i.pid}
15
+ `),console.log(JSON.stringify({status:"started",pid:i.pid,pidFile:r,logFile:t}))}async function te({quiet:r=!1}={}){let t=yt(),e=_t(t);if(!e){r||console.log(JSON.stringify({status:"not_running",pidFile:t}));return}if(!N(e)){ht(t),r||console.log(JSON.stringify({status:"not_running",pid:e,pidFile:t}));return}process.kill(e,"SIGTERM"),!await ee(e,1e4)&&N(e)&&(process.kill(e,"SIGKILL"),await ee(e,3e3)),ht(t),r||console.log(JSON.stringify({status:"stopped",pid:e,pidFile:t}))}function br(){let r=yt(),t=oe(),e=_t(r),n=!!(e&&N(e));console.log(JSON.stringify({status:n?"running":"not_running",running:n,pid:n?e:null,pidFile:r,logFile:t}))}function kr(r){let t=[],e={};for(let s=0;s<r.length;s+=1){let i=r[s];i==="--daemon"?e.daemon=!0:i==="--foreground"?e.foreground=!0:i==="--env-file"?e.envFile=r[++s]:i==="--pid-file"?e.pidFile=r[++s]:i==="--log-file"?e.logFile=r[++s]:t.push(i)}return{command:t[0]||"run",options:e}}function Lr(r){r.envFile&&(process.env.ORCHA_RUNTIME_ENV_FILE=r.envFile),r.pidFile&&(process.env.ORCHA_RUNTIME_PID_FILE=r.pidFile),r.logFile&&(process.env.ORCHA_RUNTIME_LOG_FILE=r.logFile)}function yt(){return gt(process.cwd(),process.env.ORCHA_RUNTIME_PID_FILE||xr)}function oe(){return gt(process.cwd(),process.env.ORCHA_RUNTIME_LOG_FILE||Ur)}function Pr(){let r=process.env.ORCHA_RUNTIME_LOG_FILE;if(!r)return;let t=ae();if(t<=0)return;let e=gt(process.cwd(),r);mt(e,t);let n=Dr();n<=0||setInterval(()=>mt(e,t),n).unref()}function mt(r,t=ae()){if(t<=0||!ne(r))return;let e=0,n="";try{if(e=Zt(r).size,e<=0)return;n=ft(r,"utf8")}catch(l){f("warn","runtime-bridge","runtime log cleanup skipped",{logFile:r,error:String(l)});return}let s=Date.now()-t*24*60*60*1e3,i=n.split(/\r?\n/),a=[],o=0;for(let l of i)l&&(vr(l,s)?a.push(l):o+=1);if(o===0)return;let u="";try{Zt(r).size>e&&(u=ft(r,"utf8").slice(n.length));let p=[...a,...u.split(/\r?\n/).filter(Boolean)].join(`
16
+ `);se(r,p?`${p}
17
+ `:""),f("info","runtime-bridge","runtime log cleanup completed",{logFile:r,retentionDays:t,removed:o})}catch(l){f("warn","runtime-bridge","runtime log cleanup failed",{logFile:r,error:String(l)})}}function vr(r,t){try{let e=JSON.parse(r);if(!e||typeof e!="object")return!0;let n=typeof e.ts=="string"?Date.parse(e.ts):Number.NaN;return!Number.isFinite(n)||n>=t}catch{return!0}}function ae(){return ce(process.env.ORCHA_RUNTIME_LOG_RETENTION_DAYS,Or)}function Dr(){return ce(process.env.ORCHA_RUNTIME_LOG_CLEANUP_INTERVAL_MS,Ar)}function ce(r,t){let e=Number.parseInt(String(r??""),10);return Number.isFinite(e)&&e>=0?e:t}function _t(r){if(!ne(r))return null;let t=Number.parseInt(ft(r,"utf8").trim(),10);return Number.isInteger(t)&&t>0?t:null}function N(r){try{return process.kill(r,0),!0}catch(t){return t?.code==="EPERM"}}async function ee(r,t){let e=Date.now();for(;Date.now()-e<t;){if(!N(r))return!0;await new Promise(n=>setTimeout(n,100))}return!N(r)}function re(r){wr(Er(r),{recursive:!0})}function ht(r){try{Ir(r,{force:!0})}catch{}}function Fr(){console.log(`Usage: orcha-runtime-bridge [command] [options]
16
18
 
17
19
  Commands:
18
20
  run, foreground Run in the foreground. This is the default.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orcha-ai/runtime-bridge",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Local Orcha runtime bridge for ACP-compatible agent runtimes.",