@engineeros/connector 1.59.23 → 1.59.24
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.
|
@@ -965,7 +965,7 @@ ${r}`);if(!s&&c&&i.some(f=>QV.test(f)))return"consent";if(a&&i.some(f=>mO.test(f
|
|
|
965
965
|
`)[0])}`)}let xe=await pe.text().catch(()=>"");mt();let Ve=null;try{Ve=JSON.parse(xe)}catch{Ve=null}return D.response={status:pe.status(),text:xe,json:Ve,ms:c()-ge},{method:Ee,url:W}}let gu=async M=>{let Q=[...new Set([...String(M??"").matchAll(DX)].map(H=>H[1]))],ee=String(M??"");for(let H of Q){let Ee=f[H];if(Ee===void 0||Ee==="")throw new Oe("blocked",`Set ${H} on the hunt host (\`engineeros-connector secret set ${H} --project ${N??"<project id>"}\`).`);let W;try{W=await Yp({value:String(Ee),now:c,sleep:on})}catch{throw new Oe("blocked",`${H} is not a valid authenticator secret.`)}ee=ee.replaceAll(`{totp:${H}}`,W)}return ee};async function xo(M,Q=Ne,{signingIn:ee=!1}={}){if(mt(),D.blockedRequest)throw new Oe("blocked",D.blockedRequest);let H={action:M.action,target:Ts(await gu(M.target),Q),data:Ts(await gu(M.data),Q),check:Ts(M.check,Q)};if(mt(),H.action==="fill"&&!ee&&MR(H.data).blocked)throw new Oe("blocked",Ry);if(G&&(H.action==="request"&&!/^(GET|HEAD)\s+/i.test(H.target)||["use account","run","open app"].includes(H.action)||H.action==="press"&&/enter/i.test(H.data)))throw new Oe("blocked","Public pages only permits signed-out browsing and GET or HEAD request steps, without submitting.");if(v){if(!["open","request","wait for"].includes(H.action)||H.action==="request"&&!/^GET\s+/.test(H.target)||H.data)throw new Oe("blocked","This action is not production-safe.");await on(1e3)}if(!ee){let W=hr(H,_e);if(W)throw new Oe("blocked",`Refused by the rule of engagement "${W}".`)}let Ee=H.check?go(H.check):[];switch(H.action){case"open app":{if(w.app_surface!=="electron")throw new Oe("blocked","open app requires an Electron or WebDriver hunter.");if(process.env.ENGINEEROS_HUNT_HOST!=="dedicated")throw new Oe("blocked","Electron requires ENGINEEROS_HUNT_HOST=dedicated on a VM or spare machine.");if(Me)throw new Oe("needs_repair","Open the app once per case.");Me=await y({executablePath:w.app_path,args:w.app_arguments||[],cwd:l}),he?.aborted&&(await ns(),mt()),await pt();break}case"use account":to(await Li(H.target.trim()));break;case"open":{await pt();let W=We(H.target.trim(),Z),oe=pe=>new Oe("blocked",`${D.account.role}'s recorded sign-in has expired or was signed out: opening ${W} led to ${pe}. Record it again in Bug Hunter Setup.`),le;try{le=await D.page.goto(W,{waitUntil:"domcontentloaded",timeout:J.navigation})}catch(pe){let xe=String(pe.message).split(`
|
|
966
966
|
`)[0];throw D.account?.storage_state&&/ERR_BLOCKED_BY_CLIENT/.test(xe)?oe("another site"):new Oe("blocked",`Opening ${W} failed: ${It(xe)}`)}if(await Ft(),D.account?.storage_state&&bO(W,D.page.url(),ne))throw oe(It(D.page.url(),200));await kn({requested:W,reopen:async()=>{le=await D.page.goto(W,{waitUntil:"domcontentloaded",timeout:J.navigation}),await Ft()}}),await eo();let ge=le?.status?.()??200;if(ge>=500)throw new Oe("failed",`The server answered ${ge} for ${W}.`,`server error ${ge}`);break}case"click":case"hover":case"check":case"uncheck":case"fill":case"select":{await pt();let W=await ss(fr(H.target));await no(async()=>{H.action==="click"?await W.click({timeout:J.action}):H.action==="hover"?await W.hover({timeout:J.action}):H.action==="check"?await W.check({timeout:J.action}):H.action==="uncheck"?await W.uncheck({timeout:J.action}):H.action==="fill"?await W.fill(H.data,{timeout:J.action}):await W.selectOption({label:H.data},{timeout:J.action})}),H.action==="click"&&await Ft();break}case"press":{if(await pt(),H.target.trim()){let W=await ss(fr(H.target));await no(()=>W.press(H.data.trim(),{timeout:J.action}))}else await no(()=>D.page.keyboard.press(H.data.trim()));await Ft();break}case"go back":await pt(),await no(()=>D.page.goBack({timeout:J.navigation})),await Ft();break;case"reload":await pt(),await no(()=>D.page.reload({timeout:J.navigation})),await Ft(),await eo();break;case"set viewport":{await pt();let[W,oe]=(H.data||H.target).trim().toLowerCase().split("x").map(Number);await D.page.setViewportSize({width:W,height:oe});break}case"wait for":await pt();break;case"request":{await pt();let{method:W,url:oe}=await Fi(H.target,H.data);if(D.response.status>=500&&!Ee.some(le=>["status","status_below","status_in"].includes(le.kind)))throw new Oe("failed",`The server answered ${D.response.status} for ${W} ${oe}.`,`status was ${D.response.status}: ${It(D.response.text,200)}`);break}case"poll":{await pt();let W=c()+(Number(H.data.trim())||SX)*1e3;for(;;){await Fi(H.target,"");let oe=[];for(let le of Ee){let ge=await Eo(le);ge!==null&&oe.push(ge)}if(!oe.length)break;if(c()>=W)throw new Oe("failed",`It never answered as expected: ${oe.join("; ")}.`,oe.join("; "));await on(kX)}return Cn()}case"set device":{if(D.page)throw new Oe("needs_repair","Set the device before opening a page or using an account.");if(w.device_cloud_url){Ce=H.data.trim(),Ze.hasTouch=!0;break}let W=H.data.trim().toLowerCase(),oe=Object.entries(g).find(([pe])=>pe.toLowerCase()===W);if(!oe)throw new Oe("needs_repair",`${H.data.trim()} is not a device the browser knows; use a name such as iPhone 13 or Pixel 7.`);let{defaultBrowserType:le,...ge}=oe[1];Object.assign(Ze,ge);break}case"tap":{if(await pt(),!Ze.hasTouch)throw new Oe("needs_repair","tap needs a touch device; set one with set device first.");let W=await ss(fr(H.target));await no(()=>W.tap({timeout:J.action})),await Ft();break}case"set locale":Ze.locale=H.data.trim();break;case"set time zone":Ze.timezoneId=H.data.trim();break;case"set network":{await pt();let W=H.data.trim().toLowerCase();Ot.setNetwork(W),await D.context.setOffline(W==="offline"),W!=="offline"&&await(await D.context.newCDPSession(D.page)).send("Network.emulateNetworkConditions",W==="slow"?vX:bX);break}case"run":{let W;try{W=rn(H.target.trim())}catch(ge){throw new Oe("needs_repair",`\`${H.target}\` cannot run without a shell: ${ge.message}`)}let oe=Xy.basename(W[0]).replace(/\.(exe|cmd|bat)$/i,"").toLowerCase();if(!X.has(oe))throw new Oe("blocked",`${W[0]} is not a program this hunter may run (${[...X].join(", ")||"none are allowed"}).`);let le=await p(W,{onChild:Xs,cwd:l,timeoutMs:J.command,...u?{env:u}:{},...H.data?{input:H.data}:{}});if(le.notFound)throw new Oe("blocked",`${W[0]} is not installed on the hunt host.`);D.command={exitCode:le.exitCode,output:Pe(String(le.output??""))};break}case"use":{let W=de.get(H.target.trim().toLowerCase());if(W?.builtin==="inbox"){if(!C)throw new Oe("blocked","The test inbox is not set up on this hunt host.");D.command=await ef(C,H.data,Le);break}if(!W)throw new Oe("blocked",`${H.target.trim()} is not an instrument approved for this environment (${[...de.keys()].join(", ")||"none are"}).`);let oe=W.env??[],le=oe.filter(zt=>f[zt]===void 0);if(le.length)throw new Oe("blocked",`Set ${le.join(", ")} on the hunt host to use ${W.name}.`);let ge=Object.fromEntries(oe.map(zt=>[zt,String(f[zt])])),pe={...Q,...ge,data:H.data,since:new Date(Le).toISOString()},xe=(W.command??[]).map(zt=>Ts(String(zt),pe)),Ve=await p(xe,{onChild:Xs,cwd:l,timeoutMs:J.command,env:{...u??process.env,...ge}});if(Ve.notFound)throw new Oe("blocked",`${xe[0]} is not installed on the hunt host.`);let gt=String(Ve.output??"");for(let zt of Object.values(ge))zt&&(gt=gt.replaceAll(zt,"[secret]"));D.command={exitCode:Ve.exitCode,output:Pe(gt)};break}case"wait until":{let W=/^step\s+(\d+)$/i.exec(H.target.trim()),oe=W?ve[Number(W[1])-1]:Le;if(oe===void 0)throw new Oe("needs_repair",`wait until counts from step ${W[1]}, which has not run yet.`);let le=oe+(Vp(H.data)??0);if(le-c()>xX)throw new Oe("needs_repair","wait until may wait at most three hours.");le>c()&&await on(le-c());break}case"crawl":{await pt();let W=Math.min(Number(H.data)||Jy,$X),oe=D.account?.role??null,le=c(),ge=()=>c()<le+Math.min(J.crawl+D.scanMs,3*J.crawl),pe=K?[]:[{url:We(H.target.trim()||"/",Z),from:null,source:"link"}],xe=[];for(let nt of lf(te,_e))try{xe.push({url:We(nt.path,Z),from:null,source:nt.source,seed:!0})}catch{}let Ve=xe.some(nt=>nt.url.includes("/#/")),gt=new Set(z),zt=new Set(z),Js=new Map,is=!1,at=new Map,Be={pages:0,server_errors:[],broken_links:[],routes:[],scripts:[],controls_explored:0,explore_blocked_writes:0,explore_stopped_pages:0,explore_stopped_time:0};D.crawl=Be;let Ks=[],wu=null,Nv=async()=>{let[nt,tn]=await Promise.all([D.page.title(),D.page.evaluate(Os)]);return`${nt??""}\0${tn.elements.join("")}`},tM=async()=>{let nt=`__engineeros_probe_${Math.random().toString(36).slice(2,8)}`;try{return await D.page.goto(We(Ve?`/#/${nt}`:`/${nt}`,Z),{waitUntil:"domcontentloaded",timeout:J.navigation}),await Ft(),await Nv()}catch{return!1}};for(;(pe.length||xe.length)&&Be.pages<W&&ge()&&!fe();){mt();let nt=xe.length&&(is||!pe.length)?xe.shift():pe.shift();is=!is;let tn=Yn(new URL(nt.url));if(tn===null)continue;let Ys=Rl(tn);if(gt.has(tn)||(at.get(Ys)??0)>=TX||(gt.add(tn),at.set(Ys,(at.get(Ys)??0)+1),hr({action:"open",target:tn,data:"",check:""},_e)))continue;nt.seed&&wu===null&&(wu=await tM()),D.path=nt.from,D.pathRole=oe;let ro={path:tn.slice(0,300),source:nt.source,status:null,outcome:"reached",from_path:nt.from?nt.from.slice(0,300):null},Mr=(Mt,Bt=null)=>{nt.from&&(Be.broken_links.push({from:nt.from,url:nt.url,status:Mt}),Ot.note("broken_link",nt.from,{url:nt.url,status:Mt,error:Bt,message:`A link to ${tn} ${Mt?`answers ${Mt}`:"cannot be opened"}`}))},nr;try{nr=await D.page.goto(nt.url,{waitUntil:"domcontentloaded",timeout:J.navigation})}catch(Mt){let Bt=String(Mt.message).split(`
|
|
967
967
|
`)[0];/ERR_(?!BLOCKED_BY_CLIENT)[A-Z_]+/.test(Bt)&&Mr(null,Bt),Be.routes.push({...ro,outcome:"error"});continue}await Ft(),oe&&await kn({requested:nt.url,crawling:!0,reopen:async()=>{nr=await D.page.goto(nt.url,{waitUntil:"domcontentloaded",timeout:J.navigation}),await Ft()}}).catch(()=>!1),await eo();let Ct=nr?.status?.()??200;ro.status=Ct;let cc=Ct===404||Ct===410;if(await(async()=>{if(!oe||cc)return!1;if(Ct===403)return!0;if(Ct>=400)return!1;try{let[Mt,Bt,Qs]=await Promise.all([D.page.title(),D.page.evaluate(Os),D.page.evaluate(()=>document.querySelector("h1")?.innerText??"")]);return MX.test(`${Mt??""} ${Qs??""}`)&&Bt.elements.length<=PX}catch{return!1}})()){Be.routes.push({...ro,outcome:"forbidden"});continue}let zi=Yn(new URL(D.page.url())),as=Ct===401||Ct===403||bO(nt.url,D.page.url(),ne)||zi!==tn&&xi({key:zi,elements:(await D.page.evaluate(Os).catch(()=>({elements:[]}))).elements});if(as){if(Be.routes.push({...ro,outcome:"sign_in"}),nt.seed){let Mt=new URL(D.page.url()),Bt=`${Mt.origin}${Ct===401||Ct===403?`:${Ct}`:Yn(Mt)}`,Qs=(Js.get(Bt)??0)+1;Js.set(Bt,Qs),Qs>=3&&xe.length&&(Be.deferred_seeds=xe.length,xe.length=0)}if(Ct===401||Ct===403)continue}else if(nt.seed){if(cc||wu&&await Nv()===wu){Be.routes.push({...ro,outcome:"not_found"});continue}}else if(cc){Mr(Ct),Be.routes.push({...ro,outcome:"not_found"});continue}else Ct>=400&&Ct!==401&&Ct!==403&&Mr(Ct);let Bi=new URL(D.page.url()),Pr=Yn(Bi);if(as||Be.routes.push({...ro,outcome:Ct>=500?"error":"reached"}),Pr===null||!ne.has(Bi.hostname.toLowerCase())||zt.has(Pr))continue;zt.add(Pr),Be.pages+=1,as&&Pr!==tn&&Be.routes.push({path:Pr.slice(0,300),source:"navigation",status:Ct,outcome:"reached",from_path:null}),Ct>=500&&Be.server_errors.push(Pr),await Cn(),await zn();let Zs=await D.page.evaluate(_O).catch(()=>[]);Ks.push({key:Pr,url:D.page.url(),links:Array.isArray(Zs)?Zs.length:0});for(let Mt of Array.isArray(Zs)?Zs:[]){let Bt;try{Bt=new URL(Mt,Bi)}catch{continue}!/^https?:$/.test(Bt.protocol)||!ne.has(Bt.hostname.toLowerCase())||cf(Yn(Bt),_e)&&(Ky.test(Bt.hash)||(Bt.hash=""),gt.has(Yn(Bt))||pe.push({url:Bt.toString(),from:Pr,source:"link"}))}}if(await Re(),re&&!v&&Ks.length&&!fe()){let nt=c(),tn=()=>fe()||c()-nt>=J.explore,Ys=[...Ks].sort((Mr,nr)=>Mr.links-nr.links),ro=async Mr=>{await D.page.goto(Mr.url,{waitUntil:"domcontentloaded",timeout:J.navigation}).catch(()=>{}),await Ft()};D.exploring=!0;try{for(let Mr=0;Mr<Ys.length&&!Be.explore_stopped_time;Mr+=1){if(mt(),tn()){Be.explore_stopped_time=1;break}let nr=Ys[Mr];try{await D.page.goto(nr.url,{waitUntil:"domcontentloaded",timeout:J.navigation})}catch{continue}await Ft();let Ct=await D.page.evaluate(uO).catch(()=>[]),{chosen:cc,cut:Mv}=dO(Array.isArray(Ct)?Ct:[],{forbidden:_e,limit:By});Mv&&(Be.explore_stopped_pages+=1);let zi=0;for(let as of cc){if(mt(),tn()){Be.explore_stopped_time=1;break}let Bi=as.role?D.page.getByRole(as.role,{name:as.name,exact:!0}):D.page.getByText(as.name,{exact:!0});if(await Bi.count()!==1)continue;let Pr=(await D.page.evaluate(Os)).elements;try{await Bi.click({timeout:J.action})}catch{}Be.controls_explored+=1,await on(J.exploreSettle),await Ft();let Zs=D.page.url(),Mt=null,Bt=!1;try{let ei=new URL(Zs);Mt=Yn(ei),Bt=ne.has(ei.hostname.toLowerCase())}catch{}if(Mt!==null&&Mt!==nr.key&&Bt){!zt.has(Mt)&&Be.pages<W&&(zt.add(Mt),gt.add(Mt),D.path=nr.key,D.pathRole=oe,Be.pages+=1,Be.routes.push({path:Mt.slice(0,300),source:"navigation",status:200,outcome:"reached",from_path:nr.key.slice(0,300)}),await Cn(),await zn(),zi=0,Ys.push({key:Mt,url:Zs,links:0})),await ro(nr);continue}let Qs=(await D.page.evaluate(Os)).elements,Pv=Qs.filter(ei=>!Pr.includes(ei));if(Pv.length>=2){let ei={key:nr.key.slice(0,300),title:String(await D.page.title().catch(()=>"")??"").slice(0,300),elements:[...new Set([...Pr,...Qs])].slice(0,Wy),role:oe};i(ei),q(ei)}if(await zn(),Pv.length)zi=0,await ro(nr);else if(++zi>=3){tn()&&(Be.explore_stopped_time=1);break}}}}finally{D.exploring=!1}Be.explore_blocked_writes=D.blockedWrites}Be.scripts=Ot.scripts(),Be.remaining_routes=[...pe,...xe].flatMap(nt=>{let tn=Yn(new URL(nt.url));return tn&&!gt.has(tn)?[{path:tn,source:nt.source}]:[]});return}case"remember":{let W=H.data.trim(),oe=H.target.trim();if(oe==="url")await pt(),Q[W]=D.page.url();else if(/^output(?:\s+field\s+|$)/i.test(oe)){if(!D.command)throw new Oe("needs_repair","Nothing was run before this step to remember output from.");let le=oe.replace(/^output\s*(?:field\s+)?/i,"");if(!le)Q[W]=D.command.output.trim();else{let ge=null;try{ge=JSON.parse(D.command.output)}catch{ge=null}let pe=ge===null?{found:!1}:jl(ge,le);if(!pe.found)throw new Oe("needs_repair",`The last output has no field ${le} to remember.`);Q[W]=Ba(pe.value)}}else if(/^field\s+/i.test(oe)){let le=oe.replace(/^field\s+/i,""),ge=D.response?jl(D.response.json,le):{found:!1};if(!ge.found)throw new Oe("needs_repair",`The last response has no field ${le} to remember.`);Q[W]=Ba(ge.value)}else{await pt();let le=await ss(fr(oe));Q[W]=String(await le.innerText()).trim()}break}default:throw new Oe("needs_repair",`\`${H.action}\` is not an action.`)}mt(),await mu(Ee),await Cn()}let ue=async()=>(await Ot.settled(),{signals:Ot.signals(),api_calls:v?[]:Ot.apiCalls(),vitals:Tt,scanned:Rt,scan_ms:D.scanMs});try{for(let[M,Q]of je.entries())try{if(D.step=M+1,await xo(Q),D.blockedRequest)throw new Oe("blocked",D.blockedRequest);ve[M]=c(),await zn()}catch(ee){let H=D.blockedRequest?new Oe("blocked",D.blockedRequest):ee instanceof Oe?ee:he?.aborted?new Oe("blocked",It(he.reason?.message??"The hunt was stopped; remaining actions were not run.")):new Oe("failed",It(ee.message));D.crawl||await Cn({final:!0}).catch(()=>{});let Ee=await So(),W=Ee?[{label:"after",step:M+1,media_type:"image/jpeg",data_base64:Ee}]:[];return{outcome:H.outcome,failed_step:M+1,message:`${Ye} step ${M+1}: ${It(H.message,1e3)}`,observed:H.observed?It(H.observed,1e3):null,duration_ms:c()-Le,evidence:[...W,...er],...await ue(),...D.crawl?{crawl:D.crawl}:{}}}return D.crawl||await Cn({final:!0}).catch(()=>{}),{outcome:"passed",failed_step:null,message:null,observed:null,duration_ms:c()-Le,evidence:er,...await ue(),...D.crawl?{crawl:D.crawl}:{}}}finally{he?.removeEventListener("abort",rs);let Q=(await Promise.allSettled([Vs,ns()])).find(ee=>ee.status==="rejected");if(Q)throw Q.reason}}return{run:Ke}}Gn();import un from"node:path";import{mkdirSync as bne}from"node:fs";import{format as Sne}from"node:util";mn();j();uc();j();var Nl=new Map;function Ml(e,t=Date.now()){let n=Nl.get(e);return!n||t>=n.retryAt}function EO(e,t,n,{remedy:r=null,now:o=Date.now()}={}){let s=Nl.get(e),i=(s?.failures??0)+1,a=Math.min(3e4*2**(i-1),6e5),c={id:e,title:t,remedy:r,message:LX(n),failures:i,firstFailedAt:s?.firstFailedAt??o,retryAt:o+a,retryInMs:a};return Nl.set(e,c),c}function xO(e){return Nl.delete(e)}function $O(e=Date.now()){return[...Nl.values()].map(t=>({...t,status:t.failures>=5?"failed":"warning",retryInMs:Math.max(t.retryAt-e,0)}))}function LX(e){return(e instanceof Error?e.message:String(e??"")).trim()||"No detail was reported."}mn();var Yy=22,UX=500,FX=300,zX=20,AO={ok:0,warning:1,failed:2},RO={codex:{url:"https://registry.npmjs.org/@openai%2fcodex/latest",version:e=>e?.version,remedy:"Run `npm install -g @openai/codex@latest`, then restart this connector."},forge:{url:"https://api.github.com/repos/tailcallhq/forgecode/releases/latest",version:e=>String(e?.tag_name??"").replace(/^v/,""),remedy:"Run `forge update`, then restart this connector."}},BX=360*6e4,TO=new WeakMap,GX="connector.diagnostics";function HX(e){return e.reduce((t,n)=>AO[n.status]>AO[t]?n.status:t,"ok")}async function OO({config:e,workspace:t=e?.workspace,version:n="development",probes:r,insights:o=[],agentSession:s=null,fetchImpl:i=fetch,nodeVersion:a=process.version}){let c=[qX(a),WX(e),await hf("backend","EngineerOS backend",()=>VX(e,i)),await hf("coding_agent","Coding agent",()=>XX(e,t,r.inspectAgent,i)),...s?[KX(s)]:[],await hf("tool_registry","Tool registry",()=>YX(t,r.inspectTools)),...e?.hunt_host?[]:[await hf("goal_runner","Goal runner",()=>ZX(t,r.runnerStatus,{serviceStatus:r.macRunnerStatus}))],...$O().map(QX),...o.map(l=>jt(l.id,l.title,l.status,l.detail,l.remedy))].slice(0,zX);return{checked_at:new Date().toISOString(),connector_version:String(n).slice(0,50),status:HX(c),checks:c}}function Zy(e){let t=[`Connector self-check: ${e.status} (${e.connector_version})`];for(let n of e.checks)t.push(`- ${n.title}: ${n.status} - ${n.detail}`),n.remedy&&t.push(` ${n.remedy}`);return t.join(`
|
|
968
|
-
`)}async function CO(e,t,n){return!e?.connector_id||!e.token?null:await n(e,{type:GX,...t})??{}}function qX(e){let t=Number.parseInt(String(e).replace(/^v/,""),10);return Number.isFinite(t)&&t>=Yy?jt("node_runtime","Node runtime","ok",`Node ${e}.`):jt("node_runtime","Node runtime","failed",`Node ${e} is older than the Node ${Yy} this connector requires.`,`Install Node ${Yy} or later, then start the connector again.`)}function WX(e){return e?.connector_id&&e.token?jt("pairing","Workspace pairing","ok",`Paired as ${e.name||e.connector_id} for ${e.workspace}.`):jt("pairing","Workspace pairing","failed","This workspace holds no connector credential.","Create a pairing command in EngineerOS and run it in this folder.")}async function VX(e,t){if(!e?.server_url)return jt("backend","EngineerOS backend","failed","No EngineerOS address is configured.","Pair this workspace with --url pointing at the EngineerOS backend.");let n=e0(e.server_url),r;try{r=await t(n,{signal:AbortSignal.timeout(1e4)})}catch(s){return jt("backend","EngineerOS backend","failed",`${n} is unreachable from this machine: ${Qy(s)}`,"Check the address, the network between this machine and EngineerOS, and that the backend is running.")}if(!r.ok)return jt("backend","EngineerOS backend","failed",`${n} answered ${r.status}.`,"Check that the address points at the EngineerOS backend rather than another service.");let o=await r.json().then(s=>s?.status).catch(()=>{});return o&&o!=="healthy"?jt("backend","EngineerOS backend","warning",`${n} reports itself as ${o}.`,"Open Admin > System in EngineerOS for the failing dependency."):jt("backend","EngineerOS backend","ok",`${n} is reachable.`)}async function XX(e,t,n,r){try{let o=await n(e,t),s=`${o.name} ${o.version} through ${o.protocol}.`,i=String(o.version??"").match(/\d+\.\d+\.\d+/)?.[0],a=i?await JX(o.protocol,r):null;return a&&Ur(a,i)>0?jt("coding_agent","Coding agent","warning",`${s} ${o.name} ${a} is available.`,RO[o.protocol].remedy):jt("coding_agent","Coding agent","ok",s)}catch(o){return jt("coding_agent","Coding agent","failed",Qy(o),null)}}async function JX(e,t){let n=RO[e];if(!n)return null;let r=TO.get(t)??new Map;TO.set(t,r);let o=r.get(e);if(o&&Date.now()-o.at<BX)return o.version;let s=null;try{let i=await t(n.url,{headers:{accept:"application/json"},signal:AbortSignal.timeout(5e3)}),a=i.ok?n.version(await i.json()):null;Ht(a)&&(s=a)}catch{}return r.set(e,{at:Date.now(),version:s}),s}function KX({state:e,detail:t,remedy:n=null}){return jt("agent_session","Coding agent session",e==="ready"?"ok":e==="checking"?"warning":"failed",t,n)}async function YX(e,t){let n=await t(e);if(n?.error)return jt("tool_registry","Tool registry","warning",n.error,"Run `engineeros-connector tools list` in this workspace for the full registry state.");let r=n?.entries?.length||0;return jt("tool_registry","Tool registry","ok",`${r} provider(s) registered.`)}async function ZX(e,t,{platform:n=process.platform,serviceStatus:r=cR}={}){if(n==="darwin"){let i=await r(e),a=`Run engineeros-connector runner start --workspace "${e}".`;if(i.disabled)return jt("goal_runner","Goal runner","warning","The macOS Goal runner is disabled.",`Turn it on in System Settings > General > Login Items. ${a}`);if(!i.loaded)return jt("goal_runner","Goal runner","warning",i.installed?"The macOS Goal runner is not loaded in this login session.":"The macOS Goal runner is not installed.",a);if(i.lastExitCode&&i.state!=="running")return jt("goal_runner","Goal runner","warning",`The macOS Goal runner exited with status ${i.lastExitCode} (${i.state||"unknown state"}).`,`Read .engineeros/runner/launchd.log. For protected folders, allow node under Privacy & Security > Files and Folders, or move the workspace. ${a}`)}let{jobs:o}=await t(e),s=o.filter(i=>["failed","recovering"].includes(i.status));if(s.length){let i=s[0];return jt("goal_runner","Goal runner","warning",`${s.length} local Goal job(s) need attention. ${i.runId} is ${i.status}${i.error?`: ${i.error}`:"."}`,"Open the Goal in EngineerOS, or read .engineeros/runs/<run-id>/activity.log in this workspace.")}return jt("goal_runner","Goal runner","ok",`${o.length} local Goal job(s) recorded, none stuck.`)}function QX(e){return jt(e.id,e.title,e.status,`Failing since ${$o(e.firstFailedAt)} after ${e.failures} attempt(s); retrying in ${Math.round(e.retryInMs/1e3)}s. ${e.message}`,e.remedy)}async function hf(e,t,n){try{return await n()}catch(r){return jt(e,t,"failed",Qy(r),null)}}function jt(e,t,n,r,o=null){return{id:e,title:t,status:n,detail:String(r||"No detail was reported.").slice(0,UX),remedy:o?String(o).slice(0,FX):null}}function Qy(e){return(e instanceof Error?e.message:String(e??"")).trim()||"No detail was reported."}j();import dJ from"node:path";j();import eJ from"node:path";var tJ=300*1e3,nJ={pytest:40,"node:test":40,vitest:60,jest:60},rJ=3,oJ=new Set(["pytest","vitest","jest","node:test","go-test","junit"]),sJ=new Set(["pytest-asyncio","pytest-cov","hypothesis","schemathesis","locust","bandit","pip-audit","@testing-library/react","@axe-core/playwright","k6","testify"]),IO=new Map([["@playwright/test","It drives a browser against the running app. Add an environment, then schedule it."],["cypress","It drives a browser against the running app. Add an environment, then schedule it."]]);function mf(e,t=process.env){return e?.quality_baseline===!1?!1:!["off","0","false","no"].includes(String(t.ENGINEEROS_QUALITY_BASELINE??"").trim().toLowerCase())}function jO(e=process.env){let t=Number(e.ENGINEEROS_BASELINE_IDLE_MS);return Number.isFinite(t)&&t>0?Math.floor(t):600*1e3}function iJ(e){let t=String(e?.name??"");return sJ.has(t)?{support:"helper"}:oJ.has(t)?{support:"run"}:IO.has(t)?{support:"skipped",reason:IO.get(t)}:{support:"unsupported",reason:`There is no baseline recipe for ${t||"this runner"}. Schedule its command and upload the JUnit report instead.`}}var e_=e=>String(e??"").replace(/\\/g,"/").replace(/^\.\//,"").replace(/\/+$/,""),aJ=(e,t)=>!t||e.startsWith(`${t}/`);function cJ(e,t){let n=null;for(let r of t)r.name!==e.framework||!aJ(e.file,r.root)||(!n||r.root.length>n.root.length)&&(n=r);return n}function lJ(e,{perShard:t,durations:n}){let r=e.map(c=>n[c]).filter(c=>Number.isFinite(c)&&c>0),o=[];if(!r.length){for(let c=0;c<e.length;c+=t)o.push(e.slice(c,c+t));return o}let s=r.reduce((c,l)=>c+l,0)/r.length,i=[],a=0;for(let c of e){let l=Number.isFinite(n[c])&&n[c]>0?n[c]:s;i.length&&a+l>tJ&&(o.push(i),i=[],a=0),i.push(c),a+=l}return i.length&&o.push(i),o}function NO({runners:e=[],testFiles:t=[],selection:n=null,durations:r={},workerLimit:o=1}={}){let s=n?.test_files?new Set(n.test_files.map(e_)):null,i=[];for(let l of e){let u=iJ(l);u.support!=="helper"&&i.push({index:i.length,name:l.name,root:e_(l.root),ecosystem:l.ecosystem??null,run_command:l.run_command??null,support:u.support,reason:u.reason??null,files:[],shards:[]})}for(let l of t.map(u=>({...u,file:e_(u.file)})))s&&!s.has(l.file)||cJ(l,i.filter(u=>u.support==="run"))?.files.push(l.file);for(let l of i){if(l.files=[...new Set(l.files)].sort(),l.support!=="run")continue;if(!l.files.length){l.support="skipped",l.reason=s?"None of the selected test files belong to it.":"No test files were found for it.";continue}let u=uJ(l,r);l.shards=u.map(({files:p,packages:d},f)=>({id:`${l.index}-${f}`,index:f,total:u.length,files:p,directory:l.root,packages:d}))}let a=Number(o);return{concurrency:Math.max(1,Math.min(rJ,Number.isInteger(a)&&a>0?a:1)),runners:i.map(({files:l,...u})=>u)}}function uJ(e,t){if(e.name==="go-test"){let n=new Map;for(let r of e.files){let o=e.root?r.slice(e.root.length+1):r,s=eJ.posix.dirname(o);n.set(s,[...n.get(s)??[],r])}return[...n.entries()].map(([r,o])=>({files:o,packages:[r==="."?".":r]}))}return e.name==="junit"?[{files:e.files,packages:[]}]:lJ(e.files,{perShard:nJ[e.name]??40,durations:t}).map(n=>({files:n,packages:[]}))}var pJ=2;function gf(e,t,n,{secretNames:r=[]}={}){let o=t.executionProfiles||{model_selection:!1,model_profiles:[],reasoning_efforts:[]},s=t.sessionStatus||{status:"unknown",message:"Agent authentication status was not reported.",login_command:null,logout_command:null},i=Xk(t.protocol);return{agent_protocols:[t.protocol],coding_agent:!0,connector_jobs:!0,...e.hunt_host?{hunt_host:!0}:{},capability_delivery:!e.hunt_host,measured_test_evidence:!e.hunt_host,test_automation_task:!e.hunt_host,test_checks:!e.hunt_host&&String(process.env.ENGINEEROS_TEST_CHECKS??"").trim().toLowerCase()!=="off",test_automation_workers:!e.hunt_host,model_probe:!0,test_schedules:!e.hunt_host,quality_baseline:!e.hunt_host&&mf(e),quality_map:!e.hunt_host,workspace_head:!e.hunt_host,bug_hunt:!0,bug_hunt_actions:[...Wp],bug_hunt_electron:process.env.ENGINEEROS_HUNT_HOST==="dedicated",bug_hunt_webdriver:!0,bug_hunt_native:!0,bug_hunt_browser:$i(n),bug_hunt_sign_in:!0,bug_hunt_inputs:1,bug_hunt_checks:[...$y],bug_hunt_secret_names:[...r],resumable_runs:!e.hunt_host,goal_run_contract:pJ,delivery_tasks:{protocol_version:1,backend_contract:1,schema_revision:"20261027_000183",connector_version:"1.59.23",runtime:e.agent_id||t.protocol,runtime_version:t.version||null,adapter_version:"1",worker_version:Pp,operations:e.hunt_host?[]:["start","cancel"]},http_updates:!0,product_stage_handover:!e.hunt_host,local_design_context:!e.hunt_host,agent_warm:!e.hunt_host,test_environments:!0,integrations:!0,workspace_opportunities:!e.hunt_host,codex_cli:t.protocol==="codex",platform:process.platform,workspace_name:dJ.basename(e.workspace),agent_name:t.name,agent_version:t.version,...e.agent_id?{agent_id:e.agent_id}:{},...$p(e.worker_limit),agent_session:s,provider_login:{supported:i,mode:i?"connector_terminal":null},...tA(),...n?{tool_inventory:n}:{},execution_profiles:{...o,models:(o.model_profiles||[]).map(a=>a.id)}}}j();Gt();ci();import{createHash as PO}from"node:crypto";import{readFile as fJ}from"node:fs/promises";import hJ from"node:os";import n_ from"node:path";var mJ=/^[A-Z_][A-Z0-9_]*$/,gJ=80,wJ=64,MO="hunt-secret-";function Dl(e){return typeof e=="string"&&e.length>0&&e.length<=gJ&&mJ.test(e)}function wf(e){let t=`${MO}${String(e).toLowerCase().replace(/_/g,"-")}`;return t.length<=wJ?t:`${MO}h${PO("sha256").update(String(e)).digest("hex").slice(0,40)}`}function yJ(e){let t=PO("sha256").update(n_.resolve(e??process.cwd())).digest("hex").slice(0,16);return n_.join(hJ.homedir(),".engineeros","hunt-secrets",t)}function t_(e){if(!Dl(e))throw new Error("A secret name uses capital letters, digits and underscores, for example ADMIN_TOTP_SECRET.");return e}function Ll({workspace:e=process.cwd(),vault:t,directory:n}={}){let r=n??yJ(e),o=t??En({directory:r}),s=n_.join(r,"names.json");async function i(){let u;try{u=await fJ(s,"utf8")}catch(p){if(p?.code==="ENOENT")return[];throw p}try{let p=JSON.parse(u);return(Array.isArray(p?.names)?p.names:[]).filter(Dl)}catch{return[]}}let a=Promise.resolve(),c=u=>{let p=a.then(async()=>{let d=new Set(await i());u(d),await Ae(s,`${JSON.stringify({names:[...d].sort()},null,2)}
|
|
968
|
+
`)}async function CO(e,t,n){return!e?.connector_id||!e.token?null:await n(e,{type:GX,...t})??{}}function qX(e){let t=Number.parseInt(String(e).replace(/^v/,""),10);return Number.isFinite(t)&&t>=Yy?jt("node_runtime","Node runtime","ok",`Node ${e}.`):jt("node_runtime","Node runtime","failed",`Node ${e} is older than the Node ${Yy} this connector requires.`,`Install Node ${Yy} or later, then start the connector again.`)}function WX(e){return e?.connector_id&&e.token?jt("pairing","Workspace pairing","ok",`Paired as ${e.name||e.connector_id} for ${e.workspace}.`):jt("pairing","Workspace pairing","failed","This workspace holds no connector credential.","Create a pairing command in EngineerOS and run it in this folder.")}async function VX(e,t){if(!e?.server_url)return jt("backend","EngineerOS backend","failed","No EngineerOS address is configured.","Pair this workspace with --url pointing at the EngineerOS backend.");let n=e0(e.server_url),r;try{r=await t(n,{signal:AbortSignal.timeout(1e4)})}catch(s){return jt("backend","EngineerOS backend","failed",`${n} is unreachable from this machine: ${Qy(s)}`,"Check the address, the network between this machine and EngineerOS, and that the backend is running.")}if(!r.ok)return jt("backend","EngineerOS backend","failed",`${n} answered ${r.status}.`,"Check that the address points at the EngineerOS backend rather than another service.");let o=await r.json().then(s=>s?.status).catch(()=>{});return o&&o!=="healthy"?jt("backend","EngineerOS backend","warning",`${n} reports itself as ${o}.`,"Open Admin > System in EngineerOS for the failing dependency."):jt("backend","EngineerOS backend","ok",`${n} is reachable.`)}async function XX(e,t,n,r){try{let o=await n(e,t),s=`${o.name} ${o.version} through ${o.protocol}.`,i=String(o.version??"").match(/\d+\.\d+\.\d+/)?.[0],a=i?await JX(o.protocol,r):null;return a&&Ur(a,i)>0?jt("coding_agent","Coding agent","warning",`${s} ${o.name} ${a} is available.`,RO[o.protocol].remedy):jt("coding_agent","Coding agent","ok",s)}catch(o){return jt("coding_agent","Coding agent","failed",Qy(o),null)}}async function JX(e,t){let n=RO[e];if(!n)return null;let r=TO.get(t)??new Map;TO.set(t,r);let o=r.get(e);if(o&&Date.now()-o.at<BX)return o.version;let s=null;try{let i=await t(n.url,{headers:{accept:"application/json"},signal:AbortSignal.timeout(5e3)}),a=i.ok?n.version(await i.json()):null;Ht(a)&&(s=a)}catch{}return r.set(e,{at:Date.now(),version:s}),s}function KX({state:e,detail:t,remedy:n=null}){return jt("agent_session","Coding agent session",e==="ready"?"ok":e==="checking"?"warning":"failed",t,n)}async function YX(e,t){let n=await t(e);if(n?.error)return jt("tool_registry","Tool registry","warning",n.error,"Run `engineeros-connector tools list` in this workspace for the full registry state.");let r=n?.entries?.length||0;return jt("tool_registry","Tool registry","ok",`${r} provider(s) registered.`)}async function ZX(e,t,{platform:n=process.platform,serviceStatus:r=cR}={}){if(n==="darwin"){let i=await r(e),a=`Run engineeros-connector runner start --workspace "${e}".`;if(i.disabled)return jt("goal_runner","Goal runner","warning","The macOS Goal runner is disabled.",`Turn it on in System Settings > General > Login Items. ${a}`);if(!i.loaded)return jt("goal_runner","Goal runner","warning",i.installed?"The macOS Goal runner is not loaded in this login session.":"The macOS Goal runner is not installed.",a);if(i.lastExitCode&&i.state!=="running")return jt("goal_runner","Goal runner","warning",`The macOS Goal runner exited with status ${i.lastExitCode} (${i.state||"unknown state"}).`,`Read .engineeros/runner/launchd.log. For protected folders, allow node under Privacy & Security > Files and Folders, or move the workspace. ${a}`)}let{jobs:o}=await t(e),s=o.filter(i=>["failed","recovering"].includes(i.status));if(s.length){let i=s[0];return jt("goal_runner","Goal runner","warning",`${s.length} local Goal job(s) need attention. ${i.runId} is ${i.status}${i.error?`: ${i.error}`:"."}`,"Open the Goal in EngineerOS, or read .engineeros/runs/<run-id>/activity.log in this workspace.")}return jt("goal_runner","Goal runner","ok",`${o.length} local Goal job(s) recorded, none stuck.`)}function QX(e){return jt(e.id,e.title,e.status,`Failing since ${$o(e.firstFailedAt)} after ${e.failures} attempt(s); retrying in ${Math.round(e.retryInMs/1e3)}s. ${e.message}`,e.remedy)}async function hf(e,t,n){try{return await n()}catch(r){return jt(e,t,"failed",Qy(r),null)}}function jt(e,t,n,r,o=null){return{id:e,title:t,status:n,detail:String(r||"No detail was reported.").slice(0,UX),remedy:o?String(o).slice(0,FX):null}}function Qy(e){return(e instanceof Error?e.message:String(e??"")).trim()||"No detail was reported."}j();import dJ from"node:path";j();import eJ from"node:path";var tJ=300*1e3,nJ={pytest:40,"node:test":40,vitest:60,jest:60},rJ=3,oJ=new Set(["pytest","vitest","jest","node:test","go-test","junit"]),sJ=new Set(["pytest-asyncio","pytest-cov","hypothesis","schemathesis","locust","bandit","pip-audit","@testing-library/react","@axe-core/playwright","k6","testify"]),IO=new Map([["@playwright/test","It drives a browser against the running app. Add an environment, then schedule it."],["cypress","It drives a browser against the running app. Add an environment, then schedule it."]]);function mf(e,t=process.env){return e?.quality_baseline===!1?!1:!["off","0","false","no"].includes(String(t.ENGINEEROS_QUALITY_BASELINE??"").trim().toLowerCase())}function jO(e=process.env){let t=Number(e.ENGINEEROS_BASELINE_IDLE_MS);return Number.isFinite(t)&&t>0?Math.floor(t):600*1e3}function iJ(e){let t=String(e?.name??"");return sJ.has(t)?{support:"helper"}:oJ.has(t)?{support:"run"}:IO.has(t)?{support:"skipped",reason:IO.get(t)}:{support:"unsupported",reason:`There is no baseline recipe for ${t||"this runner"}. Schedule its command and upload the JUnit report instead.`}}var e_=e=>String(e??"").replace(/\\/g,"/").replace(/^\.\//,"").replace(/\/+$/,""),aJ=(e,t)=>!t||e.startsWith(`${t}/`);function cJ(e,t){let n=null;for(let r of t)r.name!==e.framework||!aJ(e.file,r.root)||(!n||r.root.length>n.root.length)&&(n=r);return n}function lJ(e,{perShard:t,durations:n}){let r=e.map(c=>n[c]).filter(c=>Number.isFinite(c)&&c>0),o=[];if(!r.length){for(let c=0;c<e.length;c+=t)o.push(e.slice(c,c+t));return o}let s=r.reduce((c,l)=>c+l,0)/r.length,i=[],a=0;for(let c of e){let l=Number.isFinite(n[c])&&n[c]>0?n[c]:s;i.length&&a+l>tJ&&(o.push(i),i=[],a=0),i.push(c),a+=l}return i.length&&o.push(i),o}function NO({runners:e=[],testFiles:t=[],selection:n=null,durations:r={},workerLimit:o=1}={}){let s=n?.test_files?new Set(n.test_files.map(e_)):null,i=[];for(let l of e){let u=iJ(l);u.support!=="helper"&&i.push({index:i.length,name:l.name,root:e_(l.root),ecosystem:l.ecosystem??null,run_command:l.run_command??null,support:u.support,reason:u.reason??null,files:[],shards:[]})}for(let l of t.map(u=>({...u,file:e_(u.file)})))s&&!s.has(l.file)||cJ(l,i.filter(u=>u.support==="run"))?.files.push(l.file);for(let l of i){if(l.files=[...new Set(l.files)].sort(),l.support!=="run")continue;if(!l.files.length){l.support="skipped",l.reason=s?"None of the selected test files belong to it.":"No test files were found for it.";continue}let u=uJ(l,r);l.shards=u.map(({files:p,packages:d},f)=>({id:`${l.index}-${f}`,index:f,total:u.length,files:p,directory:l.root,packages:d}))}let a=Number(o);return{concurrency:Math.max(1,Math.min(rJ,Number.isInteger(a)&&a>0?a:1)),runners:i.map(({files:l,...u})=>u)}}function uJ(e,t){if(e.name==="go-test"){let n=new Map;for(let r of e.files){let o=e.root?r.slice(e.root.length+1):r,s=eJ.posix.dirname(o);n.set(s,[...n.get(s)??[],r])}return[...n.entries()].map(([r,o])=>({files:o,packages:[r==="."?".":r]}))}return e.name==="junit"?[{files:e.files,packages:[]}]:lJ(e.files,{perShard:nJ[e.name]??40,durations:t}).map(n=>({files:n,packages:[]}))}var pJ=2;function gf(e,t,n,{secretNames:r=[]}={}){let o=t.executionProfiles||{model_selection:!1,model_profiles:[],reasoning_efforts:[]},s=t.sessionStatus||{status:"unknown",message:"Agent authentication status was not reported.",login_command:null,logout_command:null},i=Xk(t.protocol);return{agent_protocols:[t.protocol],coding_agent:!0,connector_jobs:!0,...e.hunt_host?{hunt_host:!0}:{},capability_delivery:!e.hunt_host,measured_test_evidence:!e.hunt_host,test_automation_task:!e.hunt_host,test_checks:!e.hunt_host&&String(process.env.ENGINEEROS_TEST_CHECKS??"").trim().toLowerCase()!=="off",test_automation_workers:!e.hunt_host,model_probe:!0,test_schedules:!e.hunt_host,quality_baseline:!e.hunt_host&&mf(e),quality_map:!e.hunt_host,workspace_head:!e.hunt_host,bug_hunt:!0,bug_hunt_actions:[...Wp],bug_hunt_electron:process.env.ENGINEEROS_HUNT_HOST==="dedicated",bug_hunt_webdriver:!0,bug_hunt_native:!0,bug_hunt_browser:$i(n),bug_hunt_sign_in:!0,bug_hunt_inputs:1,bug_hunt_checks:[...$y],bug_hunt_secret_names:[...r],resumable_runs:!e.hunt_host,goal_run_contract:pJ,delivery_tasks:{protocol_version:1,backend_contract:1,schema_revision:"20261027_000183",connector_version:"1.59.24",runtime:e.agent_id||t.protocol,runtime_version:t.version||null,adapter_version:"1",worker_version:Pp,operations:e.hunt_host?[]:["start","cancel"]},http_updates:!0,product_stage_handover:!e.hunt_host,local_design_context:!e.hunt_host,agent_warm:!e.hunt_host,test_environments:!0,integrations:!0,workspace_opportunities:!e.hunt_host,codex_cli:t.protocol==="codex",platform:process.platform,workspace_name:dJ.basename(e.workspace),agent_name:t.name,agent_version:t.version,...e.agent_id?{agent_id:e.agent_id}:{},...$p(e.worker_limit),agent_session:s,provider_login:{supported:i,mode:i?"connector_terminal":null},...tA(),...n?{tool_inventory:n}:{},execution_profiles:{...o,models:(o.model_profiles||[]).map(a=>a.id)}}}j();Gt();ci();import{createHash as PO}from"node:crypto";import{readFile as fJ}from"node:fs/promises";import hJ from"node:os";import n_ from"node:path";var mJ=/^[A-Z_][A-Z0-9_]*$/,gJ=80,wJ=64,MO="hunt-secret-";function Dl(e){return typeof e=="string"&&e.length>0&&e.length<=gJ&&mJ.test(e)}function wf(e){let t=`${MO}${String(e).toLowerCase().replace(/_/g,"-")}`;return t.length<=wJ?t:`${MO}h${PO("sha256").update(String(e)).digest("hex").slice(0,40)}`}function yJ(e){let t=PO("sha256").update(n_.resolve(e??process.cwd())).digest("hex").slice(0,16);return n_.join(hJ.homedir(),".engineeros","hunt-secrets",t)}function t_(e){if(!Dl(e))throw new Error("A secret name uses capital letters, digits and underscores, for example ADMIN_TOTP_SECRET.");return e}function Ll({workspace:e=process.cwd(),vault:t,directory:n}={}){let r=n??yJ(e),o=t??En({directory:r}),s=n_.join(r,"names.json");async function i(){let u;try{u=await fJ(s,"utf8")}catch(p){if(p?.code==="ENOENT")return[];throw p}try{let p=JSON.parse(u);return(Array.isArray(p?.names)?p.names:[]).filter(Dl)}catch{return[]}}let a=Promise.resolve(),c=u=>{let p=a.then(async()=>{let d=new Set(await i());u(d),await Ae(s,`${JSON.stringify({names:[...d].sort()},null,2)}
|
|
969
969
|
`)});return a=p.catch(()=>{}),p},l={directory:r,async get(u){t_(u);let p=await o.get(e,wf(u));return typeof p=="string"&&p!==""?p:null},async set(u,p){if(t_(u),typeof p!="string"||p==="")throw new Error("A secret needs a value.");await o.put(e,wf(u),p),await c(d=>d.add(u))},async remove(u){t_(u),await o.delete(e,wf(u)),await c(p=>p.delete(u))},async names(){return(await i()).sort()},async has(u){return Dl(u)?!!await o.has(e,wf(u)):!1},async values(u){let p={};for(let d of[...new Set(u??[])]){if(!Dl(d))continue;let f=await l.get(d);f!==null&&(p[d]=f)}return p}};return l}async function DO({input:e=process.stdin,output:t=process.stderr,label:n="Value"}={}){if(!e.isTTY){let r=[];for await(let o of e)r.push(Buffer.from(o));return Buffer.concat(r).toString("utf8")}return t.write(`${n} (typing is hidden): `),await new Promise((r,o)=>{let s="";e.setRawMode?.(!0),e.resume(),e.setEncoding("utf8");let i=c=>{e.setRawMode?.(!1),e.pause(),e.off("data",a),t.write(`
|
|
970
970
|
`),c?o(c):r(s)},a=c=>{for(let l of c){if(l==="\r"||l===`
|
|
971
971
|
`||l==="")return i();if(l==="")return i(new Error("Cancelled."));l==="\x7F"||l==="\b"?s=s.slice(0,-1):s+=l}};e.on("data",a)})}var Pl=(e,t)=>(t?.(e),{ok:!1,message:e});async function LO({action:e,name:t,workspace:n=process.cwd(),readValue:r,vault:o,directory:s,write:i}={}){let a=(l,u)=>(i?.(u),{ok:l,message:u});if(e!=="set"&&e!=="list"&&e!=="remove")return Pl("Use `secret set NAME`, `secret list` or `secret remove NAME`.",i);let c=Ll({workspace:n,vault:o,directory:s});try{if(e==="list"){let p=await c.names();return a(!0,p.length?p.join(`
|
|
@@ -1177,7 +1177,7 @@ It is checked with the provider and stored in this machine's protected vault
|
|
|
1177
1177
|
(Windows Data Protection, the macOS Keychain or the Linux Secret Service).
|
|
1178
1178
|
EngineerOS never receives it; the running connector uses it when EngineerOS asks.`;function gne(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(`
|
|
1179
1179
|
`),c?o(c):r(s.trim())},a=c=>{for(let l of c){if(l==="\r"||l===`
|
|
1180
|
-
`)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 vN=Symbol("missing");function wne(e,t){return new Promise(n=>{let r=hne(e,t,{stdio:"inherit",shell:!1});r.once("error",o=>n(o?.code==="ENOENT"?vN:o.message)),r.once("close",o=>n(o===0?null:`${e} exited with code ${o}.`))})}function _N(e,t){for(let n of ou){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 bN(e,t,n,{vault:r=cv(),run:o=nh,fetchImpl:s=fetch,secret:i=gne,interactive:a=wne,install:c=Zf,log:l=console.log,error:u=console.error}={}){if(n.help||e!=="integrations"&&!t[0])return l(mne),n.help?0:2;if(e==="integrations")return _N(l,(await sh({run:o,vault:r})).providers),0;let p=t[0];if(!ou.includes(p))return u(`Unknown provider ${p}. Choose one of: ${ou.join(", ")}.`),2;if(p==="github"||p==="gitlab"){let f=Ii[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===vN){let g=await Us(f);if(!g){l(`Installing the ${Zl[f].label} ${Zl[f].version} for the connector...`);try{g=(await c(f)).path}catch(w){return u(w.message),1}}h=await a(g,["auth","login"])}return h?(u(`${h} ${oh[p]} is how this machine signs in to ${p}.`),1):(_N(l,{[p]:(await sh({run:o,vault:r})).providers[p]}),0)}let d=bn[p];if(e==="disconnect")return await r.delete("",p),l(`Removed the ${d.label} ${d.tokenName} from this machine.`),0;try{await lv(r);let f=await i(`${d.label} ${d.tokenName} (create one at ${d.tokenUrl}): `),h=await uv(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}}j();import{spawn as yne}from"node:child_process";async function SN({root:e,bundled:t,argv:n,workspace:r,spawnImpl:o=yne,log:s=console.log}){let i=n,a=!1;for(;;){let c=t;try{c=us(await Nn(e),t)}catch(p){s(`${p.message} Starting the installed connector ${t.version}.`)}let{code:l,signal:u}=await _ne(o,c.entry,i,t);if(l===_c){i=["start","--workspace",r],a=!1,s("Restarting the connector process on the activated update. Goal runs continue in their own processes.");continue}if(l!==0&&!u&&!a){let p=await Nn(e).catch(()=>null);if(p&&!p.confirmed&&p.active?.version===c.version)try{let d=await Gh(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 _ne(e,t,n,r){return new Promise((o,s)=>{let i=e(process.execPath,[...process.execArgv,t,...n],{stdio:"inherit",env:{...process.env,[Hi]:"1",[Lh]:r.entry,[Uh]: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 qs="1.59.
|
|
1180
|
+
`)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 vN=Symbol("missing");function wne(e,t){return new Promise(n=>{let r=hne(e,t,{stdio:"inherit",shell:!1});r.once("error",o=>n(o?.code==="ENOENT"?vN:o.message)),r.once("close",o=>n(o===0?null:`${e} exited with code ${o}.`))})}function _N(e,t){for(let n of ou){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 bN(e,t,n,{vault:r=cv(),run:o=nh,fetchImpl:s=fetch,secret:i=gne,interactive:a=wne,install:c=Zf,log:l=console.log,error:u=console.error}={}){if(n.help||e!=="integrations"&&!t[0])return l(mne),n.help?0:2;if(e==="integrations")return _N(l,(await sh({run:o,vault:r})).providers),0;let p=t[0];if(!ou.includes(p))return u(`Unknown provider ${p}. Choose one of: ${ou.join(", ")}.`),2;if(p==="github"||p==="gitlab"){let f=Ii[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===vN){let g=await Us(f);if(!g){l(`Installing the ${Zl[f].label} ${Zl[f].version} for the connector...`);try{g=(await c(f)).path}catch(w){return u(w.message),1}}h=await a(g,["auth","login"])}return h?(u(`${h} ${oh[p]} is how this machine signs in to ${p}.`),1):(_N(l,{[p]:(await sh({run:o,vault:r})).providers[p]}),0)}let d=bn[p];if(e==="disconnect")return await r.delete("",p),l(`Removed the ${d.label} ${d.tokenName} from this machine.`),0;try{await lv(r);let f=await i(`${d.label} ${d.tokenName} (create one at ${d.tokenUrl}): `),h=await uv(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}}j();import{spawn as yne}from"node:child_process";async function SN({root:e,bundled:t,argv:n,workspace:r,spawnImpl:o=yne,log:s=console.log}){let i=n,a=!1;for(;;){let c=t;try{c=us(await Nn(e),t)}catch(p){s(`${p.message} Starting the installed connector ${t.version}.`)}let{code:l,signal:u}=await _ne(o,c.entry,i,t);if(l===_c){i=["start","--workspace",r],a=!1,s("Restarting the connector process on the activated update. Goal runs continue in their own processes.");continue}if(l!==0&&!u&&!a){let p=await Nn(e).catch(()=>null);if(p&&!p.confirmed&&p.active?.version===c.version)try{let d=await Gh(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 _ne(e,t,n,r){return new Promise((o,s)=>{let i=e(process.execPath,[...process.execArgv,t,...n],{stdio:"inherit",env:{...process.env,[Hi]:"1",[Lh]:r.entry,[Uh]: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 qs="1.59.24",ph="1.59.24",kne=3e5,fh=["queued","running","reporting"],Ene=5e3,dv={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."},pv={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."},xne=6e4,$ne=3e4,Ane=60*6e4,fv={id:"tool_inventory",title:"Tool inventory refresh",remedy:"Run `engineeros-connector tools list` in this workspace for the full registry state."},hv={id:"runner_setup_reporting",title:"Goal runner setup reporting",remedy:"Restore the connection to EngineerOS; saved setup reports will retry automatically."},{command:At,positional:Nt,flags:Ie}=UO(process.argv.slice(2));At==="version"&&(console.log(qs),process.exit(0));var ts=null,Xt=!1,Ir=null,DN=!1,LN=null,Rv=null,Jt=null,fu=null,xv,kN,lu,mv,EN,Za,Pi,UN=Lf({getWorkspace:()=>P.workspace,onRecorded:e=>qI(P,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}`))}),Tne=wN({getWorkspace:()=>P.workspace,getConfig:()=>P,huntSignIns:UN}),uu=GO();At==="results"&&(Nt[0]!=="upload"&&(console.log(xf),process.exit(Ie.help||!Nt[0]?0:2)),process.exit(await YC(Ie)));(At==="connect"||At==="disconnect"||At==="integrations")&&process.exit(await bN(At,Nt,Ie,{fetchImpl:hN}));if(At==="delivery"){let e=un.resolve(Ie.workspace||process.cwd());try{if(Nt[0]==="execute")await vR(Ie.input);else if(Nt[0]==="worker"){let t=await sn(e);if(!t)throw new Error("Restore the paired connector configuration before reporting or executing delivery work.");await K1(t,Ie["attempt-id"])}else if(Nt[0]==="probe"){let t=await Dp().probe();console.log(JSON.stringify(t))}else throw new Error("Use delivery worker --attempt-id <attempt>, delivery execute --input <file> inside the qualified image, or delivery probe.");process.exit(0)}catch(t){console.error(gn(t)),process.exit(1)}}if(At==="runner"){let e=un.resolve(Ie.workspace||process.cwd()),t=Nt[0]||"status";try{if(t==="serve"||t==="worker"){let n=t==="worker"?un.join(un.dirname(Pt(e,Ie["run-id"])),"worker.log"):un.join(e,".engineeros","runner","service.log");bne(un.dirname(n),{recursive:!0});let r=(...s)=>wl(n,`${Sne(...s)}
|
|
1181
1181
|
`),o=(s,i,a)=>(wl(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(Ie["keep-awake"]!==void 0){if(!["on","off"].includes(Ie["keep-awake"]))throw new Error("Use --keep-awake on or off.");let n=await sn(e);if(!n)throw new Error("Pair this workspace before changing its runner keep-awake setting.");await br({...n,runner_keep_awake:Ie["keep-awake"]==="on"})}console.log(`Installed Goal runner service: ${await iR(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 lR(e),console.log("Goal runner service removed. Saved and queued jobs are kept.")):t==="start"?await Si(e,{enable:!0}):t==="status"?console.log(JSON.stringify(await $s(e),null,2)):t==="serve"?await fR(e):t==="worker"?await hR(e,Ie["run-id"]):vt("Usage: engineeros-connector runner [install|start|status|uninstall] --workspace PATH [--keep-awake on|off]");process.exit(0)}catch(n){vt(vy(n,e).message)}}Ie["assessment-workers"]!==void 0&&vt("--assessment-workers is no longer supported. Select 3 to 8 parallel agents in EngineerOS before starting the assessment.");if(At==="secret")try{let e=Ey(Ie),t=Nt[0]||"list",n=await LO({action:t,name:Nt[1],workspace:e,readValue:()=>DO({label:`Value for ${Nt[1]}`}),write:r=>console.log(r)});process.exit(n.ok?0:1)}catch(e){vt(e.message)}if(At==="tools"){try{let e=Ey(Ie),t=Nt[0]||"list";if(["sign-in","auth-status","sign-out"].includes(t)){let r=Nt[1];r||vt(`Usage: engineeros-connector tools ${t} PROVIDER_ID [--workspace PATH | --project PROJECT_UUID]`);let o=await Xg(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 nl(e,{type:"tools.update",command_id:"00000000-0000-4000-8000-000000000002",action:t,provider_id:Nt[1],confirmed:!0},void 0,{confirmLocal:async()=>!0}):t!=="list"&&await qg(e,t,Nt[1]);let n=await pr(e);console.log(JSON.stringify(n,null,2)),process.exitCode=n.error?1:0}catch(e){vt(e.message)}process.exit(process.exitCode||0)}if(At==="agents"){let e;try{e=await uw()}catch(n){vt(n instanceof Error?n.message:String(n))}let t=await Promise.all(e.map(async n=>{try{return await ol(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(At==="agent"){let e=Nt[0],t=Nt[1]||"check";(!e||!["check","install"].includes(t))&&vt("Usage: engineeros-connector agent AGENT_ID [check|install]");try{let n=t==="install"?await sl(e):await ol(e);console.log(`${n.name} is ready (${n.version}, ${n.distribution}).`)}catch(n){vt(n instanceof Error?n.message:String(n))}process.exit(0)}if(At==="mcp"){let e=Ie.workspace||process.env.ENGINEEROS_MCP_WORKSPACE||process.cwd(),t=Ie["run-id"]||Nt[0]||process.env.ENGINEEROS_MCP_RUN_ID||null,n=await sn(e);await aC({config:n,runId:t,version:qs,input:process.stdin,output:process.stdout}),process.exit(0)}if(At==="context-mcp"){let e=Ie["config-workspace"]||Ie.workspace||process.env.ENGINEEROS_MCP_WORKSPACE||process.cwd(),t=await sn(e);t||vt("This workspace is not paired with EngineerOS."),await zC({config:t,workspace:Ie.workspace||process.env.ENGINEEROS_CONTEXT_WORKSPACE||t.workspace,version:qs,input:process.stdin,output:process.stdout}),process.exit(0)}if(At==="status"){let e=await sn(Ie.workspace||process.cwd());console.log(e?`Paired as ${e.name} (${e.connector_id}) for ${e.workspace}`:"Not paired"),process.exit(e?0:1)}if(At==="doctor"){let e=un.resolve(Ie.workspace||process.cwd()),t=await sn(e),n=await eC(e),r=await ic(t||{workspace:e},e,r_(n));console.log(Zy(r)),process.exit(r.status==="failed"?1:0)}if(At==="update"){let e=Nt[0]||"status";try{let t=zh(process.argv[1],ph),n=await Hh(sr(),t,{action:e,policy:Nt[1]??null});console.log(bc(qh(n,t,{supervised:!0})))}catch(t){vt(`${t.message}
|
|
1182
1182
|
Usage: engineeros-connector update [status|check|apply|rollback|policy manual|approve|auto-patch|auto-minor]`)}process.exit(0)}var ec=At==="hunt-host";if(ec)try{Ie.workspace=kR(Nt,Ie)}catch(e){vt(e.message)}if((At==="start"||At==="pair"||ec)&&process.env[Hi]!=="1"&&Ht(ph))try{process.exit(await SN({root:sr(),bundled:{version:ph,entry:un.resolve(process.argv[1])},argv:process.argv.slice(2),workspace:un.resolve(Ie.workspace||process.cwd())}))}catch(e){vt(`The connector process could not be started: ${e.message}`)}if(ec){try{await ER(Ie.workspace,Nt[0]?Ie.agent:null)}catch(e){vt(e.message)}At=Nt[0]?"pair":"start"}var P,Di,du;if(At==="pair"){let e=Nt[0];e||vt("Usage: engineeros-connector pair CODE --url URL [--agent AGENT_ID | --agent-protocol forge] [--name NAME] [--workspace PATH] [--skip-git-repo-check]");let t=Ie.url;t||vt("Pairing requires --url with the EngineerOS backend address."),Ie.agent&&Ie["agent-command"]&&vt("Use either --agent or --agent-command, not both.");let n=Ie["agent-protocol"]||(Ie["agent-command"]?"acp":"codex");["codex","acp","forge"].includes(n)||vt(`Unknown --agent-protocol '${n}'. Use codex, acp, or forge.`),n==="forge"&&(Ie.agent||Ie["agent-command"])&&vt("Forge runs its own agents. Drop --agent and --agent-command when pairing with --agent-protocol forge.");let r={};try{Ie.agent&&(await ol(Ie.agent),r=await dw(Ie.agent))}catch(o){vt(o instanceof Error?o.message:String(o))}P={server_url:Xh(t),workspace:un.resolve(Ie.workspace||process.cwd()),onboard:Ie.onboard===!0,onboarding_pending:Ie.onboard===!0,hunt_host:ec,agent_protocol:n,agent_command:Ie["agent-command"]||null,agent_args:Qne(Ie["agent-args"]),agent_name:Ie["agent-name"]||null,...r,skip_git_repo_check:ec||Ie["skip-git-repo-check"]===!0,name:Ie.name||`${vne.hostname()} - ${un.basename(un.resolve(Ie.workspace||process.cwd()))}`},du=await sn(P.workspace),Di={type:"pair",pairing_code:e,name:P.name,capabilities:{},...Wb(du,P.server_url)}}else At==="start"?(P=await sn(Ie.workspace||process.cwd()),P||vt("This connector is not paired. Create a pairing command in EngineerOS first."),ec&&!P.hunt_host&&vt("This folder is not a paired hunt host. Generate a new hunt-host command in EngineerOS."),P.token||vt("This connector's token is no longer in this machine's credential store. Create a new pairing command in EngineerOS and pair again."),Di={type:"authenticate",connector_id:P.connector_id,token:P.token}):vt("Use `engineeros-connector pair`, `start`, `status`, `doctor`, `agents`, `agent`, `tools`, `secret`, or `mcp`.");var FN=mR(P,{reportError:e=>console.error(e)}),Hs=0,hh=!1,oc=null,Rn=new Map,gv=0,wv=new Set,tc=[],Sn=new Map,Vt,$v,ch,bo=null,lh=!1,zN=0,yv=null,_v=[],uh,BN,iu=1e3,nc,xN=0,vv=!1,vo=!1,jr,Bs=!1,mh=!1,Av=0;function Fs(e){return Av+=1,e.finally(()=>{Av-=1})}var Qa,ji=0;function sc({exitCode:e=0}={}){if(ji=Math.max(ji,e),Qa)return Qa;let t=setTimeout(()=>{console.error("Connector shutdown exceeded 15 seconds; inspect the retained agent logs before restarting."),process.exit(1)},15e3);return t.unref(),Qa=Rne().finally(()=>clearTimeout(t)),Qa}async function Rne(){if(Xt=!0,fu?.stop(),ts?.stop(),Rv?.stop(),LN?.stop(),clearInterval(xv),Jt?.stop(),BN?.(),clearTimeout(uh),clearInterval($v),clearInterval(ch),await Promise.all([...[...Rn.values()].map(e=>Dn(e.child))]),await Promise.all([...Sn.values()].map(jv)),await Za?.cancelAll(),await lu?.stop(),await Pi?.abortAll(),await rl(),await Hv().catch(e=>{ji=Math.max(ji,1),console.error(`${e.message}. Stop those processes before restarting the connector.`)}),Vt?.close(),ji&&ji!==_c){let e;await Promise.race([(async()=>{await ts?.drain(),await ic(P,P.workspace)})().catch(()=>{}),new Promise(t=>{e=setTimeout(t,1e4)})]).finally(()=>clearTimeout(e))}process.exit(ji)}for(let e of["SIGINT","SIGTERM","SIGHUP"])process.on(e,()=>{sc()});var $N=!1;for(let e of["uncaughtException","unhandledRejection"])process.on(e,async t=>{$N||($N=!0,console.error(`Connector stopping after an unhandled failure: ${t instanceof Error?t.stack||t.message:String(t)}`),await sc({exitCode:1}))});Jt=Yv();process.on("exit",()=>{fu?.stop(),Jt.stop()});Jt.banner(`EngineerOS connector ${qs}`,[P.workspace,P.server_url]);ts=BO({actions:{refresh_tool_inventory:async()=>{Ge.tool_inventory=await pr(P.workspace),Qn()},restart_goal_runner:()=>Si(P.workspace)},onNotify:()=>ic(P,P.workspace),explain:async e=>{if(!await Gs())return null;let{reading:t}=await h1(P,e);return t},onUpdate:e=>QO(P.workspace,e)});LN=nC({render:(e,t)=>Jt.write(e,t),onRecord:e=>ts.observe(e)});Rv=rC({workspace:P.workspace,onRecord:e=>{ts.observe(e),Jt.line(e.channel,e.level,e.message)}});ts.start();P.hunt_host||Rv.start();Jt.live&&!P.hunt_host&&(xv=setInterval(()=>{One().catch(()=>{})},Ene),xv.unref?.());var bv=new Set;async function One(){if(P.hunt_host)return;kN??=wy(P.workspace);let{jobs:e}=await kN(),t=new Set,n=e.filter(r=>r.status!=="queued"&&fh.includes(r.status)).length;for(let r of e){if(!fh.includes(r.status))continue;t.add(r.runId),bv.add(r.runId);let o=r.status==="queued"&&n>0?`queued behind running Goals (running: ${n})`:r.activity?.phase||r.status;Jt.status(`goal:${r.runId}`,r.activity?.message||o,Cne(r),{agent:r.status!=="queued",link:oc&&`${oc}/goals`,phase:o}),Jt.step(`goal:${r.runId}`,r.activity?.message)}for(let r of bv)t.has(r)||(bv.delete(r),Jt.clearStatus(`goal:${r}`))}function Cne(e){let t=e.startedAt??Date.parse(e.updatedAt??"");return Number.isFinite(t)?t:Date.now()}async function Gs({ignoreBugHunt:e=!1}={}){if(Xt||Rn.size>0||Sn.size>0||Hs>0||(Za?.active??0)>0||(lu?.active??0)>0||!e&&(Pi?.active??0)>0)return!1;try{let{jobs:t}=await $s(P.workspace);return!Xt&&!t.some(n=>fh.includes(n.status))}catch{return!1}}try{let e=P.hunt_host?{}:await Gi(P.workspace);e.committed&&(P.onboarding_pending=!0,P.connector_id&&await br(P),console.log(`Local project repository ready at ${e.revision.slice(0,8)}. Source and design artifacts are committed locally.`))}catch(e){await JN(e)}var GN=await Nn(sr()).then(e=>e.policy!=="manual",()=>!1),lt;try{lt=await ml(P,P.workspace)}catch(e){await JN(e)}console.log(`Using ${lt.name} through ${lt.protocol} (${lt.version}).`);var HN=async()=>Ll({workspace:P.workspace}).names().catch(()=>[]),Ge=gf(P,lt,await pr(P.workspace),{secretNames:await HN()}),es=Ib({workspace:P.workspace,running:zh(process.argv[1],ph),supervised:process.env[Hi]==="1",isIdle:async()=>!Xt&&Rn.size===0&&tc.length===0&&Sn.size===0&&Hs===0&&Av===0&&!Bs&&!mh&&(Pi?.active??0)===0&&(lu?.active??0)===0&&!lh,restart:()=>sc({exitCode:_c}),onChange:e=>{Ge.runtime_update=e,Vt?.readyState===WebSocket.OPEN&&Qn()}});try{await es.refresh()}catch(e){console.error(`Connector updates are unavailable: ${e.message}`)}P={...P,execution_profiles:lt.executionProfiles??null};At==="pair"&&du?.connector_id||await br(P);Ge.agent_session={...Ge.agent_session,status:"checking",message:`Checking that ${lt.name} can answer.`};Ge.bug_hunt_browser=!1;Di.capabilities=Ge;console.log(zo(P.worker_limit)===null?`Workers: automatic, ${ka()} ${lt.name} workers side by side for this machine's CPU and memory; change it with /workers.`:`Workers: ${zo(P.worker_limit)} ${lt.name} workers side by side, set with /workers.`);var pu=Af({getConfig:()=>P}),Ni=async e=>{let t;try{t=await Go(P,e)}catch(n){throw[401,403].includes(n.status)&&(vo=!0,console.error("EngineerOS withdrew this connector's authorization. Local work is stopping; saved reports are retained."),sc()),n}return t?.execution_sync&&await Ine(t.execution_sync),t},AN=Op(Ni,{signature:E1}),Sv,su,cu=new Map,Tv=new Set,kv;function Mi(){return lu??=sI({getConfig:()=>P,jobStore:pu,canRun:()=>Gs()}),Pi??=Bj({getConfig:()=>({...P,tool_inventory:Ge.tool_inventory}),jobStore:pu,recordedSignIns:UN,isIdle:()=>Gs({ignoreBugHunt:!0}),canRun:async e=>{if(!await Gs({ignoreBugHunt:!0}))return!1;let t=e.assignment;return t.kind!=="production_check"&&Ir?.state!=="ready"?!1:t.surface?.app_surface==="webdriver"||Ge.bug_hunt_browser===!0},activity:{status:Jt.status,step:Cv,agents:Jt.agents,finish:Jt.finish}}),{scheduledTests:lu,bugHunts:Pi}}async function Ine(e){let t=Mi(),n=[];for(let r of e.jobs??[])await pu.get(r.kind,r.id)&&n.push(r);await Promise.all([t.bugHunts.sync(n),t.scheduledTests.sync(n)]);for(let r of e.assignments??[]){if(r.type==="bug_hunt.grant"&&!await t.bugHunts.stage(r))continue;let o=`${r.type}:${r.grant_id??r.session_id??r.run_id}`;Tv.has(o)||cu.set(o,r)}qN()}function qN(){kv||Xt||(kv=(async()=>{let e=Mi();for(;cu.size&&!Xt;){let[t,n]=cu.entries().next().value;cu.delete(t),Tv.add(t);try{if(n.type==="bug_hunt.grant")await e.bugHunts.configure(n);else if(n.type===Of)await e.scheduledTests.configure(n);else if(n.type===N_)await e.bugHunts.handle(n);else if(n.type===Rf)await e.scheduledTests.handle(n);else throw new Error(`Unsupported cached work ${n.type}. Update the connector before accepting it.`)}catch(r){console.error(`Caching connector work: ${r.message}`)}finally{Tv.delete(t)}}})().finally(()=>{kv=null}))}async function WN(){if(!(!P.connector_id||!P.token||Xt))return su||(su=(async()=>{let e=Mi();await Promise.all([e.bugHunts.start(),e.scheduledTests.start()]);let t=await pu.list();for(let n of t)if(n.kind==="bug_hunt_grant"&&n.status==="provisioning"){let r=n.checkpoint?.pending_context??n.assignment;cu.set(`bug_hunt.grant:${n.id}`,r)}qN(),t.some(n=>["authorized","queued","running"].includes(n.status)&&Date.parse(n.execution_lease.expires_at)>Date.now())&&(YN(),Iv()),Wne()})().catch(e=>{throw su=null,e}),su)}async function jne(){let e=await $s(P.workspace).catch(()=>({service:null,jobs:[]}));return{version:qs,now:Date.now(),workspace:P.workspace,config_path:qn(P.workspace),config:P,agent:lt,automatic_worker_limit:ka(),worker_limit:zo(P.worker_limit),connection:{state:Nne(),server_url:P.server_url,last_error:jr||null},work:{assessments:[...Rn.values()].map(t=>({stage:t.stage,phase:t.phase,message:t.lastMessage,started_at:t.startedAt,pid:t.child?.pid??null,agent:lt.name})),prompts:[...Sn.values()].map(t=>({id:String(t.runId).slice(0,8),purpose:t.purpose,phase:t.phase,message:t.lastMessage,started_at:t.startedAt,pid:t.child?.pid??null,agent:lt.name})),integrations:Hs},runner:e,runtime_update:es.report(),health:ts?.health()??null,activity:uu.snapshot()}}function Nne(){return Xt||vo?"stopped":Vt?.readyState===WebSocket.OPEN?"connected":"connecting"}var Mne={async cancelPrompt(e){let t=[...Sn.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=>XN(e),setVerbose(e){return e===hh?`Detailed agent activity is already ${e?"on":"off"}.`:(Ov(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"?(es.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 es.command(e),bc(await es.refresh()))}};fu=VO({ui:Jt,snapshot:jne,actions:Mne});fu&&console.log(WO());await VN();var TN=new Set;async function VN(){if(Xt||vo)return;console.log(`Connecting ${P.name} to ${P.server_url}`),vo=!1,jr=void 0;let e=new WebSocket(P.server_url);Vt=e;let t=Zk(e,P.server_url,{onTimeout:r=>{Vt===e&&(jr=r,console.error(r),Ev())}});BN=t,e.addEventListener("open",()=>{if(Vt!==e){e.close();return}try{if(Wk(Vt,e,Di))return;throw new Error("The WebSocket was not open when authentication started.")}catch(r){jr=gn(r),console.error(`Could not authenticate the WebSocket connection: ${jr}`);try{e.close()}catch{}Ev()}}),e.addEventListener("message",r=>{if(Vt!==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: ${gn(s)}`)})});let n=async r=>{if(r.type==="authenticated"&&r.connector?.capabilities?.http_updates!==!0){Xt=!0,vo=!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=du?.connector_id===r.connector.id;if(P=Vb(P,du,r.connector.id,r.token),await br(P),r.connector?.capabilities?.http_updates!==!0){Xt=!0,vo=!0,console.error("Pairing saved. Update the EngineerOS backend for HTTP updates, then start this connector again."),e.close();return}Di={type:"authenticate",connector_id:P.connector_id,token:P.token,capabilities:Ge},console.log(s?`Reconnected existing workspace connector ${P.connector_id}; assessment history is preserved.`:`Paired. Connector ${P.connector_id} is online.`),IN(r);return}if(r.type==="authenticated"){t();let s=P.hunt_host?"Bug Hunter sessions":"EngineerOS runs";console.log(nc?`Reconnected after ${Qe(Date.now()-nc)} offline; waiting for ${s}.`:`Connected and waiting for ${s}.`),nc=void 0,IN(r);return}if(r.type==="provider.login"||r.type==="provider.logout"){mh||Dne(r);return}if(r.type==="workspace.refresh"){rc();return}if(r.type==="workers.update"){try{console.log(`EngineerOS changed the workers. ${await XN(r.worker_limit??"auto")}`)}catch(s){console.error(`Workers were not changed: ${s.message}`)}return}if(r.type==="logging.update"){Ov(r.activity_log_enabled===!0);return}if(r.type==="tools.update"){let s=r.provider_id==="playwright"&&["setup","upgrade","rollback"].includes(r.action);s&&(Qo=!1,Ge.bug_hunt_browser=!1,Qn());try{Ge.tool_inventory=await nl(P.workspace,r,void 0,{confirmLocal:i=>fu?.confirm(i)??!1,log:dh}),s&&(Qo=!0),Ge.bug_hunt_browser=$i(Ge.tool_inventory)&&Qo,e.send(JSON.stringify({type:"tools.updated",command_id:r.command_id,inventory:Ge.tool_inventory})),Qn(),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 Xg(P.workspace,r,{onStatus:async()=>{Ge.tool_inventory=await pr(P.workspace),Qn()}});Ge.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:Ge.tool_inventory})),Qn(),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"){ta(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===gN){Fs(Tne(r).then(s=>(s.error&&console.error(`${r.provider} ${r.operation} failed: ${s.error}`),yN(P,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}`;Ww(tc,Rn.get(s),r)==="deferred"&&console.log(`Assessment stage ${r.stage} is already running here; EngineerOS will be answered when it finishes.`),hu();return}if(r.type==="prompt.execute"){let s=Sn.get(r.prompt_id);s?eM(r)>s.executionRevision&&await Jne(s,r):QN(r);return}if(r.type==="prompt.cancel"){let s=Sn.get(r.prompt_id);s&&await jv(s);return}if(r.type==="agent.warm"){Bne(r);return}if(r.type==="run.available"){if(P.hunt_host){console.error("A hunt host cannot run Goals. Use Connect your code to pair a repository connector.");return}try{let s=await FN.dispatch(r);s.blocked?console.error(s.message):console.log(`Goal ${r.run_id} queued for the independent runner. Logs: ${un.join(P.workspace,".engineeros","runs",r.run_id,"activity.log")}`)}catch(s){console.error(`Goal dispatch failed: ${gn(s)}`)}return}if(r.type==="delivery.task.start"||r.type==="delivery.task.cancel"){if(P.hunt_host)throw new Error("Pair a repository connector before dispatching delivery tasks.");await X1(P.workspace,P.connector_id,r),await Si(P.workspace);return}if(r.type==="goal.cleanup"){try{await pR(P.workspace),await Si(P.workspace)}catch(s){console.error(`Goal cleanup is pending: ${s.message}`)}return}if(r.type==="run.accepted"){Zne(r);return}if(r.type==="run.cancelled"){await gy(P.workspace,r.run_id);return}if(r.type===KE){Za??=xg({getConfig:()=>P,onTestsCommitted:()=>rc()}),Fs(Za.handle(r));return}if(r.type===YE){Za??=xg({getConfig:()=>P,onTestsCommitted:()=>rc()}),await Za.cancel(r);return}if(r.type===N_){Fs(Mi().bugHunts.handle(r)).catch(s=>console.error(`Bug Hunter assignment: ${s.message}`));return}if(r.type==="bug_hunt.grant"){Fs(Mi().bugHunts.configure(r)).catch(s=>console.error(`Bug Hunter settings: ${s.message}`));return}if(r.type===Ij){Pi?.stop(r);return}if(r.type===Rf){Fs(Mi().scheduledTests.handle(r)).catch(s=>console.error(`Scheduled test assignment: ${s.message}`));return}if(r.type===Of){Fs(Mi().scheduledTests.configure(r)).catch(s=>console.error(`Scheduled test settings: ${s.message}`));return}if(r.type===dI){mv??=vI({getConfig:()=>P}),Fs(mv.handle(r));return}if(r.type===pI){await mv?.cancel(r);return}if(r.type===SI){EN??=kI({getConfig:()=>P,isIdle:()=>Gs(),agentTurn:UT}),Fs(EN.handle(r));return}if(r.type==="connector.update"){Pne(e,r);return}if(r.type==="connector.disconnect"){console.log(r.message),await sc();return}if(r.type==="connector.revoked"){Xt=!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||(Bs=!1);return}if(r.type==="connection.error"){vo=!0,console.error(`EngineerOS: ${r.message}`);return}let o=String(r.type??"(missing)").replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,120);TN.has(o)||(TN.add(o),console.warn(`Unknown EngineerOS message type ${o}; connector ${qs}. Update the connector and backend to compatible versions.`))};e.addEventListener("close",r=>{if(t(),Vt!==e||Qa)return;let o=Vk(r);if(!o.retry||vo||Xt){console.error(o.message),o.retry&&vo&&console.error("Connection rejected. Create a new pairing command in EngineerOS if this connector was revoked."),sc();return}jr=jr?`${o.message} ${jr}`:o.message,Ev()}),e.addEventListener("error",r=>{Vt===e&&(jr=qk(r),console.error(`WebSocket connection to ${P.server_url} failed: ${jr}`))})}async function Pne(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=es.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 es.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 Dne(e){let t=e.request_id,n=e.type==="provider.logout"?"logout":"login";mh=!0,console.log(`Starting interactive ${lt.name} provider ${n}.`);try{await(n==="logout"?Yk:Kk)(lt,P.workspace),lt=await ml(P,P.workspace),Ge=gf(P,lt,Ge.tool_inventory,{secretNames:await HN()}),Di.capabilities=Ge,Vt.readyState===WebSocket.OPEN&&(Vt.send(JSON.stringify({type:`provider.${n}.completed`,request_id:t,session:Ge.agent_session})),Vt.close(1e3,`Provider ${n} completed`)),console.log(`${lt.name} provider ${n} completed.`)}catch(r){let o=gn(r).slice(0,500);Vt.readyState===WebSocket.OPEN&&Vt.send(JSON.stringify({type:`provider.${n}.failed`,request_id:t,message:o})),console.error(`Provider ${n} failed: ${o}`)}finally{mh=!1}}function Ev(){if(Xt||vo||uh)return;let e=jr?` Last error: ${jr}`:"",t=nc?` Offline for ${Qe(Date.now()-nc)}.`:"";nc??=Date.now(),console.error(`Connection unavailable.${e}${t} Retrying in ${Math.round(iu/1e3)}s.`),uh=setTimeout(()=>{uh=void 0,VN()},iu),iu=Math.min(3e4,iu*2)}async function rc(){if(!P.hunt_host&&!(Bs||Vt.readyState!==WebSocket.OPEN)){Bs=!0,console.log("Inspecting the workspace without executing its code.");try{let e=await y1(P.workspace),t=await w1(P.workspace,P.last_head_reported??P.last_snapshot_head,e.head_revision).catch(()=>null);t&&(e.changed_since=t);let n=await fetch(Mn(P.server_url,P.connector_id),{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${P.token}`},body:JSON.stringify(e)});if(!n.ok)throw new Error(await ia(n,"the workspace"));let r=await n.json(),o=r.source_revision;P={...P,onboarding_pending:!1,last_snapshot_head:e.head_revision??P.last_snapshot_head,last_head_reported:e.head_revision??P.last_head_reported,last_head_branch:e.head_revision?e.branch??null:P.last_head_branch},await br(P),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 ${r.workspace_kind}. Start the baseline assessment in EngineerOS to continue.`);let{encoded:s,stats:i}=await u_({workspace:P.workspace,connectorId:P.connector_id,snapshot:e,refresh:Ki,buildMap:(a,c)=>Sf(P.workspace,a,{head:c.head_revision,branch:c.branch}),log:a=>console.error(a)});if(s&&o){let a=await fetch(Kb(P.server_url,P.connector_id),{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${P.token}`},body:JSON.stringify({source_revision:o,quality_map_base64:s.base64})});a.ok?await kf(P.workspace,P.connector_id,s.map).catch(()=>{}):console.error(await ia(a,"the workspace quality map"))}i&&console.log(`Built the local context index: ${i.total_files.toLocaleString()} file(s) ready for assignment context.`),Bs=!1}catch(e){Bs=!1,console.error(`Workspace assessment failed: ${gn(e)}`)}}}var Lne=8e6,RN,ON="";async function Une({current:e,previous:t}){if(Bs||Vt?.readyState!==WebSocket.OPEN)throw new Error("A snapshot is running or the connection is down.");let n=un.resolve(P.workspace),r=async()=>{P={...P,last_head_reported:e.head,last_head_branch:e.branch??null},await br(P)},o=await l_(P.workspace,P.connector_id),s=async()=>{if(await rc(),P.last_head_reported!==e.head)throw new Error("The snapshot did not report this commit.")};if(!o)return s();let{index:i}=await Ki(P.workspace,P.connector_id),a=null,c=await OC({previous:{head:t.head,branch:t.branch??null},current:e,compare:(d,f)=>Qw(P.workspace,d,f),inventoryDelta:d=>C0(n,Object.entries(i.files).map(([f,h])=>({path:f,size:h.size})),d),mapDelta:async()=>(a=await Sf(P.workspace,i,{head:e.head,branch:e.branch}),c_(o,a)),contentHead:(await ud(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)>Lne)return s();let u=await fetch(Yb(P.server_url,P.connector_id),{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${P.token}`},body:l});if(!u.ok)throw new Error(await ia(u,"the new commit"));let p=await u.json().catch(()=>({}));if(p.needs_snapshot)return s();await r(),a&&await kf(P.workspace,P.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 Fne(){P.hunt_host||P.onboarding_pending||Bs||Vt?.readyState!==WebSocket.OPEN||(RN??=RC({readHead:()=>TC(P.workspace),getLastReported:()=>({head:P.last_head_reported??P.last_snapshot_head,branch:P.last_head_branch}),onChange:Une,onError:e=>{e.message!==ON&&(ON=e.message,console.error(`The new commit could not be reported yet: ${gn(e)}`))}}),RN.poll().catch(()=>{}))}var zne=6e4,CN=0;async function Bne(e){if(P.hunt_host)return;let t=typeof e.session_key=="string"?e.session_key.trim():"",n=t?P.sessions?.[t]:void 0,r=[];Date.now()-CN>zne&&(CN=Date.now(),r.push(Ki(P.workspace,P.connector_id).catch(o=>console.error(`Context index refresh ahead of a conversation failed: ${o.message}`)))),P.agent_protocol==="acp"&&r.push(P$(P.workspace,P,{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(`${lt?.name||"The agent"} could not be started ahead of the conversation: ${o.message}`))),await Promise.all(r)}function Qn(){Sv||Xt||!P.connector_id||!P.token||(Sv=Gne().catch(e=>console.error(`Connector synchronization: ${e.message}`)).finally(()=>{Sv=null}))}async function Gne(){let e=o1(Rn),t=await pu.snapshot();AN.update({type:"assessment.workers",assessment_workers:e,tool_inventory:Ge.tool_inventory,runtime_update:Ge.runtime_update,agent_session:Ge.agent_session,bug_hunt_browser:Ge.bug_hunt_browser,connector_jobs:t.jobs,...$p(P.worker_limit)}),await AN.flush()}async function XN(e){let t=zo(e);return t===zo(P.worker_limit)?t===null?"Workers are already automatic.":`Workers are already set to ${t}.`:(P={...P,worker_limit:t},await br(P),hu(),Qn(),t===null?`Workers are automatic again: up to ${ka()} side by side for this machine's CPU and memory, for ${Fl} (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: ${Fl}. A Goal that uses your working folder still runs alone. Running work finishes; waiting work starts as workers free up.`)}function Ov(e){if(e!==hh){if(hh=e,!e)for(let t of Rn.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."),Qn()}}function Cv(e,t,n=null){Jt.step(e,t,n)&&hh&&console.log(`[${e}] ${n?`${n}: `:""}${t}`)}function Hne(){clearInterval(ch);let e=!1,t=()=>{e||Rn.size>0||Sn.size>0||(e=!0,ic(P,P.workspace).finally(()=>{e=!1}))};t(),ch=setInterval(t,kne),ch.unref?.()}async function ic(e,t,n=ts?.healthChecks()??[]){let r=await OO({config:e,workspace:t,version:qs,insights:n,agentSession:Ir,probes:{inspectAgent:(o,s)=>Xt?lt:ml(o,s),inspectTools:o=>Xt?Ge.tool_inventory:pr(o),runnerStatus:$s}});try{DN=(await CO(e,r,Go))?.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 JN(e){if(Xt)return Qa;let t=e instanceof Error?e.message:String(e),n=await ic(P,P.workspace).catch(()=>null);n&&console.error(Zy(n)),vt(t)}function IN(e){Ov(e.connector?.activity_log_enabled===!0),oc=e.project_url??null,iu=1e3,YN(),Iv(),es.confirm().catch(t=>console.error(`Connector update state: ${t.message}`)),WN().catch(t=>console.error(`Saved connector work: ${t.message}`)),P.onboarding_pending&&rc()}var au=null,Qo=!1,KN=0,qne=Date.now();async function YN(){return au||(au=(async()=>{GN&&await w$(P.workspace,{log:t=>console.log(`[tools] ${t}`)}).catch(t=>console.error(`[tools] Tool updates were skipped: ${t.message}`));let e=Date.now();try{dh("Preparing Bug Hunter's browser: Playwright, then a check that a browser starts. The first setup can take a few minutes."),await xR(P.workspace,{log:dh}),Qo=!0,Ge.tool_inventory=await pr(P.workspace),Ge.bug_hunt_browser=$i(Ge.tool_inventory)&&Qo,dh(`Bug Hunter's browser is ready (${Qe(Date.now()-e)}).`)}catch(t){console.error(`[browser] Bug Hunter's browser setup failed after ${Qe(Date.now()-e)}: ${t.message}`),Ge.bug_hunt_browser=!1}Qn()})(),au)}function dh(e){console.log(`[browser] ${e}`)}async function Iv(){if(Ir?.state!=="checking"){KN=Date.now(),Ge.agent_session={...Ge.agent_session,status:"checking",message:`Checking that ${lt.name} can answer.`},Qn(),Ir={state:"checking",detail:`Asking ${lt.name} one question to confirm its session.`},console.log(`Checking that ${lt.name} can answer before accepting work.`);try{await l1(P,lt.name),Ir={state:"ready",detail:`${lt.name} answered; its session is usable.`},Ge.agent_session={...Ge.agent_session,status:"authenticated",message:Ir.detail},console.log(Ir.detail)}catch(e){Ir={state:"failed",detail:e instanceof Error?e.message:String(e),remedy:P.hunt_host?AR(P.agent_id||P.agent_protocol):ya(P.agent_id||P.agent_protocol)},Ge.agent_session={...Ge.agent_session,status:"logged_out",message:Ir.remedy},console.error(`${Ir.detail}
|
|
1183
1183
|
${Ir.remedy}`)}Qn(),await ic(P,P.workspace).catch(()=>null)}}function Wne(){clearInterval($v);let e=!1,t=0,n=0,r=!1,o=()=>{es.tick(),Vne(),Fne(),P.hunt_host&&au&&Date.now()-KN>=$R(qne)&&Sn.size===0&&Rn.size===0&&!(Pi?.active>0)&&Iv(),!P.hunt_host&&!r&&Ml(hv.id)&&(r=!0,FN.flush().then(()=>ah(hv)).catch(s=>ih(hv,s)).finally(()=>{r=!1})),Qn(),!P.hunt_host&&!bo&&Date.now()-t>=xne&&Ml(dv.id)&&(t=Date.now(),ZN().then(()=>ah(dv)).catch(s=>ih(dv,s))),!P.hunt_host&&DN&&!lh&&Ml(pv.id)&&Date.now()-zN>=Rx&&(lh=!0,Xne().then(()=>ah(pv)).catch(s=>ih(pv,s)).finally(()=>{lh=!1})),!e&&Date.now()-n>=$ne&&Ml(fv.id)&&(e=!0,n=Date.now(),pr(P.workspace).then(async s=>{if(Ge.tool_inventory=s,!Qo&&$i(s))try{await(await ti(await Cs(P.workspace))).close(),Qo=!0}catch{Qo=!1}Ge.bug_hunt_browser=$i(s)&&Qo,Qn(),ah(fv)}).catch(s=>ih(fv,s)).finally(()=>{e=!1}))};o(),$v=setInterval(o,1e4),Hne()}async function Vne(){if(!(!GN||P.agent_protocol!=="acp"||!P.agent_id||vv||Ir?.state==="checking"||Date.now()-xN<Ane)){vv=!0;try{if(!await Gs())return;xN=Date.now();let e,t=await H$(P,{verify:async r=>{e=await ml(r,P.workspace)},log:r=>console.log(`[agent] ${r}`)});if(t===P||Xt)return;P={...t,execution_profiles:e.executionProfiles??null},await br(P),lt=e;let n=gf(P,lt,Ge.tool_inventory);if(Object.assign(Ge,{agent_name:n.agent_name,agent_version:n.agent_version,execution_profiles:n.execution_profiles}),Di.capabilities=Ge,!await Gs())return;await rl(),Vt?.readyState===WebSocket.OPEN&&Vt.close(1e3,"Coding agent updated")}catch(e){console.error(`[agent] The agent update check failed: ${e.message}`)}finally{vv=!1}}}function ih(e,t){let n=EO(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 ah(e){xO(e.id)&&console.log(`${e.title} recovered.`)}async function Xne(){if(P.hunt_host||!await Gs())return;zN=Date.now();let{jobs:e}=await $s(P.workspace).catch(()=>({jobs:[]})),t=await Ox(P.workspace,{jobs:e});if(!Cx(t))return;let n=`${t.fingerprint}:${_v.join(",")}`,r=yv?.key===n,o=r?yv.candidates:await m1(P,t,_v);yv={key:n,candidates:o};let s=await Ni(Nx(t,o,{version:qs}));Array.isArray(s?.refused)&&(_v=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 zs=null,jN=null;async function ZN(){if(!P.hunt_host){if(bo)return bo;bo=(async()=>{let e=await bx(P,{knownRevision:zs?.revision??null});if(e.unchanged||(zs=e),jN===zs.revision)return zs;let{jobs:t}=await $s(P.workspace);return!t.some(r=>fh.includes(r.status))&&Hs===0&&Rn.size===0&&(await Hd(P.workspace,zs),jN=zs.revision),zs})();try{return await bo}finally{bo=null,hu()}}}function NN(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)),Sn.get(e)?.events.push(n)}var MN=null;function hu(){let e=Vt.readyState===WebSocket.OPEN,t=Rn.values().next().value,n=zo(P.worker_limit)??Math.min(ka(),Vw(t?.workerLimit??tc[0]?.worker_limit)),r=e&&!bo&&Hs===0?JT(tc,Rn.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:Vw(s.worker_limit),lastActivityAt:Date.now(),eventCount:0,lastDetail:null};Rn.set(i,a),Yne(s,a)}r.length>0&&Qn();let o=KT({queued:tc,running:Rn.size,workerLimit:n,connected:e,designSync:!!bo,integrations:Hs});o&&o!==MN&&console.log(o),MN=o}function gh(e){let t=Xw(e);return t?`${lt.name} on ${t}`:lt.name}async function QN(e){let t=e.prompt_id,n=`prompt:${String(t).slice(0,8)}`,r=e.purpose||"project",o=Date.now(),s=`${r} \xB7 ${gh(e)}`,i=c1(e,lt.name),a={runId:t,purpose:r,startedAt:o,child:null,controller:null,cancelled:!1,stoppedHere:!1,cancellation:new AbortController,events:T1(Ni),executionRevision:eM(e),sessionKey:Ap(e),sessionId:null,phase:"preparing",lastMessage:s,replacement:null};Sn.set(t,a);let c=A1(Ni,{type:"prompt.heartbeat",prompt_id:t,execution_revision:a.executionRevision},{onError:w=>console.error(`[${n}] Prompt heartbeat: ${w.message}`)}),l,u=w=>{let y=w?JSON.stringify(w):null;!y||y===l||Sn.get(t)!==a||(l=y,NN(t,w))},p=Number(e.answer_within_seconds),d=p>0?o+p*1e3:void 0;console.log([`[${n}] ${i} for ${r}.`,`${lt.name} can reason for several minutes without reporting a step.`,...d?[kh(d,o)]:[]].join(" ")),NN(t,{kind:"status",message:i}),Jt.status(n,s,o,{link:oc,answerBy:d,phase:a.phase});let f=w=>{let y=WT(w),b=qT(w),_=yi(w);Sn.get(t)===a&&(b&&(a.phase=b),(_??y?.message)&&(a.lastMessage=_??y?.message),Jt.status(n,a.lastMessage,o,{link:oc,answerBy:d,phase:a.phase}),Cv(n,_??y?.message));let m=w.type==="forge.output"?null:_;u(y??(m?{kind:"status",message:m}:null))},h="failed",g=[r];try{Tp(e)||(f({type:"connector.step",message:"Syncing the design context from EngineerOS"}),e={...e,design_context:await $x(ZN,{pinned:!!e.local_design_context,last:zs,onFallback:(_,m)=>f({type:"connector.step",message:`Design context not refreshed (${_.message}); continuing with ${m?"the copy synced earlier":"none"}`})})});let w=await DT(e,P,{onProcess:_=>{Sn.get(t)===a&&(a.child=_)},onController:_=>{Sn.get(t)===a&&(a.controller=_)},onSession:_=>{a.sessionId=_},onEvent:f},{signal:a.cancellation.signal});if(a.stoppedHere)throw new Error(PN);let y=w.singleTurn?Xb(P.sessions,w.sessionKey):Jh(P.sessions,w.sessionKey,w.sessionId);if(JSON.stringify(y)!==JSON.stringify(P.sessions||{})&&(P={...P,sessions:y},await br(P)),a.cancelled)return;await a.events.close().catch(_=>{console.error(`[${n}] Prompt progress delivery: ${_.message} The agent has finished; submitting its complete response separately.`)});let b=await Rp(Ni,{type:"prompt.completed",prompt_id:t,execution_revision:a.executionRevision,content:w.content,model:w.model,session_id:w.sessionId,usage:w.usage});b||console.error(`[${n}] ${ny}`),uu.record("prompt","completed",{durationMs:Date.now()-o,usage:w.usage}),h=b?"finished":"undelivered",g=[Su(w.usage),r]}catch(w){let y=a.stoppedHere?PN:gn(w);if(uu.record("prompt","failed",{durationMs:Date.now()-o}),a.stoppedHere&&(h="cancelled"),!a.cancelled){try{await Rp(Ni,{type:"prompt.failed",prompt_id:t,execution_revision:a.executionRevision,message:y})||console.error(`[${n}] ${ny}`)}catch(b){console.error(`[${n}] Prompt failure delivery: ${b.message}`)}console.error(y)}}finally{await c.stop(),a.events.stop();let w=a.replacement;w?(h="replaced",g=[`continuing on ${gh(w)}`,r]):a.cancelled&&(h="cancelled"),Jt.finish(n,h,g),Sn.get(t)===a&&Sn.delete(t),w&&Kne(a,w)}}var PN="Cancelled from the connector terminal by the person running it.";async function jv(e){e.cancelled=!0,e.cancellation.abort(),await e.controller?.completed.catch(()=>{})}function eM(e){return Number(e.execution_revision)||1}async function Jne(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 ${gh(t)}.`),await jv(e))}function Kne(e,t){e.sessionId&&(P={...P,sessions:Jh(P.sessions,e.sessionKey,e.sessionId)},br(P).catch(n=>console.error(`Could not save the agent session: ${n.message}`))),QN(t)}async function Yne(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 ${gh(e)}.`),!wv.has(n)){wv.add(n);try{let v=await BT(P.workspace);if(!v.exists)console.log("No accepted assessment exists yet; this run establishes the baseline.");else{let k=v.accepted_head_revision?v.current_head_revision?v.current_head_revision!==v.accepted_head_revision?`The workspace is now at commit \`${v.current_head_revision}\`; the accepted assessment is from \`${v.accepted_head_revision}\`.`:"The accepted assessment is already at the current commit.":`The accepted assessment is from \`${v.accepted_head_revision}\`; the current commit could not be read.`:"Its accepted commit is unavailable; this run will refresh that provenance.";console.log(`Last accepted assessment covers ${v.stages.length||"no"} section(s). ${k}`)}}catch(v){console.error(`Assessment freshness check failed: ${v.message}`)}}let o=t.startedAt,s=`assessment:${r}`,i=!1,a=!1,c=5,l=!1,u=!1,p=null,d=null,f=null,h=new Set,g=()=>!Xt&&Rn.get(t.key)===t,w=async v=>{try{return await Rp(Ni,v)||console.warn(`[${s}] ${x1}`),!0}catch(k){return console.error(`Assessment failure delivery: ${k.message}`),!1}},y=(v,{milestone:k=!0}={})=>{if(!g()||k&&f===v)return;k&&(f=v,h.has(v)||(h.add(v),c=Math.min(90,c+10)),console.log(`[assessment:${r}] ${v}.`));let S=String(v).slice(0,500);t.progressPercent=c,t.lastMessage=S,Jt.status(s,S,o,{link:oc,phase:t.phase})};y(`Starting ${r} assessment stage`);let b=setInterval(()=>{let v=Date.now(),k=v-t.lastActivityAt,S=i&&!a?HT(r,k):null;if(!p&&S){p=S,console.error(`[assessment:${r}] ${p}`),Zw(t.controller,t.child);return}p||ts.observe({at:v,level:"info",message:Jt.status(s,`${t.lastMessage} \xB7 last agent activity ${Qe(k)} ago (${t.eventCount.toLocaleString()} events)`,o,{phase:t.phase})})},15e3),_={onSession:async v=>{g()&&(d=String(v),await FS(P.workspace,n,r,v,{sourceRevision:e.source_revision,targetHeadRevision:e.target_head_revision}))},onController:v=>{g()&&(t.controller=v)},onProcess:v=>{g()&&(t.child=v,i=!0,t.phase!=="correcting"&&(t.phase="running",y("Connected agent process started")),t.lastActivityAt=Date.now())},onEvent:v=>{t.lastActivityAt=Date.now(),t.eventCount+=1;let k=GT(v);if(k&&y(k),!g())return;let S=yi(v);!S||S===t.lastDetail||(t.lastDetail=S,Cv(s,S))}},m=(v,k)=>Hw(v,k,P,_,{draftPath:un.relative(P.workspace,un.join(cr(P.workspace,n),v.report_file)).split(un.sep).join("/")});try{let v=gv-Date.now();v>0&&(y(`Waiting ${Math.ceil(v/1e3)}s for the model provider's rate limit to clear`),await new Promise(C=>setTimeout(C,v+Math.floor(Math.random()*3e3)))),e.assessment_mode==="incremental"&&(c=15,y("Calculating changed files and affected behavior"));let k=await qS(P.workspace,e),S=await Um(P.workspace,n,r,{expectedHeadRevision:e.target_head_revision,expectedSourceRevision:e.source_revision});if(S)m(S,k),y("Recovered completed stage report from connector storage");else{if(d=await zS(P.workspace,n,r,{expectedHeadRevision:e.target_head_revision,expectedSourceRevision:e.source_revision}),d&&y("Restoring interrupted agent session"),S=await PT(k,P,_,{previousSessionId:d}),p)throw new Error(p);a=!0,await Lm(P.workspace,n,k,S)}a=!0,t.phase="delivering",t.progressPercent=95,t.lastMessage=r==="synthesis"?"Delivering completed assessment bundle":"Checkpointing connector-local stage result";let E=C=>fetch(Qb(P.server_url,P.connector_id,n),{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${P.token}`},body:JSON.stringify(C),signal:AbortSignal.timeout(bT)}),O=await a1(S,{submit:C=>i1(C,E,{isActive:()=>g()&&!Xt,onRetry:(N,x)=>{y("Completed result is waiting for EngineerOS",{milestone:!1}),console.warn(`[assessment:${r}] Completed result delivery failed: ${gn(N)} Retrying in ${Math.round(x/1e3)}s without rerunning the agent.`)}}),payloadFor:C=>r==="synthesis"?Fm(P.workspace,n,C,{expectedSourceRevision:e.source_revision}):JS(C),rejectionFor:C=>ia(C,"the assessment"),correct:async(C,N)=>{if(a=!1,t.phase="correcting",t.lastMessage="Correcting a rejected stage result",!C.correctAfterRejection)throw new Error(`${N} The connector could not start the required agent correction.`);return C.correctAfterRejection(N)},onCorrected:async C=>{if(p)throw new Error(p);a=!0,await GS(P.workspace,n,r);let N=await Lm(P.workspace,n,k,C);return m(N,k),t.phase="delivering",t.lastMessage="Delivering corrected stage result",N}});if(p)throw new Error(p);S=O.result;let I=O.response;if(!I.ok)throw new Error(await ia(I,"the assessment"));if(l=!0,uu.record("assessment stage","completed",{durationMs:Date.now()-o,usage:S.usage}),r==="synthesis"){let C=await I.json(),N=await WS(P.workspace,n,e,S,C.report_markdown);console.log(`Workspace assessment ${n} was accepted by EngineerOS and saved to ${un.relative(P.workspace,N)}.`);try{let x=await $u(P.workspace);x.committed&&console.log(`Assessment committed to Git as ${x.revision.slice(0,8)}.`)}catch(x){console.error(`The assessment is saved locally but could not be committed to Git: ${x.message}`)}}else console.log(`Workspace assessment stage ${r} was checkpointed by EngineerOS.`)}catch(v){let k=p||gn(v),S=e1(e,v),E=r1(v),A=ZT(v);E&&(await BS(P.workspace,n,r).catch(I=>{console.error(`[assessment:${r}] Could not discard the unusable agent session checkpoint: ${I.message}`)}),d=null);let O=!p&&(d||E)&&(E||YT(v))&&S<A;if(g()&&O){t.phase="starting",t.lastMessage=E?"Agent session became unusable; restarting from saved assessment work":"Agent session interrupted; resuming checkpoint",t.resumeAssignment=t1(e,v);let I=n1(v,S);gl(v)&&(gv=Math.max(gv,Date.now()+I)),console.warn(`[assessment:${r}] ${E?"Agent session became unusable":"Agent session interrupted"}: ${k} ${E?"Starting a fresh session from the saved draft":`Resuming session ${d}`} in ${Math.round(I/1e3)}s (${S+1}/${A}).`),await new Promise(C=>setTimeout(C,I))}else g()&&(u=await w({type:"workspace.assessment.failed",assessment_id:n,stage:r,message:k}));O||(uu.record("assessment stage","failed",{durationMs:Date.now()-o}),console.error(`[assessment:${r}] ${k}`))}finally{clearInterval(b),Jt.clearStatus(s),r==="synthesis"&&l&&wv.delete(n),g()&&(Rn.delete(t.key),s1(tc,t,{accepted:l,failureReported:u})&&console.log(`Resuming interrupted agent session for assessment stage ${r} from its checkpoint.`),hu())}}async function Zne(e){let t=String(e.run_id||"");Hs+=1;try{bo&&await bo;let n=await TT(P.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 rc();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: ${gn(n)}`)}finally{Hs-=1,hu()}}function Qne(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{vt('--agent-args must be a JSON array, for example: --agent-args "[\\"acp\\"]"')}}function vt(e){console.error(e),process.exit(1)}WN().catch(e=>console.error(`Saved connector work: ${e.message}`));
|