@engineeros/connector 1.59.12 → 1.59.13
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/LICENSE +2 -1
- package/README.md +2 -0
- package/bin/engineeros-connector.mjs +1 -1
- package/package.json +1 -1
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -67,4 +67,6 @@ npm install --global @engineeros/connector@latest
|
|
|
67
67
|
|
|
68
68
|
## License
|
|
69
69
|
|
|
70
|
+
Copyright (c) 2026 [Techmirus Innovations](https://www.techmirus.com).
|
|
71
|
+
|
|
70
72
|
The [EngineerOS Connector Binary Use License](LICENSE) permits personal and commercial use of the official executable distribution. The original source remains proprietary. Third-party dependencies retain their own licenses; bundled grammar notices are in [grammars/NOTICE.md](grammars/NOTICE.md).
|
|
@@ -1111,7 +1111,7 @@ It is checked with the provider and stored in this machine's protected vault
|
|
|
1111
1111
|
(Windows Data Protection, the macOS Keychain or the Linux Secret Service).
|
|
1112
1112
|
EngineerOS never receives it; the running connector uses it when EngineerOS asks.`;function XK(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(`
|
|
1113
1113
|
`),c?o(c):r(s.trim())},a=c=>{for(let l of c){if(l==="\r"||l===`
|
|
1114
|
-
`)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 mC=Symbol("missing");function JK(e,t){return new Promise(n=>{let r=qK(e,t,{stdio:"inherit",shell:!1});r.once("error",o=>n(o?.code==="ENOENT"?mC:o.message)),r.once("close",o=>n(o===0?null:`${e} exited with code ${o}.`))})}function hC(e,t){for(let n of Ac){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 gC(e,t,n,{vault:r=vw(),run:o=Xd,fetchImpl:s=fetch,secret:i=XK,interactive:a=JK,install:c=Vd,log:l=console.log,error:u=console.error}={}){if(n.help||e!=="integrations"&&!t[0])return l(VK),n.help?0:2;if(e==="integrations")return hC(l,(await Yd({run:o,vault:r})).providers),0;let p=t[0];if(!Ac.includes(p))return u(`Unknown provider ${p}. Choose one of: ${Ac.join(", ")}.`),2;if(p==="github"||p==="gitlab"){let f=ys[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===mC){let m=await xi(f);if(!m){l(`Installing the ${Ec[f].label} ${Ec[f].version} for the connector...`);try{m=(await c(f)).path}catch(g){return u(g.message),1}}h=await a(m,["auth","login"])}return h?(u(`${h} ${Kd[p]} is how this machine signs in to ${p}.`),1):(hC(l,{[p]:(await Yd({run:o,vault:r})).providers[p]}),0)}let d=rn[p];if(e==="disconnect")return await r.delete("",p),l(`Removed the ${d.label} ${d.tokenName} from this machine.`),0;try{await bw(r);let f=await i(`${d.label} ${d.tokenName} (create one at ${d.tokenUrl}): `),h=await Sw(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}}I();import{spawn as KK}from"node:child_process";async function wC({root:e,bundled:t,argv:n,workspace:r,spawnImpl:o=KK,log:s=console.log}){let i=n,a=!1;for(;;){let c=t;try{c=wo(await yn(e),t)}catch(p){s(`${p.message} Starting the installed connector ${t.version}.`)}let{code:l,signal:u}=await YK(o,c.entry,i,t);if(l===Ki){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 yn(e).catch(()=>null);if(p&&!p.confirmed&&p.active?.version===c.version)try{let d=await Mp(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 YK(e,t,n,r){return new Promise((o,s)=>{let i=e(process.execPath,[...process.execArgv,t,...n],{stdio:"inherit",env:{...process.env,[As]:"1",[Cp]:r.entry,[Op]: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 Bo="1.59.
|
|
1114
|
+
`)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 mC=Symbol("missing");function JK(e,t){return new Promise(n=>{let r=qK(e,t,{stdio:"inherit",shell:!1});r.once("error",o=>n(o?.code==="ENOENT"?mC:o.message)),r.once("close",o=>n(o===0?null:`${e} exited with code ${o}.`))})}function hC(e,t){for(let n of Ac){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 gC(e,t,n,{vault:r=vw(),run:o=Xd,fetchImpl:s=fetch,secret:i=XK,interactive:a=JK,install:c=Vd,log:l=console.log,error:u=console.error}={}){if(n.help||e!=="integrations"&&!t[0])return l(VK),n.help?0:2;if(e==="integrations")return hC(l,(await Yd({run:o,vault:r})).providers),0;let p=t[0];if(!Ac.includes(p))return u(`Unknown provider ${p}. Choose one of: ${Ac.join(", ")}.`),2;if(p==="github"||p==="gitlab"){let f=ys[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===mC){let m=await xi(f);if(!m){l(`Installing the ${Ec[f].label} ${Ec[f].version} for the connector...`);try{m=(await c(f)).path}catch(g){return u(g.message),1}}h=await a(m,["auth","login"])}return h?(u(`${h} ${Kd[p]} is how this machine signs in to ${p}.`),1):(hC(l,{[p]:(await Yd({run:o,vault:r})).providers[p]}),0)}let d=rn[p];if(e==="disconnect")return await r.delete("",p),l(`Removed the ${d.label} ${d.tokenName} from this machine.`),0;try{await bw(r);let f=await i(`${d.label} ${d.tokenName} (create one at ${d.tokenUrl}): `),h=await Sw(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}}I();import{spawn as KK}from"node:child_process";async function wC({root:e,bundled:t,argv:n,workspace:r,spawnImpl:o=KK,log:s=console.log}){let i=n,a=!1;for(;;){let c=t;try{c=wo(await yn(e),t)}catch(p){s(`${p.message} Starting the installed connector ${t.version}.`)}let{code:l,signal:u}=await YK(o,c.entry,i,t);if(l===Ki){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 yn(e).catch(()=>null);if(p&&!p.confirmed&&p.active?.version===c.version)try{let d=await Mp(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 YK(e,t,n,r){return new Promise((o,s)=>{let i=e(process.execPath,[...process.execArgv,t,...n],{stdio:"inherit",env:{...process.env,[As]:"1",[Cp]:r.entry,[Op]: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 Bo="1.59.13",op="1.59.13",tY=3e5,sp=["queued","running","reporting"],nY=5e3,kw={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."},Ew={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."},rY=6e4,oY=3e4,sY=60*6e4,$w={id:"tool_inventory",title:"Tool inventory refresh",remedy:"Run `engineeros-connector tools list` in this workspace for the full registry state."},xw={id:"runner_setup_reporting",title:"Goal runner setup reporting",remedy:"Restore the connection to EngineerOS; saved setup reports will retry automatically."},{command:kt,positional:Bt,flags:Le}=YA(process.argv.slice(2));kt==="version"&&(console.log(Bo),process.exit(0));var po=null,an=!1,Sr=null,jC=!1,NC=null,Dw=null,Gt=null,Nc=null,Mw,yC,_C,Aw,vC,Ri,Oi,MC=Md({getWorkspace:()=>M.workspace,onRecorded:e=>V1(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}`))}),iY=pC({getWorkspace:()=>M.workspace,huntSignIns:MC}),Cc=tT();kt==="results"&&(Bt[0]!=="upload"&&(console.log(Ad),process.exit(Le.help||!Bt[0]?0:2)),process.exit(await s1(Le)));(kt==="connect"||kt==="disconnect"||kt==="integrations")&&process.exit(await gC(kt,Bt,Le,{fetchImpl:lC}));if(kt==="runner"){let e=sn.resolve(Le.workspace||process.cwd()),t=Bt[0]||"status";try{if(t==="serve"||t==="worker"){let n=t==="worker"?sn.join(sn.dirname($t(e,Le["run-id"])),"worker.log"):sn.join(e,".engineeros","runner","service.log");QK(sn.dirname(n),{recursive:!0});let r=(...s)=>Ja(n,`${eY(...s)}
|
|
1115
1115
|
`),o=(s,i,a)=>(Ja(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(Le["keep-awake"]!==void 0){if(!["on","off"].includes(Le["keep-awake"]))throw new Error("Use --keep-awake on or off.");let n=await Zt(e);if(!n)throw new Error("Pair this workspace before changing its runner keep-awake setting.");await qn({...n,runner_keep_awake:Le["keep-awake"]==="on"})}console.log(`Installed Goal runner service: ${await Ku(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 Ix(e),console.log("Goal runner service removed. Saved and queued jobs are kept.")):t==="start"?await hi(e,{enable:!0}):t==="status"?console.log(JSON.stringify(await Io(e),null,2)):t==="serve"?await Px(e):t==="worker"?await Lx(e,Le["run-id"]):gt("Usage: engineeros-connector runner [install|start|status|uninstall] --workspace PATH [--keep-awake on|off]");process.exit(0)}catch(n){gt(Jm(n,e).message)}}Le["assessment-workers"]!==void 0&>("--assessment-workers is no longer supported. Select 3 to 8 parallel agents in EngineerOS before starting the assessment.");if(kt==="secret")try{let e=Ym(Le),t=Bt[0]||"list",n=await KA({action:t,name:Bt[1],workspace:e,readValue:()=>JA({label:`Value for ${Bt[1]}`}),write:r=>console.log(r)});process.exit(n.ok?0:1)}catch(e){gt(e.message)}if(kt==="tools"){try{let e=Ym(Le),t=Bt[0]||"list";if(["sign-in","auth-status","sign-out"].includes(t)){let r=Bt[1];r||gt(`Usage: engineeros-connector tools ${t} PROVIDER_ID [--workspace PATH | --project PROJECT_UUID]`);let o=await Uh(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 ja(e,{type:"tools.update",command_id:"00000000-0000-4000-8000-000000000002",action:t,provider_id:Bt[1],confirmed:!0},void 0,{confirmLocal:async()=>!0}):t!=="list"&&await Ph(e,t,Bt[1]);let n=await Bn(e);console.log(JSON.stringify(n,null,2)),process.exitCode=n.error?1:0}catch(e){gt(e.message)}process.exit(process.exitCode||0)}if(kt==="agents"){let e;try{e=await tm()}catch(n){gt(n instanceof Error?n.message:String(n))}let t=await Promise.all(e.map(async n=>{try{return await Ma(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(kt==="agent"){let e=Bt[0],t=Bt[1]||"check";(!e||!["check","install"].includes(t))&>("Usage: engineeros-connector agent AGENT_ID [check|install]");try{let n=t==="install"?await Pa(e):await Ma(e);console.log(`${n.name} is ready (${n.version}, ${n.distribution}).`)}catch(n){gt(n instanceof Error?n.message:String(n))}process.exit(0)}if(kt==="mcp"){let e=Le.workspace||process.env.ENGINEEROS_MCP_WORKSPACE||process.cwd(),t=Le["run-id"]||Bt[0]||process.env.ENGINEEROS_MCP_RUN_ID||null,n=await Zt(e);await mT({config:n,runId:t,version:Bo,input:process.stdin,output:process.stdout}),process.exit(0)}if(kt==="context-mcp"){let e=Le["config-workspace"]||Le.workspace||process.env.ENGINEEROS_MCP_WORKSPACE||process.cwd(),t=await Zt(e);t||gt("This workspace is not paired with EngineerOS."),await JT({config:t,workspace:Le.workspace||process.env.ENGINEEROS_CONTEXT_WORKSPACE||t.workspace,version:Bo,input:process.stdin,output:process.stdout}),process.exit(0)}if(kt==="status"){let e=await Zt(Le.workspace||process.cwd());console.log(e?`Paired as ${e.name} (${e.connector_id}) for ${e.workspace}`:"Not paired"),process.exit(e?0:1)}if(kt==="doctor"){let e=sn.resolve(Le.workspace||process.cwd()),t=await Zt(e),n=await uT(e),r=await Li(t||{workspace:e},e,Rg(n));console.log(Eg(r)),process.exit(r.status==="failed"?1:0)}if(kt==="update"){let e=Bt[0]||"status";try{let t=jp(process.argv[1],op),n=await Pp(Br(),t,{action:e,policy:Bt[1]??null});console.log(Zi(Lp(n,t,{supervised:!0})))}catch(t){gt(`${t.message}
|
|
1116
1116
|
Usage: engineeros-connector update [status|check|apply|rollback|policy manual|approve|auto-patch|auto-minor]`)}process.exit(0)}var Ii=kt==="hunt-host";if(Ii)try{Le.workspace=zx(Bt,Le)}catch(e){gt(e.message)}if((kt==="start"||kt==="pair"||Ii)&&process.env[As]!=="1"&&jt(op))try{process.exit(await wC({root:Br(),bundled:{version:op,entry:sn.resolve(process.argv[1])},argv:process.argv.slice(2),workspace:sn.resolve(Le.workspace||process.cwd())}))}catch(e){gt(`The connector process could not be started: ${e.message}`)}if(Ii){try{await Bx(Le.workspace,Bt[0]?Le.agent:null)}catch(e){gt(e.message)}kt=Bt[0]?"pair":"start"}var M,bs,Oc;if(kt==="pair"){let e=Bt[0];e||gt("Usage: engineeros-connector pair CODE --url URL [--agent AGENT_ID | --agent-protocol forge] [--name NAME] [--workspace PATH] [--skip-git-repo-check]");let t=Le.url;t||gt("Pairing requires --url with the EngineerOS backend address."),Le.agent&&Le["agent-command"]&>("Use either --agent or --agent-command, not both.");let n=Le["agent-protocol"]||(Le["agent-command"]?"acp":"codex");["codex","acp","forge"].includes(n)||gt(`Unknown --agent-protocol '${n}'. Use codex, acp, or forge.`),n==="forge"&&(Le.agent||Le["agent-command"])&>("Forge runs its own agents. Drop --agent and --agent-command when pairing with --agent-protocol forge.");let r={};try{Le.agent&&(await Ma(Le.agent),r=await nm(Le.agent))}catch(o){gt(o instanceof Error?o.message:String(o))}M={server_url:Fp(t),workspace:sn.resolve(Le.workspace||process.cwd()),onboard:Le.onboard===!0,onboarding_pending:Le.onboard===!0,hunt_host:Ii,agent_protocol:n,agent_command:Le["agent-command"]||null,agent_args:CY(Le["agent-args"]),agent_name:Le["agent-name"]||null,...r,skip_git_repo_check:Ii||Le["skip-git-repo-check"]===!0,name:Le.name||`${ZK.hostname()} - ${sn.basename(sn.resolve(Le.workspace||process.cwd()))}`},Oc=await Zt(M.workspace),bs={type:"pair",pairing_code:e,name:M.name,capabilities:{},...Yy(Oc,M.server_url)}}else kt==="start"?(M=await Zt(Le.workspace||process.cwd()),M||gt("This connector is not paired. Create a pairing command in EngineerOS first."),Ii&&!M.hunt_host&>("This folder is not a paired hunt host. Generate a new hunt-host command in EngineerOS."),M.token||gt("This connector's token is no longer in this machine's credential store. Create a new pairing command in EngineerOS and pair again."),bs={type:"authenticate",connector_id:M.connector_id,token:M.token}):gt("Use `engineeros-connector pair`, `start`, `status`, `doctor`, `agents`, `agent`, `tools`, `secret`, or `mcp`.");var PC=Dx(M,{reportError:e=>console.error(e)}),zo=0,ip=!1,Ic=null,cn=new Map,Tw=0,Rw=new Set,ji=[],on=new Map,Mt,Pw,ep,Mr=null,tp=!1,LC=0,Cw=null,Ow=[],np,DC,Tc=1e3,Ni,bC=0,Iw=!1,co=!1,nr,Fo=!1,ap=!1,Lw=0;function Ti(e){return Lw+=1,e.finally(()=>{Lw-=1})}var Ci,_s=0;function jc({exitCode:e=0}={}){if(_s=Math.max(_s,e),Ci)return Ci;let t=setTimeout(()=>{console.error("Connector shutdown exceeded 15 seconds; inspect the retained agent logs before restarting."),process.exit(1)},15e3);return t.unref(),Ci=aY().finally(()=>clearTimeout(t)),Ci}async function aY(){if(an=!0,Nc?.stop(),po?.stop(),Dw?.stop(),NC?.stop(),clearInterval(Mw),Gt?.stop(),DC?.(),clearTimeout(np),clearInterval(Pw),clearInterval(ep),await Promise.all([...[...cn.values()].map(e=>vn(e.child))]),await Promise.all([...on.values()].map(zw)),await Ri?.cancelAll(),await Oi?.abortAll(),await Na(),await Kw().catch(e=>{_s=Math.max(_s,1),console.error(`${e.message}. Stop those processes before restarting the connector.`)}),Mt?.close(),_s&&_s!==Ki){let e;await Promise.race([(async()=>{await po?.drain(),await Li(M,M.workspace)})().catch(()=>{}),new Promise(t=>{e=setTimeout(t,1e4)})]).finally(()=>clearTimeout(e))}process.exit(_s)}for(let e of["SIGINT","SIGTERM","SIGHUP"])process.on(e,()=>{jc()});var SC=!1;for(let e of["uncaughtException","unhandledRejection"])process.on(e,async t=>{SC||(SC=!0,console.error(`Connector stopping after an unhandled failure: ${t instanceof Error?t.stack||t.message:String(t)}`),await jc({exitCode:1}))});Gt=ry();process.on("exit",()=>{Nc?.stop(),Gt.stop()});Gt.banner(`EngineerOS connector ${Bo}`,[M.workspace,M.server_url]);po=eT({actions:{refresh_tool_inventory:async()=>{He.tool_inventory=await Bn(M.workspace),In()},restart_goal_runner:()=>hi(M.workspace)},onNotify:()=>Li(M,M.workspace),explain:async e=>{if(!await Pi())return null;let{reading:t}=await ax(M,e);return t},onUpdate:e=>lT(M.workspace,e)});NC=pT({render:(e,t)=>Gt.write(e,t),onRecord:e=>po.observe(e)});Dw=fT({workspace:M.workspace,onRecord:e=>{po.observe(e),Gt.line(e.channel,e.level,e.message)}});po.start();M.hunt_host||Dw.start();Gt.live&&!M.hunt_host&&(Mw=setInterval(()=>{cY().catch(()=>{})},nY),Mw.unref?.());var jw=new Set;async function cY(){if(M.hunt_host)return;yC??=qm(M.workspace);let{jobs:e}=await yC(),t=new Set,n=e.filter(r=>r.status!=="queued"&&sp.includes(r.status)).length;for(let r of e){if(!sp.includes(r.status))continue;t.add(r.runId),jw.add(r.runId);let o=r.status==="queued"&&n>0?`queued behind running Goals (running: ${n})`:r.activity?.phase||r.status;Gt.status(`goal:${r.runId}`,o,lY(r),{agent:r.status!=="queued",link:Ic&&`${Ic}/goals`}),Gt.step(`goal:${r.runId}`,r.activity?.message)}for(let r of jw)t.has(r)||(jw.delete(r),Gt.clearStatus(`goal:${r}`))}function lY(e){let t=e.startedAt??Date.parse(e.updatedAt??"");return Number.isFinite(t)?t:Date.now()}async function Pi({ignoreBugHunt:e=!1}={}){if(an||cn.size>0||on.size>0||zo>0||(Ri?.active??0)>0||!e&&(Oi?.active??0)>0)return!1;try{let{jobs:t}=await Io(M.workspace);return!an&&!t.some(n=>sp.includes(n.status))}catch{return!1}}try{let e=M.hunt_host?{}:await $s(M.workspace);e.committed&&(M.onboarding_pending=!0,M.connector_id&&await qn(M),console.log(`Local project repository ready at ${e.revision.slice(0,8)}. Source and design artifacts are committed locally.`))}catch(e){await GC(e)}var UC=await yn(Br()).then(e=>e.policy!=="manual",()=>!1),ut;try{ut=await qa(M,M.workspace)}catch(e){await GC(e)}console.log(`Using ${ut.name} through ${ut.protocol} (${ut.version}).`);var FC=async()=>dc({workspace:M.workspace}).names().catch(()=>[]),He=yd(M,ut,await Bn(M.workspace),{secretNames:await FC()}),uo=Ly({running:jp(process.argv[1],op),supervised:process.env[As]==="1",isIdle:async()=>!an&&cn.size===0&&ji.length===0&&on.size===0&&zo===0&&Lw===0&&!Fo&&!ap&&!tp,restart:()=>jc({exitCode:Ki}),onChange:e=>{He.runtime_update=e,Mt?.readyState===WebSocket.OPEN&&In()}});try{await uo.refresh()}catch(e){console.error(`Connector updates are unavailable: ${e.message}`)}M={...M,execution_profiles:ut.executionProfiles??null};kt==="pair"&&Oc?.connector_id||await qn(M);He.agent_session={...He.agent_session,status:"checking",message:`Checking that ${ut.name} can answer.`};He.bug_hunt_browser=!1;bs.capabilities=He;console.log(to(M.worker_limit)===null?`Workers: automatic, ${ai()} ${ut.name} workers side by side for this machine's CPU and memory; change it with /workers.`:`Workers: ${to(M.worker_limit)} ${ut.name} workers side by side, set with /workers.`);var vs=e=>no(M,e),kC=qu(vs,{signature:gx});async function uY(){let e=await Io(M.workspace).catch(()=>({service:null,jobs:[]}));return{version:Bo,now:Date.now(),workspace:M.workspace,config_path:An(M.workspace),config:M,agent:ut,automatic_worker_limit:ai(),worker_limit:to(M.worker_limit),connection:{state:dY(),server_url:M.server_url,last_error:nr||null},work:{assessments:[...cn.values()].map(t=>({stage:t.stage,message:t.lastMessage,started_at:t.startedAt})),prompts:[...on.values()].map(t=>({id:String(t.runId).slice(0,8),purpose:t.purpose,started_at:t.startedAt})),integrations:zo},runner:e,runtime_update:uo.report(),health:po?.health()??null,activity:Cc.snapshot()}}function dY(){return an||co?"stopped":Mt?.readyState===WebSocket.OPEN?"connected":"connecting"}var pY={async cancelPrompt(e){let t=[...on.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=>BC(e),setVerbose(e){return e===ip?`Detailed agent activity is already ${e?"on":"off"}.`:(Uw(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"?(uo.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 uo.command(e),Zi(await uo.refresh()))}};Nc=sT({ui:Gt,snapshot:uY,actions:pY});Nc&&console.log(oT());await zC();var EC=new Set;async function zC(){if(an||co)return;console.log(`Connecting ${M.name} to ${M.server_url}`),co=!1,nr=void 0;let e=new WebSocket(M.server_url);Mt=e;let t=tb(e,M.server_url,{onTimeout:r=>{Mt===e&&(nr=r,console.error(r),Nw())}});DC=t,e.addEventListener("open",()=>{if(Mt!==e){e.close();return}try{if(Jv(Mt,e,bs))return;throw new Error("The WebSocket was not open when authentication started.")}catch(r){nr=pn(r),console.error(`Could not authenticate the WebSocket connection: ${nr}`);try{e.close()}catch{}Nw()}}),e.addEventListener("message",r=>{if(Mt!==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: ${pn(s)}`)})});let n=async r=>{if(r.type==="authenticated"&&r.connector?.capabilities?.http_updates!==!0){an=!0,co=!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=Oc?.connector_id===r.connector.id;if(M=Zy(M,Oc,r.connector.id,r.token),await qn(M),r.connector?.capabilities?.http_updates!==!0){an=!0,co=!0,console.error("Pairing saved. Update the EngineerOS backend for HTTP updates, then start this connector again."),e.close();return}bs={type:"authenticate",connector_id:M.connector_id,token:M.token,capabilities:He},console.log(s?`Reconnected existing workspace connector ${M.connector_id}; assessment history is preserved.`:`Paired. Connector ${M.connector_id} is online.`),TC(r);return}if(r.type==="authenticated"){t();let s=M.hunt_host?"Bug Hunter sessions":"EngineerOS runs";console.log(Ni?`Reconnected after ${ot(Date.now()-Ni)} offline; waiting for ${s}.`:`Connected and waiting for ${s}.`),Ni=void 0,TC(r);return}if(r.type==="provider.login"||r.type==="provider.logout"){ap||hY(r);return}if(r.type==="workspace.refresh"){Mi();return}if(r.type==="workers.update"){try{console.log(`EngineerOS changed the workers. ${await BC(r.worker_limit??"auto")}`)}catch(s){console.error(`Workers were not changed: ${s.message}`)}return}if(r.type==="logging.update"){Uw(r.activity_log_enabled===!0);return}if(r.type==="tools.update"){let s=r.provider_id==="playwright"&&["setup","upgrade","rollback"].includes(r.action);s&&(lo=!1,He.bug_hunt_browser=!1,In());try{He.tool_inventory=await ja(M.workspace,r,void 0,{confirmLocal:i=>Nc?.confirm(i)??!1,log:rp}),s&&(lo=!0),He.bug_hunt_browser=gs(He.tool_inventory)&&lo,e.send(JSON.stringify({type:"tools.updated",command_id:r.command_id,inventory:He.tool_inventory})),In(),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 Uh(M.workspace,r,{onStatus:async()=>{He.tool_inventory=await Bn(M.workspace),In()}});He.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:He.tool_inventory})),In(),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"){Us(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===dC){Ti(iY(r).then(s=>(s.error&&console.error(`${r.provider} ${r.operation} failed: ${s.error}`),fC(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}`;Nm(ji,cn.get(s),r)==="deferred"&&console.log(`Assessment stage ${r.stage} is already running here; EngineerOS will be answered when it finishes.`),Mc();return}if(r.type==="prompt.execute"){let s=on.get(r.prompt_id);s?XC(r)>s.executionRevision&&await xY(s,r):VC(r);return}if(r.type==="prompt.cancel"){let s=on.get(r.prompt_id);s&&await zw(s);return}if(r.type==="agent.warm"){_Y(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 PC.dispatch(r);s.blocked?console.error(s.message):console.log(`Goal ${r.run_id} queued for the independent runner. Logs: ${sn.join(M.workspace,".engineeros","runs",r.run_id,"activity.log")}`)}catch(s){console.error(`Goal dispatch failed: ${pn(s)}`)}return}if(r.type==="goal.cleanup"){try{await Mx(M.workspace),await hi(M.workspace)}catch(s){console.error(`Goal cleanup is pending: ${s.message}`)}return}if(r.type==="run.accepted"){RY(r);return}if(r.type==="run.cancelled"){await Wm(M.workspace,r.run_id);return}if(r.type===Qb){Ri??=wh({getConfig:()=>M,onTestsCommitted:()=>Mi()}),Ti(Ri.handle(r));return}if(r.type===eS){Ri??=wh({getConfig:()=>M,onTestsCommitted:()=>Mi()}),await Ri.cancel(r);return}if(r.type===jR){Oi??=DR({getConfig:()=>M,isIdle:()=>Pi({ignoreBugHunt:!0}),recordedSignIns:MC,activity:{status:Gt.status,step:Fw,agents:Gt.agents,finish:Gt.finish}}),Ti(Oi.handle(r));return}if(r.type===NR){Oi?.stop(r);return}if(r.type===i1){_C??=a1({getConfig:()=>M}),Ti(_C.handle(r));return}if(r.type===f1){Aw??=S1({getConfig:()=>M}),Ti(Aw.handle(r));return}if(r.type===h1){await Aw?.cancel(r);return}if(r.type===E1){vC??=$1({getConfig:()=>M,isIdle:()=>Pi(),agentTurn:j$}),Ti(vC.handle(r));return}if(r.type==="connector.update"){fY(e,r);return}if(r.type==="connector.disconnect"){console.log(r.message),await jc();return}if(r.type==="connector.revoked"){an=!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||(Fo=!1);return}if(r.type==="connection.error"){co=!0,console.error(`EngineerOS: ${r.message}`);return}let o=String(r.type??"(missing)").replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,120);EC.has(o)||(EC.add(o),console.warn(`Unknown EngineerOS message type ${o}; connector ${Bo}. Update the connector and backend to compatible versions.`))};e.addEventListener("close",r=>{if(t(),Mt!==e||Ci)return;let o=Kv(r);if(!o.retry||co||an){console.error(o.message),o.retry&&co&&console.error("Connection rejected. Create a new pairing command in EngineerOS if this connector was revoked."),jc();return}nr=nr?`${o.message} ${nr}`:o.message,Nw()}),e.addEventListener("error",r=>{Mt===e&&(nr=Xv(r),console.error(`WebSocket connection to ${M.server_url} failed: ${nr}`))})}async function fY(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=uo.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 uo.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 hY(e){let t=e.request_id,n=e.type==="provider.logout"?"logout":"login";ap=!0,console.log(`Starting interactive ${ut.name} provider ${n}.`);try{await(n==="logout"?eb:Qv)(ut,M.workspace),ut=await qa(M,M.workspace),He=yd(M,ut,He.tool_inventory,{secretNames:await FC()}),bs.capabilities=He,Mt.readyState===WebSocket.OPEN&&(Mt.send(JSON.stringify({type:`provider.${n}.completed`,request_id:t,session:He.agent_session})),Mt.close(1e3,`Provider ${n} completed`)),console.log(`${ut.name} provider ${n} completed.`)}catch(r){let o=pn(r).slice(0,500);Mt.readyState===WebSocket.OPEN&&Mt.send(JSON.stringify({type:`provider.${n}.failed`,request_id:t,message:o})),console.error(`Provider ${n} failed: ${o}`)}finally{ap=!1}}function Nw(){if(an||co||np)return;let e=nr?` Last error: ${nr}`:"",t=Ni?` Offline for ${ot(Date.now()-Ni)}.`:"";Ni??=Date.now(),console.error(`Connection unavailable.${e}${t} Retrying in ${Math.round(Tc/1e3)}s.`),np=setTimeout(()=>{np=void 0,zC()},Tc),Tc=Math.min(3e4,Tc*2)}async function Mi(){if(!M.hunt_host&&!(Fo||Mt.readyState!==WebSocket.OPEN)){Fo=!0,console.log("Inspecting the workspace without executing its code.");try{let{snapshot:e,map:t,stats:n}=await Pg({workspace:M.workspace,connectorId:M.connector_id,refresh:Ns,takeSnapshot:ux,buildMap:(i,a)=>Ed(M.workspace,i,{head:a.head_revision,branch:a.branch}),log:i=>console.error(i)}),r=await lx(M.workspace,M.last_head_reported??M.last_snapshot_head,e.head_revision).catch(()=>null);r&&(e.changed_since=r);let o=await fetch(Ts(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 _a(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 qn(M),t&&await $d(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.`),Fo=!1}catch(e){Fo=!1,console.error(`Workspace assessment failed: ${pn(e)}`)}}}var mY=8e6,$C,xC="";async function gY({current:e,previous:t}){if(Fo||Mt?.readyState!==WebSocket.OPEN)throw new Error("A snapshot is running or the connection is down.");let n=sn.resolve(M.workspace),r=async()=>{M={...M,last_head_reported:e.head,last_head_branch:e.branch??null},await qn(M)},o=await Mg(M.workspace,M.connector_id),s=async()=>{if(await Mi(),M.last_head_reported!==e.head)throw new Error("The snapshot did not report this commit.")};if(!o)return s();let{index:i}=await Ns(M.workspace,M.connector_id),a=null,c=await DT({previous:{head:t.head,branch:t.branch??null},current:e,compare:(d,f)=>Dm(M.workspace,d,f),inventoryDelta:d=>N_(n,Object.entries(i.files).map(([f,h])=>({path:f,size:h.size})),d),mapDelta:async()=>(a=await Ed(M.workspace,i,{head:e.head,branch:e.branch}),Ng(o,a)),contentHead:(await Al(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)>mY)return s();let u=await fetch(t_(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 _a(u,"the new commit"));let p=await u.json().catch(()=>({}));if(p.needs_snapshot)return s();await r(),a&&await $d(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 wY(){M.hunt_host||M.onboarding_pending||Fo||Mt?.readyState!==WebSocket.OPEN||($C??=LT({readHead:()=>PT(M.workspace),getLastReported:()=>({head:M.last_head_reported??M.last_snapshot_head,branch:M.last_head_branch}),onChange:gY,onError:e=>{e.message!==xC&&(xC=e.message,console.error(`The new commit could not be reported yet: ${pn(e)}`))}}),$C.poll().catch(()=>{}))}var yY=6e4,AC=0;async function _Y(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()-AC>yY&&(AC=Date.now(),r.push(Ns(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(Ck(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(`${ut?.name||"The agent"} could not be started ahead of the conversation: ${o.message}`))),await Promise.all(r)}function In(){let e=Y$(cn);kC.update({type:"assessment.workers",assessment_workers:e,tool_inventory:He.tool_inventory,runtime_update:He.runtime_update,agent_session:He.agent_session,bug_hunt_browser:He.bug_hunt_browser,...Bu(M.worker_limit)}),kC.flush().catch(t=>console.error(`Assessment status: ${t.message}`))}async function BC(e){let t=to(e);return t===to(M.worker_limit)?t===null?"Workers are already automatic.":`Workers are already set to ${t}.`:(M={...M,worker_limit:t},await qn(M),Mc(),In(),t===null?`Workers are automatic again: up to ${ai()} side by side for this machine's CPU and memory, for ${fc} (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: ${fc}. A Goal that uses your working folder still runs alone. Running work finishes; waiting work starts as workers free up.`)}function Uw(e){if(e!==ip){if(ip=e,!e)for(let t of cn.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."),In()}}function Fw(e,t,n=null){Gt.step(e,t,n)&&ip&&console.log(`[${e}] ${n?`${n}: `:""}${t}`)}function vY(){clearInterval(ep);let e=!1,t=()=>{e||cn.size>0||on.size>0||(e=!0,Li(M,M.workspace).finally(()=>{e=!1}))};t(),ep=setInterval(t,tY),ep.unref?.()}async function Li(e,t,n=po?.healthChecks()??[]){let r=await BA({config:e,workspace:t,version:Bo,insights:n,agentSession:Sr,probes:{inspectAgent:(o,s)=>an?ut:qa(o,s),inspectTools:o=>an?He.tool_inventory:Bn(o),runnerStatus:Io}});try{jC=(await GA(e,r,no))?.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 GC(e){if(an)return Ci;let t=e instanceof Error?e.message:String(e),n=await Li(M,M.workspace).catch(()=>null);n&&console.error(Eg(n)),gt(t)}function TC(e){Uw(e.connector?.activity_log_enabled===!0),Ic=e.project_url??null,Tc=1e3,SY(),WC(),uo.confirm().catch(t=>console.error(`Connector update state: ${t.message}`)),kY(),M.onboarding_pending&&Mi()}var Rc=null,lo=!1,HC=0,bY=Date.now();async function SY(){return Rc||(Rc=(async()=>{UC&&await pk(M.workspace,{log:t=>console.log(`[tools] ${t}`)}).catch(t=>console.error(`[tools] Tool updates were skipped: ${t.message}`));let e=Date.now();try{rp("Preparing Bug Hunter's browser: Playwright, then a check that a browser starts. The first setup can take a few minutes."),await Gx(M.workspace,{log:rp}),lo=!0,He.tool_inventory=await Bn(M.workspace),He.bug_hunt_browser=gs(He.tool_inventory)&&lo,rp(`Bug Hunter's browser is ready (${ot(Date.now()-e)}).`)}catch(t){console.error(`[browser] Bug Hunter's browser setup failed after ${ot(Date.now()-e)}: ${t.message}`),He.bug_hunt_browser=!1}In()})(),Rc)}function rp(e){console.log(`[browser] ${e}`)}async function WC(){if(Sr?.state!=="checking"){HC=Date.now(),He.agent_session={...He.agent_session,status:"checking",message:`Checking that ${ut.name} can answer.`},In(),Sr={state:"checking",detail:`Asking ${ut.name} one question to confirm its session.`},console.log(`Checking that ${ut.name} can answer before accepting work.`);try{await nx(M,ut.name),Sr={state:"ready",detail:`${ut.name} answered; its session is usable.`},He.agent_session={...He.agent_session,status:"authenticated",message:Sr.detail},console.log(Sr.detail)}catch(e){Sr={state:"failed",detail:e instanceof Error?e.message:String(e),remedy:M.hunt_host?Wx(M.agent_id||M.agent_protocol):ni(M.agent_id||M.agent_protocol)},He.agent_session={...He.agent_session,status:"logged_out",message:Sr.remedy},console.error(`${Sr.detail}
|
|
1117
1117
|
${Sr.remedy}`)}In(),await Li(M,M.workspace).catch(()=>null)}}function kY(){clearInterval(Pw);let e=!1,t=0,n=0,r=!1,o=()=>{uo.tick(),EY(),wY(),M.hunt_host&&Rc&&Date.now()-HC>=Hx(bY)&&on.size===0&&cn.size===0&&!(Oi?.active>0)&&WC(),!M.hunt_host&&!r&&cc(xw.id)&&(r=!0,PC.flush().then(()=>Qd(xw)).catch(s=>Zd(xw,s)).finally(()=>{r=!1})),cn.size>0&&In(),!M.hunt_host&&!Mr&&Date.now()-t>=rY&&cc(kw.id)&&(t=Date.now(),qC().then(()=>Qd(kw)).catch(s=>Zd(kw,s))),!M.hunt_host&&jC&&!tp&&cc(Ew.id)&&Date.now()-LC>=ES&&(tp=!0,$Y().then(()=>Qd(Ew)).catch(s=>Zd(Ew,s)).finally(()=>{tp=!1})),!e&&Date.now()-n>=oY&&cc($w.id)&&(e=!0,n=Date.now(),Bn(M.workspace).then(async s=>{if(He.tool_inventory=s,!lo&&gs(s))try{await(await Jo(await Mo(M.workspace))).close(),lo=!0}catch{lo=!1}He.bug_hunt_browser=gs(s)&&lo,In(),Qd($w)}).catch(s=>Zd($w,s)).finally(()=>{e=!1}))};o(),Pw=setInterval(o,1e4),vY()}async function EY(){if(!(!UC||M.agent_protocol!=="acp"||!M.agent_id||Iw||Sr?.state==="checking"||Date.now()-bC<sY)){Iw=!0;try{if(!await Pi())return;bC=Date.now();let e,t=await Dk(M,{verify:async r=>{e=await qa(r,M.workspace)},log:r=>console.log(`[agent] ${r}`)});if(t===M||an)return;M={...t,execution_profiles:e.executionProfiles??null},await qn(M),ut=e;let n=yd(M,ut,He.tool_inventory);if(Object.assign(He,{agent_name:n.agent_name,agent_version:n.agent_version,execution_profiles:n.execution_profiles}),bs.capabilities=He,!await Pi())return;await Na(),Mt?.readyState===WebSocket.OPEN&&Mt.close(1e3,"Coding agent updated")}catch(e){console.error(`[agent] The agent update check failed: ${e.message}`)}finally{Iw=!1}}}function Zd(e,t){let n=PA(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 Qd(e){LA(e.id)&&console.log(`${e.title} recovered.`)}async function $Y(){if(M.hunt_host||!await Pi())return;LC=Date.now();let{jobs:e}=await Io(M.workspace).catch(()=>({jobs:[]})),t=await $S(M.workspace,{jobs:e});if(!xS(t))return;let n=`${t.fingerprint}:${Ow.join(",")}`,r=Cw?.key===n,o=r?Cw.candidates:await cx(M,t,Ow);Cw={key:n,candidates:o};let s=await vs(RS(t,o,{version:Bo}));Array.isArray(s?.refused)&&(Ow=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 Uo=null,RC=null;async function qC(){if(!M.hunt_host){if(Mr)return Mr;Mr=(async()=>{let e=await gS(M,{knownRevision:Uo?.revision??null});if(e.unchanged||(Uo=e),RC===Uo.revision)return Uo;let{jobs:t}=await Io(M.workspace);return!t.some(r=>sp.includes(r.status))&&zo===0&&cn.size===0&&(await au(M.workspace,Uo),RC=Uo.revision),Uo})();try{return await Mr}finally{Mr=null,Mc()}}}function CC(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)),on.get(e)?.events.push(n)}var OC=null;function Mc(){let e=Mt.readyState===WebSocket.OPEN,t=cn.values().next().value,n=to(M.worker_limit)??Math.min(ai(),Mm(t?.workerLimit??ji[0]?.worker_limit)),r=e&&!Mr&&zo===0?B$(ji,cn.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:Mm(s.worker_limit),lastActivityAt:Date.now(),eventCount:0,lastDetail:null};cn.set(i,a),TY(s,a)}r.length>0&&In();let o=G$({queued:ji,running:cn.size,workerLimit:n,connected:e,designSync:!!Mr,integrations:zo});o&&o!==OC&&console.log(o),OC=o}function cp(e){let t=Pm(e);return t?`${ut.name} on ${t}`:ut.name}async function VC(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:vx(vs),executionRevision:XC(e),sessionKey:Gu(e),sessionId:null,replacement:null};on.set(t,s);let i=_x(vs,{type:"prompt.heartbeat",prompt_id:t,execution_revision:s.executionRevision},{onError:g=>console.error(`[${n}] Prompt heartbeat: ${g.message}`)}),a,c=g=>{let w=g?JSON.stringify(g):null;!w||w===a||on.get(t)!==s||(a=w,CC(t,g))},l=`${r} \xB7 ${cp(e)}`,u=tx(e,ut.name);CC(t,{kind:"status",message:u});let p=Number(e.answer_within_seconds),d=p>0?o+p*1e3:void 0;console.log([`[${n}] ${u} for ${r}.`,`${ut.name} can reason for several minutes without reporting a step.`,...d?[mp(d,o)]:[]].join(" ")),Gt.status(n,l,o,{link:Ic,answerBy:d});let f=g=>{let w=U$(g),S=us(g);on.get(t)===s&&Fw(n,S??w?.message);let y=g.type==="forge.output"?null:S;c(w??(y?{kind:"status",message:y}:null))},h="failed",m=[r];try{Hu(e)||(f({type:"connector.step",message:"Syncing the design context from EngineerOS"}),e={...e,design_context:await bS(qC,{pinned:!!e.local_design_context,last:Uo,onFallback:(y,_)=>f({type:"connector.step",message:`Design context not refreshed (${y.message}); continuing with ${_?"the copy synced earlier":"none"}`})})});let g=await I$(e,M,{onProcess:y=>{on.get(t)===s&&(s.child=y)},onController:y=>{on.get(t)===s&&(s.controller=y)},onSession:y=>{s.sessionId=y},onEvent:f},{signal:s.cancellation.signal});if(s.stoppedHere)throw new Error(IC);let w=g.singleTurn?Qy(M.sessions,g.sessionKey):zp(M.sessions,g.sessionKey,g.sessionId);if(JSON.stringify(w)!==JSON.stringify(M.sessions||{})&&(M={...M,sessions:w},await qn(M)),s.cancelled)return;await s.events.close().catch(y=>{console.error(`[${n}] Prompt progress delivery: ${y.message} The agent has finished; submitting its complete response separately.`)});let S=await Wu(vs,{type:"prompt.completed",prompt_id:t,execution_revision:s.executionRevision,content:g.content,model:g.model,session_id:g.sessionId,usage:g.usage});S||console.error(`[${n}] ${zm}`),Cc.record("prompt","completed",{durationMs:Date.now()-o,usage:g.usage}),h=S?"finished":"undelivered",m=[Gc(g.usage),r]}catch(g){let w=s.stoppedHere?IC:pn(g);if(Cc.record("prompt","failed",{durationMs:Date.now()-o}),s.stoppedHere&&(h="cancelled"),!s.cancelled){try{await Wu(vs,{type:"prompt.failed",prompt_id:t,execution_revision:s.executionRevision,message:w})||console.error(`[${n}] ${zm}`)}catch(S){console.error(`[${n}] Prompt failure delivery: ${S.message}`)}console.error(w)}}finally{await i.stop(),s.events.stop();let g=s.replacement;g?(h="replaced",m=[`continuing on ${cp(g)}`,r]):s.cancelled&&(h="cancelled"),Gt.finish(n,h,m),on.get(t)===s&&on.delete(t),g&&AY(s,g)}}var IC="Cancelled from the connector terminal by the person running it.";async function zw(e){e.cancelled=!0,e.cancellation.abort(),await e.controller?.completed.catch(()=>{})}function XC(e){return Number(e.execution_revision)||1}async function xY(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 ${cp(t)}.`),await zw(e))}function AY(e,t){e.sessionId&&(M={...M,sessions:zp(M.sessions,e.sessionKey,e.sessionId)},qn(M).catch(n=>console.error(`Could not save the agent session: ${n.message}`))),VC(t)}async function TY(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 ${cp(e)}.`),!Rw.has(n)){Rw.add(n);try{let b=await P$(M.workspace);if(!b.exists)console.log("No accepted assessment exists yet; this run establishes the baseline.");else{let $=b.accepted_head_revision?b.current_head_revision?b.current_head_revision!==b.accepted_head_revision?`The workspace is now at commit \`${b.current_head_revision}\`; the accepted assessment is from \`${b.accepted_head_revision}\`.`:"The accepted assessment is already at the current commit.":`The accepted assessment is from \`${b.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 ${b.stages.length||"no"} section(s). ${$}`)}}catch(b){console.error(`Assessment freshness check failed: ${b.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=()=>!an&&cn.get(t.key)===t,g=async b=>{try{return await Wu(vs,b)||console.warn(`[${s}] ${wx}`),!0}catch($){return console.error(`Assessment failure delivery: ${$.message}`),!1}},w=(b,{milestone:$=!0}={})=>{if(!m()||$&&f===b)return;$&&(f=b,h.has(b)||(h.add(b),c=Math.min(90,c+10)),console.log(`[assessment:${r}] ${b}.`));let k=String(b).slice(0,500);t.progressPercent=c,t.lastMessage=k,Gt.status(s,k,o,{link:Ic})};w(`Starting ${r} assessment stage`);let S=setInterval(()=>{let b=Date.now(),$=b-t.lastActivityAt,k=i&&!a?D$(r,$):null;if(!p&&k){p=k,console.error(`[assessment:${r}] ${p}`),Xa(t.controller,t.child);return}p||po.observe({at:b,level:"info",message:Gt.status(s,`${t.lastMessage} \xB7 last agent activity ${ot($)} ago (${t.eventCount.toLocaleString()} events)`,o)})},15e3),y={onSession:async b=>{m()&&(d=String(b),await G0(M.workspace,n,r,b,{sourceRevision:e.source_revision,targetHeadRevision:e.target_head_revision}))},onController:b=>{m()&&(t.controller=b)},onProcess:b=>{m()&&(t.child=b,i=!0,t.phase!=="correcting"&&(t.phase="running",w("Connected agent process started")),t.lastActivityAt=Date.now())},onEvent:b=>{t.lastActivityAt=Date.now(),t.eventCount+=1;let $=L$(b);if($&&w($),!m())return;let k=us(b);!k||k===t.lastDetail||(t.lastDetail=k,Fw(s,k))}},_=(b,$)=>Im(b,$,M,y,{draftPath:sn.relative(M.workspace,sn.join(Ln(M.workspace,n),b.report_file)).split(sn.sep).join("/")});try{let b=Tw-Date.now();b>0&&(w(`Waiting ${Math.ceil(b/1e3)}s for the model provider's rate limit to clear`),await new Promise(R=>setTimeout(R,b+Math.floor(Math.random()*3e3)))),e.assessment_mode==="incremental"&&(c=15,w("Calculating changed files and affected behavior"));let $=await X0(M.workspace,e),k=await If(M.workspace,n,r,{expectedHeadRevision:e.target_head_revision,expectedSourceRevision:e.source_revision});if(k)_(k,$),w("Recovered completed stage report from connector storage");else{if(d=await H0(M.workspace,n,r,{expectedHeadRevision:e.target_head_revision,expectedSourceRevision:e.source_revision}),d&&w("Restoring interrupted agent session"),k=await O$($,M,y,{previousSessionId:d}),p)throw new Error(p);a=!0,await Of(M.workspace,n,$,k)}a=!0,t.phase="delivering",t.progressPercent=95,t.lastMessage=r==="synthesis"?"Delivering completed assessment bundle":"Checkpointing connector-local stage result";let C=R=>fetch(r_(M.server_url,M.connector_id,n),{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${M.token}`},body:JSON.stringify(R),signal:AbortSignal.timeout(g$)}),A=await ex(k,{submit:R=>Q$(R,C,{isActive:()=>m()&&!an,onRetry:(O,T)=>{w("Completed result is waiting for EngineerOS",{milestone:!1}),console.warn(`[assessment:${r}] Completed result delivery failed: ${pn(O)} Retrying in ${Math.round(T/1e3)}s without rerunning the agent.`)}}),payloadFor:R=>r==="synthesis"?jf(M.workspace,n,R,{expectedSourceRevision:e.source_revision}):Z0(R),rejectionFor:R=>_a(R,"the assessment"),correct:async(R,O)=>{if(a=!1,t.phase="correcting",t.lastMessage="Correcting a rejected stage result",!R.correctAfterRejection)throw new Error(`${O} The connector could not start the required agent correction.`);return R.correctAfterRejection(O)},onCorrected:async R=>{if(p)throw new Error(p);a=!0,await q0(M.workspace,n,r);let O=await Of(M.workspace,n,$,R);return _(O,$),t.phase="delivering",t.lastMessage="Delivering corrected stage result",O}});if(p)throw new Error(p);k=A.result;let x=A.response;if(!x.ok)throw new Error(await _a(x,"the assessment"));if(l=!0,Cc.record("assessment stage","completed",{durationMs:Date.now()-o,usage:k.usage}),r==="synthesis"){let R=await x.json(),O=await J0(M.workspace,n,e,k,R.report_markdown);console.log(`Workspace assessment ${n} was accepted by EngineerOS and saved to ${sn.relative(M.workspace,O)}.`);try{let T=await Vc(M.workspace);T.committed&&console.log(`Assessment committed to Git as ${T.revision.slice(0,8)}.`)}catch(T){console.error(`The assessment is saved locally but could not be committed to Git: ${T.message}`)}}else console.log(`Workspace assessment stage ${r} was checkpointed by EngineerOS.`)}catch(b){let $=p||pn(b),k=V$(e,b),C=K$(b),E=W$(b);C&&(await W0(M.workspace,n,r).catch(x=>{console.error(`[assessment:${r}] Could not discard the unusable agent session checkpoint: ${x.message}`)}),d=null);let A=!p&&(d||C)&&(C||H$(b))&&k<E;if(m()&&A){t.phase="starting",t.lastMessage=C?"Agent session became unusable; restarting from saved assessment work":"Agent session interrupted; resuming checkpoint",t.resumeAssignment=X$(e,b);let x=J$(b,k);Va(b)&&(Tw=Math.max(Tw,Date.now()+x)),console.warn(`[assessment:${r}] ${C?"Agent session became unusable":"Agent session interrupted"}: ${$} ${C?"Starting a fresh session from the saved draft":`Resuming session ${d}`} in ${Math.round(x/1e3)}s (${k+1}/${E}).`),await new Promise(R=>setTimeout(R,x))}else m()&&(u=await g({type:"workspace.assessment.failed",assessment_id:n,stage:r,message:$}));A||(Cc.record("assessment stage","failed",{durationMs:Date.now()-o}),console.error(`[assessment:${r}] ${$}`))}finally{clearInterval(S),Gt.clearStatus(s),r==="synthesis"&&l&&Rw.delete(n),m()&&(cn.delete(t.key),Z$(ji,t,{accepted:l,failureReported:u})&&console.log(`Resuming interrupted agent session for assessment stage ${r} from its checkpoint.`),Mc())}}async function RY(e){let t=String(e.run_id||"");zo+=1;try{Mr&&await Mr;let n=await k$(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 Mi();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: ${pn(n)}`)}finally{zo-=1,Mc()}}function CY(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{gt('--agent-args must be a JSON array, for example: --agent-args "[\\"acp\\"]"')}}function gt(e){console.error(e),process.exit(1)}
|