@engineeros/connector 1.58.0 → 1.58.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.
@@ -1069,7 +1069,7 @@ It is checked with the provider and stored in this machine's protected vault
1069
1069
  (Windows Data Protection, the macOS Keychain or the Linux Secret Service).
1070
1070
  EngineerOS never receives it; the running connector uses it when EngineerOS asks.`;function bV(e,{input:t=process.stdin,output:n=process.stdout}={}){return t.isTTY?new Promise((r,o)=>{n.write(e);let s="";t.setRawMode(!0),t.resume(),t.setEncoding("utf8");let i=c=>{t.setRawMode(!1),t.pause(),t.removeListener("data",a),n.write(`
1071
1071
  `),c?o(c):r(s.trim())},a=c=>{for(let l of c){if(l==="\r"||l===`
1072
- `)return i();if(l==="")return i(new Error("Cancelled."));l==="\x7F"||l==="\b"?s=s.slice(0,-1):s+=l}};t.on("data",a)}):new Promise((r,o)=>{let s="";t.setEncoding("utf8"),t.on("data",i=>s+=i),t.on("end",()=>r(s.trim())),t.on("error",o)})}var t1=Symbol("missing");function SV(e,t){return new Promise(n=>{let r=_V(e,t,{stdio:"inherit",shell:!1});r.once("error",o=>n(o?.code==="ENOENT"?t1:o.message)),r.once("close",o=>n(o===0?null:`${e} exited with code ${o}.`))})}function e1(e,t){for(let n of Da){let r=t[n],o=r.connected?`connected${r.account?` as ${r.account}`:""}`:"not connected";e(`${n.padEnd(8)} ${o}`),r.connected||e(` ${r.detail?`${r.detail} `:""}Connect: ${r.connect_command}`)}}async function n1(e,t,n,{vault:r=ag(),run:o=Ju,fetchImpl:s=fetch,secret:i=bV,interactive:a=SV,install:c=Xu,log:l=console.log,error:u=console.error}={}){if(n.help||e!=="integrations"&&!t[0])return l(vV),n.help?0:2;if(e==="integrations")return e1(l,(await Zu({run:o,vault:r})).providers),0;let p=t[0];if(!Da.includes(p))return u(`Unknown provider ${p}. Choose one of: ${Da.join(", ")}.`),2;if(p==="github"||p==="gitlab"){let f=ts[p];if(e==="disconnect")return l(`${p} uses this machine's ${f} sign-in. Run \`${f} auth logout\` to sign out everywhere on this machine.`),0;let h=await a(f,["auth","login"]);if(h===t1){let m=await Qs(f);if(!m){l(`Installing the ${Ma[f].label} ${Ma[f].version} for the connector...`);try{m=(await c(f)).path}catch(w){return u(w.message),1}}h=await a(m,["auth","login"])}return h?(u(`${h} ${Yu[p]} is how this machine signs in to ${p}.`),1):(e1(l,{[p]:(await Zu({run:o,vault:r})).providers[p]}),0)}let d=Gt[p];if(e==="disconnect")return await r.delete("",p),l(`Removed the ${d.label} ${d.tokenName} from this machine.`),0;try{await cg(r);let f=await i(`${d.label} ${d.tokenName} (create one at ${d.tokenUrl}): `),h=await lg(r,p,{token:f,site:n.site,email:n.email},s);return l(`Connected ${d.label}${h.account?` as ${h.account}`:""}. The token stays on this machine.`),0}catch(f){return u(f.message),1}}N();import{spawn as kV}from"node:child_process";async function r1({root:e,bundled:t,argv:n,workspace:r,spawnImpl:o=kV,log:s=console.log}){let i=n,a=!1;for(;;){let c=t;try{c=Kr(await nn(e),t)}catch(p){s(`${p.message} Starting the installed connector ${t.version}.`)}let{code:l,signal:u}=await EV(o,c.entry,i,t);if(l===yi){i=["start","--workspace",r],a=!1,s("Restarting the connector process on the activated update. Goal runs continue in their own processes.");continue}if(l!==0&&!u&&!a){let p=await nn(e).catch(()=>null);if(p&&!p.confirmed&&p.active?.version===c.version)try{let d=await Ld(e,{version:c.version,entry:c.entry,bundled:t},{automatic:!0,reason:`${c.version} exited with code ${l} before connecting to EngineerOS.`});a=!0,s(`Connector ${c.version} stopped before connecting; rolled back to ${d.version}.`);continue}catch(d){s(`Automatic rollback failed: ${d.message}`)}}return l??1}}function EV(e,t,n,r){return new Promise((o,s)=>{let i=e(process.execPath,[...process.execArgv,t,...n],{stdio:"inherit",env:{...process.env,[is]:"1",[Id]:r.entry,[jd]:r.version}}),a=process.platform==="win32"?[]:["SIGINT","SIGTERM","SIGHUP"],c=u=>i.kill(u);for(let u of a)process.on(u,c);let l=()=>{for(let u of a)process.off(u,c)};i.once("error",u=>{l(),s(u)}),i.once("exit",(u,p)=>{l(),o({code:u,signal:p})})})}var _o="1.58.0",sd="1.58.0",TV=3e5,id=["queued","running","reporting"],RV=5e3,ug={id:"design_sync",title:"Design artifact sync",remedy:"Fix the reported problem in this workspace. The connector retries on its own; it does not need restarting."},dg={id:"opportunity_scan",title:"Workspace opportunity scan",remedy:"EngineerOS asked this workspace what to deliver next and the scan failed. Check that the coding agent still answers here, or turn autonomy off in Project steering."},CV=6e4,OV=3e4,IV=60*6e4,pg={id:"tool_inventory",title:"Tool inventory refresh",remedy:"Run `engineeros-connector tools list` in this workspace for the full registry state."},fg={id:"runner_setup_reporting",title:"Goal runner setup reporting",remedy:"Restore the connection to EngineerOS; saved setup reports will retry automatically."},{command:ft,positional:qt,flags:Re}=vx(process.argv.slice(2));ft==="version"&&(console.log(_o),process.exit(0));var qr=null,Wt=!1,ir=null,y1=!1,_1=null,$g=null,At=null,Ja=null,Sg,o1,s1,hg,Ga,ni,v1=Gu({getWorkspace:()=>M.workspace,onRecorded:e=>aT(M,e).then(()=>console.log(`Recorded the ${e.role} sign-in for Bug Hunter; it is kept on this machine.`)).catch(t=>console.error(`The recorded ${e.role} sign-in was not reported to EngineerOS: ${t.message}`))}),jV=ZT({getWorkspace:()=>M.workspace,huntSignIns:v1}),Ba=Ex();ft==="results"&&(qt[0]!=="upload"&&(console.log(Mu),process.exit(Re.help||!qt[0]?0:2)),process.exit(await TA(Re)));(ft==="connect"||ft==="disconnect"||ft==="integrations")&&process.exit(await n1(ft,qt,Re,{fetchImpl:JT}));if(ft==="runner"){let e=Ht.resolve(Re.workspace||process.cwd()),t=qt[0]||"status";try{if(t==="serve"||t==="worker"){let n=t==="worker"?Ht.join(Ht.dirname(lt(e,Re["run-id"])),"worker.log"):Ht.join(e,".engineeros","runner","service.log");xV(Ht.dirname(n),{recursive:!0});let r=(...s)=>wa(n,`${AV(...s)}
1072
+ `)return i();if(l==="")return i(new Error("Cancelled."));l==="\x7F"||l==="\b"?s=s.slice(0,-1):s+=l}};t.on("data",a)}):new Promise((r,o)=>{let s="";t.setEncoding("utf8"),t.on("data",i=>s+=i),t.on("end",()=>r(s.trim())),t.on("error",o)})}var t1=Symbol("missing");function SV(e,t){return new Promise(n=>{let r=_V(e,t,{stdio:"inherit",shell:!1});r.once("error",o=>n(o?.code==="ENOENT"?t1:o.message)),r.once("close",o=>n(o===0?null:`${e} exited with code ${o}.`))})}function e1(e,t){for(let n of Da){let r=t[n],o=r.connected?`connected${r.account?` as ${r.account}`:""}`:"not connected";e(`${n.padEnd(8)} ${o}`),r.connected||e(` ${r.detail?`${r.detail} `:""}Connect: ${r.connect_command}`)}}async function n1(e,t,n,{vault:r=ag(),run:o=Ju,fetchImpl:s=fetch,secret:i=bV,interactive:a=SV,install:c=Xu,log:l=console.log,error:u=console.error}={}){if(n.help||e!=="integrations"&&!t[0])return l(vV),n.help?0:2;if(e==="integrations")return e1(l,(await Zu({run:o,vault:r})).providers),0;let p=t[0];if(!Da.includes(p))return u(`Unknown provider ${p}. Choose one of: ${Da.join(", ")}.`),2;if(p==="github"||p==="gitlab"){let f=ts[p];if(e==="disconnect")return l(`${p} uses this machine's ${f} sign-in. Run \`${f} auth logout\` to sign out everywhere on this machine.`),0;let h=await a(f,["auth","login"]);if(h===t1){let m=await Qs(f);if(!m){l(`Installing the ${Ma[f].label} ${Ma[f].version} for the connector...`);try{m=(await c(f)).path}catch(w){return u(w.message),1}}h=await a(m,["auth","login"])}return h?(u(`${h} ${Yu[p]} is how this machine signs in to ${p}.`),1):(e1(l,{[p]:(await Zu({run:o,vault:r})).providers[p]}),0)}let d=Gt[p];if(e==="disconnect")return await r.delete("",p),l(`Removed the ${d.label} ${d.tokenName} from this machine.`),0;try{await cg(r);let f=await i(`${d.label} ${d.tokenName} (create one at ${d.tokenUrl}): `),h=await lg(r,p,{token:f,site:n.site,email:n.email},s);return l(`Connected ${d.label}${h.account?` as ${h.account}`:""}. The token stays on this machine.`),0}catch(f){return u(f.message),1}}N();import{spawn as kV}from"node:child_process";async function r1({root:e,bundled:t,argv:n,workspace:r,spawnImpl:o=kV,log:s=console.log}){let i=n,a=!1;for(;;){let c=t;try{c=Kr(await nn(e),t)}catch(p){s(`${p.message} Starting the installed connector ${t.version}.`)}let{code:l,signal:u}=await EV(o,c.entry,i,t);if(l===yi){i=["start","--workspace",r],a=!1,s("Restarting the connector process on the activated update. Goal runs continue in their own processes.");continue}if(l!==0&&!u&&!a){let p=await nn(e).catch(()=>null);if(p&&!p.confirmed&&p.active?.version===c.version)try{let d=await Ld(e,{version:c.version,entry:c.entry,bundled:t},{automatic:!0,reason:`${c.version} exited with code ${l} before connecting to EngineerOS.`});a=!0,s(`Connector ${c.version} stopped before connecting; rolled back to ${d.version}.`);continue}catch(d){s(`Automatic rollback failed: ${d.message}`)}}return l??1}}function EV(e,t,n,r){return new Promise((o,s)=>{let i=e(process.execPath,[...process.execArgv,t,...n],{stdio:"inherit",env:{...process.env,[is]:"1",[Id]:r.entry,[jd]:r.version}}),a=process.platform==="win32"?[]:["SIGINT","SIGTERM","SIGHUP"],c=u=>i.kill(u);for(let u of a)process.on(u,c);let l=()=>{for(let u of a)process.off(u,c)};i.once("error",u=>{l(),s(u)}),i.once("exit",(u,p)=>{l(),o({code:u,signal:p})})})}var _o="1.58.1",sd="1.58.1",TV=3e5,id=["queued","running","reporting"],RV=5e3,ug={id:"design_sync",title:"Design artifact sync",remedy:"Fix the reported problem in this workspace. The connector retries on its own; it does not need restarting."},dg={id:"opportunity_scan",title:"Workspace opportunity scan",remedy:"EngineerOS asked this workspace what to deliver next and the scan failed. Check that the coding agent still answers here, or turn autonomy off in Project steering."},CV=6e4,OV=3e4,IV=60*6e4,pg={id:"tool_inventory",title:"Tool inventory refresh",remedy:"Run `engineeros-connector tools list` in this workspace for the full registry state."},fg={id:"runner_setup_reporting",title:"Goal runner setup reporting",remedy:"Restore the connection to EngineerOS; saved setup reports will retry automatically."},{command:ft,positional:qt,flags:Re}=vx(process.argv.slice(2));ft==="version"&&(console.log(_o),process.exit(0));var qr=null,Wt=!1,ir=null,y1=!1,_1=null,$g=null,At=null,Ja=null,Sg,o1,s1,hg,Ga,ni,v1=Gu({getWorkspace:()=>M.workspace,onRecorded:e=>aT(M,e).then(()=>console.log(`Recorded the ${e.role} sign-in for Bug Hunter; it is kept on this machine.`)).catch(t=>console.error(`The recorded ${e.role} sign-in was not reported to EngineerOS: ${t.message}`))}),jV=ZT({getWorkspace:()=>M.workspace,huntSignIns:v1}),Ba=Ex();ft==="results"&&(qt[0]!=="upload"&&(console.log(Mu),process.exit(Re.help||!qt[0]?0:2)),process.exit(await TA(Re)));(ft==="connect"||ft==="disconnect"||ft==="integrations")&&process.exit(await n1(ft,qt,Re,{fetchImpl:JT}));if(ft==="runner"){let e=Ht.resolve(Re.workspace||process.cwd()),t=qt[0]||"status";try{if(t==="serve"||t==="worker"){let n=t==="worker"?Ht.join(Ht.dirname(lt(e,Re["run-id"])),"worker.log"):Ht.join(e,".engineeros","runner","service.log");xV(Ht.dirname(n),{recursive:!0});let r=(...s)=>wa(n,`${AV(...s)}
1073
1073
  `),o=(s,i,a)=>(wa(n,s),(typeof i=="function"?i:a)?.(),!0);process.stdout.write=process.stderr.write=o,console.log=console.error=console.warn=r}if(t==="install"){if(Re["keep-awake"]!==void 0){if(!["on","off"].includes(Re["keep-awake"]))throw new Error("Use --keep-awake on or off.");let n=await Dt(e);if(!n)throw new Error("Pair this workspace before changing its runner keep-awake setting.");await In({...n,runner_keep_awake:Re["keep-awake"]==="on"})}console.log(`Installed Goal runner service: ${await pu(e)}`),process.platform==="darwin"&&console.log("macOS may show a Background Items Added notice. Manage the runner in System Settings > General > Login Items.")}else t==="uninstall"?(await m$(e),console.log("Goal runner service removed. Saved and queued jobs are kept.")):t==="start"?await Ws(e,{enable:!0}):t==="status"?console.log(JSON.stringify(await co(e),null,2)):t==="serve"?await _$(e):t==="worker"?await v$(e,Re["run-id"]):rt("Usage: engineeros-connector runner [install|start|status|uninstall] --workspace PATH [--keep-awake on|off]");process.exit(0)}catch(n){rt(Yh(n,e).message)}}Re["assessment-workers"]!==void 0&&rt("--assessment-workers is no longer supported. Select 3 to 8 parallel agents in EngineerOS before starting the assessment.");if(ft==="tools"){try{let e=$$(Re),t=qt[0]||"list";if(["sign-in","auth-status","sign-out"].includes(t)){let r=qt[1];r||rt(`Usage: engineeros-connector tools ${t} PROVIDER_ID [--workspace PATH | --project PROJECT_UUID]`);let o=await zf(e,{type:"tools.auth",command_id:"00000000-0000-4000-8000-000000000001",action:{"sign-in":"sign_in","auth-status":"status","sign-out":"sign_out"}[t],provider_id:r,confirmed:t==="sign-out"});o.completion&&await o.completion}else["setup","upgrade","rollback"].includes(t)?await ta(e,{type:"tools.update",command_id:"00000000-0000-4000-8000-000000000002",action:t,provider_id:qt[1],confirmed:!0},void 0,{confirmLocal:async()=>!0}):t!=="list"&&await Df(e,t,qt[1]);let n=await Tn(e);console.log(JSON.stringify(n,null,2)),process.exitCode=n.error?1:0}catch(e){rt(e.message)}process.exit(process.exitCode||0)}if(ft==="agents"){let e;try{e=await rh()}catch(n){rt(n instanceof Error?n.message:String(n))}let t=await Promise.all(e.map(async n=>{try{return await ra(n.id),`${n.id}: ready (${n.name} ${n.version}, ${n.distribution_type})`}catch(r){let o=r instanceof Error?r.message:String(r);return`${n.id}: setup needed (${n.name} ${n.version}, ${n.distribution_type}) - ${o}`}}));for(let n of t)console.log(n);process.exit(0)}if(ft==="agent"){let e=qt[0],t=qt[1]||"check";(!e||!["check","install"].includes(t))&&rt("Usage: engineeros-connector agent AGENT_ID [check|install]");try{let n=t==="install"?await oa(e):await ra(e);console.log(`${n.name} is ready (${n.version}, ${n.distribution}).`)}catch(n){rt(n instanceof Error?n.message:String(n))}process.exit(0)}if(ft==="mcp"){let e=Re.workspace||process.env.ENGINEEROS_MCP_WORKSPACE||process.cwd(),t=Re["run-id"]||qt[0]||process.env.ENGINEEROS_MCP_RUN_ID||null,n=await Dt(e);await Dx({config:n,runId:t,version:_o,input:process.stdin,output:process.stdout}),process.exit(0)}if(ft==="context-mcp"){let e=Re["config-workspace"]||Re.workspace||process.env.ENGINEEROS_MCP_WORKSPACE||process.cwd(),t=await Dt(e);t||rt("This workspace is not paired with EngineerOS."),await yA({config:t,workspace:Re.workspace||process.env.ENGINEEROS_CONTEXT_WORKSPACE||t.workspace,version:_o,input:process.stdin,output:process.stdout}),process.exit(0)}if(ft==="status"){let e=await Dt(Re.workspace||process.cwd());console.log(e?`Paired as ${e.name} (${e.connector_id}) for ${e.workspace}`:"Not paired"),process.exit(e?0:1)}if(ft==="doctor"){let e=Ht.resolve(Re.workspace||process.cwd()),t=await Dt(e),n=await jx(e),r=await ai(t||{workspace:e},e,Sm(n));console.log(_m(r)),process.exit(r.status==="failed"?1:0)}if(ft==="update"){let e=qt[0]||"status";try{let t=Md(process.argv[1],sd),n=await Dd(kr(),t,{action:e,policy:qt[1]??null});console.log(vi(Fd(n,t,{supervised:!0})))}catch(t){rt(`${t.message}
