grix-connector
Version:
Connect local AI coding agents (Claude, Codex, Gemini, Qwen, DeepSeek, Cursor, OpenCode, Pi, OpenHuman, Reasonix) to the Grix scheduling platform. Also serves as an OpenClaw plugin for Grix channel transport.
3 lines (2 loc) • 2.03 kB
JavaScript
import{EventEmitter as l}from"node:events";import{JsonRpcTransport as p}from"../core/transport/json-rpc.js";import{log as a}from"../core/log/index.js";import{resolveCommandPath as m,spawnCommand as h,killProcessGroup as d}from"../core/runtime/spawn.js";class _ extends l{proc=null;_transport=null;_alive=!1;bridgeLog;constructor(r){super(),this.bridgeLog=r??null}get transport(){return this._transport}get pid(){return this.proc?.pid}get alive(){return this._alive}async start(r){if(this.proc)throw new Error("process already started");const o={...process.env,...r.env},s=m(r.command,typeof o.PATH=="string"?o.PATH:void 0),e=h(s,r.args??[],{cwd:r.cwd,env:o}).process;if(this.proc=e,this._alive=!0,this.bridgeLog?.logLifecycle(`spawn command=${s} pid=${e.pid??""}`),e.on("error",t=>{this._alive=!1,this.bridgeLog?.logLifecycle(`process error: ${t.message}`),this.emitProcessError(t)}),e.on("exit",(t,i)=>{this._alive=!1,this.bridgeLog?.logLifecycle(`exit code=${t} signal=${i??""}`),a.info("agent-process",`exited command=${s} pid=${e.pid} code=${t} signal=${i}`),this.emit("exit",t)}),e.stderr?.on("data",t=>{const i=t.toString();if(i.trim()){this.bridgeLog?.logStderr(i),process.stderr.write(`[agent stderr] ${i}`);for(const c of i.split(`
`))c.trim()&&a.info("agent-stderr",`[${s}] ${c.trimEnd()}`)}this.emit("stderr",t)}),!e.stdin||!e.stdout)throw new Error("failed to create stdin/stdout pipes");const n=new p(e.stdout,e.stdin,void 0,void 0,this.bridgeLog);return n.on("close",()=>{this._alive=!1}),this._transport=n,n}async close(r=5e3){if(this._transport?.close(),this._transport=null,!this.proc||!this.proc.pid){this._alive=!1;return}d(this.proc,"SIGTERM"),!await Promise.race([new Promise(s=>{this.proc.once("exit",()=>s(!0))}),new Promise(s=>{setTimeout(()=>s(!1),r)})])&&this.proc.pid&&d(this.proc,"SIGKILL"),this._alive=!1,this.proc=null}emitProcessError(r){if(this.listenerCount("error")===0){a.error("agent-process",`Process error (no listeners): ${r.message}`);return}this.emit("error",r)}}export{_ as AgentProcess};