@orcha-ai/runtime-bridge 0.1.28 → 0.1.30

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
@@ -9,6 +9,7 @@ ORCHA_RUNTIME_NODE_NAME=Workstation A
9
9
  ORCHA_RUNTIME_DEFAULT_TARGET=codex
10
10
  ORCHA_RUNTIME_RECONNECT_MS=3000
11
11
  ORCHA_RUNTIME_CONNECT_TIMEOUT_MS=10000
12
+ ORCHA_RUNTIME_HEARTBEAT_INTERVAL_MS=15000
12
13
  ORCHA_RUNTIME_SESSION_PROMPT_TIMEOUT_MS=3600000
13
14
  ORCHA_RUNTIME_PERMISSION_TIMEOUT_MS=300000
14
15
  ORCHA_RUNTIME_SESSION_IDLE_TTL_MS=600000
@@ -21,5 +22,29 @@ ORCHA_RUNTIME_LOG_FILE=.orcha-runtime-bridge.log
21
22
  ORCHA_RUNTIME_LOG_RETENTION_DAYS=3
22
23
  ORCHA_RUNTIME_LOG_CLEANUP_INTERVAL_MS=3600000
23
24
 
25
+ # Runtime Node production safety. Node mode requires the bundled Linux
26
+ # Bubblewrap broker and never falls back to spawning on the host.
27
+ ORCHA_RUNTIME_SANDBOX_REQUIRED=true
28
+ # Optional override; the bundled orcha-runtime-sandbox-broker is used by default.
29
+ # ORCHA_RUNTIME_SANDBOX_BROKER_COMMAND=/usr/local/bin/orcha-runtime-sandbox-broker
30
+ # ORCHA_RUNTIME_SANDBOX_BROKER_ARGUMENTS='[]'
31
+ ORCHA_RUNTIME_SANDBOX_PROBE_TIMEOUT_MS=10000
32
+ ORCHA_RUNTIME_SANDBOX_TEMP_ROOT=/var/lib/orcha/runtime-sandboxes
33
+ ORCHA_RUNTIME_TRUSTED_WORKSPACE_ROOTS='["/workspaces"]'
34
+ # Add only immutable runtime installations required by a target (for example
35
+ # an nvm Node installation); target toolchainRoots must remain within these.
36
+ ORCHA_RUNTIME_TRUSTED_TOOLCHAIN_ROOTS='["/opt/orcha-runtime-tools"]'
37
+
38
+ # Required for the “workspace and network” permission mode. Use the same local
39
+ # Egress Proxy service/protocol as the cloud runtime.
40
+ ORCHA_RUNTIME_EGRESS_PROXY_REQUIRED=true
41
+ ORCHA_RUNTIME_EGRESS_PROXY_SOCKET=/run/orcha-egress/egress.sock
42
+ ORCHA_RUNTIME_EGRESS_PROXY_TOKEN=replace-with-local-egress-service-token
43
+ ORCHA_RUNTIME_EGRESS_GRANT_MAX_TTL_MS=900000
44
+ # The bundled `orcha-runtime-egress-proxy` accepts the same runtime-prefixed
45
+ # socket/token variables above. Optional daemon-specific limits:
46
+ ORCHA_EGRESS_PROXY_MAX_GRANT_TTL_MS=900000
47
+ ORCHA_EGRESS_PROXY_MAX_CONNECTIONS=128
48
+
24
49
  # Target examples. Keep this JSON on one line.
25
- 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"}}'
50
+ ORCHA_RUNTIME_TARGETS_JSON='{"codex":{"type":"cli","command":"/opt/orcha-runtime-tools/bin/codex","toolchainRoots":["/opt/orcha-runtime-tools"],"args":["exec","--json"],"workspace":"/workspaces/project-a","promptMode":"stdin","outputMode":"json-lines","captureLastMessage":true},"openclaw":{"type":"openclaw","command":"/opt/orcha-runtime-tools/bin/openclaw","toolchainRoots":["/opt/orcha-runtime-tools"],"workspace":"/workspaces/project-a","maxSessions":1,"releaseAfterPrompt":true,"sessionIdleTtlMs":60000},"claude":{"type":"cli","command":"/opt/orcha-runtime-tools/bin/claude","toolchainRoots":["/opt/orcha-runtime-tools"],"args":["-p","--output-format","json","--no-session-persistence"],"workspace":"/workspaces/project-a","promptMode":"args","outputMode":"json-lines"}}'
package/README.md CHANGED
@@ -11,12 +11,29 @@ runtime permission requests, and process lifecycle are implemented under
11
11
  In production the Runtime Node actively connects to Orcha over WebSocket. The
12
12
  computer running Codex/OpenClaw/Claude does not need to expose an inbound port.
13
13
 
14
+ Runtime Node mode is fail-closed: before registering targets as available it
15
+ runs the bundled Linux Bubblewrap broker probe. Every prompt/dispatch is bound
16
+ to a control-plane `runId` and frozen sandbox policy, and the actual Runtime
17
+ process is started by the broker inside an empty-root namespace. Missing
18
+ Bubblewrap, `prlimit`, Egress Proxy, trusted workspace, or a failed escape probe
19
+ keeps the node visible for diagnostics but unavailable for dispatch. It never
20
+ falls back to spawning Codex/OpenClaw/Claude directly on the host.
21
+
22
+ The broker does not mount `/usr/local` or other operator directories by
23
+ default. Install runtime CLIs under a dedicated immutable directory, list it in
24
+ `ORCHA_RUNTIME_TRUSTED_TOOLCHAIN_ROOTS`, and repeat it in each target's
25
+ `toolchainRoots`. This keeps the executable surface explicit and avoids
26
+ exposing unrelated host installations or credentials.
27
+
14
28
  ## Install
15
29
 
16
30
  ```bash
17
31
  npm install -g @orcha-ai/runtime-bridge
18
32
  ```
19
33
 
34
+ Production Runtime Nodes require Node.js 22.19 or newer and Linux with
35
+ Bubblewrap, `prlimit`, `ip`, and `socat` installed.
36
+
20
37
  Run it with:
21
38
 
22
39
  ```bash
@@ -113,19 +130,40 @@ and receives Orcha RPC frames for:
113
130
  - `agents/create`
114
131
  - `agents/dispatch`
115
132
  - `sessions/prompt`
133
+ - `sessions/policy`
116
134
  - `sessions/cancel`
117
135
  - `permissions/respond`
118
136
 
119
137
  Runtime targets are configured with `ORCHA_RUNTIME_TARGETS_JSON`.
120
138
 
139
+ Start the bundled Egress Proxy as a separate supervised process before the
140
+ Runtime Bridge. In production use separate protected environment files: the
141
+ proxy file contains only its socket, token, and limits; the bridge file contains
142
+ the Node identity plus the matching proxy socket/token. The proxy accepts
143
+ `ORCHA_RUNTIME_EGRESS_PROXY_SOCKET` and `ORCHA_RUNTIME_EGRESS_PROXY_TOKEN`, and
144
+ listens only on that Unix Socket.
145
+
146
+ ```bash
147
+ orcha-runtime-egress-proxy --env-file /etc/orcha/runtime-egress.env
148
+ orcha-runtime-bridge start --env-file /etc/orcha/runtime-node.env
149
+ ```
150
+
151
+ The proxy must run under its own OS account in production. The bridge uses its
152
+ admin token only to create and revoke short-lived Run-bound grants; sandboxed
153
+ commands receive only the individual grant credential. A node whose proxy or
154
+ escape probe is unavailable remains registered for diagnostics but cannot
155
+ receive work.
156
+
121
157
  ```json