1074
1074
  Usage: engineeros-connector update [status|check|apply|rollback|policy manual|approve|auto-patch|auto-minor]`)}process.exit(0)}var ri=ft==="hunt-host";if(ri)try{Re.workspace=E$(qt,Re)}catch(e){rt(e.message)}if((ft==="start"||ft==="pair"||ri)&&process.env[is]!=="1"&&mt(sd))try{process.exit(await r1({root:kr(),bundled:{version:sd,entry:Ht.resolve(process.argv[1])},argv:process.argv.slice(2),workspace:Ht.resolve(Re.workspace||process.cwd())}))}catch(e){rt(`The connector process could not be started: ${e.message}`)}if(ri){try{await x$(Re.workspace,qt[0]?Re.agent:null)}catch(e){rt(e.message)}ft=qt[0]?"pair":"start"}var M,rs,Ha;if(ft==="pair"){let e=qt[0];e||rt("Usage: engineeros-connector pair CODE --url URL [--agent AGENT_ID | --agent-protocol forge] [--name NAME] [--workspace PATH] [--skip-git-repo-check]");let t=Re.url;t||rt("Pairing requires --url with the EngineerOS backend address."),Re.agent&&Re["agent-command"]&&rt("Use either --agent or --agent-command, not both.");let n=Re["agent-protocol"]||(Re["agent-command"]?"acp":"codex");["codex","acp","forge"].includes(n)||rt(`Unknown --agent-protocol '${n}'. Use codex, acp, or forge.`),n==="forge"&&(Re.agent||Re["agent-command"])&&rt("Forge runs its own agents. Drop --agent and --agent-command when pairing with --agent-protocol forge.");let r={};try{Re.agent&&(await ra(Re.agent),r=await oh(Re.agent))}catch(o){rt(o instanceof Error?o.message:String(o))}M={server_url:Bd(t),workspace:Ht.resolve(Re.workspace||process.cwd()),onboard:Re.onboard===!0,onboarding_pending:Re.onboard===!0,hunt_host:ri,agent_protocol:n,agent_command:Re["agent-command"]||null,agent_args:r9(Re["agent-args"]),agent_name:Re["agent-name"]||null,...r,skip_git_repo_check:ri||Re["skip-git-repo-check"]===!0,name:Re.name||`${$V.hostname()} - ${Ht.basename(Ht.resolve(Re.workspace||process.cwd()))}`},Ha=await Dt(M.workspace),rs={type:"pair",pairing_code:e,name:M.name,capabilities:{},...Dw(Ha,M.server_url)}}else ft==="start"?(M=await Dt(Re.workspace||process.cwd()),M||rt("This connector is not paired. Create a pairing command in EngineerOS first."),ri&&!M.hunt_host&&rt("This folder is not a paired hunt host. Generate a new hunt-host command in EngineerOS."),M.token||rt("This connector's token is no longer in this machine's credential store. Create a new pairing command in EngineerOS and pair again."),rs={type:"authenticate",connector_id:M.connector_id,token:M.token}):rt("Use `engineeros-connector pair`, `start`, `status`, `doctor`, `agents`, `agent`, `tools`, or `mcp`.");var b1=b$(M,{reportError:e=>console.error(e)}),yo=0,ad=!1,Wa=null,Vt=new Map,mg=0,gg=new Set,oi=[],Bt=new Map,yt,kg,td,yr=null,nd=!1,S1=0,wg=null,yg=[],rd,k1,Ua=1e3,si,i1=0,_g=!1,Br=!1,Gn,wo=!1,cd=!1,Eg=0;function Fa(e){return Eg+=1,e.finally(()=>{Eg-=1})}var ti,ns=0;function qa({exitCode:e=0}={}){if(ns=Math.max(ns,e),ti)return ti;let t=setTimeout(()=>{console.error("Connector shutdown exceeded 15 seconds; inspect the retained agent logs before restarting."),process.exit(1)},15e3);return t.unref(),ti=NV().finally(()=>clearTimeout(t)),ti}async function NV(){if(Wt=!0,Ja?.stop(),qr?.stop(),$g?.stop(),_1?.stop(),clearInterval(Sg),At?.stop(),k1?.(),clearTimeout(rd),clearInterval(kg),clearInterval(td),await Promise.all([...[...Vt.values()].map(e=>on(e.child))]),await Promise.all([...Bt.values()].map(Tg)),await Ga?.cancelAll(),await ni?.abortAll(),await na(),await Dg().catch(e=>{ns=Math.max(ns,1),console.error(`${e.message}. Stop those processes before restarting the connector.`)}),yt?.close(),ns&&ns!==yi){let e;await Promise.race([(async()=>{await qr?.drain(),await ai(M,M.workspace)})().catch(()=>{}),new Promise(t=>{e=setTimeout(t,1e4)})]).finally(()=>clearTimeout(e))}process.exit(ns)}for(let e of["SIGINT","SIGTERM","SIGHUP"])process.on(e,()=>{qa()});var a1=!1;for(let e of["uncaughtException","unhandledRejection"])process.on(e,async t=>{a1||(a1=!0,console.error(`Connector stopping after an unhandled failure: ${t instanceof Error?t.stack||t.message:String(t)}`),await qa({exitCode:1}))});At=Wg();process.on("exit",()=>{Ja?.stop(),At.stop()});At.banner(`EngineerOS connector ${_o}`,[M.workspace,M.server_url]);qr=kx({actions:{refresh_tool_inventory:async()=>{Oe.tool_inventory=await Tn(M.workspace),_n()},restart_goal_runner:()=>Ws(M.workspace)},onNotify:()=>ai(M,M.workspace),explain:async e=>{if(!await Va())return null;let{reading:t}=await WE(M,e);return t},onUpdate:e=>Ix(M.workspace,e)});_1=Mx({render:(e,t)=>At.write(e,t),onRecord:e=>qr.observe(e)});$g=Px({workspace:M.workspace,onRecord:e=>{qr.observe(e),At.line(e.channel,e.level,e.message)}});qr.start();M.hunt_host||$g.start();At.live&&!M.hunt_host&&(Sg=setInterval(()=>{MV().catch(()=>{})},RV),Sg.unref?.());var vg=new Set;async function MV(){if(M.hunt_host)return;o1??=Xh(M.workspace);let{jobs:e}=await o1(),t=new Set,n=e.filter(r=>r.status!=="queued"&&id.includes(r.status)).length;for(let r of e){if(!id.includes(r.status))continue;t.add(r.runId),vg.add(r.runId);let o=r.status==="queued"&&n>0?`queued behind running Goals (running: ${n})`:r.activity?.phase||r.status;At.status(`goal:${r.runId}`,o,PV(r),{agent:r.status!=="queued",link:Wa&&`${Wa}/goals`}),At.step(`goal:${r.runId}`,r.activity?.message)}for(let r of vg)t.has(r)||(vg.delete(r),At.clearStatus(`goal:${r}`))}function PV(e){let t=e.startedAt??Date.parse(e.updatedAt??"");return Number.isFinite(t)?t:Date.now()}async function Va({ignoreBugHunt:e=!1}={}){if(Wt||Vt.size>0||Bt.size>0||yo>0||(Ga?.active??0)>0||!e&&(ni?.active??0)>0)return!1;try{let{jobs:t}=await co(M.workspace);return!Wt&&!t.some(n=>id.includes(n.status))}catch{return!1}}try{let e=M.hunt_host?{}:await os(M.workspace);e.committed&&(M.onboarding_pending=!0,M.connector_id&&await In(M),console.log(`Local project repository ready at ${e.revision.slice(0,8)}. Source and design artifacts are committed locally.`))}catch(e){await A1(e)}var E1=await nn(kr()).then(e=>e.policy!=="manual",()=>!1),Xe;try{Xe=await ma(M,M.workspace)}catch(e){await A1(e)}console.log(`Using ${Xe.name} through ${Xe.protocol} (${Xe.version}).`);var Oe=Au(M,Xe,await Tn(M.workspace)),Wr=$w({running:Md(process.argv[1],sd),supervised:process.env[is]==="1",isIdle:async()=>!Wt&&Vt.size===0&&oi.length===0&&Bt.size===0&&yo===0&&Eg===0&&!wo&&!cd&&!nd,restart:()=>qa({exitCode:yi}),onChange:e=>{Oe.runtime_update=e,yt?.readyState===WebSocket.OPEN&&_n()}});try{await Wr.refresh()}catch(e){console.error(`Connector updates are unavailable: ${e.message}`)}M={...M,execution_profiles:Xe.executionProfiles??null};ft==="pair"&&Ha?.connector_id||await In(M);Oe.agent_session={...Oe.agent_session,status:"checking",message:`Checking that ${Xe.name} can answer.`};Oe.bug_hunt_browser=!1;rs.capabilities=Oe;console.log(Pr(M.worker_limit)===null?`Workers: automatic, ${Ds()} ${Xe.name} workers side by side for this machine's CPU and memory; change it with /workers.`:`Workers: ${Pr(M.worker_limit)} ${Xe.name} workers side by side, set with /workers.`);var ii=e=>Lr(M,e),c1=cu(ii,{signature:e$});async function LV(){let e=await co(M.workspace).catch(()=>({service:null,jobs:[]}));return{version:_o,now:Date.now(),workspace:M.workspace,config_path:hn(M.workspace),config:M,agent:Xe,automatic_worker_limit:Ds(),worker_limit:Pr(M.worker_limit),connection:{state:DV(),server_url:M.server_url,last_error:Gn||null},work:{assessments:[...Vt.values()].map(t=>({stage:t.stage,message:t.lastMessage,started_at:t.startedAt})),prompts:[...Bt.values()].map(t=>({id:String(t.runId).slice(0,8),purpose:t.purpose,started_at:t.startedAt})),integrations:yo},runner:e,runtime_update:Wr.report(),health:qr?.health()??null,activity:Ba.snapshot()}}function DV(){return Wt||Br?"stopped":yt?.readyState===WebSocket.OPEN?"connected":"connecting"}var FV={async cancelPrompt(e){let t=[...Bt.values()].find(n=>n.runId.startsWith(e));return t?(t.stoppedHere=!0,t.cancellation.abort(),await t.controller?.completed.catch(()=>{}),`Stopping prompt ${e} (${t.purpose}); EngineerOS will be told it was cancelled here.`):`Prompt ${e} finished before it could be stopped.`},setWorkers:e=>x1(e),setVerbose(e){return e===ad?`Detailed agent activity is already ${e?"on":"off"}.`:(xg(e),"This lasts until EngineerOS sends its own setting again: when the connector reconnects, or when it is changed there.")},async runtimeUpdate(e){return e.action==="apply"?(Wr.command(e).catch(t=>console.error(`Connector update: ${t.message}`)),"Preparing the latest connector release beside this one; it switches over once this connector is idle."):(await Wr.command(e),vi(await Wr.refresh()))}};Ja=Tx({ui:At,snapshot:LV,actions:FV});Ja&&console.log(Ax());await $1();var l1=new Set;async function $1(){if(Wt||Br)return;console.log(`Connecting ${M.name} to ${M.server_url}`),Br=!1,Gn=void 0;let e=new WebSocket(M.server_url);yt=e;let t=Fv(e,M.server_url,{onTimeout:r=>{yt===e&&(Gn=r,console.error(r),bg())}});k1=t,e.addEventListener("open",()=>{if(yt!==e){e.close();return}try{if(jv(yt,e,rs))return;throw new Error("The WebSocket was not open when authentication started.")}catch(r){Gn=Jt(r),console.error(`Could not authenticate the WebSocket connection: ${Gn}`);try{e.close()}catch{}bg()}}),e.addEventListener("message",r=>{if(yt!==e)return;let o;try{o=JSON.parse(String(r.data))}catch{console.error("Ignored a malformed EngineerOS message frame (invalid JSON).");return}n(o).catch(s=>{console.error(`EngineerOS ${String(o?.type||"unknown").slice(0,80)} message failed: ${Jt(s)}`)})});let n=async r=>{if(r.type==="authenticated"&&r.connector?.capabilities?.http_updates!==!0){Wt=!0,Br=!0,t(),console.error("Update the EngineerOS backend to support connector HTTP updates before reconnecting."),e.close();return}if(r.type==="paired"){t();let s=Ha?.connector_id===r.connector.id;if(M=Fw(M,Ha,r.connector.id,r.token),await In(M),r.connector?.capabilities?.http_updates!==!0){Wt=!0,Br=!0,console.error("Pairing saved. Update the EngineerOS backend for HTTP updates, then start this connector again."),e.close();return}rs={type:"authenticate",connector_id:M.connector_id,token:M.token,capabilities:Oe},console.log(s?`Reconnected existing workspace connector ${M.connector_id}; assessment history is preserved.`:`Paired. Connector ${M.connector_id} is online.`),f1(r);return}if(r.type==="authenticated"){t();let s=M.hunt_host?"Bug Hunter sessions":"EngineerOS runs";console.log(si?`Reconnected after ${Ge(Date.now()-si)} offline; waiting for ${s}.`:`Connected and waiting for ${s}.`),si=void 0,f1(r);return}if(r.type==="provider.login"||r.type==="provider.logout"){cd||zV(r);return}if(r.type==="workspace.refresh"){Xa();return}if(r.type==="workers.update"){try{console.log(`EngineerOS changed the workers. ${await x1(r.worker_limit??"auto")}`)}catch(s){console.error(`Workers were not changed: ${s.message}`)}return}if(r.type==="logging.update"){xg(r.activity_log_enabled===!0);return}if(r.type==="tools.update"){let s=r.provider_id==="playwright"&&["setup","upgrade","rollback"].includes(r.action);s&&(Hr=!1,Oe.bug_hunt_browser=!1,_n());try{Oe.tool_inventory=await ta(M.workspace,r,void 0,{confirmLocal:i=>Ja?.confirm(i)??!1,log:od}),s&&(Hr=!0),Oe.bug_hunt_browser=es(Oe.tool_inventory)&&Hr,e.send(JSON.stringify({type:"tools.updated",command_id:r.command_id,inventory:Oe.tool_inventory})),_n(),console.log(`Tool registry updated: ${r.action} ${r.provider_id}.`)}catch(i){let a=i instanceof Error?i.message.slice(0,300):"The local connector rejected the tool registry update.";e.send(JSON.stringify({type:"tools.updated",command_id:r.command_id,error:a})),console.error(`Tool registry update rejected: ${a}`)}return}if(r.type==="tools.auth"){try{let s=await zf(M.workspace,r,{onStatus:async()=>{Oe.tool_inventory=await Tn(M.workspace),_n()}});Oe.tool_inventory=s.inventory,s.completion&&s.completion.catch(i=>console.error(`Tool authentication status: ${i instanceof Error?i.message.slice(0,300):"Local status update failed."}`)),e.send(JSON.stringify({type:"tools.updated",command_id:r.command_id,inventory:Oe.tool_inventory})),_n(),console.log(`Tool authentication updated: ${r.action} ${r.provider_id}.`)}catch(s){let i=s instanceof Error?s.message.slice(0,300):"The local connector rejected the tool authentication request.";e.send(JSON.stringify({type:"tools.updated",command_id:r.command_id,error:i})),console.error(`Tool authentication rejected: ${i}`)}return}if(r.type==="test_environment.health_check"){_s(r).then(s=>{e.send(JSON.stringify({type:"test_environment.health_result",command_id:r.command_id,result:s})),console.log(`Test environment health: ${s.status}${s.message?` (${s.message})`:""}.`)}).catch(s=>console.error(`Test environment health was not reported: ${s.message}`));return}if(r.type===YT){Fa(jV(r).then(s=>(s.error&&console.error(`${r.provider} ${r.operation} failed: ${s.error}`),QT(M,s))).catch(s=>console.error(`An integration answer was not delivered: ${s.message}`)));return}if(r.type==="workspace.assessment"){let s=`${r.assessment_id}:${r.stage}`;Ph(oi,Vt.get(s),r)==="deferred"&&console.log(`Assessment stage ${r.stage} is already running here; EngineerOS will be answered when it finishes.`),Ka();return}if(r.type==="prompt.execute"){let s=Bt.get(r.prompt_id);s?I1(r)>s.executionRevision&&await QV(s,r):O1(r);return}if(r.type==="prompt.cancel"){let s=Bt.get(r.prompt_id);s&&await Tg(s);return}if(r.type==="agent.warm"){qV(r);return}if(r.type==="run.available"){if(M.hunt_host){console.error("A hunt host cannot run Goals. Use Connect your code to pair a repository connector.");return}try{let s=await b1.dispatch(r);s.blocked?console.error(s.message):console.log(`Goal ${r.run_id} queued for the independent runner. Logs: ${Ht.join(M.workspace,".engineeros","runs",r.run_id,"activity.log")}`)}catch(s){console.error(`Goal dispatch failed: ${Jt(s)}`)}return}if(r.type==="goal.cleanup"){try{await y$(M.workspace),await Ws(M.workspace)}catch(s){console.error(`Goal cleanup is pending: ${s.message}`)}return}if(r.type==="run.accepted"){n9(r);return}if(r.type==="run.cancelled"){await Vh(M.workspace,r.run_id);return}if(r.type===L0){Ga??=V0({getConfig:()=>M,onTestsCommitted:()=>Xa()}),Fa(Ga.handle(r));return}if(r.type===D0){await Ga?.cancel(r);return}if(r.type===_T){ni??=ET({getConfig:()=>M,isIdle:()=>Va({ignoreBugHunt:!0}),recordedSignIns:v1,activity:{status:At.status,step:Ag,agents:At.agents,finish:At.finish}}),Fa(ni.handle(r));return}if(r.type===vT){ni?.stop(r);return}if(r.type===RA){s1??=CA({getConfig:()=>M}),Fa(s1.handle(r));return}if(r.type===PA){hg??=WA({getConfig:()=>M}),Fa(hg.handle(r));return}if(r.type===LA){await hg?.cancel(r);return}if(r.type==="connector.update"){UV(e,r);return}if(r.type==="connector.disconnect"){console.log(r.message),await qa();return}if(r.type==="connector.revoked"){Wt=!0,console.error("This connector was revoked in EngineerOS."),e.close();return}if(r.type==="run.error"){console.error(`EngineerOS: ${r.message}`),r.run_id||(wo=!1);return}if(r.type==="connection.error"){Br=!0,console.error(`EngineerOS: ${r.message}`);return}let o=String(r.type??"(missing)").replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,120);l1.has(o)||(l1.add(o),console.warn(`Unknown EngineerOS message type ${o}; connector ${_o}. Update the connector and backend to compatible versions.`))};e.addEventListener("close",r=>{if(t(),yt!==e||ti)return;let o=Nv(r);if(!o.retry||Br||Wt){console.error(o.message),o.retry&&Br&&console.error("Connection rejected. Create a new pairing command in EngineerOS if this connector was revoked."),qa();return}Gn=Gn?`${o.message} ${Gn}`:o.message,bg()}),e.addEventListener("error",r=>{yt===e&&(Gn=Iv(r),console.error(`WebSocket connection to ${M.server_url} failed: ${Gn}`))})}async function UV(e,t){let n=r=>e.send(JSON.stringify({type:"connector.updated",command_id:t.command_id,...r}));try{let r={action:t.action,policy:t.policy??null},o=Wr.command(r);r.action==="apply"?(o.catch(s=>console.error(`Connector update: ${s.message}`)),await Promise.race([o,new Promise(s=>setTimeout(s,3e3).unref())])):await o,n({report:await Wr.refresh()}),console.log(`EngineerOS asked for connector update ${r.action}.`)}catch(r){let o=(r instanceof Error?r.message:String(r)).slice(0,300)||"The connector rejected the update request.";n({error:o}),console.error(`Connector update ${t.action} rejected: ${o}`)}}async function zV(e){let t=e.request_id,n=e.type==="provider.logout"?"logout":"login";cd=!0,console.log(`Starting interactive ${Xe.name} provider ${n}.`);try{await(n==="logout"?Dv:Lv)(Xe,M.workspace),Xe=await ma(M,M.workspace),Oe=Au(M,Xe,Oe.tool_inventory),rs.capabilities=Oe,yt.readyState===WebSocket.OPEN&&(yt.send(JSON.stringify({type:`provider.${n}.completed`,request_id:t,session:Oe.agent_session})),yt.close(1e3,`Provider ${n} completed`)),console.log(`${Xe.name} provider ${n} completed.`)}catch(r){let o=Jt(r).slice(0,500);yt.readyState===WebSocket.OPEN&&yt.send(JSON.stringify({type:`provider.${n}.failed`,request_id:t,message:o})),console.error(`Provider ${n} failed: ${o}`)}finally{cd=!1}}function bg(){if(Wt||Br||rd)return;let e=Gn?` Last error: ${Gn}`:"",t=si?` Offline for ${Ge(Date.now()-si)}.`:"";si??=Date.now(),console.error(`Connection unavailable.${e}${t} Retrying in ${Math.round(Ua/1e3)}s.`),rd=setTimeout(()=>{rd=void 0,$1()},Ua),Ua=Math.min(3e4,Ua*2)}async function Xa(){if(!M.hunt_host&&!(wo||yt.readyState!==WebSocket.OPEN)){wo=!0,console.log("Inspecting the workspace without executing its code.");try{let{snapshot:e,map:t,stats:n}=await Rm({workspace:M.workspace,connectorId:M.connector_id,refresh:fs,takeSnapshot:XE,buildMap:(i,a)=>Iu(M.workspace,i,{head:a.head_revision,branch:a.branch}),log:i=>console.error(i)}),r=await VE(M.workspace,M.last_head_reported??M.last_snapshot_head,e.head_revision).catch(()=>null);r&&(e.changed_since=r);let o=await fetch(as(M.server_url,M.connector_id),{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${M.token}`},body:JSON.stringify(e)});if(!o.ok)throw new Error(await Ui(o,"the workspace"));let s=await o.json();M={...M,onboarding_pending:!1,last_snapshot_head:e.head_revision??M.last_snapshot_head,last_head_reported:e.head_revision??M.last_head_reported,last_head_branch:e.head_revision?e.branch??null:M.last_head_branch},await In(M),t&&await ju(M.workspace,M.connector_id,t).catch(()=>{}),console.log(`Inventoried ${e.total_file_count.toLocaleString()} safe file(s).`),console.log(`Uploaded ${e.evidence_file_count.toLocaleString()} prioritized source file(s).`),console.log(`Excluded ${e.excluded_file_count.toLocaleString()} sensitive or generated file(s).`),e.omitted_evidence_file_count>0&&console.log(`${e.omitted_evidence_file_count.toLocaleString()} additional file(s) remain available to the connected Agent locally.`),console.log(`Workspace inventory registered as ${s.workspace_kind}. Start the baseline assessment in EngineerOS to continue.`),n&&console.log(`Built the local context index: ${n.total_files.toLocaleString()} file(s) ready for assignment context.`),wo=!1}catch(e){wo=!1,console.error(`Workspace assessment failed: ${Jt(e)}`)}}}var GV=8e6,u1,d1="";async function BV({current:e,previous:t}){if(wo||yt?.readyState!==WebSocket.OPEN)throw new Error("A snapshot is running or the connection is down.");let n=Ht.resolve(M.workspace),r=async()=>{M={...M,last_head_reported:e.head,last_head_branch:e.branch??null},await In(M)},o=await Tm(M.workspace,M.connector_id),s=async()=>{if(await Xa(),M.last_head_reported!==e.head)throw new Error("The snapshot did not report this commit.")};if(!o)return s();let{index:i}=await fs(M.workspace,M.connector_id),a=null,c=await aA({previous:{head:t.head,branch:t.branch??null},current:e,compare:(d,f)=>Uh(M.workspace,d,f),inventoryDelta:d=>by(n,Object.entries(i.files).map(([f,h])=>({path:f,size:h.size})),d),mapDelta:async()=>(a=await Iu(M.workspace,i,{head:e.head,branch:e.branch}),Am(o,a)),contentHead:(await Gc(n).catch(()=>null))?.content_head_revision??null});if(c.status==="snapshot")return s();if(c.status==="nothing")return r();let l=JSON.stringify(c.report);if(Buffer.byteLength(l)>GV)return s();let u=await fetch(Gw(M.server_url,M.connector_id),{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${M.token}`},body:l});if(!u.ok)throw new Error(await Ui(u,"the new commit"));let p=await u.json().catch(()=>({}));if(p.needs_snapshot)return s();await r(),a&&await ju(M.workspace,M.connector_id,a).catch(()=>{}),console.log(`Reported ${c.report.reason==="branch_switch"?"the switch to ":"commit "}${e.head.slice(0,7)}${p.flagged_cases?`: ${p.flagged_cases} test case(s) to check again`:""}.`)}function HV(){M.hunt_host||M.onboarding_pending||wo||yt?.readyState!==WebSocket.OPEN||(u1??=iA({readHead:()=>sA(M.workspace),getLastReported:()=>({head:M.last_head_reported??M.last_snapshot_head,branch:M.last_head_branch}),onChange:BV,onError:e=>{e.message!==d1&&(d1=e.message,console.error(`The new commit could not be reported yet: ${Jt(e)}`))}}),u1.poll().catch(()=>{}))}var WV=6e4,p1=0;async function qV(e){if(M.hunt_host)return;let t=typeof e.session_key=="string"?e.session_key.trim():"",n=t?M.sessions?.[t]:void 0,r=[];Date.now()-p1>WV&&(p1=Date.now(),r.push(fs(M.workspace,M.connector_id).catch(o=>console.error(`Context index refresh ahead of a conversation failed: ${o.message}`)))),M.agent_protocol==="acp"&&r.push(mS(M.workspace,M,{sessionKey:n?t:null,previousSessionId:n,sandbox:e.sandbox_mode==="workspace-write"?"workspace-write":"read-only",profile:e.execution_profile&&typeof e.execution_profile=="object"?e.execution_profile:{}}).catch(o=>console.error(`${Xe?.name||"The agent"} could not be started ahead of the conversation: ${o.message}`))),await Promise.all(r)}function _n(){let e=ME(Vt);c1.update({type:"assessment.workers",assessment_workers:e,tool_inventory:Oe.tool_inventory,runtime_update:Oe.runtime_update,agent_session:Oe.agent_session,bug_hunt_browser:Oe.bug_hunt_browser,...ru(M.worker_limit)}),c1.flush().catch(t=>console.error(`Assessment status: ${t.message}`))}async function x1(e){let t=Pr(e);return t===Pr(M.worker_limit)?t===null?"Workers are already automatic.":`Workers are already set to ${t}.`:(M={...M,worker_limit:t},await In(M),Ka(),_n(),t===null?`Workers are automatic again: up to ${Ds()} side by side for this machine's CPU and memory, for ${Ra} (an assessment may ask for fewer). A Goal that uses your working folder still runs alone.`:`Up to ${t} worker${t===1?"":"s"} now run side by side: ${Ra}. A Goal that uses your working folder still runs alone. Running work finishes; waiting work starts as workers free up.`)}function xg(e){if(e!==ad){if(ad=e,!e)for(let t of Vt.values())t.lastDetail=null;console.log(e?"Detailed agent activity is on: every agent action is printed here and shown in EngineerOS.":"Detailed agent activity is off: prompts and stages show only their latest steps."),_n()}}function Ag(e,t,n=null){At.step(e,t,n)&&ad&&console.log(`[${e}] ${n?`${n}: `:""}${t}`)}function VV(){clearInterval(td);let e=!1,t=()=>{e||Vt.size>0||Bt.size>0||(e=!0,ai(M,M.workspace).finally(()=>{e=!1}))};t(),td=setInterval(t,TV),td.unref?.()}async function ai(e,t,n=qr?.healthChecks()??[]){let r=await mx({config:e,workspace:t,version:_o,insights:n,agentSession:ir,probes:{inspectAgent:(o,s)=>Wt?Xe:ma(o,s),inspectTools:o=>Wt?Oe.tool_inventory:Tn(o),runnerStatus:co}});try{y1=(await gx(e,r,Lr))?.autonomy_scan===!0}catch(o){console.error(`EngineerOS did not accept the connector self-check: ${o instanceof Error?o.message:String(o)}`)}return r}async function A1(e){if(Wt)return ti;let t=e instanceof Error?e.message:String(e),n=await ai(M,M.workspace).catch(()=>null);n&&console.error(_m(n)),rt(t)}function f1(e){xg(e.connector?.activity_log_enabled===!0),Wa=e.project_url??null,Ua=1e3,JV(),R1(),Wr.confirm().catch(t=>console.error(`Connector update state: ${t.message}`)),KV(),M.onboarding_pending&&Xa()}var za=null,Hr=!1,T1=0,XV=Date.now();async function JV(){return za||(za=(async()=>{E1&&await Yb(M.workspace,{log:t=>console.log(`[tools] ${t}`)}).catch(t=>console.error(`[tools] Tool updates were skipped: ${t.message}`));let e=Date.now();try{od("Preparing Bug Hunter's browser: Playwright, then a check that a browser starts. The first setup can take a few minutes."),await A$(M.workspace,{log:od}),Hr=!0,Oe.tool_inventory=await Tn(M.workspace),Oe.bug_hunt_browser=es(Oe.tool_inventory)&&Hr,od(`Bug Hunter's browser is ready (${Ge(Date.now()-e)}).`)}catch(t){console.error(`[browser] Bug Hunter's browser setup failed after ${Ge(Date.now()-e)}: ${t.message}`),Oe.bug_hunt_browser=!1}_n()})(),za)}function od(e){console.log(`[browser] ${e}`)}async function R1(){if(ir?.state!=="checking"){T1=Date.now(),Oe.agent_session={...Oe.agent_session,status:"checking",message:`Checking that ${Xe.name} can answer.`},_n(),ir={state:"checking",detail:`Asking ${Xe.name} one question to confirm its session.`},console.log(`Checking that ${Xe.name} can answer before accepting work.`);try{await UE(M,Xe.name),ir={state:"ready",detail:`${Xe.name} answered; its session is usable.`},Oe.agent_session={...Oe.agent_session,status:"authenticated",message:ir.detail},console.log(ir.detail)}catch(e){ir={state:"failed",detail:e instanceof Error?e.message:String(e),remedy:M.hunt_host?R$(M.agent_id||M.agent_protocol):Ns(M.agent_id||M.agent_protocol)},Oe.agent_session={...Oe.agent_session,status:"logged_out",message:ir.remedy},console.error(`${ir.detail}
