@orcha-ai/runtime-bridge 0.1.3 → 0.1.6
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 +6 -1
- package/README.md +24 -2
- package/bin/orcha-runtime-bridge.js +15 -13
- package/package.json +1 -1
package/.env.example
CHANGED
|
@@ -10,10 +10,15 @@ ORCHA_RUNTIME_DEFAULT_TARGET=codex
|
|
|
10
10
|
ORCHA_RUNTIME_RECONNECT_MS=3000
|
|
11
11
|
ORCHA_RUNTIME_SESSION_PROMPT_TIMEOUT_MS=3600000
|
|
12
12
|
ORCHA_RUNTIME_PERMISSION_TIMEOUT_MS=300000
|
|
13
|
+
ORCHA_RUNTIME_SESSION_IDLE_TTL_MS=600000
|
|
14
|
+
ORCHA_RUNTIME_SESSION_CLEANUP_INTERVAL_MS=60000
|
|
15
|
+
ORCHA_RUNTIME_MAX_SESSIONS_PER_TARGET=8
|
|
16
|
+
ORCHA_RUNTIME_OPENCLAW_SESSION_IDLE_TTL_MS=60000
|
|
17
|
+
ORCHA_RUNTIME_OPENCLAW_MAX_SESSIONS=1
|
|
13
18
|
ORCHA_RUNTIME_PID_FILE=.orcha-runtime-bridge.pid
|
|
14
19
|
ORCHA_RUNTIME_LOG_FILE=.orcha-runtime-bridge.log
|
|
15
20
|
ORCHA_RUNTIME_LOG_RETENTION_DAYS=3
|
|
16
21
|
ORCHA_RUNTIME_LOG_CLEANUP_INTERVAL_MS=3600000
|
|
17
22
|
|
|
18
23
|
# Target examples. Keep this JSON on one line.
|
|
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"}}'
|
|
24
|
+
ORCHA_RUNTIME_TARGETS_JSON='{"codex":{"type":"cli","command":"codex","args":["exec","--json"],"promptMode":"stdin","outputMode":"json-lines","captureLastMessage":true},"openclaw":{"type":"openclaw","command":"openclaw","maxSessions":1,"releaseAfterPrompt":true,"sessionIdleTtlMs":60000},"claude":{"type":"cli","command":"claude","args":["-p","--output-format","json","--no-session-persistence"],"promptMode":"args","outputMode":"json-lines"}}'
|
package/README.md
CHANGED
|
@@ -125,6 +125,9 @@ Runtime targets are configured with `ORCHA_RUNTIME_TARGETS_JSON`.
|
|
|
125
125
|
"openclaw": {
|
|
126
126
|
"type": "openclaw",
|
|
127
127
|
"command": "openclaw",
|
|
128
|
+
"maxSessions": 1,
|
|
129
|
+
"releaseAfterPrompt": true,
|
|
130
|
+
"sessionIdleTtlMs": 60000,
|
|
128
131
|
"mcpServers": []
|
|
129
132
|
},
|
|
130
133
|
"custom-acp": {
|
|
@@ -136,8 +139,9 @@ Runtime targets are configured with `ORCHA_RUNTIME_TARGETS_JSON`.
|
|
|
136
139
|
}
|
|
137
140
|
```
|
|
138
141
|
|
|
139
|
-
If a
|
|
140
|
-
|
|
142
|
+
If a request references a missing target, the bridge returns
|
|
143
|
+
`RUNTIME_TARGET_NOT_FOUND`. The built-in `echo` adapter is available only when
|
|
144
|
+
you explicitly configure a target with `"type": "echo"`.
|
|
141
145
|
|
|
142
146
|
Target types:
|
|
143
147
|
|
|
@@ -153,6 +157,24 @@ OpenClaw targets use request metadata `agentCode` as the local OpenClaw agent
|
|
|
153
157
|
id, producing sessions like `agent:<agentCode>:<sessionId>`. When `agentCode`
|
|
154
158
|
is missing, the bridge falls back to a plain `orcha-<sessionId>` session.
|
|
155
159
|
|
|
160
|
+
OpenClaw may start browser processes under the hood, so the bridge applies
|
|
161
|
+
stricter defaults for this target type:
|
|
162
|
+
|
|
163
|
+
- `maxSessions`: defaults to `1` for OpenClaw.
|
|
164
|
+
- `releaseAfterPrompt`: defaults to `true` for OpenClaw, stopping the runtime
|
|
165
|
+
process after each prompt.
|
|
166
|
+
- `sessionIdleTtlMs`: defaults to `60000` for OpenClaw.
|
|
167
|
+
|
|
168
|
+
Global lifecycle knobs:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
ORCHA_RUNTIME_SESSION_IDLE_TTL_MS=600000
|
|
172
|
+
ORCHA_RUNTIME_SESSION_CLEANUP_INTERVAL_MS=60000
|
|
173
|
+
ORCHA_RUNTIME_MAX_SESSIONS_PER_TARGET=8
|
|
174
|
+
ORCHA_RUNTIME_OPENCLAW_SESSION_IDLE_TTL_MS=60000
|
|
175
|
+
ORCHA_RUNTIME_OPENCLAW_MAX_SESSIONS=1
|
|
176
|
+
```
|
|
177
|
+
|
|
156
178
|
Supported stdio framing:
|
|
157
179
|
|
|
158
180
|
- `line`: one JSON-RPC frame per line.
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{spawn as
|
|
3
|
-
`):""}var
|
|
2
|
+
import{spawn as Ar}from"node:child_process";import{closeSync as Or,existsSync as Oe,mkdirSync as Ur,openSync as Cr,readFileSync as xt,rmSync as Mr,statSync as Se,writeFileSync as Ue}from"node:fs";import{dirname as Nr,resolve as Ut}from"node:path";import{fileURLToPath as br}from"node:url";import{randomUUID as nt}from"node:crypto";var P="0.1.6";function v(){return new Date().toISOString()}function S(e,t=2){return String(e).padStart(t,"0")}function Ft(e){let t=e>=0?"+":"-",n=Math.abs(e);return`${t}${S(Math.floor(n/60))}:${S(n%60)}`}function De(e){let t=-e.getTimezoneOffset();return[`${e.getFullYear()}-${S(e.getMonth()+1)}-${S(e.getDate())}`,`T${S(e.getHours())}:${S(e.getMinutes())}:${S(e.getSeconds())}.${S(e.getMilliseconds(),3)}`,Ft(t)].join("")}function Fe(e,t){let n=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"}),r={};for(let s of n.formatToParts(e))s.type!=="literal"&&(r[s.type]=Number(s.value));return r}function $e(e,t){let n=Fe(e,t),r=Date.UTC(n.year,n.month-1,n.day,n.hour,n.minute,n.second,e.getMilliseconds()),s=Math.round((r-e.getTime())/6e4);return[`${n.year}-${S(n.month)}-${S(n.day)}`,`T${S(n.hour)}:${S(n.minute)}:${S(n.second)}.${S(e.getMilliseconds(),3)}`,Ft(s)].join("")}function He(e=new Date){let t=o(process.env.ORCHA_RUNTIME_LOG_TIMEZONE||process.env.TZ||"Asia/Shanghai");try{return $e(e,t)}catch{return De(e)}}function c(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function o(e){return String(e??"").trim()}function h(e,t){let n=Number.parseInt(String(e??""),10);return Number.isFinite(n)?n:t}function I(e){return Array.isArray(e)?e.map(String):[]}var ve="[redacted]",Be=/(authorization|api[_-]?key|credential|password|secret|token)/i;function H(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 r={name:e.name,message:e.message};e.stack&&(r.stack=e.stack);for(let s of Object.keys(e))r[s]=H(e[s],t);return t.delete(e),r}if(t.has(e))return"[circular]";if(t.add(e),Array.isArray(e)){let r=e.map(s=>H(s,t));return t.delete(e),r}let n={};for(let[r,s]of Object.entries(e))n[r]=Be.test(r)?ve:H(s,t);return t.delete(e),n}function $t(e,t=4e3){let n=JSON.stringify(H(e))??String(e);return!Number.isFinite(t)||n.length<=t?n:`${n.slice(0,t)}...`}function f(e,t,n,r={}){let s={ts:He(),level:e,module:t,msg:n,...c(r)?H(r):{}};console.error(JSON.stringify(s))}function q(e){return Array.isArray(e)?e.map(t=>c(t)?t.type==="text"?o(t.text):t.type==="file"?o(t.uri):t.type==="image"?o(t.uri):"":"").filter(Boolean).join(`
|
|
3
|
+
`):""}var K=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,n){let r=q(t.prompt);return n({sessionId:t.sessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:r?`Echo runtime received: ${r}`:"Echo runtime received an empty prompt."}}}),{stopReason:"end_turn"}}async sessionCancel(){return{ok:!0}}};import{spawn as ze}from"node:child_process";var B="2.0",je=3e4;function Ge(e){return{code:Number.isInteger(e?.code)?e.code:-32e3,message:o(e?.message)||String(e),data:c(e?.data)?e.data:void 0}}function Je(e){if(!c(e))return new Error(String(e||"runtime error"));let t=o(e.message)||"runtime error",n="data"in e?$t(e.data,4e3):"",r=new Error(n?`${t}; data=${n}`:t);return r.rpcCode=e.code,r.data=e.data,r}function qe(e){return c(e)&&"id"in e&&!("method"in e)}function Ke(e){return c(e)&&typeof e.method=="string"&&"id"in e}function We(e){return c(e)&&typeof e.method=="string"&&!("id"in e)}var W=class{constructor({command:t,args:n=[],cwd:r,env:s,label:i,framing:u="line"}){this.command=t,this.args=Array.isArray(n)?n.map(String):[],this.cwd=r||process.cwd(),this.env={...process.env,...c(s)?s:{}},this.label=i||t,this.framing=u==="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:n={}}={}){this.child&&!this.child.killed||(this.child=ze(this.command,this.args,{cwd:this.cwd,env:this.env,stdio:["pipe","pipe","pipe"]}),this.child.stdout.on("data",r=>this.onStdout(r)),this.child.stderr.setEncoding("utf8"),this.child.stderr.on("data",r=>{let s=r.trimEnd();s&&f("debug","runtime.stderr","runtime stderr",{target:this.label,text:s})}),this.child.on("exit",(r,s)=>this.handleExit(r,s)),this.child.on("error",r=>this.rejectAll(r)),t&&await this.call("initialize",{protocolVersion:1,clientCapabilities:{},...n}).catch(r=>{throw Object.assign(new Error(`runtime initialize failed: ${r.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 n=this.lineBuffer.split(/\r?\n/);this.lineBuffer=n.pop()||"";for(let r of n){let s=r.trim();s&&this.dispatchRaw(s)}}onContentLengthData(t){for(this.headerBuffer=Buffer.concat([this.headerBuffer,t]);this.headerBuffer.length>0;){let n=this.headerBuffer.indexOf(`\r
|
|
4
4
|
\r
|
|
5
|
-
`);if(
|
|
5
|
+
`);if(n<0)return;let s=this.headerBuffer.subarray(0,n).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),u=n+4,a=u+i;if(this.headerBuffer.length<a)return;let l=this.headerBuffer.subarray(u,a).toString("utf8");this.headerBuffer=this.headerBuffer.subarray(a),this.dispatchRaw(l)}}dispatchRaw(t){let n;try{n=JSON.parse(t)}catch(r){f("warn","runtime.protocol","invalid JSON frame",{target:this.label,error:String(r)});return}this.dispatch(n)}dispatch(t){if(qe(t)){this.resolveResponse(t);return}if(Ke(t)){this.handleRequest(t);return}We(t)&&this.handleNotification(t)}resolveResponse(t){let n=String(t.id),r=this.pending.get(n);r&&(clearTimeout(r.timer),this.pending.delete(n),t.error?(f("warn","runtime.protocol","runtime rpc error",{target:this.label,method:r.method,requestId:n,error:t.error}),r.reject(Je(t.error))):r.resolve(t.result))}async handleRequest(t){let n=this.requestHandlers.get(t.method);if(!n){this.writeFrame({jsonrpc:B,id:t.id,error:{code:-32601,message:`method not found: ${t.method}`}});return}try{let r=await n(c(t.params)?t.params:{},t);this.writeFrame({jsonrpc:B,id:t.id,result:r??{}})}catch(r){this.writeFrame({jsonrpc:B,id:t.id,error:Ge(r)})}}handleNotification(t){let n=this.notificationHandlers.get(t.method);if(n)for(let r of n)r(c(t.params)?t.params:{},t)}call(t,n={},r=je){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:n};return new Promise((u,a)=>{let l=setTimeout(()=>{this.pending.delete(s),a(new Error(`${t} timed out after ${r}ms`))},r);this.pending.set(s,{resolve:u,reject:a,timer:l,method:t}),this.writeFrame(i,d=>{d&&(clearTimeout(l),this.pending.delete(s),a(d))})})}notify(t,n={}){this.writeFrame({jsonrpc:B,method:t,params:n})}writeFrame(t,n){if(!this.child?.stdin||this.child.killed){n?.(new Error("runtime process is not running"));return}let r=JSON.stringify(t),s=this.framing==="content-length"?`Content-Length: ${Buffer.byteLength(r,"utf8")}\r
|
|
6
6
|
\r
|
|
7
|
-
${
|
|
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?`
|
|
7
|
+
${r}`:`${r}
|
|
8
|
+
`;this.child.stdin.write(s,n)}onNotification(t,n){let r=this.notificationHandlers.get(t)||new Set;return r.add(n),this.notificationHandlers.set(t,r),()=>{r.delete(n),r.size===0&&this.notificationHandlers.delete(t)}}onRequest(t,n){return this.requestHandlers.set(t,n),()=>this.requestHandlers.delete(t)}onExit(t){return this.exitHandlers.add(t),()=>this.exitHandlers.delete(t)}rejectAll(t){for(let n of this.pending.values())clearTimeout(n.timer),n.reject(t);this.pending.clear()}handleExit(t,n){this.rejectAll(new Error(`runtime exited before response (${t}/${n})`));for(let r of this.exitHandlers)r(t,n)}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 Bt}from"node:crypto";import{existsSync as Xe,readFileSync as Ve,realpathSync as Ht,statSync as Ye}from"node:fs";import{basename as zt,extname as jt,isAbsolute as Ze,relative as Qe}from"node:path";var tn=25*1024*1024;function Gt(e,t=""){let n=o(t);if(n)return n;let r=jt(o(e)).toLowerCase();return r===".jpg"||r===".jpeg"?"image/jpeg":r===".webp"?"image/webp":r===".gif"?"image/gif":"image/png"}function Jt(e,t){let n=typeof e=="string"?e.trim():"";return!n||n==="<omitted>"?"":n.startsWith("data:")?n:`data:${t};base64,${n.replace(/\s+/g,"")}`}function X(e){if(Array.isArray(e))return e.map(o).filter(Boolean);let t=o(e);return t?[t]:[]}function en(e,t){let n=Qe(t,e);return n===""||!!n&&!n.startsWith("..")&&!Ze(n)}function nn(e,t){let n=o(e);if(!n||!Xe(n))return"";try{let r=Ht(n);for(let s of t)try{let i=Ht(s);if(en(r,i))return r}catch{}}catch{return""}return""}function ft(e,t,n={}){let r=o(e);return!r||r.startsWith("data:")||/^https?:\/\//i.test(r)?r:rn(r,t,n)}function rn(e,t,n={}){let r=[...X(n.trustedFileRoots),...X(n.trustedFileRoot),...X(n.artifactRoots),...X(n.artifactRoot)],s=nn(e,r);if(!s)return"";try{let i=Ye(s);return!i.isFile()||i.size<=0||i.size>tn?"":`data:${t};base64,${Ve(s).toString("base64")}`}catch{return""}}function _(...e){for(let t of e){let n=o(t);if(n)return n}return""}function sn(e,t,n,r){let s=n.toLowerCase();if(s==="image"||s==="picture")return!0;let i=_(r,e.previewUrl,e.fileUrl,e.imageUrl,e.dataUrl,e.url,e.uri,t.previewUrl,t.fileUrl,t.imageUrl,t.dataUrl,t.url,t.uri),u=jt(i.split("?",1)[0].split("#",1)[0]).toLowerCase();return[".png",".jpg",".jpeg",".webp",".gif"].includes(u)}function mt(e,t={}){let{source:n="runtime_image_generation_event"}=t;if(!c(e))return null;let r=c(e.payload)?e.payload:{},s=o(e.type),i=o(r.type);if(!(s==="event_msg"&&i==="image_generation_end"||s==="response_item"&&i==="image_generation_call"))return null;let u=_(r.call_id,r.id),a=_(r.saved_path,r.savedPath),l=_(r.revised_prompt,r.revisedPrompt),d=Gt(a,r.mimeType||r.mime_type),p=Jt(r.result,d)||ft(a,d,t);if(!p)return null;let m=a?zt(a):`${u||Bt()}.png`;return{artifactType:"image",type:"image",title:m||"Generated image",summary:l||"Generated image",content:{prompt:l||void 0,imageUrl:p,previewUrl:p,fileUrl:p,mimeType:d},previewUrl:p,fileUrl:p,metadata:{source:n,eventType:i,callId:u||void 0,savedPath:a||void 0,filename:m,mimeType:d,revisedPrompt:l||void 0}}}function on(e){let t=c(e)?e:{},n=[];for(let r of["_artifacts","artifacts"]){let s=t[r];Array.isArray(s)&&n.push(...s)}for(let r of["_artifact","artifact"]){let s=t[r];c(s)&&n.push(s)}return n}function an(e,t={}){let{source:n="runtime_artifact"}=t,r=c(e)?e:{};if(!Object.keys(r).length)return null;let s=c(r.content)?{...r.content}:{},i=c(r.metadata)?{...r.metadata}:{},u=_(r.saved_path,r.savedPath,s.saved_path,s.savedPath,i.savedPath),a=_(r.mimeType,r.mime_type,s.mimeType,s.mime_type,i.mimeType),l=_(r.artifactType,r.artifact_type,r.type,r.kind,s.type,u?"image":"file"),d=sn(r,s,l,u),p=d?Gt(u,a):a;if(d){let E=_(r.dataUrl,s.dataUrl),A=E.startsWith("data:")?E:"",w=_(r.imageUrl,r.previewUrl,r.fileUrl,r.downloadUrl,r.url,r.uri,s.imageUrl,s.previewUrl,s.fileUrl,s.downloadUrl,s.url,s.uri),O=Jt(r.result??s.result,p)||A||ft(u,p,t)||ft(w,p,t);O&&(s.imageUrl||=O,s.previewUrl||=O,s.fileUrl||=O,p&&(s.mimeType||=p))}for(let[E,A]of[["prompt","prompt"],["previewUrl","previewUrl"],["fileUrl","fileUrl"],["downloadUrl","downloadUrl"],["imageUrl","imageUrl"],["dataUrl","dataUrl"],["url","url"],["uri","uri"],["mimeType","mimeType"],["mime_type","mimeType"]]){let w=r[E];w!=null&&w!==""&&!(A in s)&&(s[A]=w)}let m=_(r.fileUrl,r.downloadUrl,r.imageUrl,r.dataUrl,r.url,r.uri,s.fileUrl,s.downloadUrl,s.imageUrl,s.dataUrl,s.url,s.uri),T=_(r.previewUrl,r.imageUrl,r.dataUrl,r.url,r.fileUrl,r.uri,s.previewUrl,s.imageUrl,s.dataUrl,s.url,s.fileUrl,s.uri),x=_(r.filename,i.filename,u?zt(u):"");return{...r,artifactType:l,type:r.type||l,title:_(r.title,x,"Runtime artifact"),summary:_(r.summary,s.prompt,r.title,x,"Runtime artifact"),content:s,fileUrl:m||void 0,previewUrl:T||void 0,metadata:{...i,source:_(i.source,n),savedPath:u||i.savedPath,filename:x||i.filename,mimeType:p||i.mimeType}}}function V(e,t){if(!t||!e)return;let n=c(t.metadata)?t.metadata:{},r=_(n.savedPath,n.callId,t.previewUrl,t.fileUrl)||Bt(),s=e.get(r);if(!s){e.set(r,t);return}s.content={...c(s.content)?s.content:{},...c(t.content)?t.content:{}},s.metadata={...c(s.metadata)?s.metadata:{},...n},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 pt(e,t,n={}){for(let r of on(e))V(t,an(r,n))}function ht(e){if(!c(e)||!c(e.payload))return c(e)?e:{value:e};let t=o(e.payload.type);if(t!=="image_generation_end"&&t!=="image_generation_call")return e;let n={...e.payload};return typeof n.result=="string"&&n.result&&(n.result="<omitted>",n.resultLength=e.payload.result.length),{...e,payload:n}}function vt(e,t,n){if(!c(e))return e;let r=c(e.event)?e.event:null;return r?(V(t,mt(r,n)),{...e,event:ht(r)}):e}function qt(e,t,n={}){if(!c(e))return e;pt(e,t,n);let r=vt(e,t,n),s=c(r.update)?vt(r.update,t,n):null;return s&&s!==r.update&&(r={...r,update:s}),r}function Kt(e,t,n={}){let r=c(e)?{...e}:{};pt(r,t,n),pt(c(r.output)?r.output:{},t,n);let s=[...t?.values?.()||[]];return s.length&&(r.artifacts=s),r}var D=class{constructor(t,n,r={},s={}){this.agent=t,this.target=n,this.callbacks=r,this.options=s,this.proc=null,this.permissionHandlers=new Map}async ensureStarted(){if(this.proc)return;let t=o(this.target.command);if(!t)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);this.proc=new W({command:t,args:I(this.target.args),cwd:o(this.target.cwd)||this.agent.workspace||process.cwd(),env:c(this.target.env)?this.target.env:{},label:`${this.agent.agentId}:${this.agent.targetCode}`,framing:o(this.target.framing||"line")}),this.proc.onRequest("session/request_permission",n=>this.handlePermissionRequest(n)),this.proc.onRequest("session/requestPermission",n=>this.handlePermissionRequest(n)),await this.proc.start({initialize:this.target.initialize!==!1,initializeParams:{clientInfo:{name:"orcha-runtime-bridge",version:P},...c(this.target.initializeParams)?this.target.initializeParams:{}}})}async sessionNew(t={}){await this.ensureStarted();let n=Array.isArray(t.mcpServers)?t.mcpServers:Array.isArray(this.target.mcpServers)?this.target.mcpServers:[];return this.proc.call("session/new",{...t,mcpServers:n})}async sessionPrompt(t,n){await this.ensureStarted();let r=o(t.sessionId),s=new Map,i=this.artifactOptions(),u=this.proc.onNotification("session/update",l=>{let d=o(l.sessionId);(!d||d===r)&&n(qt(l,s,i))}),a=async l=>this.callbacks.onPermissionRequest?.({agent:this.agent,runtimeSessionId:r,request:l,emitUpdate:n})||{outcome:"denied",reason:"permission handler is not configured"};r&&this.permissionHandlers.set(r,a),this.permissionHandlers.set("*",a);try{let l=await this.proc.call("session/prompt",t,this.options.sessionPromptTimeoutMs);return Kt(l,s,i)}finally{u(),r&&this.permissionHandlers.delete(r),this.permissionHandlers.delete("*")}}async sessionCancel(t){return await this.ensureStarted(),this.proc.call("session/cancel",t,5e3).catch(()=>({ok:!0}))}async handlePermissionRequest(t){let n=o(t.sessionId),r=this.permissionHandlers.get(n)||this.permissionHandlers.get("*");return r?r(t):{outcome:"denied",reason:"no active Orcha permission handler"}}artifactSource(){return o(this.target.type||"acp")==="openclaw"?"openclaw_image_generation":"acp_runtime_image_generation"}artifactOptions(){let t=c(this.target.env)?this.target.env:{};return{source:this.artifactSource(),trustedFileRoots:[o(this.target.artifactRoot),o(this.target.artifactDir),o(this.target.runtimeArtifactRoot),o(t.ORCHA_RUNTIME_ARTIFACT_DIR),...I(this.target.trustedArtifactRoots),...I(this.target.trustedFileRoots),...I(this.target.artifactRoots),...I(this.target.artifactFileRoots)].filter(Boolean)}}stop(t){this.proc?.stop(t)}};function cn(e){let t=c(e.metadata)?e.metadata:{};return o(t.agentCode)}function un(e,t){let n=cn(e);return n?`agent:${n}:${t}`:`orcha-${t}`}var Y=class extends D{constructor(t,n,r,s={},i={}){let u=o(r).replace(/[^A-Za-z0-9._-]+/g,"-")||"default",a=o(n.command)||"openclaw",l=Array.isArray(n.args)?n.args.map(String):[],d=l.length>0?l:["acp","--session",un(t,u)];super(t,{...n,command:a,args:d},s,i)}};import{spawn as ln}from"node:child_process";import{randomUUID as z}from"node:crypto";import{existsSync as Zt,mkdirSync as dn,readdirSync as Qt,readFileSync as te,realpathSync as tt,rmSync as fn,rmdirSync as pn,statSync as mn,unlinkSync as hn}from"node:fs";import{homedir as gn,tmpdir as ee}from"node:os";import{basename as ne,dirname as _n,join as C,resolve as Wt}from"node:path";var Tn=36e5,yn=5e3,Sn=2*60*1e3,In=2*60*1e3,En=12,wn=1e3,Z=24*60*60*1e3;function Q(e,t){try{e.kill(t)}catch{}}function R(e){if(typeof e=="string")return e;if(Array.isArray(e))return e.map(t=>R(t)).join("");if(!c(e))return"";for(let t of["text","delta","output_text","content","message","output"]){let n=R(e[t]);if(n)return n}return""}function re(e){if(!c(e))return"";let t=c(e.payload)?e.payload:{};if(o(e.type)==="event_msg"){if(o(t.type)==="agent_message")return o(t.message);if(o(t.type)==="task_complete")return o(t.last_agent_message)}if(o(e.type)==="response_item"&&o(t.type)==="message"&&o(t.role)==="assistant")return R(t.content)||R(t.message);let n=R(e.delta)||R(e.text)||R(e.content);if(n)return n;let r=c(e.item)?e.item:{};return o(r.role)==="assistant"||o(r.type)==="message"?R(r.content)||R(r.text)||R(r.message):""}function se(e,t={}){return mt(e,{source:"codex_cli_image_generation",...t})}function ie(e,t){V(e.artifacts,t)}function oe(e){return ht(e)}function Rn(e,t,n){return n.captureLastMessage===!1||t.includes("--output-last-message")||t.includes("-o")?!1:n.captureLastMessage===!0?!0:ne(e)==="codex"}function xn(e,t){return t.collectCodexTranscriptArtifacts===!1?!1:t.collectCodexTranscriptArtifacts===!0?!0:ne(e)==="codex"}function An(e){return Math.max(20,h(e.codexTranscriptPollMs||e.transcriptPollMs,wn))}function On(e){return e.codexTranscriptStreaming===!0||e.streamCodexTranscript===!0}function Un(e,t,n,r=new Set){return{target:e,promptText:t,startedAtMs:n,baselinePaths:r,matchedPath:"",disabled:!1,processedLines:new Map}}function Cn(e,t){let n=c(e.env)?e.env:{},r=o(e.artifactRoot||e.artifactDir||e.runtimeArtifactRoot||n.ORCHA_RUNTIME_ARTIFACT_DIR)||C(ee(),"orcha-runtime-artifacts"),s=o(t).replace(/[^A-Za-z0-9._-]+/g,"-").slice(0,80)||z(),i=C(r,s),u=C(i,z());return dn(u,{recursive:!0}),{root:u,realRoot:tt(u),sessionRoot:i,realSessionRoot:tt(i)}}function ae(e){return o(c(e)?e.root:e)}function Xt(e){let t=ae(e),n=o(c(e)?e.sessionRoot:_n(t)),r=o(c(e)?e.realSessionRoot:"");if(n)try{if(r&&tt(n)!==r)return;pn(n)}catch{}}function Mn(e,t={}){let n=ae(e),r=o(c(e)?e.realRoot:"");if(n){try{if(r&&tt(n)!==r){f("warn","runtime.cli","runtime artifact directory cleanup skipped; path changed",{...t,artifactRoot:n});return}}catch{Xt(e);return}try{fn(n,{recursive:!0,force:!0})}catch(s){f("warn","runtime.cli","runtime artifact directory cleanup failed",{...t,artifactRoot:n,error:String(s?.message||s)});return}Xt(e)}}function Nn(e,t){return{trustedFileRoots:[t,...I(e.trustedArtifactRoots),...I(e.trustedFileRoots),...I(e.artifactRoots),...I(e.artifactFileRoots)].filter(Boolean)}}function ce(e){let t=o(e.codexSessionsRoot||e.codexSessionRoot);if(t)return t;let n=c(e.env)?e.env:{},r=o(e.codexHome||n.CODEX_HOME||process.env.CODEX_HOME)||C(gn(),".codex");return C(r,"sessions")}function bn(e,t){let n=new Date(t),r=String(n.getFullYear()),s=String(n.getMonth()+1).padStart(2,"0"),i=String(n.getDate()).padStart(2,"0");return C(e,r,s,i)}function ue(e,t,n){let r=new Set;for(let s of[t-Z,t,t+Z,n-Z,n,n+Z])r.add(bn(e,s));return[...r].filter(s=>Zt(s))}function kn(e,t,n){let r=ce(e),s=t-Sn,i=n+In,u=[];for(let a of ue(r,t,n)){let l=[];try{l=Qt(a)}catch{continue}for(let d of l){if(!d.endsWith(".jsonl"))continue;let p=C(a,d);try{let m=mn(p);if(!m.isFile()||m.mtimeMs<s||m.mtimeMs>i)continue;u.push({path:p,mtimeMs:m.mtimeMs})}catch{}}}return u.sort((a,l)=>l.mtimeMs-a.mtimeMs).slice(0,En)}function Ln(e,t,n=t){let r=ce(e),s=new Set;for(let i of ue(r,t,n)){let u=[];try{u=Qt(i)}catch{continue}for(let a of u)a.endsWith(".jsonl")&&s.add(C(i,a))}return s}function gt(e,t,n=0){if(!(n>8||e===null||e===void 0)){if(typeof e=="string"){e&&t.push(e);return}if(Array.isArray(e)){for(let r of e)gt(r,t,n+1);return}if(c(e))for(let r of["payload","item","text","delta","output_text","content","message","output","input","prompt","last_agent_message","revised_prompt"])r in e&>(e[r],t,n+1)}}function le(e){return o(e).replace(/\s+/g," ")}function Pn(e){let t=le(e);if(!t)return[];if(t.length<=200)return[t];let n=160,r=[0,Math.floor((t.length-n)/2),t.length-n],s=new Set,i=[];for(let u of r){let a=t.slice(Math.max(0,u),Math.max(0,u)+n).trim();a.length>=40&&!s.has(a)&&(s.add(a),i.push(a))}return i}function Dn(e,t){let n=Pn(t);if(!n.length)return!1;let r=[];for(let i of e)gt(i,r);let s=le(r.join(" "));return n.every(i=>s.includes(i))}function Fn(e){return e.find(t=>c(t)&&o(t.type)==="session_meta"&&c(t.payload))||null}function $n(e){let t=c(e?.payload)?e.payload:{},n=o(e?.timestamp||t.timestamp),r=Date.parse(n);return Number.isFinite(r)?r:Number.NaN}function Hn(e,t,n){if(!Dn(e,t.promptText))return!1;let r=Fn(e);if(!r)return!1;let s=r.payload,i=o(s.originator),u=o(s.source);if(i!=="codex_exec"&&u!=="exec")return!1;let a=$n(r);if(!Number.isFinite(a)||a<t.startedAtMs-5e3||a>n+5e3)return!1;let l=o(t.target.cwd),d=o(s.cwd);return!(l&&d&&Wt(l)!==Wt(d))}function Vt(e){try{return Bn(te(e,"utf8"))}catch{return null}}function vn(e,t,n){if(!e||e.disabled)return null;if(e.matchedPath){let s=Vt(e.matchedPath);return s?{path:e.matchedPath,events:s}:null}let r=[];for(let s of kn(e.target,e.startedAtMs,n)){if(e.baselinePaths.has(s.path))continue;let i=Vt(s.path);!i||!Hn(i,e,n)||r.push({path:s.path,events:i})}return r.length!==1?(r.length>1&&(e.disabled=!0,f("warn","runtime.cli","codex transcript fallback disabled; multiple matching transcripts",{target:e.target.targetCode,sessionId:t,transcriptCount:r.length})),null):(e.matchedPath=r[0].path,f("info","runtime.cli","codex transcript stream attached",{target:e.target.targetCode,sessionId:t}),r[0])}function Bn(e){let t=[];for(let n of e.split(/\r?\n/)){let r=n.trim();if(r)try{t.push(JSON.parse(r))}catch{}}return t}function zn(e){if(!c(e))return!1;let t=c(e.payload)?e.payload:{},n=o(e.type),r=o(t.type);return n==="event_msg"&&r==="image_generation_end"||n==="response_item"&&r==="image_generation_call"}function jn(e,t,n,r){let s=re(e);if(s&&!t.emittedTexts.has(s)){let i=t.emittedTexts.size?`
|
|
9
9
|
|
|
10
|
-
${s}`:s;t.emittedTexts.add(s),
|
|
11
|
-
`,
|
|
12
|
-
`}}})}}}async sessionCancel(t){let
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
`),
|
|
16
|
-
`);
|
|
17
|
-
|
|
10
|
+
${s}`:s;t.emittedTexts.add(s),r({sessionId:n,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:i}}})}ie(t,se(e,t.artifactOptions)),zn(e)&&r({sessionId:n,update:{sessionUpdate:"runtime_event",event:oe(e)}})}function Yt(e,t,n,r,s=Date.now()){if(!t)return{artifactCount:0,transcriptCount:0};let i=e.artifacts.size,u=0,a=vn(t,n,s);if(a){let l=Math.min(t.processedLines.get(a.path)||0,a.events.length),d=e.artifacts.size;for(let p of a.events.slice(l))jn(p,e,n,r);t.processedLines.set(a.path,a.events.length),(a.events.length>l||e.artifacts.size>d)&&(u=1)}return{artifactCount:e.artifacts.size-i,transcriptCount:u}}function Gn(e){if(!e||!Zt(e))return"";try{return te(e,"utf8").trim()}catch{return""}finally{try{hn(e)}catch{}}}var et=class{constructor(t,n,r={}){this.agent=t,this.target=n,this.options=r,this.active=new Map}async sessionNew(){return{sessionId:`cli-${this.agent.agentId}-${z()}`}}async sessionPrompt(t,n){let r=Date.now(),s=o(this.target.command);if(!s)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);let i=o(t.sessionId)||z(),u=q(t.prompt),a=o(this.target.promptMode||"stdin"),l=this.buildArgs(a,u),d=o(this.target.cwd)||this.agent.workspace||process.cwd(),p=Cn(this.target,i),m=p.root,T=Nn(this.target,m),x=xn(s,this.target),E={...this.target,targetCode:this.agent.targetCode,cwd:d},A=x?Ln(E,r):new Set,w=Rn(s,l,this.target)?C(ee(),`orcha-runtime-last-message-${z()}.txt`):"";w&&l.push("--output-last-message",w);let O=h(this.target.timeoutMs||this.target.sessionPromptTimeoutMs,h(this.options.sessionPromptTimeoutMs,Tn)),ke={...process.env,...c(this.target.env)?this.target.env:{},...a==="env"?{ORCHA_RUNTIME_PROMPT:u}:{},ORCHA_AGENT_ID:this.agent.agentId,ORCHA_SESSION_ID:i,ORCHA_RUNTIME_ARTIFACT_DIR:m},g=ln(s,l,{cwd:d,env:ke,stdio:["pipe","pipe","pipe"]});this.active.set(i,g),f("info","runtime.cli","runtime prompt started",{target:this.agent.targetCode,sessionId:i,pid:g.pid,timeoutMs:O});let Nt="",ct=o(this.target.outputMode||"text"),U={artifacts:new Map,emittedTexts:new Set,value:"",artifactOptions:T},ut=x?Un(E,u,r,A):null;return g.stdout.setEncoding("utf8"),g.stdout.on("data",L=>this.handleStdout(L,ct,U,i,n)),g.stderr.setEncoding("utf8"),g.stderr.on("data",L=>{Nt+=L,this.target.emitStderr===!0&&n({sessionId:i,update:{sessionUpdate:"runtime_stderr_chunk",content:{type:"text",text:L}}})}),a==="stdin"?g.stdin.end(u):g.stdin.end(),await new Promise((L,Le)=>{let j=!1,bt=!1,M=null,lt=ut&&On(this.target)?setInterval(()=>{try{Yt(U,ut,i,n)}catch(y){f("warn","runtime.cli","codex transcript stream poll failed",{target:this.agent.targetCode,sessionId:i,error:String(y?.message||y)})}},An(this.target)):null;lt?.unref?.();let kt=setTimeout(()=>{bt=!0,f("warn","runtime.cli","runtime prompt timed out; terminating child",{target:this.agent.targetCode,sessionId:i,pid:g.pid,timeoutMs:O}),Q(g,"SIGTERM"),M=setTimeout(()=>{f("warn","runtime.cli","runtime prompt force killing child",{target:this.agent.targetCode,sessionId:i,pid:g.pid}),Q(g,"SIGKILL")},yn),M.unref?.(),Pt(Object.assign(new Error(`runtime CLI timed out after ${O}ms`),{code:"RUNTIME_CLI_TIMEOUT"}))},O);kt.unref?.();let Lt=()=>{clearTimeout(kt),lt&&clearInterval(lt),M&&!bt&&clearTimeout(M),Mn(p,{target:this.agent.targetCode,sessionId:i}),this.active.delete(i)},Pe=y=>{j||(j=!0,Lt(),L(y))},Pt=y=>{j||(j=!0,Lt(),Le(y))};g.on("error",y=>{f("warn","runtime.cli","runtime child error",{target:this.agent.targetCode,sessionId:i,pid:g.pid,error:String(y?.message||y)}),Pt(y)}),g.on("exit",(y,Dt)=>{M&&(clearTimeout(M),M=null),ct==="json-lines"&&U.value.trim()&&this.handleStdout(`
|
|
11
|
+
`,ct,U,i,n);let dt=Yt(U,ut,i,n,Date.now());dt.artifactCount>0&&f("info","runtime.cli","codex transcript artifacts collected",{target:this.agent.targetCode,sessionId:i,artifactCount:dt.artifactCount,transcriptCount:dt.transcriptCount});let G=Gn(w);G&&!U.emittedTexts.has(G)&&(U.emittedTexts.add(G),n({sessionId:i,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:G}}}));let J=Nt.trim();J&&f("debug","runtime.cli","runtime stderr",{target:this.agent.targetCode,sessionId:i,stderr:J}),f("info","runtime.cli","runtime prompt finished",{target:this.agent.targetCode,sessionId:i,pid:g.pid,exitCode:y,signal:Dt,artifactCount:U.artifacts.size}),Pe({stopReason:y===0?"end_turn":"error",exitCode:y,signal:Dt,artifacts:[...U.artifacts.values()],...J?{stderr:J}:{}})})})}buildArgs(t,n){let r=I(this.target.args);return t==="args"?[...r,n]:r}handleStdout(t,n,r,s,i){if(n!=="json-lines"){i({sessionId:s,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:t}}});return}r.value+=t;let u=r.value.split(/\r?\n/);r.value=u.pop()||"";for(let a of u){let l=a.trim();if(l)try{let d=JSON.parse(l);ie(r,se(d,r.artifactOptions)),i({sessionId:s,update:{sessionUpdate:"runtime_event",event:oe(d)}});let p=re(d);p&&!r.emittedTexts.has(p)&&(r.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:`${a}
|
|
12
|
+
`}}})}}}async sessionCancel(t){let n=o(t.sessionId),r=this.active.get(n);return r?(f("info","runtime.cli","cancelling runtime child",{target:this.agent.targetCode,sessionId:n,pid:r.pid}),Q(r,"SIGTERM"),this.active.delete(n),{ok:!0,cancelled:!0}):{ok:!0,cancelled:!1}}stop(t="stop"){for(let[n,r]of this.active.entries())f("info","runtime.cli","stopping runtime child",{target:this.agent.targetCode,sessionId:n,pid:r.pid,reason:t}),Q(r,"SIGTERM");this.active.clear()}};var _t=24e3,Tt=8,yt=50,St=6e3,Jn=new Set(["fail","failed","failure","error","errored","timeout","timed_out","cancelled","canceled","aborted"]),qn=10*60*1e3,Kn=60*1e3,Wn=8,Xn=60*1e3,Vn=1,Yn=new Set(["agentId","taskId","executionId","sessionId","nodeId","targetCode","framework","workspace","instructions"]),Zn=/(^|[_-])(token|secret|password|authorization|api[-_]?key|private[-_]?key|credential|cookie|jwt|access[-_]?token|refresh[-_]?token|service[-_]?token|execution[-_]?token)([_-]|$)/i;function Qn(e,t,n){let r=c(e?._meta)?e._meta:{};return{...c(e)?e:{},sessionId:t,update:c(e?.update)?e.update:{},_meta:{...r,orchaAgentId:n.agentId,runtimeSessionId:n.runtimeSessionId,bridgeUpdateId:nt()}}}function b(e){return e==null||e===""?!1:typeof e=="string"?o(e)!=="":Array.isArray(e)?e.length>0:c(e)?Object.keys(e).length>0:!0}function tr(e){let t=o(e).toLowerCase().replace(/[.。!!]+$/g,"").replace(/[\s-]+/g,"_");return Jn.has(t)}function N(e,t){let n=h(e,t);return Number.isFinite(n)&&n>0?n:t}function er(e,t=!1){if(typeof e=="boolean")return e;let n=o(e).toLowerCase();return["true","1","yes","y","on"].includes(n)?!0:["false","0","no","n","off"].includes(n)?!1:t}function F(e){return o(e?.type||"echo")}function nr(e){let t=String(e||"");if(Zn.test(t))return!0;let n=t.replace(/[^a-z0-9]/gi,"").toLowerCase();return n.endsWith("token")||n.endsWith("secret")||n.endsWith("password")||n.endsWith("apikey")||n.endsWith("privatekey")||n==="authorization"||n==="cookie"||n==="jwt"||n.includes("credential")}function It(e,t=0){if(e==null||typeof e=="number"||typeof e=="boolean")return e;if(typeof e=="string"){if(e.length<=St)return e;let n=e.length-St;return`${e.slice(0,St)}... [truncated ${n} characters]`}if(t>=Tt)return Array.isArray(e)?`[array truncated at depth ${Tt}, items=${e.length}]`:c(e)?`[object truncated at depth ${Tt}, keys=${Object.keys(e).length}]`:String(e);if(Array.isArray(e)){let n=e.slice(0,yt).map(r=>It(r,t+1));return e.length>yt&&n.push(`[truncated ${e.length-yt} items]`),n}if(c(e)){let n={};for(let[r,s]of Object.entries(e))n[r]=nr(r)?"[REDACTED]":It(s,t+1);return n}return String(e)}function rr(e){let t=c(e)?e:{},n={};b(t.metadata)&&(n.metadata=t.metadata);for(let[r,s]of Object.entries(t))Yn.has(r)||r==="metadata"||b(s)&&(n[r]=s);return n}function sr(e){let t=rr(e);if(!b(t))return"";let n=JSON.stringify(It(t),null,2);if(n.length<=_t)return n;let r=n.length-_t;return`${n.slice(0,_t)}
|
|
13
|
+
... [truncated ${r} characters]`}function ir(e){if(!c(e))return"";let t=c(e.update)?e.update:e,r=(c(t.content)?t.content:{}).text??t.text;return r==null?"":String(r)}function or(e){if(!c(e))return null;let t=c(e.update)?e.update:e;return o(t.sessionUpdate)!=="runtime_event"?null:c(t.event)?t.event:null}function ar(e){if(!c(e))return"";let t=c(e.payload)?e.payload:{},n=o(e.type),r=o(t.type);if(n==="event_msg"){if(r==="task_complete")return o(t.last_agent_message||t.message||t.output);if(r==="agent_message"){let s=o(t.phase||t.status||t.stage).toLowerCase();if(["final_answer","final","complete","completed","done"].includes(s))return o(t.message||t.text||t.content)}}return""}function cr(e){if(!Array.isArray(e))return"";for(let t=e.length-1;t>=0;t-=1){let n=ar(or(e[t]));if(n)return n}return""}function ur(e){let t="";for(let n of e){let r=String(n||"");r&&(t?r.startsWith(t)?t=r:t.endsWith(r)||(t+=r):t=r)}return t.trim()}function lr(e){let t=String(e||"").trim();if(!t)return"";let n=t.match(/(?:^|\n)#{1,3}\s+\S/);return!n||n.index===0?t:t.slice(n.index+(t[n.index]===`
|
|
14
|
+
`?1:0)).trim()}function de(e){let t=String(e||"").trim();if(!t)return null;try{let n=JSON.parse(t);if(c(n)&&(fe(n)||b(n._artifacts)||b(n._decision)||b(n._meta)))return n}catch{}return null}function dr(e){let t=String(e||"").trim();if(!t)return null;let n=[...t.matchAll(/```(?:json)?\s*([\s\S]*?)```/gi)];for(let r=n.length-1;r>=0;r-=1){let s=de(n[r][1]);if(s)return s}if(!t.endsWith("}"))return null;for(let r=t.lastIndexOf("{");r>=0;r=t.lastIndexOf("{",r-1)){let s=de(t.slice(r));if(s)return s}return null}function fe(e){if(!c(e))return!1;if(b(e.output))return!0;for(let t of["content","text","message","summary"])if(o(e[t]))return!0;return!!(tr(e.status)||o(e.error)||o(e.errorMessage))}function fr(e,t){let n=c(e)?{...e}:{};if(fe(n))return n;let r=cr(t);if(r){let i=dr(r);return i?{...n,...i,_meta:{...c(n._meta)?n._meta:{},...c(i._meta)?i._meta:{},runtimeOutputSource:"final_event"}}:{...n,output:r,_meta:{...c(n._meta)?n._meta:{},runtimeOutputSource:"final_event"}}}let s=lr(ur((Array.isArray(t)?t:[]).map(ir)));return s?{...n,output:s,_meta:{...c(n._meta)?n._meta:{},runtimeOutputSource:"updates"}}:n}var rt=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=v(),this.cleanupTimer=null,this.startSessionCleanup()}targetFor(t){let n=o(t)||this.config.defaultTargetCode,r=this.targets[n];if(!n||!c(r)){let s=new Error(`runtime target is not configured: ${n||"<empty>"}`);throw s.code="RUNTIME_TARGET_NOT_FOUND",s}return{code:n,target:r}}targetIdleTtlMs(t){let r=F(t)==="openclaw"?N(this.config.openClawSessionIdleTtlMs,Xn):N(this.config.sessionIdleTtlMs,qn);return N(t?.sessionIdleTtlMs??t?.idleTtlMs,r)}targetMaxSessions(t){let r=F(t)==="openclaw"?N(this.config.openClawMaxSessions,Vn):N(this.config.maxSessionsPerTarget,Wn);return N(t?.maxSessions,r)}targetReleaseAfterPrompt(t){let n=F(t);return er(t?.releaseAfterPrompt??t?.disposeAfterPrompt,n==="openclaw")}startSessionCleanup(){let t=N(this.config.sessionCleanupIntervalMs,Kn);t<=0||(this.cleanupTimer=setInterval(()=>this.cleanupExpiredSessions(),t),this.cleanupTimer.unref?.())}sessionCountForTarget(t){let n=0;for(let r of this.sessions.values())r.targetCode===t&&(n+=1);return n}idleTargetSessions(t){return[...this.sessions.entries()].filter(([,n])=>n.targetCode===t&&!n.busy).sort((n,r)=>(n[1].lastUsedAtMs||0)-(r[1].lastUsedAtMs||0))}closeSession(t,n="session_closed"){let r=this.sessions.get(t);if(!r)return!1;try{r.runtime?.stop?.(n)}catch(s){f("warn","runtime-bridge","runtime session stop failed",{sessionId:r.sessionId,runtimeSessionId:r.runtimeSessionId,targetCode:r.targetCode,runtimeKind:r.runtimeKind,error:String(s)})}return this.sessions.delete(t),this.runtimeSessionIndex.delete(`${r.agentId}:${r.runtimeSessionId}`),f("info","runtime-bridge","runtime session closed",{sessionId:r.sessionId,runtimeSessionId:r.runtimeSessionId,targetCode:r.targetCode,runtimeKind:r.runtimeKind,reason:n}),!0}closeAllSessions(t="bridge_shutdown"){for(let n of[...this.sessions.keys()])this.closeSession(n,t)}stop(t="bridge_stop"){this.cleanupTimer&&clearInterval(this.cleanupTimer),this.cleanupTimer=null,this.closeAllSessions(t)}cleanupExpiredSessions(t=Date.now()){for(let[n,r]of[...this.sessions.entries()])r.busy||t-(r.lastUsedAtMs||r.createdAtMs||t)>r.idleTtlMs&&this.closeSession(n,"idle_timeout")}reserveTargetSlot(t,n){let r=this.targetMaxSessions(n);for(;this.sessionCountForTarget(t)>=r;){let s=this.idleTargetSessions(t);if(!s.length){let i=new Error(`runtime target session limit reached: ${t}`);throw i.code="RUNTIME_TARGET_SESSION_LIMIT",i}this.closeSession(s[0][0],"target_session_limit")}}async createAgent(t){let n=o(t.agentId);if(!n)throw Object.assign(new Error("agentId is required"),{status:400,code:"BAD_REQUEST"});let{code:r,target:s}=this.targetFor(t.targetCode||t.framework),i={agentId:n,targetCode:r,framework:o(t.framework||r),workspace:o(t.workspace),metadata:c(t.metadata)?t.metadata:{},createdAt:v(),runtimeKind:F(s)};return this.agents.set(n,i),{agent:i}}runtimeFor(t,n){let{target:r}=this.targetFor(t.targetCode),s=F(r),i={onPermissionRequest:a=>this.requestPermission(a)},u={sessionPromptTimeoutMs:this.config.sessionPromptTimeoutMs};return s==="stdio-acp"||s==="acp"?new D(t,r,i,u):s==="openclaw"?new Y(t,r,n,i,u):s==="cli"?new et(t,r,u):new K(t)}async prompt(t,n={}){let r=o(t.agentId),s=o(t.sessionId)||nt();if(!r)throw Object.assign(new Error("agentId is required"),{status:400,code:"BAD_REQUEST"});let i=this.agents.get(r)||(await this.createAgent({agentId:r,targetCode:t.targetCode,framework:t.framework,workspace:t.workspace,metadata:t.metadata})).agent,u=o(t.workspace);u&&u!==i.workspace&&(i.workspace=u);let a=`${r}:${s}`;this.cleanupExpiredSessions();let l=this.sessions.get(a);if(!l){let{code:m,target:T}=this.targetFor(i.targetCode);this.reserveTargetSlot(m,T);let x=this.runtimeFor(i,s),E=await x.sessionNew({cwd:i.workspace||process.cwd(),metadata:c(t.metadata)?t.metadata:{}}),A=Date.now();l={agentId:r,sessionId:s,runtime:x,targetCode:m,runtimeKind:F(T),runtimeSessionId:o(c(E)?E.sessionId:"")||s,idleTtlMs:this.targetIdleTtlMs(T),releaseAfterPrompt:this.targetReleaseAfterPrompt(T),createdAtMs:A,lastUsedAtMs:A,busy:!1,createdAt:v()},this.sessions.set(a,l),this.runtimeSessionIndex.set(`${r}:${l.runtimeSessionId}`,l)}if(l.busy){let m=new Error(`runtime session is already running: ${s}`);throw m.code="RUNTIME_SESSION_BUSY",m}l.busy=!0,l.lastUsedAtMs=Date.now();let d=[],p=m=>{let T=Qn(m,s,l);d.push(T),n.onUpdate?.(T)};try{let m=await l.runtime.sessionPrompt({sessionId:l.runtimeSessionId,prompt:Array.isArray(t.prompt)?t.prompt:[],metadata:c(t.metadata)?t.metadata:{}},p),T=fr(m,d);return{sessionId:s,runtimeSessionId:l.runtimeSessionId,result:T,updates:d}}finally{l.busy=!1,l.lastUsedAtMs=Date.now(),l.releaseAfterPrompt&&this.closeSession(a,"release_after_prompt")}}async cancel(t){let n=o(t.agentId),r=o(t.sessionId),s=`${n}:${r}`,i=this.sessions.get(s);return i?(await i.runtime.sessionCancel({sessionId:i.runtimeSessionId}),this.closeSession(s,"cancelled"),{cancelled:!0}):{cancelled:!1}}async dispatch(t,n={}){let r=o(t.agentId),s=o(t.taskId),i=o(t.executionId);if(!r||!s)throw Object.assign(new Error("agentId and taskId are required"),{status:400,code:"BAD_REQUEST"});let u=o(t.sessionId)||`dispatch-${i||s}`,a=o(t.instructions),l=sr(t),d=[{type:"text",text:["Task dispatch received.",`taskId: ${s}`,i?`executionId: ${i}`:"",a?`instructions: ${a}`:"",l?"orchaContext:":"",l,l?"Use orchaContext as the source of truth for upstream outputs, review reports, artifacts, and workflow metadata.":"","Return only the final task result. Do not include process notes, logs, or explanations. Orcha will wrap the result into its runtime protocol."].filter(Boolean).join(`
|
|
15
|
+
`)}];return this.prompt({...t,agentId:r,sessionId:u,prompt:d},n)}async requestPermission({agent:t,runtimeSessionId:n,request:r,emitUpdate:s}){let i=nt(),a=this.runtimeSessionIndex.get(`${t.agentId}:${n}`)?.sessionId||n||nt(),l={permissionId:i,agentId:t.agentId,sessionId:a,runtimeSessionId:n,request:c(r)?r:{},status:"pending",createdAt:v()};return s?.({sessionId:n,update:{sessionUpdate:"permission_request",permission:l}}),await new Promise(d=>{let p=h(r?.timeoutMs,this.config.permissionRequestTimeoutMs),m=setTimeout(()=>{this.pendingPermissions.delete(i),d({permissionId:i,outcome:"denied",response:{reason:"permission request timed out"}})},p);this.pendingPermissions.set(i,{timer:m,resolve:d,permission:l})})}async respondPermission(t){let n=o(t.permissionId),r=this.pendingPermissions.get(n),s=o(t.outcome||"approved")||"approved";return r?(clearTimeout(r.timer),this.pendingPermissions.delete(n),r.resolve({permissionId:n,outcome:s,response:c(t.response)?t.response:{},userId:o(t.userId),metadata:c(t.metadata)?t.metadata:{}}),{accepted:!0,permissionId:n,outcome:s}):{accepted:!1,permissionId:n,outcome:s}}health(){return{status:"ok",bridgeVersion:P,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 pr from"node:http";import mr from"node:https";import{randomBytes as pe}from"node:crypto";var st=1,Et=3,it=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,n){let r=this.listeners.get(t)||new Set;r.add(n),this.listeners.set(t,r)}emit(t,n={}){let r=this.listeners.get(t);if(r)for(let s of r)s(n)}connect(){let t=new URL(this.url),n=t.protocol==="wss:"?mr:pr,r=pe(16).toString("base64"),s=n.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":r,"Sec-WebSocket-Version":"13"}});s.on("upgrade",(i,u,a)=>{this.socket=u,this.readyState=st,u.on("data",l=>this.onData(l)),u.on("close",()=>this.onClose()),u.on("error",l=>{this.emit("error",{error:l,message:l.message,type:"error"}),this.onClose()}),a?.length&&this.onData(a),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!==st||this.socket.write(wt(1,Buffer.from(String(t),"utf8")))}close(){!this.socket||this.readyState===Et||(this.socket.write(wt(8,Buffer.alloc(0))),this.socket.end(),this.onClose())}onClose(){this.readyState!==Et&&(this.readyState=Et,this.emit("close"))}onData(t){for(this.buffer=Buffer.concat([this.buffer,t]);this.buffer.length>=2;){let n=this.buffer[0],r=this.buffer[1],s=n&15,i=(r&128)!==0,u=r&127,a=2;if(u===126){if(this.buffer.length<a+2)return;u=this.buffer.readUInt16BE(a),a+=2}else if(u===127){if(this.buffer.length<a+8)return;let p=this.buffer.readUInt32BE(a),m=this.buffer.readUInt32BE(a+4);u=p*2**32+m,a+=8}let l=a;if(i&&(a+=4),this.buffer.length<a+u)return;let d=this.buffer.subarray(a,a+u);if(i){let p=this.buffer.subarray(l,l+4);d=Buffer.from(d.map((m,T)=>m^p[T%4]))}this.buffer=this.buffer.subarray(a+u),s===1?this.emit("message",{data:d.toString("utf8")}):s===8?this.close():s===9&&this.socket?.write(wt(10,d))}}};function wt(e,t){let n=t.length,r=2;n>=126&&n<=65535?r+=2:n>65535&&(r+=8);let s=pe(4),i=Buffer.alloc(r+4+n);i[0]=128|e;let u=2;n<126?i[1]=128|n:n<=65535?(i[1]=254,i.writeUInt16BE(n,u),u+=2):(i[1]=255,i.writeUInt32BE(Math.floor(n/2**32),u),i.writeUInt32BE(n>>>0,u+4),u+=8),s.copy(i,u),u+=4;for(let a=0;a<n;a+=1)i[u+a]=t[a]^s[a%4];return i}function hr(e){let t=new URL(e);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 gr(e){return Object.entries(e||{}).map(([t,n])=>({targetCode:t,targetName:o(n?.name||n?.targetName||t),targetType:o(n?.type||"echo"),status:"available",metadata:c(n)?n:{}}))}var ot=class{constructor(t,n){this.config=t,this.bridge=n,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=hr(this.config.orchaUrl),n=new it(t);this.ws=n,n.addEventListener("open",()=>this.authenticate()),n.addEventListener("message",r=>this.handleMessage(r.data)),n.addEventListener("close",()=>this.scheduleReconnect("close")),n.addEventListener("error",r=>{f("warn","orcha-client","runtime node websocket error",{error:String(r?.message||r?.type||r)})})}authenticate(){this.send({type:"runtime_node.authenticate",token:this.config.nodeToken,nodeId:this.config.nodeId,nodeName:this.config.nodeName,version:P,protocolVersion:"orcha-runtime-node.v1",defaultTargetCode:this.config.defaultTargetCode,targets:gr(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 n;try{n=JSON.parse(String(t))}catch(r){f("warn","orcha-client","invalid Orcha websocket frame",{error:String(r)});return}if(c(n)){if(n.type==="runtime_node.authenticated"){this.connected=!0,f("info","orcha-client","runtime node authenticated",{nodeId:this.config.nodeId,connectionId:n.connectionId});return}if(n.type==="orcha.runtime.request"){await this.handleRequest(n);return}n.type==="runtime_node.ping"&&this.send({type:"runtime_node.pong",ts:new Date().toISOString()})}}async handleRequest(t){let n=o(t.id),r=o(t.method),s=c(t.params)?t.params:{};try{let i=await this.invoke(r,s,n);this.send({type:"orcha.runtime.response",id:n,ok:!0,result:i})}catch(i){this.send({type:"orcha.runtime.response",id:n,ok:!1,error:{code:i.code||"RUNTIME_NODE_ERROR",message:i.message||String(i)}})}}async invoke(t,n,r){if(t==="health")return this.bridge.health();if(t==="agents/create")return this.bridge.createAgent(n);if(t==="agents/dispatch")return this.bridge.dispatch(n,{onUpdate:s=>this.sendUpdate(r,s)});if(t==="sessions/prompt")return this.bridge.prompt(n,{onUpdate:s=>this.sendUpdate(r,s)});if(t==="sessions/cancel")return this.bridge.cancel(n);if(t==="permissions/respond")return this.bridge.respondPermission(n);throw Object.assign(new Error(`unsupported Orcha runtime method: ${t}`),{code:"METHOD_NOT_FOUND"})}sendUpdate(t,n){this.send({type:"orcha.runtime.event",requestId:t,eventType:"runtime.update",payload:n})}send(t){return!this.ws||this.ws.readyState!==st?!1:(this.ws.send(JSON.stringify(t)),!0)}};import{existsSync as _r,readFileSync as Tr}from"node:fs";import{resolve as me}from"node:path";var yr=/^[A-Za-z_][A-Za-z0-9_]*$/;function he(e=process.env,t=process.cwd()){let n=o(e.ORCHA_RUNTIME_ENV_FILE),r=n?me(t,n):me(t,".env");if(!_r(r))return n&&f("warn","config","runtime env file not found",{path:r}),{loaded:!1,path:r,keys:[]};let s=[],i=Tr(r,"utf8");for(let u of i.split(/\r?\n/)){let a=Ir(u);if(!a)continue;let[l,d]=a;Object.prototype.hasOwnProperty.call(e,l)||(e[l]=d,s.push(l))}return f("info","config","runtime env file loaded",{path:r,keyCount:s.length}),{loaded:!0,path:r,keys:s}}function ge(e=process.env){return{mode:o(e.ORCHA_RUNTIME_MODE||(e.ORCHA_RUNTIME_ORCHA_URL?"node":"server")),host:e.ORCHA_RUNTIME_BRIDGE_HOST||"127.0.0.1",port:h(e.ORCHA_RUNTIME_BRIDGE_PORT,5588),token:e.ORCHA_RUNTIME_BRIDGE_TOKEN||"",orchaUrl:o(e.ORCHA_RUNTIME_ORCHA_URL),nodeToken:e.ORCHA_RUNTIME_NODE_TOKEN||e.ORCHA_RUNTIME_BRIDGE_TOKEN||"",nodeId:o(e.ORCHA_RUNTIME_NODE_ID||e.HOSTNAME||"local-runtime-node"),nodeName:o(e.ORCHA_RUNTIME_NODE_NAME||e.ORCHA_RUNTIME_NODE_ID||e.HOSTNAME||"Local Runtime Node"),reconnectMs:h(e.ORCHA_RUNTIME_RECONNECT_MS,3e3),defaultTargetCode:e.ORCHA_RUNTIME_DEFAULT_TARGET||"echo",requestLimitBytes:h(e.ORCHA_RUNTIME_REQUEST_LIMIT_BYTES,1048576),sessionPromptTimeoutMs:h(e.ORCHA_RUNTIME_SESSION_PROMPT_TIMEOUT_MS,36e5),permissionRequestTimeoutMs:h(e.ORCHA_RUNTIME_PERMISSION_TIMEOUT_MS,3e5),sessionIdleTtlMs:h(e.ORCHA_RUNTIME_SESSION_IDLE_TTL_MS,6e5),sessionCleanupIntervalMs:h(e.ORCHA_RUNTIME_SESSION_CLEANUP_INTERVAL_MS,6e4),maxSessionsPerTarget:h(e.ORCHA_RUNTIME_MAX_SESSIONS_PER_TARGET,8),openClawSessionIdleTtlMs:h(e.ORCHA_RUNTIME_OPENCLAW_SESSION_IDLE_TTL_MS,6e4),openClawMaxSessions:h(e.ORCHA_RUNTIME_OPENCLAW_MAX_SESSIONS,1),targets:Sr(e.ORCHA_RUNTIME_TARGETS_JSON||"")}}function Sr(e){if(!o(e))return{};try{let t=JSON.parse(e);if(c(t))return t}catch(t){f("warn","config","invalid ORCHA_RUNTIME_TARGETS_JSON",{error:String(t)})}return{}}function Ir(e){let t=e.trim();if(!t||t.startsWith("#"))return null;let n=t.startsWith("export ")?t.slice(7).trimStart():t,r=n.indexOf("=");if(r<=0)return null;let s=n.slice(0,r).trim();if(!yr.test(s))return null;let i=Er(n.slice(r+1).trim());return[s,i]}function Er(e){if(!e)return"";let t=e[0];if((t==='"'||t==="'")&&e.endsWith(t)){let n=e.slice(1,-1);return t==='"'?wr(n):n}return Rr(e).trim()}function wr(e){return e.replaceAll("\\n",`
|
|
16
|
+
`).replaceAll("\\r","\r").replaceAll("\\t"," ").replaceAll('\\"','"').replaceAll("\\\\","\\")}function Rr(e){let t=!1,n=!1;for(let r=0;r<e.length;r+=1){let s=e[r],i=e[r-1];if(s==="'"&&!n)t=!t;else if(s==='"'&&!t&&i!=="\\")n=!n;else if(s==="#"&&!t&&!n&&/\s/.test(i||""))return e.slice(0,r)}return e}import{createServer as xr}from"node:http";function at(e,t,n){let r=JSON.stringify(n);e.writeHead(t,{"content-type":"application/json; charset=utf-8","content-length":Buffer.byteLength(r)}),e.end(r)}function k(e={}){return{ok:!0,...e}}function Rt(e,t,n){return{ok:!1,error:{code:e,message:t,...n===void 0?{}:{detail:n}}}}async function _e(e,t){let n=[],r=0;for await(let i of e){if(r+=i.length,r>t)throw Object.assign(new Error("request body too large"),{status:413,code:"REQUEST_TOO_LARGE"});n.push(i)}if(n.length===0)return{};let s=Buffer.concat(n).toString("utf8");if(!s.trim())return{};try{let i=JSON.parse(s);if(!c(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 Te(e,t){if(!t)return;if((e.headers.authorization||"")!==`Bearer ${t}`)throw Object.assign(new Error("runtime bridge token is invalid"),{status:401,code:"UNAUTHORIZED"})}function ye(e,t){let n={"GET /health":async()=>k(t.health()),"POST /agents/create":async r=>k(await t.createAgent(r)),"POST /agents/dispatch":async r=>k(await t.dispatch(r)),"POST /sessions/prompt":async r=>k(await t.prompt(r)),"POST /sessions/cancel":async r=>k(await t.cancel(r)),"POST /permissions/respond":async r=>k(await t.respondPermission(r))};return xr(async(r,s)=>{let i=new URL(r.url||"/",`http://${r.headers.host||`${e.host}:${e.port}`}`),u=`${r.method||"GET"} ${i.pathname}`,a=n[u];if(!a){at(s,404,Rt("NOT_FOUND",`No route for ${u}`));return}try{Te(r,e.token);let l=r.method==="GET"?{}:await _e(r,e.requestLimitBytes);at(s,200,await a(l))}catch(l){let d=l.status||500,p=l.code||"BRIDGE_INTERNAL";at(s,d,Rt(p,l.message||String(l)))}})}var kr=br(import.meta.url),Lr=".orcha-runtime-bridge.pid",Pr=".orcha-runtime-bridge.log",Dr=3,Fr=36e5,{command:$r,options:Ce}=zr(process.argv.slice(2));jr(Ce);he();var Hr=ge();await vr($r,Hr,Ce);async function vr(e,t,n){switch(e){case"run":case"foreground":Ie(t);return;case"start":if(n.foreground){Ie(t);return}we();return;case"reload":case"restart":await Re({quiet:!0}),we();return;case"stop":await Re();return;case"status":Br();return;case"help":case"--help":case"-h":Kr();return;default:throw new Error(`Unknown command: ${e}`)}}function Ie(e){Gr();let t=new rt(e);if(e.mode==="server"){let r=ye(e,t);Ee({bridge:t,server:r}),r.listen(e.port,e.host,()=>{f("info","runtime-bridge","Orcha runtime bridge HTTP server started",{host:e.host,port:e.port,targets:Object.keys(t.targets)})});return}if(!e.orchaUrl)throw new Error("ORCHA_RUNTIME_ORCHA_URL is required in runtime node mode");let n=new ot(e,t);Ee({bridge:t,client:n}),n.start(),f("info","runtime-bridge","Orcha runtime node started",{nodeId:e.nodeId,nodeName:e.nodeName,orchaUrl:e.orchaUrl,targets:Object.keys(t.targets)})}function Ee({bridge:e,client:t,server:n}){let r=!1,s=i=>{if(r)return;r=!0;let u=Number(e?.sessions?.size||0)>0;f("info","runtime-bridge","runtime bridge shutting down",{signal:i});try{t?.stop?.()}catch(a){f("warn","runtime-bridge","runtime client stop failed",{error:String(a)})}try{e?.stop?.(`process_${String(i||"shutdown").toLowerCase()}`)}catch(a){f("warn","runtime-bridge","runtime bridge stop failed",{error:String(a)})}try{n?.close?.()}catch(a){f("warn","runtime-bridge","runtime server close failed",{error:String(a)})}setTimeout(()=>process.exit(0),u?5500:200)};process.once("SIGTERM",()=>s("SIGTERM")),process.once("SIGINT",()=>s("SIGINT"))}function we(){let e=Ct(),t=Me(),n=Mt(e);if(n&&$(n)){console.log(JSON.stringify({status:"already_running",pid:n,pidFile:e,logFile:t}));return}n&&Ot(e),Ae(e),Ae(t),At(t);let r=Cr(t,"a"),s={...process.env,ORCHA_RUNTIME_PID_FILE:e,ORCHA_RUNTIME_LOG_FILE:t},i=Ar(process.execPath,[kr,"run"],{cwd:process.cwd(),detached:!0,env:s,stdio:["ignore",r,r]});i.unref(),Or(r),Ue(e,`${i.pid}
|
|
17
|
+
`),console.log(JSON.stringify({status:"started",pid:i.pid,pidFile:e,logFile:t}))}async function Re({quiet:e=!1}={}){let t=Ct(),n=Mt(t);if(!n){e||console.log(JSON.stringify({status:"not_running",pidFile:t}));return}if(!$(n)){Ot(t),e||console.log(JSON.stringify({status:"not_running",pid:n,pidFile:t}));return}process.kill(n,"SIGTERM"),!await xe(n,1e4)&&$(n)&&(process.kill(n,"SIGKILL"),await xe(n,3e3)),Ot(t),e||console.log(JSON.stringify({status:"stopped",pid:n,pidFile:t}))}function Br(){let e=Ct(),t=Me(),n=Mt(e),r=!!(n&&$(n));console.log(JSON.stringify({status:r?"running":"not_running",running:r,pid:r?n:null,pidFile:e,logFile:t}))}function zr(e){let t=[],n={};for(let s=0;s<e.length;s+=1){let i=e[s];i==="--daemon"?n.daemon=!0:i==="--foreground"?n.foreground=!0:i==="--env-file"?n.envFile=e[++s]:i==="--pid-file"?n.pidFile=e[++s]:i==="--log-file"?n.logFile=e[++s]:t.push(i)}return{command:t[0]||"run",options:n}}function jr(e){e.envFile&&(process.env.ORCHA_RUNTIME_ENV_FILE=e.envFile),e.pidFile&&(process.env.ORCHA_RUNTIME_PID_FILE=e.pidFile),e.logFile&&(process.env.ORCHA_RUNTIME_LOG_FILE=e.logFile)}function Ct(){return Ut(process.cwd(),process.env.ORCHA_RUNTIME_PID_FILE||Lr)}function Me(){return Ut(process.cwd(),process.env.ORCHA_RUNTIME_LOG_FILE||Pr)}function Gr(){let e=process.env.ORCHA_RUNTIME_LOG_FILE;if(!e)return;let t=Ne();if(t<=0)return;let n=Ut(process.cwd(),e);At(n,t);let r=qr();r<=0||setInterval(()=>At(n,t),r).unref()}function At(e,t=Ne()){if(t<=0||!Oe(e))return;let n=0,r="";try{if(n=Se(e).size,n<=0)return;r=xt(e,"utf8")}catch(d){f("warn","runtime-bridge","runtime log cleanup skipped",{logFile:e,error:String(d)});return}let s=Date.now()-t*24*60*60*1e3,i=r.split(/\r?\n/),u=[],a=0;for(let d of i)d&&(Jr(d,s)?u.push(d):a+=1);if(a===0)return;let l="";try{Se(e).size>n&&(l=xt(e,"utf8").slice(r.length));let p=[...u,...l.split(/\r?\n/).filter(Boolean)].join(`
|
|
18
|
+
`);Ue(e,p?`${p}
|
|
19
|
+
`:""),f("info","runtime-bridge","runtime log cleanup completed",{logFile:e,retentionDays:t,removed:a})}catch(d){f("warn","runtime-bridge","runtime log cleanup failed",{logFile:e,error:String(d)})}}function Jr(e,t){try{let n=JSON.parse(e);if(!n||typeof n!="object")return!0;let r=typeof n.ts=="string"?Date.parse(n.ts):Number.NaN;return!Number.isFinite(r)||r>=t}catch{return!0}}function Ne(){return be(process.env.ORCHA_RUNTIME_LOG_RETENTION_DAYS,Dr)}function qr(){return be(process.env.ORCHA_RUNTIME_LOG_CLEANUP_INTERVAL_MS,Fr)}function be(e,t){let n=Number.parseInt(String(e??""),10);return Number.isFinite(n)&&n>=0?n:t}function Mt(e){if(!Oe(e))return null;let t=Number.parseInt(xt(e,"utf8").trim(),10);return Number.isInteger(t)&&t>0?t:null}function $(e){try{return process.kill(e,0),!0}catch(t){return t?.code==="EPERM"}}async function xe(e,t){let n=Date.now();for(;Date.now()-n<t;){if(!$(e))return!0;await new Promise(r=>setTimeout(r,100))}return!$(e)}function Ae(e){Ur(Nr(e),{recursive:!0})}function Ot(e){try{Mr(e,{force:!0})}catch{}}function Kr(){console.log(`Usage: orcha-runtime-bridge [command] [options]
|
|
18
20
|
|
|
19
21
|
Commands:
|
|
20
22
|
run, foreground Run in the foreground. This is the default.
|