@engineeros/connector 1.52.2 → 1.52.3

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.
@@ -982,7 +982,7 @@ It is checked with the provider and stored in this machine's protected vault
982
982
  (Windows Data Protection, the macOS Keychain or the Linux Secret Service).
983
983
  EngineerOS never receives it; the running connector uses it when EngineerOS asks.`;function MU(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(`
984
984
  `),c?o(c):r(s.trim())},a=c=>{for(let l of c){if(l==="\r"||l===`
985
- `)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 gS=Symbol("missing");function PU(e,t){return new Promise(n=>{let r=jU(e,t,{stdio:"inherit",shell:!1});r.once("error",o=>n(o?.code==="ENOENT"?gS:o.message)),r.once("close",o=>n(o===0?null:`${e} exited with code ${o}.`))})}function mS(e,t){for(let n of Ss){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 wS(e,t,n,{vault:r=Zu(),run:o=Ya,fetchImpl:s=fetch,secret:i=MU,interactive:a=PU,install:c=Ka,log:l=console.log,error:d=console.error}={}){if(n.help||e!=="integrations"&&!t[0])return l(NU),n.help?0:2;if(e==="integrations")return mS(l,(await ec({run:o,vault:r})).providers),0;let u=t[0];if(!Ss.includes(u))return d(`Unknown provider ${u}. Choose one of: ${Ss.join(", ")}.`),2;if(u==="github"||u==="gitlab"){let p=Rr[u];if(e==="disconnect")return l(`${u} uses this machine's ${p} sign-in. Run \`${p} auth logout\` to sign out everywhere on this machine.`),0;let h=await a(p,["auth","login"]);if(h===gS){let g=await ho(p);if(!g){l(`Installing the ${_s[p].label} ${_s[p].version} for the connector...`);try{g=(await c(p)).path}catch(v){return d(v.message),1}}h=await a(g,["auth","login"])}return h?(d(`${h} ${Qa[u]} is how this machine signs in to ${u}.`),1):(mS(l,{[u]:(await ec({run:o,vault:r})).providers[u]}),0)}let f=et[u];if(e==="disconnect")return await r.delete("",u),l(`Removed the ${f.label} ${f.tokenName} from this machine.`),0;try{await Qu(r);let p=await i(`${f.label} ${f.tokenName} (create one at ${f.tokenUrl}): `),h=await ep(r,u,{token:p,site:n.site,email:n.email},s);return l(`Connected ${f.label}${h.account?` as ${h.account}`:""}. The token stays on this machine.`),0}catch(p){return d(p.message),1}}import{spawn as LU}from"node:child_process";async function yS({root:e,bundled:t,argv:n,workspace:r,spawnImpl:o=LU,log:s=console.log}){let i=n,a=!1;for(;;){let c=t;try{c=qn(await $t(e),t)}catch(u){s(`${u.message} Starting the installed connector ${t.version}.`)}let{code:l,signal:d}=await DU(o,c.entry,i,t);if(l===To){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&&!d&&!a){let u=await $t(e).catch(()=>null);if(u&&!u.confirmed&&u.active?.version===c.version)try{let f=await Mc(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 ${f.version}.`);continue}catch(f){s(`Automatic rollback failed: ${f.message}`)}}return l??1}}function DU(e,t,n,r){return new Promise((o,s)=>{let i=e(process.execPath,[...process.execArgv,t,...n],{stdio:"inherit",env:{...process.env,[jr]:"1",[Cc]:r.entry,[Ic]:r.version}}),a=process.platform==="win32"?[]:["SIGINT","SIGTERM","SIGHUP"],c=d=>i.kill(d);for(let d of a)process.on(d,c);let l=()=>{for(let d of a)process.off(d,c)};i.once("error",d=>{l(),s(d)}),i.once("exit",(d,u)=>{l(),o({code:d,signal:u})})})}var lr="1.52.2",ac="1.52.2",GU=3e5,cc=["queued","running","reporting"],HU=5e3,tp={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."},np={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."},BU=6e4,WU=3e4,rp={id:"tool_inventory",title:"Tool inventory refresh",remedy:"Run `engineeros-connector tools list` in this workspace for the full registry state."},op={id:"runner_setup_reporting",title:"Goal runner setup reporting",remedy:"Restore the connection to EngineerOS; saved setup reports will retry automatically."},{command:Pe,positional:ot,flags:ue}=E0(process.argv.slice(2));Pe==="version"&&(console.log(lr),process.exit(0));var Gn=null,lt=!1,yn=null,CS=!1,IS=null,hp=null,it=null,Cs=null,up,_S,vS,xs,yo,OS=qa({getWorkspace:()=>A.workspace,onRecorded:e=>jb(A,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}`))}),qU=fS({getWorkspace:()=>A.workspace,huntSignIns:OS}),$s=A0();Pe==="results"&&(ot[0]!=="upload"&&(console.log(Fa),process.exit(ue.help||!ot[0]?0:2)),process.exit(await mb(ue)));(Pe==="connect"||Pe==="disconnect"||Pe==="integrations")&&process.exit(await wS(Pe,ot,ue,{fetchImpl:dS}));if(Pe==="runner"){let e=rt.resolve(ue.workspace||process.cwd()),t=ot[0]||"status";try{if(t==="serve"||t==="worker"){let n=t==="worker"?rt.join(rt.dirname(Oe(e,ue["run-id"])),"worker.log"):rt.join(e,".engineeros","runner","service.log");UU(rt.dirname(n),{recursive:!0});let r=(...s)=>as(n,`${zU(...s)}
985
+ `)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 gS=Symbol("missing");function PU(e,t){return new Promise(n=>{let r=jU(e,t,{stdio:"inherit",shell:!1});r.once("error",o=>n(o?.code==="ENOENT"?gS:o.message)),r.once("close",o=>n(o===0?null:`${e} exited with code ${o}.`))})}function mS(e,t){for(let n of Ss){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 wS(e,t,n,{vault:r=Zu(),run:o=Ya,fetchImpl:s=fetch,secret:i=MU,interactive:a=PU,install:c=Ka,log:l=console.log,error:d=console.error}={}){if(n.help||e!=="integrations"&&!t[0])return l(NU),n.help?0:2;if(e==="integrations")return mS(l,(await ec({run:o,vault:r})).providers),0;let u=t[0];if(!Ss.includes(u))return d(`Unknown provider ${u}. Choose one of: ${Ss.join(", ")}.`),2;if(u==="github"||u==="gitlab"){let p=Rr[u];if(e==="disconnect")return l(`${u} uses this machine's ${p} sign-in. Run \`${p} auth logout\` to sign out everywhere on this machine.`),0;let h=await a(p,["auth","login"]);if(h===gS){let g=await ho(p);if(!g){l(`Installing the ${_s[p].label} ${_s[p].version} for the connector...`);try{g=(await c(p)).path}catch(v){return d(v.message),1}}h=await a(g,["auth","login"])}return h?(d(`${h} ${Qa[u]} is how this machine signs in to ${u}.`),1):(mS(l,{[u]:(await ec({run:o,vault:r})).providers[u]}),0)}let f=et[u];if(e==="disconnect")return await r.delete("",u),l(`Removed the ${f.label} ${f.tokenName} from this machine.`),0;try{await Qu(r);let p=await i(`${f.label} ${f.tokenName} (create one at ${f.tokenUrl}): `),h=await ep(r,u,{token:p,site:n.site,email:n.email},s);return l(`Connected ${f.label}${h.account?` as ${h.account}`:""}. The token stays on this machine.`),0}catch(p){return d(p.message),1}}import{spawn as LU}from"node:child_process";async function yS({root:e,bundled:t,argv:n,workspace:r,spawnImpl:o=LU,log:s=console.log}){let i=n,a=!1;for(;;){let c=t;try{c=qn(await $t(e),t)}catch(u){s(`${u.message} Starting the installed connector ${t.version}.`)}let{code:l,signal:d}=await DU(o,c.entry,i,t);if(l===To){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&&!d&&!a){let u=await $t(e).catch(()=>null);if(u&&!u.confirmed&&u.active?.version===c.version)try{let f=await Mc(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 ${f.version}.`);continue}catch(f){s(`Automatic rollback failed: ${f.message}`)}}return l??1}}function DU(e,t,n,r){return new Promise((o,s)=>{let i=e(process.execPath,[...process.execArgv,t,...n],{stdio:"inherit",env:{...process.env,[jr]:"1",[Cc]:r.entry,[Ic]:r.version}}),a=process.platform==="win32"?[]:["SIGINT","SIGTERM","SIGHUP"],c=d=>i.kill(d);for(let d of a)process.on(d,c);let l=()=>{for(let d of a)process.off(d,c)};i.once("error",d=>{l(),s(d)}),i.once("exit",(d,u)=>{l(),o({code:d,signal:u})})})}var lr="1.52.3",ac="1.52.3",GU=3e5,cc=["queued","running","reporting"],HU=5e3,tp={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."},np={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."},BU=6e4,WU=3e4,rp={id:"tool_inventory",title:"Tool inventory refresh",remedy:"Run `engineeros-connector tools list` in this workspace for the full registry state."},op={id:"runner_setup_reporting",title:"Goal runner setup reporting",remedy:"Restore the connection to EngineerOS; saved setup reports will retry automatically."},{command:Pe,positional:ot,flags:ue}=E0(process.argv.slice(2));Pe==="version"&&(console.log(lr),process.exit(0));var Gn=null,lt=!1,yn=null,CS=!1,IS=null,hp=null,it=null,Cs=null,up,_S,vS,xs,yo,OS=qa({getWorkspace:()=>A.workspace,onRecorded:e=>jb(A,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}`))}),qU=fS({getWorkspace:()=>A.workspace,huntSignIns:OS}),$s=A0();Pe==="results"&&(ot[0]!=="upload"&&(console.log(Fa),process.exit(ue.help||!ot[0]?0:2)),process.exit(await mb(ue)));(Pe==="connect"||Pe==="disconnect"||Pe==="integrations")&&process.exit(await wS(Pe,ot,ue,{fetchImpl:dS}));if(Pe==="runner"){let e=rt.resolve(ue.workspace||process.cwd()),t=ot[0]||"status";try{if(t==="serve"||t==="worker"){let n=t==="worker"?rt.join(rt.dirname(Oe(e,ue["run-id"])),"worker.log"):rt.join(e,".engineeros","runner","service.log");UU(rt.dirname(n),{recursive:!0});let r=(...s)=>as(n,`${zU(...s)}
986
986
  `),o=(s,i,a)=>(as(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(ue["keep-awake"]!==void 0){if(!["on","off"].includes(ue["keep-awake"]))throw new Error("Use --keep-awake on or off.");let n=await Ke(e);if(!n)throw new Error("Pair this workspace before changing its runner keep-awake setting.");await xn({...n,runner_keep_awake:ue["keep-awake"]==="on"})}console.log(`Installed Goal runner service: ${await Aa(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 Wv(e),console.log("Goal runner service removed. Saved and queued jobs are kept.")):t==="start"?await co(e,{enable:!0}):t==="status"?console.log(JSON.stringify(await rr(e),null,2)):t==="serve"?await Jv(e):t==="worker"?await Kv(e,ue["run-id"]):Ce("Usage: engineeros-connector runner [install|start|status|uninstall] --workspace PATH [--keep-awake on|off]");process.exit(0)}catch(n){Ce(uu(n,e).message)}}ue["assessment-workers"]!==void 0&&Ce("--assessment-workers is no longer supported. Select 3 to 8 parallel agents in EngineerOS before starting the assessment.");if(Pe==="tools"){let e=rt.resolve(ue.workspace||process.cwd());try{let t=ot[0]||"list";if(["sign-in","auth-status","sign-out"].includes(t)){let r=ot[1];r||Ce(`Usage: engineeros-connector tools ${t} PROVIDER_ID --workspace PATH`);let o=await id(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 Ko(e,{type:"tools.update",command_id:"00000000-0000-4000-8000-000000000002",action:t,provider_id:ot[1],confirmed:!0},void 0,{confirmLocal:async()=>!0}):t!=="list"&&await od(e,t,ot[1]);let n=await It(e);console.log(JSON.stringify(n,null,2)),process.exitCode=n.error?1:0}catch(t){Ce(t.message)}process.exit(process.exitCode||0)}if(Pe==="agents"){let e;try{e=await Sd()}catch(n){Ce(n instanceof Error?n.message:String(n))}let t=await Promise.all(e.map(async n=>{try{return await Yo(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(Pe==="agent"){let e=ot[0],t=ot[1]||"check";(!e||!["check","install"].includes(t))&&Ce("Usage: engineeros-connector agent AGENT_ID [check|install]");try{let n=t==="install"?await Ki(e):await Yo(e);console.log(`${n.name} is ready (${n.version}, ${n.distribution}).`)}catch(n){Ce(n instanceof Error?n.message:String(n))}process.exit(0)}if(Pe==="mcp"){let e=ue.workspace||process.env.ENGINEEROS_MCP_WORKSPACE||process.cwd(),t=ue["run-id"]||ot[0]||process.env.ENGINEEROS_MCP_RUN_ID||null,n=await Ke(e);await X0({config:n,runId:t,version:lr,input:process.stdin,output:process.stdout}),process.exit(0)}if(Pe==="context-mcp"){let e=ue["config-workspace"]||ue.workspace||process.env.ENGINEEROS_MCP_WORKSPACE||process.cwd(),t=await Ke(e);t||Ce("This workspace is not paired with EngineerOS."),await sb({config:t,workspace:ue.workspace||process.env.ENGINEEROS_CONTEXT_WORKSPACE||t.workspace,version:lr,input:process.stdin,output:process.stdout}),process.exit(0)}if(Pe==="status"){let e=await Ke(ue.workspace||process.cwd());console.log(e?`Paired as ${e.name} (${e.connector_id}) for ${e.workspace}`:"Not paired"),process.exit(e?0:1)}if(Pe==="doctor"){let e=rt.resolve(ue.workspace||process.cwd()),t=await Ke(e),n=await H0(e),r=await Eo(t||{workspace:e},e,Eu(n));console.log(vu(r)),process.exit(r.status==="failed"?1:0)}if(Pe==="update"){let e=ot[0]||"status";try{let t=jc(process.argv[1],ac),n=await Pc(Wn(),t,{action:e,policy:ot[1]??null});console.log(Co(Lc(n,t,{supervised:!0})))}catch(t){Ce(`${t.message}
987
987
  Usage: engineeros-connector update [status|check|apply|rollback|policy manual|approve|auto-patch|auto-minor]`)}process.exit(0)}var _o=Pe==="hunt-host";if(_o)try{ue.workspace=Zv(ot,ue)}catch(e){Ce(e.message)}if((Pe==="start"||Pe==="pair"||_o)&&process.env[jr]!=="1"&&He(ac))try{process.exit(await yS({root:Wn(),bundled:{version:ac,entry:rt.resolve(process.argv[1])},argv:process.argv.slice(2),workspace:rt.resolve(ue.workspace||process.cwd())}))}catch(e){Ce(`The connector process could not be started: ${e.message}`)}if(_o){try{await Qv(ue.workspace,ot[0]?ue.agent:null)}catch(e){Ce(e.message)}Pe=ot[0]?"pair":"start"}var A,So,As;if(Pe==="pair"){let e=ot[0];e||Ce("Usage: engineeros-connector pair CODE --url URL [--agent AGENT_ID | --agent-protocol forge] [--name NAME] [--workspace PATH] [--skip-git-repo-check]");let t=ue.url;t||Ce("Pairing requires --url with the EngineerOS backend address."),ue.agent&&ue["agent-command"]&&Ce("Use either --agent or --agent-command, not both.");let n=ue["agent-protocol"]||(ue["agent-command"]?"acp":"codex");["codex","acp","forge"].includes(n)||Ce(`Unknown --agent-protocol '${n}'. Use codex, acp, or forge.`),n==="forge"&&(ue.agent||ue["agent-command"])&&Ce("Forge runs its own agents. Drop --agent and --agent-command when pairing with --agent-protocol forge.");let r={};try{ue.agent&&(await Yo(ue.agent),r=await dy(ue.agent))}catch(o){Ce(o instanceof Error?o.message:String(o))}A={server_url:Dc(t),workspace:rt.resolve(ue.workspace||process.cwd()),onboard:ue.onboard===!0,onboarding_pending:ue.onboard===!0,hunt_host:_o,agent_protocol:n,agent_command:ue["agent-command"]||null,agent_args:fz(ue["agent-args"]),agent_name:ue["agent-name"]||null,...r,skip_git_repo_check:_o||ue["skip-git-repo-check"]===!0,name:ue.name||`${FU.hostname()} - ${rt.basename(rt.resolve(ue.workspace||process.cwd()))}`},As=await Ke(A.workspace),So={type:"pair",pairing_code:e,name:A.name,capabilities:{},...of(As,A.server_url)}}else Pe==="start"?(A=await Ke(ue.workspace||process.cwd()),A||Ce("This connector is not paired. Create a pairing command in EngineerOS first."),_o&&!A.hunt_host&&Ce("This folder is not a paired hunt host. Generate a new hunt-host command in EngineerOS."),So={type:"authenticate",connector_id:A.connector_id,token:A.token}):Ce("Use `engineeros-connector pair`, `start`, `status`, `doctor`, `agents`, `agent`, `tools`, or `mcp`.");var jS=Yv(A,{reportError:e=>console.error(e)}),cr=0,lc=!1,Ts=null,st=new Map,sp=0,ip=new Set,vo=[],tt=new Map,nt,pp,oc,_n=null,sc=!1,NS=0,ap=null,cp=[],ic,MS,Es=1e3,Fn=!1,Ht,go=!1,dc=!1,fp=0;function tc(e){return fp+=1,e.finally(()=>{fp-=1})}var wo,Cr=0;function Rs({exitCode:e=0}={}){if(Cr=Math.max(Cr,e),wo)return wo;let t=setTimeout(()=>{console.error("Connector shutdown exceeded 15 seconds; inspect the retained agent logs before restarting."),process.exit(1)},15e3);return t.unref(),wo=VU().finally(()=>clearTimeout(t)),wo}async function VU(){if(lt=!0,Cs?.stop(),Gn?.stop(),hp?.stop(),IS?.stop(),clearInterval(up),it?.stop(),MS?.(),clearTimeout(ic),clearInterval(pp),clearInterval(oc),await Promise.all([...[...st.values()].map(e=>ht(e.child))]),await Promise.all([...tt.values()].map(wp)),await xs?.cancelAll(),await yo?.abortAll(),await Vi(),await Ep().catch(e=>{Cr=Math.max(Cr,1),console.error(`${e.message}. Stop those processes before restarting the connector.`)}),nt?.close(),Cr&&Cr!==To){let e;await Promise.race([(async()=>{await Gn?.drain(),await Eo(A,A.workspace)})().catch(()=>{}),new Promise(t=>{e=setTimeout(t,1e4)})]).finally(()=>clearTimeout(e))}process.exit(Cr)}for(let e of["SIGINT","SIGTERM","SIGHUP"])process.on(e,()=>{Rs()});var bS=!1;for(let e of["uncaughtException","unhandledRejection"])process.on(e,async t=>{bS||(bS=!0,console.error(`Connector stopping after an unhandled failure: ${t instanceof Error?t.stack||t.message:String(t)}`),await Rs({exitCode:1}))});it=N0();process.on("exit",()=>{Cs?.stop(),it.stop()});it.banner(`EngineerOS connector ${lr}`,[A.workspace,A.server_url]);Gn=$0({actions:{refresh_tool_inventory:async()=>{ye.tool_inventory=await It(A.workspace),Et()},restart_goal_runner:()=>co(A.workspace)},onNotify:()=>Eo(A,A.workspace),explain:async e=>{if(!await mp())return null;let{reading:t}=await Ev(A,e);return t},onUpdate:e=>G0(A.workspace,e)});IS=W0({render:(e,t)=>it.write(e,t),onRecord:e=>Gn.observe(e)});hp=q0({workspace:A.workspace,onRecord:e=>{Gn.observe(e),it.line(e.channel,e.level,e.message)}});Gn.start();A.hunt_host||hp.start();it.live&&!A.hunt_host&&(up=setInterval(()=>{XU().catch(()=>{})},HU),up.unref?.());var lp=new Set;async function XU(){if(A.hunt_host)return;_S??=cu(A.workspace);let{jobs:e}=await _S(),t=new Set,n=e.filter(r=>r.status!=="queued"&&cc.includes(r.status)).length;for(let r of e){if(!cc.includes(r.status))continue;t.add(r.runId),lp.add(r.runId);let o=r.status==="queued"&&n>0?`queued behind running Goals (running: ${n})`:r.activity?.phase||r.status;it.status(`goal:${r.runId}`,o,JU(r),{agent:r.status!=="queued",link:Ts&&`${Ts}/goals`}),it.step(`goal:${r.runId}`,r.activity?.message)}for(let r of lp)t.has(r)||(lp.delete(r),it.clearStatus(`goal:${r}`))}function JU(e){let t=e.startedAt??Date.parse(e.updatedAt??"");return Number.isFinite(t)?t:Date.now()}async function mp({ignoreBugHunt:e=!1}={}){if(lt||st.size>0||tt.size>0||cr>0||(xs?.active??0)>0||!e&&(yo?.active??0)>0)return!1;try{let{jobs:t}=await rr(A.workspace);return!lt&&!t.some(n=>cc.includes(n.status))}catch{return!1}}try{let e=A.hunt_host?{}:await Ir(A.workspace);e.committed&&(A.onboarding_pending=!0,A.connector_id&&await xn(A),console.log(`Local project repository ready at ${e.revision.slice(0,8)}. Source and design artifacts are committed locally.`))}catch(e){await FS(e)}var $e;try{$e=await ga(A,A.workspace)}catch(e){await FS(e)}console.log(`Using ${$e.name} through ${$e.protocol} (${$e.version}).`);var ye=Su(A,$e,await It(A.workspace)),zn=nf({running:jc(process.argv[1],ac),supervised:process.env[jr]==="1",isIdle:async()=>!lt&&st.size===0&&vo.length===0&&tt.size===0&&cr===0&&fp===0&&!go&&!dc&&!sc,restart:()=>Rs({exitCode:To}),onChange:e=>{ye.runtime_update=e,nt?.readyState===WebSocket.OPEN&&Et()}});try{await zn.refresh()}catch(e){console.error(`Connector updates are unavailable: ${e.message}`)}A={...A,execution_profiles:$e.executionProfiles??null};Pe==="pair"&&As?.connector_id||await xn(A);ye.agent_session={...ye.agent_session,status:"checking",message:`Checking that ${$e.name} can answer.`};ye.bug_hunt_browser=!1;So.capabilities=ye;console.log(jn(A.worker_limit)===null?`Workers: automatic, ${no()} ${$e.name} workers side by side for this machine's CPU and memory; change it with /workers.`:`Workers: ${jn(A.worker_limit)} ${$e.name} workers side by side, set with /workers.`);var bo=e=>Nn(A,e),SS=Sa(bo,{signature:Iv});async function KU(){let e=await rr(A.workspace).catch(()=>({service:null,jobs:[]}));return{version:lr,now:Date.now(),workspace:A.workspace,config_path:dn(A.workspace),config:A,agent:$e,automatic_worker_limit:no(),worker_limit:jn(A.worker_limit),connection:{state:YU(),server_url:A.server_url,last_error:Ht||null},work:{assessments:[...st.values()].map(t=>({stage:t.stage,message:t.lastMessage,started_at:t.startedAt})),prompts:[...tt.values()].map(t=>({id:String(t.runId).slice(0,8),purpose:t.purpose,started_at:t.startedAt})),integrations:cr},runner:e,runtime_update:zn.report(),health:Gn?.health()??null,activity:$s.snapshot()}}function YU(){return lt||Fn?"stopped":nt?.readyState===WebSocket.OPEN?"connected":"connecting"}var ZU={async cancelPrompt(e){let t=[...tt.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=>LS(e),setVerbose(e){return e===lc?`Detailed agent activity is already ${e?"on":"off"}.`:(gp(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"?(zn.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 zn.command(e),Co(await zn.refresh()))}};Cs=D0({ui:it,snapshot:KU,actions:ZU});Cs&&console.log(L0());await PS();var ES=new Set;async function PS(){if(lt||Fn)return;console.log(`Connecting ${A.name} to ${A.server_url}`),Fn=!1,Ht=void 0;let e=new WebSocket(A.server_url);nt=e;let t=eg(e,A.server_url,{onTimeout:r=>{nt===e&&(Ht=r,console.error(r),dp())}});MS=t,e.addEventListener("open",()=>{if(nt!==e){e.close();return}try{if(Xm(nt,e,So))return;throw new Error("The WebSocket was not open when authentication started.")}catch(r){Ht=pt(r),console.error(`Could not authenticate the WebSocket connection: ${Ht}`);try{e.close()}catch{}dp()}}),e.addEventListener("message",r=>{if(nt!==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: ${pt(s)}`)})});let n=async r=>{if(r.type==="authenticated"&&r.connector?.capabilities?.http_updates!==!0){lt=!0,Fn=!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=As?.connector_id===r.connector.id;if(A=sf(A,As,r.connector.id,r.token),await xn(A),r.connector?.capabilities?.http_updates!==!0){lt=!0,Fn=!0,console.error("Pairing saved. Update the EngineerOS backend for HTTP updates, then start this connector again."),e.close();return}So={type:"authenticate",connector_id:A.connector_id,token:A.token,capabilities:ye},console.log(s?`Reconnected existing workspace connector ${A.connector_id}; assessment history is preserved.`:`Paired. Connector ${A.connector_id} is online.`),xS(r);return}if(r.type==="authenticated"){t(),console.log("Connected and waiting for EngineerOS runs."),xS(r);return}if(r.type==="provider.login"||r.type==="provider.logout"){dc||ez(r);return}if(r.type==="workspace.refresh"){uc();return}if(r.type==="workers.update"){try{console.log(`EngineerOS changed the workers. ${await LS(r.worker_limit??"auto")}`)}catch(s){console.error(`Workers were not changed: ${s.message}`)}return}if(r.type==="logging.update"){gp(r.activity_log_enabled===!0);return}if(r.type==="tools.update"){let s=r.provider_id==="playwright"&&["setup","upgrade","rollback"].includes(r.action);s&&(Un=!1,ye.bug_hunt_browser=!1,Et());try{ye.tool_inventory=await Ko(A.workspace,r,void 0,{confirmLocal:i=>Cs?.confirm(i)??!1}),s&&(Un=!0),ye.bug_hunt_browser=Tr(ye.tool_inventory)&&Un,e.send(JSON.stringify({type:"tools.updated",command_id:r.command_id,inventory:ye.tool_inventory})),Et(),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 id(A.workspace,r,{onStatus:async()=>{ye.tool_inventory=await It(A.workspace),Et()}});ye.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:ye.tool_inventory})),Et(),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"){zr(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===pS){tc(qU(r).then(s=>(s.error&&console.error(`${r.provider} ${r.operation} failed: ${s.error}`),hS(A,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}`;Kd(vo,st.get(s),r)==="deferred"&&console.log(`Assessment stage ${r.stage} is already running here; EngineerOS will be answered when it finishes.`),Is();return}if(r.type==="prompt.execute"){let s=tt.get(r.prompt_id);s?BS(r)>s.executionRevision&&await lz(s,r):HS(r);return}if(r.type==="prompt.cancel"){let s=tt.get(r.prompt_id);s&&await wp(s);return}if(r.type==="agent.warm"){nz(r);return}if(r.type==="run.available"){if(A.hunt_host){console.error("A hunt host cannot run Goals. Use Connect your code to pair a repository connector.");return}try{let s=await jS.dispatch(r);s.blocked?console.error(s.message):console.log(`Goal ${r.run_id} queued for the independent runner. Logs: ${rt.join(A.workspace,".engineeros","runs",r.run_id,"activity.log")}`)}catch(s){console.error(`Goal dispatch failed: ${pt(s)}`)}return}if(r.type==="goal.cleanup"){try{await Xv(A.workspace),await co(A.workspace)}catch(s){console.error(`Goal cleanup is pending: ${s.message}`)}return}if(r.type==="run.accepted"){pz(r);return}if(r.type==="run.cancelled"){await au(A.workspace,r.run_id);return}if(r.type===_g){xs??=Rg({getConfig:()=>A,onTestsCommitted:()=>uc()}),tc(xs.handle(r));return}if(r.type===vg){await xs?.cancel(r);return}if(r.type===Pb){yo??=Fb({getConfig:()=>A,isIdle:()=>mp({ignoreBugHunt:!0}),recordedSignIns:OS}),tc(yo.handle(r));return}if(r.type===Lb){yo?.stop(r);return}if(r.type===gb){vS??=wb({getConfig:()=>A}),tc(vS.handle(r));return}if(r.type==="connector.update"){QU(e,r);return}if(r.type==="connector.disconnect"){console.log(r.message),await Rs();return}if(r.type==="connector.revoked"){lt=!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||(go=!1);return}if(r.type==="connection.error"){Fn=!0,console.error(`EngineerOS: ${r.message}`);return}let o=String(r.type??"(missing)").replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,120);ES.has(o)||(ES.add(o),console.warn(`Unknown EngineerOS message type ${o}; connector ${lr}. Update the connector and backend to compatible versions.`))};e.addEventListener("close",r=>{if(t(),nt!==e||wo)return;let o=Jm(r);if(!o.retry||Fn||lt){console.error(o.message),o.retry&&Fn&&console.error("Connection rejected. Create a new pairing command in EngineerOS if this connector was revoked."),Rs();return}Ht=Ht?`${o.message} ${Ht}`:o.message,dp()}),e.addEventListener("error",r=>{nt===e&&(Ht=Vm(r),console.error(`WebSocket connection to ${A.server_url} failed: ${Ht}`))})}async function QU(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=zn.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 zn.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 ez(e){let t=e.request_id,n=e.type==="provider.logout"?"logout":"login";dc=!0,console.log(`Starting interactive ${$e.name} provider ${n}.`);try{await(n==="logout"?Qm:Zm)($e,A.workspace),$e=await ga(A,A.workspace),ye=Su(A,$e,ye.tool_inventory),So.capabilities=ye,nt.readyState===WebSocket.OPEN&&(nt.send(JSON.stringify({type:`provider.${n}.completed`,request_id:t,session:ye.agent_session})),nt.close(1e3,`Provider ${n} completed`)),console.log(`${$e.name} provider ${n} completed.`)}catch(r){let o=pt(r).slice(0,500);nt.readyState===WebSocket.OPEN&&nt.send(JSON.stringify({type:`provider.${n}.failed`,request_id:t,message:o})),console.error(`Provider ${n} failed: ${o}`)}finally{dc=!1}}function dp(){if(lt||Fn||ic)return;let e=Ht?` Last error: ${Ht}`:"";console.error(`Connection unavailable.${e} Retrying in ${Math.round(Es/1e3)}s.`),ic=setTimeout(()=>{ic=void 0,PS()},Es),Es=Math.min(3e4,Es*2)}async function uc(){if(!A.hunt_host&&!(go||nt.readyState!==WebSocket.OPEN)){go=!0,console.log("Inspecting the workspace without executing its code.");try{let e=await xv(A.workspace),t=await fetch(Nr(A.server_url,A.connector_id),{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${A.token}`},body:JSON.stringify(e)});if(!t.ok)throw new Error(await _i(t,"the workspace"));let n=await t.json();A={...A,onboarding_pending:!1},await xn(A),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 ${n.workspace_kind}. Start the baseline assessment in EngineerOS to continue.`);try{let r=await ri(A.workspace,A.connector_id);console.log(`Built the local context index: ${r.total_files.toLocaleString()} file(s) ready for assignment context.`)}catch(r){console.error(`Local context index build failed: ${r.message}`)}go=!1}catch(e){go=!1,console.error(`Workspace assessment failed: ${pt(e)}`)}}}var tz=6e4,kS=0;async function nz(e){if(A.hunt_host)return;let t=typeof e.session_key=="string"?e.session_key.trim():"",n=t?A.sessions?.[t]:void 0,r=[];Date.now()-kS>tz&&(kS=Date.now(),r.push(ri(A.workspace,A.connector_id).catch(o=>console.error(`Context index refresh ahead of a conversation failed: ${o.message}`)))),A.agent_protocol==="acp"&&r.push(ny(A.workspace,A,{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(`${$e?.name||"The agent"} could not be started ahead of the conversation: ${o.message}`))),await Promise.all(r)}function Et(){let e=fv(st);SS.update({type:"assessment.workers",assessment_workers:e,tool_inventory:ye.tool_inventory,runtime_update:ye.runtime_update,agent_session:ye.agent_session,bug_hunt_browser:ye.bug_hunt_browser,...wa(A.worker_limit)}),SS.flush().catch(t=>console.error(`Assessment status: ${t.message}`))}async function LS(e){let t=jn(e);return t===jn(A.worker_limit)?t===null?"Workers are already automatic.":`Workers are already set to ${t}.`:(A={...A,worker_limit:t},await xn(A),Is(),Et(),t===null?`Workers are automatic again: up to ${no()} side by side for this machine's CPU and memory, for assessment stages, generation, test design and Goals (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: assessment stages, generation, test design and Goals. A Goal that uses your working folder still runs alone. Running work finishes; waiting work starts as workers free up.`)}function gp(e){if(e!==lc){if(lc=e,!e)for(let t of st.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."),Et()}}function DS(e,t){it.step(e,t)&&lc&&console.log(`[${e}] ${t}`)}function rz(){clearInterval(oc);let e=!1,t=()=>{e||st.size>0||tt.size>0||(e=!0,Eo(A,A.workspace).finally(()=>{e=!1}))};t(),oc=setInterval(t,GU),oc.unref?.()}async function Eo(e,t,n=Gn?.healthChecks()??[]){let r=await b0({config:e,workspace:t,version:lr,insights:n,agentSession:yn,probes:{inspectAgent:(o,s)=>lt?$e:ga(o,s),inspectTools:o=>lt?ye.tool_inventory:It(o),runnerStatus:rr}});try{CS=(await S0(e,r,Nn))?.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 FS(e){if(lt)return wo;let t=e instanceof Error?e.message:String(e),n=await Eo(A,A.workspace).catch(()=>null);n&&console.error(vu(n)),Ce(t)}function xS(e){gp(e.connector?.activity_log_enabled===!0),Ts=e.project_url??null,Es=1e3,sz(),zS(),zn.confirm().catch(t=>console.error(`Connector update state: ${t.message}`)),iz(),A.onboarding_pending&&uc()}var ks=null,Un=!1,US=0,oz=Date.now();async function sz(){return ks||(ks=(async()=>{try{console.log("Preparing Bug Hunter: setting up Playwright and checking this machine's browser."),await e0(A.workspace),Un=!0,ye.tool_inventory=await It(A.workspace),ye.bug_hunt_browser=Tr(ye.tool_inventory)&&Un,console.log("Bug Hunter browser is ready.")}catch(e){console.error(`Hunt browser setup failed: ${e.message}`),ye.bug_hunt_browser=!1}Et()})(),ks)}async function zS(){if(yn?.state!=="checking"){US=Date.now(),ye.agent_session={...ye.agent_session,status:"checking",message:`Checking that ${$e.name} can answer.`},Et(),yn={state:"checking",detail:`Asking ${$e.name} one question to confirm its session.`},console.log(`Checking that ${$e.name} can answer before accepting work.`);try{await yv(A,$e.name),yn={state:"ready",detail:`${$e.name} answered; its session is usable.`},ye.agent_session={...ye.agent_session,status:"authenticated",message:yn.detail},console.log(yn.detail)}catch(e){yn={state:"failed",detail:e instanceof Error?e.message:String(e),remedy:A.hunt_host?n0(A.agent_id||A.agent_protocol):Zr(A.agent_id||A.agent_protocol)},ye.agent_session={...ye.agent_session,status:"logged_out",message:yn.remedy},console.error(`${yn.detail}
988
988
  ${yn.remedy}`)}Et(),await Eo(A,A.workspace).catch(()=>null)}}function iz(){clearInterval(pp);let e=!1,t=0,n=0,r=!1,o=()=>{zn.tick(),A.hunt_host&&ks&&Date.now()-US>=t0(oz)&&tt.size===0&&st.size===0&&!(yo?.active>0)&&zS(),!A.hunt_host&&!r&&ps(op.id)&&(r=!0,jS.flush().then(()=>rc(op)).catch(s=>nc(op,s)).finally(()=>{r=!1})),st.size>0&&Et(),!A.hunt_host&&!_n&&Date.now()-t>=BU&&ps(tp.id)&&(t=Date.now(),GS().then(()=>rc(tp)).catch(s=>nc(tp,s))),!A.hunt_host&&CS&&!sc&&ps(np.id)&&Date.now()-NS>=Wg&&(sc=!0,az().then(()=>rc(np)).catch(s=>nc(np,s)).finally(()=>{sc=!1})),!e&&Date.now()-n>=WU&&ps(rp.id)&&(e=!0,n=Date.now(),It(A.workspace).then(async s=>{if(ye.tool_inventory=s,!Un&&Tr(s))try{await(await dr(await sr(A.workspace))).close(),Un=!0}catch{Un=!1}ye.bug_hunt_browser=Tr(s)&&Un,Et(),rc(rp)}).catch(s=>nc(rp,s)).finally(()=>{e=!1}))};o(),pp=setInterval(o,1e4),rz()}function nc(e,t){let n=w0(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 rc(e){y0(e.id)&&console.log(`${e.title} recovered.`)}async function az(){if(A.hunt_host||!await mp())return;NS=Date.now();let{jobs:e}=await rr(A.workspace).catch(()=>({jobs:[]})),t=await qg(A.workspace,{jobs:e});if(!Vg(t))return;let n=`${t.fingerprint}:${cp.join(",")}`,r=ap?.key===n,o=r?ap.candidates:await kv(A,t,cp);ap={key:n,candidates:o};let s=await bo(Kg(t,o,{version:lr}));Array.isArray(s?.refused)&&(cp=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 ar=null,$S=null;async function GS(){if(!A.hunt_host){if(_n)return _n;_n=(async()=>{let e=await Lg(A,{knownRevision:ar?.revision??null});if(e.unchanged||(ar=e),$S===ar.revision)return ar;let{jobs:t}=await rr(A.workspace);return!t.some(r=>cc.includes(r.status))&&cr===0&&st.size===0&&(await ji(A.workspace,ar),$S=ar.revision),ar})();try{return await _n}finally{_n=null,Is()}}}function AS(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)),tt.get(e)?.events.push(n)}var TS=null;function Is(){let e=nt.readyState===WebSocket.OPEN,t=st.values().next().value,n=jn(A.worker_limit)??Math.min(no(),Zd(t?.workerLimit??vo[0]?.worker_limit)),r=e&&!_n&&cr===0?ov(vo,st.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:Zd(s.worker_limit),lastActivityAt:Date.now(),eventCount:0,lastDetail:null};st.set(i,a),uz(s,a)}r.length>0&&Et();let o=sv({queued:vo,running:st.size,workerLimit:n,connected:e,designSync:!!_n,integrations:cr});o&&o!==TS&&console.log(o),TS=o}function pc(e){let t=Qd(e);return t?`${$e.name} on ${t}`:$e.name}async function HS(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:Nv(bo),executionRevision:BS(e),sessionKey:ya(e),sessionId:null,replacement:null};tt.set(t,s);let i,a=g=>{let v=g?JSON.stringify(g):null;!v||v===i||tt.get(t)!==s||(i=v,AS(t,g))},c=`${r} \xB7 ${pc(e)}`,l=wv(e,$e.name);AS(t,{kind:"status",message:l});let d=Number(e.answer_within_seconds),u=d>0?o+d*1e3:void 0;console.log([`[${n}] ${l} for ${r}.`,`${$e.name} can reason for several minutes without reporting a step.`,...u?[Au(u,o)]:[]].join(" ")),it.status(n,c,o,{link:Ts,answerBy:u});let f=g=>{let v=tv(g),y=kr(g);tt.get(t)===s&&DS(n,y??v?.message);let k=g.type==="forge.output"?null:y;a(v??(k?{kind:"status",message:k}:null))},p="failed",h=[r];try{_a(e)||(f({type:"connector.step",message:"Syncing the design context from EngineerOS"}),e={...e,design_context:await Gg(GS,{pinned:!!e.local_design_context,last:ar,onFallback:(k,_)=>f({type:"connector.step",message:`Design context not refreshed (${k.message}); continuing with ${_?"the copy synced earlier":"none"}`})})});let g=await J_(e,A,{onProcess:k=>{tt.get(t)===s&&(s.child=k)},onController:k=>{tt.get(t)===s&&(s.controller=k)},onSession:k=>{s.sessionId=k},onEvent:f},{signal:s.cancellation.signal});if(s.stoppedHere)throw new Error(RS);let v=g.singleTurn?af(A.sessions,g.sessionKey):Fc(A.sessions,g.sessionKey,g.sessionId);if(JSON.stringify(v)!==JSON.stringify(A.sessions||{})&&(A={...A,sessions:v},await xn(A)),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 y=await ba(bo,{type:"prompt.completed",prompt_id:t,execution_revision:s.executionRevision,content:g.content,model:g.model,session_id:g.sessionId,usage:g.usage});y||console.error(`[${n}] ${ru}`),$s.record("prompt","completed",{durationMs:Date.now()-o,usage:g.usage}),p=y?"finished":"undelivered",h=[cz(g.usage),r]}catch(g){let v=s.stoppedHere?RS:pt(g);if($s.record("prompt","failed",{durationMs:Date.now()-o}),s.stoppedHere&&(p="cancelled"),!s.cancelled){try{await ba(bo,{type:"prompt.failed",prompt_id:t,execution_revision:s.executionRevision,message:v})||console.error(`[${n}] ${ru}`)}catch(y){console.error(`[${n}] Prompt failure delivery: ${y.message}`)}console.error(v)}}finally{s.events.stop();let g=s.replacement;g?(p="replaced",h=[`continuing on ${pc(g)}`,r]):s.cancelled&&(p="cancelled"),it.finish(n,p,h),tt.get(t)===s&&tt.delete(t),g&&dz(s,g)}}var RS="Cancelled from the connector terminal by the person running it.";function cz(e){let t=Number(e?.total_tokens)||(Number(e?.input_tokens)||0)+(Number(e?.output_tokens)||0);return t?`${t.toLocaleString()} tokens`:null}async function wp(e){e.cancelled=!0,e.cancellation.abort(),await e.controller?.completed.catch(()=>{})}function BS(e){return Number(e.execution_revision)||1}async function lz(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 ${pc(t)}.`),await wp(e))}function dz(e,t){e.sessionId&&(A={...A,sessions:Fc(A.sessions,e.sessionKey,e.sessionId)},xn(A).catch(n=>console.error(`Could not save the agent session: ${n.message}`))),HS(t)}async function uz(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 ${pc(e)}.`),!ip.has(n)){ip.add(n);try{let m=await Z_(A.workspace);if(!m.exists)console.log("No accepted assessment exists yet; this run establishes the baseline.");else{let S=m.accepted_head_revision?m.current_head_revision?m.current_head_revision!==m.accepted_head_revision?`The workspace is now at commit \`${m.current_head_revision}\`; the accepted assessment is from \`${m.accepted_head_revision}\`.`:"The accepted assessment is already at the current commit.":`The accepted assessment is from \`${m.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 ${m.stages.length||"no"} section(s). ${S}`)}}catch(m){console.error(`Assessment freshness check failed: ${m.message}`)}}let o=t.startedAt,s=`assessment:${r}`,i=!1,a=!1,c=5,l=!1,d=!1,u=null,f=null,p=null,h=new Set,g=()=>!lt&&st.get(t.key)===t,v=async m=>{try{return await ba(bo,m)||console.warn(`[${s}] ${Ov}`),!0}catch(S){return console.error(`Assessment failure delivery: ${S.message}`),!1}},y=(m,{milestone:S=!0}={})=>{if(!g()||S&&p===m)return;S&&(p=m,h.has(m)||(h.add(m),c=Math.min(90,c+10)),console.log(`[assessment:${r}] ${m}.`));let w=String(m).slice(0,500);t.progressPercent=c,t.lastMessage=w,it.status(s,w,o,{link:Ts})};y(`Starting ${r} assessment stage`);let k=setInterval(()=>{let m=Date.now(),S=m-t.lastActivityAt,w=i&&!a?ev(r,S):null;if(!u&&w){u=w,console.error(`[assessment:${r}] ${u}`),va(t.controller,t.child);return}u||Gn.observe({at:m,level:"info",message:it.status(s,`${t.lastMessage} \xB7 last agent activity ${qe(S)} ago (${t.eventCount.toLocaleString()} events)`,o)})},15e3),_={onSession:async m=>{g()&&(f=String(m),await Fh(A.workspace,n,r,m,{sourceRevision:e.source_revision,targetHeadRevision:e.target_head_revision}))},onController:m=>{g()&&(t.controller=m)},onProcess:m=>{g()&&(t.child=m,i=!0,t.phase!=="correcting"&&(t.phase="running",y("Connected agent process started")),t.lastActivityAt=Date.now())},onEvent:m=>{t.lastActivityAt=Date.now(),t.eventCount+=1;let S=Q_(m);if(S&&y(S),!g())return;let w=kr(m);!w||w===t.lastDetail||(t.lastDetail=w,DS(s,w))}},b=(m,S)=>Xd(m,S,A,_,{draftPath:rt.relative(A.workspace,rt.join(At(A.workspace,n),m.report_file)).split(rt.sep).join("/")});try{let m=sp-Date.now();m>0&&(y(`Waiting ${Math.ceil(m/1e3)}s for the model provider's rate limit to clear`),await new Promise(I=>setTimeout(I,m+Math.floor(Math.random()*3e3)))),e.assessment_mode==="incremental"&&(c=15,y("Calculating changed files and affected behavior"));let S=await Bh(A.workspace,e),w=await dl(A.workspace,n,r,{expectedHeadRevision:e.target_head_revision,expectedSourceRevision:e.source_revision});if(w)b(w,S),y("Recovered completed stage report from connector storage");else{if(f=await Uh(A.workspace,n,r,{expectedHeadRevision:e.target_head_revision,expectedSourceRevision:e.source_revision}),f&&y("Restoring interrupted agent session"),w=await X_(S,A,_,{previousSessionId:f}),u)throw new Error(u);a=!0,await ll(A.workspace,n,S,w)}a=!0,t.phase="delivering",t.progressPercent=95,t.lastMessage=r==="synthesis"?"Delivering completed assessment bundle":"Checkpointing connector-local stage result";let x=I=>fetch(df(A.server_url,A.connector_id,n),{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${A.token}`},body:JSON.stringify(I),signal:AbortSignal.timeout(j_)}),O=await gv(w,{submit:I=>mv(I,x,{isActive:()=>g()&&!lt,onRetry:(L,N)=>{y("Completed result is waiting for EngineerOS",{milestone:!1}),console.warn(`[assessment:${r}] Completed result delivery failed: ${pt(L)} Retrying in ${Math.round(N/1e3)}s without rerunning the agent.`)}}),payloadFor:I=>r==="synthesis"?ul(A.workspace,n,I,{expectedSourceRevision:e.source_revision}):Xh(I),rejectionFor:I=>_i(I,"the assessment"),correct:async(I,L)=>{if(a=!1,t.phase="correcting",t.lastMessage="Correcting a rejected stage result",!I.correctAfterRejection)throw new Error(`${L} The connector could not start the required agent correction.`);return I.correctAfterRejection(L)},onCorrected:async I=>{if(u)throw new Error(u);a=!0,await Gh(A.workspace,n,r);let L=await ll(A.workspace,n,S,I);return b(L,S),t.phase="delivering",t.lastMessage="Delivering corrected stage result",L}});if(u)throw new Error(u);w=O.result;let T=O.response;if(!T.ok)throw new Error(await _i(T,"the assessment"));if(l=!0,$s.record("assessment stage","completed",{durationMs:Date.now()-o,usage:w.usage}),r==="synthesis"){let I=await T.json(),L=await Wh(A.workspace,n,e,w,I.report_markdown);console.log(`Workspace assessment ${n} was accepted by EngineerOS and saved to ${rt.relative(A.workspace,L)}.`);try{let N=await Ls(A.workspace);N.committed&&console.log(`Assessment committed to Git as ${N.revision.slice(0,8)}.`)}catch(N){console.error(`The assessment is saved locally but could not be committed to Git: ${N.message}`)}}else console.log(`Workspace assessment stage ${r} was checkpointed by EngineerOS.`)}catch(m){let S=u||pt(m),w=lv(e,m),x=pv(m),C=av(m);x&&(await zh(A.workspace,n,r).catch(T=>{console.error(`[assessment:${r}] Could not discard the unusable agent session checkpoint: ${T.message}`)}),f=null);let O=!u&&(f||x)&&(x||iv(m))&&w<C;if(g()&&O){t.phase="starting",t.lastMessage=x?"Agent session became unusable; restarting from saved assessment work":"Agent session interrupted; resuming checkpoint",t.resumeAssignment=dv(e,m);let T=uv(m,w);is(m)&&(sp=Math.max(sp,Date.now()+T)),console.warn(`[assessment:${r}] ${x?"Agent session became unusable":"Agent session interrupted"}: ${S} ${x?"Starting a fresh session from the saved draft":`Resuming session ${f}`} in ${Math.round(T/1e3)}s (${w+1}/${C}).`),await new Promise(I=>setTimeout(I,T))}else g()&&(d=await v({type:"workspace.assessment.failed",assessment_id:n,stage:r,message:S}));O||($s.record("assessment stage","failed",{durationMs:Date.now()-o}),console.error(`[assessment:${r}] ${S}`))}finally{clearInterval(k),it.clearStatus(s),r==="synthesis"&&l&&ip.delete(n),g()&&(st.delete(t.key),hv(vo,t,{accepted:l,failureReported:d})&&console.log(`Resuming interrupted agent session for assessment stage ${r} from its checkpoint.`),Is())}}async function pz(e){let t=String(e.run_id||"");cr+=1;try{_n&&await _n;let n=await U_(A.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 uc();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: ${pt(n)}`)}finally{cr-=1,Is()}}function fz(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{Ce('--agent-args must be a JSON array, for example: --agent-args "[\\"acp\\"]"')}}function Ce(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.52.2",
3
+ "version": "1.52.3",
4
4
  "description": "Connect a local coding agent to EngineerOS, using ACP when supported.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",