1075
1075
  ${ir.remedy}`)}_n(),await ai(M,M.workspace).catch(()=>null)}}function KV(){clearInterval(kg);let e=!1,t=0,n=0,r=!1,o=()=>{Wr.tick(),YV(),HV(),M.hunt_host&&za&&Date.now()-T1>=T$(XV)&&Bt.size===0&&Vt.size===0&&!(ni?.active>0)&&R1(),!M.hunt_host&&!r&&Aa(fg.id)&&(r=!0,b1.flush().then(()=>ed(fg)).catch(s=>Qu(fg,s)).finally(()=>{r=!1})),Vt.size>0&&_n(),!M.hunt_host&&!yr&&Date.now()-t>=CV&&Aa(ug.id)&&(t=Date.now(),C1().then(()=>ed(ug)).catch(s=>Qu(ug,s))),!M.hunt_host&&y1&&!nd&&Aa(dg.id)&&Date.now()-S1>=lb&&(nd=!0,ZV().then(()=>ed(dg)).catch(s=>Qu(dg,s)).finally(()=>{nd=!1})),!e&&Date.now()-n>=OV&&Aa(pg.id)&&(e=!0,n=Date.now(),Tn(M.workspace).then(async s=>{if(Oe.tool_inventory=s,!Hr&&es(s))try{await(await To(await po(M.workspace))).close(),Hr=!0}catch{Hr=!1}Oe.bug_hunt_browser=es(s)&&Hr,_n(),ed(pg)}).catch(s=>Qu(pg,s)).finally(()=>{e=!1}))};o(),kg=setInterval(o,1e4),VV()}async function YV(){if(!(!E1||M.agent_protocol!=="acp"||!M.agent_id||_g||ir?.state==="checking"||Date.now()-i1<IV)){_g=!0;try{if(!await Va())return;i1=Date.now();let e,t=await kS(M,{verify:async r=>{e=await ma(r,M.workspace)},log:r=>console.log(`[agent] ${r}`)});if(t===M||Wt)return;M={...t,execution_profiles:e.executionProfiles??null},await In(M),Xe=e;let n=Au(M,Xe,Oe.tool_inventory);if(Object.assign(Oe,{agent_name:n.agent_name,agent_version:n.agent_version,execution_profiles:n.execution_profiles}),rs.capabilities=Oe,!await Va())return;await na(),yt?.readyState===WebSocket.OPEN&&yt.close(1e3,"Coding agent updated")}catch(e){console.error(`[agent] The agent update check failed: ${e.message}`)}finally{_g=!1}}}function Qu(e,t){let n=lx(e.id,e.title,t,{remedy:e.remedy});console.error(`${e.title} failed ${n.failures} time(s); retrying in ${Math.round(n.retryInMs/1e3)}s: ${n.message}`)}function ed(e){ux(e.id)&&console.log(`${e.title} recovered.`)}async function ZV(){if(M.hunt_host||!await Va())return;S1=Date.now();let{jobs:e}=await co(M.workspace).catch(()=>({jobs:[]})),t=await ub(M.workspace,{jobs:e});if(!db(t))return;let n=`${t.fingerprint}:${yg.join(",")}`,r=wg?.key===n,o=r?wg.candidates:await qE(M,t,yg);wg={key:n,candidates:o};let s=await ii(hb(t,o,{version:_o}));Array.isArray(s?.refused)&&(yg=s.refused.map(String));let i=r?"unchanged since the last scan":"scanned";console.log(o.length?`Workspace ${i}; reported ${o.length} delivery candidate(s) to EngineerOS: ${o.map(a=>a.capability_name).join(", ")}.`:`Workspace ${i}; nothing worth starting.`)}var go=null,h1=null;async function C1(){if(!M.hunt_host){if(yr)return yr;yr=(async()=>{let e=await tb(M,{knownRevision:go?.revision??null});if(e.unchanged||(go=e),h1===go.revision)return go;let{jobs:t}=await co(M.workspace);return!t.some(r=>id.includes(r.status))&&yo===0&&Vt.size===0&&(await Sl(M.workspace,go),h1=go.revision),go})();try{return await yr}finally{yr=null,Ka()}}}function m1(e,t){if(!t)return;let n={type:"prompt.event",prompt_id:e,kind:t.kind};t.message&&(n.message=String(t.message).slice(0,500)),t.delta&&(n.delta=String(t.delta).slice(0,5e4)),t.status&&(n.status=String(t.status).slice(0,100)),Bt.get(e)?.events.push(n)}var g1=null;function Ka(){let e=yt.readyState===WebSocket.OPEN,t=Vt.values().next().value,n=Pr(M.worker_limit)??Math.min(Ds(),Lh(t?.workerLimit??oi[0]?.worker_limit)),r=e&&!yr&&yo===0?xE(oi,Vt.size,n):[];for(let s of r){let i=`${s.assessment_id}:${s.stage}`,a={kind:"assessment",key:i,runId:s.assessment_id,stage:s.stage,child:null,controller:null,resumeAssignment:null,phase:"starting",progressPercent:5,lastMessage:`Starting ${s.stage} assessment stage`,startedAt:Date.now(),workerLimit:Lh(s.worker_limit),lastActivityAt:Date.now(),eventCount:0,lastDetail:null};Vt.set(i,a),t9(s,a)}r.length>0&&_n();let o=AE({queued:oi,running:Vt.size,workerLimit:n,connected:e,designSync:!!yr,integrations:yo});o&&o!==g1&&console.log(o),g1=o}function ld(e){let t=Dh(e);return t?`${Xe.name} on ${t}`:Xe.name}async function O1(e){let t=e.prompt_id,n=`prompt:${String(t).slice(0,8)}`,r=e.purpose||"project",o=Date.now(),s={runId:t,purpose:r,startedAt:o,child:null,controller:null,cancelled:!1,stoppedHere:!1,cancellation:new AbortController,events:r$(ii),executionRevision:I1(e),sessionKey:ou(e),sessionId:null,replacement:null};Bt.set(t,s);let i,a=m=>{let w=m?JSON.stringify(m):null;!w||w===i||Bt.get(t)!==s||(i=w,m1(t,m))},c=`${r} \xB7 ${ld(e)}`,l=FE(e,Xe.name);m1(t,{kind:"status",message:l});let u=Number(e.answer_within_seconds),p=u>0?o+u*1e3:void 0;console.log([`[${n}] ${l} for ${r}.`,`${Xe.name} can reason for several minutes without reporting a step.`,...p?[wd(p,o)]:[]].join(" ")),At.status(n,c,o,{link:Wa,answerBy:p});let d=m=>{let w=kE(m),_=Wo(m);Bt.get(t)===s&&Ag(n,_??w?.message);let k=m.type==="forge.output"?null:_;a(w??(k?{kind:"status",message:k}:null))},f="failed",h=[r];try{su(e)||(d({type:"connector.step",message:"Syncing the design context from EngineerOS"}),e={...e,design_context:await ib(C1,{pinned:!!e.local_design_context,last:go,onFallback:(k,b)=>d({type:"connector.step",message:`Design context not refreshed (${k.message}); continuing with ${b?"the copy synced earlier":"none"}`})})});let m=await wE(e,M,{onProcess:k=>{Bt.get(t)===s&&(s.child=k)},onController:k=>{Bt.get(t)===s&&(s.controller=k)},onSession:k=>{s.sessionId=k},onEvent:d},{signal:s.cancellation.signal});if(s.stoppedHere)throw new Error(w1);let w=m.singleTurn?Uw(M.sessions,m.sessionKey):Hd(M.sessions,m.sessionKey,m.sessionId);if(JSON.stringify(w)!==JSON.stringify(M.sessions||{})&&(M={...M,sessions:w},await In(M)),s.cancelled)return;await s.events.close().catch(k=>{console.error(`[${n}] Prompt progress delivery: ${k.message} The agent has finished; submitting its complete response separately.`)});let _=await au(ii,{type:"prompt.completed",prompt_id:t,execution_revision:s.executionRevision,content:m.content,model:m.model,session_id:m.sessionId,usage:m.usage});_||console.error(`[${n}] ${Bh}`),Ba.record("prompt","completed",{durationMs:Date.now()-o,usage:m.usage}),f=_?"finished":"undelivered",h=[rc(m.usage),r]}catch(m){let w=s.stoppedHere?w1:Jt(m);if(Ba.record("prompt","failed",{durationMs:Date.now()-o}),s.stoppedHere&&(f="cancelled"),!s.cancelled){try{await au(ii,{type:"prompt.failed",prompt_id:t,execution_revision:s.executionRevision,message:w})||console.error(`[${n}] ${Bh}`)}catch(_){console.error(`[${n}] Prompt failure delivery: ${_.message}`)}console.error(w)}}finally{s.events.stop();let m=s.replacement;m?(f="replaced",h=[`continuing on ${ld(m)}`,r]):s.cancelled&&(f="cancelled"),At.finish(n,f,h),Bt.get(t)===s&&Bt.delete(t),m&&e9(s,m)}}var w1="Cancelled from the connector terminal by the person running it.";async function Tg(e){e.cancelled=!0,e.cancellation.abort(),await e.controller?.completed.catch(()=>{})}function I1(e){return Number(e.execution_revision)||1}async function QV(e,t){let n=e.replacement!==null;e.replacement=t,!n&&(console.log(`[prompt:${String(e.runId).slice(0,8)}] The model was changed in EngineerOS; stopping this turn to continue it on ${ld(t)}.`),await Tg(e))}function e9(e,t){e.sessionId&&(M={...M,sessions:Hd(M.sessions,e.sessionKey,e.sessionId)},In(M).catch(n=>console.error(`Could not save the agent session: ${n.message}`))),O1(t)}async function t9(e,t){let n=e.assessment_id,r=e.stage;if(console.log(`Running assessment stage ${r}${e.stage_label&&e.stage_label!==r?` "${e.stage_label}"`:""} (${n}) with ${ld(e)}.`),!gg.has(n)){gg.add(n);try{let v=await vE(M.workspace);if(!v.exists)console.log("No accepted assessment exists yet; this run establishes the baseline.");else{let x=v.accepted_head_revision?v.current_head_revision?v.current_head_revision!==v.accepted_head_revision?`The workspace is now at commit \`${v.current_head_revision}\`; the accepted assessment is from \`${v.accepted_head_revision}\`.`:"The accepted assessment is already at the current commit.":`The accepted assessment is from \`${v.accepted_head_revision}\`; the current commit could not be read.`:"Its accepted commit is unavailable; this run will refresh that provenance.";console.log(`Last accepted assessment covers ${v.stages.length||"no"} section(s). ${x}`)}}catch(v){console.error(`Assessment freshness check failed: ${v.message}`)}}let o=t.startedAt,s=`assessment:${r}`,i=!1,a=!1,c=5,l=!1,u=!1,p=null,d=null,f=null,h=new Set,m=()=>!Wt&&Vt.get(t.key)===t,w=async v=>{try{return await au(ii,v)||console.warn(`[${s}] ${t$}`),!0}catch(x){return console.error(`Assessment failure delivery: ${x.message}`),!1}},_=(v,{milestone:x=!0}={})=>{if(!m()||x&&f===v)return;x&&(f=v,h.has(v)||(h.add(v),c=Math.min(90,c+10)),console.log(`[assessment:${r}] ${v}.`));let g=String(v).slice(0,500);t.progressPercent=c,t.lastMessage=g,At.status(s,g,o,{link:Wa})};_(`Starting ${r} assessment stage`);let k=setInterval(()=>{let v=Date.now(),x=v-t.lastActivityAt,g=i&&!a?SE(r,x):null;if(!p&&g){p=g,console.error(`[assessment:${r}] ${p}`),iu(t.controller,t.child);return}p||qr.observe({at:v,level:"info",message:At.status(s,`${t.lastMessage} \xB7 last agent activity ${Ge(x)} ago (${t.eventCount.toLocaleString()} events)`,o)})},15e3),b={onSession:async v=>{m()&&(d=String(v),await C_(M.workspace,n,r,v,{sourceRevision:e.source_revision,targetHeadRevision:e.target_head_revision}))},onController:v=>{m()&&(t.controller=v)},onProcess:v=>{m()&&(t.child=v,i=!0,t.phase!=="correcting"&&(t.phase="running",_("Connected agent process started")),t.lastActivityAt=Date.now())},onEvent:v=>{t.lastActivityAt=Date.now(),t.eventCount+=1;let x=bE(v);if(x&&_(x),!m())return;let g=Wo(v);!g||g===t.lastDetail||(t.lastDetail=g,Ag(s,g))}},S=(v,x)=>Nh(v,x,M,b,{draftPath:Ht.relative(M.workspace,Ht.join(kn(M.workspace,n),v.report_file)).split(Ht.sep).join("/")});try{let v=mg-Date.now();v>0&&(_(`Waiting ${Math.ceil(v/1e3)}s for the model provider's rate limit to clear`),await new Promise(T=>setTimeout(T,v+Math.floor(Math.random()*3e3)))),e.assessment_mode==="incremental"&&(c=15,_("Calculating changed files and affected behavior"));let x=await M_(M.workspace,e),g=await Np(M.workspace,n,r,{expectedHeadRevision:e.target_head_revision,expectedSourceRevision:e.source_revision});if(g)S(g,x),_("Recovered completed stage report from connector storage");else{if(d=await O_(M.workspace,n,r,{expectedHeadRevision:e.target_head_revision,expectedSourceRevision:e.source_revision}),d&&_("Restoring interrupted agent session"),g=await gE(x,M,b,{previousSessionId:d}),p)throw new Error(p);a=!0,await jp(M.workspace,n,x,g)}a=!0,t.phase="delivering",t.progressPercent=95,t.lastMessage=r==="synthesis"?"Delivering completed assessment bundle":"Checkpointing connector-local stage result";let E=T=>fetch(Hw(M.server_url,M.connector_id,n),{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${M.token}`},body:JSON.stringify(T),signal:AbortSignal.timeout(tE)}),O=await DE(g,{submit:T=>LE(T,E,{isActive:()=>m()&&!Wt,onRetry:(C,R)=>{_("Completed result is waiting for EngineerOS",{milestone:!1}),console.warn(`[assessment:${r}] Completed result delivery failed: ${Jt(C)} Retrying in ${Math.round(R/1e3)}s without rerunning the agent.`)}}),payloadFor:T=>r==="synthesis"?Mp(M.workspace,n,T,{expectedSourceRevision:e.source_revision}):F_(T),rejectionFor:T=>Ui(T,"the assessment"),correct:async(T,C)=>{if(a=!1,t.phase="correcting",t.lastMessage="Correcting a rejected stage result",!T.correctAfterRejection)throw new Error(`${C} The connector could not start the required agent correction.`);return T.correctAfterRejection(C)},onCorrected:async T=>{if(p)throw new Error(p);a=!0,await j_(M.workspace,n,r);let C=await jp(M.workspace,n,x,T);return S(C,x),t.phase="delivering",t.lastMessage="Delivering corrected stage result",C}});if(p)throw new Error(p);g=O.result;let A=O.response;if(!A.ok)throw new Error(await Ui(A,"the assessment"));if(l=!0,Ba.record("assessment stage","completed",{durationMs:Date.now()-o,usage:g.usage}),r==="synthesis"){let T=await A.json(),C=await P_(M.workspace,n,e,g,T.report_markdown);console.log(`Workspace assessment ${n} was accepted by EngineerOS and saved to ${Ht.relative(M.workspace,C)}.`);try{let R=await ac(M.workspace);R.committed&&console.log(`Assessment committed to Git as ${R.revision.slice(0,8)}.`)}catch(R){console.error(`The assessment is saved locally but could not be committed to Git: ${R.message}`)}}else console.log(`Workspace assessment stage ${r} was checkpointed by EngineerOS.`)}catch(v){let x=p||Jt(v),g=OE(e,v),E=NE(v),$=RE(v);E&&(await I_(M.workspace,n,r).catch(A=>{console.error(`[assessment:${r}] Could not discard the unusable agent session checkpoint: ${A.message}`)}),d=null);let O=!p&&(d||E)&&(E||TE(v))&&g<$;if(m()&&O){t.phase="starting",t.lastMessage=E?"Agent session became unusable; restarting from saved assessment work":"Agent session interrupted; resuming checkpoint",t.resumeAssignment=IE(e,v);let A=jE(v,g);ga(v)&&(mg=Math.max(mg,Date.now()+A)),console.warn(`[assessment:${r}] ${E?"Agent session became unusable":"Agent session interrupted"}: ${x} ${E?"Starting a fresh session from the saved draft":`Resuming session ${d}`} in ${Math.round(A/1e3)}s (${g+1}/${$}).`),await new Promise(T=>setTimeout(T,A))}else m()&&(u=await w({type:"workspace.assessment.failed",assessment_id:n,stage:r,message:x}));O||(Ba.record("assessment stage","failed",{durationMs:Date.now()-o}),console.error(`[assessment:${r}] ${x}`))}finally{clearInterval(k),At.clearStatus(s),r==="synthesis"&&l&&gg.delete(n),m()&&(Vt.delete(t.key),PE(oi,t,{accepted:l,failureReported:u})&&console.log(`Resuming interrupted agent session for assessment stage ${r} from its checkpoint.`),Ka())}}async function n9(e){let t=String(e.run_id||"");yo+=1;try{yr&&await yr;let n=await cE(M.workspace,String(e.base_revision||""),String(e.head_revision||""),String(e.integration_branch||"")||null);if(n.applied){console.log(`Accepted Goal Run ${t} applied to the connected repository at ${n.revision} (${n.method}).`),await Xa();return}console.warn(`Accepted Goal Run ${t} remains on its review branch. ${n.reason}`)}catch(n){console.error(`Accepted Goal Run ${t} could not be integrated: ${Jt(n)}`)}finally{yo-=1,Ka()}}function r9(e){if(!e)return[];try{let t=JSON.parse(e);if(!Array.isArray(t)||t.some(n=>typeof n!="string"))throw new Error;return t}catch{rt('--agent-args must be a JSON array, for example: --agent-args "[\\"acp\\"]"')}}function rt(e){console.error(e),process.exit(1)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@engineeros/connector",
3
- "version": "1.58.0",
3
+ "version": "1.58.1",
4
4
  "description": "Connect a local coding agent to EngineerOS, using ACP when supported.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",