@orcha-ai/runtime-bridge 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/orcha-runtime-bridge.js +10 -10
- package/package.json +1 -1
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{spawn as
|
|
3
|
-
`):""}var C=class{constructor(
|
|
2
|
+
import{spawn as Rt}from"node:child_process";import{closeSync as St,existsSync as Ut,mkdirSync as xt,openSync as Ot,readFileSync as Nt,rmSync as At,writeFileSync as bt}from"node:fs";import{dirname as Mt,resolve as Ae}from"node:path";import{fileURLToPath as kt}from"node:url";import{randomUUID as $}from"node:crypto";var U="0.1.1";function x(){return new Date().toISOString()}function u(s){return s!==null&&typeof s=="object"&&!Array.isArray(s)}function o(s){return String(s??"").trim()}function T(s,e){let t=Number.parseInt(String(s??""),10);return Number.isFinite(t)?t:e}function v(s){return Array.isArray(s)?s.map(String):[]}function m(s,e,t,r={}){let n={ts:x(),level:s,module:e,msg:t,...u(r)?r:{}};console.error(JSON.stringify(n))}function P(s){return Array.isArray(s)?s.map(e=>u(e)?e.type==="text"?o(e.text):e.type==="file"?o(e.uri):e.type==="image"?o(e.uri):"":"").filter(Boolean).join(`
|
|
3
|
+
`):""}var C=class{constructor(e){this.agent=e,this.sessionCounter=0}async sessionNew(){return this.sessionCounter+=1,{sessionId:`echo-${this.agent.agentId}-${this.sessionCounter}`}}async sessionPrompt(e,t){let r=P(e.prompt);return t({sessionId:e.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 Pe}from"node:child_process";var A="2.0",Ce=3e4;function Le(s){return{code:Number.isInteger(s?.code)?s.code:-32e3,message:o(s?.message)||String(s),data:u(s?.data)?s.data:void 0}}function Fe(s){return u(s)&&"id"in s&&!("method"in s)}function He(s){return u(s)&&typeof s.method=="string"&&"id"in s}function De(s){return u(s)&&typeof s.method=="string"&&!("id"in s)}var L=class{constructor({command:e,args:t=[],cwd:r,env:n,label:i,framing:a="line"}){this.command=e,this.args=Array.isArray(t)?t.map(String):[],this.cwd=r||process.cwd(),this.env={...process.env,...u(n)?n:{}},this.label=i||e,this.framing=a==="content-length"?"content-length":"line",this.child=null,this.lineBuffer="",this.headerBuffer=Buffer.alloc(0),this.seq=0,this.pending=new Map,this.notificationHandlers=new Map,this.requestHandlers=new Map,this.exitHandlers=new Set}async start({initialize:e=!0,initializeParams:t={}}={}){this.child&&!this.child.killed||(this.child=Pe(this.command,this.args,{cwd:this.cwd,env:this.env,stdio:["pipe","pipe","pipe"]}),this.child.stdout.on("data",r=>this.onStdout(r)),this.child.stderr.setEncoding("utf8"),this.child.stderr.on("data",r=>{let n=r.trimEnd();n&&m("debug","runtime.stderr","runtime stderr",{target:this.label,text:n})}),this.child.on("exit",(r,n)=>this.handleExit(r,n)),this.child.on("error",r=>this.rejectAll(r)),e&&await this.call("initialize",{protocolVersion:1,clientCapabilities:{},...t}).catch(r=>{throw Object.assign(new Error(`runtime initialize failed: ${r.message}`),{code:"RUNTIME_INITIALIZE_FAILED"})}))}onStdout(e){if(this.framing==="content-length"){this.onContentLengthData(Buffer.isBuffer(e)?e:Buffer.from(e));return}this.onLineData(e.toString("utf8"))}onLineData(e){this.lineBuffer+=e;let t=this.lineBuffer.split(/\r?\n/);this.lineBuffer=t.pop()||"";for(let r of t){let n=r.trim();n&&this.dispatchRaw(n)}}onContentLengthData(e){for(this.headerBuffer=Buffer.concat([this.headerBuffer,e]);this.headerBuffer.length>0;){let t=this.headerBuffer.indexOf(`\r
|
|
4
4
|
\r
|
|
5
|
-
`);if(
|
|
5
|
+
`);if(t<0)return;let n=this.headerBuffer.subarray(0,t).toString("utf8").match(/content-length:\s*(\d+)/i);if(!n){m("warn","runtime.protocol","missing Content-Length header",{target:this.label}),this.headerBuffer=Buffer.alloc(0);return}let i=Number.parseInt(n[1],10),a=t+4,c=a+i;if(this.headerBuffer.length<c)return;let d=this.headerBuffer.subarray(a,c).toString("utf8");this.headerBuffer=this.headerBuffer.subarray(c),this.dispatchRaw(d)}}dispatchRaw(e){let t;try{t=JSON.parse(e)}catch(r){m("warn","runtime.protocol","invalid JSON frame",{target:this.label,error:String(r)});return}this.dispatch(t)}dispatch(e){if(Fe(e)){this.resolveResponse(e);return}if(He(e)){this.handleRequest(e);return}De(e)&&this.handleNotification(e)}resolveResponse(e){let t=String(e.id),r=this.pending.get(t);r&&(clearTimeout(r.timer),this.pending.delete(t),e.error?r.reject(new Error(u(e.error)?String(e.error.message||"runtime error"):String(e.error))):r.resolve(e.result))}async handleRequest(e){let t=this.requestHandlers.get(e.method);if(!t){this.writeFrame({jsonrpc:A,id:e.id,error:{code:-32601,message:`method not found: ${e.method}`}});return}try{let r=await t(u(e.params)?e.params:{},e);this.writeFrame({jsonrpc:A,id:e.id,result:r??{}})}catch(r){this.writeFrame({jsonrpc:A,id:e.id,error:Le(r)})}}handleNotification(e){let t=this.notificationHandlers.get(e.method);if(t)for(let r of t)r(u(e.params)?e.params:{},e)}call(e,t={},r=Ce){if(!this.child||!this.child.stdin||this.child.killed)return Promise.reject(new Error("runtime process is not running"));let n=`${e}_${++this.seq}`,i={jsonrpc:A,id:n,method:e,params:t};return new Promise((a,c)=>{let d=setTimeout(()=>{this.pending.delete(n),c(new Error(`${e} timed out after ${r}ms`))},r);this.pending.set(n,{resolve:a,reject:c,timer:d}),this.writeFrame(i,l=>{l&&(clearTimeout(d),this.pending.delete(n),c(l))})})}notify(e,t={}){this.writeFrame({jsonrpc:A,method:e,params:t})}writeFrame(e,t){if(!this.child?.stdin||this.child.killed){t?.(new Error("runtime process is not running"));return}let r=JSON.stringify(e),n=this.framing==="content-length"?`Content-Length: ${Buffer.byteLength(r,"utf8")}\r
|
|
6
6
|
\r
|
|
7
|
-
${
|
|
8
|
-
`;this.child.stdin.write(r,e)}onNotification(t,e){let n=this.notificationHandlers.get(t)||new Set;return n.add(e),this.notificationHandlers.set(t,n),()=>{n.delete(e),n.size===0&&this.notificationHandlers.delete(t)}}onRequest(t,e){return this.requestHandlers.set(t,e),()=>this.requestHandlers.delete(t)}onExit(t){return this.exitHandlers.add(t),()=>this.exitHandlers.delete(t)}rejectAll(t){for(let e of this.pending.values())clearTimeout(e.timer),e.reject(t);this.pending.clear()}handleExit(t,e){this.rejectAll(new Error(`runtime exited before response (${t}/${e})`));for(let n of this.exitHandlers)n(t,e)}stop(t="stop"){!this.child||this.child.killed||(h("info","runtime","stopping runtime",{target:this.label,reason:t}),this.child.kill("SIGTERM"),setTimeout(()=>{this.child&&!this.child.killed&&this.child.kill("SIGKILL")},5e3).unref())}};var O=class{constructor(t,e,n={},r={}){this.agent=t,this.target=e,this.callbacks=n,this.options=r,this.proc=null,this.permissionHandlers=new Map}async ensureStarted(){if(this.proc)return;let t=o(this.target.command);if(!t)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);this.proc=new L({command:t,args:k(this.target.args),cwd:o(this.target.cwd)||this.agent.workspace||process.cwd(),env:d(this.target.env)?this.target.env:{},label:`${this.agent.agentId}:${this.agent.targetCode}`,framing:o(this.target.framing||"line")}),this.proc.onRequest("session/request_permission",e=>this.handlePermissionRequest(e)),this.proc.onRequest("session/requestPermission",e=>this.handlePermissionRequest(e)),await this.proc.start({initialize:this.target.initialize!==!1,initializeParams:{clientInfo:{name:"orcha-runtime-bridge",version:"0.1.0"},...d(this.target.initializeParams)?this.target.initializeParams:{}}})}async sessionNew(t={}){return await this.ensureStarted(),this.proc.call("session/new",t)}async sessionPrompt(t,e){await this.ensureStarted();let n=o(t.sessionId),r=this.proc.onNotification("session/update",a=>{let c=o(a.sessionId);(!c||c===n)&&e(a)}),i=async a=>this.callbacks.onPermissionRequest?.({agent:this.agent,runtimeSessionId:n,request:a,emitUpdate:e})||{outcome:"denied",reason:"permission handler is not configured"};n&&this.permissionHandlers.set(n,i),this.permissionHandlers.set("*",i);try{return await this.proc.call("session/prompt",t,this.options.sessionPromptTimeoutMs)}finally{r(),n&&this.permissionHandlers.delete(n),this.permissionHandlers.delete("*")}}async sessionCancel(t){return await this.ensureStarted(),this.proc.call("session/cancel",t,5e3).catch(()=>({ok:!0}))}async handlePermissionRequest(t){let e=o(t.sessionId),n=this.permissionHandlers.get(e)||this.permissionHandlers.get("*");return n?n(t):{outcome:"denied",reason:"no active Orcha permission handler"}}stop(t){this.proc?.stop(t)}};var v=class extends O{constructor(t,e,n,r={},i={}){let a=o(n).replace(/[^A-Za-z0-9._-]+/g,"-")||"default",c=o(e.command)||"openclaw",u=Array.isArray(e.args)?e.args.map(String):[],l=u.length>0?u:["acp","--session",`agent:${t.agentId}:${a}`];super(t,{...e,command:c,args:l},r,i)}};import{spawn as Nt}from"node:child_process";import{randomUUID as F}from"node:crypto";import{existsSync as Ut,readFileSync as bt,unlinkSync as At}from"node:fs";import{tmpdir as Mt}from"node:os";import{basename as nt,extname as kt,join as Pt}from"node:path";var Ct=36e5,Lt=5e3;function H(s,t){try{s.kill(t)}catch{}}function w(s){if(typeof s=="string")return s;if(Array.isArray(s))return s.map(t=>w(t)).join("");if(!d(s))return"";for(let t of["text","delta","output_text","content","message","output"]){let e=w(s[t]);if(e)return e}return""}function vt(s){if(!d(s))return"";let t=d(s.payload)?s.payload:{};if(o(s.type)==="event_msg"){if(o(t.type)==="agent_message")return o(t.message);if(o(t.type)==="task_complete")return o(t.last_agent_message)}if(o(s.type)==="response_item"&&o(t.type)==="message"&&o(t.role)==="assistant")return w(t.content)||w(t.message);let e=w(s.delta)||w(s.text)||w(s.content);if(e)return e;let n=d(s.item)?s.item:{};return o(n.role)==="assistant"||o(n.type)==="message"?w(n.content)||w(n.text)||w(n.message):""}function Ht(s){let t=kt(o(s)).toLowerCase();return t===".jpg"||t===".jpeg"?"image/jpeg":t===".webp"?"image/webp":t===".gif"?"image/gif":"image/png"}function Ft(s,t){let e=typeof s=="string"?s.trim():"";return e?e.startsWith("data:")?e:`data:${t};base64,${e.replace(/\s+/g,"")}`:""}function Dt(s){if(!d(s))return null;let t=d(s.payload)?s.payload:{},e=o(s.type),n=o(t.type);if(!(e==="event_msg"&&n==="image_generation_end"||e==="response_item"&&n==="image_generation_call"))return null;let r=o(t.call_id||t.id),i=o(t.saved_path||t.savedPath),a=o(t.revised_prompt||t.revisedPrompt),c=Ht(i),l=Ft(t.result,c)||i;if(!l)return null;let f=i?nt(i):`${r||F()}.png`;return{artifactType:"image",type:"image",title:f||"Generated image",summary:a||"Generated image",content:{prompt:a||void 0,imageUrl:l,previewUrl:l,fileUrl:l,mimeType:c},previewUrl:l,fileUrl:l,metadata:{source:"codex_cli_image_generation",eventType:n,callId:r||void 0,savedPath:i||void 0,filename:f,mimeType:c,revisedPrompt:a||void 0}}}function $t(s,t){if(!t)return;let e=d(t.metadata)?t.metadata:{},n=o(e.callId||e.savedPath||t.previewUrl||t.fileUrl);if(!n)return;let r=s.artifacts.get(n);if(!r){s.artifacts.set(n,t);return}r.content={...d(r.content)?r.content:{},...d(t.content)?t.content:{}},r.metadata={...d(r.metadata)?r.metadata:{},...e},r.previewUrl=t.previewUrl||r.previewUrl,r.fileUrl=t.fileUrl||r.fileUrl,r.summary=t.summary||r.summary,r.title=t.title||r.title}function Bt(s){if(!d(s)||!d(s.payload))return d(s)?s:{value:s};let t=o(s.payload.type);if(t!=="image_generation_end"&&t!=="image_generation_call")return s;let e={...s.payload};return typeof e.result=="string"&&e.result&&(e.result="<omitted>",e.resultLength=s.payload.result.length),{...s,payload:e}}function jt(s,t,e){return e.captureLastMessage===!1||t.includes("--output-last-message")||t.includes("-o")?!1:e.captureLastMessage===!0?!0:nt(s)==="codex"}function qt(s){if(!s||!Ut(s))return"";try{return bt(s,"utf8").trim()}catch{return""}finally{try{At(s)}catch{}}}var D=class{constructor(t,e,n={}){this.agent=t,this.target=e,this.options=n,this.active=new Map}async sessionNew(){return{sessionId:`cli-${this.agent.agentId}-${F()}`}}async sessionPrompt(t,e){let n=o(this.target.command);if(!n)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);let r=o(t.sessionId)||F(),i=P(t.prompt),a=o(this.target.promptMode||"stdin"),c=this.buildArgs(a,i),u=jt(n,c,this.target)?Pt(Mt(),`orcha-runtime-last-message-${F()}.txt`):"";u&&c.push("--output-last-message",u);let l=g(this.target.timeoutMs||this.target.sessionPromptTimeoutMs,g(this.options.sessionPromptTimeoutMs,Ct)),f={...process.env,...d(this.target.env)?this.target.env:{},...a==="env"?{ORCHA_RUNTIME_PROMPT:i}:{},ORCHA_AGENT_ID:this.agent.agentId,ORCHA_SESSION_ID:r},p=Nt(n,c,{cwd:o(this.target.cwd)||this.agent.workspace||process.cwd(),env:f,stdio:["pipe","pipe","pipe"]});this.active.set(r,p),h("info","runtime.cli","runtime prompt started",{target:this.agent.targetCode,sessionId:r,pid:p.pid,timeoutMs:l});let I="",_=o(this.target.outputMode||"text"),T={artifacts:new Map,emittedTexts:new Set,value:""};return p.stdout.setEncoding("utf8"),p.stdout.on("data",S=>this.handleStdout(S,_,T,r,e)),p.stderr.setEncoding("utf8"),p.stderr.on("data",S=>{I+=S,this.target.emitStderr===!0&&e({sessionId:r,update:{sessionUpdate:"runtime_stderr_chunk",content:{type:"text",text:S}}})}),a==="stdin"?p.stdin.end(i):p.stdin.end(),await new Promise((S,_t)=>{let U=!1,Y=!1,E=null,X=setTimeout(()=>{Y=!0,h("warn","runtime.cli","runtime prompt timed out; terminating child",{target:this.agent.targetCode,sessionId:r,pid:p.pid,timeoutMs:l}),H(p,"SIGTERM"),E=setTimeout(()=>{h("warn","runtime.cli","runtime prompt force killing child",{target:this.agent.targetCode,sessionId:r,pid:p.pid}),H(p,"SIGKILL")},Lt),E.unref?.(),et(Object.assign(new Error(`runtime CLI timed out after ${l}ms`),{code:"RUNTIME_CLI_TIMEOUT"}))},l);X.unref?.();let tt=()=>{clearTimeout(X),E&&!Y&&clearTimeout(E),this.active.delete(r)},Et=m=>{U||(U=!0,tt(),S(m))},et=m=>{U||(U=!0,tt(),_t(m))};p.on("error",m=>{h("warn","runtime.cli","runtime child error",{target:this.agent.targetCode,sessionId:r,pid:p.pid,error:String(m?.message||m)}),et(m)}),p.on("exit",(m,st)=>{E&&(clearTimeout(E),E=null),_==="json-lines"&&T.value.trim()&&this.handleStdout(`
|
|
9
|
-
`,_,
|
|
10
|
-
`}}})}}}async sessionCancel(
|
|
11
|
-
`)}];return this.prompt({...
|
|
12
|
-
`).replaceAll("\\r","\r").replaceAll("\\t"," ").replaceAll('\\"','"').replaceAll("\\\\","\\")}function
|
|
13
|
-
`),console.log(JSON.stringify({status:"started",pid:
|
|
7
|
+
${r}`:`${r}
|
|
8
|
+
`;this.child.stdin.write(n,t)}onNotification(e,t){let r=this.notificationHandlers.get(e)||new Set;return r.add(t),this.notificationHandlers.set(e,r),()=>{r.delete(t),r.size===0&&this.notificationHandlers.delete(e)}}onRequest(e,t){return this.requestHandlers.set(e,t),()=>this.requestHandlers.delete(e)}onExit(e){return this.exitHandlers.add(e),()=>this.exitHandlers.delete(e)}rejectAll(e){for(let t of this.pending.values())clearTimeout(t.timer),t.reject(e);this.pending.clear()}handleExit(e,t){this.rejectAll(new Error(`runtime exited before response (${e}/${t})`));for(let r of this.exitHandlers)r(e,t)}stop(e="stop"){!this.child||this.child.killed||(m("info","runtime","stopping runtime",{target:this.label,reason:e}),this.child.kill("SIGTERM"),setTimeout(()=>{this.child&&!this.child.killed&&this.child.kill("SIGKILL")},5e3).unref())}};import{randomUUID as ue}from"node:crypto";import{existsSync as Be,readFileSync as $e,statSync as je}from"node:fs";import{basename as le,extname as pe}from"node:path";var qe=25*1024*1024;function me(s,e=""){let t=o(e);if(t)return t;let r=pe(o(s)).toLowerCase();return r===".jpg"||r===".jpeg"?"image/jpeg":r===".webp"?"image/webp":r===".gif"?"image/gif":"image/png"}function he(s,e){let t=typeof s=="string"?s.trim():"";return!t||t==="<omitted>"?"":t.startsWith("data:")?t:`data:${e};base64,${t.replace(/\s+/g,"")}`}function W(s,e){let t=o(s);if(!t||!Be(t))return"";try{let r=je(t);return!r.isFile()||r.size<=0||r.size>qe?"":`data:${e};base64,${$e(t).toString("base64")}`}catch{return""}}function g(...s){for(let e of s){let t=o(e);if(t)return t}return""}function Ge(s,e){let t=o(s);return!t||t.startsWith("data:")||/^https?:\/\//i.test(t)?t:W(t,e)||t}function ze(s,e,t,r){let n=t.toLowerCase();if(n==="image"||n==="picture")return!0;let i=g(r,s.previewUrl,s.fileUrl,s.imageUrl,s.dataUrl,s.url,s.uri,e.previewUrl,e.fileUrl,e.imageUrl,e.dataUrl,e.url,e.uri),a=pe(i.split("?",1)[0].split("#",1)[0]).toLowerCase();return[".png",".jpg",".jpeg",".webp",".gif"].includes(a)}function V(s,{source:e="runtime_image_generation_event"}={}){if(!u(s))return null;let t=u(s.payload)?s.payload:{},r=o(s.type),n=o(t.type);if(!(r==="event_msg"&&n==="image_generation_end"||r==="response_item"&&n==="image_generation_call"))return null;let i=g(t.call_id,t.id),a=g(t.saved_path,t.savedPath),c=g(t.revised_prompt,t.revisedPrompt),d=me(a,t.mimeType||t.mime_type),h=he(t.result,d)||W(a,d)||a;if(!h)return null;let p=a?le(a):`${i||ue()}.png`;return{artifactType:"image",type:"image",title:p||"Generated image",summary:c||"Generated image",content:{prompt:c||void 0,imageUrl:h,previewUrl:h,fileUrl:h,mimeType:d},previewUrl:h,fileUrl:h,metadata:{source:e,eventType:n,callId:i||void 0,savedPath:a||void 0,filename:p,mimeType:d,revisedPrompt:c||void 0}}}function Je(s){let e=u(s)?s:{},t=[];for(let r of["_artifacts","artifacts"]){let n=e[r];Array.isArray(n)&&t.push(...n)}for(let r of["_artifact","artifact"]){let n=e[r];u(n)&&t.push(n)}return t}function Ke(s,{source:e="runtime_artifact"}={}){let t=u(s)?s:{};if(!Object.keys(t).length)return null;let r=u(t.content)?{...t.content}:{},n=u(t.metadata)?{...t.metadata}:{},i=g(t.saved_path,t.savedPath,r.saved_path,r.savedPath,n.savedPath),a=g(t.mimeType,t.mime_type,r.mimeType,r.mime_type,n.mimeType),c=g(t.artifactType,t.artifact_type,t.type,t.kind,r.type,i?"image":"file"),d=ze(t,r,c,i),l=d?me(i,a):a;if(d){let y=g(t.dataUrl,r.dataUrl),_=g(t.imageUrl,t.previewUrl,t.fileUrl,t.downloadUrl,t.url,t.uri,r.imageUrl,r.previewUrl,r.fileUrl,r.downloadUrl,r.url,r.uri),f=he(t.result??r.result,l)||y||W(i,l)||Ge(_,l)||i;f&&(r.imageUrl||=f,r.previewUrl||=f,r.fileUrl||=f,l&&(r.mimeType||=l))}for(let[y,_]of[["prompt","prompt"],["previewUrl","previewUrl"],["fileUrl","fileUrl"],["downloadUrl","downloadUrl"],["imageUrl","imageUrl"],["dataUrl","dataUrl"],["url","url"],["uri","uri"],["mimeType","mimeType"],["mime_type","mimeType"]]){let f=t[y];f!=null&&f!==""&&!(_ in r)&&(r[_]=f)}let h=g(t.fileUrl,t.downloadUrl,t.imageUrl,t.dataUrl,t.url,t.uri,r.fileUrl,r.downloadUrl,r.imageUrl,r.dataUrl,r.url,r.uri),p=g(t.previewUrl,t.imageUrl,t.dataUrl,t.url,t.fileUrl,t.uri,r.previewUrl,r.imageUrl,r.dataUrl,r.url,r.fileUrl,r.uri),w=g(t.filename,n.filename,i?le(i):"");return{...t,artifactType:c,type:t.type||c,title:g(t.title,w,"Runtime artifact"),summary:g(t.summary,r.prompt,t.title,w,"Runtime artifact"),content:r,fileUrl:h||void 0,previewUrl:p||void 0,metadata:{...n,source:g(n.source,e),savedPath:i||n.savedPath,filename:w||n.filename,mimeType:l||n.mimeType}}}function F(s,e){if(!e||!s)return;let t=u(e.metadata)?e.metadata:{},r=g(t.savedPath,t.callId,e.previewUrl,e.fileUrl)||ue(),n=s.get(r);if(!n){s.set(r,e);return}n.content={...u(n.content)?n.content:{},...u(e.content)?e.content:{}},n.metadata={...u(n.metadata)?n.metadata:{},...t},n.previewUrl=e.previewUrl||n.previewUrl,n.fileUrl=e.fileUrl||n.fileUrl,n.summary=e.summary||n.summary,n.title=e.title||n.title}function K(s,e,t={}){for(let r of Je(s))F(e,Ke(r,t))}function Q(s){if(!u(s)||!u(s.payload))return u(s)?s:{value:s};let e=o(s.payload.type);if(e!=="image_generation_end"&&e!=="image_generation_call")return s;let t={...s.payload};return typeof t.result=="string"&&t.result&&(t.result="<omitted>",t.resultLength=s.payload.result.length),{...s,payload:t}}function de(s,e,t){if(!u(s))return s;let r=u(s.event)?s.event:null;return r?(F(e,V(r,t)),{...s,event:Q(r)}):s}function fe(s,e,t={}){if(!u(s))return s;K(s,e,t);let r=de(s,e,t),n=u(r.update)?de(r.update,e,t):null;return n&&n!==r.update&&(r={...r,update:n}),r}function ge(s,e,t={}){let r=u(s)?{...s}:{};K(r,e,t),K(u(r.output)?r.output:{},e,t);let n=[...e?.values?.()||[]];return n.length&&(r.artifacts=n),r}var O=class{constructor(e,t,r={},n={}){this.agent=e,this.target=t,this.callbacks=r,this.options=n,this.proc=null,this.permissionHandlers=new Map}async ensureStarted(){if(this.proc)return;let e=o(this.target.command);if(!e)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);this.proc=new L({command:e,args:v(this.target.args),cwd:o(this.target.cwd)||this.agent.workspace||process.cwd(),env:u(this.target.env)?this.target.env:{},label:`${this.agent.agentId}:${this.agent.targetCode}`,framing:o(this.target.framing||"line")}),this.proc.onRequest("session/request_permission",t=>this.handlePermissionRequest(t)),this.proc.onRequest("session/requestPermission",t=>this.handlePermissionRequest(t)),await this.proc.start({initialize:this.target.initialize!==!1,initializeParams:{clientInfo:{name:"orcha-runtime-bridge",version:U},...u(this.target.initializeParams)?this.target.initializeParams:{}}})}async sessionNew(e={}){return await this.ensureStarted(),this.proc.call("session/new",e)}async sessionPrompt(e,t){await this.ensureStarted();let r=o(e.sessionId),n=new Map,i={source:this.artifactSource()},a=this.proc.onNotification("session/update",d=>{let l=o(d.sessionId);(!l||l===r)&&t(fe(d,n,i))}),c=async d=>this.callbacks.onPermissionRequest?.({agent:this.agent,runtimeSessionId:r,request:d,emitUpdate:t})||{outcome:"denied",reason:"permission handler is not configured"};r&&this.permissionHandlers.set(r,c),this.permissionHandlers.set("*",c);try{let d=await this.proc.call("session/prompt",e,this.options.sessionPromptTimeoutMs);return ge(d,n,i)}finally{a(),r&&this.permissionHandlers.delete(r),this.permissionHandlers.delete("*")}}async sessionCancel(e){return await this.ensureStarted(),this.proc.call("session/cancel",e,5e3).catch(()=>({ok:!0}))}async handlePermissionRequest(e){let t=o(e.sessionId),r=this.permissionHandlers.get(t)||this.permissionHandlers.get("*");return r?r(e):{outcome:"denied",reason:"no active Orcha permission handler"}}artifactSource(){return o(this.target.type||"acp")==="openclaw"?"openclaw_image_generation":"acp_runtime_image_generation"}stop(e){this.proc?.stop(e)}};var H=class extends O{constructor(e,t,r,n={},i={}){let a=o(r).replace(/[^A-Za-z0-9._-]+/g,"-")||"default",c=o(t.command)||"openclaw",d=Array.isArray(t.args)?t.args.map(String):[],l=d.length>0?d:["acp","--session",`agent:${e.agentId}:${a}`];super(e,{...t,command:c,args:l},n,i)}};import{spawn as We}from"node:child_process";import{randomUUID as Y}from"node:crypto";import{existsSync as Ve,readFileSync as Qe,unlinkSync as Ye}from"node:fs";import{tmpdir as Ze}from"node:os";import{basename as Xe,join as et}from"node:path";var tt=36e5,rt=5e3;function D(s,e){try{s.kill(e)}catch{}}function E(s){if(typeof s=="string")return s;if(Array.isArray(s))return s.map(e=>E(e)).join("");if(!u(s))return"";for(let e of["text","delta","output_text","content","message","output"]){let t=E(s[e]);if(t)return t}return""}function st(s){if(!u(s))return"";let e=u(s.payload)?s.payload:{};if(o(s.type)==="event_msg"){if(o(e.type)==="agent_message")return o(e.message);if(o(e.type)==="task_complete")return o(e.last_agent_message)}if(o(s.type)==="response_item"&&o(e.type)==="message"&&o(e.role)==="assistant")return E(e.content)||E(e.message);let t=E(s.delta)||E(s.text)||E(s.content);if(t)return t;let r=u(s.item)?s.item:{};return o(r.role)==="assistant"||o(r.type)==="message"?E(r.content)||E(r.text)||E(r.message):""}function nt(s){return V(s,{source:"codex_cli_image_generation"})}function it(s,e){F(s.artifacts,e)}function ot(s){return Q(s)}function at(s,e,t){return t.captureLastMessage===!1||e.includes("--output-last-message")||e.includes("-o")?!1:t.captureLastMessage===!0?!0:Xe(s)==="codex"}function ct(s){if(!s||!Ve(s))return"";try{return Qe(s,"utf8").trim()}catch{return""}finally{try{Ye(s)}catch{}}}var B=class{constructor(e,t,r={}){this.agent=e,this.target=t,this.options=r,this.active=new Map}async sessionNew(){return{sessionId:`cli-${this.agent.agentId}-${Y()}`}}async sessionPrompt(e,t){let r=o(this.target.command);if(!r)throw new Error(`runtime target ${this.agent.targetCode} is missing command`);let n=o(e.sessionId)||Y(),i=P(e.prompt),a=o(this.target.promptMode||"stdin"),c=this.buildArgs(a,i),d=at(r,c,this.target)?et(Ze(),`orcha-runtime-last-message-${Y()}.txt`):"";d&&c.push("--output-last-message",d);let l=T(this.target.timeoutMs||this.target.sessionPromptTimeoutMs,T(this.options.sessionPromptTimeoutMs,tt)),h={...process.env,...u(this.target.env)?this.target.env:{},...a==="env"?{ORCHA_RUNTIME_PROMPT:i}:{},ORCHA_AGENT_ID:this.agent.agentId,ORCHA_SESSION_ID:n},p=We(r,c,{cwd:o(this.target.cwd)||this.agent.workspace||process.cwd(),env:h,stdio:["pipe","pipe","pipe"]});this.active.set(n,p),m("info","runtime.cli","runtime prompt started",{target:this.agent.targetCode,sessionId:n,pid:p.pid,timeoutMs:l});let w="",y=o(this.target.outputMode||"text"),_={artifacts:new Map,emittedTexts:new Set,value:""};return p.stdout.setEncoding("utf8"),p.stdout.on("data",f=>this.handleStdout(f,y,_,n,t)),p.stderr.setEncoding("utf8"),p.stderr.on("data",f=>{w+=f,this.target.emitStderr===!0&&t({sessionId:n,update:{sessionUpdate:"runtime_stderr_chunk",content:{type:"text",text:f}}})}),a==="stdin"?p.stdin.end(i):p.stdin.end(),await new Promise((f,ke)=>{let b=!1,ne=!1,R=null,ie=setTimeout(()=>{ne=!0,m("warn","runtime.cli","runtime prompt timed out; terminating child",{target:this.agent.targetCode,sessionId:n,pid:p.pid,timeoutMs:l}),D(p,"SIGTERM"),R=setTimeout(()=>{m("warn","runtime.cli","runtime prompt force killing child",{target:this.agent.targetCode,sessionId:n,pid:p.pid}),D(p,"SIGKILL")},rt),R.unref?.(),ae(Object.assign(new Error(`runtime CLI timed out after ${l}ms`),{code:"RUNTIME_CLI_TIMEOUT"}))},l);ie.unref?.();let oe=()=>{clearTimeout(ie),R&&!ne&&clearTimeout(R),this.active.delete(n)},ve=I=>{b||(b=!0,oe(),f(I))},ae=I=>{b||(b=!0,oe(),ke(I))};p.on("error",I=>{m("warn","runtime.cli","runtime child error",{target:this.agent.targetCode,sessionId:n,pid:p.pid,error:String(I?.message||I)}),ae(I)}),p.on("exit",(I,ce)=>{R&&(clearTimeout(R),R=null),y==="json-lines"&&_.value.trim()&&this.handleStdout(`
|
|
9
|
+
`,y,_,n,t);let M=ct(d);M&&!_.emittedTexts.has(M)&&(_.emittedTexts.add(M),t({sessionId:n,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:M}}}));let k=w.trim();k&&m("debug","runtime.cli","runtime stderr",{target:this.agent.targetCode,sessionId:n,stderr:k}),m("info","runtime.cli","runtime prompt finished",{target:this.agent.targetCode,sessionId:n,pid:p.pid,exitCode:I,signal:ce}),ve({stopReason:I===0?"end_turn":"error",exitCode:I,signal:ce,artifacts:[..._.artifacts.values()],...k?{stderr:k}:{}})})})}buildArgs(e,t){let r=v(this.target.args);return e==="args"?[...r,t]:r}handleStdout(e,t,r,n,i){if(t!=="json-lines"){i({sessionId:n,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:e}}});return}r.value+=e;let a=r.value.split(/\r?\n/);r.value=a.pop()||"";for(let c of a){let d=c.trim();if(d)try{let l=JSON.parse(d);it(r,nt(l)),i({sessionId:n,update:{sessionUpdate:"runtime_event",event:ot(l)}});let h=st(l);h&&!r.emittedTexts.has(h)&&(r.emittedTexts.add(h),i({sessionId:n,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:h}}}))}catch{i({sessionId:n,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`${c}
|
|
10
|
+
`}}})}}}async sessionCancel(e){let t=o(e.sessionId),r=this.active.get(t);return r?(m("info","runtime.cli","cancelling runtime child",{target:this.agent.targetCode,sessionId:t,pid:r.pid}),D(r,"SIGTERM"),this.active.delete(t),{ok:!0,cancelled:!0}):{ok:!0,cancelled:!1}}stop(e="stop"){for(let[t,r]of this.active.entries())m("info","runtime.cli","stopping runtime child",{target:this.agent.targetCode,sessionId:t,pid:r.pid,reason:e}),D(r,"SIGTERM");this.active.clear()}};function dt(s,e,t){let r=u(s?._meta)?s._meta:{};return{...u(s)?s:{},sessionId:e,update:u(s?.update)?s.update:{},_meta:{...r,orchaAgentId:t.agentId,runtimeSessionId:t.runtimeSessionId,bridgeUpdateId:$()}}}var j=class{constructor(e){this.config=e,this.targets=e.targets||{},this.agents=new Map,this.sessions=new Map,this.runtimeSessionIndex=new Map,this.pendingPermissions=new Map,this.startedAt=x()}targetFor(e){let t=o(e)||this.config.defaultTargetCode,r=this.targets[t];return{code:t,target:u(r)?r:{type:"echo"}}}async createAgent(e){let t=o(e.agentId);if(!t)throw Object.assign(new Error("agentId is required"),{status:400,code:"BAD_REQUEST"});let{code:r,target:n}=this.targetFor(e.targetCode||e.framework),i={agentId:t,targetCode:r,framework:o(e.framework||r),workspace:o(e.workspace),metadata:u(e.metadata)?e.metadata:{},createdAt:x(),runtimeKind:o(n.type||"echo")};return this.agents.set(t,i),{agent:i}}runtimeFor(e,t){let{target:r}=this.targetFor(e.targetCode),n=o(r.type||"echo"),i={onPermissionRequest:c=>this.requestPermission(c)},a={sessionPromptTimeoutMs:this.config.sessionPromptTimeoutMs};return n==="stdio-acp"||n==="acp"?new O(e,r,i,a):n==="openclaw"?new H(e,r,t,i,a):n==="cli"?new B(e,r,a):new C(e)}async prompt(e,t={}){let r=o(e.agentId),n=o(e.sessionId)||$();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:e.targetCode,framework:e.framework,workspace:e.workspace,metadata:e.metadata})).agent,a=o(e.workspace);a&&a!==i.workspace&&(i.workspace=a);let c=`${r}:${n}`,d=this.sessions.get(c);if(!d){let w=this.runtimeFor(i,n),y=await w.sessionNew({cwd:i.workspace||process.cwd(),metadata:u(e.metadata)?e.metadata:{}});d={agentId:r,sessionId:n,runtime:w,runtimeSessionId:o(u(y)?y.sessionId:"")||n,createdAt:x()},this.sessions.set(c,d),this.runtimeSessionIndex.set(`${r}:${d.runtimeSessionId}`,d)}let l=[],h=w=>{let y=dt(w,n,d);l.push(y),t.onUpdate?.(y)},p=await d.runtime.sessionPrompt({sessionId:d.runtimeSessionId,prompt:Array.isArray(e.prompt)?e.prompt:[],metadata:u(e.metadata)?e.metadata:{}},h);return{sessionId:n,runtimeSessionId:d.runtimeSessionId,result:u(p)?p:{},updates:l}}async cancel(e){let t=o(e.agentId),r=o(e.sessionId),n=this.sessions.get(`${t}:${r}`);return n?(await n.runtime.sessionCancel({sessionId:n.runtimeSessionId}),{cancelled:!0}):{cancelled:!1}}async dispatch(e,t={}){let r=o(e.agentId),n=o(e.taskId),i=o(e.executionId);if(!r||!n)throw Object.assign(new Error("agentId and taskId are required"),{status:400,code:"BAD_REQUEST"});let a=o(e.sessionId)||`dispatch-${i||n}`,c=o(e.instructions),d=[{type:"text",text:["Task dispatch received.",`taskId: ${n}`,i?`executionId: ${i}`:"",c?`instructions: ${c}`:""].filter(Boolean).join(`
|
|
11
|
+
`)}];return this.prompt({...e,agentId:r,sessionId:a,prompt:d},t)}async requestPermission({agent:e,runtimeSessionId:t,request:r,emitUpdate:n}){let i=$(),c=this.runtimeSessionIndex.get(`${e.agentId}:${t}`)?.sessionId||t||$(),d={permissionId:i,agentId:e.agentId,sessionId:c,runtimeSessionId:t,request:u(r)?r:{},status:"pending",createdAt:x()};return n?.({sessionId:t,update:{sessionUpdate:"permission_request",permission:d}}),await new Promise(l=>{let h=T(r?.timeoutMs,this.config.permissionRequestTimeoutMs),p=setTimeout(()=>{this.pendingPermissions.delete(i),l({permissionId:i,outcome:"denied",response:{reason:"permission request timed out"}})},h);this.pendingPermissions.set(i,{timer:p,resolve:l,permission:d})})}async respondPermission(e){let t=o(e.permissionId),r=this.pendingPermissions.get(t),n=o(e.outcome||"approved")||"approved";return r?(clearTimeout(r.timer),this.pendingPermissions.delete(t),r.resolve({permissionId:t,outcome:n,response:u(e.response)?e.response:{},userId:o(e.userId),metadata:u(e.metadata)?e.metadata:{}}),{accepted:!0,permissionId:t,outcome:n}):{accepted:!1,permissionId:t,outcome:n}}health(){return{status:"ok",bridgeVersion:U,startedAt:this.startedAt,agents:[...this.agents.values()].map(e=>({agentId:e.agentId,targetCode:e.targetCode,framework:e.framework,runtimeKind:e.runtimeKind})),sessions:this.sessions.size,pendingPermissions:this.pendingPermissions.size,targets:Object.keys(this.targets)}}};import ut from"node:http";import lt from"node:https";import{randomBytes as we}from"node:crypto";var q=1,Z=3,G=class{constructor(e){this.url=e,this.readyState=0,this.socket=null,this.buffer=Buffer.alloc(0),this.listeners=new Map,this.connect()}addEventListener(e,t){let r=this.listeners.get(e)||new Set;r.add(t),this.listeners.set(e,r)}emit(e,t={}){let r=this.listeners.get(e);if(r)for(let n of r)n(t)}connect(){let e=new URL(this.url),t=e.protocol==="wss:"?lt:ut,r=we(16).toString("base64"),n=t.request({protocol:e.protocol==="wss:"?"https:":"http:",hostname:e.hostname,port:e.port||(e.protocol==="wss:"?443:80),path:`${e.pathname}${e.search}`,method:"GET",headers:{Connection:"Upgrade",Upgrade:"websocket","Sec-WebSocket-Key":r,"Sec-WebSocket-Version":"13"}});n.on("upgrade",(i,a,c)=>{this.socket=a,this.readyState=q,a.on("data",d=>this.onData(d)),a.on("close",()=>this.onClose()),a.on("error",d=>{this.emit("error",{error:d,message:d.message,type:"error"}),this.onClose()}),c?.length&&this.onData(c),this.emit("open")}),n.on("response",i=>{this.emit("error",{message:`websocket upgrade failed: HTTP ${i.statusCode}`,type:"error"}),i.resume(),this.onClose()}),n.on("error",i=>{this.emit("error",{error:i,message:i.message,type:"error"}),this.onClose()}),n.end()}send(e){!this.socket||this.readyState!==q||this.socket.write(X(1,Buffer.from(String(e),"utf8")))}close(){!this.socket||this.readyState===Z||(this.socket.write(X(8,Buffer.alloc(0))),this.socket.end(),this.onClose())}onClose(){this.readyState!==Z&&(this.readyState=Z,this.emit("close"))}onData(e){for(this.buffer=Buffer.concat([this.buffer,e]);this.buffer.length>=2;){let t=this.buffer[0],r=this.buffer[1],n=t&15,i=(r&128)!==0,a=r&127,c=2;if(a===126){if(this.buffer.length<c+2)return;a=this.buffer.readUInt16BE(c),c+=2}else if(a===127){if(this.buffer.length<c+8)return;let h=this.buffer.readUInt32BE(c),p=this.buffer.readUInt32BE(c+4);a=h*2**32+p,c+=8}let d=c;if(i&&(c+=4),this.buffer.length<c+a)return;let l=this.buffer.subarray(c,c+a);if(i){let h=this.buffer.subarray(d,d+4);l=Buffer.from(l.map((p,w)=>p^h[w%4]))}this.buffer=this.buffer.subarray(c+a),n===1?this.emit("message",{data:l.toString("utf8")}):n===8?this.close():n===9&&this.socket?.write(X(10,l))}}};function X(s,e){let t=e.length,r=2;t>=126&&t<=65535?r+=2:t>65535&&(r+=8);let n=we(4),i=Buffer.alloc(r+4+t);i[0]=128|s;let a=2;t<126?i[1]=128|t:t<=65535?(i[1]=254,i.writeUInt16BE(t,a),a+=2):(i[1]=255,i.writeUInt32BE(Math.floor(t/2**32),a),i.writeUInt32BE(t>>>0,a+4),a+=8),n.copy(i,a),a+=4;for(let c=0;c<t;c+=1)i[a+c]=e[c]^n[c%4];return i}function pt(s){let e=new URL(s);if(e.protocol==="http:")e.protocol="ws:";else if(e.protocol==="https:")e.protocol="wss:";else if(e.protocol!=="ws:"&&e.protocol!=="wss:")throw new Error(`unsupported ORCHA_RUNTIME_ORCHA_URL protocol: ${e.protocol}`);return e.pathname=`${e.pathname.replace(/\/+$/,"")}/api/agent-runtime-bridge/ws`,e.search="",e.toString()}function mt(s){return Object.entries(s||{}).map(([e,t])=>({targetCode:e,targetName:o(t?.name||t?.targetName||e),targetType:o(t?.type||"echo"),status:"available",metadata:u(t)?t:{}}))}var z=class{constructor(e,t){this.config=e,this.bridge=t,this.ws=null,this.stopped=!1,this.connected=!1,this.reconnectTimer=null}start(){this.connect()}stop(){this.stopped=!0,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.reconnectTimer=null,this.ws?.close()}connect(){let e=pt(this.config.orchaUrl),t=new G(e);this.ws=t,t.addEventListener("open",()=>this.authenticate()),t.addEventListener("message",r=>this.handleMessage(r.data)),t.addEventListener("close",()=>this.scheduleReconnect("close")),t.addEventListener("error",r=>{m("warn","orcha-client","runtime node websocket error",{error:String(r?.message||r?.type||r)})})}authenticate(){this.send({type:"runtime_node.authenticate",token:this.config.nodeToken,nodeId:this.config.nodeId,nodeName:this.config.nodeName,version:U,protocolVersion:"orcha-runtime-node.v1",defaultTargetCode:this.config.defaultTargetCode,targets:mt(this.config.targets)})}scheduleReconnect(e){this.connected=!1,!this.stopped&&(this.reconnectTimer||(m("info","orcha-client","runtime node disconnected; reconnect scheduled",{reason:e,reconnectMs:this.config.reconnectMs}),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.connect()},this.config.reconnectMs)))}async handleMessage(e){let t;try{t=JSON.parse(String(e))}catch(r){m("warn","orcha-client","invalid Orcha websocket frame",{error:String(r)});return}if(u(t)){if(t.type==="runtime_node.authenticated"){this.connected=!0,m("info","orcha-client","runtime node authenticated",{nodeId:this.config.nodeId,connectionId:t.connectionId});return}if(t.type==="orcha.runtime.request"){await this.handleRequest(t);return}t.type==="runtime_node.ping"&&this.send({type:"runtime_node.pong",ts:new Date().toISOString()})}}async handleRequest(e){let t=o(e.id),r=o(e.method),n=u(e.params)?e.params:{};try{let i=await this.invoke(r,n,t);this.send({type:"orcha.runtime.response",id:t,ok:!0,result:i})}catch(i){this.send({type:"orcha.runtime.response",id:t,ok:!1,error:{code:i.code||"RUNTIME_NODE_ERROR",message:i.message||String(i)}})}}async invoke(e,t,r){if(e==="health")return this.bridge.health();if(e==="agents/create")return this.bridge.createAgent(t);if(e==="agents/dispatch")return this.bridge.dispatch(t,{onUpdate:n=>this.sendUpdate(r,n)});if(e==="sessions/prompt")return this.bridge.prompt(t,{onUpdate:n=>this.sendUpdate(r,n)});if(e==="sessions/cancel")return this.bridge.cancel(t);if(e==="permissions/respond")return this.bridge.respondPermission(t);throw Object.assign(new Error(`unsupported Orcha runtime method: ${e}`),{code:"METHOD_NOT_FOUND"})}sendUpdate(e,t){this.send({type:"orcha.runtime.event",requestId:e,eventType:"runtime.update",payload:t})}send(e){return!this.ws||this.ws.readyState!==q?!1:(this.ws.send(JSON.stringify(e)),!0)}};import{existsSync as ht,readFileSync as ft}from"node:fs";import{resolve as ye}from"node:path";var gt=/^[A-Za-z_][A-Za-z0-9_]*$/;function _e(s=process.env,e=process.cwd()){let t=o(s.ORCHA_RUNTIME_ENV_FILE),r=t?ye(e,t):ye(e,".env");if(!ht(r))return t&&m("warn","config","runtime env file not found",{path:r}),{loaded:!1,path:r,keys:[]};let n=[],i=ft(r,"utf8");for(let a of i.split(/\r?\n/)){let c=yt(a);if(!c)continue;let[d,l]=c;Object.prototype.hasOwnProperty.call(s,d)||(s[d]=l,n.push(d))}return m("info","config","runtime env file loaded",{path:r,keyCount:n.length}),{loaded:!0,path:r,keys:n}}function Ie(s=process.env){return{mode:o(s.ORCHA_RUNTIME_MODE||(s.ORCHA_RUNTIME_ORCHA_URL?"node":"server")),host:s.ORCHA_RUNTIME_BRIDGE_HOST||"127.0.0.1",port:T(s.ORCHA_RUNTIME_BRIDGE_PORT,5588),token:s.ORCHA_RUNTIME_BRIDGE_TOKEN||"",orchaUrl:o(s.ORCHA_RUNTIME_ORCHA_URL),nodeToken:s.ORCHA_RUNTIME_NODE_TOKEN||s.ORCHA_RUNTIME_BRIDGE_TOKEN||"",nodeId:o(s.ORCHA_RUNTIME_NODE_ID||s.HOSTNAME||"local-runtime-node"),nodeName:o(s.ORCHA_RUNTIME_NODE_NAME||s.ORCHA_RUNTIME_NODE_ID||s.HOSTNAME||"Local Runtime Node"),reconnectMs:T(s.ORCHA_RUNTIME_RECONNECT_MS,3e3),defaultTargetCode:s.ORCHA_RUNTIME_DEFAULT_TARGET||"echo",requestLimitBytes:T(s.ORCHA_RUNTIME_REQUEST_LIMIT_BYTES,1048576),sessionPromptTimeoutMs:T(s.ORCHA_RUNTIME_SESSION_PROMPT_TIMEOUT_MS,36e5),permissionRequestTimeoutMs:T(s.ORCHA_RUNTIME_PERMISSION_TIMEOUT_MS,3e5),targets:wt(s.ORCHA_RUNTIME_TARGETS_JSON||"")}}function wt(s){if(!o(s))return{};try{let e=JSON.parse(s);if(u(e))return e}catch(e){m("warn","config","invalid ORCHA_RUNTIME_TARGETS_JSON",{error:String(e)})}return{}}function yt(s){let e=s.trim();if(!e||e.startsWith("#"))return null;let t=e.startsWith("export ")?e.slice(7).trimStart():e,r=t.indexOf("=");if(r<=0)return null;let n=t.slice(0,r).trim();if(!gt.test(n))return null;let i=_t(t.slice(r+1).trim());return[n,i]}function _t(s){if(!s)return"";let e=s[0];if((e==='"'||e==="'")&&s.endsWith(e)){let t=s.slice(1,-1);return e==='"'?It(t):t}return Tt(s).trim()}function It(s){return s.replaceAll("\\n",`
|
|
12
|
+
`).replaceAll("\\r","\r").replaceAll("\\t"," ").replaceAll('\\"','"').replaceAll("\\\\","\\")}function Tt(s){let e=!1,t=!1;for(let r=0;r<s.length;r+=1){let n=s[r],i=s[r-1];if(n==="'"&&!t)e=!e;else if(n==='"'&&!e&&i!=="\\")t=!t;else if(n==="#"&&!e&&!t&&/\s/.test(i||""))return s.slice(0,r)}return s}import{createServer as Et}from"node:http";function J(s,e,t){let r=JSON.stringify(t);s.writeHead(e,{"content-type":"application/json; charset=utf-8","content-length":Buffer.byteLength(r)}),s.end(r)}function S(s={}){return{ok:!0,...s}}function ee(s,e,t){return{ok:!1,error:{code:s,message:e,...t===void 0?{}:{detail:t}}}}async function Te(s,e){let t=[],r=0;for await(let i of s){if(r+=i.length,r>e)throw Object.assign(new Error("request body too large"),{status:413,code:"REQUEST_TOO_LARGE"});t.push(i)}if(t.length===0)return{};let n=Buffer.concat(t).toString("utf8");if(!n.trim())return{};try{let i=JSON.parse(n);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 Ee(s,e){if(!e)return;if((s.headers.authorization||"")!==`Bearer ${e}`)throw Object.assign(new Error("runtime bridge token is invalid"),{status:401,code:"UNAUTHORIZED"})}function Re(s,e){let t={"GET /health":async()=>S(e.health()),"POST /agents/create":async r=>S(await e.createAgent(r)),"POST /agents/dispatch":async r=>S(await e.dispatch(r)),"POST /sessions/prompt":async r=>S(await e.prompt(r)),"POST /sessions/cancel":async r=>S(await e.cancel(r)),"POST /permissions/respond":async r=>S(await e.respondPermission(r))};return Et(async(r,n)=>{let i=new URL(r.url||"/",`http://${r.headers.host||`${s.host}:${s.port}`}`),a=`${r.method||"GET"} ${i.pathname}`,c=t[a];if(!c){J(n,404,ee("NOT_FOUND",`No route for ${a}`));return}try{Ee(r,s.token);let d=r.method==="GET"?{}:await Te(r,s.requestLimitBytes);J(n,200,await c(d))}catch(d){let l=d.status||500,h=d.code||"BRIDGE_INTERNAL";J(n,l,ee(h,d.message||String(d)))}})}var vt=kt(import.meta.url),Pt=".orcha-runtime-bridge.pid",Ct=".orcha-runtime-bridge.log",{command:Lt,options:be}=Bt(process.argv.slice(2));$t(be);_e();var Ft=Ie();await Ht(Lt,Ft,be);async function Ht(s,e,t){switch(s){case"run":case"foreground":Se(e);return;case"start":if(t.foreground){Se(e);return}Ue();return;case"reload":case"restart":await xe({quiet:!0}),Ue();return;case"stop":await xe();return;case"status":Dt();return;case"help":case"--help":case"-h":jt();return;default:throw new Error(`Unknown command: ${s}`)}}function Se(s){let e=new j(s);if(s.mode==="server"){Re(s,e).listen(s.port,s.host,()=>{m("info","runtime-bridge","Orcha runtime bridge HTTP server started",{host:s.host,port:s.port,targets:Object.keys(e.targets)})});return}if(!s.orchaUrl)throw new Error("ORCHA_RUNTIME_ORCHA_URL is required in runtime node mode");new z(s,e).start(),m("info","runtime-bridge","Orcha runtime node started",{nodeId:s.nodeId,nodeName:s.nodeName,orchaUrl:s.orchaUrl,targets:Object.keys(e.targets)})}function Ue(){let s=re(),e=Me(),t=se(s);if(t&&N(t)){console.log(JSON.stringify({status:"already_running",pid:t,pidFile:s,logFile:e}));return}t&&te(s),Ne(s),Ne(e);let r=Ot(e,"a"),n=Rt(process.execPath,[vt,"run"],{cwd:process.cwd(),detached:!0,env:process.env,stdio:["ignore",r,r]});n.unref(),St(r),bt(s,`${n.pid}
|
|
13
|
+
`),console.log(JSON.stringify({status:"started",pid:n.pid,pidFile:s,logFile:e}))}async function xe({quiet:s=!1}={}){let e=re(),t=se(e);if(!t){s||console.log(JSON.stringify({status:"not_running",pidFile:e}));return}if(!N(t)){te(e),s||console.log(JSON.stringify({status:"not_running",pid:t,pidFile:e}));return}process.kill(t,"SIGTERM"),!await Oe(t,1e4)&&N(t)&&(process.kill(t,"SIGKILL"),await Oe(t,3e3)),te(e),s||console.log(JSON.stringify({status:"stopped",pid:t,pidFile:e}))}function Dt(){let s=re(),e=Me(),t=se(s),r=!!(t&&N(t));console.log(JSON.stringify({status:r?"running":"not_running",running:r,pid:r?t:null,pidFile:s,logFile:e}))}function Bt(s){let e=[],t={};for(let n=0;n<s.length;n+=1){let i=s[n];i==="--daemon"?t.daemon=!0:i==="--foreground"?t.foreground=!0:i==="--env-file"?t.envFile=s[++n]:i==="--pid-file"?t.pidFile=s[++n]:i==="--log-file"?t.logFile=s[++n]:e.push(i)}return{command:e[0]||"run",options:t}}function $t(s){s.envFile&&(process.env.ORCHA_RUNTIME_ENV_FILE=s.envFile),s.pidFile&&(process.env.ORCHA_RUNTIME_PID_FILE=s.pidFile),s.logFile&&(process.env.ORCHA_RUNTIME_LOG_FILE=s.logFile)}function re(){return Ae(process.cwd(),process.env.ORCHA_RUNTIME_PID_FILE||Pt)}function Me(){return Ae(process.cwd(),process.env.ORCHA_RUNTIME_LOG_FILE||Ct)}function se(s){if(!Ut(s))return null;let e=Number.parseInt(Nt(s,"utf8").trim(),10);return Number.isInteger(e)&&e>0?e:null}function N(s){try{return process.kill(s,0),!0}catch(e){return e?.code==="EPERM"}}async function Oe(s,e){let t=Date.now();for(;Date.now()-t<e;){if(!N(s))return!0;await new Promise(r=>setTimeout(r,100))}return!N(s)}function Ne(s){xt(Mt(s),{recursive:!0})}function te(s){try{At(s,{force:!0})}catch{}}function jt(){console.log(`Usage: orcha-runtime-bridge [command] [options]
|
|
14
14
|
|
|
15
15
|
Commands:
|
|
16
16
|
run, foreground Run in the foreground. This is the default.
|