122
158
  {
123
159
  "codex": {
124
160
  "type": "cli",
125
- "command": "codex",
161
+ "command": "/opt/orcha-runtime-tools/bin/codex",
162
+ "toolchainRoots": ["/opt/orcha-runtime-tools"],
126
163
  "args": ["exec", "--json"],
127
164
  "promptMode": "stdin",
128
- "outputMode": "json-lines"
165
+ "outputMode": "json-lines",
166
+ "workspace": "/workspaces/project-a"
129
167
  },
130
168
  "openclaw": {
131
169
  "type": "openclaw",
@@ -144,6 +182,37 @@ Runtime targets are configured with `ORCHA_RUNTIME_TARGETS_JSON`.
144
182
  }
145
183
  ```
146
184
 
185
+ In production every target must configure an absolute `workspace`/`cwd` chosen
186
+ by the operator. Request payloads and model output cannot choose a host path.
187
+ The path must be inside `ORCHA_RUNTIME_TRUSTED_WORKSPACE_ROOTS`. If a runtime
188
+ binary is installed outside the broker's read-only system toolchain, the target
189
+ may list `toolchainRoots`, but each root must also be inside the operator-owned
190
+ `ORCHA_RUNTIME_TRUSTED_TOOLCHAIN_ROOTS` list.
191
+
192
+ The bundled broker currently provides the production backend on Linux. macOS
193
+ and Windows nodes remain non-dispatchable until an equivalent VM-backed broker
194
+ is configured; client scheduling must route those tasks to a secure cloud node
195
+ or report local execution unavailable. Node-only `cwd` checks or child-process
196
+ environment filtering are not treated as a sandbox.
197
+
198
+ Minimum production configuration:
199
+
200
+ ```bash
201
+ ORCHA_RUNTIME_SANDBOX_REQUIRED=true
202
+ ORCHA_RUNTIME_SANDBOX_TEMP_ROOT=/var/lib/orcha/runtime-sandboxes
203
+ ORCHA_RUNTIME_TRUSTED_WORKSPACE_ROOTS='["/workspaces"]'
204
+ ORCHA_RUNTIME_EGRESS_PROXY_REQUIRED=true
205
+ ORCHA_RUNTIME_EGRESS_PROXY_SOCKET=/run/orcha-egress/egress.sock
206
+ ORCHA_RUNTIME_EGRESS_PROXY_TOKEN=replace-with-local-egress-service-token
207
+ ```
208
+
209
+ The Egress Proxy is mandatory at node startup so all three permission modes can
210
+ be honored. `read_only` and `workspace_write` runs have no network route;
211
+ `workspace_network` receives only a short-lived grant to the local Egress Proxy,
212
+ which blocks localhost, private networks, metadata endpoints, unsafe ports, and
213
+ DNS rebinding. Policy downgrades terminate the current process tree and revoke
214
+ the grant before the next launch.
215
+
147
216
  If a request references a missing target, the bridge returns
148
217
  `RUNTIME_TARGET_NOT_FOUND`. The built-in `echo` adapter is available only when
149
218
  you explicitly configure a target with `"type": "echo"`.
@@ -1,23 +1,24 @@
1
1
  #!/usr/bin/env node
2
- import{spawn as vs}from"node:child_process";import{closeSync as Bs,existsSync as mn,mkdirSync as Ks,openSync as zs,readFileSync as Wt,rmSync as js,statSync as an,writeFileSync as hn}from"node:fs";import{dirname as Gs,resolve as Yt}from"node:path";import{fileURLToPath as qs}from"node:url";import{randomUUID as mt}from"node:crypto";var K="0.1.28";function W(){return new Date().toISOString()}function w(e,t=2){return String(e).padStart(t,"0")}function ie(e){let t=e>=0?"+":"-",n=Math.abs(e);return`${t}${w(Math.floor(n/60))}:${w(n%60)}`}function En(e){let t=-e.getTimezoneOffset();return[`${e.getFullYear()}-${w(e.getMonth()+1)}-${w(e.getDate())}`,`T${w(e.getHours())}:${w(e.getMinutes())}:${w(e.getSeconds())}.${w(e.getMilliseconds(),3)}`,ie(t)].join("")}function In(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 xn(e,t){let n=In(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}-${w(n.month)}-${w(n.day)}`,`T${w(n.hour)}:${w(n.minute)}:${w(n.second)}.${w(e.getMilliseconds(),3)}`,ie(s)].join("")}function On(e=new Date){let t=a(process.env.ORCHA_RUNTIME_LOG_TIMEZONE||process.env.TZ||"Asia/Shanghai");try{return xn(e,t)}catch{return En(e)}}function c(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function a(e){return String(e??"").trim()}function T(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 Cn="[redacted]",se=/(authorization|api[_-]?key|credential|password|secret|token)/i;function J(e,t=new WeakSet){if(e==null)return e;if(typeof e=="bigint")return e.toString();if(typeof e!="object")return e;if(e instanceof Date)return e.toISOString();if(e instanceof Error){if(t.has(e))return"[circular]";t.add(e);let s={name:e.name,message:e.message};e.stack&&(s.stack=e.stack);for(let i of Object.keys(e))s[i]=J(e[i],t);return t.delete(e),s}if(t.has(e))return"[circular]";if(t.add(e),Array.isArray(e)){let s=e.map(i=>J(i,t));return t.delete(e),s}let n={},r=se.test(a(e.name||e.key));for(let[s,i]of Object.entries(e))n[s]=se.test(s)||r&&s.toLowerCase()==="value"?Cn:J(i,t);return t.delete(e),n}function oe(e,t=4e3){let n=JSON.stringify(J(e))??String(e);return!Number.isFinite(t)||n.length<=t?n:`${n.slice(0,t)}...`}function p(e,t,n,r={}){let s={ts:On(),level:e,module:t,msg:n,...c(r)?J(r):{}};console.error(JSON.stringify(s))}function nt(e){return Array.isArray(e)?e.map(t=>c(t)?t.type==="text"?a(t.text):t.type==="file"?a(t.uri):t.type==="image"?a(t.uri):"":"").filter(Boolean).join(`
3
- `):""}var rt=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=nt(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 An}from"node:child_process";var V="2.0",Nn=3e4;function Mn(e){return{code:Number.isInteger(e?.code)?e.code:-32e3,message:a(e?.message)||String(e),data:c(e?.data)?e.data:void 0}}function Un(e){if(!c(e))return new Error(String(e||"runtime error"));let t=a(e.message)||"runtime error",n="data"in e?oe(e.data,4e3):"",r=new Error(n?`${t}; data=${n}`:t);return r.rpcCode=e.code,r.data=e.data,r}function bn(e){return c(e)&&"id"in e&&!("method"in e)}function kn(e){return c(e)&&typeof e.method=="string"&&"id"in e}function Ln(e){return c(e)&&typeof e.method=="string"&&!("id"in e)}var st=class{constructor({command:t,args:n=[],cwd:r,env:s,label:i,framing:o="line",detached:u=!0}){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=o==="content-length"?"content-length":"line",this.detached=u!==!1,this.child=null,this.exited=!1,this.exitCode=null,this.exitSignal=null,this.stopPromise=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.exited||(this.exited=!1,this.exitCode=null,this.exitSignal=null,this.child=An(this.command,this.args,{cwd:this.cwd,env:this.env,stdio:["pipe","pipe","pipe"],detached:this.detached}),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&&p("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
2
+ import{spawn as No}from"node:child_process";import{closeSync as bo,existsSync as mn,mkdirSync as Mo,openSync as Uo,readFileSync as ke,rmSync as Po,statSync as an,writeFileSync as hn}from"node:fs";import{dirname as ko,resolve as ve}from"node:path";import{fileURLToPath as Lo}from"node:url";import{createHash as bi,randomUUID as kt}from"node:crypto";var Y="0.1.30";function ot(){return new Date().toISOString()}function M(e,t=2){return String(e).padStart(t,"0")}function Ke(e){let t=e>=0?"+":"-",r=Math.abs(e);return`${t}${M(Math.floor(r/60))}:${M(r%60)}`}function Sn(e){let t=-e.getTimezoneOffset();return[`${e.getFullYear()}-${M(e.getMonth()+1)}-${M(e.getDate())}`,`T${M(e.getHours())}:${M(e.getMinutes())}:${M(e.getSeconds())}.${M(e.getMilliseconds(),3)}`,Ke(t)].join("")}function wn(e,t){let r=new Intl.DateTimeFormat("en-US",{timeZone:t,hourCycle:"h23",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}),n={};for(let s of r.formatToParts(e))s.type!=="literal"&&(n[s.type]=Number(s.value));return n}function In(e,t){let r=wn(e,t),n=Date.UTC(r.year,r.month-1,r.day,r.hour,r.minute,r.second,e.getMilliseconds()),s=Math.round((n-e.getTime())/6e4);return[`${r.year}-${M(r.month)}-${M(r.day)}`,`T${M(r.hour)}:${M(r.minute)}:${M(r.second)}.${M(e.getMilliseconds(),3)}`,Ke(s)].join("")}function On(e=new Date){let t=a(process.env.ORCHA_RUNTIME_LOG_TIMEZONE||process.env.TZ||"Asia/Shanghai");try{return In(e,t)}catch{return Sn(e)}}function u(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function a(e){return String(e??"").trim()}function T(e,t){let r=Number.parseInt(String(e??""),10);return Number.isFinite(r)?r:t}function C(e){return Array.isArray(e)?e.map(String):[]}var xn="[redacted]",Ge=/(authorization|api[_-]?key|credential|password|secret|token)/i;function G(e,t=new WeakSet){if(e==null)return e;if(typeof e=="bigint")return e.toString();if(typeof e!="object")return e;if(e instanceof Date)return e.toISOString();if(e instanceof Error){if(t.has(e))return"[circular]";t.add(e);let s={name:e.name,message:e.message};e.stack&&(s.stack=e.stack);for(let i of Object.keys(e))s[i]=G(e[i],t);return t.delete(e),s}if(t.has(e))return"[circular]";if(t.add(e),Array.isArray(e)){let s=e.map(i=>G(i,t));return t.delete(e),s}let r={},n=Ge.test(a(e.name||e.key));for(let[s,i]of Object.entries(e))r[s]=Ge.test(s)||n&&s.toLowerCase()==="value"?xn:G(i,t);return t.delete(e),r}function Ve(e,t=4e3){let r=JSON.stringify(G(e))??String(e);return!Number.isFinite(t)||r.length<=t?r:`${r.slice(0,t)}...`}function h(e,t,r,n={}){let s={ts:On(),level:e,module:t,msg:r,...u(n)?G(n):{}};console.error(JSON.stringify(s))}function Tt(e){return Array.isArray(e)?e.map(t=>u(t)?t.type==="text"?a(t.text):t.type==="file"?a(t.uri):t.type==="image"?a(t.uri):"":"").filter(Boolean).join(`
3
+ `):""}var yt=class{constructor(t){this.agent=t,this.sessionCounter=0}async sessionNew(){return this.sessionCounter+=1,{sessionId:`echo-${this.agent.agentId}-${this.sessionCounter}`}}async sessionPrompt(t,r){let n=Tt(t.prompt);return r({sessionId:t.sessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:n?`Echo runtime received: ${n}`:"Echo runtime received an empty prompt."}}}),{stopReason:"end_turn"}}async sessionCancel(){return{ok:!0}}};import{spawn as An}from"node:child_process";var at="2.0",Cn=3e4;function Nn(e){return{code:Number.isInteger(e?.code)?e.code:-32e3,message:a(e?.message)||String(e),data:u(e?.data)?e.data:void 0}}function bn(e){if(!u(e))return new Error(String(e||"runtime error"));let t=a(e.message)||"runtime error",r="data"in e?Ve(e.data,4e3):"",n=new Error(r?`${t}; data=${r}`:t);return n.rpcCode=e.code,n.data=e.data,n}function Mn(e){return u(e)&&"id"in e&&!("method"in e)}function Un(e){return u(e)&&typeof e.method=="string"&&"id"in e}function Pn(e){return u(e)&&typeof e.method=="string"&&!("id"in e)}var Rt=class{constructor({command:t,args:r=[],cwd:n,env:s,label:i,framing:o="line",detached:c=!0}){this.command=t,this.args=Array.isArray(r)?r.map(String):[],this.cwd=n||process.cwd(),this.env=u(s)?{...s}:{...process.env},this.label=i||t,this.framing=o==="content-length"?"content-length":"line",this.detached=c!==!1,this.child=null,this.exited=!1,this.exitCode=null,this.exitSignal=null,this.stopPromise=null,this.lineBuffer="",this.headerBuffer=Buffer.alloc(0),this.seq=0,this.pending=new Map,this.notificationHandlers=new Map,this.requestHandlers=new Map,this.exitHandlers=new Set}async start({initialize:t=!0,initializeParams:r={}}={}){this.child&&!this.exited||(this.exited=!1,this.exitCode=null,this.exitSignal=null,this.child=An(this.command,this.args,{cwd:this.cwd,env:this.env,stdio:["pipe","pipe","pipe"],detached:this.detached}),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:{},...r}).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 r=this.lineBuffer.split(/\r?\n/);this.lineBuffer=r.pop()||"";for(let n of r){let s=n.trim();s&&this.dispatchRaw(s)}}onContentLengthData(t){for(this.headerBuffer=Buffer.concat([this.headerBuffer,t]);this.headerBuffer.length>0;){let r=this.headerBuffer.indexOf(`\r
4
4
  \r
5
- `);if(n<0)return;let s=this.headerBuffer.subarray(0,n).toString("utf8").match(/content-length:\s*(\d+)/i);if(!s){p("warn","runtime.protocol","missing Content-Length header",{target:this.label}),this.headerBuffer=Buffer.alloc(0);return}let i=Number.parseInt(s[1],10),o=n+4,u=o+i;if(this.headerBuffer.length<u)return;let l=this.headerBuffer.subarray(o,u).toString("utf8");this.headerBuffer=this.headerBuffer.subarray(u),this.dispatchRaw(l)}}dispatchRaw(t){let n;try{n=JSON.parse(t)}catch(r){p("warn","runtime.protocol","invalid JSON frame",{target:this.label,error:String(r)});return}this.dispatch(n)}dispatch(t){if(bn(t)){this.resolveResponse(t);return}if(kn(t)){this.handleRequest(t);return}Ln(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?(p("warn","runtime.protocol","runtime rpc error",{target:this.label,method:r.method,requestId:n,error:t.error}),r.reject(Un(t.error))):r.resolve(t.result))}async handleRequest(t){let n=this.requestHandlers.get(t.method);if(!n){this.writeFrame({jsonrpc:V,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:V,id:t.id,result:r??{}})}catch(r){this.writeFrame({jsonrpc:V,id:t.id,error:Mn(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=Nn){if(!this.child||!this.child.stdin||this.exited)return Promise.reject(new Error("runtime process is not running"));let s=`${t}_${++this.seq}`,i={jsonrpc:V,id:s,method:t,params:n};return new Promise((o,u)=>{let l=setTimeout(()=>{this.pending.delete(s),u(new Error(`${t} timed out after ${r}ms`))},r);this.pending.set(s,{resolve:o,reject:u,timer:l,method:t}),this.writeFrame(i,d=>{d&&(clearTimeout(l),this.pending.delete(s),u(d))})})}notify(t,n={}){this.writeFrame({jsonrpc:V,method:t,params:n})}writeFrame(t,n){if(!this.child?.stdin||this.exited){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
5
+ `);if(r<0)return;let s=this.headerBuffer.subarray(0,r).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),o=r+4,c=o+i;if(this.headerBuffer.length<c)return;let l=this.headerBuffer.subarray(o,c).toString("utf8");this.headerBuffer=this.headerBuffer.subarray(c),this.dispatchRaw(l)}}dispatchRaw(t){let r;try{r=JSON.parse(t)}catch(n){h("warn","runtime.protocol","invalid JSON frame",{target:this.label,error:String(n)});return}this.dispatch(r)}dispatch(t){if(Mn(t)){this.resolveResponse(t);return}if(Un(t)){this.handleRequest(t);return}Pn(t)&&this.handleNotification(t)}resolveResponse(t){let r=String(t.id),n=this.pending.get(r);n&&(clearTimeout(n.timer),this.pending.delete(r),t.error?(h("warn","runtime.protocol","runtime rpc error",{target:this.label,method:n.method,requestId:r,error:t.error}),n.reject(bn(t.error))):n.resolve(t.result))}async handleRequest(t){let r=this.requestHandlers.get(t.method);if(!r){this.writeFrame({jsonrpc:at,id:t.id,error:{code:-32601,message:`method not found: ${t.method}`}});return}try{let n=await r(u(t.params)?t.params:{},t);this.writeFrame({jsonrpc:at,id:t.id,result:n??{}})}catch(n){this.writeFrame({jsonrpc:at,id:t.id,error:Nn(n)})}}handleNotification(t){let r=this.notificationHandlers.get(t.method);if(r)for(let n of r)n(u(t.params)?t.params:{},t)}call(t,r={},n=Cn){if(!this.child||!this.child.stdin||this.exited)return Promise.reject(new Error("runtime process is not running"));let s=`${t}_${++this.seq}`,i={jsonrpc:at,id:s,method:t,params:r};return new Promise((o,c)=>{let l=setTimeout(()=>{this.pending.delete(s),c(new Error(`${t} timed out after ${n}ms`))},n);this.pending.set(s,{resolve:o,reject:c,timer:l,method:t}),this.writeFrame(i,d=>{d&&(clearTimeout(l),this.pending.delete(s),c(d))})})}notify(t,r={}){this.writeFrame({jsonrpc:at,method:t,params:r})}writeFrame(t,r){if(!this.child?.stdin||this.exited){r?.(new Error("runtime process is not running"));return}let n=JSON.stringify(t),s=this.framing==="content-length"?`Content-Length: ${Buffer.byteLength(n,"utf8")}\r
6
6
  \r
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.exited=!0,this.exitCode=t,this.exitSignal=n,this.rejectAll(new Error(`runtime exited before response (${t}/${n})`));for(let r of this.exitHandlers)r(t,n)}async waitForExit(t=5e3){return!this.child||this.exited?!0:await new Promise(n=>{let r=setTimeout(()=>{s(),n(!1)},t);r.unref?.();let s=()=>{clearTimeout(r),this.exitHandlers.delete(i)},i=()=>{s(),n(!0)};this.exitHandlers.add(i),this.exited&&i()})}signal(t){if(!this.child||this.exited)return!1;let n=this.child.pid;if(!n)return!1;try{return this.detached&&process.platform!=="win32"?process.kill(-n,t):this.child.kill(t),!0}catch(r){if(r?.code==="ESRCH")return this.exited=!0,!1;try{return this.child.kill(t),!0}catch(s){return s?.code!=="ESRCH"&&p("warn","runtime","runtime signal failed",{target:this.label,pid:n,signal:t,error:String(s)}),!1}}}async stop(t="stop",{termTimeoutMs:n=5e3,killTimeoutMs:r=2e3}={}){if(!(!this.child||this.exited)){if(this.stopPromise)return await this.stopPromise;this.stopPromise=(async()=>{if(!this.child||this.exited)return;let s=this.child.pid;p("info","runtime","stopping runtime",{target:this.label,reason:t,pid:s}),this.rejectAll(new Error(`runtime stopped: ${t}`)),this.signal("SIGTERM"),!await this.waitForExit(n)&&this.child&&!this.exited&&(p("warn","runtime","runtime did not exit after SIGTERM; force killing",{target:this.label,reason:t,pid:s}),this.signal("SIGKILL"),await this.waitForExit(r))})();try{await this.stopPromise}finally{this.stopPromise=null}}}};import{randomUUID as ue}from"node:crypto";import{existsSync as Pn,readFileSync as Dn,realpathSync as ae,statSync as Fn}from"node:fs";import{basename as le,extname as de,isAbsolute as $n,relative as Hn}from"node:path";var vn=25*1024*1024;function fe(e,t=""){let n=a(t);if(n)return n;let r=de(a(e)).toLowerCase();return r===".jpg"||r===".jpeg"?"image/jpeg":r===".webp"?"image/webp":r===".gif"?"image/gif":"image/png"}function pe(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 it(e){if(Array.isArray(e))return e.map(a).filter(Boolean);let t=a(e);return t?[t]:[]}function Bn(e,t){let n=Hn(t,e);return n===""||!!n&&!n.startsWith("..")&&!$n(n)}function Kn(e,t){let n=a(e);if(!n||!Pn(n))return"";try{let r=ae(n);for(let s of t)try{let i=ae(s);if(Bn(r,i))return r}catch{}}catch{return""}return""}function Et(e,t,n={}){let r=a(e);return!r||r.startsWith("data:")||/^https?:\/\//i.test(r)?r:zn(r,t,n)}function zn(e,t,n={}){let r=[...it(n.trustedFileRoots),...it(n.trustedFileRoot),...it(n.artifactRoots),...it(n.artifactRoot)],s=Kn(e,r);if(!s)return"";try{let i=Fn(s);return!i.isFile()||i.size<=0||i.size>vn?"":`data:${t};base64,${Dn(s).toString("base64")}`}catch{return""}}function S(...e){for(let t of e){let n=a(t);if(n)return n}return""}function jn(e,t,n,r){let s=n.toLowerCase();if(s==="image"||s==="picture")return!0;let i=S(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),o=de(i.split("?",1)[0].split("#",1)[0]).toLowerCase();return[".png",".jpg",".jpeg",".webp",".gif"].includes(o)}function xt(e,t={}){let{source:n="runtime_image_generation_event"}=t;if(!c(e))return null;let r=c(e.payload)?e.payload:{},s=a(e.type),i=a(r.type);if(!(s==="event_msg"&&i==="image_generation_end"||s==="response_item"&&i==="image_generation_call"))return null;let o=S(r.call_id,r.id),u=S(r.saved_path,r.savedPath),l=S(r.revised_prompt,r.revisedPrompt),d=fe(u,r.mimeType||r.mime_type),f=pe(r.result,d)||Et(u,d,t);if(!f)return null;let m=f.startsWith("data:")?f:"",g=u?le(u):`${o||ue()}.png`;return{artifactType:"image",type:"image",fieldKey:"image",title:g||"Generated image",summary:l||"Generated image",content:{prompt:l||void 0,dataUrl:m||void 0,imageUrl:f,previewUrl:f,fileUrl:f,mimeType:d},dataUrl:m||void 0,previewUrl:f,fileUrl:f,metadata:{source:n,eventType:i,callId:o||void 0,savedPath:u||void 0,filename:g,mimeType:d,revisedPrompt:l||void 0}}}function Gn(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 qn(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}:{},o=S(r.saved_path,r.savedPath,s.saved_path,s.savedPath,i.savedPath),u=S(r.mimeType,r.mime_type,s.mimeType,s.mime_type,i.mimeType),l=S(r.artifactType,r.artifact_type,r.type,r.kind,s.type,o?"image":"file"),d=jn(r,s,l,o),f=d?fe(o,u):u;if(d){let x=S(r.dataUrl,s.dataUrl),A=x.startsWith("data:")?x:"",b=S(r.imageUrl,r.previewUrl,r.fileUrl,r.downloadUrl,r.url,r.uri,s.imageUrl,s.previewUrl,s.fileUrl,s.downloadUrl,s.url,s.uri),_=pe(r.result??s.result,f)||A||Et(o,f,t)||Et(b,f,t);_&&(_.startsWith("data:")&&(s.dataUrl||=_),s.imageUrl||=_,s.previewUrl||=_,s.fileUrl||=_,f&&(s.mimeType||=f))}for(let[x,A]of[["prompt","prompt"],["previewUrl","previewUrl"],["fileUrl","fileUrl"],["downloadUrl","downloadUrl"],["imageUrl","imageUrl"],["dataUrl","dataUrl"],["url","url"],["uri","uri"],["mimeType","mimeType"],["mime_type","mimeType"]]){let b=r[x];b!=null&&b!==""&&!(A in s)&&(s[A]=b)}let m=S(r.fileUrl,r.downloadUrl,r.imageUrl,r.dataUrl,r.url,r.uri,s.fileUrl,s.downloadUrl,s.imageUrl,s.dataUrl,s.url,s.uri),g=S(r.previewUrl,r.imageUrl,r.dataUrl,r.url,r.fileUrl,r.uri,s.previewUrl,s.imageUrl,s.dataUrl,s.url,s.fileUrl,s.uri),h=S(r.dataUrl,s.dataUrl,m.startsWith("data:")?m:"",g.startsWith("data:")?g:""),y=S(r.filename,i.filename,o?le(o):""),U=S(r.fieldKey,r.field_key,s.fieldKey,i.fieldKey,d?"image":"artifact");return{...r,artifactType:l,type:r.type||l,fieldKey:U,title:S(r.title,y,"Runtime artifact"),summary:S(r.summary,s.prompt,r.title,y,"Runtime artifact"),content:s,dataUrl:h||void 0,fileUrl:m||void 0,previewUrl:g||void 0,metadata:{...i,source:S(i.source,n),savedPath:o||i.savedPath,filename:y||i.filename,mimeType:f||i.mimeType}}}function ot(e,t){if(!t||!e)return;let n=c(t.metadata)?t.metadata:{},r=S(n.savedPath,n.callId,t.previewUrl,t.fileUrl)||ue(),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 It(e,t,n={}){for(let r of Gn(e))ot(t,qn(r,n))}function Ot(e){if(!c(e)||!c(e.payload))return c(e)?e:{value:e};let t=a(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 ce(e,t,n){if(!c(e))return e;let r=c(e.event)?e.event:null;return r?(ot(t,xt(r,n)),{...e,event:Ot(r)}):e}function me(e,t,n={}){if(!c(e))return e;It(e,t,n);let r=ce(e,t,n),s=c(r.update)?ce(r.update,t,n):null;return s&&s!==r.update&&(r={...r,update:s}),r}function he(e,t,n={}){let r=c(e)?{...e}:{};It(r,t,n),It(c(r.output)?r.output:{},t,n);let s=[...t?.values?.()||[]];return s.length&&(r._artifacts=s),delete r.artifacts,r}var z=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=a(this.target.command);if(!t)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);this.proc=new st({command:t,args:I(this.target.args),cwd:a(this.target.cwd)||this.agent.workspace||process.cwd(),env:c(this.target.env)?this.target.env:{},label:`${this.agent.agentId}:${this.agent.targetCode}`,framing:a(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:K},...c(this.target.initializeParams)?this.target.initializeParams:{}}})}async sessionNew(t={}){return await this.ensureStarted(),this.proc.call("session/new",this.sessionNewParams(t))}sessionNewParams(t={}){let n=Array.isArray(t.mcpServers)?t.mcpServers:Array.isArray(this.target.mcpServers)?this.target.mcpServers:[];return{...t,mcpServers:n}}async sessionPrompt(t,n){await this.ensureStarted();let r=a(t.sessionId),s=new Map,i=this.artifactOptions(),o=this.proc.onNotification("session/update",l=>{let d=a(l.sessionId);(!d||d===r)&&n(me(l,s,i))}),u=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,u),this.permissionHandlers.set("*",u);try{let l=await this.proc.call("session/prompt",t,this.options.sessionPromptTimeoutMs);return he(l,s,i)}finally{o(),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=a(t.sessionId),r=this.permissionHandlers.get(n)||this.permissionHandlers.get("*");return r?r(t):{outcome:"denied",reason:"no active Orcha permission handler"}}artifactSource(){return a(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:[a(this.target.artifactRoot),a(this.target.artifactDir),a(this.target.runtimeArtifactRoot),a(t.ORCHA_RUNTIME_ARTIFACT_DIR),...I(this.target.trustedArtifactRoots),...I(this.target.trustedFileRoots),...I(this.target.artifactRoots),...I(this.target.artifactFileRoots)].filter(Boolean)}}async stop(t){await this.proc?.stop(t)}};function Jn(e){let t=c(e.metadata)?e.metadata:{};return a(t.agentCode)}function Wn(e,t){let n=Jn(e);return n?`agent:${n}:${t}`:`orcha-${t}`}var at=class extends z{constructor(t,n,r,s={},i={}){let o=a(r).replace(/[^A-Za-z0-9._-]+/g,"-")||"default",u=a(n.command)||"openclaw",l=Array.isArray(n.args)?n.args.map(String):[],d=l.length>0?l:["acp","--session",Wn(t,o)];super(t,{...n,command:u,args:d},s,i)}sessionNewParams(t={}){return{...t,mcpServers:[]}}};import{spawn as Vn}from"node:child_process";import{randomUUID as X}from"node:crypto";import{existsSync as Se,mkdirSync as Xn,readdirSync as Re,readFileSync as we,realpathSync as dt,rmSync as Yn,rmdirSync as Zn,statSync as Qn,unlinkSync as tr}from"node:fs";import{homedir as er,tmpdir as Ee}from"node:os";import{basename as Ie,dirname as nr,join as N,resolve as ge}from"node:path";var rr=36e5,sr=5e3,ir=2*60*1e3,or=2*60*1e3,ar=12,cr=1e3,ur=1500,ct=24*60*60*1e3,Y=new Set(["final_answer","final","complete","completed","done"]),lr=new Set(["function_call","function_call_output","custom_tool_call","custom_tool_call_output","local_shell_call","local_shell_call_output","mcp_tool_call","mcp_tool_call_output","web_search_call","image_generation_call","image_generation_end"]);function ut(e,t){try{e.kill(t)}catch{}}function C(e){if(typeof e=="string")return e;if(Array.isArray(e))return e.map(t=>C(t)).join("");if(!c(e))return"";for(let t of["text","delta","output_text","content","message","output"]){let n=C(e[t]);if(n)return n}return""}function xe(e){if(!c(e))return"";let t=c(e.payload)?e.payload:{};if(a(e.type)==="event_msg"){if(a(t.type)==="agent_message")return a(t.message);if(a(t.type)==="task_complete")return a(t.last_agent_message)}if(a(e.type)==="response_item"&&a(t.type)==="message"&&a(t.role)==="assistant")return C(t.content)||C(t.message);let n=C(e.delta)||C(e.text)||C(e.content);if(n)return n;let r=c(e.item)?e.item:{};return a(r.role)==="assistant"||a(r.type)==="message"?C(r.content)||C(r.text)||C(r.message):""}function Oe(e,t={}){return xt(e,{source:"codex_cli_image_generation",...t})}function Ce(e,t){ot(e.artifacts,t)}function Ae(e){let t=Ot(e);if(!De(e))return t;let n=c(e.payload)?e.payload:{};return{type:e.type,...e.timestamp?{timestamp:e.timestamp}:{},payload:Object.fromEntries(["type","name","namespace","title","call_id","callId","id","status","phase","stage"].filter(r=>n[r]!==void 0&&n[r]!==null&&n[r]!=="").map(r=>[r,n[r]]))}}function Mt(e){if(!c(e))return!1;let t=c(e.payload)?e.payload:{},n=a(e.type),r=a(t.type);if(n==="event_msg"&&r==="task_complete")return!0;let s=a(t.phase||t.status||t.stage).toLowerCase();return n==="event_msg"&&r==="agent_message"||n==="response_item"&&r==="message"&&a(t.role)==="assistant"?Y.has(s):!1}function _e(e){return c(e)?a(e.phase||e.status||e.stage).toLowerCase():""}function dr(e){if(!c(e)||Mt(e))return!1;let t=c(e.payload)?e.payload:{},n=a(e.type),r=a(t.type),s=_e(t);if(n==="event_msg"&&r==="agent_message"||n==="response_item"&&r==="message"&&a(t.role)==="assistant")return!!(s&&!Y.has(s));let i=c(e.item)?e.item:{},o=_e(i);return a(i.role)==="assistant"||a(i.type)==="message"?!!(o&&!Y.has(o)):!1}function fr(e,t,n){return n.captureLastMessage===!1||t.includes("--output-last-message")||t.includes("-o")?!1:n.captureLastMessage===!0?!0:Ie(e)==="codex"}function pr(e,t){return t.collectCodexTranscriptArtifacts===!1?!1:t.collectCodexTranscriptArtifacts===!0?!0:Ie(e)==="codex"}function Ne(e){return Math.max(20,T(e.codexTranscriptPollMs||e.transcriptPollMs,cr))}function mr(e){return Math.max(0,T(e.codexFinalOutputWaitMs||e.finalOutputWaitMs,ur))}function ft(e){if(typeof e=="boolean")return e;let t=a(e).toLowerCase();return["true","1","yes","y","on"].includes(t)?!0:["false","0","no","n","off"].includes(t)?!1:null}function Ut(e){let t=c(e?.metadata)?e.metadata:{};return c(t._runtimeBridge)?t._runtimeBridge:{}}function Ct(e){return a(Ut(e).promptKind).toLowerCase()}function hr(e,t){for(let n of[e.codexTranscriptStreaming,e.streamCodexTranscript]){let r=ft(n);if(r!=null)return r}return Ct(t)==="chat"}function gr(e,t){let n=Ut(e);for(let s of[n.emitThoughtChunks,n.streamThoughts]){let i=ft(s);if(i!=null)return i}let r=Ct(e);if(r&&r!=="chat")return!1;for(let s of[t.emitThoughtChunks,t.streamThoughts]){let i=ft(s);if(i!=null)return i}return Ct(e)==="chat"}function _r(e){let t=Ut(e);for(let n of[t.finalTextOnly,t.finalOutputOnly]){let r=ft(n);if(r!=null)return r}return null}function Tr(e,t){let n=_r(e);return n??(t.finalTextOnly===!0||t.finalOutputOnly===!0?!0:(t.finalTextOnly===!1||t.finalOutputOnly===!1,!1))}function yr(e,t){return!e.finalTextOnly||t}function Me(e,t,n,r,s=r){return!r||e.emittedTexts.has(s)?!1:(e.emittedTexts.add(s),n({sessionId:t,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:r}}}),!0)}function Ue(e,t,n,r){return!r||e.emittedThoughtTexts.has(r)?!1:(e.emittedThoughtTexts.add(r),n({sessionId:t,update:{sessionUpdate:"agent_thought_chunk",content:{type:"text",text:r}}}),!0)}function Sr(e,t,n,r=new Set){return{target:e,promptText:t,startedAtMs:n,baselinePaths:r,matchedPath:"",disabled:!1,processedLines:new Map}}function Rr(e,t){let n=c(e.env)?e.env:{},r=a(e.artifactRoot||e.artifactDir||e.runtimeArtifactRoot||n.ORCHA_RUNTIME_ARTIFACT_DIR)||N(Ee(),"orcha-runtime-artifacts"),s=a(t).replace(/[^A-Za-z0-9._-]+/g,"-").slice(0,80)||X(),i=N(r,s),o=N(i,X());return Xn(o,{recursive:!0}),{root:o,realRoot:dt(o),sessionRoot:i,realSessionRoot:dt(i)}}function be(e){return a(c(e)?e.root:e)}function Te(e){let t=be(e),n=a(c(e)?e.sessionRoot:nr(t)),r=a(c(e)?e.realSessionRoot:"");if(n)try{if(r&&dt(n)!==r)return;Zn(n)}catch{}}function wr(e,t={}){let n=be(e),r=a(c(e)?e.realRoot:"");if(n){try{if(r&&dt(n)!==r){p("warn","runtime.cli","runtime artifact directory cleanup skipped; path changed",{...t,artifactRoot:n});return}}catch{Te(e);return}try{Yn(n,{recursive:!0,force:!0})}catch(s){p("warn","runtime.cli","runtime artifact directory cleanup failed",{...t,artifactRoot:n,error:String(s?.message||s)});return}Te(e)}}function Er(e,t){return{trustedFileRoots:[t,...I(e.trustedArtifactRoots),...I(e.trustedFileRoots),...I(e.artifactRoots),...I(e.artifactFileRoots)].filter(Boolean)}}function ke(e){let t=a(e.codexSessionsRoot||e.codexSessionRoot);if(t)return t;let n=c(e.env)?e.env:{},r=a(e.codexHome||n.CODEX_HOME||process.env.CODEX_HOME)||N(er(),".codex");return N(r,"sessions")}function Ir(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 N(e,r,s,i)}function Le(e,t,n){let r=new Set;for(let s of[t-ct,t,t+ct,n-ct,n,n+ct])r.add(Ir(e,s));return[...r].filter(s=>Se(s))}function xr(e,t,n){let r=ke(e),s=t-ir,i=n+or,o=[];for(let u of Le(r,t,n)){let l=[];try{l=Re(u)}catch{continue}for(let d of l){if(!d.endsWith(".jsonl"))continue;let f=N(u,d);try{let m=Qn(f);if(!m.isFile()||m.mtimeMs<s||m.mtimeMs>i)continue;o.push({path:f,mtimeMs:m.mtimeMs})}catch{}}}return o.sort((u,l)=>l.mtimeMs-u.mtimeMs).slice(0,ar)}function Or(e,t,n=t){let r=ke(e),s=new Set;for(let i of Le(r,t,n)){let o=[];try{o=Re(i)}catch{continue}for(let u of o)u.endsWith(".jsonl")&&s.add(N(i,u))}return s}function At(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)At(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&&At(e[r],t,n+1)}}function Pe(e){return a(e).replace(/\s+/g," ")}function Cr(e){let t=Pe(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 o of r){let u=t.slice(Math.max(0,o),Math.max(0,o)+n).trim();u.length>=40&&!s.has(u)&&(s.add(u),i.push(u))}return i}function Ar(e,t){let n=Cr(t);if(!n.length)return!1;let r=[];for(let i of e)At(i,r);let s=Pe(r.join(" "));return n.every(i=>s.includes(i))}function Nr(e){return e.find(t=>c(t)&&a(t.type)==="session_meta"&&c(t.payload))||null}function Mr(e){let t=c(e?.payload)?e.payload:{},n=a(e?.timestamp||t.timestamp),r=Date.parse(n);return Number.isFinite(r)?r:Number.NaN}function Ur(e){let t=a(e.originator),n=a(e.source);if(t!=="codex_exec"&&n!=="exec"||a(e.parent_thread_id))return!1;let r=a(e.thread_source);if(r&&r!=="user")return!1;let s=a(e.session_id),i=a(e.id);return!(s&&i&&s!==i)}function br(e,t,n){if(!Ar(e,t.promptText))return!1;let r=Nr(e);if(!r)return!1;let s=r.payload;if(!Ur(s))return!1;let i=Mr(r);if(!Number.isFinite(i)||i<t.startedAtMs-5e3||i>n+5e3)return!1;let o=a(t.target.cwd),u=a(s.cwd);return!(o&&u&&ge(o)!==ge(u))}function ye(e){try{return Lr(we(e,"utf8"))}catch{return null}}function kr(e,t,n){if(!e||e.disabled)return null;if(e.matchedPath){let s=ye(e.matchedPath);return s?{path:e.matchedPath,events:s}:null}let r=[];for(let s of xr(e.target,e.startedAtMs,n)){if(e.baselinePaths.has(s.path))continue;let i=ye(s.path);!i||!br(i,e,n)||r.push({path:s.path,events:i})}return r.length!==1?(r.length>1&&(e.disabled=!0,p("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,p("info","runtime.cli","codex transcript stream attached",{target:e.target.targetCode,sessionId:t}),r[0])}function Lr(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 Pr(e){if(!c(e))return!1;let t=c(e.payload)?e.payload:{},n=a(e.type),r=a(t.type);return n==="event_msg"&&r==="image_generation_end"||n==="response_item"&&r==="image_generation_call"}function De(e){if(!c(e))return!1;let t=c(e.payload)?e.payload:{};return a(e.type)==="response_item"&&lr.has(a(t.type))}function Dr(e,t,n,r){let s=xe(e),i=Mt(e),o=0,u=0,l=0;if(s&&!i&&t.emitThoughtChunks&&Ue(t,n,r,s)&&(l=1),s&&i){let d=t.emittedTexts.size?`
7
+ ${n}`:`${n}
8
+ `;this.child.stdin.write(s,r)}onNotification(t,r){let n=this.notificationHandlers.get(t)||new Set;return n.add(r),this.notificationHandlers.set(t,n),()=>{n.delete(r),n.size===0&&this.notificationHandlers.delete(t)}}onRequest(t,r){return this.requestHandlers.set(t,r),()=>this.requestHandlers.delete(t)}onExit(t){return this.exitHandlers.add(t),()=>this.exitHandlers.delete(t)}rejectAll(t){for(let r of this.pending.values())clearTimeout(r.timer),r.reject(t);this.pending.clear()}handleExit(t,r){this.exited=!0,this.exitCode=t,this.exitSignal=r,this.rejectAll(new Error(`runtime exited before response (${t}/${r})`));for(let n of this.exitHandlers)n(t,r)}async waitForExit(t=5e3){return!this.child||this.exited?!0:await new Promise(r=>{let n=setTimeout(()=>{s(),r(!1)},t);n.unref?.();let s=()=>{clearTimeout(n),this.exitHandlers.delete(i)},i=()=>{s(),r(!0)};this.exitHandlers.add(i),this.exited&&i()})}signal(t){if(!this.child||this.exited)return!1;let r=this.child.pid;if(!r)return!1;try{return this.detached&&process.platform!=="win32"?process.kill(-r,t):this.child.kill(t),!0}catch(n){if(n?.code==="ESRCH")return this.exited=!0,!1;try{return this.child.kill(t),!0}catch(s){return s?.code!=="ESRCH"&&h("warn","runtime","runtime signal failed",{target:this.label,pid:r,signal:t,error:String(s)}),!1}}}async stop(t="stop",{termTimeoutMs:r=5e3,killTimeoutMs:n=2e3}={}){if(!(!this.child||this.exited)){if(this.stopPromise)return await this.stopPromise;this.stopPromise=(async()=>{if(!this.child||this.exited)return;let s=this.child.pid;h("info","runtime","stopping runtime",{target:this.label,reason:t,pid:s}),this.rejectAll(new Error(`runtime stopped: ${t}`)),this.signal("SIGTERM"),!await this.waitForExit(r)&&this.child&&!this.exited&&(h("warn","runtime","runtime did not exit after SIGTERM; force killing",{target:this.label,reason:t,pid:s}),this.signal("SIGKILL"),await this.waitForExit(n))})();try{await this.stopPromise}finally{this.stopPromise=null}}}};import{randomUUID as Xe}from"node:crypto";import{existsSync as kn,readFileSync as Ln,realpathSync as ze,statSync as Dn}from"node:fs";import{basename as Ye,extname as Qe,isAbsolute as ct,join as vn,relative as Ze,resolve as We}from"node:path";var Fn=25*1024*1024;function tr(e,t=""){let r=a(t);if(r)return r;let n=Qe(a(e)).toLowerCase();return n===".jpg"||n===".jpeg"?"image/jpeg":n===".webp"?"image/webp":n===".gif"?"image/gif":"image/png"}function er(e,t){let r=typeof e=="string"?e.trim():"";return!r||r==="<omitted>"?"":r.startsWith("data:")?r:`data:${t};base64,${r.replace(/\s+/g,"")}`}function Et(e){if(Array.isArray(e))return e.map(a).filter(Boolean);let t=a(e);return t?[t]:[]}function Hn(e,t){let r=Ze(t,e);return r===""||!!r&&!r.startsWith("..")&&!ct(r)}function $n(e,t){let r=a(e);if(!r||!kn(r))return"";try{let n=ze(r);for(let s of t)try{let i=ze(s);if(Hn(n,i))return n}catch{}}catch{return""}return""}function Bn(e,t){let r=a(e);if(!r||!ct(r))return r;for(let n of Array.isArray(t)?t:[]){if(!u(n))continue;let s=a(n.runtimeRoot),i=a(n.hostRoot);if(!s||!i||!ct(s)||!ct(i))continue;let o=Ze(We(s),We(r));if(o===""||!o.startsWith("..")&&!ct(o))return o?vn(i,o):i}return r}function Kt(e,t,r={}){let n=a(e);return!n||n.startsWith("data:")||/^https?:\/\//i.test(n)?n:qn(n,t,r)}function qn(e,t,r={}){let n=[...Et(r.trustedFileRoots),...Et(r.trustedFileRoot),...Et(r.artifactRoots),...Et(r.artifactRoot)],s=$n(Bn(e,r.pathMappings),n);if(!s)return"";try{let i=Dn(s);return!i.isFile()||i.size<=0||i.size>Fn?"":`data:${t};base64,${Ln(s).toString("base64")}`}catch{return""}}function x(...e){for(let t of e){let r=a(t);if(r)return r}return""}function jn(e,t,r,n){let s=r.toLowerCase();if(s==="image"||s==="picture")return!0;let i=x(n,e.previewUrl,e.fileUrl,e.imageUrl,e.dataUrl,e.url,e.uri,t.previewUrl,t.fileUrl,t.imageUrl,t.dataUrl,t.url,t.uri),o=Qe(i.split("?",1)[0].split("#",1)[0]).toLowerCase();return[".png",".jpg",".jpeg",".webp",".gif"].includes(o)}function zt(e,t={}){let{source:r="runtime_image_generation_event"}=t;if(!u(e))return null;let n=u(e.payload)?e.payload:{},s=a(e.type),i=a(n.type);if(!(s==="event_msg"&&i==="image_generation_end"||s==="response_item"&&i==="image_generation_call"))return null;let o=x(n.call_id,n.id),c=x(n.saved_path,n.savedPath),l=x(n.revised_prompt,n.revisedPrompt),d=tr(c,n.mimeType||n.mime_type),f=er(n.result,d)||Kt(c,d,t);if(!f)return null;let p=f.startsWith("data:")?f:"",g=c?Ye(c):`${o||Xe()}.png`;return{artifactType:"image",type:"image",fieldKey:"image",title:g||"Generated image",summary:l||"Generated image",content:{prompt:l||void 0,dataUrl:p||void 0,imageUrl:f,previewUrl:f,fileUrl:f,mimeType:d},dataUrl:p||void 0,previewUrl:f,fileUrl:f,metadata:{source:r,eventType:i,callId:o||void 0,savedPath:c||void 0,filename:g,mimeType:d,revisedPrompt:l||void 0}}}function Gn(e){let t=u(e)?e:{},r=[];for(let n of["_artifacts","artifacts"]){let s=t[n];Array.isArray(s)&&r.push(...s)}for(let n of["_artifact","artifact"]){let s=t[n];u(s)&&r.push(s)}return r}function Kn(e,t={}){let{source:r="runtime_artifact"}=t,n=u(e)?e:{};if(!Object.keys(n).length)return null;let s=u(n.content)?{...n.content}:{},i=u(n.metadata)?{...n.metadata}:{},o=x(n.saved_path,n.savedPath,s.saved_path,s.savedPath,i.savedPath),c=x(n.mimeType,n.mime_type,s.mimeType,s.mime_type,i.mimeType),l=x(n.artifactType,n.artifact_type,n.type,n.kind,s.type,o?"image":"file"),d=jn(n,s,l,o),f=d?tr(o,c):c;if(d){let N=x(n.dataUrl,s.dataUrl),_=N.startsWith("data:")?N:"",y=x(n.imageUrl,n.previewUrl,n.fileUrl,n.downloadUrl,n.url,n.uri,s.imageUrl,s.previewUrl,s.fileUrl,s.downloadUrl,s.url,s.uri),S=er(n.result??s.result,f)||_||Kt(o,f,t)||Kt(y,f,t);S&&(S.startsWith("data:")&&(s.dataUrl||=S),s.imageUrl||=S,s.previewUrl||=S,s.fileUrl||=S,f&&(s.mimeType||=f))}for(let[N,_]of[["prompt","prompt"],["previewUrl","previewUrl"],["fileUrl","fileUrl"],["downloadUrl","downloadUrl"],["imageUrl","imageUrl"],["dataUrl","dataUrl"],["url","url"],["uri","uri"],["mimeType","mimeType"],["mime_type","mimeType"]]){let y=n[N];y!=null&&y!==""&&!(_ in s)&&(s[_]=y)}let p=x(n.fileUrl,n.downloadUrl,n.imageUrl,n.dataUrl,n.url,n.uri,s.fileUrl,s.downloadUrl,s.imageUrl,s.dataUrl,s.url,s.uri),g=x(n.previewUrl,n.imageUrl,n.dataUrl,n.url,n.fileUrl,n.uri,s.previewUrl,s.imageUrl,s.dataUrl,s.url,s.fileUrl,s.uri),m=x(n.dataUrl,s.dataUrl,p.startsWith("data:")?p:"",g.startsWith("data:")?g:""),E=x(n.filename,i.filename,o?Ye(o):""),O=x(n.fieldKey,n.field_key,s.fieldKey,i.fieldKey,d?"image":"artifact");return{...n,artifactType:l,type:n.type||l,fieldKey:O,title:x(n.title,E,"Runtime artifact"),summary:x(n.summary,s.prompt,n.title,E,"Runtime artifact"),content:s,dataUrl:m||void 0,fileUrl:p||void 0,previewUrl:g||void 0,metadata:{...i,source:x(i.source,r),savedPath:o||i.savedPath,filename:E||i.filename,mimeType:f||i.mimeType}}}function St(e,t){if(!t||!e)return;let r=u(t.metadata)?t.metadata:{},n=x(r.savedPath,r.callId,t.previewUrl,t.fileUrl)||Xe(),s=e.get(n);if(!s){e.set(n,t);return}s.content={...u(s.content)?s.content:{},...u(t.content)?t.content:{}},s.metadata={...u(s.metadata)?s.metadata:{},...r},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 Vt(e,t,r={}){for(let n of Gn(e))St(t,Kn(n,r))}function Wt(e){if(!u(e)||!u(e.payload))return u(e)?e:{value:e};let t=a(e.payload.type);if(t!=="image_generation_end"&&t!=="image_generation_call")return e;let r={...e.payload};return typeof r.result=="string"&&r.result&&(r.result="<omitted>",r.resultLength=e.payload.result.length),{...e,payload:r}}function Je(e,t,r){if(!u(e))return e;let n=u(e.event)?e.event:null;return n?(St(t,zt(n,r)),{...e,event:Wt(n)}):e}function rr(e,t,r={}){if(!u(e))return e;Vt(e,t,r);let n=Je(e,t,r),s=u(n.update)?Je(n.update,t,r):null;return s&&s!==n.update&&(n={...n,update:s}),n}function nr(e,t,r={}){let n=u(e)?{...e}:{};Vt(n,t,r),Vt(u(n.output)?n.output:{},t,r);let s=[...t?.values?.()||[]];return s.length&&(n._artifacts=s),delete n.artifacts,n}var Q=class{constructor(t,r,n={},s={}){this.agent=t,this.target=r,this.callbacks=n,this.options=s,this.proc=null,this.launch=null,this.launchCleanup=null,this.permissionHandlers=new Map}async ensureStarted(){if(this.proc)return;let t=a(this.target.command);if(!t)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);let r={command:t,args:C(this.target.args),cwd:a(this.target.cwd)||this.agent.workspace||process.cwd(),environment:u(this.target.env)?this.target.env:{}},n=this.options.prepareLaunch?await this.options.prepareLaunch(r):{...r,environment:{...process.env,...r.environment},cleanup:async()=>{}};this.launch=n,this.launchCleanup=n.cleanup,this.proc=new Rt({command:n.command,args:n.args,cwd:n.cwd,env:n.environment,label:`${this.agent.agentId}:${this.agent.targetCode}`,framing:a(this.target.framing||"line")}),this.proc.onRequest("session/request_permission",s=>this.handlePermissionRequest(s)),this.proc.onRequest("session/requestPermission",s=>this.handlePermissionRequest(s));try{await this.proc.start({initialize:this.target.initialize!==!1,initializeParams:{clientInfo:{name:"orcha-runtime-bridge",version:Y},...u(this.target.initializeParams)?this.target.initializeParams:{}}})}catch(s){throw this.proc=null,await this.cleanupLaunch(),s}}async sessionNew(t={}){return await this.ensureStarted(),this.proc.call("session/new",this.sessionNewParams(t))}sessionNewParams(t={}){let r=Array.isArray(t.mcpServers)?t.mcpServers:Array.isArray(this.target.mcpServers)?this.target.mcpServers:[];return{...t,mcpServers:r}}async sessionPrompt(t,r){await this.ensureStarted();let n=a(t.sessionId),s=new Map,i=this.artifactOptions(),o=this.proc.onNotification("session/update",l=>{let d=a(l.sessionId);(!d||d===n)&&r(rr(l,s,i))}),c=async l=>this.callbacks.onPermissionRequest?.({agent:this.agent,runtimeSessionId:n,request:l,emitUpdate:r})||{outcome:"denied",reason:"permission handler is not configured"};n&&this.permissionHandlers.set(n,c),this.permissionHandlers.set("*",c);try{let l=await this.proc.call("session/prompt",t,this.options.sessionPromptTimeoutMs);return nr(l,s,i)}finally{o(),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 r=a(t.sessionId),n=this.permissionHandlers.get(r)||this.permissionHandlers.get("*");return n?n(t):{outcome:"denied",reason:"no active Orcha permission handler"}}artifactSource(){return a(this.target.type||"acp")==="openclaw"?"openclaw_image_generation":"acp_runtime_image_generation"}artifactOptions(){let t=u(this.target.env)?this.target.env:{};return{source:this.artifactSource(),trustedFileRoots:[a(this.launch?.artifactDirectory),a(this.launch?.homeDirectory),a(this.target.artifactRoot),a(this.target.artifactDir),a(this.target.runtimeArtifactRoot),a(t.ORCHA_RUNTIME_ARTIFACT_DIR),...C(this.target.trustedArtifactRoots),...C(this.target.trustedFileRoots),...C(this.target.artifactRoots),...C(this.target.artifactFileRoots)].filter(Boolean),pathMappings:Array.isArray(this.launch?.pathMappings)?this.launch.pathMappings:[]}}async stop(t){try{await this.proc?.stop(t)}finally{this.proc=null,await this.cleanupLaunch()}}async cleanupLaunch(){let t=this.launchCleanup;this.launchCleanup=null,this.launch=null,await t?.()}};function Vn(e){let t=u(e.metadata)?e.metadata:{};return a(t.agentCode)}function zn(e,t){let r=Vn(e);return r?`agent:${r}:${t}`:`orcha-${t}`}var wt=class extends Q{constructor(t,r,n,s={},i={}){let o=a(n).replace(/[^A-Za-z0-9._-]+/g,"-")||"default",c=a(r.command)||"openclaw",l=Array.isArray(r.args)?r.args.map(String):[],d=l.length>0?l:["acp","--session",zn(t,o)];super(t,{...r,command:c,args:d},s,i)}sessionNewParams(t={}){return{...t,mcpServers:[]}}};import{spawn as ur}from"node:child_process";import{randomUUID as Z}from"node:crypto";import{existsSync as lr,mkdirSync as Wn,readdirSync as dr,readFileSync as fr,realpathSync as lt,rmSync as Jn,rmdirSync as Xn,statSync as Yn,unlinkSync as Qn}from"node:fs";import{homedir as Zn,tmpdir as pr}from"node:os";import{basename as Zt,dirname as ts,join as L,resolve as sr}from"node:path";var es=36e5,mr=5e3,rs=2*60*1e3,ns=2*60*1e3,ss=12,is=1e3,os=1500,as=1e3,It=24*60*60*1e3,ut=new Set(["final_answer","final","complete","completed","done"]),cs=new Set(["function_call","function_call_output","custom_tool_call","custom_tool_call_output","local_shell_call","local_shell_call_output","mcp_tool_call","mcp_tool_call_output","web_search_call","image_generation_call","image_generation_end"]),us=new Set(["context_compacted","context_compaction","context_compressed"]);function xt(e,t){if(e?.pid){if(process.platform==="win32"){let r=["/PID",String(e.pid),"/T"];t==="SIGKILL"&&r.push("/F");try{ur("taskkill",r,{stdio:"ignore",windowsHide:!0}).unref?.()}catch{try{e.kill(t)}catch{}}return}try{process.kill(-e.pid,t)}catch(r){if(r?.code==="ESRCH")return;try{e.kill(t)}catch{}}}}function Jt(e){xt(e,"SIGTERM");let t=setTimeout(()=>xt(e,"SIGKILL"),mr);return t.unref?.(),t}function P(e){if(typeof e=="string")return e;if(Array.isArray(e))return e.map(t=>P(t)).join("");if(!u(e))return"";for(let t of["text","delta","output_text","content","message","output"]){let r=P(e[t]);if(r)return r}return""}function hr(e){if(!u(e))return"";let t=u(e.payload)?e.payload:{};if(a(e.type)==="event_msg"){if(a(t.type)==="agent_message")return a(t.message);if(a(t.type)==="task_complete")return a(t.last_agent_message)}if(a(e.type)==="response_item"&&a(t.type)==="message"&&a(t.role)==="assistant")return P(t.content)||P(t.message);if(a(e.type)==="result")return P(e.result);let r=P(e.delta)||P(e.text)||P(e.content);if(r)return r;let n=u(e.item)?e.item:{};return["message","agent_message"].includes(a(n.type))||a(n.role)==="assistant"?P(n.content)||P(n.text)||P(n.message):""}function gr(e,t={}){return zt(e,{source:"codex_cli_image_generation",...t})}function _r(e,t){St(e.artifacts,t)}function Tr(e){return G(Wt(e))}function te(e){if(!u(e))return!1;let t=u(e.payload)?e.payload:{},r=a(e.type),n=a(t.type);if(r==="event_msg"&&n==="task_complete")return!0;let s=a(t.phase||t.status||t.stage).toLowerCase();if(r==="event_msg"&&n==="agent_message"||r==="response_item"&&n==="message"&&a(t.role)==="assistant")return ut.has(s);let i=u(e.item)?e.item:{};return r==="item.completed"&&a(i.type)==="agent_message"?!0:r==="result"&&e.is_error!==!0?a(e.result).length>0:!1}function ls(e){let t=a(e.terminalProtocol||e.eventProtocol).toLowerCase();if(t)return t;let r=Zt(a(e.command)).replace(/\.exe$/i,"").toLowerCase();return r==="codex"||r==="claude"?r:""}function ir(e,t,r){let n=u(t.error)?t.error:{},s=a(n.message)||P(t.error)||a(t.result)||a(t.message)||r;return Object.assign(new Error(s),{code:e})}function ds(e,t){if(!u(e))return null;let r=a(e.type).toLowerCase();if(t==="codex")return r==="turn.completed"?{status:"completed",result:{stopReason:"end_turn"}}:r==="turn.failed"?{status:"failed",error:ir("RUNTIME_CODEX_TURN_FAILED",e,"Codex turn failed")}:null;if(t==="claude"&&r==="result"){let n=a(e.subtype).toLowerCase();return e.is_error===!0||n.startsWith("error")||["failed","failure"].includes(n)?{status:"failed",error:ir("RUNTIME_CLAUDE_RESULT_FAILED",e,"Claude result failed")}:{status:"completed",result:{stopReason:"end_turn",...a(e.result)?{output:a(e.result)}:{}}}}return null}function or(e){return u(e)?a(e.phase||e.status||e.stage).toLowerCase():""}function fs(e){if(!u(e)||te(e))return!1;let t=u(e.payload)?e.payload:{},r=a(e.type),n=a(t.type),s=or(t);if(r==="event_msg"&&n==="agent_message"||r==="response_item"&&n==="message"&&a(t.role)==="assistant")return!!(s&&!ut.has(s));let i=u(e.item)?e.item:{},o=or(i);return a(i.role)==="assistant"||a(i.type)==="message"?!!(o&&!ut.has(o)):!1}function ps(e,t,r){return r.captureLastMessage===!1||t.includes("--output-last-message")||t.includes("-o")?!1:r.captureLastMessage===!0?!0:Zt(e)==="codex"}function ms(e,t){return t.collectCodexTranscriptArtifacts===!1?!1:t.collectCodexTranscriptArtifacts===!0?!0:Zt(e)==="codex"}function yr(e){return Math.max(20,T(e.codexTranscriptPollMs||e.transcriptPollMs,is))}function hs(e){return Math.max(0,T(e.codexFinalOutputWaitMs||e.finalOutputWaitMs,os))}function At(e){if(typeof e=="boolean")return e;let t=a(e).toLowerCase();return["true","1","yes","y","on"].includes(t)?!0:["false","0","no","n","off"].includes(t)?!1:null}function ee(e){let t=u(e?.metadata)?e.metadata:{};return u(t._runtimeBridge)?t._runtimeBridge:{}}function Xt(e){return a(ee(e).promptKind).toLowerCase()}function gs(e,t){for(let r of[e.codexTranscriptStreaming,e.streamCodexTranscript]){let n=At(r);if(n!=null)return n}return Xt(t)==="chat"}function _s(e,t){let r=ee(e);for(let s of[r.emitThoughtChunks,r.streamThoughts]){let i=At(s);if(i!=null)return i}let n=Xt(e);if(n&&n!=="chat")return!1;for(let s of[t.emitThoughtChunks,t.streamThoughts]){let i=At(s);if(i!=null)return i}return Xt(e)==="chat"}function Ts(e){let t=ee(e);for(let r of[t.finalTextOnly,t.finalOutputOnly]){let n=At(r);if(n!=null)return n}return null}function ys(e,t){let r=Ts(e);return r??(t.finalTextOnly===!0||t.finalOutputOnly===!0?!0:(t.finalTextOnly===!1||t.finalOutputOnly===!1,!1))}function Rs(e,t){return!e.finalTextOnly||t}function Rr(e,t,r,n,s=n){return!n||e.emittedTexts.has(s)?!1:(e.emittedTexts.add(s),r({sessionId:t,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:n}}}),!0)}function Er(e,t,r,n){return!n||e.emittedThoughtTexts.has(n)?!1:(e.emittedThoughtTexts.add(n),r({sessionId:t,update:{sessionUpdate:"agent_thought_chunk",content:{type:"text",text:n}}}),!0)}function Es(e,t,r,n=new Set){return{target:e,promptText:t,startedAtMs:r,baselinePaths:n,matchedPath:"",disabled:!1,processedLines:new Map}}function Ss(e,t){let r=u(e.env)?e.env:{},n=a(e.artifactRoot||e.artifactDir||e.runtimeArtifactRoot||r.ORCHA_RUNTIME_ARTIFACT_DIR)||L(pr(),"orcha-runtime-artifacts"),s=a(t).replace(/[^A-Za-z0-9._-]+/g,"-").slice(0,80)||Z(),i=L(n,s),o=L(i,Z());return Wn(o,{recursive:!0}),{root:o,realRoot:lt(o),sessionRoot:i,realSessionRoot:lt(i)}}function ws(e){let t=a(e?.artifactDirectory);if(!t)throw new Error("sandbox launch did not provide an artifact directory");return{root:t,realRoot:lt(t),sessionRoot:"",realSessionRoot:""}}function Sr(e){return a(u(e)?e.root:e)}function ar(e){let t=Sr(e),r=a(u(e)?e.sessionRoot:ts(t)),n=a(u(e)?e.realSessionRoot:"");if(r)try{if(n&&lt(r)!==n)return;Xn(r)}catch{}}function Is(e,t={}){let r=Sr(e),n=a(u(e)?e.realRoot:"");if(r){try{if(n&&lt(r)!==n){h("warn","runtime.cli","runtime artifact directory cleanup skipped; path changed",{...t,artifactRoot:r});return}}catch{ar(e);return}try{Jn(r,{recursive:!0,force:!0})}catch(s){h("warn","runtime.cli","runtime artifact directory cleanup failed",{...t,artifactRoot:r,error:String(s?.message||s)});return}ar(e)}}function Os(e,t,r=null){return{trustedFileRoots:[t,a(r?.artifactDirectory),a(r?.homeDirectory),...C(e.trustedArtifactRoots),...C(e.trustedFileRoots),...C(e.artifactRoots),...C(e.artifactFileRoots)].filter(Boolean),pathMappings:Array.isArray(r?.pathMappings)?r.pathMappings:[]}}function wr(e){let t=a(e.codexSessionsRoot||e.codexSessionRoot);if(t)return t;let r=u(e.env)?e.env:{},n=a(e.codexHome||r.CODEX_HOME||process.env.CODEX_HOME)||L(Zn(),".codex");return L(n,"sessions")}function xs(e,t){let r=new Date(t),n=String(r.getFullYear()),s=String(r.getMonth()+1).padStart(2,"0"),i=String(r.getDate()).padStart(2,"0");return L(e,n,s,i)}function Ir(e,t,r){let n=new Set;for(let s of[t-It,t,t+It,r-It,r,r+It])n.add(xs(e,s));return[...n].filter(s=>lr(s))}function As(e,t,r){let n=wr(e),s=t-rs,i=r+ns,o=[];for(let c of Ir(n,t,r)){let l=[];try{l=dr(c)}catch{continue}for(let d of l){if(!d.endsWith(".jsonl"))continue;let f=L(c,d);try{let p=Yn(f);if(!p.isFile()||p.mtimeMs<s||p.mtimeMs>i)continue;o.push({path:f,mtimeMs:p.mtimeMs})}catch{}}}return o.sort((c,l)=>l.mtimeMs-c.mtimeMs).slice(0,ss)}function Cs(e,t,r=t){let n=wr(e),s=new Set;for(let i of Ir(n,t,r)){let o=[];try{o=dr(i)}catch{continue}for(let c of o)c.endsWith(".jsonl")&&s.add(L(i,c))}return s}function Yt(e,t,r=0){if(!(r>8||e===null||e===void 0)){if(typeof e=="string"){e&&t.push(e);return}if(Array.isArray(e)){for(let n of e)Yt(n,t,r+1);return}if(u(e))for(let n of["payload","item","text","delta","output_text","content","message","output","input","prompt","last_agent_message","revised_prompt"])n in e&&Yt(e[n],t,r+1)}}function Or(e){return a(e).replace(/\s+/g," ")}function Ns(e){let t=Or(e);if(!t)return[];if(t.length<=200)return[t];let r=160,n=[0,Math.floor((t.length-r)/2),t.length-r],s=new Set,i=[];for(let o of n){let c=t.slice(Math.max(0,o),Math.max(0,o)+r).trim();c.length>=40&&!s.has(c)&&(s.add(c),i.push(c))}return i}function bs(e,t){let r=Ns(t);if(!r.length)return!1;let n=[];for(let i of e)Yt(i,n);let s=Or(n.join(" "));return r.every(i=>s.includes(i))}function Ms(e){return e.find(t=>u(t)&&a(t.type)==="session_meta"&&u(t.payload))||null}function Us(e){let t=u(e?.payload)?e.payload:{},r=a(e?.timestamp||t.timestamp),n=Date.parse(r);return Number.isFinite(n)?n:Number.NaN}function Ps(e){let t=a(e.originator),r=a(e.source);if(t!=="codex_exec"&&r!=="exec"||a(e.parent_thread_id))return!1;let n=a(e.thread_source);if(n&&n!=="user")return!1;let s=a(e.session_id),i=a(e.id);return!(s&&i&&s!==i)}function ks(e,t,r){if(!bs(e,t.promptText))return!1;let n=Ms(e);if(!n)return!1;let s=n.payload;if(!Ps(s))return!1;let i=Us(n);if(!Number.isFinite(i)||i<t.startedAtMs-5e3||i>r+5e3)return!1;let o=a(t.target.cwd),c=a(s.cwd);return!(o&&c&&sr(o)!==sr(c))}function cr(e){try{return Ds(fr(e,"utf8"))}catch{return null}}function Ls(e,t,r){if(!e||e.disabled)return null;if(e.matchedPath){let s=cr(e.matchedPath);return s?{path:e.matchedPath,events:s}:null}let n=[];for(let s of As(e.target,e.startedAtMs,r)){if(e.baselinePaths.has(s.path))continue;let i=cr(s.path);!i||!ks(i,e,r)||n.push({path:s.path,events:i})}return n.length!==1?(n.length>1&&(e.disabled=!0,h("warn","runtime.cli","codex transcript fallback disabled; multiple matching transcripts",{target:e.target.targetCode,sessionId:t,transcriptCount:n.length})),null):(e.matchedPath=n[0].path,h("info","runtime.cli","codex transcript stream attached",{target:e.target.targetCode,sessionId:t}),n[0])}function Ds(e){let t=[];for(let r of e.split(/\r?\n/)){let n=r.trim();if(n)try{t.push(JSON.parse(n))}catch{}}return t}function vs(e){if(!u(e))return!1;let t=u(e.payload)?e.payload:{},r=a(e.type),n=a(t.type);return r==="event_msg"&&n==="image_generation_end"||r==="response_item"&&n==="image_generation_call"}function Fs(e){if(!u(e))return!1;let t=u(e.payload)?e.payload:{};return a(e.type)==="response_item"&&cs.has(a(t.type))}function Hs(e){if(!u(e))return!1;let t=u(e.payload)?e.payload:{};return us.has(a(t.type))}function $s(e,t,r,n){let s=hr(e),i=te(e),o=0,c=0,l=0;if(s&&!i&&t.emitThoughtChunks&&Er(t,r,n,s)&&(l=1),s&&i){let d=t.emittedTexts.size?`
9
9
 
10
- ${s}`:s;Me(t,n,r,d,s)&&(o=1,u=1)}return s&&i&&(t.finalTextSeen=!0),Ce(t,Oe(e,t.artifactOptions)),(Pr(e)||De(e)||i)&&r({sessionId:n,update:{sessionUpdate:"runtime_event",event:Ae(e)}}),{textCount:o,finalTextCount:u,thoughtCount:l}}function Nt(e,t,n,r,s=Date.now()){if(!t)return{artifactCount:0,transcriptCount:0,textCount:0,finalTextCount:0,thoughtCount:0};let i=e.artifacts.size,o=0,u=0,l=0,d=0,f=kr(t,n,s);if(f){let m=Math.min(t.processedLines.get(f.path)||0,f.events.length),g=e.artifacts.size;for(let h of f.events.slice(m)){let y=Dr(h,e,n,r);u+=y.textCount,l+=y.finalTextCount,d+=y.thoughtCount}t.processedLines.set(f.path,f.events.length),(f.events.length>m||e.artifacts.size>g)&&(o=1)}return{artifactCount:e.artifacts.size-i,transcriptCount:o,textCount:u,finalTextCount:l,thoughtCount:d}}function Fr(e,{remove:t=!0}={}){if(!e||!Se(e))return"";try{return we(e,"utf8").trim()}catch{return""}finally{t&&lt(e)}}function lt(e){if(e)try{tr(e)}catch{}}function $r(e,t){return{artifactCount:(e?.artifactCount||0)+(t?.artifactCount||0),transcriptCount:(e?.transcriptCount||0)+(t?.transcriptCount||0),textCount:(e?.textCount||0)+(t?.textCount||0),finalTextCount:(e?.finalTextCount||0)+(t?.finalTextCount||0),thoughtCount:(e?.thoughtCount||0)+(t?.thoughtCount||0)}}function Hr(e){return new Promise(t=>setTimeout(t,e))}function vr(e,t,n,r){return r?(e.finalTextSeen=!0,e.emittedTexts.has(r)||(e.emittedTexts.add(r),n({sessionId:t,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:r}}})),!0):!1}async function Br(e,t,n,r,s,i){let o=Nt(e,t,n,r,Date.now()),u=()=>vr(e,n,r,Fr(s,{remove:!1}));if(u()||e.finalTextSeen)return lt(s),o;let l=mr(i);if(l<=0||!t&&!s)return lt(s),o;let d=Date.now()+l,f=Math.min(Ne(i),100);for(;!e.finalTextSeen&&Date.now()<d&&(await Hr(Math.min(f,Math.max(0,d-Date.now()))),o=$r(o,Nt(e,t,n,r,Date.now())),!u()););return lt(s),o}var pt=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}-${X()}`}}async sessionPrompt(t,n){let r=Date.now(),s=a(this.target.command);if(!s)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);let i=a(t.sessionId)||X(),o=nt(t.prompt),u=a(this.target.promptMode||"stdin"),l=this.buildArgs(u,o),d=a(this.target.cwd)||this.agent.workspace||process.cwd(),f=Rr(this.target,i),m=f.root,g=Er(this.target,m),h=pr(s,this.target),y={...this.target,targetCode:this.agent.targetCode,cwd:d},U=h?Or(y,r):new Set,x=fr(s,l,this.target)?N(Ee(),`orcha-runtime-last-message-${X()}.txt`):"";x&&l.push("--output-last-message",x);let A=T(this.target.timeoutMs||this.target.sessionPromptTimeoutMs,T(this.options.sessionPromptTimeoutMs,rr)),b={...process.env,...c(this.target.env)?this.target.env:{},...u==="env"?{ORCHA_RUNTIME_PROMPT:o}:{},ORCHA_AGENT_ID:this.agent.agentId,ORCHA_SESSION_ID:i,ORCHA_RUNTIME_ARTIFACT_DIR:m},_=Vn(s,l,{cwd:d,env:b,stdio:["pipe","pipe","pipe"]});this.active.set(i,_),p("info","runtime.cli","runtime prompt started",{target:this.agent.targetCode,sessionId:i,pid:_.pid,timeoutMs:A});let te="",St=a(this.target.outputMode||"text"),k={artifacts:new Map,emittedTexts:new Set,emittedThoughtTexts:new Set,value:"",artifactOptions:g,finalTextSeen:!1,finalTextOnly:Tr(t,this.target),emitThoughtChunks:gr(t,this.target)},Rt=h?Sr(y,o,r,U):null;return _.stdout.setEncoding("utf8"),_.stdout.on("data",B=>this.handleStdout(B,St,k,i,n)),_.stderr.setEncoding("utf8"),_.stderr.on("data",B=>{te+=B,this.target.emitStderr===!0&&n({sessionId:i,update:{sessionUpdate:"runtime_stderr_chunk",content:{type:"text",text:B}}})}),u==="stdin"?_.stdin.end(o):_.stdin.end(),await new Promise((B,Sn)=>{let Q=!1,ee=!1,F=null,wt=Rt&&hr(this.target,t)?setInterval(()=>{try{Nt(k,Rt,i,n)}catch(R){p("warn","runtime.cli","codex transcript stream poll failed",{target:this.agent.targetCode,sessionId:i,error:String(R?.message||R)})}},Ne(this.target)):null;wt?.unref?.();let ne=setTimeout(()=>{ee=!0,p("warn","runtime.cli","runtime prompt timed out; terminating child",{target:this.agent.targetCode,sessionId:i,pid:_.pid,timeoutMs:A}),ut(_,"SIGTERM"),F=setTimeout(()=>{p("warn","runtime.cli","runtime prompt force killing child",{target:this.agent.targetCode,sessionId:i,pid:_.pid}),ut(_,"SIGKILL")},sr),F.unref?.(),tt(Object.assign(new Error(`runtime CLI timed out after ${A}ms`),{code:"RUNTIME_CLI_TIMEOUT"}))},A);ne.unref?.();let re=()=>{clearTimeout(ne),wt&&clearInterval(wt),F&&!ee&&clearTimeout(F),wr(f,{target:this.agent.targetCode,sessionId:i}),this.active.delete(i)},Rn=R=>{Q||(Q=!0,re(),B(R))},tt=R=>{Q||(Q=!0,re(),Sn(R))};_.on("error",R=>{p("warn","runtime.cli","runtime child error",{target:this.agent.targetCode,sessionId:i,pid:_.pid,error:String(R?.message||R)}),tt(R)}),_.on("exit",(R,q)=>{(async()=>{F&&(clearTimeout(F),F=null),St==="json-lines"&&k.value.trim()&&this.handleStdout(`
11
- `,St,k,i,n);let L=await Br(k,Rt,i,n,x,this.target);(L.artifactCount>0||L.textCount>0||L.thoughtCount>0)&&p("info","runtime.cli","codex transcript updates collected",{target:this.agent.targetCode,sessionId:i,artifactCount:L.artifactCount,textCount:L.textCount,finalTextCount:L.finalTextCount,thoughtCount:L.thoughtCount,transcriptCount:L.transcriptCount});let et=te.trim();if(et&&p("debug","runtime.cli","runtime stderr",{target:this.agent.targetCode,sessionId:i,stderr:et}),p("info","runtime.cli","runtime prompt finished",{target:this.agent.targetCode,sessionId:i,pid:_.pid,exitCode:R,signal:q,artifactCount:k.artifacts.size,finalTextSeen:k.finalTextSeen}),R!==0){let wn=Object.assign(new Error(`runtime CLI exited with code ${R??"unknown"}${q?` (${q})`:""}`),{code:"RUNTIME_CLI_EXIT_NONZERO",exitCode:R,signal:q});tt(wn);return}Rn({stopReason:"end_turn",exitCode:R,signal:q,_artifacts:[...k.artifacts.values()],...et?{stderr:et}:{}})})().catch(tt)})})}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 o=r.value.split(/\r?\n/);r.value=o.pop()||"";for(let u of o){let l=u.trim();if(l)try{let d=JSON.parse(l);Ce(r,Oe(d,r.artifactOptions)),i({sessionId:s,update:{sessionUpdate:"runtime_event",event:Ae(d)}});let f=xe(d),m=Mt(d);f&&r.emitThoughtChunks&&!m&&dr(d)?Ue(r,s,i,f):f&&yr(r,m)&&Me(r,s,i,f),f&&m&&(r.finalTextSeen=!0)}catch{i({sessionId:s,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`${u}
12
- `}}})}}}async sessionCancel(t){let n=a(t.sessionId),r=this.active.get(n);return r?(p("info","runtime.cli","cancelling runtime child",{target:this.agent.targetCode,sessionId:n,pid:r.pid}),ut(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())p("info","runtime.cli","stopping runtime child",{target:this.agent.targetCode,sessionId:n,pid:r.pid,reason:t}),ut(r,"SIGTERM");this.active.clear()}};var bt="ORCHA_RUNTIME_OUTPUT_START",kt="ORCHA_RUNTIME_OUTPUT_END",Lt="ORCHA_RUNTIME_CONTROL_START",Pt="ORCHA_RUNTIME_CONTROL_END",$e=bt,He=kt,ve=Lt,Be=Pt,Dt=[bt,kt,Lt,Pt],Kr=new Set(["_artifacts","_decision","_meta"]),zr=new RegExp(`(?:^|(?<=[\\r\\n]))[ \\t]*(?<marker>${Dt.join("|")})[ \\t]*(?=\\r\\n?|\\n|$)`,"g"),O=class extends Error{constructor(t,n){super(n),this.name="RuntimeResultProtocolError",this.code=t}};function Ke(e){let t=typeof e=="string"?e.trimStart():"";return Dt.some(n=>t.startsWith(n))}function ze(e){if(typeof e!="string")return null;let t=e,n=jr(t);if(![...n.values()].some(h=>h.length>0))return null;let r=[],s=[];for(let[h,y]of n)y.length===0?r.push(h):y.length>1&&s.push(h);if(r.length>0||s.length>0){let h=[];throw r.length>0&&h.push(`\u7F3A\u5C11 ${r.join(", ")}`),s.length>0&&h.push(`\u91CD\u590D ${s.join(", ")}`),new O("invalid_markers",`Runtime Result \u534F\u8BAE\u6807\u8BB0\u4E0D\u5B8C\u6574\uFF1A${h.join("\uFF1B")}`)}let i=n.get(bt)[0],o=n.get(kt)[0],u=n.get(Lt)[0],l=n.get(Pt)[0];if(!(i.end<=o.start&&o.end<=u.start&&u.end<=l.start))throw new O("invalid_marker_order","Runtime Result \u534F\u8BAE\u6807\u8BB0\u987A\u5E8F\u9519\u8BEF\uFF1A\u5FC5\u987B\u5148\u8F93\u51FA OUTPUT \u5757\uFF0C\u518D\u8F93\u51FA CONTROL \u5757");let d=Gr(t.slice(i.end,o.start));if(!d.trim())throw new O("empty_output","Runtime Result OUTPUT \u5757\u4E0D\u80FD\u4E3A\u7A7A");let f=t.slice(u.end,l.start).trim();if(!f)throw new O("empty_control","Runtime Result CONTROL \u5757\u4E0D\u80FD\u4E3A\u7A7A");let m;try{m=JSON.parse(f)}catch(h){throw new O("invalid_control_json",`Runtime Result CONTROL \u5757\u4E0D\u662F\u5408\u6CD5 JSON\uFF1A${String(h?.message||h)}`)}if(!Fe(m))throw new O("invalid_control_type","Runtime Result CONTROL \u5757\u5FC5\u987B\u662F JSON \u5BF9\u8C61");let g=Object.keys(m).filter(h=>!Kr.has(h)).sort();if(g.length>0)throw new O("invalid_control_keys",`Runtime Result CONTROL \u5757\u5305\u542B\u975E\u6807\u51C6\u5B57\u6BB5\uFF1A${g.join(", ")}`);if("_artifacts"in m&&!Array.isArray(m._artifacts))throw new O("invalid_control_field_type","Runtime Result CONTROL \u5757\u7684 _artifacts \u5FC5\u987B\u662F JSON \u6570\u7EC4");for(let h of["_decision","_meta"])if(h in m&&!Fe(m[h]))throw new O("invalid_control_field_type",`Runtime Result CONTROL \u5757\u7684 ${h} \u5FC5\u987B\u662F JSON \u5BF9\u8C61`);return{output:d,...m}}function jr(e){let t=new Map(Dt.map(n=>[n,[]]));for(let n of e.matchAll(zr))t.get(n.groups.marker).push({start:n.index,end:n.index+n[0].length});return t}function Gr(e){let t=e.match(/^(?:\r\n|\r|\n)/)?.[0]||"",n=t?e.slice(t.length):e;return t&&n.endsWith(t)?n.slice(0,-t.length):n}function Fe(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}var Ft=24e3,$t=8,Ht=50,vt=6e3,qr=new Set(["fail","failed","failure","error","errored","timeout","timed_out","cancelled","canceled","aborted"]),Jr=10*60*1e3,Wr=60*1e3,Vr=8,Xr=60*1e3,Yr=1,Zr=new Set(["agentId","taskId","executionId","sessionId","nodeId","targetCode","framework","workspace","instructions","runtimeMaxSessions"]),Qr=/(^|[_-])(token|secret|password|authorization|api[-_]?key|private[-_]?key|credential|cookie|jwt|access[-_]?token|refresh[-_]?token|service[-_]?token|execution[-_]?token)([_-]|$)/i;function ts(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:mt()}}}function E(e){return e==null||e===""?!1:typeof e=="string"?a(e)!=="":Array.isArray(e)?e.length>0:c(e)?Object.keys(e).length>0:!0}function Ve(e){let t=a(e).toLowerCase().replace(/[.。!!]+$/g,"").replace(/[\s-]+/g,"_");return qr.has(t)}function $(e,t){let n=T(e,t);return Number.isFinite(n)&&n>0?n:t}function Kt(e){let t=T(e,null);return Number.isFinite(t)&&t>0?t:null}function Z(e,t=!1){if(typeof e=="boolean")return e;let n=a(e).toLowerCase();return["true","1","yes","y","on"].includes(n)?!0:["false","0","no","n","off"].includes(n)?!1:t}function D(e){return a(e?.type||"echo")}function es(e){let t=D(e);return t==="acp"||t==="stdio-acp"||t==="openclaw"}function zt(e){if(c(e)){if(Object.prototype.hasOwnProperty.call(e,"releaseAfterPrompt"))return e.releaseAfterPrompt;if(Object.prototype.hasOwnProperty.call(e,"disposeAfterPrompt"))return e.disposeAfterPrompt}}function ns(e){let t=String(e||"");if(Qr.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 jt(e,t=0){if(e==null||typeof e=="number"||typeof e=="boolean")return e;if(typeof e=="string"){if(e.length<=vt)return e;let n=e.length-vt;return`${e.slice(0,vt)}... [truncated ${n} characters]`}if(t>=$t)return Array.isArray(e)?`[array truncated at depth ${$t}, items=${e.length}]`:c(e)?`[object truncated at depth ${$t}, keys=${Object.keys(e).length}]`:String(e);if(Array.isArray(e)){let n=e.slice(0,Ht).map(r=>jt(r,t+1));return e.length>Ht&&n.push(`[truncated ${e.length-Ht} items]`),n}if(c(e)){let n={};for(let[r,s]of Object.entries(e))n[r]=ns(r)?"[REDACTED]":jt(s,t+1);return n}return String(e)}var rs=new Set(["type","executionId","taskId","task","traceId","requestId","agentCode","stage","phase","nodeId","nodeType","capabilityCode","operationCode","outputType","artifactType","input","inputs","rejection","previous","artifactRefs","outputSchema","executionPolicy","resultContract"]);function ss(e){if(!c(e))return e;let t={};for(let n of rs)E(e[n])&&(t[n]=e[n]);return t}function is(e){if(!c(e))return e;let t={...e};return c(t.renderedPayload)&&(t.renderedPayload=ss(t.renderedPayload)),t}function os(e){let t=c(e)?e:{},n={};E(t.metadata)&&(n.metadata=is(t.metadata));for(let[r,s]of Object.entries(t))Zr.has(r)||r==="metadata"||E(s)&&(n[r]=s);return n}function as(e){let t=c(e)?e:{},n=c(t.metadata)?t.metadata:{},r=c(n.renderedPayload)?n.renderedPayload:{};return c(t.resultContract)?t.resultContract:c(r.resultContract)?r.resultContract:{}}function Xe(e){return a(as(e).kind).toLowerCase()==="decision"}function je(e){let t=c(e)?e:{},n=c(t.metadata)?t.metadata:{};return Kt(t.runtimeMaxSessions??n.runtimeMaxSessions)}function cs(e){return e?.dispatchFinalTextOnly===!0||e?.dispatchFinalOutputOnly===!0?!0:e?.dispatchFinalTextOnly===!1||e?.dispatchFinalOutputOnly===!1?!1:D(e)==="cli"}function Ge(e){let t=e?.dispatchReleaseAfterPrompt??e?.dispatchDisposeAfterPrompt;return Z(t,es(e))}function us(e,t){let n=c(e?.metadata)?{...e.metadata}:{},r=c(n._runtimeBridge)?{...n._runtimeBridge}:{},s=zt(r);return n._runtimeBridge={...r,promptKind:"dispatch",finalTextOnly:cs(t),releaseAfterPrompt:s===void 0?Ge(t):Z(s,Ge(t)),requiresRuntimeResult:Xe(e)},n}function ls(e){let t=os(e);if(!E(t))return"";let n=JSON.stringify(jt(t),null,2);if(n.length<=Ft)return n;let r=n.length-Ft;return`${n.slice(0,Ft)}
13
- ... [truncated ${r} characters]`}function Ye(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 ds(e){if(!c(e))return"";let t=c(e.update)?e.update:e;return a(t.sessionUpdate)}function fs(e){if(!Array.isArray(e))return"";let t=!1,n=[],r=[],s=[],i=()=>{n.length>0&&(r.push(n),n=[])};for(let u of e){let l=ds(u),d=Ye(u);if(!l){d&&s.push(d);continue}if(t=!0,l==="agent_message_chunk"){d&&n.push(d);continue}(l==="agent_thought_chunk"||l==="user_message_chunk"||l==="tool_call"||l==="tool_call_update"||l==="plan")&&i()}if(i(),!t)return Gt(s);let o=r[r.length-1]||[];return Gt(o)}function ps(e){return Array.isArray(e)?e.map(Ye).filter(t=>a(t)):[]}function ms(e){if(!c(e))return null;let t=c(e.update)?e.update:e;return a(t.sessionUpdate)!=="runtime_event"?null:c(t.event)?t.event:null}function hs(e){if(!c(e))return"";let t=c(e.payload)?e.payload:{},n=a(e.type),r=a(t.type);if(n==="event_msg"){if(r==="task_complete")return a(t.last_agent_message||t.message||t.output);if(r==="agent_message"){let s=a(t.phase||t.status||t.stage).toLowerCase();if(["final_answer","final","complete","completed","done"].includes(s))return a(t.message||t.text||t.content)}}return""}function gs(e){if(!Array.isArray(e))return"";for(let t=e.length-1;t>=0;t-=1){let n=hs(ms(e[t]));if(n)return n}return""}function Gt(e){let t="";for(let n of e){let r=String(n||"");if(r){if(!t)t=r;else if(r.startsWith(t))t=r;else if(!t.endsWith(r)){let s=Ke(r)&&!/[\r\n]$/.test(t)?`
14
- `:"";t+=`${s}${r}`}}}return t.trim()}function _s(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]===`
15
- `?1:0)).trim()}function qe(e){let t=String(e||"").trim();if(!t)return null;try{let n=JSON.parse(t);if(c(n)&&(Ze(n)||E(n._artifacts)||E(n.artifacts)||E(n._decision)||E(n._meta)))return n}catch{}return null}function ht(e){try{return ze(e)}catch{return null}}function Je(e){let t=String(e||"").trim();if(!t)return null;let n=ht(t);if(n)return n;let r=[...t.matchAll(/```(?:json)?\s*([\s\S]*?)```/gi)];for(let s=r.length-1;s>=0;s-=1){let i=qe(r[s][1]);if(i)return i}if(!t.endsWith("}"))return null;for(let s=t.lastIndexOf("{");s>=0;s=t.lastIndexOf("{",s-1)){let i=qe(t.slice(s));if(i)return i}return null}function Ts(e){let t=ps(e);for(let n=t.length-1;n>=0;n-=1){let r=ht(t[n]);if(r)return r}return ht(Gt(t))}function Ze(e){if(!c(e))return!1;if(E(e.output))return!0;for(let t of["content","text","message","summary"])if(a(e[t]))return!0;return!!(Ve(e.status)||a(e.error)||a(e.errorMessage))}function M(e){let t=c(e)?{...e}:{};return(!Array.isArray(t._artifacts)||t._artifacts.length===0)&&Array.isArray(t.artifacts)&&t.artifacts.length>0&&(t._artifacts=t.artifacts),delete t.artifacts,t}function ys(e){return c(e)?typeof(c(e._decision)?e._decision:c(e.decision)?e.decision:e).passed=="boolean":!1}function Ss(e){return c(e)?c(e._decision)&&typeof e._decision.passed=="boolean"?!0:ys(e.output):!1}function Bt(e,t,n){let r=c(e)?{...e}:{};if(!E(r.output)){for(let s of["summary","message","content","text"])if(a(r[s])){r.output=a(r[s]);break}}return!E(r.output)&&a(n)&&(r.output=a(n)),{...r,_meta:{...c(r._meta)?r._meta:{},runtimeOutputSource:t,requiredRuntimeResult:!0,finalMessagePreview:a(n).slice(0,1e3)}}}var Rs=["dataUrl","dataURL","contentDataUrl","contentDataURL","contentBase64","base64","data"];function We(e){if(!c(e))return"";let t=c(e.content)?e.content:{},n=c(e.metadata)?e.metadata:{};return a(e.fieldKey||e.field_key||t.fieldKey||n.fieldKey)}function ws(e,t){let n=c(e.content)?e.content:{},r=c(t.content)?t.content:{},s={...e,...t,content:{...n,...r},metadata:{...c(e.metadata)?e.metadata:{},...c(t.metadata)?t.metadata:{}}};for(let i of Rs)E(e[i])&&(s[i]=e[i]),E(n[i])&&(s.content[i]=n[i]);return s}function Es(e,t){let n=Array.isArray(e)?e.filter(c):[],r=Array.isArray(t)?t.filter(c):[];if(!n.length)return r;if(!r.length)return n;let s=[...n],i=new Map;for(let u=0;u<n.length;u+=1){let l=We(n[u]),d=i.get(l)||[];d.push(u),i.set(l,d)}let o=new Map;for(let u of r){let l=We(u),d=o.get(l)||0;o.set(l,d+1);let f=i.get(l)?.[d];f===void 0?s.push(u):s[f]=ws(s[f],u)}return s}function P(e,t,n){let r={...e,...t,_meta:{...c(e._meta)?e._meta:{},...c(t._meta)?t._meta:{},runtimeOutputSource:n}};return(Array.isArray(e._artifacts)||Array.isArray(t._artifacts))&&(r._artifacts=Es(e._artifacts,t._artifacts)),r}function Is(e,t,n={}){let r=a(n.promptKind),s=n.requiresRuntimeResult===!0,i=s||r==="dispatch",o=M(e),u=typeof o.output=="string"?ht(o.output):null;if(u)return P(o,M(u),"result_block");let l=gs(t),d=l?Je(l):null,f=i?Ts(t):null;if(Ze(o))return Ve(o.status)||a(o.error)||a(o.errorMessage)?o:r==="dispatch"&&d?P(o,M(d),"final_event"):r==="dispatch"&&f?P(o,M(f),"updates"):!s||Ss(o)?o:d?P(o,M(d),"final_event"):f?P(o,M(f),"updates"):Bt(o,"result",o.output);if(d)return P(o,M(d),"final_event");if(f)return P(o,M(f),"updates");if(l)return s?Bt(o,"final_event",l):{...o,output:l,_meta:{...c(o._meta)?o._meta:{},runtimeOutputSource:"final_event"}};let m=_s(fs(t));if(!m)return o;let g=Je(m);return g?P(o,M(g),"updates"):s?Bt(o,"updates",m):{...o,output:m,_meta:{...c(o._meta)?o._meta:{},runtimeOutputSource:"updates"}}}var gt=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=W(),this.cleanupTimer=null,this.startSessionCleanup()}targetFor(t){let n=a(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=D(t)==="openclaw"?$(this.config.openClawSessionIdleTtlMs,Xr):$(this.config.sessionIdleTtlMs,Jr);return $(t?.sessionIdleTtlMs??t?.idleTtlMs,r)}targetMaxSessions(t,n=null){let s=D(t)==="openclaw"?$(this.config.openClawMaxSessions,Yr):$(this.config.maxSessionsPerTarget,Vr),i=$(t?.maxSessions,s),o=Kt(n);return o?Math.max(i,o):i}targetReleaseAfterPrompt(t,n={}){let r=D(t),s=c(n?._runtimeBridge)?n._runtimeBridge:{},i=zt(s);return i!==void 0?Z(i,!1):Z(t?.releaseAfterPrompt??t?.disposeAfterPrompt,r==="openclaw")}promptReleaseAfterPrompt(t,n={}){let r=c(n?._runtimeBridge)?n._runtimeBridge:{},s=zt(r);return s!==void 0?Z(s,t.releaseAfterPrompt):t.releaseAfterPrompt}startSessionCleanup(){let t=$(this.config.sessionCleanupIntervalMs,Wr);t<=0||(this.cleanupTimer=setInterval(()=>{this.cleanupExpiredSessions().catch(n=>{p("warn","runtime-bridge","runtime session cleanup failed",{error:String(n)})})},t),this.cleanupTimer.unref?.())}sessionCountForTarget(t){let n=0;for(let r of this.sessions.values())r.targetCode===t&&(n+=1);return n}sessionCountForAgentTarget(t,n){let r=0;for(let s of this.sessions.values())s.agentId===t&&s.targetCode===n&&(r+=1);return r}idleTargetSessions(t){return[...this.sessions.entries()].filter(([,n])=>n.targetCode===t&&!n.busy).sort((n,r)=>(n[1].lastUsedAtMs||0)-(r[1].lastUsedAtMs||0))}idleAgentTargetSessions(t,n){return[...this.sessions.entries()].filter(([,r])=>r.agentId===t&&r.targetCode===n&&!r.busy).sort((r,s)=>(r[1].lastUsedAtMs||0)-(s[1].lastUsedAtMs||0))}async closeSession(t,n="session_closed"){let r=this.sessions.get(t);if(!r)return!1;try{await r.runtime?.stop?.(n)}catch(s){p("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}`),p("info","runtime-bridge","runtime session closed",{sessionId:r.sessionId,runtimeSessionId:r.runtimeSessionId,targetCode:r.targetCode,runtimeKind:r.runtimeKind,reason:n}),!0}async closeAllSessions(t="bridge_shutdown"){for(let n of[...this.sessions.keys()])await this.closeSession(n,t)}async stop(t="bridge_stop"){this.cleanupTimer&&clearInterval(this.cleanupTimer),this.cleanupTimer=null,await this.closeAllSessions(t)}async cleanupExpiredSessions(t=Date.now()){for(let[n,r]of[...this.sessions.entries()])r.busy||t-(r.lastUsedAtMs||r.createdAtMs||t)>r.idleTtlMs&&await this.closeSession(n,"idle_timeout")}async reserveTargetSlot(t,n,r={}){let s=a(r.agentId),i=Kt(r.runtimeMaxSessions);if(s&&i)for(;this.sessionCountForAgentTarget(s,t)>=i;){let u=this.idleAgentTargetSessions(s,t);if(!u.length){let l=new Error(`runtime agent session limit reached: ${s}`);throw l.code="RUNTIME_AGENT_SESSION_LIMIT",l}await this.closeSession(u[0][0],"agent_session_limit")}let o=this.targetMaxSessions(n,i);for(;this.sessionCountForTarget(t)>=o;){let u=this.idleTargetSessions(t);if(!u.length){let l=new Error(`runtime target session limit reached: ${t}`);throw l.code="RUNTIME_TARGET_SESSION_LIMIT",l}await this.closeSession(u[0][0],"target_session_limit")}}async createAgent(t){let n=a(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:a(t.framework||r),workspace:a(t.workspace),metadata:c(t.metadata)?t.metadata:{},createdAt:W(),runtimeKind:D(s),runtimeMaxSessions:je(t)};return this.agents.set(n,i),{agent:i}}runtimeFor(t,n){let{target:r}=this.targetFor(t.targetCode),s=D(r),i={onPermissionRequest:u=>this.requestPermission(u)},o={sessionPromptTimeoutMs:this.config.sessionPromptTimeoutMs};return s==="stdio-acp"||s==="acp"?new z(t,r,i,o):s==="openclaw"?new at(t,r,n,i,o):s==="cli"?new pt(t,r,o):new rt(t)}async prompt(t,n={}){let r=a(t.agentId),s=a(t.sessionId)||mt();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,runtimeMaxSessions:t.runtimeMaxSessions,metadata:t.metadata})).agent,o=je(t);o&&(i.runtimeMaxSessions=o);let u=a(t.workspace);u&&u!==i.workspace&&(i.workspace=u);let l=`${r}:${s}`;await this.cleanupExpiredSessions();let d=this.sessions.get(l);if(!d){let{code:g,target:h}=this.targetFor(i.targetCode);await this.reserveTargetSlot(g,h,{agentId:r,runtimeMaxSessions:i.runtimeMaxSessions});let y=this.runtimeFor(i,s),U=await y.sessionNew({cwd:i.workspace||process.cwd(),mcpServers:Array.isArray(t.mcpServers)?t.mcpServers:[],metadata:c(t.metadata)?t.metadata:{}}),x=Date.now();d={agentId:r,sessionId:s,runtime:y,targetCode:g,runtimeKind:D(h),runtimeSessionId:a(c(U)?U.sessionId:"")||s,idleTtlMs:this.targetIdleTtlMs(h),releaseAfterPrompt:this.targetReleaseAfterPrompt(h,t.metadata),createdAtMs:x,lastUsedAtMs:x,busy:!1,createdAt:W()},this.sessions.set(l,d),this.runtimeSessionIndex.set(`${r}:${d.runtimeSessionId}`,d)}if(d.busy){let g=new Error(`runtime session is already running: ${s}`);throw g.code="RUNTIME_SESSION_BUSY",g}d.busy=!0,d.lastUsedAtMs=Date.now();let f=[],m=g=>{let h=ts(g,s,d);f.push(h),n.onUpdate?.(h)};try{let g=await d.runtime.sessionPrompt({sessionId:d.runtimeSessionId,prompt:Array.isArray(t.prompt)?t.prompt:[],metadata:c(t.metadata)?t.metadata:{}},m),h=c(t.metadata)?t.metadata:{},y=c(h._runtimeBridge)?h._runtimeBridge:{},U=Is(g,f,y);return{sessionId:s,runtimeSessionId:d.runtimeSessionId,result:U,updates:f}}finally{d.busy=!1,d.lastUsedAtMs=Date.now(),this.promptReleaseAfterPrompt(d,c(t.metadata)?t.metadata:{})&&await this.closeSession(l,"release_after_prompt")}}async cancel(t){let n=a(t.agentId),r=a(t.sessionId),s=`${n}:${r}`,i=this.sessions.get(s);return i?(await i.runtime.sessionCancel({sessionId:i.runtimeSessionId}),await this.closeSession(s,"cancelled"),{cancelled:!0}):{cancelled:!1}}async dispatch(t,n={}){let r=a(t.agentId),s=a(t.taskId),i=a(t.executionId);if(!r||!s)throw Object.assign(new Error("agentId and taskId are required"),{status:400,code:"BAD_REQUEST"});let o=a(t.sessionId)||`dispatch-${i||s}`,u=a(t.instructions),l=ls(t),d=Xe(t),{target:f}=this.targetFor(t.targetCode||t.framework),m=[{type:"text",text:["Task dispatch received.",`taskId: ${s}`,i?`executionId: ${i}`:"",u?`instructions: ${u}`:"",l?"orchaContext:":"",l,l?"Use orchaContext as the source of truth for upstream outputs, review reports, artifacts, and workflow metadata.":"","Follow the execution protocol in instructions exactly.","When embedding a generated artifact in final Markdown, use the Orcha artifact placeholder as the link target: orcha-artifact://<fieldKey>/<index>.","Example: use ![illustration](orcha-artifact://image/0) for the first generated image artifact.","Do not use local filesystem paths, file:// URLs, or data: URLs in final Markdown; Orcha replaces artifact placeholders after ingestion.",d?`For decision results, put the raw report between ${$e} and ${He}.`:"",d?`Then put a JSON object containing _decision between ${ve} and ${Be}.`:"",d?"Do not JSON-escape the report. Keep output out of the CONTROL JSON, and put every protocol marker on its own line.":"","Return only the final answer required by that protocol.","Do not include process notes, logs, or explanations."].filter(Boolean).join(`
16
- `)}];return this.prompt({...t,agentId:r,sessionId:o,prompt:m,metadata:us(t,f)},n)}async requestPermission({agent:t,runtimeSessionId:n,request:r,emitUpdate:s}){let i=mt(),u=this.runtimeSessionIndex.get(`${t.agentId}:${n}`)?.sessionId||n||mt(),l={permissionId:i,agentId:t.agentId,sessionId:u,runtimeSessionId:n,request:c(r)?r:{},status:"pending",createdAt:W()};return s?.({sessionId:n,update:{sessionUpdate:"permission_request",permission:l}}),await new Promise(d=>{let f=T(r?.timeoutMs,this.config.permissionRequestTimeoutMs),m=setTimeout(()=>{this.pendingPermissions.delete(i),d({permissionId:i,outcome:"denied",response:{reason:"permission request timed out"}})},f);this.pendingPermissions.set(i,{timer:m,resolve:d,permission:l})})}async respondPermission(t){let n=a(t.permissionId),r=this.pendingPermissions.get(n),s=a(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:a(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:K,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 xs from"node:http";import Os from"node:https";import{randomBytes as Qe}from"node:crypto";var j=1,H=3,Cs=1e4,_t=class{constructor(t,n={}){this.url=t,this.readyState=0,this.socket=null,this.request=null,this.buffer=Buffer.alloc(0),this.listeners=new Map,this.connectTimeoutMs=As(n.connectTimeoutMs,Cs),this.connectTimer=null,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:"?Os:xs,r=Qe(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"}});this.request=s,this.startConnectTimer(s),s.on("upgrade",(i,o,u)=>{if(this.clearConnectTimer(),this.readyState===H){o.destroy();return}this.socket=o,this.readyState=j,o.on("data",l=>this.onData(l)),o.on("close",()=>this.onClose()),o.on("error",l=>{this.readyState!==H&&this.emit("error",{error:l,message:l.message,type:"error"}),this.onClose()}),u?.length&&this.onData(u),this.emit("open")}),s.on("response",i=>{this.clearConnectTimer(),this.emit("error",{message:`websocket upgrade failed: HTTP ${i.statusCode}`,type:"error"}),i.resume(),this.onClose()}),s.on("error",i=>{this.clearConnectTimer(),this.readyState!==H&&this.emit("error",{error:i,message:i.message,type:"error"}),this.onClose()}),s.end()}startConnectTimer(t){this.connectTimeoutMs<=0||(this.connectTimer=setTimeout(()=>{if(this.readyState===j||this.readyState===H)return;let n=`websocket connect timeout after ${this.connectTimeoutMs}ms`;this.emit("error",{message:n,type:"timeout"}),this.onClose(),t.destroy(new Error(n))},this.connectTimeoutMs),this.connectTimer.unref?.())}clearConnectTimer(){this.connectTimer&&(clearTimeout(this.connectTimer),this.connectTimer=null)}send(t){!this.socket||this.readyState!==j||this.socket.write(qt(1,Buffer.from(String(t),"utf8")))}close(){if(this.readyState!==H){if(this.clearConnectTimer(),!this.socket){this.request?.destroy(),this.onClose();return}try{this.readyState===j&&this.socket.write(qt(8,Buffer.alloc(0))),this.socket.end()}catch{this.socket.destroy()}this.onClose()}}onClose(){this.readyState!==H&&(this.clearConnectTimer(),this.readyState=H,this.request=null,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,o=r&127,u=2;if(o===126){if(this.buffer.length<u+2)return;o=this.buffer.readUInt16BE(u),u+=2}else if(o===127){if(this.buffer.length<u+8)return;let f=this.buffer.readUInt32BE(u),m=this.buffer.readUInt32BE(u+4);o=f*2**32+m,u+=8}let l=u;if(i&&(u+=4),this.buffer.length<u+o)return;let d=this.buffer.subarray(u,u+o);if(i){let f=this.buffer.subarray(l,l+4);d=Buffer.from(d.map((m,g)=>m^f[g%4]))}this.buffer=this.buffer.subarray(u+o),s===1?this.emit("message",{data:d.toString("utf8")}):s===8?this.close():s===9&&this.socket?.write(qt(10,d))}}};function As(e,t){let n=Number.parseInt(String(e??""),10);return Number.isFinite(n)&&n>=0?n:t}function qt(e,t){let n=t.length,r=2;n>=126&&n<=65535?r+=2:n>65535&&(r+=8);let s=Qe(4),i=Buffer.alloc(r+4+n);i[0]=128|e;let o=2;n<126?i[1]=128|n:n<=65535?(i[1]=254,i.writeUInt16BE(n,o),o+=2):(i[1]=255,i.writeUInt32BE(Math.floor(n/2**32),o),i.writeUInt32BE(n>>>0,o+4),o+=8),s.copy(i,o),o+=4;for(let u=0;u<n;u+=1)i[o+u]=t[u]^s[u%4];return i}function Ns(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 Ms(e){return Object.entries(e||{}).map(([t,n])=>({targetCode:t,targetName:a(n?.name||n?.targetName||t),targetType:a(n?.type||"echo"),status:"available",metadata:c(n)?n:{}}))}var Tt=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(){if(this.stopped)return;let t=Ns(this.config.orchaUrl),n=new _t(t,{connectTimeoutMs:this.config.connectTimeoutMs});this.ws=n,n.addEventListener("open",()=>{if(this.ws!==n||this.stopped){n.close();return}this.authenticate(n)}),n.addEventListener("message",r=>this.handleMessage(r.data,n)),n.addEventListener("close",()=>this.scheduleReconnect("close",n)),n.addEventListener("error",r=>{p("warn","orcha-client","runtime node websocket error",{error:String(r?.message||r?.type||r)})})}authenticate(t=this.ws){this.send({type:"runtime_node.authenticate",token:this.config.nodeToken,nodeId:this.config.nodeId,nodeName:this.config.nodeName,version:K,protocolVersion:"orcha-runtime-node.v1",defaultTargetCode:this.config.defaultTargetCode,targets:Ms(this.config.targets)},t)}scheduleReconnect(t,n=this.ws){n&&this.ws!==n||(this.connected=!1,n&&this.ws===n&&(this.ws=null),!this.stopped&&(this.reconnectTimer||(p("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,n=this.ws){if(n&&this.ws!==n)return;let r;try{r=JSON.parse(String(t))}catch(s){p("warn","orcha-client","invalid Orcha websocket frame",{error:String(s)});return}if(c(r)){if(r.type==="runtime_node.authenticated"){if(n&&this.ws!==n)return;this.connected=!0,p("info","orcha-client","runtime node authenticated",{nodeId:this.config.nodeId,connectionId:r.connectionId});return}if(r.type==="orcha.runtime.request"){await this.handleRequest(r);return}r.type==="runtime_node.ping"&&this.send({type:"runtime_node.pong",ts:new Date().toISOString()})}}async handleRequest(t){let n=a(t.id),r=a(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,n=this.ws){return!n||n!==this.ws||n.readyState!==j?!1:(n.send(JSON.stringify(t)),!0)}};import{existsSync as Us,readFileSync as bs}from"node:fs";import{resolve as tn}from"node:path";var ks=/^[A-Za-z_][A-Za-z0-9_]*$/;function en(e=process.env,t=process.cwd()){let n=a(e.ORCHA_RUNTIME_ENV_FILE),r=n?tn(t,n):tn(t,".env");if(!Us(r))return n&&p("warn","config","runtime env file not found",{path:r}),{loaded:!1,path:r,keys:[]};let s=[],i=bs(r,"utf8");for(let o of i.split(/\r?\n/)){let u=Ps(o);if(!u)continue;let[l,d]=u;Object.prototype.hasOwnProperty.call(e,l)||(e[l]=d,s.push(l))}return p("info","config","runtime env file loaded",{path:r,keyCount:s.length}),{loaded:!0,path:r,keys:s}}function nn(e=process.env){return{mode:a(e.ORCHA_RUNTIME_MODE||(e.ORCHA_RUNTIME_ORCHA_URL?"node":"server")),host:e.ORCHA_RUNTIME_BRIDGE_HOST||"127.0.0.1",port:T(e.ORCHA_RUNTIME_BRIDGE_PORT,5588),token:e.ORCHA_RUNTIME_BRIDGE_TOKEN||"",orchaUrl:a(e.ORCHA_RUNTIME_ORCHA_URL),nodeToken:e.ORCHA_RUNTIME_NODE_TOKEN||e.ORCHA_RUNTIME_BRIDGE_TOKEN||"",nodeId:a(e.ORCHA_RUNTIME_NODE_ID||e.HOSTNAME||"local-runtime-node"),nodeName:a(e.ORCHA_RUNTIME_NODE_NAME||e.ORCHA_RUNTIME_NODE_ID||e.HOSTNAME||"Local Runtime Node"),reconnectMs:T(e.ORCHA_RUNTIME_RECONNECT_MS,3e3),connectTimeoutMs:T(e.ORCHA_RUNTIME_CONNECT_TIMEOUT_MS||e.ORCHA_RUNTIME_WS_CONNECT_TIMEOUT_MS,1e4),defaultTargetCode:e.ORCHA_RUNTIME_DEFAULT_TARGET||"echo",requestLimitBytes:T(e.ORCHA_RUNTIME_REQUEST_LIMIT_BYTES,1048576),sessionPromptTimeoutMs:T(e.ORCHA_RUNTIME_SESSION_PROMPT_TIMEOUT_MS,36e5),permissionRequestTimeoutMs:T(e.ORCHA_RUNTIME_PERMISSION_TIMEOUT_MS,3e5),sessionIdleTtlMs:T(e.ORCHA_RUNTIME_SESSION_IDLE_TTL_MS,6e5),sessionCleanupIntervalMs:T(e.ORCHA_RUNTIME_SESSION_CLEANUP_INTERVAL_MS,6e4),maxSessionsPerTarget:T(e.ORCHA_RUNTIME_MAX_SESSIONS_PER_TARGET,8),openClawSessionIdleTtlMs:T(e.ORCHA_RUNTIME_OPENCLAW_SESSION_IDLE_TTL_MS,6e4),openClawMaxSessions:T(e.ORCHA_RUNTIME_OPENCLAW_MAX_SESSIONS,1),targets:Ls(e.ORCHA_RUNTIME_TARGETS_JSON||"")}}function Ls(e){if(!a(e))return{};try{let t=JSON.parse(e);if(c(t))return t}catch(t){p("warn","config","invalid ORCHA_RUNTIME_TARGETS_JSON",{error:String(t)})}return{}}function Ps(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(!ks.test(s))return null;let i=Ds(n.slice(r+1).trim());return[s,i]}function Ds(e){if(!e)return"";let t=e[0];if((t==='"'||t==="'")&&e.endsWith(t)){let n=e.slice(1,-1);return t==='"'?Fs(n):n}return $s(e).trim()}function Fs(e){return e.replaceAll("\\n",`
17
- `).replaceAll("\\r","\r").replaceAll("\\t"," ").replaceAll('\\"','"').replaceAll("\\\\","\\")}function $s(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 Hs}from"node:http";function yt(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 v(e={}){return{ok:!0,...e}}function Jt(e,t,n){return{ok:!1,error:{code:e,message:t,...n===void 0?{}:{detail:n}}}}async function rn(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 sn(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 on(e,t){let n={"GET /health":async()=>v(t.health()),"POST /agents/create":async r=>v(await t.createAgent(r)),"POST /agents/dispatch":async r=>v(await t.dispatch(r)),"POST /sessions/prompt":async r=>v(await t.prompt(r)),"POST /sessions/cancel":async r=>v(await t.cancel(r)),"POST /permissions/respond":async r=>v(await t.respondPermission(r))};return Hs(async(r,s)=>{let i=new URL(r.url||"/",`http://${r.headers.host||`${e.host}:${e.port}`}`),o=`${r.method||"GET"} ${i.pathname}`,u=n[o];if(!u){yt(s,404,Jt("NOT_FOUND",`No route for ${o}`));return}try{sn(r,e.token);let l=r.method==="GET"?{}:await rn(r,e.requestLimitBytes);yt(s,200,await u(l))}catch(l){let d=l.status||500,f=l.code||"BRIDGE_INTERNAL";yt(s,d,Jt(f,l.message||String(l)))}})}var Js=qs(import.meta.url),Ws=".orcha-runtime-bridge.pid",Vs=".orcha-runtime-bridge.log",Xs=3,Ys=36e5,{command:Zs,options:gn}=ni(process.argv.slice(2));ri(gn);en();var Qs=nn();await ti(Zs,Qs,gn);async function ti(e,t,n){switch(e){case"run":case"foreground":cn(t);return;case"start":if(n.foreground){cn(t);return}ln();return;case"reload":case"restart":await dn({quiet:!0}),ln();return;case"stop":await dn();return;case"status":ei();return;case"help":case"--help":case"-h":ai();return;default:throw new Error(`Unknown command: ${e}`)}}function cn(e){si();let t=new gt(e);if(e.mode==="server"){let r=on(e,t);un({bridge:t,server:r}),r.listen(e.port,e.host,()=>{p("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 Tt(e,t);un({bridge:t,client:n}),n.start(),p("info","runtime-bridge","Orcha runtime node started",{nodeId:e.nodeId,nodeName:e.nodeName,orchaUrl:e.orchaUrl,targets:Object.keys(t.targets)})}function un({bridge:e,client:t,server:n}){let r=!1,s=i=>{if(r)return;r=!0;let o=Number(e?.sessions?.size||0)>0;p("info","runtime-bridge","runtime bridge shutting down",{signal:i});try{t?.stop?.()}catch(u){p("warn","runtime-bridge","runtime client stop failed",{error:String(u)})}Promise.resolve(e?.stop?.(`process_${String(i||"shutdown").toLowerCase()}`)).catch(u=>{p("warn","runtime-bridge","runtime bridge stop failed",{error:String(u)})}).finally(()=>{try{n?.close?.()}catch(u){p("warn","runtime-bridge","runtime server close failed",{error:String(u)})}}),setTimeout(()=>process.exit(0),o?8500:200)};process.once("SIGTERM",()=>s("SIGTERM")),process.once("SIGINT",()=>s("SIGINT"))}function ln(){let e=Zt(),t=_n(),n=Qt(e);if(n&&G(n)){console.log(JSON.stringify({status:"already_running",pid:n,pidFile:e,logFile:t}));return}n&&Xt(e),pn(e),pn(t),Vt(t);let r=zs(t,"a"),s={...process.env,ORCHA_RUNTIME_PID_FILE:e,ORCHA_RUNTIME_LOG_FILE:t},i=vs(process.execPath,[Js,"run"],{cwd:process.cwd(),detached:!0,env:s,stdio:["ignore",r,r]});i.unref(),Bs(r),hn(e,`${i.pid}
18
- `),console.log(JSON.stringify({status:"started",pid:i.pid,pidFile:e,logFile:t}))}async function dn({quiet:e=!1}={}){let t=Zt(),n=Qt(t);if(!n){e||console.log(JSON.stringify({status:"not_running",pidFile:t}));return}if(!G(n)){Xt(t),e||console.log(JSON.stringify({status:"not_running",pid:n,pidFile:t}));return}process.kill(n,"SIGTERM"),!await fn(n,1e4)&&G(n)&&(process.kill(n,"SIGKILL"),await fn(n,3e3)),Xt(t),e||console.log(JSON.stringify({status:"stopped",pid:n,pidFile:t}))}function ei(){let e=Zt(),t=_n(),n=Qt(e),r=!!(n&&G(n));console.log(JSON.stringify({status:r?"running":"not_running",running:r,pid:r?n:null,pidFile:e,logFile:t}))}function ni(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 ri(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 Zt(){return Yt(process.cwd(),process.env.ORCHA_RUNTIME_PID_FILE||Ws)}function _n(){return Yt(process.cwd(),process.env.ORCHA_RUNTIME_LOG_FILE||Vs)}function si(){let e=process.env.ORCHA_RUNTIME_LOG_FILE;if(!e)return;let t=Tn();if(t<=0)return;let n=Yt(process.cwd(),e);Vt(n,t);let r=oi();r<=0||setInterval(()=>Vt(n,t),r).unref()}function Vt(e,t=Tn()){if(t<=0||!mn(e))return;let n=0,r="";try{if(n=an(e).size,n<=0)return;r=Wt(e,"utf8")}catch(d){p("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/),o=[],u=0;for(let d of i)d&&(ii(d,s)?o.push(d):u+=1);if(u===0)return;let l="";try{an(e).size>n&&(l=Wt(e,"utf8").slice(r.length));let f=[...o,...l.split(/\r?\n/).filter(Boolean)].join(`
10
+ ${s}`:s;Rr(t,r,n,d,s)&&(o=1,c=1)}return s&&i&&(t.finalTextSeen=!0),_r(t,gr(e,t.artifactOptions)),(vs(e)||Fs(e)||Hs(e)||i)&&n({sessionId:r,update:{sessionUpdate:"runtime_event",event:Tr(e)}}),{textCount:o,finalTextCount:c,thoughtCount:l}}function Qt(e,t,r,n,s=Date.now()){if(!t)return{artifactCount:0,transcriptCount:0,textCount:0,finalTextCount:0,thoughtCount:0};let i=e.artifacts.size,o=0,c=0,l=0,d=0,f=Ls(t,r,s);if(f){let p=Math.min(t.processedLines.get(f.path)||0,f.events.length),g=e.artifacts.size;for(let m of f.events.slice(p)){let E=$s(m,e,r,n);c+=E.textCount,l+=E.finalTextCount,d+=E.thoughtCount}t.processedLines.set(f.path,f.events.length),(f.events.length>p||e.artifacts.size>g)&&(o=1)}return{artifactCount:e.artifacts.size-i,transcriptCount:o,textCount:c,finalTextCount:l,thoughtCount:d}}function Bs(e,{remove:t=!0}={}){if(!e||!lr(e))return"";try{return fr(e,"utf8").trim()}catch{return""}finally{t&&Ot(e)}}function Ot(e){if(e)try{Qn(e)}catch{}}function qs(e,t){return{artifactCount:(e?.artifactCount||0)+(t?.artifactCount||0),transcriptCount:(e?.transcriptCount||0)+(t?.transcriptCount||0),textCount:(e?.textCount||0)+(t?.textCount||0),finalTextCount:(e?.finalTextCount||0)+(t?.finalTextCount||0),thoughtCount:(e?.thoughtCount||0)+(t?.thoughtCount||0)}}function js(e){return new Promise(t=>setTimeout(t,e))}function Gs(e,t,r,n){return n?(e.finalTextSeen=!0,e.emittedTexts.has(n)||(e.emittedTexts.add(n),r({sessionId:t,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:n}}})),!0):!1}async function Ks(e,t,r,n,s,i){let o=Qt(e,t,r,n,Date.now()),c=()=>Gs(e,r,n,Bs(s,{remove:!1}));if(c()||e.finalTextSeen)return Ot(s),o;let l=hs(i);if(l<=0||!t&&!s)return Ot(s),o;let d=Date.now()+l,f=Math.min(yr(i),100);for(;!e.finalTextSeen&&Date.now()<d&&(await js(Math.min(f,Math.max(0,d-Date.now()))),o=qs(o,Qt(e,t,r,n,Date.now())),!c()););return Ot(s),o}var Ct=class{constructor(t,r,n={}){this.agent=t,this.target=r,this.options=n,this.active=new Map}async sessionNew(){return{sessionId:`cli-${this.agent.agentId}-${Z()}`}}async sessionPrompt(t,r,n){let s=Date.now(),i=a(this.target.command);if(!i)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);let o=a(t.sessionId)||Z(),c=Tt(t.prompt),l=a(this.target.promptMode||"stdin"),d=this.buildArgs(l,c),f=a(this.target.cwd)||this.agent.workspace||process.cwd(),p=typeof this.options.prepareLaunch=="function",m=ps(i,d,this.target)?p?`/tmp/orcha-runtime-last-message-${Z()}.txt`:L(pr(),`orcha-runtime-last-message-${Z()}.txt`):"";m&&d.push("--output-last-message",m);let E={...u(this.target.env)?this.target.env:{},...l==="env"?{ORCHA_RUNTIME_PROMPT:c}:{},ORCHA_AGENT_ID:this.agent.agentId,ORCHA_SESSION_ID:o},O=p?await this.options.prepareLaunch({command:i,args:d,cwd:f,environment:E}):{command:i,args:d,cwd:f,environment:{...process.env,...E},cleanup:async()=>{}},N=p?ws(O):Ss(this.target,o),_=N.root,y=Os(this.target,_,O),S=ms(i,this.target),A={...this.target,targetCode:this.agent.targetCode,cwd:f,...p?{codexHome:L(O.homeDirectory,".codex")}:{}},W=S?Cs(A,s):new Set,gt=p&&m?L(O.tempDirectory,m.slice(5)):m,J=T(this.target.timeoutMs||this.target.sessionPromptTimeoutMs,T(this.options.sessionPromptTimeoutMs,es));p||(O.environment.ORCHA_RUNTIME_ARTIFACT_DIR=_);let I=ur(O.command,O.args,{cwd:O.cwd,env:O.environment,stdio:["pipe","pipe","pipe"],detached:process.platform!=="win32",windowsHide:!0});this.active.set(o,I),h("info","runtime.cli","runtime prompt started",{target:this.agent.targetCode,sessionId:o,pid:I.pid,timeoutMs:J,isolation:O.isolation});let $e="",Bt=a(this.target.outputMode||"text"),b={artifacts:new Map,emittedTexts:new Set,emittedThoughtTexts:new Set,value:"",artifactOptions:y,finalTextSeen:!1,finalTextOnly:ys(t,this.target),emitThoughtChunks:_s(t,this.target),terminalOutcome:null,terminalProtocol:ls(this.target),emitTerminal:null},qt=S?Es(A,c,s,W):null;return I.stdout.setEncoding("utf8"),I.stdout.on("data",X=>this.handleStdout(X,Bt,b,o,r)),I.stderr.setEncoding("utf8"),I.stderr.on("data",X=>{$e+=X,this.target.emitStderr===!0&&r({sessionId:o,update:{sessionUpdate:"runtime_stderr_chunk",content:{type:"text",text:X}}})}),l==="stdin"?I.stdin.end(c):I.stdin.end(),await new Promise((X,jt)=>{let nt=!1,Be=!1,_t=null,st=null,Gt=qt&&gs(this.target,t)?setInterval(()=>{try{Qt(b,qt,o,r)}catch(w){h("warn","runtime.cli","codex transcript stream poll failed",{target:this.agent.targetCode,sessionId:o,error:String(w?.message||w)})}},yr(this.target)):null;Gt?.unref?.();let qe=setTimeout(()=>{Be=!0,h("warn","runtime.cli","runtime prompt timed out; terminating child",{target:this.agent.targetCode,sessionId:o,pid:I.pid,timeoutMs:J}),xt(I,"SIGTERM"),_t=setTimeout(()=>{h("warn","runtime.cli","runtime prompt force killing child",{target:this.agent.targetCode,sessionId:o,pid:I.pid}),xt(I,"SIGKILL")},mr),_t.unref?.(),it(Object.assign(new Error(`runtime CLI timed out after ${J}ms`),{code:"RUNTIME_CLI_TIMEOUT"}))},J);qe.unref?.();let je=async()=>{clearTimeout(qe),st&&clearTimeout(st),Gt&&clearInterval(Gt),_t&&!Be&&clearTimeout(_t),Is(N,{target:this.agent.targetCode,sessionId:o}),this.active.delete(o),b.emitTerminal=null,await O.cleanup?.()},Rn=w=>{nt||(nt=!0,je().then(()=>X(w),jt))},it=w=>{nt||(nt=!0,je().then(()=>jt(w),v=>{h("warn","runtime.cli","sandbox launch cleanup failed",{target:this.agent.targetCode,sessionId:o,error:String(v?.message||v)}),jt(w)}))};b.emitTerminal=w=>{let v={...u(w.result)?w.result:{},_artifacts:[...b.artifacts.values()]};try{n?.({...w,result:v})}catch(j){h("warn","runtime.cli","runtime terminal listener failed",{target:this.agent.targetCode,sessionId:o,error:String(j?.message||j)})}let k=Math.max(0,T(this.target.terminalExitGraceMs,as));st=setTimeout(()=>{st=null,!(nt||this.active.get(o)!==I)&&(h("warn","runtime.cli","runtime stayed alive after terminal event; terminating child",{target:this.agent.targetCode,sessionId:o,pid:I.pid,terminalProtocol:b.terminalProtocol,graceMs:k}),Jt(I))},k),st.unref?.()},I.on("error",w=>{h("warn","runtime.cli","runtime child error",{target:this.agent.targetCode,sessionId:o,pid:I.pid,error:String(w?.message||w)}),it(w)}),I.on("exit",(w,v)=>{(async()=>{Bt==="json-lines"&&b.value.trim()&&this.handleStdout(`
11
+ `,Bt,b,o,r);let k=await Ks(b,qt,o,r,gt,this.target);(k.artifactCount>0||k.textCount>0||k.thoughtCount>0)&&h("info","runtime.cli","codex transcript updates collected",{target:this.agent.targetCode,sessionId:o,artifactCount:k.artifactCount,textCount:k.textCount,finalTextCount:k.finalTextCount,thoughtCount:k.thoughtCount,transcriptCount:k.transcriptCount});let j=$e.trim();if(j&&h("debug","runtime.cli","runtime stderr",{target:this.agent.targetCode,sessionId:o,stderr:j}),h("info","runtime.cli","runtime prompt finished",{target:this.agent.targetCode,sessionId:o,pid:I.pid,exitCode:w,signal:v,artifactCount:b.artifacts.size,finalTextSeen:b.finalTextSeen}),b.terminalOutcome?.status==="failed"){it(b.terminalOutcome.error);return}if(w!==0&&b.terminalOutcome?.status!=="completed"){let En=Object.assign(new Error(`runtime CLI exited with code ${w??"unknown"}${v?` (${v})`:""}`),{code:"RUNTIME_CLI_EXIT_NONZERO",exitCode:w,signal:v});it(En);return}Rn({stopReason:"end_turn",exitCode:w,signal:v,_artifacts:[...b.artifacts.values()],...j?{stderr:j}:{}})})().catch(it)})})}buildArgs(t,r){let n=C(this.target.args);return t==="args"?[...n,r]:n}handleStdout(t,r,n,s,i){if(r!=="json-lines"){i({sessionId:s,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:t}}});return}n.value+=t;let o=n.value.split(/\r?\n/);n.value=o.pop()||"";for(let c of o){let l=c.trim();if(l)try{let d=JSON.parse(l);_r(n,gr(d,n.artifactOptions)),i({sessionId:s,update:{sessionUpdate:"runtime_event",event:Tr(d)}});let f=hr(d),p=te(d);f&&n.emitThoughtChunks&&!p&&fs(d)?Er(n,s,i,f):f&&Rs(n,p)&&Rr(n,s,i,f),f&&p&&(n.finalTextSeen=!0);let g=ds(d,n.terminalProtocol);g&&!n.terminalOutcome&&(g.status==="failed"||n.finalTextSeen||n.artifacts.size>0)&&(n.terminalOutcome=g,n.emitTerminal?.(g))}catch{i({sessionId:s,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`${c}
12
+ `}}})}}}async sessionCancel(t){let r=a(t.sessionId),n=this.active.get(r);return n?(h("info","runtime.cli","cancelling runtime child",{target:this.agent.targetCode,sessionId:r,pid:n.pid}),Jt(n),{ok:!0,cancelled:!0}):{ok:!0,cancelled:!1}}stop(t="stop"){for(let[r,n]of this.active.entries())h("info","runtime.cli","stopping runtime child",{target:this.agent.targetCode,sessionId:r,pid:n.pid,reason:t}),Jt(n);this.active.clear()}};var re="ORCHA_RUNTIME_OUTPUT_START",ne="ORCHA_RUNTIME_OUTPUT_END",se="ORCHA_RUNTIME_CONTROL_START",ie="ORCHA_RUNTIME_CONTROL_END",Ar=re,Cr=ne,Nr=se,br=ie,oe=[re,ne,se,ie],Vs=new Set(["_artifacts","_decision","_meta"]),zs=new RegExp(`(?:^|(?<=[\\r\\n]))[ \\t]*(?<marker>${oe.join("|")})[ \\t]*(?=\\r\\n?|\\n|$)`,"g"),D=class extends Error{constructor(t,r){super(r),this.name="RuntimeResultProtocolError",this.code=t}};function Mr(e){let t=typeof e=="string"?e.trimStart():"";return oe.some(r=>t.startsWith(r))}function ae(e){if(typeof e!="string")return null;let t=e,r=Ws(t);if(![...r.values()].some(m=>m.length>0))return null;let n=[],s=[];for(let[m,E]of r)E.length===0?n.push(m):E.length>1&&s.push(m);if(n.length>0||s.length>0){let m=[];throw n.length>0&&m.push(`\u7F3A\u5C11 ${n.join(", ")}`),s.length>0&&m.push(`\u91CD\u590D ${s.join(", ")}`),new D("invalid_markers",`Runtime Result \u534F\u8BAE\u6807\u8BB0\u4E0D\u5B8C\u6574\uFF1A${m.join("\uFF1B")}`)}let i=r.get(re)[0],o=r.get(ne)[0],c=r.get(se)[0],l=r.get(ie)[0];if(!(i.end<=o.start&&o.end<=c.start&&c.end<=l.start))throw new D("invalid_marker_order","Runtime Result \u534F\u8BAE\u6807\u8BB0\u987A\u5E8F\u9519\u8BEF\uFF1A\u5FC5\u987B\u5148\u8F93\u51FA OUTPUT \u5757\uFF0C\u518D\u8F93\u51FA CONTROL \u5757");let d=Js(t.slice(i.end,o.start));if(!d.trim())throw new D("empty_output","Runtime Result OUTPUT \u5757\u4E0D\u80FD\u4E3A\u7A7A");let f=t.slice(c.end,l.start).trim();if(!f)throw new D("empty_control","Runtime Result CONTROL \u5757\u4E0D\u80FD\u4E3A\u7A7A");let p;try{p=JSON.parse(f)}catch(m){throw new D("invalid_control_json",`Runtime Result CONTROL \u5757\u4E0D\u662F\u5408\u6CD5 JSON\uFF1A${String(m?.message||m)}`)}if(!xr(p))throw new D("invalid_control_type","Runtime Result CONTROL \u5757\u5FC5\u987B\u662F JSON \u5BF9\u8C61");let g=Object.keys(p).filter(m=>!Vs.has(m)).sort();if(g.length>0)throw new D("invalid_control_keys",`Runtime Result CONTROL \u5757\u5305\u542B\u975E\u6807\u51C6\u5B57\u6BB5\uFF1A${g.join(", ")}`);if("_artifacts"in p&&!Array.isArray(p._artifacts))throw new D("invalid_control_field_type","Runtime Result CONTROL \u5757\u7684 _artifacts \u5FC5\u987B\u662F JSON \u6570\u7EC4");for(let m of["_decision","_meta"])if(m in p&&!xr(p[m]))throw new D("invalid_control_field_type",`Runtime Result CONTROL \u5757\u7684 ${m} \u5FC5\u987B\u662F JSON \u5BF9\u8C61`);return{output:d,...p}}function Ws(e){let t=new Map(oe.map(r=>[r,[]]));for(let r of e.matchAll(zs))t.get(r.groups.marker).push({start:r.index,end:r.index+r[0].length});return t}function Js(e){let t=e.match(/^(?:\r\n|\r|\n)/)?.[0]||"",r=t?e.slice(t.length):e;return t&&r.endsWith(t)?r.slice(0,-t.length):r}function xr(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}import{createHash as Xs}from"node:crypto";var Ys="orcha.goal-contract/v1",Qs=new Set(["complete","completed","done","ok","passed","success","succeeded"]),Zs=new Set(["aborted","blocked","cancelled","canceled","denied","error","failed","failure","timeout","timed_out"]),ti=new Map([["exec_command","run_command"],["local_shell_call","run_command"],["run_command","run_command"],["apply_patch","apply_patch"],["read_file","read_file"],["list_files","list_files"],["plugin_operation","plugin_operation"]]);function de(e){return Xs("sha256").update(F(e)).digest("hex")}function Pr(e){if(!Lr(e))return"";let t=["The following Orcha goal contract is immutable for this turn. Do not narrow its outcome or constraints.",`<goal_contract>${JSON.stringify(e)}</goal_contract>`];return e.verificationPlan?.required===!0&&t.push("Every verification check must be satisfied by a real successful tool call from one of its toolNames.","A final text claim is not verification; missing or failed tool evidence prevents completion."),t.join(`
13
+ `)}function kr(e,t,r=""){if(!Lr(e))return e==null?null:{required:!0,status:"failed",outcome:a(e?.outcome),goalContractHash:"",checks:[],errorCode:"invalid_goal_contract"};let n=de(e),s=e.verificationPlan.required===!0;if(a(r)&&a(r)!==n)return{required:s,status:"failed",outcome:e.outcome,goalContractHash:n,checks:[],errorCode:"goal_contract_hash_mismatch"};if(!s)return{required:!1,status:"not_required",outcome:e.outcome,goalContractHash:n,checks:[]};let i=ei(t),o=e.verificationPlan.checks.map(l=>ci(l,i));return{required:!0,status:o.some(l=>l.status==="failed")?"failed":o.some(l=>l.status==="missing")?"missing":"passed",outcome:e.outcome,goalContractHash:n,checks:o}}function Lr(e){if(!u(e)||e.schemaVersion!==Ys||!a(e.outcome))return!1;let t=e.verificationPlan;if(!u(t)||typeof t.required!="boolean"||!Array.isArray(t.checks)||t.required&&t.checks.length===0)return!1;let r=new Set;for(let n of t.checks)if(!u(n)||!a(n.id)||r.has(a(n.id))||(r.add(a(n.id)),!Array.isArray(n.toolNames)||n.toolNames.length===0||n.toolNames.some(s=>!a(s)))||n.arguments!==void 0&&!u(n.arguments))return!1;return!0}function ei(e){let t=new Map,r=[];for(let n of Array.isArray(e)?e:[]){let s=u(n?.update)?n.update:{},i=a(s.sessionUpdate);if(i==="runtime_event"){ri(s.event,t,r);continue}if(i==="tool_call"){let o=bt(s)||`tool-${r.length+1}`,c=Nt(t,r,o),l=ue(s,s.name||s.toolName||s.kind);c.toolName=l.toolName,c.arguments=l.arguments,c.status=dt(s.status),c.evidence=Ut(s);continue}if(i==="tool_call_update"){let o=bt(s);if(!o)continue;let c=Nt(t,r,o),l=ue(s,s.name||s.toolName||s.kind);c.toolName||=l.toolName,Object.keys(c.arguments).length===0&&(c.arguments=l.arguments),c.status=dt(s.status),c.evidence.push(...Ut(s))}}return r}function ri(e,t,r){let n=u(e)&&u(e.payload)?e.payload:u(e)?e:{},s=a(n.type);if(["function_call","custom_tool_call","local_shell_call","mcp_tool_call"].includes(s)){let c=bt(n)||`runtime-${r.length+1}`,l=Nt(t,r,c),d=ue(n,n.name||n.tool||s,s);l.toolName=d.toolName,l.arguments=d.arguments,l.status=dt(n.status),l.evidence.push(...Ut(n));return}if(!["function_call_output","custom_tool_call_output","local_shell_call_output","mcp_tool_call_output"].includes(s))return;let i=bt(n);if(!i)return;let o=Nt(t,r,i);o.status=oi(n,o.toolName),o.evidence.push(...Ut(n))}function Nt(e,t,r){let n=e.get(r);return n||(n={toolCallId:r,toolName:"",arguments:{},status:"unknown",evidence:[]},e.set(r,n),t.push(n)),n}function ni(e){let t=a(e).toLowerCase();return ti.get(t)||t}function ue(e,t,r=""){let n=si(e),s=a(r)==="mcp_tool_call"||a(e?.kind).toLowerCase()==="mcp",i=u(e?._meta)?e._meta:{},o=a(e?.server||e?.serverName||e?.server_name||e?.mcpServer||i.server||i.serverName).toLowerCase();if(s&&o==="orcha"){let c=a(e?.tool||e?.toolName||e?.name||t);return{toolName:"plugin_operation",arguments:{...n,...c?{operationCode:c}:{}}}}return{toolName:ni(t),arguments:n}}function bt(e){return u(e)?a(e.call_id||e.callId||e.toolCallId||e.id):""}function si(e){if(!u(e))return{};for(let r of["arguments","args","rawInput","input","params","parameters"]){let n=ii(e[r]);if(n)return n}let t={};for(let r of["cmd","command","cwd","operationCode","path","query","url"])e[r]!==void 0&&(t[r]=e[r]);return t}function ii(e){if(u(e))return structuredClone(e);if(typeof e!="string")return null;try{let t=JSON.parse(e);return u(t)?t:null}catch{return null}}function oi(e,t){if(!u(e))return"unknown";let r=Mt(e,0,{parseCliExitCode:t==="run_command"||t==="apply_patch"});return r.includes("failed")?"failed":r.includes("success")?"success":"unknown"}function Mt(e,t=0,r={}){if(t>8||e===null||e===void 0)return[];if(typeof e=="string")return ai(e,t,r);if(Array.isArray(e))return e.flatMap(o=>Mt(o,t+1,r));if(!u(e))return[];let n=[];typeof e.isError=="boolean"&&n.push(e.isError?"failed":"success"),typeof e.ok=="boolean"&&n.push(e.ok?"success":"failed"),typeof e.success=="boolean"&&n.push(e.success?"success":"failed");let s=dt(e.status);s!=="unknown"&&n.push(s);let i=e.exitCode??e.exit_code;typeof i=="number"&&Number.isFinite(i)&&n.push(i===0?"success":"failed");for(let o of["output","result","structuredContent","content"])e[o]!==void 0&&n.push(...Mt(e[o],t+1,r));return n}function ai(e,t,r){let n=e.trim();if(!n)return[];try{return Mt(JSON.parse(n),t+1,r)}catch{}if(r.parseCliExitCode!==!0)return[];let s=[];for(let i of n.matchAll(/(?:process\s+exited\s+with\s+code|exit\s+code\s*:?)\s*(-?\d+)/gi))s.push(Number(i[1])===0?"success":"failed");return s}function dt(e){let t=a(e).toLowerCase();return Qs.has(t)?"success":Zs.has(t)?"failed":"unknown"}function Ut(e){if(!u(e))return[];let t=u(e.output)?e.output:{},r=[e.verificationEvidence,u(e.verification)?e.verification.evidence:null,t.verificationEvidence,u(t.verification)?t.verification.evidence:null],n=[];for(let s of r)for(let i of Array.isArray(s)?s:s?[s]:[])!u(i)||!a(i.id)||n.push({id:a(i.id),status:dt(i.status??(i.passed===!0?"passed":i.passed===!1?"failed":"")),...a(i.message)?{message:a(i.message)}:{}});return n}function ci(e,t){let r=t.filter(o=>e.toolNames.includes(o.toolName)&&le(e.arguments||{},o.arguments)),n=a(e.evidenceId),s=r.find(o=>o.status==="success"&&(!n||o.evidence.some(c=>c.id===n&&c.status==="success")));if(s)return ce(e,"passed",s,"Runtime tool evidence passed.");let i=r.find(o=>o.status==="failed"||n&&o.evidence.some(c=>c.id===n&&c.status==="failed"));return i?ce(e,"failed",i,"Runtime tool evidence failed."):ce(e,"missing",r.at(-1),n?"Required evidence is missing.":"Required tool execution is missing.")}function ce(e,t,r,n){return{id:e.id,status:t,message:n,...a(e.description)?{description:a(e.description)}:{},toolNames:e.toolNames,...u(e.arguments)?{arguments:e.arguments}:{},...a(e.evidenceId)?{evidenceId:a(e.evidenceId)}:{},...r?.toolCallId?{toolCallId:r.toolCallId}:{}}}function le(e,t){return Array.isArray(e)?Array.isArray(t)&&e.length===t.length&&e.every((r,n)=>le(r,t[n])):u(e)?u(t)?Object.entries(e).every(([r,n])=>Object.hasOwn(t,r)&&le(n,t[r])):!1:Object.is(e,t)}function F(e){if(e===null||typeof e=="boolean")return JSON.stringify(e);if(typeof e=="string")return Ur(e);if(typeof e=="number"){if(!Number.isFinite(e))throw new Error("invalid_jcs_number");return JSON.stringify(Object.is(e,-0)?0:e)}if(Array.isArray(e))return`[${Array.from({length:e.length},(t,r)=>{if(!Object.hasOwn(e,r))throw new Error("invalid_jcs_json_value");return F(e[r])}).join(",")}]`;if(u(e))return`{${Object.keys(e).sort().map(t=>`${Ur(t)}:${F(e[t])}`).join(",")}}`;throw new Error("invalid_jcs_json_value")}function Ur(e){return ui(e),JSON.stringify(e)}function ui(e){for(let t=0;t<e.length;t+=1){let r=e.charCodeAt(t);if(r>=55296&&r<=56319){let n=e.charCodeAt(t+1);if(!(n>=56320&&n<=57343))throw new Error("invalid_jcs_unicode");t+=1}else if(r>=56320&&r<=57343)throw new Error("invalid_jcs_unicode")}}import{spawn as li}from"node:child_process";import{createHash as di,randomUUID as fi}from"node:crypto";import{constants as pi}from"node:fs";import{access as mi,mkdir as fe,readdir as hi,realpath as ft,rm as gi,stat as _i}from"node:fs/promises";import Ti from"node:http";import{tmpdir as yi}from"node:os";import{isAbsolute as pt,join as tt,relative as Dr,resolve as me}from"node:path";var he=1,Ri="orcha.process-isolation/v1",ge="orcha.egress-proxy/v1",Pt={read_only:0,workspace_write:1,workspace_network:2},pe={read_only:["read_only","denied"],workspace_write:["workspace_write","denied"],workspace_network:["workspace_write","restricted"]},Ei=new Set([".env",".git-credentials",".netrc",".npmrc",".pypirc","credentials.json","secrets.json","id_rsa","id_ed25519"]);function K(e){if(!u(e))throw R("RUNTIME_SANDBOX_POLICY_REQUIRED","sandboxPolicy is required");let t=structuredClone(e),r=a(t.accessMode),n=a(t.accessModeCeiling);if(!(r in pe)||!(n in pe))throw R("RUNTIME_SANDBOX_POLICY_INVALID","unsupported runtime access mode");if(Pt[r]>Pt[n])throw R("RUNTIME_SANDBOX_POLICY_INVALID","access mode exceeds its ceiling");let[s,i]=pe[r];if(t.filesystemMode!==s||t.networkMode!==i)throw R("RUNTIME_SANDBOX_POLICY_INVALID","runtime access profile does not match its mode");if(Number(t.policySchemaVersion)!==he||!Number.isInteger(Number(t.policyRevision))||Number(t.policyRevision)<1)throw R("RUNTIME_SANDBOX_POLICY_INVALID","unsupported sandbox policy schema or revision");for(let[c,l]of Object.entries({outsideWorkspaceAccess:"denied",hostAccess:"denied",hostEnvironmentAccess:"denied",dockerSocketAccess:"denied",environmentMode:"allowlist"}))if(t[c]!==l)throw R("RUNTIME_SANDBOX_POLICY_INVALID",`${c} cannot be relaxed`);let o=u(t.processIsolation)?t.processIsolation:{};if(o.mode!=="required"||o.backend==="direct")throw R("RUNTIME_SANDBOX_POLICY_INVALID","strong process isolation is required");if(Array.isArray(t.alwaysApprovedApprovalKeys)&&t.alwaysApprovedApprovalKeys.length)throw R("RUNTIME_SANDBOX_POLICY_INVALID","persistent runtime approvals are forbidden");return t}function vr(e,t){let r=K(e),n=K(t);return Pt[n.accessMode]<Pt[r.accessMode]}async function Fr(e){if(!e.sandboxRequired)return{dispatchable:!1,enforced:!1,backend:"development_direct",daemonStatus:"development_only",daemonProtocolVersion:"",policySchemaVersions:[he],runtimePolicyUpdates:!0,workspaceSync:!1,egressProxy:!1,reason:"sandbox_not_required_in_development"};let t=await $r(e.sandboxBrokerCommand,process.env.PATH||"");if(!t)throw R("RUNTIME_SANDBOX_UNAVAILABLE","sandbox broker is not executable");let r=await xi(t,C(e.sandboxBrokerArguments),e.sandboxProbeTimeoutMs);if(r.enforced!==!0||a(r.protocolVersion)!=="orcha.runtime-sandbox-broker/v1"||!["bubblewrap","broker"].includes(a(r.backend)))throw R("RUNTIME_SANDBOX_UNAVAILABLE","sandbox broker did not report enforced isolation");let n=u(r.probes)?r.probes:{};for(let s of["emptyRoot","outsideWorkspaceDenied","hostFilesystemDenied","sensitiveFilesDenied","environmentAllowlist","dockerSocketDenied","networkNamespace","workspaceReadOnly","workspaceWrite","resourceLimits"])if(n[s]!==!0)throw R("RUNTIME_SANDBOX_UNAVAILABLE",`sandbox broker probe failed: ${s}`);return e.egressProxyRequired&&await Ni(e),{dispatchable:!0,enforced:!0,backend:a(r.backend),daemonStatus:"ok",daemonProtocolVersion:a(r.protocolVersion||"orcha.runtime-sandbox-broker/v1"),policySchemaVersions:[he],runtimePolicyUpdates:!0,workspaceSync:!1,egressProxy:e.egressProxyRequired}}async function _e(e,t,r){let n=a(t.workspace||t.cwd),s=a(r),i=n||(t.allowRequestWorkspace===!0?s:"");if(!i||!pt(i))throw R("RUNTIME_WORKSPACE_NOT_CONFIGURED","runtime target must configure an absolute trusted workspace");let o=await ft(i);if(!(await _i(o)).isDirectory())throw R("RUNTIME_WORKSPACE_INVALID","runtime workspace is not a directory");if(!(e.trustedWorkspaceRoots.length?await Promise.all(e.trustedWorkspaceRoots.map(d=>ft(d))):[o]).some(d=>ye(d,o)))throw R("RUNTIME_WORKSPACE_OUTSIDE_TRUSTED_ROOT","runtime workspace is outside trusted roots");return o}async function Hr({config:e,target:t,command:r,args:n,cwd:s,environment:i,runId:o,agentId:c,sessionId:l,sandboxPolicy:d}){if(!e.sandboxRequired)return{command:r,args:[...n],cwd:s,environment:{...process.env,...i},tempDirectory:"",isolation:{enforced:!1,backend:"development_direct"},cleanup:async()=>{}};let f=K(d),p=await _e(e,t,s),g=await ft(s);if(!ye(p,g))throw R("RUNTIME_WORKSPACE_CWD_INVALID","runtime cwd is outside its workspace");let m=await $r(e.sandboxBrokerCommand,process.env.PATH||"");if(!m)throw R("RUNTIME_SANDBOX_UNAVAILABLE","sandbox broker is not executable");let E=`runtime-${di("sha256").update(String(o)).digest("hex").slice(0,32)}`,O=me(e.sandboxTempRoot||tt(yi(),"orcha-runtime-sandboxes"));await fe(O,{recursive:!0,mode:448});let N=tt(O,`${E}-${fi()}`),_=tt(N,"home"),y=tt(N,"artifacts");await fe(_,{recursive:!0,mode:448}),await fe(y,{recursive:!0,mode:448});let S=f.networkMode==="restricted"?await Ai(e,{runId:String(o),instanceId:E,policyRevision:Number(f.policyRevision),ttlMs:Math.min(T(f.maxRuntimeSeconds,900)*1e3,e.egressGrantMaxTtlMs),maxTransferBytes:T(f.maxNetworkBytes,64*1024*1024)}):null,A={PATH:a(i.PATH||process.env.PATH),LANG:a(i.LANG||process.env.LANG||"C.UTF-8"),HOME:"/tmp/home",TMPDIR:"/tmp",USER:"orcha",LOGNAME:"orcha",SHELL:"/bin/sh",ORCHA_AGENT_ID:String(c),ORCHA_SESSION_ID:String(l),ORCHA_RUN_ID:String(o),ORCHA_RUNTIME_ARTIFACT_DIR:"/tmp/artifacts",...wi(t,i)};A.HOME="/tmp/home",A.TMPDIR="/tmp",A.ORCHA_RUNTIME_ARTIFACT_DIR="/tmp/artifacts";let W={schemaVersion:Ri,runId:String(o),instanceId:E,workspace:p,cwd:g,filesystemMode:f.filesystemMode,networkMode:f.networkMode,environmentMode:"allowlist",deniedRelativePaths:await Ii(p),temporaryDirectory:N,egressProxy:S,environment:A,resourceLimits:Oi(f),readOnlyToolchainRoots:await Si(e,t)},gt=!1,J=async()=>{if(!gt){gt=!0;try{S&&await Ci(e,S,{runId:String(o),instanceId:E})}finally{await gi(N,{recursive:!0,force:!0})}}};return{command:m,args:[...C(e.sandboxBrokerArguments),"--",r,...n],cwd:g,environment:{PATH:process.env.PATH||"",LANG:process.env.LANG||"C.UTF-8",ORCHA_PROCESS_ISOLATION_REQUEST:JSON.stringify(W)},tempDirectory:N,homeDirectory:_,artifactDirectory:y,pathMappings:[{runtimeRoot:"/tmp/artifacts",hostRoot:y},{runtimeRoot:"/tmp/home",hostRoot:_}],isolation:{enforced:!0,backend:"broker",instanceId:E,policyRevision:f.policyRevision},cleanup:J}}async function Si(e,t){let r=C(t.toolchainRoots||t.sandboxToolchainRoots);if(!r.length)return[];let n=await Promise.all(C(e.trustedToolchainRoots).map(i=>ft(i)));if(!n.length)throw R("RUNTIME_TOOLCHAIN_ROOT_NOT_TRUSTED","target toolchain roots require ORCHA_RUNTIME_TRUSTED_TOOLCHAIN_ROOTS");let s=[];for(let i of r){if(!pt(i))throw R("RUNTIME_TOOLCHAIN_ROOT_INVALID","toolchain roots must be absolute");let o=await ft(i);if(!n.some(c=>ye(c,o)))throw R("RUNTIME_TOOLCHAIN_ROOT_NOT_TRUSTED","toolchain root is outside trusted roots");s.push(o)}return[...new Set(s)]}function wi(e,t){let r=u(e.env)?e.env:{},n={};for(let[s,i]of Object.entries(r))/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&i!=null&&(n[s]=String(i));for(let s of["ORCHA_RUNTIME_PROMPT","ORCHA_RUNTIME_ARTIFACT_DIR"])t[s]!=null&&(n[s]=String(t[s]));return n}async function Ii(e){let t=[],r=0,n=async s=>{let i;try{i=await hi(s,{withFileTypes:!0})}catch(o){if(s===e)throw o;return}for(let o of i){if(r+=1,r>1e4)throw R("RUNTIME_WORKSPACE_SCAN_LIMIT_EXCEEDED","workspace contains more than 10000 entries");let c=tt(s,o.name),l=Dr(e,c),d=o.name.toLowerCase();(Ei.has(d)||d.startsWith(".env."))&&t.push(l),o.isDirectory()&&!o.isSymbolicLink()&&await n(c)}};return await n(e),t.sort()}function Oi(e){return{maxCpuSeconds:Math.max(1,T(e.maxRuntimeSeconds,900)),maxMemoryBytes:T(e.maxMemoryBytes,2*1024*1024*1024),maxProcesses:T(e.maxProcesses,128),maxOpenFiles:T(e.maxOpenFiles,1024),maxFileBytes:T(e.maxFileBytes,64*1024*1024)}}async function xi(e,t,r){return await new Promise((n,s)=>{let i=li(e,[...t,"--probe"],{env:{PATH:process.env.PATH||"",LANG:"C.UTF-8"},stdio:["ignore","pipe","pipe"],windowsHide:!0}),o=[],c=[];i.stdout.on("data",d=>o.push(Buffer.from(d))),i.stderr.on("data",d=>c.push(Buffer.from(d)));let l=setTimeout(()=>i.kill("SIGKILL"),Math.max(1e3,r));i.once("error",s),i.once("close",d=>{if(clearTimeout(l),d!==0){s(R("RUNTIME_SANDBOX_UNAVAILABLE",Buffer.concat(c).toString("utf8").trim()||`sandbox probe exited with ${d}`));return}try{n(JSON.parse(Buffer.concat(o).toString("utf8")))}catch{s(R("RUNTIME_SANDBOX_UNAVAILABLE","sandbox probe returned invalid JSON"))}})})}async function $r(e,t){let r=a(e);if(!r)return"";let n=pt(r)?[r]:String(t||"").split(":").filter(Boolean).map(s=>tt(s,r));for(let s of n)try{return await mi(s,pi.X_OK),s}catch{}return""}async function Ai(e,t){if(!e.egressProxyRequired)throw R("RUNTIME_EGRESS_UNAVAILABLE","restricted network requires the Egress Proxy");let r=await Te(e,"POST","/v1/grants",{protocolVersion:ge,...t}),n={socketPath:e.egressProxySocket,grantId:a(r.grantId),credential:a(r.credential)};if(!n.grantId||!n.credential)throw R("RUNTIME_EGRESS_UNAVAILABLE","Egress Proxy returned an invalid grant");return n}async function Ci(e,t,r){await Te(e,"POST",`/v1/grants/${encodeURIComponent(t.grantId)}/revoke`,{protocolVersion:ge,...r}).catch(()=>{})}async function Ni(e){let t=await Te(e,"GET","/health");if(t.status!=="ok"||t.proxy!=="orcha-egress-proxy"||t.protocolVersion!==ge)throw R("RUNTIME_EGRESS_UNAVAILABLE","Egress Proxy is unavailable or incompatible")}async function Te(e,t,r,n){if(!pt(e.egressProxySocket)||!e.egressProxyToken)throw R("RUNTIME_EGRESS_UNAVAILABLE","Egress Proxy socket and token are required");return await new Promise((s,i)=>{let o=Ti.request({socketPath:e.egressProxySocket,path:r,method:t,headers:{Authorization:`Bearer ${e.egressProxyToken}`,Accept:"application/json",...n?{"Content-Type":"application/json"}:{}}},c=>{let l=[],d=0;c.on("data",f=>{d+=f.length,d>1048576?o.destroy(new Error("egress response is too large")):l.push(Buffer.from(f))}),c.once("end",()=>{try{let f=JSON.parse(Buffer.concat(l).toString("utf8")||"{}");(c.statusCode||500)>=400?i(R("RUNTIME_EGRESS_UNAVAILABLE",a(f.error)||"Egress Proxy rejected the request")):s(f)}catch(f){i(f)}})});o.once("error",i),o.setTimeout(3e3,()=>o.destroy(new Error("Egress Proxy request timed out"))),n?o.end(JSON.stringify(n)):o.end()})}function ye(e,t){let r=Dr(me(e),me(t));return r===""||!r.startsWith("..")&&!pt(r)}function R(e,t){return Object.assign(new Error(t),{code:e})}var Re=24e3,Ee=8,Se=50,we=6e3,Mi=new Set(["fail","failed","failure","error","errored","timeout","timed_out","cancelled","canceled","aborted"]),Ui=10*60*1e3,Pi=60*1e3,ki=8,Li=30*60*1e3,Di=60*1e3,vi=1,Fi=new Set(["agentId","taskId","executionId","sessionId","nodeId","targetCode","framework","workspace","instructions","runtimeMaxSessions"]),Hi=/(^|[_-])(token|secret|password|authorization|api[-_]?key|private[-_]?key|credential|cookie|jwt|access[-_]?token|refresh[-_]?token|service[-_]?token|execution[-_]?token)([_-]|$)/i;function $i(e){if(!u(e))return{};let t={};for(let r of["name","code","serverName","serverCode","type","transport","url","command","protocolVersion"]){let n=a(e[r]);n&&(t[r]=n)}return t}function Bi(e){return(Array.isArray(e)?e:[]).map($i).sort((t,r)=>{let n=F(t),s=F(r);return n<s?-1:n>s?1:0})}function qi(e){return!u(e)||e.verificationPlan?.required!==!0?!1:(Array.isArray(e.verificationPlan.checks)?e.verificationPlan.checks:[]).some(r=>u(r)&&Array.isArray(r.toolNames)&&r.toolNames.some(n=>a(n)==="plugin_operation"))}function ji(e,t,r){let n=u(e?._meta)?e._meta:{};return{...u(e)?e:{},sessionId:t,update:u(e?.update)?e.update:{},_meta:{...n,orchaAgentId:r.agentId,runtimeSessionId:r.runtimeSessionId,bridgeUpdateId:kt()}}}function U(e){return e==null||e===""?!1:typeof e=="string"?a(e)!=="":Array.isArray(e)?e.length>0:u(e)?Object.keys(e).length>0:!0}function zr(e){let t=a(e).toLowerCase().replace(/[.。!!]+$/g,"").replace(/[\s-]+/g,"_");return Mi.has(t)}function B(e,t){let r=T(e,t);return Number.isFinite(r)&&r>0?r:t}function xe(e){let t=T(e,null);return Number.isFinite(t)&&t>0?t:null}function mt(e,t=!1){if(typeof e=="boolean")return e;let r=a(e).toLowerCase();return["true","1","yes","y","on"].includes(r)?!0:["false","0","no","n","off"].includes(r)?!1:t}function $(e){return a(e?.type||"echo")}function Gi(e){let t=$(e);return t==="acp"||t==="stdio-acp"||t==="openclaw"}function Ae(e){if(u(e)){if(Object.prototype.hasOwnProperty.call(e,"releaseAfterPrompt"))return e.releaseAfterPrompt;if(Object.prototype.hasOwnProperty.call(e,"disposeAfterPrompt"))return e.disposeAfterPrompt}}function Ki(e){let t=String(e||"");if(Hi.test(t))return!0;let r=t.replace(/[^a-z0-9]/gi,"").toLowerCase();return r.endsWith("token")||r.endsWith("secret")||r.endsWith("password")||r.endsWith("apikey")||r.endsWith("privatekey")||r==="authorization"||r==="cookie"||r==="jwt"||r.includes("credential")}function Ce(e,t=0){if(e==null||typeof e=="number"||typeof e=="boolean")return e;if(typeof e=="string"){if(e.length<=we)return e;let r=e.length-we;return`${e.slice(0,we)}... [truncated ${r} characters]`}if(t>=Ee)return Array.isArray(e)?`[array truncated at depth ${Ee}, items=${e.length}]`:u(e)?`[object truncated at depth ${Ee}, keys=${Object.keys(e).length}]`:String(e);if(Array.isArray(e)){let r=e.slice(0,Se).map(n=>Ce(n,t+1));return e.length>Se&&r.push(`[truncated ${e.length-Se} items]`),r}if(u(e)){let r={};for(let[n,s]of Object.entries(e))r[n]=Ki(n)?"[REDACTED]":Ce(s,t+1);return r}return String(e)}var Vi=new Set(["type","executionId","taskId","task","traceId","requestId","agentCode","stage","phase","nodeId","nodeType","capabilityCode","operationCode","outputType","artifactType","input","inputs","rejection","previous","artifactRefs","outputSchema","executionPolicy","resultContract"]);function zi(e){if(!u(e))return e;let t={};for(let r of Vi)U(e[r])&&(t[r]=e[r]);return t}function Wi(e){if(!u(e))return e;let t={...e};return u(t.renderedPayload)&&(t.renderedPayload=zi(t.renderedPayload)),t}function Ji(e){let t=u(e)?e:{},r={};U(t.metadata)&&(r.metadata=Wi(t.metadata));for(let[n,s]of Object.entries(t))Fi.has(n)||n==="metadata"||U(s)&&(r[n]=s);return r}function Xi(e){let t=u(e)?e:{},r=u(t.metadata)?t.metadata:{},n=u(r.renderedPayload)?r.renderedPayload:{};return u(t.resultContract)?t.resultContract:u(n.resultContract)?n.resultContract:{}}function Wr(e){return a(Xi(e).kind).toLowerCase()==="decision"}function Br(e){let t=u(e)?e:{},r=u(t.metadata)?t.metadata:{};return xe(t.runtimeMaxSessions??r.runtimeMaxSessions)}function Yi(e){return e?.dispatchFinalTextOnly===!0||e?.dispatchFinalOutputOnly===!0?!0:e?.dispatchFinalTextOnly===!1||e?.dispatchFinalOutputOnly===!1?!1:$(e)==="cli"}function qr(e){let t=e?.dispatchReleaseAfterPrompt??e?.dispatchDisposeAfterPrompt;return mt(t,Gi(e))}function Qi(e,t){let r=u(e?.metadata)?{...e.metadata}:{},n=u(r._runtimeBridge)?{...r._runtimeBridge}:{},s=Ae(n);return r._runtimeBridge={...n,promptKind:"dispatch",finalTextOnly:Yi(t),releaseAfterPrompt:s===void 0?qr(t):mt(s,qr(t)),requiresRuntimeResult:Wr(e)},r}function Zi(e){let t=Ji(e);if(!U(t))return"";let r=JSON.stringify(Ce(t),null,2);if(r.length<=Re)return r;let n=r.length-Re;return`${r.slice(0,Re)}
14
+ ... [truncated ${n} characters]`}function Jr(e){if(!u(e))return"";let t=u(e.update)?e.update:e,n=(u(t.content)?t.content:{}).text??t.text;return n==null?"":String(n)}function to(e){if(!u(e))return"";let t=u(e.update)?e.update:e;return a(t.sessionUpdate)}function jr(e){if(!Array.isArray(e))return"";let t=!1,r=[],n=[],s=[],i=()=>{r.length>0&&(n.push(r),r=[])};for(let c of e){let l=to(c),d=Jr(c);if(!l){d&&s.push(d);continue}if(t=!0,l==="agent_message_chunk"){d&&r.push(d);continue}(l==="agent_thought_chunk"||l==="user_message_chunk"||l==="tool_call"||l==="tool_call_update"||l==="plan")&&i()}if(i(),!t)return ht(s);let o=n[n.length-1]||[];return ht(o)}function Ne(e){return Array.isArray(e)?e.map(Jr).filter(t=>t!==""):[]}function eo(e){if(!u(e))return null;let t=u(e.update)?e.update:e;return a(t.sessionUpdate)!=="runtime_event"?null:u(t.event)?t.event:null}function ro(e){if(!u(e))return"";let t=u(e.payload)?e.payload:{},r=a(e.type),n=a(t.type);if(r==="event_msg"){if(n==="task_complete")return a(t.last_agent_message||t.message||t.output);if(n==="agent_message"){let s=a(t.phase||t.status||t.stage).toLowerCase();if(["final_answer","final","complete","completed","done"].includes(s))return a(t.message||t.text||t.content)}}return""}function no(e){if(!Array.isArray(e))return"";for(let t=e.length-1;t>=0;t-=1){let r=ro(eo(e[t]));if(r)return r}return""}function ht(e){let t="";for(let r of e){let n=String(r||"");if(n)if(!t)t=n;else if(n.length>t.length&&n.startsWith(t))t=n;else{let s=Mr(n)&&!/[\r\n]$/.test(t)?`
15
+ `:"";t+=`${s}${n}`}}return t.trim()}function so(e){let t=String(e||"").trim();if(!t)return"";let r=t.match(/(?:^|\n)#{1,3}\s+\S/);return!r||r.index===0?t:t.slice(r.index+(t[r.index]===`
16
+ `?1:0)).trim()}function Gr(e){let t=String(e||"").trim();if(!t)return null;try{let r=JSON.parse(t);if(u(r)&&(Xr(r)||U(r._artifacts)||U(r.artifacts)||U(r._decision)||U(r._meta)))return r}catch{}return null}function Lt(e){try{return ae(e)}catch{return null}}function io(e){try{return ae(e),null}catch(t){return t}}function Ie(...e){for(let t of e){let r=io(t);if(r)throw r}}function Kr(e){let t=String(e||"").trim();if(!t)return null;let r=Lt(t);if(r)return r;let n=[...t.matchAll(/```(?:json)?\s*([\s\S]*?)```/gi)];for(let s=n.length-1;s>=0;s-=1){let i=Gr(n[s][1]);if(i)return i}if(!t.endsWith("}"))return null;for(let s=t.lastIndexOf("{");s>=0;s=t.lastIndexOf("{",s-1)){let i=Gr(t.slice(s));if(i)return i}return null}function oo(e){let t=Ne(e);for(let r=t.length-1;r>=0;r-=1){let n=Lt(t[r]);if(n)return n}return Lt(ht(t))}function Xr(e){if(!u(e))return!1;if(U(e.output))return!0;for(let t of["content","text","message","summary"])if(a(e[t]))return!0;return!!(zr(e.status)||a(e.error)||a(e.errorMessage))}function H(e){let t=u(e)?{...e}:{};return(!Array.isArray(t._artifacts)||t._artifacts.length===0)&&Array.isArray(t.artifacts)&&t.artifacts.length>0&&(t._artifacts=t.artifacts),delete t.artifacts,t}function ao(e){return u(e)?typeof(u(e._decision)?e._decision:u(e.decision)?e.decision:e).passed=="boolean":!1}function co(e){return u(e)?u(e._decision)&&typeof e._decision.passed=="boolean"?!0:ao(e.output):!1}function Oe(e,t,r){let n=u(e)?{...e}:{};if(!U(n.output)){for(let s of["summary","message","content","text"])if(a(n[s])){n.output=a(n[s]);break}}return!U(n.output)&&a(r)&&(n.output=a(r)),{...n,_meta:{...u(n._meta)?n._meta:{},runtimeOutputSource:t,requiredRuntimeResult:!0,finalMessagePreview:a(r).slice(0,1e3)}}}var uo=["dataUrl","dataURL","contentDataUrl","contentDataURL","contentBase64","base64","data"];function Vr(e){if(!u(e))return"";let t=u(e.content)?e.content:{},r=u(e.metadata)?e.metadata:{};return a(e.fieldKey||e.field_key||t.fieldKey||r.fieldKey)}function lo(e,t){let r=u(e.content)?e.content:{},n=u(t.content)?t.content:{},s={...e,...t,content:{...r,...n},metadata:{...u(e.metadata)?e.metadata:{},...u(t.metadata)?t.metadata:{}}};for(let i of uo)U(e[i])&&(s[i]=e[i]),U(r[i])&&(s.content[i]=r[i]);return s}function fo(e,t){let r=Array.isArray(e)?e.filter(u):[],n=Array.isArray(t)?t.filter(u):[];if(!r.length)return n;if(!n.length)return r;let s=[...r],i=new Map;for(let c=0;c<r.length;c+=1){let l=Vr(r[c]),d=i.get(l)||[];d.push(c),i.set(l,d)}let o=new Map;for(let c of n){let l=Vr(c),d=o.get(l)||0;o.set(l,d+1);let f=i.get(l)?.[d];f===void 0?s.push(c):s[f]=lo(s[f],c)}return s}function q(e,t,r){let n={...e,...t,_meta:{...u(e._meta)?e._meta:{},...u(t._meta)?t._meta:{},runtimeOutputSource:r}};return(Array.isArray(e._artifacts)||Array.isArray(t._artifacts))&&(n._artifacts=fo(e._artifacts,t._artifacts)),n}function po(e,t,r={}){let n=a(r.promptKind),s=r.requiresRuntimeResult===!0,i=s||n==="dispatch",o=H(e),c=typeof o.output=="string"?Lt(o.output):null;if(c)return q(o,H(c),"result_block");let l=no(t),d=l?Kr(l):null,f=i?oo(t):null;if(Xr(o))return zr(o.status)||a(o.error)||a(o.errorMessage)?o:n==="dispatch"&&d?q(o,H(d),"final_event"):n==="dispatch"&&f?q(o,H(f),"updates"):!s||co(o)?o:d?q(o,H(d),"final_event"):f?q(o,H(f),"updates"):(Ie(o.output,l,ht(Ne(t))),Oe(o,"result",o.output));if(d)return q(o,H(d),"final_event");if(f)return q(o,H(f),"updates");if(l)return s?(Ie(l,ht(Ne(t))),Oe(o,"final_event",l)):{...o,output:l,_meta:{...u(o._meta)?o._meta:{},runtimeOutputSource:"final_event"}};let p=so(jr(t));if(!p)return o;let g=Kr(p);return g?q(o,H(g),"updates"):s?(Ie(jr(t),p),Oe(o,"updates",p)):{...o,output:p,_meta:{...u(o._meta)?o._meta:{},runtimeOutputSource:"updates"}}}var Dt=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.operations=new Map,this.startedAt=ot(),this.sandboxCapabilities={dispatchable:!1,enforced:!1,backend:t.sandboxRequired?"unavailable":"development_direct",daemonStatus:t.sandboxRequired?"pending":"development_only",policySchemaVersions:[1],runtimePolicyUpdates:!0,workspaceSync:!1,egressProxy:!1},this.cleanupTimer=null,this.startSessionCleanup()}async start(){try{this.sandboxCapabilities=await Fr(this.config)}catch(t){this.sandboxCapabilities={...this.sandboxCapabilities,dispatchable:!1,enforced:!1,backend:"unavailable",daemonStatus:"unavailable",reason:a(t?.code||t?.message||t)||"sandbox_probe_failed"},h("error","runtime-bridge","runtime node sandbox probe failed; node will not accept work",{reason:this.sandboxCapabilities.reason})}return this.sandboxCapabilities}assertDispatchable(){if(this.config.sandboxRequired&&!(this.sandboxCapabilities.dispatchable===!0&&this.sandboxCapabilities.enforced===!0))throw Object.assign(new Error("runtime node strong sandbox is unavailable"),{code:"RUNTIME_NODE_SANDBOX_UNAVAILABLE"})}operationIdentity(t,r,n){let s=u(t.goalContract)?de(t.goalContract):a(t.goalContractHash),i=bi("sha256").update(F({prompt:Array.isArray(t.prompt)?t.prompt:[],mcpServers:Bi(t.mcpServers)})).digest("hex");return{agentId:r,runId:a(t.runId),sessionId:n,targetCode:a(t.targetCode||t.framework),workspace:a(t.workspace),goalContractHash:s,requestHash:i}}assertOperationIdentity(t,r,n,s){let i=this.operationIdentity(r,n,s),o=Object.keys(t.identity).find(c=>t.identity[c]!==i[c]);if(o)throw Object.assign(new Error(`runtime operation correlation conflict: ${t.correlationId}`),{code:"RUNTIME_OPERATION_CORRELATION_CONFLICT",field:o})}createOperation(t,r,n,s){let i={correlationId:t,agentId:n,sessionId:s,identity:this.operationIdentity(r,n,s),sandboxPolicy:u(r.sandboxPolicy)?structuredClone(r.sandboxPolicy):null,status:"running",updates:[],listeners:new Set,waiters:[],response:null,error:null,createdAtMs:Date.now(),completedAtMs:null};return this.operations.set(t,i),i}async attachOperation(t,r={}){let n=()=>{if(r.onUpdate)for(let s of t.updates)r.onUpdate(s)};if(t.status==="completed")return n(),t.response;if(t.status==="failed")throw n(),t.error;r.onUpdate&&t.listeners.add(r.onUpdate);try{return n(),await new Promise((s,i)=>t.waiters.push({resolve:s,reject:i}))}finally{r.onUpdate&&t.listeners.delete(r.onUpdate)}}completeOperation(t,r){if(t.status==="running"){t.status="completed",t.response=r,t.completedAtMs=Date.now();for(let n of t.waiters.splice(0))n.resolve(r);t.listeners.clear()}}promptResponse(t,r,n,s,i){let o=u(t.metadata)?t.metadata:{},c=u(o._runtimeBridge)?o._runtimeBridge:{},l=po(i,s,c),d=kr(t.goalContract,s,t.goalContractHash);return{sessionId:n,runtimeSessionId:r.runtimeSessionId,result:l,updates:s,...d?{verification:d}:{}}}failOperation(t,r){if(t.status!=="running")return;let n=r instanceof Error?r:Object.assign(new Error(String(r||"runtime operation failed")),{code:"RUNTIME_NODE_ERROR"});t.status="failed",t.error=n,t.completedAtMs=Date.now();for(let s of t.waiters.splice(0))s.reject(n);t.listeners.clear()}cleanupOperations(t=Date.now()){let r=B(this.config.operationTtlMs,Li);for(let[n,s]of this.operations)s.status!=="running"&&t-(s.completedAtMs||s.createdAtMs)>r&&this.operations.delete(n)}targetFor(t){let r=a(t)||this.config.defaultTargetCode,n=this.targets[r];if(!r||!u(n)){let s=new Error(`runtime target is not configured: ${r||"<empty>"}`);throw s.code="RUNTIME_TARGET_NOT_FOUND",s}return{code:r,target:n}}targetIdleTtlMs(t){let n=$(t)==="openclaw"?B(this.config.openClawSessionIdleTtlMs,Di):B(this.config.sessionIdleTtlMs,Ui);return B(t?.sessionIdleTtlMs??t?.idleTtlMs,n)}targetMaxSessions(t,r=null){let s=$(t)==="openclaw"?B(this.config.openClawMaxSessions,vi):B(this.config.maxSessionsPerTarget,ki),i=B(t?.maxSessions,s),o=xe(r);return o?Math.max(i,o):i}targetReleaseAfterPrompt(t,r={}){let n=$(t),s=u(r?._runtimeBridge)?r._runtimeBridge:{},i=Ae(s);return i!==void 0?mt(i,!1):mt(t?.releaseAfterPrompt??t?.disposeAfterPrompt,n==="openclaw")}promptReleaseAfterPrompt(t,r={}){if(this.config.sandboxRequired)return!0;let n=u(r?._runtimeBridge)?r._runtimeBridge:{},s=Ae(n);return s!==void 0?mt(s,t.releaseAfterPrompt):t.releaseAfterPrompt}startSessionCleanup(){let t=B(this.config.sessionCleanupIntervalMs,Pi);t<=0||(this.cleanupTimer=setInterval(()=>{this.cleanupExpiredSessions().catch(r=>{h("warn","runtime-bridge","runtime session cleanup failed",{error:String(r)})})},t),this.cleanupTimer.unref?.())}sessionCountForTarget(t){let r=0;for(let n of this.sessions.values())n.targetCode===t&&(r+=1);return r}sessionCountForAgentTarget(t,r){let n=0;for(let s of this.sessions.values())s.agentId===t&&s.targetCode===r&&(n+=1);return n}idleTargetSessions(t){return[...this.sessions.entries()].filter(([,r])=>r.targetCode===t&&!r.busy).sort((r,n)=>(r[1].lastUsedAtMs||0)-(n[1].lastUsedAtMs||0))}idleAgentTargetSessions(t,r){return[...this.sessions.entries()].filter(([,n])=>n.agentId===t&&n.targetCode===r&&!n.busy).sort((n,s)=>(n[1].lastUsedAtMs||0)-(s[1].lastUsedAtMs||0))}async closeSession(t,r="session_closed"){let n=this.sessions.get(t);if(!n)return!1;try{await n.runtime?.stop?.(r)}catch(s){h("warn","runtime-bridge","runtime session stop failed",{sessionId:n.sessionId,runtimeSessionId:n.runtimeSessionId,targetCode:n.targetCode,runtimeKind:n.runtimeKind,error:String(s)})}return this.sessions.delete(t),this.runtimeSessionIndex.delete(`${n.agentId}:${n.runtimeSessionId}`),h("info","runtime-bridge","runtime session closed",{sessionId:n.sessionId,runtimeSessionId:n.runtimeSessionId,targetCode:n.targetCode,runtimeKind:n.runtimeKind,reason:r}),!0}async closeAllSessions(t="bridge_shutdown"){for(let r of[...this.sessions.keys()])await this.closeSession(r,t)}async stop(t="bridge_stop"){this.cleanupTimer&&clearInterval(this.cleanupTimer),this.cleanupTimer=null,await this.closeAllSessions(t)}async cleanupExpiredSessions(t=Date.now()){for(let[r,n]of[...this.sessions.entries()])n.busy||t-(n.lastUsedAtMs||n.createdAtMs||t)>n.idleTtlMs&&await this.closeSession(r,"idle_timeout")}async reserveTargetSlot(t,r,n={}){let s=a(n.agentId),i=xe(n.runtimeMaxSessions);if(s&&i)for(;this.sessionCountForAgentTarget(s,t)>=i;){let c=this.idleAgentTargetSessions(s,t);if(!c.length){let l=new Error(`runtime agent session limit reached: ${s}`);throw l.code="RUNTIME_AGENT_SESSION_LIMIT",l}await this.closeSession(c[0][0],"agent_session_limit")}let o=this.targetMaxSessions(r,i);for(;this.sessionCountForTarget(t)>=o;){let c=this.idleTargetSessions(t);if(!c.length){let l=new Error(`runtime target session limit reached: ${t}`);throw l.code="RUNTIME_TARGET_SESSION_LIMIT",l}await this.closeSession(c[0][0],"target_session_limit")}}async createAgent(t){let r=a(t.agentId);if(!r)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=this.agents.get(r);if(i&&i.targetCode!==n)throw Object.assign(new Error(`runtime agent target conflict: ${r}`),{code:"RUNTIME_AGENT_TARGET_CONFLICT"});let o=this.config.sandboxRequired?await _e(this.config,s,t.workspace):a(t.workspace),c={agentId:r,targetCode:n,framework:a(t.framework||n),workspace:o,metadata:u(t.metadata)?t.metadata:{},createdAt:ot(),runtimeKind:$(s),runtimeMaxSessions:Br(t)};return this.agents.set(r,c),{agent:c}}runtimeFor(t,r,n={}){let{target:s}=this.targetFor(t.targetCode),i=$(s),o={onPermissionRequest:l=>this.requestPermission(l)},c={sessionPromptTimeoutMs:this.config.sessionPromptTimeoutMs,sandboxRequired:this.config.sandboxRequired,...this.config.sandboxRequired?{prepareLaunch:l=>Hr({config:this.config,target:s,...l,runId:n.runId,agentId:t.agentId,sessionId:r,sandboxPolicy:n.sandboxPolicy})}:{}};return i==="stdio-acp"||i==="acp"?new Q(t,s,o,c):i==="openclaw"?new wt(t,s,r,o,c):i==="cli"?new Ct(t,s,c):new yt(t)}async prompt(t,r={}){if(this.assertDispatchable(),this.config.sandboxRequired){let c=a(t.runId);if(!c)throw Object.assign(new Error("runId is required"),{code:"BAD_REQUEST"});t={...t,runId:c,sandboxPolicy:K(t.sandboxPolicy)}}let n=a(t.agentId),s=a(t.sessionId)||kt(),i=a(t.correlationId);if(!n)throw Object.assign(new Error("agentId is required"),{status:400,code:"BAD_REQUEST"});if(this.cleanupOperations(),i){let c=this.operations.get(i);if(c)return this.assertOperationIdentity(c,t,n,s),this.attachOperation(c,r);if(t.attachOnly===!0)throw Object.assign(new Error(`runtime operation is no longer available: ${i}`),{code:"RUNTIME_OPERATION_NOT_FOUND"})}else if(t.attachOnly===!0)throw Object.assign(new Error("correlationId is required for attachOnly"),{code:"BAD_REQUEST"});let o=i?this.createOperation(i,t,n,s):null;if(o){let c=this.attachOperation(o,r);return(async()=>{try{await this._promptOwned(t,{},o,n,s)}catch(l){let d=o.status==="completed";this.failOperation(o,l),d&&h("warn","runtime-bridge","runtime cleanup failed after operation completion",{correlationId:o.correlationId,error:String(l)})}})(),await c}return await this._promptOwned(t,r,o,n,s)}async _promptOwned(t,r,n,s,i){let o=a(t.runId),c=this.config.sandboxRequired?K(n?.sandboxPolicy||t.sandboxPolicy):null,l=this.agents.get(s),d=this.targetFor(t.targetCode||t.framework||l?.targetCode);if(l&&l.targetCode!==d.code)throw Object.assign(new Error(`runtime agent target conflict: ${s}`),{code:"RUNTIME_AGENT_TARGET_CONFLICT"});if($(d.target)==="cli"&&qi(t.goalContract))throw Object.assign(new Error("CLI runtimes do not support per-run dynamic MCP required by plugin_operation"),{code:"unsupported_dynamic_mcp"});let f=l||(await this.createAgent({agentId:s,targetCode:d.code,framework:t.framework,workspace:t.workspace,runtimeMaxSessions:t.runtimeMaxSessions,metadata:t.metadata})).agent,p=Br(t);if(p&&(f.runtimeMaxSessions=p),!this.config.sandboxRequired){let _=a(t.workspace);_&&_!==f.workspace&&(f.workspace=_)}let g=`${s}:${i}`;await this.cleanupExpiredSessions();let m=this.sessions.get(g);if(m&&m.targetCode!==d.code)throw Object.assign(new Error(`runtime session target conflict: ${i}`),{code:"RUNTIME_SESSION_TARGET_CONFLICT"});if(m&&this.config.sandboxRequired&&m.runId!==o)throw Object.assign(new Error(`runtime session cannot be shared across runs: ${i}`),{code:"RUNTIME_SESSION_RUN_CONFLICT"});if(!m){let{code:_,target:y}=d;await this.reserveTargetSlot(_,y,{agentId:s,runtimeMaxSessions:f.runtimeMaxSessions});let S=this.runtimeFor(f,i,{runId:o,sandboxPolicy:c}),A=await S.sessionNew({cwd:f.workspace||process.cwd(),mcpServers:Array.isArray(t.mcpServers)?t.mcpServers:[],metadata:u(t.metadata)?t.metadata:{}}),W=Date.now();m={agentId:s,sessionId:i,runtime:S,targetCode:_,runtimeKind:$(y),runId:o,sandboxPolicy:c?structuredClone(c):null,runtimeSessionId:a(u(A)?A.sessionId:"")||i,idleTtlMs:this.targetIdleTtlMs(y),releaseAfterPrompt:this.config.sandboxRequired?!0:this.targetReleaseAfterPrompt(y,t.metadata),createdAtMs:W,lastUsedAtMs:W,busy:!1,createdAt:ot()},this.sessions.set(g,m),this.runtimeSessionIndex.set(`${s}:${m.runtimeSessionId}`,m)}if(m.busy){let _=new Error(`runtime session is already running: ${i}`);throw _.code="RUNTIME_SESSION_BUSY",_}m.busy=!0,m.operationCorrelationId=n?.correlationId||null,m.lastUsedAtMs=Date.now();let E=n?.updates||[],O=_=>{let y=ji(_,i,m);if(E.push(y),n)for(let S of n.listeners)try{S?.(y)}catch(A){h("warn","runtime-bridge","runtime operation update listener failed",{correlationId:n.correlationId,error:String(A)})}else r.onUpdate?.(y)},N=_=>{if(!(!n||n.status!=="running"||!u(_))){if(_.status==="failed"){let y=_.error;if(y instanceof Error){this.failOperation(n,y);return}let S=u(y)?y:{},A=Object.assign(new Error(a(S.message||_.message)||"runtime terminal failure"),{code:a(S.code||_.code)||"RUNTIME_TERMINAL_FAILED"});this.failOperation(n,A);return}this.completeOperation(n,this.promptResponse(t,m,i,E,u(_.result)?_.result:{stopReason:"end_turn"}))}};try{let _=Pr(t.goalContract),y=Array.isArray(t.prompt)?[...t.prompt]:[];_&&y.unshift({type:"text",text:_,metadata:{source:"orcha_goal_contract"}});let S=await m.runtime.sessionPrompt({sessionId:m.runtimeSessionId,prompt:y,metadata:u(t.metadata)?t.metadata:{}},O,N),A=this.promptResponse(t,m,i,E,S);return n&&this.completeOperation(n,A),A}finally{m.busy=!1,m.operationCorrelationId===n?.correlationId&&(m.operationCorrelationId=null),m.lastUsedAtMs=Date.now(),this.promptReleaseAfterPrompt(m,u(t.metadata)?t.metadata:{})&&await this.closeSession(g,"release_after_prompt")}}async updatePolicy(t){if(this.assertDispatchable(),!this.config.sandboxRequired)throw Object.assign(new Error("runtime sandbox policy updates require an enforced sandbox"),{code:"RUNTIME_NODE_SANDBOX_UNAVAILABLE"});let r=a(t.agentId),n=a(t.runId),s=a(t.sessionId),i=a(t.correlationId);if(!r||!n||!s||!i)throw Object.assign(new Error("agentId, runId, sessionId and correlationId are required"),{code:"BAD_REQUEST"});let o=K(t.sandboxPolicy),c=this.operations.get(i);if(c&&(c.agentId!==r||c.sessionId!==s||c.identity.runId!==n))throw Object.assign(new Error(`runtime operation policy identity conflict: ${i}`),{code:"RUNTIME_OPERATION_CORRELATION_CONFLICT"});let l=`${r}:${s}`,d=this.sessions.get(l);if(d&&d.runId!==n)throw Object.assign(new Error(`runtime session policy identity conflict: ${s}`),{code:"RUNTIME_SESSION_RUN_CONFLICT"});let f=d?.sandboxPolicy||c?.sandboxPolicy;if(!f)throw Object.assign(new Error(`runtime operation is no longer available: ${i}`),{code:"RUNTIME_OPERATION_NOT_FOUND"});let p=Number(f.policyRevision),g=Number(o.policyRevision);if(g<p)throw Object.assign(new Error("runtime sandbox policy revision is stale"),{code:"RUNTIME_POLICY_REVISION_CONFLICT",currentPolicyRevision:p});if(g===p){if(F(f)!==F(o))throw Object.assign(new Error("runtime sandbox policy revision payload conflicts"),{code:"RUNTIME_POLICY_REVISION_CONFLICT",currentPolicyRevision:p});return{updated:!1,idempotent:!0,policyRevision:p,accessMode:f.accessMode}}let m=vr(f,o);c&&(c.sandboxPolicy=structuredClone(o)),d&&(d.sandboxPolicy=structuredClone(o));let E=!1;return m&&d?.busy===!0&&(await d.runtime.sessionCancel({sessionId:d.runtimeSessionId}),E=await this.closeSession(l,"sandbox_policy_downgrade")),{updated:!0,policyRevision:g,accessMode:o.accessMode,activeCommandCancelled:E,deferredToNextLaunch:!m&&d?.busy===!0}}async cancel(t){let r=a(t.agentId),n=a(t.sessionId),s=a(t.correlationId);if(s){let c=this.operations.get(s);if(!c||c.status!=="running")return{cancelled:!1,correlationId:s,reason:"operation_not_running"};if(c.agentId!==r||c.sessionId!==n)throw Object.assign(new Error(`runtime operation cancellation identity conflict: ${s}`),{code:"RUNTIME_OPERATION_CORRELATION_CONFLICT"});let l=this.sessions.get(`${r}:${n}`);return!l||l.busy!==!0||l.operationCorrelationId!==s?{cancelled:!1,correlationId:s,reason:"operation_not_running"}:(await l.runtime.sessionCancel({sessionId:l.runtimeSessionId}),await this.closeSession(`${r}:${n}`,"cancelled"),{cancelled:!0,correlationId:s})}let i=`${r}:${n}`,o=this.sessions.get(i);return o?(await o.runtime.sessionCancel({sessionId:o.runtimeSessionId}),await this.closeSession(i,"cancelled"),{cancelled:!0}):{cancelled:!1}}async dispatch(t,r={}){let n=a(t.agentId),s=a(t.taskId),i=a(t.executionId);if(!n||!s)throw Object.assign(new Error("agentId and taskId are required"),{status:400,code:"BAD_REQUEST"});let o=a(t.sessionId)||`dispatch-${i||s}`,c=a(t.instructions),l=Zi(t),d=Wr(t),{target:f}=this.targetFor(t.targetCode||t.framework),p=[{type:"text",text:["Task dispatch received.",`taskId: ${s}`,i?`executionId: ${i}`:"",c?`instructions: ${c}`:"",l?"orchaContext:":"",l,l?"Use orchaContext as the source of truth for upstream outputs, review reports, artifacts, and workflow metadata.":"","Follow the execution protocol in instructions exactly.","When embedding a generated artifact in final Markdown, use the Orcha artifact placeholder as the link target: orcha-artifact://<fieldKey>/<index>.","Example: use ![illustration](orcha-artifact://image/0) for the first generated image artifact.","Do not use local filesystem paths, file:// URLs, or data: URLs in final Markdown; Orcha replaces artifact placeholders after ingestion.",d?`For decision results, put the raw report between ${Ar} and ${Cr}.`:"",d?`Then put a JSON object containing _decision between ${Nr} and ${br}.`:"",d?"Do not JSON-escape the report. Keep output out of the CONTROL JSON, and put every protocol marker on its own line.":"","Return only the final answer required by that protocol.","Do not include process notes, logs, or explanations."].filter(Boolean).join(`
17
+ `)}];return this.prompt({...t,agentId:n,sessionId:o,prompt:p,metadata:Qi(t,f)},r)}async requestPermission({agent:t,runtimeSessionId:r,request:n,emitUpdate:s}){let i=kt(),c=this.runtimeSessionIndex.get(`${t.agentId}:${r}`)?.sessionId||r||kt(),l={permissionId:i,agentId:t.agentId,sessionId:c,runtimeSessionId:r,request:u(n)?n:{},status:"pending",createdAt:ot()};return s?.({sessionId:r,update:{sessionUpdate:"permission_request",permission:l}}),await new Promise(d=>{let f=T(n?.timeoutMs,this.config.permissionRequestTimeoutMs),p=setTimeout(()=>{this.pendingPermissions.delete(i),d({permissionId:i,outcome:"denied",response:{reason:"permission request timed out"}})},f);this.pendingPermissions.set(i,{timer:p,resolve:d,permission:l})})}async respondPermission(t){let r=a(t.permissionId),n=this.pendingPermissions.get(r),s=a(t.outcome||"approved")||"approved";return n?(clearTimeout(n.timer),this.pendingPermissions.delete(r),n.resolve({permissionId:r,outcome:s,response:u(t.response)?t.response:{},userId:a(t.userId),metadata:u(t.metadata)?t.metadata:{}}),{accepted:!0,permissionId:r,outcome:s}):{accepted:!1,permissionId:r,outcome:s}}health(){return{status:this.config.sandboxRequired&&!this.sandboxCapabilities.dispatchable?"unavailable":"ok",bridgeVersion:Y,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),sandboxCapabilities:this.sandboxCapabilities}}};import mo from"node:http";import ho from"node:https";import{randomBytes as Yr}from"node:crypto";var et=1,V=3,go=1e4,vt=class{constructor(t,r={}){this.url=t,this.readyState=0,this.socket=null,this.request=null,this.buffer=Buffer.alloc(0),this.listeners=new Map,this.connectTimeoutMs=_o(r.connectTimeoutMs,go),this.connectTimer=null,this.connect()}addEventListener(t,r){let n=this.listeners.get(t)||new Set;n.add(r),this.listeners.set(t,n)}emit(t,r={}){let n=this.listeners.get(t);if(n)for(let s of n)s(r)}connect(){let t=new URL(this.url),r=t.protocol==="wss:"?ho:mo,n=Yr(16).toString("base64"),s=r.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"}});this.request=s,this.startConnectTimer(s),s.on("upgrade",(i,o,c)=>{if(this.clearConnectTimer(),this.readyState===V){o.destroy();return}this.socket=o,this.readyState=et,o.on("data",l=>this.onData(l)),o.on("close",()=>this.onClose()),o.on("error",l=>{this.readyState!==V&&this.emit("error",{error:l,message:l.message,type:"error"}),this.onClose()}),c?.length&&this.onData(c),this.emit("open")}),s.on("response",i=>{this.clearConnectTimer(),this.emit("error",{message:`websocket upgrade failed: HTTP ${i.statusCode}`,type:"error"}),i.resume(),this.onClose()}),s.on("error",i=>{this.clearConnectTimer(),this.readyState!==V&&this.emit("error",{error:i,message:i.message,type:"error"}),this.onClose()}),s.end()}startConnectTimer(t){this.connectTimeoutMs<=0||(this.connectTimer=setTimeout(()=>{if(this.readyState===et||this.readyState===V)return;let r=`websocket connect timeout after ${this.connectTimeoutMs}ms`;this.emit("error",{message:r,type:"timeout"}),this.onClose(),t.destroy(new Error(r))},this.connectTimeoutMs),this.connectTimer.unref?.())}clearConnectTimer(){this.connectTimer&&(clearTimeout(this.connectTimer),this.connectTimer=null)}send(t){!this.socket||this.readyState!==et||this.socket.write(be(1,Buffer.from(String(t),"utf8")))}close(){if(this.readyState!==V){if(this.clearConnectTimer(),!this.socket){this.request?.destroy(),this.onClose();return}try{this.readyState===et&&this.socket.write(be(8,Buffer.alloc(0))),this.socket.end()}catch{this.socket.destroy()}this.onClose()}}onClose(){this.readyState!==V&&(this.clearConnectTimer(),this.readyState=V,this.request=null,this.emit("close"))}onData(t){for(this.buffer=Buffer.concat([this.buffer,t]);this.buffer.length>=2;){let r=this.buffer[0],n=this.buffer[1],s=r&15,i=(n&128)!==0,o=n&127,c=2;if(o===126){if(this.buffer.length<c+2)return;o=this.buffer.readUInt16BE(c),c+=2}else if(o===127){if(this.buffer.length<c+8)return;let f=this.buffer.readUInt32BE(c),p=this.buffer.readUInt32BE(c+4);o=f*2**32+p,c+=8}let l=c;if(i&&(c+=4),this.buffer.length<c+o)return;let d=this.buffer.subarray(c,c+o);if(i){let f=this.buffer.subarray(l,l+4);d=Buffer.from(d.map((p,g)=>p^f[g%4]))}this.buffer=this.buffer.subarray(c+o),s===1?this.emit("message",{data:d.toString("utf8")}):s===8?this.close():s===9&&this.socket?.write(be(10,d))}}};function _o(e,t){let r=Number.parseInt(String(e??""),10);return Number.isFinite(r)&&r>=0?r:t}function be(e,t){let r=t.length,n=2;r>=126&&r<=65535?n+=2:r>65535&&(n+=8);let s=Yr(4),i=Buffer.alloc(n+4+r);i[0]=128|e;let o=2;r<126?i[1]=128|r:r<=65535?(i[1]=254,i.writeUInt16BE(r,o),o+=2):(i[1]=255,i.writeUInt32BE(Math.floor(r/2**32),o),i.writeUInt32BE(r>>>0,o+4),o+=8),s.copy(i,o),o+=4;for(let c=0;c<r;c+=1)i[o+c]=t[c]^s[c%4];return i}function To(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 Me(e,t=!0){return Object.entries(e||{}).map(([r,n])=>({targetCode:r,targetName:a(n?.name||n?.targetName||r),targetType:a(n?.type||"echo"),status:t?"available":"unavailable"}))}var Ft=class{constructor(t,r){this.config=t,this.bridge=r,this.ws=null,this.stopped=!1,this.connected=!1,this.reconnectTimer=null,this.heartbeatTimer=null}sandboxCapabilities(){return this.bridge.sandboxCapabilities||{dispatchable:this.config.sandboxRequired!==!0,enforced:!1,backend:"development_direct",daemonStatus:"development_only",policySchemaVersions:[1],runtimePolicyUpdates:!0,workspaceSync:!1,egressProxy:!1}}start(){this.connect()}stop(){this.stopped=!0,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.reconnectTimer=null,this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.heartbeatTimer=null,this.ws?.close()}connect(){if(this.stopped)return;let t=To(this.config.orchaUrl),r=new vt(t,{connectTimeoutMs:this.config.connectTimeoutMs});this.ws=r,r.addEventListener("open",()=>{if(this.ws!==r||this.stopped){r.close();return}this.authenticate(r)}),r.addEventListener("message",n=>this.handleMessage(n.data,r)),r.addEventListener("close",()=>this.scheduleReconnect("close",r)),r.addEventListener("error",n=>{h("warn","orcha-client","runtime node websocket error",{error:String(n?.message||n?.type||n)})})}authenticate(t=this.ws){this.send({type:"runtime_node.authenticate",token:this.config.nodeToken,nodeId:this.config.nodeId,nodeName:this.config.nodeName,version:Y,protocolVersion:"orcha-runtime-node.v1",defaultTargetCode:this.config.defaultTargetCode,sandboxCapabilities:this.sandboxCapabilities(),targets:Me(this.config.targets,this.sandboxCapabilities().dispatchable===!0)},t)}scheduleReconnect(t,r=this.ws){r&&this.ws!==r||(this.connected=!1,this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.heartbeatTimer=null,r&&this.ws===r&&(this.ws=null),!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,r=this.ws){if(r&&this.ws!==r)return;let n;try{n=JSON.parse(String(t))}catch(s){h("warn","orcha-client","invalid Orcha websocket frame",{error:String(s)});return}if(u(n)){if(n.type==="runtime_node.authenticated"){if(r&&this.ws!==r)return;this.connected=!0,this.startHeartbeat(r),h("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(),sandboxCapabilities:this.sandboxCapabilities(),targets:Me(this.config.targets,this.sandboxCapabilities().dispatchable===!0)})}}startHeartbeat(t){this.heartbeatTimer&&clearInterval(this.heartbeatTimer);let r=Math.max(1e3,Number(this.config.heartbeatIntervalMs||15e3)),n=()=>this.send({type:"runtime_node.heartbeat",ts:new Date().toISOString(),sandboxCapabilities:this.sandboxCapabilities(),targets:Me(this.config.targets,this.sandboxCapabilities().dispatchable===!0)},t);n(),this.heartbeatTimer=setInterval(n,r),this.heartbeatTimer.unref?.()}async handleRequest(t){let r=a(t.id),n=a(t.method),s=u(t.params)?t.params:{};try{let i=await this.invoke(n,s,r);this.send({type:"orcha.runtime.response",id:r,ok:!0,result:i})}catch(i){this.send({type:"orcha.runtime.response",id:r,ok:!1,error:{code:i.code||"RUNTIME_NODE_ERROR",message:i.message||String(i)}})}}async invoke(t,r,n){if(t==="health")return this.bridge.health();if(t==="agents/create")return this.bridge.createAgent(r);if(t==="agents/dispatch")return this.bridge.dispatch(r,{onUpdate:s=>this.sendUpdate(n,s)});if(t==="sessions/prompt")return this.bridge.prompt(r,{onUpdate:s=>this.sendUpdate(n,s)});if(t==="sessions/policy")return this.bridge.updatePolicy(r);if(t==="sessions/cancel")return this.bridge.cancel(r);if(t==="permissions/respond")return this.bridge.respondPermission(r);throw Object.assign(new Error(`unsupported Orcha runtime method: ${t}`),{code:"METHOD_NOT_FOUND"})}sendUpdate(t,r){this.send({type:"orcha.runtime.event",requestId:t,eventType:"runtime.update",payload:r})}send(t,r=this.ws){return!r||r!==this.ws||r.readyState!==et?!1:(r.send(JSON.stringify(t)),!0)}};import{existsSync as tn,readFileSync as yo}from"node:fs";import{dirname as Ro,resolve as Ht}from"node:path";import{fileURLToPath as Eo}from"node:url";var So=/^[A-Za-z_][A-Za-z0-9_]*$/;function en(e=process.env,t=process.cwd()){let r=a(e.ORCHA_RUNTIME_ENV_FILE),n=r?Ht(t,r):Ht(t,".env");if(!tn(n))return r&&h("warn","config","runtime env file not found",{path:n}),{loaded:!1,path:n,keys:[]};let s=[],i=yo(n,"utf8");for(let o of i.split(/\r?\n/)){let c=Io(o);if(!c)continue;let[l,d]=c;Object.prototype.hasOwnProperty.call(e,l)||(e[l]=d,s.push(l))}return h("info","config","runtime env file loaded",{path:n,keyCount:s.length}),{loaded:!0,path:n,keys:s}}function rn(e=process.env){let t=a(e.ORCHA_RUNTIME_MODE||(e.ORCHA_RUNTIME_ORCHA_URL?"node":"server")),r=a(e.ORCHA_RUNTIME_BRIDGE_HOST||"127.0.0.1"),n=["production","prod"].includes(a(e.NODE_ENV||e.ORCHA_ENVIRONMENT).toLowerCase()),s=Zr(e.ORCHA_RUNTIME_SANDBOX_REQUIRED,t==="node"||n||!Qr(r));if(!s&&(t==="node"||n||!Qr(r)))throw new Error("strong runtime sandbox cannot be disabled for a node, production, or non-loopback listener");let i=Ro(Eo(import.meta.url)),o=Ht(i,"sandbox","broker.js"),c=Ht(i,"orcha-runtime-sandbox-broker.js"),l=tn(o)?o:c,d=a(e.ORCHA_RUNTIME_SANDBOX_BROKER_COMMAND);return{mode:t,host:r,port:T(e.ORCHA_RUNTIME_BRIDGE_PORT,5588),token:e.ORCHA_RUNTIME_BRIDGE_TOKEN||"",orchaUrl:a(e.ORCHA_RUNTIME_ORCHA_URL),nodeToken:e.ORCHA_RUNTIME_NODE_TOKEN||e.ORCHA_RUNTIME_BRIDGE_TOKEN||"",nodeId:a(e.ORCHA_RUNTIME_NODE_ID||e.HOSTNAME||"local-runtime-node"),nodeName:a(e.ORCHA_RUNTIME_NODE_NAME||e.ORCHA_RUNTIME_NODE_ID||e.HOSTNAME||"Local Runtime Node"),reconnectMs:T(e.ORCHA_RUNTIME_RECONNECT_MS,3e3),connectTimeoutMs:T(e.ORCHA_RUNTIME_CONNECT_TIMEOUT_MS||e.ORCHA_RUNTIME_WS_CONNECT_TIMEOUT_MS,1e4),defaultTargetCode:e.ORCHA_RUNTIME_DEFAULT_TARGET||"echo",requestLimitBytes:T(e.ORCHA_RUNTIME_REQUEST_LIMIT_BYTES,1048576),sessionPromptTimeoutMs:T(e.ORCHA_RUNTIME_SESSION_PROMPT_TIMEOUT_MS,36e5),permissionRequestTimeoutMs:T(e.ORCHA_RUNTIME_PERMISSION_TIMEOUT_MS,3e5),sessionIdleTtlMs:T(e.ORCHA_RUNTIME_SESSION_IDLE_TTL_MS,6e5),sessionCleanupIntervalMs:T(e.ORCHA_RUNTIME_SESSION_CLEANUP_INTERVAL_MS,6e4),maxSessionsPerTarget:T(e.ORCHA_RUNTIME_MAX_SESSIONS_PER_TARGET,8),openClawSessionIdleTtlMs:T(e.ORCHA_RUNTIME_OPENCLAW_SESSION_IDLE_TTL_MS,6e4),openClawMaxSessions:T(e.ORCHA_RUNTIME_OPENCLAW_MAX_SESSIONS,1),heartbeatIntervalMs:T(e.ORCHA_RUNTIME_HEARTBEAT_INTERVAL_MS,15e3),sandboxRequired:s,sandboxBrokerCommand:d||process.execPath,sandboxBrokerArguments:Ue(e.ORCHA_RUNTIME_SANDBOX_BROKER_ARGUMENTS,"ORCHA_RUNTIME_SANDBOX_BROKER_ARGUMENTS",d?[]:[l]),sandboxProbeTimeoutMs:T(e.ORCHA_RUNTIME_SANDBOX_PROBE_TIMEOUT_MS,1e4),sandboxTempRoot:a(e.ORCHA_RUNTIME_SANDBOX_TEMP_ROOT),trustedWorkspaceRoots:Ue(e.ORCHA_RUNTIME_TRUSTED_WORKSPACE_ROOTS,"ORCHA_RUNTIME_TRUSTED_WORKSPACE_ROOTS"),trustedToolchainRoots:Ue(e.ORCHA_RUNTIME_TRUSTED_TOOLCHAIN_ROOTS,"ORCHA_RUNTIME_TRUSTED_TOOLCHAIN_ROOTS"),egressProxyRequired:Zr(e.ORCHA_RUNTIME_EGRESS_PROXY_REQUIRED,t==="node"),egressProxySocket:a(e.ORCHA_RUNTIME_EGRESS_PROXY_SOCKET),egressProxyToken:a(e.ORCHA_RUNTIME_EGRESS_PROXY_TOKEN),egressGrantMaxTtlMs:T(e.ORCHA_RUNTIME_EGRESS_GRANT_MAX_TTL_MS,9e5),targets:wo(e.ORCHA_RUNTIME_TARGETS_JSON||"")}}function Qr(e){let t=a(e).toLowerCase().replace(/^\[|\]$/g,"");return t==="localhost"||t==="127.0.0.1"||t==="::1"}function wo(e){if(!a(e))return{};try{let t=JSON.parse(e);if(u(t))return t}catch(t){h("warn","config","invalid ORCHA_RUNTIME_TARGETS_JSON",{error:String(t)})}return{}}function Zr(e,t){let r=a(e).toLowerCase();if(!r)return t;if(["true","1","yes","on"].includes(r))return!0;if(["false","0","no","off"].includes(r))return!1;throw new Error(`invalid boolean configuration value: ${r}`)}function Ue(e,t,r=[]){let n=a(e);if(!n)return[...r];let s;try{s=JSON.parse(n)}catch{throw new Error(`${t} must be a JSON string array`)}if(!Array.isArray(s)||s.some(i=>typeof i!="string"))throw new Error(`${t} must be a JSON string array`);return s.map(i=>i.trim()).filter(Boolean)}function Io(e){let t=e.trim();if(!t||t.startsWith("#"))return null;let r=t.startsWith("export ")?t.slice(7).trimStart():t,n=r.indexOf("=");if(n<=0)return null;let s=r.slice(0,n).trim();if(!So.test(s))return null;let i=Oo(r.slice(n+1).trim());return[s,i]}function Oo(e){if(!e)return"";let t=e[0];if((t==='"'||t==="'")&&e.endsWith(t)){let r=e.slice(1,-1);return t==='"'?xo(r):r}return Ao(e).trim()}function xo(e){return e.replaceAll("\\n",`
18
+ `).replaceAll("\\r","\r").replaceAll("\\t"," ").replaceAll('\\"','"').replaceAll("\\\\","\\")}function Ao(e){let t=!1,r=!1;for(let n=0;n<e.length;n+=1){let s=e[n],i=e[n-1];if(s==="'"&&!r)t=!t;else if(s==='"'&&!t&&i!=="\\")r=!r;else if(s==="#"&&!t&&!r&&/\s/.test(i||""))return e.slice(0,n)}return e}import{createServer as Co}from"node:http";function $t(e,t,r){let n=JSON.stringify(r);e.writeHead(t,{"content-type":"application/json; charset=utf-8","content-length":Buffer.byteLength(n)}),e.end(n)}function z(e={}){return{ok:!0,...e}}function Pe(e,t,r){return{ok:!1,error:{code:e,message:t,...r===void 0?{}:{detail:r}}}}async function nn(e,t){let r=[],n=0;for await(let i of e){if(n+=i.length,n>t)throw Object.assign(new Error("request body too large"),{status:413,code:"REQUEST_TOO_LARGE"});r.push(i)}if(r.length===0)return{};let s=Buffer.concat(r).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 sn(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 on(e,t){let r={"GET /health":async()=>z(t.health()),"POST /agents/create":async n=>z(await t.createAgent(n)),"POST /agents/dispatch":async n=>z(await t.dispatch(n)),"POST /sessions/prompt":async n=>z(await t.prompt(n)),"POST /sessions/cancel":async n=>z(await t.cancel(n)),"POST /permissions/respond":async n=>z(await t.respondPermission(n))};return Co(async(n,s)=>{let i=new URL(n.url||"/",`http://${n.headers.host||`${e.host}:${e.port}`}`),o=`${n.method||"GET"} ${i.pathname}`,c=r[o];if(!c){$t(s,404,Pe("NOT_FOUND",`No route for ${o}`));return}try{sn(n,e.token);let l=n.method==="GET"?{}:await nn(n,e.requestLimitBytes);$t(s,200,await c(l))}catch(l){let d=l.status||500,f=l.code||"BRIDGE_INTERNAL";$t(s,d,Pe(f,l.message||String(l)))}})}var Do=Lo(import.meta.url),vo=".orcha-runtime-bridge.pid",Fo=".orcha-runtime-bridge.log",Ho=3,$o=36e5,{command:Bo,options:gn}=Ko(process.argv.slice(2));Vo(gn);en();var qo=rn();await jo(Bo,qo,gn);async function jo(e,t,r){switch(e){case"run":case"foreground":await cn(t);return;case"start":if(r.foreground){await cn(t);return}ln();return;case"reload":case"restart":await dn({quiet:!0}),ln();return;case"stop":await dn();return;case"status":Go();return;case"help":case"--help":case"-h":Xo();return;default:throw new Error(`Unknown command: ${e}`)}}async function cn(e){zo();let t=new Dt(e);if(await t.start(),e.mode==="server"){let n=on(e,t);un({bridge:t,server:n}),n.listen(e.port,e.host,()=>{h("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 r=new Ft(e,t);un({bridge:t,client:r}),r.start(),h("info","runtime-bridge","Orcha runtime node started",{nodeId:e.nodeId,nodeName:e.nodeName,orchaUrl:e.orchaUrl,targets:Object.keys(t.targets)})}function un({bridge:e,client:t,server:r}){let n=!1,s=i=>{if(n)return;n=!0;let o=Number(e?.sessions?.size||0)>0;h("info","runtime-bridge","runtime bridge shutting down",{signal:i});try{t?.stop?.()}catch(c){h("warn","runtime-bridge","runtime client stop failed",{error:String(c)})}Promise.resolve(e?.stop?.(`process_${String(i||"shutdown").toLowerCase()}`)).catch(c=>{h("warn","runtime-bridge","runtime bridge stop failed",{error:String(c)})}).finally(()=>{try{r?.close?.()}catch(c){h("warn","runtime-bridge","runtime server close failed",{error:String(c)})}}),setTimeout(()=>process.exit(0),o?8500:200)};process.once("SIGTERM",()=>s("SIGTERM")),process.once("SIGINT",()=>s("SIGINT"))}function ln(){let e=Fe(),t=_n(),r=He(e);if(r&&rt(r)){console.log(JSON.stringify({status:"already_running",pid:r,pidFile:e,logFile:t}));return}r&&De(e),pn(e),pn(t),Le(t);let n=Uo(t,"a"),s={...process.env,ORCHA_RUNTIME_PID_FILE:e,ORCHA_RUNTIME_LOG_FILE:t},i=No(process.execPath,[Do,"run"],{cwd:process.cwd(),detached:!0,env:s,stdio:["ignore",n,n]});i.unref(),bo(n),hn(e,`${i.pid}
19
+ `),console.log(JSON.stringify({status:"started",pid:i.pid,pidFile:e,logFile:t}))}async function dn({quiet:e=!1}={}){let t=Fe(),r=He(t);if(!r){e||console.log(JSON.stringify({status:"not_running",pidFile:t}));return}if(!rt(r)){De(t),e||console.log(JSON.stringify({status:"not_running",pid:r,pidFile:t}));return}process.kill(r,"SIGTERM"),!await fn(r,1e4)&&rt(r)&&(process.kill(r,"SIGKILL"),await fn(r,3e3)),De(t),e||console.log(JSON.stringify({status:"stopped",pid:r,pidFile:t}))}function Go(){let e=Fe(),t=_n(),r=He(e),n=!!(r&&rt(r));console.log(JSON.stringify({status:n?"running":"not_running",running:n,pid:n?r:null,pidFile:e,logFile:t}))}function Ko(e){let t=[],r={};for(let s=0;s<e.length;s+=1){let i=e[s];i==="--daemon"?r.daemon=!0:i==="--foreground"?r.foreground=!0:i==="--env-file"?r.envFile=e[++s]:i==="--pid-file"?r.pidFile=e[++s]:i==="--log-file"?r.logFile=e[++s]:t.push(i)}return{command:t[0]||"run",options:r}}function Vo(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 Fe(){return ve(process.cwd(),process.env.ORCHA_RUNTIME_PID_FILE||vo)}function _n(){return ve(process.cwd(),process.env.ORCHA_RUNTIME_LOG_FILE||Fo)}function zo(){let e=process.env.ORCHA_RUNTIME_LOG_FILE;if(!e)return;let t=Tn();if(t<=0)return;let r=ve(process.cwd(),e);Le(r,t);let n=Jo();n<=0||setInterval(()=>Le(r,t),n).unref()}function Le(e,t=Tn()){if(t<=0||!mn(e))return;let r=0,n="";try{if(r=an(e).size,r<=0)return;n=ke(e,"utf8")}catch(d){h("warn","runtime-bridge","runtime log cleanup skipped",{logFile:e,error:String(d)});return}let s=Date.now()-t*24*60*60*1e3,i=n.split(/\r?\n/),o=[],c=0;for(let d of i)d&&(Wo(d,s)?o.push(d):c+=1);if(c===0)return;let l="";try{an(e).size>r&&(l=ke(e,"utf8").slice(n.length));let f=[...o,...l.split(/\r?\n/).filter(Boolean)].join(`
19
20
  `);hn(e,f?`${f}
20
- `:""),p("info","runtime-bridge","runtime log cleanup completed",{logFile:e,retentionDays:t,removed:u})}catch(d){p("warn","runtime-bridge","runtime log cleanup failed",{logFile:e,error:String(d)})}}function ii(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 Tn(){return yn(process.env.ORCHA_RUNTIME_LOG_RETENTION_DAYS,Xs)}function oi(){return yn(process.env.ORCHA_RUNTIME_LOG_CLEANUP_INTERVAL_MS,Ys)}function yn(e,t){let n=Number.parseInt(String(e??""),10);return Number.isFinite(n)&&n>=0?n:t}function Qt(e){if(!mn(e))return null;let t=Number.parseInt(Wt(e,"utf8").trim(),10);return Number.isInteger(t)&&t>0?t:null}function G(e){try{return process.kill(e,0),!0}catch(t){return t?.code==="EPERM"}}async function fn(e,t){let n=Date.now();for(;Date.now()-n<t;){if(!G(e))return!0;await new Promise(r=>setTimeout(r,100))}return!G(e)}function pn(e){Ks(Gs(e),{recursive:!0})}function Xt(e){try{js(e,{force:!0})}catch{}}function ai(){console.log(`Usage: orcha-runtime-bridge [command] [options]
21
+ `:""),h("info","runtime-bridge","runtime log cleanup completed",{logFile:e,retentionDays:t,removed:c})}catch(d){h("warn","runtime-bridge","runtime log cleanup failed",{logFile:e,error:String(d)})}}function Wo(e,t){try{let r=JSON.parse(e);if(!r||typeof r!="object")return!0;let n=typeof r.ts=="string"?Date.parse(r.ts):Number.NaN;return!Number.isFinite(n)||n>=t}catch{return!0}}function Tn(){return yn(process.env.ORCHA_RUNTIME_LOG_RETENTION_DAYS,Ho)}function Jo(){return yn(process.env.ORCHA_RUNTIME_LOG_CLEANUP_INTERVAL_MS,$o)}function yn(e,t){let r=Number.parseInt(String(e??""),10);return Number.isFinite(r)&&r>=0?r:t}function He(e){if(!mn(e))return null;let t=Number.parseInt(ke(e,"utf8").trim(),10);return Number.isInteger(t)&&t>0?t:null}function rt(e){try{return process.kill(e,0),!0}catch(t){return t?.code==="EPERM"}}async function fn(e,t){let r=Date.now();for(;Date.now()-r<t;){if(!rt(e))return!0;await new Promise(n=>setTimeout(n,100))}return!rt(e)}function pn(e){Mo(ko(e),{recursive:!0})}function De(e){try{Po(e,{force:!0})}catch{}}function Xo(){console.log(`Usage: orcha-runtime-bridge [command] [options]
21
22
 
22
23
  Commands:
23
24
  run, foreground Run in the foreground. This is the default.
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ import{randomBytes as ae,randomUUID as ce,timingSafeEqual as ue}from"node:crypto";import de from"node:dns/promises";import T from"node:fs/promises";import w from"node:http";import x from"node:net";import U from"node:path";var C="orcha.egress-proxy/v1";var fe=z("ipv4",[["0.0.0.0",8],["10.0.0.0",8],["100.64.0.0",10],["127.0.0.0",8],["169.254.0.0",16],["172.16.0.0",12],["192.0.0.0",24],["192.0.2.0",24],["192.88.99.0",24],["192.168.0.0",16],["198.18.0.0",15],["198.51.100.0",24],["203.0.113.0",24],["224.0.0.0",4],["240.0.0.0",4]]),_e=z("ipv6",[["::",128],["::1",128],["::ffff:0:0",96],["64:ff9b::",96],["64:ff9b:1::",48],["100::",64],["2001::",23],["2001:db8::",32],["2002::",16],["3fff::",20],["fc00::",7],["fe80::",10],["fec0::",10],["ff00::",8]]);function F(){let e=String(process.env.ORCHA_EGRESS_PROXY_SOCKET||process.env.ORCHA_RUNTIME_EGRESS_PROXY_SOCKET||"/run/orcha-egress/egress.sock").trim(),r=String(process.env.ORCHA_EGRESS_PROXY_TOKEN||process.env.ORCHA_RUNTIME_EGRESS_PROXY_TOKEN||"").trim();if(!U.isAbsolute(e))throw new Error("egress_proxy_socket_must_be_absolute");if(!r)throw new Error("egress_proxy_token_required");return{socketPath:e,expectedToken:r,maxBodyBytes:N(process.env.ORCHA_EGRESS_PROXY_MAX_BODY_BYTES,64*1024,1024),maxRequestBytes:N(process.env.ORCHA_EGRESS_PROXY_MAX_REQUEST_BYTES,16*1024*1024,1024),maxGrantTtlMs:N(process.env.ORCHA_EGRESS_PROXY_MAX_GRANT_TTL_MS,15*6e4,1e3),maxConnectionsPerGrant:N(process.env.ORCHA_EGRESS_PROXY_MAX_CONNECTIONS,128,1)}}function Y(e){if(!U.isAbsolute(e.socketPath))throw new Error("egress_proxy_socket_must_be_absolute");if(!e.expectedToken)throw new Error("egress_proxy_token_required");let r=new Map,t=new Map,n=e.now||Date.now,o=e.dnsLookup||de.lookup,c=(s,a)=>{r.delete(s.credential),t.delete(s.grantId);for(let d of s.active)d.destroy(new Error(a));s.active.clear()},E=s=>{let a=pe(s.headers["proxy-authorization"]),d=r.get(a);if(!d)throw S(407,"proxy_authentication_required");if(d.expiresAt<=n())throw c(d,"egress_grant_expired"),S(407,"egress_grant_expired");if(d.connectionCount>=e.maxConnectionsPerGrant)throw S(429,"egress_connection_limit_exceeded");return d.connectionCount+=1,d},_=w.createServer(async(s,a)=>{if(s.method==="GET"&&s.url==="/health"){R(a,200,{status:"ok",proxy:"orcha-egress-proxy",protocolVersion:C,activeGrants:t.size});return}if(s.url==="/v1/grants"&&s.method==="POST"){if(!$(s.headers.authorization,e.expectedToken)){R(a,401,{error:"unauthorized"});return}try{let i=await L(s,e.maxBodyBytes);X(i.protocolVersion);let u=j(i.runId,"egress_run_id_required"),l=j(i.instanceId,"egress_instance_id_required"),O=P(i.policyRevision,"egress_policy_revision_invalid"),p=Math.min(P(i.ttlMs,"egress_grant_ttl_invalid"),e.maxGrantTtlMs),I=Math.min(P(i.maxTransferBytes,"egress_transfer_limit_invalid"),256*1024*1024),y={grantId:ce(),credential:ae(32).toString("base64url"),runId:u,instanceId:l,policyRevision:O,expiresAt:n()+p,maxTransferBytes:I,transferredBytes:0,connectionCount:0,active:new Set};r.set(y.credential,y),t.set(y.grantId,y),R(a,201,{grantId:y.grantId,credential:y.credential,expiresAt:new Date(y.expiresAt).toISOString(),policyRevision:y.policyRevision})}catch(i){R(a,400,{error:h(i)})}return}let d=/^\/v1\/grants\/([^/]+)\/revoke$/.exec(String(s.url||""));if(s.method==="POST"&&d){if(!$(s.headers.authorization,e.expectedToken)){R(a,401,{error:"unauthorized"});return}try{let i=await L(s,e.maxBodyBytes);X(i.protocolVersion);let u=t.get(decodeURIComponent(String(d[1]||"")));if(!u){R(a,200,{revoked:!1});return}if(u.runId!==String(i.runId||"")||u.instanceId!==String(i.instanceId||"")){R(a,403,{error:"egress_grant_owner_mismatch"});return}c(u,"egress_grant_revoked"),R(a,200,{revoked:!0,grantId:u.grantId})}catch(i){R(a,400,{error:h(i)})}return}let f;try{f=E(s);let i=await G(String(s.url||""),"http:",o),u=le(s.headers,i.url.host),l=w.request({host:i.address,family:i.family,port:i.port,method:s.method,path:`${i.url.pathname}${i.url.search}`,headers:u},p=>{let I={...p.headers};delete I["proxy-authenticate"],a.writeHead(p.statusCode||502,I),p.on("data",y=>{(!f||!H(f,y.length))&&(l.destroy(new Error("egress_transfer_limit_exceeded")),a.destroy(new Error("egress_transfer_limit_exceeded")))}),p.pipe(a)});b(f,l);let O=0;s.on("data",p=>{O+=p.length,(O>e.maxRequestBytes||!H(f,p.length))&&(l.destroy(new Error("egress_request_limit_exceeded")),s.destroy(new Error("egress_request_limit_exceeded")))}),l.once("error",p=>{a.headersSent?a.destroy(p):R(a,502,{error:h(p)})}),k(l,f,n),s.pipe(l),D(f,i.url.hostname,i.port,s.method||"GET")}catch(i){let u=V(i);a.headersSent||(u.status===407&&a.setHeader("Proxy-Authenticate",'Basic realm="Orcha Egress"'),R(a,u.status,{error:u.message}))}});_.on("connect",async(s,a,d)=>{let f=a,i,u;try{i=E(s);let l=await G(`https://${String(s.url||"")}`,"https:",o);u=x.connect({host:l.address,family:l.family,port:l.port}),b(i,f),b(i,u),k(f,i,n),k(u,i,n),u.once("connect",()=>{f.write(`HTTP/1.1 200 Connection Established\r
3
+ Proxy-Agent: Orcha-Egress\r
4
+ \r
5
+ `),d.length&&u?.write(d),v(f,u,i),v(u,f,i)}),u.once("error",O=>{f.destroyed||(f.write(`HTTP/1.1 502 Bad Gateway\r
6
+ Content-Type: text/plain\r
7
+ \r
8
+ ${h(O)}`),f.destroy())}),D(i,l.url.hostname,l.port,"CONNECT")}catch(l){u?.destroy();let O=V(l);if(!f.destroyed){let p=O.status===407?`Proxy-Authenticate: Basic realm="Orcha Egress"\r
9
+ `:"";f.end(`HTTP/1.1 ${O.status} ${w.STATUS_CODES[O.status]||"Rejected"}\r
10
+ ${p}Content-Length: 0\r
11
+ \r
12
+ `)}}});let m;return{server:_,activeGrantCount:()=>t.size,start:async()=>{await ge(e.socketPath),await new Promise((s,a)=>{let d=f=>a(f);_.once("error",d),_.listen(e.socketPath,()=>{_.removeListener("error",d),s()})}),await T.chmod(e.socketPath,432),m=setInterval(()=>{for(let s of t.values())s.expiresAt<=n()&&c(s,"egress_grant_expired")},1e3),m.unref?.()},stop:async()=>{m&&clearInterval(m);for(let s of[...t.values()])c(s,"egress_proxy_stopping");await new Promise((s,a)=>{_.close(d=>d?a(d):s())}),await Ee(e.socketPath)}}}async function G(e,r,t){let n;try{n=new URL(e)}catch{throw S(400,"egress_target_url_invalid")}if(n.protocol!==r||n.username||n.password)throw S(403,"egress_protocol_not_allowed");let o=n.hostname.replace(/^\[|\]$/g,"").replace(/\.$/,"").toLowerCase();if(!o||o==="localhost"||o.endsWith(".localhost")||o.endsWith(".local"))throw S(403,"egress_target_not_public");let c=Number(n.port||(r==="https:"?443:80));if(r==="https:"&&c!==443||r==="http:"&&c!==80)throw S(403,"egress_port_not_allowed");let E=x.isIP(o),_=E?[{address:o,family:E}]:await t(o,{all:!0,verbatim:!0}),m=_.filter(a=>J(a.address));if(!_.length||m.length!==_.length)throw S(403,"egress_target_not_public");let s=m[0];return{url:n,address:s.address,family:s.family,port:c}}function J(e){let r=e.toLowerCase().split("%")[0]||"";if(r.startsWith("::ffff:"))return J(r.slice(7));let t=x.isIP(r);if(t===4)return!fe.check(r,"ipv4");if(t===6){let n=Number.parseInt(r.split(":",1)[0]||"",16);return n>=8192&&n<=16383&&!_e.check(r,"ipv6")}return!1}function z(e,r){let t=new x.BlockList;for(let[n,o]of r)t.addSubnet(n,o,e);return t}function le(e,r){let t={...e,host:r};return delete t["proxy-authorization"],delete t["proxy-connection"],delete t.connection,t}function pe(e){let r=Array.isArray(e)?String(e[0]||""):String(e||""),t=/^Basic\s+(.+)$/i.exec(r.trim());if(!t)return"";try{let n=Buffer.from(String(t[1]||""),"base64").toString("utf8"),o=n.indexOf(":");return o<0||n.slice(0,o)!=="orcha"?"":n.slice(o+1)}catch{return""}}function H(e,r){return e.transferredBytes+=Math.max(0,r),e.transferredBytes<=e.maxTransferBytes}function v(e,r,t){e.on("data",n=>{H(t,n.length)||(e.destroy(new Error("egress_transfer_limit_exceeded")),r.destroy(new Error("egress_transfer_limit_exceeded")))}),e.pipe(r)}function b(e,r){e.active.add(r),"once"in r&&typeof r.once=="function"&&r.once("close",()=>e.active.delete(r))}function k(e,r,t){e.setTimeout(Math.max(1,r.expiresAt-t()),()=>{e.destroy(new Error("egress_grant_expired"))})}function D(e,r,t,n){process.stderr.write(`${JSON.stringify({event:"egress_request",runId:e.runId,instanceId:e.instanceId,policyRevision:e.policyRevision,hostname:r,port:t,method:n})}
13
+ `)}async function L(e,r){let t=[],n=0;for await(let E of e){let _=Buffer.isBuffer(E)?E:Buffer.from(E);if(n+=_.length,n>r)throw new Error("request_body_too_large");t.push(_)}let o=Buffer.concat(t).toString("utf8"),c=o?JSON.parse(o):{};return c&&typeof c=="object"&&!Array.isArray(c)?c:{}}function $(e,r){let t=String(e||"").replace(/^Bearer\s+/i,""),n=Buffer.from(t),o=Buffer.from(r);return n.length===o.length&&ue(n,o)}function X(e){if(e!==C)throw new Error("unsupported_egress_protocol_version")}function j(e,r){let t=String(e||"").trim();if(!t)throw new Error(r);return t}function P(e,r){let t=Number(e);if(!Number.isInteger(t)||t<1)throw new Error(r);return t}function S(e,r){let t=new Error(r);return t.status=e,t}function V(e){return e instanceof Error&&"status"in e&&Number.isInteger(e.status)?e:S(502,h(e))}function h(e){return e instanceof Error?e.message:String(e||"egress_proxy_failed")}function R(e,r,t){e.writeHead(r,{"Content-Type":"application/json; charset=utf-8"}),e.end(JSON.stringify(t))}async function ge(e){await T.mkdir(U.dirname(e),{recursive:!0,mode:488});try{if(!(await T.lstat(e)).isSocket())throw new Error("egress_proxy_socket_path_is_not_socket");await T.unlink(e)}catch(r){if(K(r)!=="ENOENT")throw r}}async function Ee(e){try{(await T.lstat(e)).isSocket()&&await T.unlink(e)}catch(r){if(K(r)!=="ENOENT")throw r}}function K(e){return typeof e=="object"&&e!==null&&"code"in e?String(e.code||""):""}function N(e,r,t){let n=Number(e||r);return Number.isFinite(n)?Math.max(t,Math.trunc(n)):r}var W=[22,19,0];function me(e){let r=/^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(String(e||"").trim());if(!r)return!1;let t=r.slice(1,4).map(Number);for(let n=0;n<W.length;n+=1){let o=W[n]??0;if((t[n]||0)>o)return!0;if((t[n]||0)<o)return!1}return!0}function q(e=process.versions.node){if(!me(e))throw new Error(`Orcha Managed Agent Runtime requires Node.js >=22.19.0; current version is ${e||"unknown"}`)}function g(e,r=2){return String(e).padStart(r,"0")}function Q(e){let r=e>=0?"+":"-",t=Math.abs(e);return`${r}${g(Math.floor(t/60))}:${g(t%60)}`}function Re(e){let r=-e.getTimezoneOffset();return[`${e.getFullYear()}-${g(e.getMonth()+1)}-${g(e.getDate())}`,`T${g(e.getHours())}:${g(e.getMinutes())}:${g(e.getSeconds())}.${g(e.getMilliseconds(),3)}`,Q(r)].join("")}function Oe(e,r){let t=new Intl.DateTimeFormat("en-US",{timeZone:r,hourCycle:"h23",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}),n={};for(let o of t.formatToParts(e))o.type!=="literal"&&(n[o.type]=Number(o.value));return n}function ye(e,r){let t=Oe(e,r),n=Date.UTC(t.year,t.month-1,t.day,t.hour,t.minute,t.second,e.getMilliseconds()),o=Math.round((n-e.getTime())/6e4);return[`${t.year}-${g(t.month)}-${g(t.day)}`,`T${g(t.hour)}:${g(t.minute)}:${g(t.second)}.${g(e.getMilliseconds(),3)}`,Q(o)].join("")}function Se(e=new Date){let r=M(process.env.ORCHA_RUNTIME_LOG_TIMEZONE||process.env.TZ||"Asia/Shanghai");try{return ye(e,r)}catch{return Re(e)}}function ee(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function M(e){return String(e??"").trim()}var Te="[redacted]",Z=/(authorization|api[_-]?key|credential|password|secret|token)/i;function A(e,r=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(r.has(e))return"[circular]";r.add(e);let o={name:e.name,message:e.message};e.stack&&(o.stack=e.stack);for(let c of Object.keys(e))o[c]=A(e[c],r);return r.delete(e),o}if(r.has(e))return"[circular]";if(r.add(e),Array.isArray(e)){let o=e.map(c=>A(c,r));return r.delete(e),o}let t={},n=Z.test(M(e.name||e.key));for(let[o,c]of Object.entries(e))t[o]=Z.test(o)||n&&o.toLowerCase()==="value"?Te:A(c,r);return r.delete(e),t}function B(e,r,t,n={}){let o={ts:Se(),level:e,module:r,msg:t,...ee(n)?A(n):{}};console.error(JSON.stringify(o))}import{existsSync as he,readFileSync as Ie}from"node:fs";import{dirname as Fe,resolve as re}from"node:path";var Ne=/^[A-Za-z_][A-Za-z0-9_]*$/;function te(e=process.env,r=process.cwd()){let t=M(e.ORCHA_RUNTIME_ENV_FILE),n=t?re(r,t):re(r,".env");if(!he(n))return t&&B("warn","config","runtime env file not found",{path:n}),{loaded:!1,path:n,keys:[]};let o=[],c=Ie(n,"utf8");for(let E of c.split(/\r?\n/)){let _=xe(E);if(!_)continue;let[m,s]=_;Object.prototype.hasOwnProperty.call(e,m)||(e[m]=s,o.push(m))}return B("info","config","runtime env file loaded",{path:n,keyCount:o.length}),{loaded:!0,path:n,keys:o}}function xe(e){let r=e.trim();if(!r||r.startsWith("#"))return null;let t=r.startsWith("export ")?r.slice(7).trimStart():r,n=t.indexOf("=");if(n<=0)return null;let o=t.slice(0,n).trim();if(!Ne.test(o))return null;let c=Ae(t.slice(n+1).trim());return[o,c]}function Ae(e){if(!e)return"";let r=e[0];if((r==='"'||r==="'")&&e.endsWith(r)){let t=e.slice(1,-1);return r==='"'?Me(t):t}return Ce(e).trim()}function Me(e){return e.replaceAll("\\n",`
14
+ `).replaceAll("\\r","\r").replaceAll("\\t"," ").replaceAll('\\"','"').replaceAll("\\\\","\\")}function Ce(e){let r=!1,t=!1;for(let n=0;n<e.length;n+=1){let o=e[n],c=e[n-1];if(o==="'"&&!t)r=!r;else if(o==='"'&&!r&&c!=="\\")t=!t;else if(o==="#"&&!r&&!t&&/\s/.test(c||""))return e.slice(0,n)}return e}var ne=process.argv.indexOf("--env-file");if(ne>=0){let e=String(process.argv[ne+1]||"").trim();if(!e)throw new Error("--env-file requires a path");process.env.ORCHA_RUNTIME_ENV_FILE=e}q();te();var se=F(),ie=Y(se);await ie.start();process.stderr.write(`Orcha Runtime Egress Proxy listening on ${se.socketPath}
15
+ `);var oe=!1;for(let e of["SIGINT","SIGTERM"])process.on(e,()=>{oe||(oe=!0,ie.stop().finally(()=>process.exit(0)))});
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ import{spawn as C,spawnSync as M}from"node:child_process";import{constants as $}from"node:fs";import{access as F,lstat as O,mkdir as x,mkdtemp as L,realpath as T,rm as D,writeFile as h}from"node:fs/promises";import{tmpdir as H}from"node:os";import{isAbsolute as f,join as m,relative as U,resolve as v}from"node:path";var j="orcha.runtime-sandbox-broker/v1",B="orcha.process-isolation/v1",A=["/usr","/bin","/sbin","/lib","/lib64","/nix/store","/etc/ld.so.cache","/etc/ld.so.conf","/etc/ld.so.conf.d","/etc/ssl","/etc/pki","/etc/ca-certificates","/etc/localtime"];await q(process.argv.slice(2));async function q(t){if(t.includes("--probe")){await z();return}let e=t.indexOf("--");(e<0||e===t.length-1)&&r("sandbox_broker_command_required");let n=G(process.env.ORCHA_PROCESS_ISOLATION_REQUEST),o=t[e+1],s=t.slice(e+2),i=await X(n,o,s);await W(i)}async function z(){process.platform!=="linux"&&r("sandbox_broker_linux_required");let t=await p(process.env.ORCHA_RUNTIME_BWRAP_COMMAND||"bwrap"),e=await p(process.env.ORCHA_RUNTIME_PRLIMIT_COMMAND||"prlimit");t||r("bubblewrap_not_executable"),e||r("prlimit_not_executable");let n=await L(m(H(),"orcha-runtime-broker-probe-")),o=m(n,"workspace"),s=m(n,"temporary"),i=m(n,"outside-secret");try{await x(o,{recursive:!0,mode:448}),await x(m(s,"home"),{recursive:!0,mode:448}),await h(i,"must-not-be-visible",{mode:384}),await h(m(o,".env"),"must-not-be-readable",{mode:384});let a=await k({bwrap:t,prlimit:e,request:{workspace:o,cwd:o,filesystemMode:"workspace_write",networkMode:"denied",environmentMode:"allowlist",deniedRelativePaths:[".env"],temporaryDirectory:s,egressProxy:null,environment:{PATH:"/usr/bin:/bin",LANG:"C.UTF-8"},resourceLimits:{maxCpuSeconds:5,maxMemoryBytes:256*1024*1024,maxProcesses:16,maxOpenFiles:128,maxFileBytes:1024*1024},readOnlyToolchainRoots:[]},command:"/bin/sh",args:["-c",["set -eu",'test ! -e "$1"',"test ! -e /etc/shadow","test ! -s .env","test ! -e /run/docker.sock","test ! -e /var/run/docker.sock",'test -z "${ORCHA_RUNTIME_NODE_TOKEN:-}"',"printf probe > probe-write",'test "$(cat probe-write)" = probe',"default_route=0","if test -r /proc/net/route; then"," while read -r interface destination remainder; do",' test "$destination" = 00000000 && default_route=1'," done < /proc/net/route","fi",'test "$default_route" -eq 0','test "$(ulimit -n)" -le 128','test "$(ulimit -t)" -le 5'].join(`
3
+ `),"orcha-probe",i]}),c=M(a.command,a.args,{cwd:o,env:a.environment,encoding:"utf8",timeout:5e3});c.status!==0&&r(`sandbox_probe_failed:${String(c.stderr||c.stdout).trim().slice(0,500)}`);let _=await k({bwrap:t,prlimit:e,request:{...a.request,filesystemMode:"read_only"},command:"/bin/sh",args:["-c","if printf blocked > should-not-write 2>/dev/null; then exit 1; fi"]});M(_.command,_.args,{cwd:o,env:_.environment,encoding:"utf8",timeout:5e3}).status!==0&&r("sandbox_read_only_probe_failed"),process.stdout.write(JSON.stringify({enforced:!0,backend:"bubblewrap",protocolVersion:j,probes:{emptyRoot:!0,outsideWorkspaceDenied:!0,hostFilesystemDenied:!0,sensitiveFilesDenied:!0,environmentAllowlist:!0,dockerSocketDenied:!0,networkNamespace:!0,workspaceReadOnly:!0,workspaceWrite:!0,resourceLimits:!0}}))}finally{await D(n,{recursive:!0,force:!0})}}function G(t){let e;try{e=JSON.parse(String(t||""))}catch{r("sandbox_broker_request_invalid_json")}return(!e||typeof e!="object"||Array.isArray(e))&&r("sandbox_broker_request_required"),e.schemaVersion!==B&&r("sandbox_broker_request_version_unsupported"),(!String(e.runId||"").trim()||!String(e.instanceId||"").trim())&&r("sandbox_broker_run_identity_required"),["read_only","workspace_write"].includes(e.filesystemMode)||r("sandbox_broker_filesystem_mode_invalid"),["denied","restricted"].includes(e.networkMode)||r("sandbox_broker_network_mode_invalid"),e.environmentMode!=="allowlist"&&r("sandbox_broker_environment_mode_invalid"),e}async function X(t,e,n){process.platform!=="linux"&&r("sandbox_broker_linux_required");let o=await p(process.env.ORCHA_RUNTIME_BWRAP_COMMAND||"bwrap"),s=await p(process.env.ORCHA_RUNTIME_PRLIMIT_COMMAND||"prlimit");return o||r("bubblewrap_not_executable"),s||r("prlimit_not_executable"),await k({bwrap:o,prlimit:s,request:t,command:e,args:n})}async function k({bwrap:t,prlimit:e,request:n,command:o,args:s}){let i=await y(n.workspace,"sandbox_workspace_invalid"),a=await y(n.cwd,"sandbox_cwd_invalid");g(i,a)||r("sandbox_cwd_outside_workspace");let c=await y(n.temporaryDirectory,"sandbox_temporary_directory_invalid"),_=Y(n.environment),d=V(n.resourceLimits),S=await J(n.readOnlyToolchainRoots),P=await K(i,n.deniedRelativePaths),u=n.networkMode==="restricted"?await Q(n.egressProxy):null,N=await te(o,_.PATH,[i,...S]),I=await ee(c,u!==null),R=[e,`--cpu=${d.maxCpuSeconds}:${d.maxCpuSeconds}`,`--as=${d.maxMemoryBytes}:${d.maxMemoryBytes}`,`--nproc=${d.maxProcesses}:${d.maxProcesses}`,`--nofile=${d.maxOpenFiles}:${d.maxOpenFiles}`,`--fsize=${d.maxFileBytes}:${d.maxFileBytes}`,"--",N,...s.map(String)],E=["--die-with-parent","--new-session","--unshare-all","--clearenv","--dir","/etc","--dir","/run",...u?["--dir","/run/orcha-egress"]:[],...A.flatMap(l=>["--ro-bind-try",l,l]),...S.flatMap(l=>["--ro-bind",l,l]),...Object.entries(I).flatMap(([l,w])=>["--ro-bind",w,`/etc/${l}`]),n.filesystemMode==="workspace_write"?"--bind":"--ro-bind",i,i,...P,"--proc","/proc","--dev","/dev","--bind",c,"/tmp",...u?["--ro-bind",u.socketPath,"/run/orcha-egress/proxy.sock"]:[],"--chdir",a,...Object.entries(_).flatMap(([l,w])=>["--setenv",l,w]),"--setenv","HOME","/tmp/home","--setenv","TMPDIR","/tmp","--setenv","USER","orcha","--setenv","LOGNAME","orcha","--setenv","SHELL","/bin/sh",...u?Z(u):[],"--",...u?["/bin/sh","-c",["set -eu","ip link set lo up","socat TCP4-LISTEN:17891,bind=127.0.0.1,reuseaddr,fork UNIX-CONNECT:/run/orcha-egress/proxy.sock &","proxy_pid=$!",`trap 'kill "$proxy_pid" 2>/dev/null || true' EXIT INT TERM`,"sleep 0.05",'exec "$@"'].join(`
4
+ `),"orcha-egress-bridge",...R]:R];return{command:t,args:E,cwd:a,environment:{PATH:process.env.PATH||"/usr/bin:/bin",LANG:"C.UTF-8"},request:{...n,workspace:i,cwd:a,temporaryDirectory:c}}}async function W(t){let e=C(t.command,t.args,{cwd:t.cwd,env:t.environment,stdio:"inherit"}),n=s=>{try{e.kill(s)}catch{}};process.once("SIGTERM",()=>n("SIGTERM")),process.once("SIGINT",()=>n("SIGINT"));let o=await new Promise((s,i)=>{e.once("error",i),e.once("exit",(a,c)=>s({code:a,signal:c}))});o.signal&&process.kill(process.pid,o.signal),process.exitCode=Number.isInteger(o.code)?o.code:1}async function y(t,e){let n=String(t||"").trim();f(n)||r(e);let o;try{o=await T(n),(await O(o)).isDirectory()||r(e)}catch{r(e)}return o}function Y(t){(!t||typeof t!="object"||Array.isArray(t))&&r("sandbox_environment_invalid");let e={};for(let[n,o]of Object.entries(t))/^[A-Za-z_][A-Za-z0-9_]*$/.test(n)||r("sandbox_environment_key_invalid"),(o==null||typeof o=="object")&&r("sandbox_environment_value_invalid"),e[n]=String(o);return e.PATH||="/usr/local/bin:/usr/bin:/bin",e.LANG||="C.UTF-8",e}function V(t){let e=t&&typeof t=="object"?t:{};return{maxCpuSeconds:b(e.maxCpuSeconds,1,900,900),maxMemoryBytes:b(e.maxMemoryBytes,64*1024*1024,8*1024*1024*1024,2*1024*1024*1024),maxProcesses:b(e.maxProcesses,8,512,128),maxOpenFiles:b(e.maxOpenFiles,64,4096,1024),maxFileBytes:b(e.maxFileBytes,1024*1024,64*1024*1024,64*1024*1024)}}async function J(t){if(t==null)return[];(!Array.isArray(t)||t.some(n=>typeof n!="string"))&&r("sandbox_toolchain_roots_invalid");let e=[];for(let n of t){let o=await y(n,"sandbox_toolchain_root_invalid");["/","/etc","/home","/root","/var","/run","/private"].includes(o)&&r("sandbox_toolchain_root_forbidden"),e.push(o)}return[...new Set(e)]}async function K(t,e){Array.isArray(e)||r("sandbox_denied_paths_invalid"),e.length>1e4&&r("sandbox_denied_paths_limit_exceeded");let n=[];for(let o of e){let s=String(o||"").trim();(!s||f(s))&&r("sandbox_denied_path_invalid");let i=v(t,s);g(t,i)||r("sandbox_denied_path_outside_workspace");let a;try{a=await O(i)}catch{continue}n.push(a.isDirectory()?"--tmpfs":"--ro-bind"),a.isDirectory()||n.push("/dev/null"),n.push(i)}return n}async function Q(t){(!t||typeof t!="object")&&r("sandbox_egress_required");let e=String(t.socketPath||"").trim(),n=String(t.credential||"").trim(),o=String(t.grantId||"").trim();(!f(e)||!n||!o)&&r("sandbox_egress_invalid");try{(await O(e)).isSocket()||r("sandbox_egress_socket_invalid")}catch{r("sandbox_egress_socket_invalid")}for(let s of["ip","socat"])await p(s)||r(`sandbox_${s}_not_executable`);return{socketPath:e,credential:n,grantId:o}}function Z(t){let e=`http://orcha:${t.credential}@127.0.0.1:17891`;return["--setenv","HTTP_PROXY",e,"--setenv","HTTPS_PROXY",e,"--setenv","ALL_PROXY",e,"--setenv","http_proxy",e,"--setenv","https_proxy",e,"--setenv","all_proxy",e,"--setenv","NO_PROXY","","--setenv","no_proxy",""]}async function ee(t,e){let n=m(t,".orcha-system");await x(n,{recursive:!0,mode:448});let o={passwd:`orcha:x:65534:65534:Orcha Runtime:/tmp/home:/bin/sh
5
+ `,group:`orcha:x:65534:
6
+ `,hosts:`127.0.0.1 localhost
7
+ ::1 localhost
8
+ `,hostname:`orcha-sandbox
9
+ `,"nsswitch.conf":`hosts: files dns
10
+ `,"resolv.conf":e?`nameserver 127.0.0.1
11
+ `:""},s={};for(let[i,a]of Object.entries(o)){let c=m(n,i);await h(c,a,{mode:384}),s[i]=c}return s}async function te(t,e,n){let o=await p(t,e);return o||r("sandbox_runtime_command_not_executable"),[...A.filter(i=>!i.includes(".")),...n].some(i=>g(i,o))||r("sandbox_runtime_command_outside_toolchain"),o}async function p(t,e=process.env.PATH||""){let n=String(t||"").trim();if(!n)return"";let o=f(n)?[n]:String(e).split(":").filter(Boolean).map(s=>m(s,n));for(let s of o)try{return await F(s,$.X_OK),await T(s)}catch{}return""}function b(t,e,n,o){let s=Number(t);return Number.isInteger(s)&&s>=e&&s<=n?s:o}function g(t,e){let n=U(v(t),v(e));return n===""||!n.startsWith("..")&&!f(n)}function r(t){process.stderr.write(`${String(t)}
12
+ `),process.exit(1)}
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "@orcha-ai/runtime-bridge",
3
- "version": "0.1.28",
3
+ "version": "0.1.30",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Local Orcha runtime bridge for ACP-compatible agent runtimes.",
7
7
  "license": "UNLICENSED",
8
8
  "homepage": "https://orcha.tansuo.cloud",
9
9
  "bin": {
10
- "orcha-runtime-bridge": "./bin/orcha-runtime-bridge.js"
10
+ "orcha-runtime-bridge": "./bin/orcha-runtime-bridge.js",
11
+ "orcha-runtime-sandbox-broker": "./bin/orcha-runtime-sandbox-broker.js",
12
+ "orcha-runtime-egress-proxy": "./bin/orcha-runtime-egress-proxy.js"
11
13
  },
12
14
  "files": [
13
15
  "bin",
@@ -29,6 +31,6 @@
29
31
  "access": "public"
30
32
  },
31
33
  "engines": {
32
- "node": ">=20"
34
+ "node": ">=22.19.0"
33
35
  }
34
36
  }