@engineeros/connector 1.42.0 → 1.42.4
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.
|
@@ -263,7 +263,7 @@ A report file a Proof writes, such as JUnit XML, is read and then removed: do no
|
|
|
263
263
|
`)}function Ob({passed:e,failed:t}){return e===0&&t===0}function gn(e){return e.exit_code!==0||Ob(e)}function Gu(e){return e.exit_code===Pu?"environment":"implementation"}function Hu(e,t){let n=new Map(t.map(r=>[r.proof_index,r.test_run]));return e.map(r=>{let o=n.get(r.proof_index);if(!o)return r;let s={...r,exit_code:o.exit_code,test_run:o};if(!gn(o))return s;let i=o.exit_code===0?"ran no tests (0 passed, 0 failed)":`exited with code ${o.exit_code}${jb(o)}`;return{...s,status:"failed",output_excerpt:`Command \`${o.command}\` ${i}.
|
|
264
264
|
${o.log_excerpt.slice(-1500)}`}})}function jb({passed:e,failed:t,skipped:n}){return e===null?"":` (${e} passed, ${t} failed, ${n} skipped)`}var Nb=200,Mb=4,mn={name:300,file:500,covers:1e3,command:2e3,evidence:1e3},Pb=500,Lb=["unit","smoke","e2e_integration","security"],Bu=new Map([["unit","unit"],["smoke","smoke"],...["e2e","end-to-end","end to end","integration","e2e/integration","e2e-integration","e2e_integration"].map(e=>[e,"e2e_integration"]),...["pen-test","pentest","pen test","penetration","security"].map(e=>[e,"security"])]),Db=new Map([["passed","passed"],["pass","passed"],["failed","failed"],["fail","failed"],["blocked","blocked"],["manual","manual"],["not run","not_run"],["skipped","not_run"]]),Fb=/^[\s*_`"'[(]*(passed|pass|failed|fail|blocked|manual|not[\s_-]*run|skipped)(?![a-z0-9_])/i,zb=new Set(["","none","n/a","-"]),Ub=/^[ \t]*[-*][ \t]+\**(Category|Name|File|Covers|Command|Result|Evidence)\**[ \t]*:\**[ \t]*(.*)$/i,Gb=new Set(["command","evidence"]),Hb=/^[ \t]*(?:```|~~~)/;function hn(e,t){let n=ye(String(e??"").slice(0,t*4)).trim();return zb.has(n.toLowerCase())?null:n.slice(0,t).replace(/[\ud800-\udbff]$/,"")}function Bb(e){let t={},n=null,r=!1;for(let o of e){let s=o.replace(/\r$/,"");if(Hb.test(s)){r=!r;continue}let i=r?null:Ub.exec(s);if(i){let a=i[1].toLowerCase();n=a in t?null:a,n&&(t[a]=i[2])}else n&&Gb.has(n)&&t[n].length<mn[n]*4&&(t[n]+=`
|
|
265
265
|
${s}`)}return t}function qb(e){let t=String(e??"").trim(),n=Fb.exec(t);if(!n)return null;let r=n[1].toLowerCase().replace(/[\s_-]+/g," "),o=Db.get(r)??"not_run",s=t.length>n[0].length?t:null;return{result:o,detail:o==="failed"||o==="blocked"?s:null}}function Wb(e){let t=Bb(e),n=hn(t.name,mn.name),r=qb(t.result);if(!n||!r)return null;let{result:o}=r;return{category:Bu.get(String(t.category??"").trim().toLowerCase())??"other",name:n,file:hn(t.file,mn.file),covers:hn(t.covers,mn.covers),command:hn(t.command,mn.command),result:o,evidence:hn(t.evidence,mn.evidence)??hn(r.detail,mn.evidence)}}function Vb(e,t){let n=Bu.get(e.trim().toLowerCase());if(!Lb.includes(n))return null;let r=t.map(s=>/^- Reason:\s*(.*)$/i.exec(s.replace(/\r$/,""))?.[1]).find(s=>s!==void 0),o=hn(r,Pb);return o?{category:n,reason:o}:null}function qu(e){let t=String(e??""),n=/^## Test Inventory\s*$/im.exec(t);if(!n)return null;let r=t.slice(n.index+n[0].length).split(/^## /m)[0],o=[],s=[],i=r.split(/^### /m).slice(1);for(let c of i){let[l,...d]=c.split(`
|
|
266
|
-
`),p=/^not applicable\s*:\s*(.*)$/i.exec(l.trim());if(p){let u=Vb(p[1],d);u&&s.length<Mb&&!s.some(f=>f.category===u.category)&&s.push(u)}else if(o.length<Nb){let u=Wb(d);u&&o.push(u)}}return(i.length>0||/^[ \t]*[-*][ \t]+\**(?:Name|Result)\**[ \t]*:/im.test(r))&&!o.length&&!s.length?null:{cases:o,not_applicable:s}}import{createHash as SS}from"node:crypto";import{readFile as Xb}from"node:fs/promises";import De from"node:path";var Jb=1,Kb=768*1024,Yb=2e4,Qb=2e3,Wu=300,Vu=64,ia=new Set([".js",".jsx",".mjs",".cjs",".ts",".tsx"]),Zb=new Set([...ia,".py",".go",".java",".kt",".cs",".rb",".rs"]),Qu=/(^|\/)(tests?|__tests__|spec|specs|e2e|integration_tests|it)\//,eS=/(^|\/)(node_modules|__snapshots__|__mocks__|fixtures?|__fixtures__|testdata|vendor|dist|build)\//,tS=new RegExp([String.raw`\bassert\w*\b`,String.raw`\bexpect\w*\s*\(`,String.raw`\.should\b`,String.raw`\bpytest\.raises\b`,String.raw`\bself\.assert\w+`,String.raw`\bt\.(?:Error|Errorf|Fatal|Fatalf|Fail|FailNow)\b`,String.raw`\brequire\.\w+\(`,String.raw`\bAssert\.\w+`,String.raw`\bassert_(?:eq|ne)!`,String.raw`\bverify\s*\(`,String.raw`\bto(?:Have|Be|Equal|Contain|Match|Throw)\w*\s*\(`].join("|"),"g"),nS=[["e2e",["e2e","end-to-end","playwright","cypress"]],["integration",["integration","integration_tests","integration-tests"]],["smoke",["smoke"]],["contract",["contract","contracts","pact"]],["performance",["perf","performance","benchmark","benchmarks"]],["load",["load","k6","locust"]],["security",["security","pentest"]],["accessibility",["a11y","accessibility"]],["visual",["visual","screenshots"]],["regression",["regression"]]],rS={e2e:"e2e",integration:"integration",smoke:"smoke",sanity:"sanity",regression:"regression",security:"security",contract:"contract",performance:"performance",perf:"performance",benchmark:"performance",load:"load",stress:"stress",database:"database",db:"database",accessibility:"accessibility",a11y:"accessibility",visual:"visual",resilience:"resilience",api:"api"},oS=[["accessibility",/@axe-core\/|\baxe\.run\(|\bcheckA11y\(|AxeBuilder/],["visual",/\btoHaveScreenshot\(|\bmatchImageSnapshot\(/],["contract",/\bschemathesis\b|@pact-foundation\/|\bpact\b/],["load",/\bfrom\s+locust\b|from\s+["']k6(\/[\w-]+)?["']/],["database",/\btestcontainers\b|PostgresContainer|MySqlContainer/i]],Xu=[["pytest","python",/(^|[\s"'[,])pytest([<>=~!\s"',\]]|$)/m,"pytest",null],["pytest-asyncio","python",/\bpytest-asyncio\b/,null,null],["pytest-cov","python",/\bpytest-cov\b/,null,null],["hypothesis","python",/(^|[\s"'[,])hypothesis([<>=~!\s"',\]]|$)/m,null,null],["schemathesis","python",/\bschemathesis\b/,"schemathesis run","contract"],["locust","python",/(^|[\s"'[,])locust([<>=~!\s"',\]]|$)/m,"locust","load"],["bandit","python",/(^|[\s"'[,])bandit([<>=~!\s"',\]]|$)/m,"bandit -r .","security"],["pip-audit","python",/\bpip-audit\b/,"pip-audit","security"],["vitest","node",/"vitest"\s*:/,"vitest run",null],["jest","node",/"jest"\s*:/,"jest",null],["mocha","node",/"mocha"\s*:/,"mocha",null],["@testing-library/react","node",/"@testing-library\/react"\s*:/,null,"component"],["@playwright/test","node",/"@playwright\/test"\s*:/,"playwright test","e2e"],["cypress","node",/"cypress"\s*:/,"cypress run","e2e"],["@axe-core/playwright","node",/"@axe-core\/(playwright|react)"\s*:/,null,"accessibility"],["k6","node",/"k6"\s*:/,"k6 run","load"],["testify","go",/github\.com\/stretchr\/testify/,null,null],["junit","jvm",/junit-jupiter|<artifactId>junit<\/artifactId>|junit:junit/,null,null],["xunit","dotnet",/PackageReference\s+Include="xunit"/i,"dotnet test",null],["nunit","dotnet",/PackageReference\s+Include="NUnit"/i,"dotnet test",null],["rspec","ruby",/gem\s+["']rspec/,"bundle exec rspec",null]],sS=new Set(["package.json","pyproject.toml","setup.cfg","setup.py","pipfile","go.mod","pom.xml","build.gradle","build.gradle.kts","gemfile","cargo.toml"]),Zu=[[/^vitest\.config\.[cm]?[jt]s$/,"vitest"],[/^vitest\.workspace\.[cm]?[jt]s$/,"vitest"],[/^jest\.config\.[cm]?[jt]s$/,"jest"],[/^playwright\.config\.[cm]?[jt]s$/,"@playwright/test"],[/^cypress\.config\.[cm]?[jt]s$/,"cypress"],[/^pytest\.ini$/,"pytest"]];function sa(e){let t=De.posix.basename(e).toLowerCase();return sS.has(t)||/^requirements[\w.-]*\.txt$/.test(t)||t.endsWith(".csproj")}function iS(e,t){let n=t.replace(/[.*+?^${}()|[\]\\/]/g,"\\$&"),r=new RegExp(`"${n}"\\s*:\\s*"([^"]+)"`).exec(e)?.[1];if(r)return r;let o=new RegExp(`(?:^|["'\\s,\\[])${n}\\s*(?:\\[[^\\]]*\\])?\\s*([<>=~!]=?\\s*[\\w.*]+)`,"m").exec(e)?.[1];return o?o.replace(/\s+/g,""):null}function aS(e){let t=new Map,n=(r,o,s,{version:i=null,command:a=null,category:c=null}={})=>{let l=`${r}\0${De.posix.dirname(s)}`,d=t.get(l)??{name:r,ecosystem:o,version:null,run_command:a,category:c,root:De.posix.dirname(s)==="."?"":De.posix.dirname(s),evidence:[]};d.version??=i,d.run_command??=a,d.evidence.includes(s)||d.evidence.push(s),t.set(l,d)};for(let{relative:r,text:o}of e){let s=De.posix.basename(r).toLowerCase();for(let[i,a]of Zu){if(!i.test(s))continue;let c=Xu.find(([l])=>l===a);n(a,c[1],r,{command:c[3],category:c[4]})}if(!(o===null||!sa(r))){for(let[i,a,c,l,d]of Xu)c.test(o)&&n(i,a,r,{version:iS(o,i),command:l,category:d});if(s==="package.json")for(let i of cS(o)){let a=[...t.values()].find(c=>c.evidence.includes(r)&&i.command.includes(c.name.replace(/^@[\w-]+\//,"").split("/")[0]));a&&(a.run_command=i.invocation)}}}if([...t.values()].every(r=>r.name!=="go-test")){let r=e.find(({relative:o})=>De.posix.basename(o)==="go.mod");r&&n("go-test","go",r.relative,{command:"go test ./..."})}if([...t.values()].every(r=>r.name!=="cargo-test")){let r=e.find(({relative:o})=>De.posix.basename(o).toLowerCase()==="cargo.toml");r&&n("cargo-test","rust",r.relative,{command:"cargo test"})}return[...t.values()].map(r=>({...r,evidence:r.evidence.sort()})).sort((r,o)=>r.root.localeCompare(o.root)||r.name.localeCompare(o.name))}function cS(e){let t;try{t=JSON.parse(e)?.scripts}catch{return[]}return!t||typeof t!="object"?[]:Object.entries(t).filter(([n,r])=>typeof r=="string"&&/^(test|e2e|test:[\w:-]+)$/.test(n)).map(([n,r])=>({command:r,invocation:n==="test"?"npm test":`npm run ${n}`}))}function lS(e){let t=[0];for(let n=0;n<e.length;n+=1)e.charCodeAt(n)===10&&t.push(n+1);return t}function dS(e,t){let n=0,r=e.length-1;for(;n<r;){let o=n+r+1>>1;e[o]<=t?n=o:r=o-1}return n+1}function Ju(e){let t=String(e).replace(/\s+/g," ").trim();return t.length>Wu?`${t.slice(0,Wu-1)}\u2026`:t}function No(e,t){let n=e.slice(0,t).split(`
|
|
266
|
+
`),p=/^not applicable\s*:\s*(.*)$/i.exec(l.trim());if(p){let u=Vb(p[1],d);u&&s.length<Mb&&!s.some(f=>f.category===u.category)&&s.push(u)}else if(o.length<Nb){let u=Wb(d);u&&o.push(u)}}return(i.length>0||/^[ \t]*[-*][ \t]+\**(?:Name|Result)\**[ \t]*:/im.test(r))&&!o.length&&!s.length?null:{cases:o,not_applicable:s}}import{createHash as SS}from"node:crypto";import{readFile as Xb}from"node:fs/promises";import De from"node:path";var Jb=1,Kb=768*1024,Yb=2e4,Qb=2e3,Wu=300,Vu=64,ia=new Set([".js",".jsx",".mjs",".cjs",".ts",".tsx"]),Zb=new Set([...ia,".py",".go",".java",".kt",".cs",".rb",".rs"]),Qu=/(^|\/)(tests?|__tests__|spec|specs|e2e|integration_tests|it)\//,eS=/(^|\/)(node_modules|__snapshots__|__mocks__|fixtures?|__fixtures__|testdata|vendor|dist|build)\//,tS=new RegExp([String.raw`\bassert\w*\b`,String.raw`\bexpect\w*\s*\(`,String.raw`\.should\b`,String.raw`\bpytest\.raises\b`,String.raw`\bself\.assert\w+`,String.raw`\bt\.(?:Error|Errorf|Fatal|Fatalf|Fail|FailNow)\b`,String.raw`\brequire\.\w+\(`,String.raw`\bAssert\.\w+`,String.raw`\bassert_(?:eq|ne)!`,String.raw`\bverify\s*\(`,String.raw`\bto(?:Have|Be|Equal|Contain|Match|Throw)\w*\s*\(`].join("|"),"g"),nS=[["e2e",["e2e","end-to-end","playwright","cypress"]],["integration",["integration","integration_tests","integration-tests"]],["smoke",["smoke"]],["contract",["contract","contracts","pact"]],["performance",["perf","performance","benchmark","benchmarks"]],["load",["load","k6","locust"]],["security",["security","pentest"]],["accessibility",["a11y","accessibility"]],["visual",["visual","screenshots"]],["regression",["regression"]]],rS={e2e:"e2e",integration:"integration",smoke:"smoke",sanity:"sanity",regression:"regression",security:"security",contract:"contract",performance:"performance",perf:"performance",benchmark:"performance",load:"load",stress:"stress",database:"database",db:"database",accessibility:"accessibility",a11y:"accessibility",visual:"visual",resilience:"resilience",api:"api"},oS=[["accessibility",/@axe-core\/|\baxe\.run\(|\bcheckA11y\(|AxeBuilder/],["visual",/\btoHaveScreenshot\(|\bmatchImageSnapshot\(/],["contract",/\bschemathesis\b|@pact-foundation\/|\bpact\b/],["load",/\bfrom\s+locust\b|from\s+["']k6(\/[\w-]+)?["']/],["database",/\btestcontainers\b|PostgresContainer|MySqlContainer/i]],Xu=[["pytest","python",/(^|[\s"'[,])pytest([<>=~!\s"',\]]|$)/m,"pytest",null],["pytest-asyncio","python",/\bpytest-asyncio\b/,null,null],["pytest-cov","python",/\bpytest-cov\b/,null,null],["hypothesis","python",/(^|[\s"'[,])hypothesis([<>=~!\s"',\]]|$)/m,null,null],["schemathesis","python",/\bschemathesis\b/,"schemathesis run","contract"],["locust","python",/(^|[\s"'[,])locust([<>=~!\s"',\]]|$)/m,"locust","load"],["bandit","python",/(^|[\s"'[,])bandit([<>=~!\s"',\]]|$)/m,"bandit -r .","security"],["pip-audit","python",/\bpip-audit\b/,"pip-audit","security"],["vitest","node",/"vitest"\s*:/,"vitest run",null],["jest","node",/"jest"\s*:/,"jest",null],["mocha","node",/"mocha"\s*:/,"mocha",null],["@testing-library/react","node",/"@testing-library\/react"\s*:/,null,"component"],["@playwright/test","node",/"@playwright\/test"\s*:/,"playwright test","e2e"],["cypress","node",/"cypress"\s*:/,"cypress run","e2e"],["@axe-core/playwright","node",/"@axe-core\/(playwright|react)"\s*:/,null,"accessibility"],["k6","node",/"k6"\s*:/,"k6 run","load"],["testify","go",/github\.com\/stretchr\/testify/,null,null],["junit","jvm",/junit-jupiter|<artifactId>junit<\/artifactId>|junit:junit/,null,null],["xunit","dotnet",/PackageReference\s+Include="xunit"/i,"dotnet test",null],["nunit","dotnet",/PackageReference\s+Include="NUnit"/i,"dotnet test",null],["rspec","ruby",/gem\s+["']rspec/,"bundle exec rspec",null]],sS=new Set(["package.json","pyproject.toml","setup.cfg","setup.py","pipfile","go.mod","pom.xml","build.gradle","build.gradle.kts","gemfile","cargo.toml"]),Zu=[[/^vitest\.config\.[cm]?[jt]s$/,"vitest"],[/^vitest\.workspace\.[cm]?[jt]s$/,"vitest"],[/^jest\.config\.[cm]?[jt]s$/,"jest"],[/^playwright\.config\.[cm]?[jt]s$/,"@playwright/test"],[/^cypress\.config\.[cm]?[jt]s$/,"cypress"],[/^pytest\.ini$/,"pytest"]];function sa(e){let t=De.posix.basename(e).toLowerCase();return sS.has(t)||/^requirements[\w.-]*\.txt$/.test(t)||t.endsWith(".csproj")}function iS(e,t){let n=t.replace(/[.*+?^${}()|[\]\\/]/g,"\\$&"),r=new RegExp(`"${n}"\\s*:\\s*"([^"]+)"`).exec(e)?.[1];if(r)return r;let o=new RegExp(`(?:^|["'\\s,\\[])${n}\\s*(?:\\[[^\\]]*\\])?\\s*([<>=~!]=?\\s*[\\w.*]+)`,"m").exec(e)?.[1];return o?o.replace(/\s+/g,""):null}function aS(e){let t=new Map,n=(r,o,s,{version:i=null,command:a=null,category:c=null}={})=>{let l=`${r}\0${De.posix.dirname(s)}`,d=t.get(l)??{name:r,ecosystem:o,version:null,run_command:a,category:c,root:De.posix.dirname(s)==="."?"":De.posix.dirname(s),evidence:[]};d.version??=i,d.run_command??=a,d.evidence.includes(s)||d.evidence.push(s),t.set(l,d)};for(let{relative:r,text:o}of e){let s=De.posix.basename(r).toLowerCase();for(let[i,a]of Zu){if(!i.test(s))continue;let c=Xu.find(([l])=>l===a);n(a,c[1],r,{command:c[3],category:c[4]})}if(!(o===null||!sa(r))){for(let[i,a,c,l,d]of Xu)c.test(o)&&n(i,a,r,{version:iS(o,i),command:l,category:d});if(s==="package.json")for(let i of cS(o)){/(^|[\s;&|(])node\b[^;&|]*\s--test\b/.test(i.command)&&n("node:test","node",r,{command:i.invocation});let a=[...t.values()].find(c=>c.evidence.includes(r)&&i.command.includes(c.name.replace(/^@[\w-]+\//,"").split("/")[0]));a&&(a.run_command=i.invocation)}}}if([...t.values()].every(r=>r.name!=="go-test")){let r=e.find(({relative:o})=>De.posix.basename(o)==="go.mod");r&&n("go-test","go",r.relative,{command:"go test ./..."})}if([...t.values()].every(r=>r.name!=="cargo-test")){let r=e.find(({relative:o})=>De.posix.basename(o).toLowerCase()==="cargo.toml");r&&n("cargo-test","rust",r.relative,{command:"cargo test"})}return[...t.values()].map(r=>({...r,evidence:r.evidence.sort()})).sort((r,o)=>r.root.localeCompare(o.root)||r.name.localeCompare(o.name))}function cS(e){let t;try{t=JSON.parse(e)?.scripts}catch{return[]}return!t||typeof t!="object"?[]:Object.entries(t).filter(([n,r])=>typeof r=="string"&&/^(test|e2e|test:[\w:-]+)$/.test(n)).map(([n,r])=>({command:r,invocation:n==="test"?"npm test":`npm run ${n}`}))}function lS(e){let t=[0];for(let n=0;n<e.length;n+=1)e.charCodeAt(n)===10&&t.push(n+1);return t}function dS(e,t){let n=0,r=e.length-1;for(;n<r;){let o=n+r+1>>1;e[o]<=t?n=o:r=o-1}return n+1}function Ju(e){let t=String(e).replace(/\s+/g," ").trim();return t.length>Wu?`${t.slice(0,Wu-1)}\u2026`:t}function No(e,t){let n=e.slice(0,t).split(`
|
|
267
267
|
`);n.pop();let r=[];for(let o=n.length-1;o>=0;o-=1){let s=n[o].trim();if(/^(@|\[|#\[)/.test(s))r.push(s);else if(s)break}return r.join(`
|
|
268
268
|
`)}function uS(e){let t=[],n=[];for(let r of e.matchAll(/^([ \t]*)(class|(?:async\s+)?def)\s+(\w+)/gm)){let o=r[1].length;for(;n.length&&n.at(-1).indent>=o;)n.pop();let s=r[2]==="class"?"class":"def",i=n.at(-1);if(n.push({indent:o,kind:s,name:r[3],decorators:s==="class"?No(e,r.index):""}),s==="class"||!r[3].startsWith("test")||i&&!(i.kind==="class"&&i.name.startsWith("Test")&&n.length===2))continue;let a=i,c=`${a?.decorators??""}
|
|
269
269
|
${No(e,r.index)}`,l=[...c.matchAll(/@pytest\.mark\.(\w+)/g)].map(d=>d[1]);t.push({name:r[3],suite:a?.name??null,offset:r.index,markers:l,status:l.some(d=>d==="skip"||d==="skipif")?"skipped":l.includes("xfail")?"expected_failure":/@unittest\.skip/.test(c)?"skipped":"active"})}return t}var pS=/^([ \t]*)(describe|context|suite|it|test|specify)((?:\.(?:skip|only|todo|fixme|concurrent|each|serial|parallel|fails))*)\s*(?:\([^)]*\)\s*)?\(\s*(["'`])((?:\\.|(?!\4).)*)\4/gm;function fS(e){let t=[],n=[];for(let r of e.matchAll(pS)){let o=r[1].length;for(;n.length&&n.at(-1).indent>=o;)n.pop();let s=r[3],i=/\.(skip|todo|fixme)/.test(s)||n.some(a=>a.skipped);if(["describe","context","suite"].includes(r[2])){n.push({indent:o,name:r[5],skipped:i});continue}t.push({name:r[5],suite:n.map(a=>a.name).join(" \u203A ")||null,offset:r.index,markers:[],status:/\.todo/.test(s)?"todo":i?"skipped":"active"})}for(let r of e.matchAll(/^[ \t]*xit\s*\(\s*(["'`])((?:\\.|(?!\1).)*)\1/gm))t.push({name:r[2],suite:null,offset:r.index,markers:[],status:"skipped"});return t}function mS(e){let t=[],n=[];for(let r of e.matchAll(/^([ \t]*)(describe|context|it|specify|xit|scenario)\s*\(?\s*(["'])((?:\\.|(?!\3).)*)\3/gm)){let o=r[1].length;for(;n.length&&n.at(-1).indent>=o;)n.pop();if(r[2]==="describe"||r[2]==="context"){n.push({indent:o,name:r[4]});continue}t.push({name:r[4],suite:n.map(s=>s.name).join(" \u203A ")||null,offset:r.index,markers:[],status:r[2]==="xit"?"skipped":"active"})}return t}function hS(e){return[...e.matchAll(/^func\s+(Test\w+|Benchmark\w+|Fuzz\w+)\s*\(\s*\w+\s+\*testing\.[TBF]\s*\)/gm)].map(t=>({name:t[1],suite:null,offset:t.index,markers:t[1].startsWith("Benchmark")?["benchmark"]:[],status:"active"}))}function Ku(e,t,n,r){let o=/\bclass\s+(\w+)/.exec(e)?.[1]??null,s=[];for(let i of e.matchAll(n)){let a=No(e,i.index);t.test(a)&&s.push({name:i[1]??i[2],suite:o,offset:i.index,markers:[...a.matchAll(/@Tag\(\s*"([^"]+)"|\[Trait\(\s*"Category"\s*,\s*"([^"]+)"/g)].map(c=>c[1]??c[2]),status:r.test(a)?"skipped":"active"})}return s}function gS(e){return[...e.matchAll(/^[ \t]*(?:pub\s+)?(?:async\s+)?fn\s+(\w+)\s*\(/gm)].map(t=>({match:t,decorators:No(e,t.index)})).filter(({decorators:t})=>/#\[(?:\w+::)?test\b/.test(t)).map(({match:t,decorators:n})=>({name:t[1],suite:null,offset:t.index,markers:[],status:/#\[ignore\b/.test(n)?"skipped":"active"}))}function wS(e,t){let n=De.posix.extname(e).toLowerCase();return n===".py"?uS(t):ia.has(n)?fS(t):n===".rb"?mS(t):n===".go"?hS(t):n===".rs"?gS(t):n===".java"||n===".kt"?Ku(t,/@(Test|ParameterizedTest|RepeatedTest|TestFactory)\b/,/^[ \t]*(?:(?:public|private|protected|internal|open|suspend|override)\s+)*(?:fun\s+`?([^`(\s]+)`?|void\s+(\w+))\s*\(/gm,/@(Disabled|Ignore)\b/):n===".cs"?Ku(t,/\[(Fact|Theory|Test|TestMethod|TestCase)\b/,/^[ \t]*(?:public|private|internal)\s+(?:async\s+)?(?:static\s+)?[\w<>[\],\s]+?\s+(\w+)\s*\(/gm,/Skip\s*=|\[Ignore\b/):[]}function yS(e,t,n,r){let o=new Set,s=e.toLowerCase(),i=s.split("/").slice(0,-1),a=De.posix.basename(s).split(".").slice(1,-1);for(let[c,l]of nS)l.some(d=>i.includes(d)||a.includes(d))&&o.add(c);for(let c of n){let l=rS[String(c).toLowerCase()];l&&o.add(l)}(t==="@playwright/test"||t==="cypress")&&o.add("e2e");for(let[c,l]of oS)l.test(r)&&o.add(c);return/\.(test|spec)\.[jt]sx$/.test(s)&&/\brender(Hook)?\s*\(/.test(r)&&!o.has("e2e")&&o.add("component"),[...o].sort()}function vS(e,t,n){let r=De.posix.extname(e).toLowerCase(),o=i=>n.filter(a=>a.name===i&&(!a.root||e.startsWith(`${a.root}/`))).sort((a,c)=>c.root.length-a.root.length)[0],s=i=>i.test(t);if(r===".py")return s(/^\s*import\s+unittest|^\s*from\s+unittest\b/m)&&!o("pytest")?"unittest":"pytest";if(ia.has(r)){if(s(/from\s+["']@playwright\/test["']/))return"@playwright/test";if(s(/from\s+["']vitest["']/))return"vitest";if(s(/from\s+["']node:test["']/))return"node:test";if(/\bcy\.\w+\(/.test(t))return"cypress";for(let i of["vitest","jest","mocha","@playwright/test"])if(o(i))return i;return"unknown"}return r===".go"?"go-test":r===".rs"?"cargo-test":r===".rb"?"rspec":r===".java"||r===".kt"?"junit":r===".cs"?o("nunit")?"nunit":"xunit":"unknown"}function _S(e,t,n=[]){let r=vS(e,t,n),o=wS(e,t).filter(a=>a.name).sort((a,c)=>a.offset-c.offset).slice(0,Qb),s=lS(t),i=new Map;return o.map((a,c)=>{let l=t.slice(a.offset,o[c+1]?.offset??t.length),d=Ju(a.name),p=a.suite?Ju(a.suite):null,u=`${p?`${p} \u203A `:""}${d}`,f=(i.get(u)??0)+1;return i.set(u,f),{key:`${e}::${u}${f>1?` #${f}`:""}`,file:e,line:dS(s,a.offset),name:d,suite:p,framework:r,status:a.status,markers:[...new Set(a.markers)].sort(),categories:yS(e,r,a.markers,t),assertion_count:(l.match(tS)??[]).length}})}function Er(e){let t=e.toLowerCase(),n=De.posix.extname(t);if(!Zb.has(n)||eS.test(t))return!1;let r=De.posix.basename(t);return r==="conftest.py"||r==="__init__.py"||/\.config\.[cm]?[jt]s$/.test(r)?!1:Qu.test(t)||/^test_.*\.py$|_test\.py$|_test\.go$|_spec\.rb$|\.(test|spec)\.[cm]?[jt]sx?$|\.cy\.[jt]sx?$|(test|tests)\.(java|kt|cs)$/.test(r)}var bS=/(^|\/)(tests?|__tests__|spec|specs|e2e|integration_tests|it)\/(?:[^/]+\/)*(fixtures?|__snapshots__)\//;function ep(e){let t=String(e??"").replace(/\\/g,"/").replace(/^\.\//,"").toLowerCase(),n=De.posix.basename(t);return n==="conftest.py"?!0:n==="__init__.py"?Qu.test(t):bS.test(t)}async function Yu(e,t,n){if((n??0)>Kb)return null;let r=await Xb(De.join(e,t),"utf8").catch(()=>null);return r&&!r.includes("\0")?r:null}async function xr(e,t,{headCommittedAt:n=null}={}){let r=t.filter(({path:l})=>sa(l)||Zu.some(([d])=>d.test(De.posix.basename(l).toLowerCase()))),o=await Promise.all(r.map(async({path:l,size:d})=>({relative:l,text:sa(l)?await Yu(e,l,d):null}))),s=aS(o),i=t.filter(({path:l})=>Er(l)).sort((l,d)=>l.path.localeCompare(d.path)),a=[],c=!1;for(let l=0;l<i.length&&!c;l+=Vu){let d=await Promise.all(i.slice(l,l+Vu).map(async({path:p,size:u})=>{let f=await Yu(e,p,u);return f?_S(p,f,s):[]}));for(let p of d){if(a.length+p.length>Yb){c=!0;break}a.push(...p)}}return{version:Jb,frameworks:s,test_file_count:i.length,cases:a,truncated:c,coverage:await Ru(e,s.map(l=>l.root),{headCommittedAt:n})}}var $r=2,ES=50,np=2e3,xS=1e5,kS=6e3,$S=300,AS=1500,Gn=40;var TS=/(?<![A-Za-z0-9])TC[-_]([A-Z0-9]+)[-_](\d+)(?![A-Za-z0-9])/gi;function kr(e){return new Set([...String(e??"").matchAll(TS)].map(([,t,n])=>`TC-${t.toUpperCase()}-${n}`))}function tp(e){return(e??[]).filter(t=>!Er(t)&&!ep(t))}function RS(e){let t=new Map;for(let n of e.automation_cases??[]){let[r]=kr(n?.reference);r&&!t.has(r)&&t.set(r,{reference:r,title:String(n.title??"").trim()})}return[...t.values()]}function Vt(e,t){let n=String(e??"").replace(/\s+/g," ").trim();return n.length>t?`${n.slice(0,t-1).replace(/[\ud800-\udbff]$/,"")}\u2026`:n}function aa(e,t){let n=String(e??"");return n.length>t?`${n.slice(0,t-1).replace(/[\ud800-\udbff]$/,"")}\u2026`:n}function IS(e,t=null){let n=String(e??""),r=/^#{1,3}[ \t]*Needs Goal route[ \t]*$/im.exec(n);if(!r)return[];let o=n.slice(r.index+r[0].length).split(/^#{1,6}[ \t]+\S/m)[0],s=new Map;for(let i of o.split(/\r?\n/)){let a=/^[ \t]*[-*][ \t]+[*`]*(TC[-_][A-Za-z0-9]+[-_]\d+)[*`]*[ \t]*[:—–-][ \t]*[*`]*(product_change|framework_setup|product_bug)[*`]*[ \t]*(?:[—–:-][ \t]*)?(.*)$/i.exec(i);if(!a)continue;let[c]=kr(a[1]);!c||t&&!t.has(c)||s.set(c,{reference:c,reason:a[2].toLowerCase(),detail:Vt(a[3],np)})}return[...s.values()]}function rp(e){return String(e??"").split(/\s+(?:›|>)\s+/).at(-1).trim().toLowerCase()}function CS(e,t){let n=rp(e.name),r=t.get(n)??[];!r.length&&n.includes("[")&&(r=t.get(n.split("[")[0])??[]);let o=String(e.file??"").replace(/\\/g,"/").toLowerCase();if(o&&(r=r.filter(a=>{let c=a.file.toLowerCase();return o===c||o.endsWith(`/${c}`)||c.endsWith(`/${o}`)})),r.length<=1)return r[0]??null;let s=String(e.classname??"").replace(/\./g,"/").toLowerCase(),i=r.filter(a=>s&&a.file.toLowerCase().includes(s));return i.length===1?i[0]:null}function OS({cases:e,measured:t=[],inventory:n}){let r=new Set(e.map(l=>l.reference)),o=(n?.cases??[]).filter(l=>l.status!=="removed"),s=new Map;for(let l of o){let d=rp(l.name);s.set(d,[...s.get(d)??[],l])}let i=new Map(e.map(l=>[l.reference,[]])),a=new Map(e.map(l=>[l.reference,[]])),c=0;for(let{test_run:l}of t)for(let d of l?.test_cases??[]){c+=1;let p=[...kr(d.name)];if(p.length>1)for(let u of p)r.has(u)&&a.get(u).push(d.name);else p.length===1&&r.has(p[0])&&i.get(p[0]).push({item:d,test:CS(d,s)})}return e.map(({reference:l,title:d})=>{let p=i.get(l),u=o.filter(h=>kr(h.name).has(l)),f=[];if(!p.length){let h=[...a.get(l),...u.filter(w=>kr(w.name).size>1).map(w=>w.name)];h.length?f.push(`\`${Vt(h[0],200)}\` names several case references; give each test exactly one, in its own name.`):u.length?f.push(`The committed test \`${u[0].file}::${Vt(u[0].name,200)}\` produced no result in the connector's run${c?"":" (the command wrote no JUnit test cases)"}; make sure the Proof command selects it by name and that it runs.`):f.push(`No committed test carries ${l} in its name. Write one whose name contains \`${l.replace(/-/g,"_")}\`.`)}for(let{item:h,test:w}of p){let g=`\`${Vt(h.name,200)}\``;h.status==="failed"?f.push(`${g} failed: ${Vt(h.message,300)||"no failure message was reported"}`):h.status==="skipped"?f.push(`${g} was skipped; it must run and pass.`):w?w.status!=="active"?f.push(`${g} is ${w.status} in the source; it must be an active test.`):w.assertion_count>0||f.push(`${g} passed without making any assertion; assert the expected outcome.`):f.push(`${g} passed but matches no committed test of that name; keep the name in the source as the runner reports it.`)}let m=p.filter(({item:h,test:w})=>h.status==="passed"&&w?.status==="active"&&w.assertion_count>0);return{reference:l,title:d,passed:p.length>0&&f.length===0,tests:[...new Set(m.map(({test:h})=>`${h.file}::${h.name}`))],assertions:m.reduce((h,{test:w})=>h+w.assertion_count,0),has_tests:p.length>0||u.length>0,problems:f}})}function op(e,t=[]){return["## How the connector checks these tests",`When you finish, the connector commits your change, runs the command below itself and reads its JUnit report. A selected case counts as automated only when a test whose name carries exactly that one case reference passes in that run and makes real assertions.
|
|
@@ -834,7 +834,7 @@ It is checked with the provider and stored in this machine's protected vault
|
|
|
834
834
|
(Windows Data Protection, the macOS Keychain or the Linux Secret Service).
|
|
835
835
|
EngineerOS never receives it; the running connector uses it when EngineerOS asks.`;function KO(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(`
|
|
836
836
|
`),c?o(c):r(s.trim())},a=c=>{for(let l of c){if(l==="\r"||l===`
|
|
837
|
-
`)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 ry=Symbol("missing");function YO(e,t){return new Promise(n=>{let r=XO(e,t,{stdio:"inherit",shell:!1});r.once("error",o=>n(o?.code==="ENOENT"?ry:o.message)),r.once("close",o=>n(o===0?null:`${e} exited with code ${o}.`))})}function ny(e,t){for(let n of no){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 oy(e,t,n,{vault:r=nl(),run:o=Js,fetchImpl:s=fetch,secret:i=KO,interactive:a=YO,install:c=Xs,log:l=console.log,error:d=console.error}={}){if(n.help||e!=="integrations"&&!t[0])return l(JO),n.help?0:2;if(e==="integrations")return ny(l,(await Qs({run:o,vault:r})).providers),0;let p=t[0];if(!no.includes(p))return d(`Unknown provider ${p}. Choose one of: ${no.join(", ")}.`),2;if(p==="github"||p==="gitlab"){let f=$n[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 m=await a(f,["auth","login"]);if(m===ry){let h=await ir(f);if(!h){l(`Installing the ${Zr[f].label} ${Zr[f].version} for the connector...`);try{h=(await c(f)).path}catch(w){return d(w.message),1}}m=await a(h,["auth","login"])}return m?(d(`${m} ${Ys[p]} is how this machine signs in to ${p}.`),1):(ny(l,{[p]:(await Qs({run:o,vault:r})).providers[p]}),0)}let u=$e[p];if(e==="disconnect")return await r.delete("",p),l(`Removed the ${u.label} ${u.tokenName} from this machine.`),0;try{await rl(r);let f=await i(`${u.label} ${u.tokenName} (create one at ${u.tokenUrl}): `),m=await ol(r,p,{token:f,site:n.site,email:n.email},s);return l(`Connected ${u.label}${m.account?` as ${m.account}`:""}. The token stays on this machine.`),0}catch(f){return d(f.message),1}}import{spawn as QO}from"node:child_process";async function sy({root:e,bundled:t,argv:n,workspace:r,spawnImpl:o=QO,log:s=console.log}){let i=n,a=!1;for(;;){let c=t;try{c=Zt(await Je(e),t)}catch(p){s(`${p.message} Starting the installed connector ${t.version}.`)}let{code:l,signal:d}=await ZO(o,c.entry,i,t);if(l===Jr){i=["start","--workspace",r],a=!1,s("Restarting the connector process on the activated update. Goal runs continue in their own processes.");continue}if(l!==0&&!d&&!a){let p=await Je(e).catch(()=>null);if(p&&!p.confirmed&&p.active?.version===c.version)try{let u=await zc(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 ${u.version}.`);continue}catch(u){s(`Automatic rollback failed: ${u.message}`)}}return l??1}}function ZO(e,t,n,r){return new Promise((o,s)=>{let i=e(process.execPath,[...process.execArgv,t,...n],{stdio:"inherit",env:{...process.env,[rr]:"1",[Lc]:r.entry,[Dc]:r.version}}),a=process.platform==="win32"?[]:["SIGINT","SIGTERM","SIGHUP"],c=d=>i.kill(d);for(let d of a)process.on(d,c);let l=()=>{for(let d of a)process.off(d,c)};i.once("error",d=>{l(),s(d)}),i.once("exit",(d,p)=>{l(),o({code:d,signal:p})})})}var on="1.42.
|
|
837
|
+
`)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 ry=Symbol("missing");function YO(e,t){return new Promise(n=>{let r=XO(e,t,{stdio:"inherit",shell:!1});r.once("error",o=>n(o?.code==="ENOENT"?ry:o.message)),r.once("close",o=>n(o===0?null:`${e} exited with code ${o}.`))})}function ny(e,t){for(let n of no){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 oy(e,t,n,{vault:r=nl(),run:o=Js,fetchImpl:s=fetch,secret:i=KO,interactive:a=YO,install:c=Xs,log:l=console.log,error:d=console.error}={}){if(n.help||e!=="integrations"&&!t[0])return l(JO),n.help?0:2;if(e==="integrations")return ny(l,(await Qs({run:o,vault:r})).providers),0;let p=t[0];if(!no.includes(p))return d(`Unknown provider ${p}. Choose one of: ${no.join(", ")}.`),2;if(p==="github"||p==="gitlab"){let f=$n[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 m=await a(f,["auth","login"]);if(m===ry){let h=await ir(f);if(!h){l(`Installing the ${Zr[f].label} ${Zr[f].version} for the connector...`);try{h=(await c(f)).path}catch(w){return d(w.message),1}}m=await a(h,["auth","login"])}return m?(d(`${m} ${Ys[p]} is how this machine signs in to ${p}.`),1):(ny(l,{[p]:(await Qs({run:o,vault:r})).providers[p]}),0)}let u=$e[p];if(e==="disconnect")return await r.delete("",p),l(`Removed the ${u.label} ${u.tokenName} from this machine.`),0;try{await rl(r);let f=await i(`${u.label} ${u.tokenName} (create one at ${u.tokenUrl}): `),m=await ol(r,p,{token:f,site:n.site,email:n.email},s);return l(`Connected ${u.label}${m.account?` as ${m.account}`:""}. The token stays on this machine.`),0}catch(f){return d(f.message),1}}import{spawn as QO}from"node:child_process";async function sy({root:e,bundled:t,argv:n,workspace:r,spawnImpl:o=QO,log:s=console.log}){let i=n,a=!1;for(;;){let c=t;try{c=Zt(await Je(e),t)}catch(p){s(`${p.message} Starting the installed connector ${t.version}.`)}let{code:l,signal:d}=await ZO(o,c.entry,i,t);if(l===Jr){i=["start","--workspace",r],a=!1,s("Restarting the connector process on the activated update. Goal runs continue in their own processes.");continue}if(l!==0&&!d&&!a){let p=await Je(e).catch(()=>null);if(p&&!p.confirmed&&p.active?.version===c.version)try{let u=await zc(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 ${u.version}.`);continue}catch(u){s(`Automatic rollback failed: ${u.message}`)}}return l??1}}function ZO(e,t,n,r){return new Promise((o,s)=>{let i=e(process.execPath,[...process.execArgv,t,...n],{stdio:"inherit",env:{...process.env,[rr]:"1",[Lc]:r.entry,[Dc]:r.version}}),a=process.platform==="win32"?[]:["SIGINT","SIGTERM","SIGHUP"],c=d=>i.kill(d);for(let d of a)process.on(d,c);let l=()=>{for(let d of a)process.off(d,c)};i.once("error",d=>{l(),s(d)}),i.once("exit",(d,p)=>{l(),o({code:d,signal:p})})})}var on="1.42.4",oi="1.42.4",rj=3e5,si=["queued","running","reporting"],oj=5e3,sl={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."},il={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."},sj=6e4,ij=3e4,al={id:"tool_inventory",title:"Tool inventory refresh",remedy:"Run `engineeros-connector tools list` in this workspace for the full registry state."},cl={id:"runner_setup_reporting",title:"Goal runner setup reporting",remedy:"Restore the connection to EngineerOS; saved setup reports will retry automatically."},{command:ge,positional:Be,flags:X}=Rg(process.argv.slice(2));ge==="version"&&(console.log(on),process.exit(0));var zt=null,Ne=!1,tn=null,wy=!1,yy=null,yl=null,Ie=null,co=null,hl,iy,ay,aj=ey({getWorkspace:()=>x.workspace}),oo=jg();ge==="results"&&(Be[0]!=="upload"&&(console.log(Bs),process.exit(X.help||!Be[0]?0:2)),process.exit(await kw(X)));(ge==="connect"||ge==="disconnect"||ge==="integrations")&&process.exit(await oy(ge,Be,X,{fetchImpl:Yw}));if(ge==="runner"){let e=Re.resolve(X.workspace||process.cwd()),t=Be[0]||"status";try{if(t==="serve"||t==="worker"){let n=t==="worker"?Re.join(Re.dirname(ue(e,X["run-id"])),"worker.log"):Re.join(e,".engineeros","runner","service.log");tj(Re.dirname(n),{recursive:!0});let r=(...s)=>Dr(n,`${nj(...s)}
|
|
838
838
|
`),o=(s,i,a)=>(Dr(n,s),(typeof i=="function"?i:a)?.(),!0);process.stdout.write=process.stderr.write=o,console.log=console.error=console.warn=r}t==="install"?console.log(`Installed Goal runner service: ${await bc(e)}`):t==="start"?await nr(e,{enable:!0}):t==="status"?console.log(JSON.stringify(await Yt(e),null,2)):t==="serve"?await _g(e):t==="worker"?await bg(e,X["run-id"]):le("Usage: engineeros-connector runner [install|start|status] --workspace PATH"),process.exit(0)}catch(n){le(n.message)}}X["assessment-workers"]!==void 0&&le("--assessment-workers is no longer supported. Select 3 to 8 parallel agents in EngineerOS before starting the assessment.");if(ge==="tools"){let e=Re.resolve(X.workspace||process.cwd());try{let t=Be[0]||"list";if(["sign-in","auth-status","sign-out"].includes(t)){let r=Be[1];r||le(`Usage: engineeros-connector tools ${t} PROVIDER_ID --workspace PATH`);let o=await Ta(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 $a(e,{type:"tools.update",command_id:"00000000-0000-4000-8000-000000000002",action:t,provider_id:Be[1],confirmed:!0},void 0,{confirmLocal:async()=>!0}):t!=="list"&&await ka(e,t,Be[1]);let n=await Ve(e);console.log(JSON.stringify(n,null,2)),process.exitCode=n.error?1:0}catch(t){le(t.message)}process.exit(process.exitCode||0)}if(ge==="agents"){let e;try{e=await Da()}catch(n){le(n instanceof Error?n.message:String(n))}let t=await Promise.all(e.map(async n=>{try{return await Cr(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(ge==="agent"){let e=Be[0],t=Be[1]||"check";(!e||!["check","install"].includes(t))&&le("Usage: engineeros-connector agent AGENT_ID [check|install]");try{let n=t==="install"?await Wf(e):await Cr(e);console.log(`${n.name} is ready (${n.version}, ${n.distribution}).`)}catch(n){le(n instanceof Error?n.message:String(n))}process.exit(0)}if(ge==="mcp"){let e=X.workspace||process.env.ENGINEEROS_MCP_WORKSPACE||process.cwd(),t=X["run-id"]||Be[0]||process.env.ENGINEEROS_MCP_RUN_ID||null,n=await Le(e);await lw({config:n,runId:t,version:on,input:process.stdin,output:process.stdout}),process.exit(0)}if(ge==="context-mcp"){let e=X["config-workspace"]||X.workspace||process.cwd(),t=await Le(e);t||le("This workspace is not paired with EngineerOS."),await hw({config:t,workspace:X.workspace||t.workspace,version:on,input:process.stdin,output:process.stdout}),process.exit(0)}if(ge==="status"){let e=await Le(X.workspace||process.cwd());console.log(e?`Paired as ${e.name} (${e.connector_id}) for ${e.workspace}`:"Not paired"),process.exit(e?0:1)}if(ge==="doctor"){let e=Re.resolve(X.workspace||process.cwd()),t=await Le(e),n=await ow(e),r=await mr(t||{workspace:e},e,Ac(n));console.log(xc(r)),process.exit(r.status==="failed"?1:0)}if(ge==="update"){let e=Be[0]||"status";try{let t=Fc(process.argv[1],oi),n=await Uc(zs(),t,{action:e,policy:Be[1]??null});console.log(Yr(Gc(n,t,{supervised:!0})))}catch(t){le(`${t.message}
|
|
839
839
|
Usage: engineeros-connector update [status|check|apply|rollback|policy manual|approve|auto-patch|auto-minor]`)}process.exit(0)}if((ge==="start"||ge==="pair")&&process.env[rr]!=="1"&&xe(oi))try{process.exit(await sy({root:zs(),bundled:{version:oi,entry:Re.resolve(process.argv[1])},argv:process.argv.slice(2),workspace:Re.resolve(X.workspace||process.cwd())}))}catch(e){le(`The connector process could not be started: ${e.message}`)}var x,fr,so;if(ge==="pair"){let e=Be[0];e||le("Usage: engineeros-connector pair CODE --url URL [--agent AGENT_ID | --agent-protocol forge] [--name NAME] [--workspace PATH] [--skip-git-repo-check]");let t=X.url;t||le("Pairing requires --url with the EngineerOS backend address."),X.agent&&X["agent-command"]&&le("Use either --agent or --agent-command, not both.");let n=X["agent-protocol"]||(X["agent-command"]?"acp":"codex");["codex","acp","forge"].includes(n)||le(`Unknown --agent-protocol '${n}'. Use codex, acp, or forge.`),n==="forge"&&(X.agent||X["agent-command"])&&le("Forge runs its own agents. Drop --agent and --agent-command when pairing with --agent-protocol forge.");let r={};try{X.agent&&(await Cr(X.agent),r=await qf(X.agent))}catch(o){le(o instanceof Error?o.message:String(o))}x={server_url:mi(t),workspace:Re.resolve(X.workspace||process.cwd()),onboard:X.onboard===!0,onboarding_pending:X.onboard===!0,agent_protocol:n,agent_command:X["agent-command"]||null,agent_args:kj(X["agent-args"]),agent_name:X["agent-name"]||null,...r,skip_git_repo_check:X["skip-git-repo-check"]===!0,name:X.name||`${ej.hostname()} - ${Re.basename(Re.resolve(X.workspace||process.cwd()))}`},so=await Le(x.workspace),fr={type:"pair",pairing_code:e,name:x.name,capabilities:{},...Fl(so,x.server_url)}}else ge==="start"?(x=await Le(X.workspace||process.cwd()),x||le("This connector is not paired. Create a pairing command in EngineerOS first."),fr={type:"authenticate",connector_id:x.connector_id,token:x.token}):le("Use `engineeros-connector pair`, `start`, `status`, `doctor`, `agents`, `agent`, `tools`, or `mcp`.");var vy=Sg(x,{reportError:e=>console.error(e)}),rn=0,ii=!1,io=null,Me=new Map,ll=0,dl=new Set,ur=[],je=new Map,Ae,gl,ti,vt=null,ni=!1,_y=0,ul=null,pl=[],ri,by,ro=1e3,Dt=!1,rt,lr=!1,ai=!1,wl=0;function cy(e){return wl+=1,e.finally(()=>{wl-=1})}var dr,Tn=0;function ao({exitCode:e=0}={}){if(Tn=Math.max(Tn,e),dr)return dr;let t=setTimeout(()=>{console.error("Connector shutdown exceeded 15 seconds; inspect the retained agent logs before restarting."),process.exit(1)},15e3);return t.unref(),dr=cj().finally(()=>clearTimeout(t)),dr}async function cj(){if(Ne=!0,co?.stop(),zt?.stop(),yl?.stop(),yy?.stop(),clearInterval(hl),Ie?.stop(),by?.(),clearTimeout(ri),clearInterval(gl),clearInterval(ti),await Promise.all([...[...Me.values()].map(e=>Ze(e.child))]),await Promise.all([...je.values()].map(bl)),await os(),await Tu().catch(e=>{Tn=Math.max(Tn,1),console.error(`${e.message}. Stop those processes before restarting the connector.`)}),Ae?.close(),Tn&&Tn!==Jr){let e;await Promise.race([(async()=>{await zt?.drain(),await mr(x,x.workspace)})().catch(()=>{}),new Promise(t=>{e=setTimeout(t,1e4)})]).finally(()=>clearTimeout(e))}process.exit(Tn)}for(let e of["SIGINT","SIGTERM","SIGHUP"])process.on(e,()=>{ao()});var ly=!1;for(let e of["uncaughtException","unhandledRejection"])process.on(e,async t=>{ly||(ly=!0,console.error(`Connector stopping after an unhandled failure: ${t instanceof Error?t.stack||t.message:String(t)}`),await ao({exitCode:1}))});Ie=zg();process.on("exit",()=>{co?.stop(),Ie.stop()});Ie.banner(`EngineerOS connector ${on}`,[x.workspace,x.server_url]);zt=Og({actions:{refresh_tool_inventory:async()=>{Te.tool_inventory=await Ve(x.workspace),_t()},restart_goal_runner:()=>nr(x.workspace)},onNotify:()=>mr(x,x.workspace),explain:async e=>{if(!await Sy())return null;let{reading:t}=await Gh(x,e);return t},onUpdate:e=>rw(x.workspace,e)});yy=iw({render:(e,t)=>Ie.write(e,t),onRecord:e=>zt.observe(e)});yl=aw({workspace:x.workspace,onRecord:e=>{zt.observe(e),Ie.line(e.channel,e.level,e.message)}});zt.start();yl.start();Ie.live&&(hl=setInterval(()=>{lj().catch(()=>{})},oj),hl.unref?.());var fl=new Set;async function lj(){iy??=_c(x.workspace);let{jobs:e}=await iy(),t=new Set,n=e.filter(r=>r.status!=="queued"&&si.includes(r.status)).length;for(let r of e){if(!si.includes(r.status))continue;t.add(r.runId),fl.add(r.runId);let o=r.status==="queued"&&n>0?`queued behind running Goals (running: ${n})`:r.activity?.phase||r.status;Ie.status(`goal:${r.runId}`,o,dj(r),{agent:r.status!=="queued",link:io&&`${io}/goals`}),Ie.step(`goal:${r.runId}`,r.activity?.message)}for(let r of fl)t.has(r)||(fl.delete(r),Ie.clearStatus(`goal:${r}`))}function dj(e){let t=e.startedAt??Date.parse(e.updatedAt??"");return Number.isFinite(t)?t:Date.now()}async function Sy(){if(Ne||Me.size>0||je.size>0||rn>0)return!1;try{let{jobs:e}=await Yt(x.workspace);return!Ne&&!e.some(t=>si.includes(t.status))}catch{return!1}}try{let e=await On(x.workspace);e.committed&&(x.onboarding_pending=!0,x.connector_id&&await Gt(x),console.log(`Local project repository ready at ${e.revision.slice(0,8)}. Source and design artifacts are committed locally.`))}catch(e){await $y(e)}var ee;try{ee=await Es(x,x.workspace)}catch(e){await $y(e)}console.log(`Using ${ee.name} through ${ee.protocol} (${ee.version}).`);var Te=$c(x,ee,await Ve(x.workspace)),Ft=Jg({running:Fc(process.argv[1],oi),supervised:process.env[rr]==="1",isIdle:async()=>!Ne&&Me.size===0&&ur.length===0&&je.size===0&&rn===0&&wl===0&&!lr&&!ai&&!ni,restart:()=>ao({exitCode:Jr}),onChange:e=>{Te.runtime_update=e,Ae?.readyState===WebSocket.OPEN&&_t()}});try{await Ft.refresh()}catch(e){console.error(`Connector updates are unavailable: ${e.message}`)}x={...x,execution_profiles:ee.executionProfiles??null};ge==="pair"&&so?.connector_id||await Gt(x);fr.capabilities=Te;console.log(Ct(x.worker_limit)===null?`Workers: automatic, ${Yn()} ${ee.name} workers side by side for this machine's CPU and memory; change it with /workers.`:`Workers: ${Ct(x.worker_limit)} ${ee.name} workers side by side, set with /workers.`);var pr=e=>jt(x,e),dy=Cs(pr,{signature:ag});async function uj(){let e=await Yt(x.workspace).catch(()=>({service:null,jobs:[]}));return{version:on,now:Date.now(),workspace:x.workspace,config_path:ht(x.workspace),config:x,agent:ee,automatic_worker_limit:Yn(),worker_limit:Ct(x.worker_limit),connection:{state:pj(),server_url:x.server_url,last_error:rt||null},work:{assessments:[...Me.values()].map(t=>({stage:t.stage,message:t.lastMessage,started_at:t.startedAt})),prompts:[...je.values()].map(t=>({id:String(t.runId).slice(0,8),purpose:t.purpose,started_at:t.startedAt})),integrations:rn},runner:e,runtime_update:Ft.report(),health:zt?.health()??null,activity:oo.snapshot()}}function pj(){return Ne||Dt?"stopped":Ae?.readyState===WebSocket.OPEN?"connected":"connecting"}var fj={async cancelPrompt(e){let t=[...je.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=>xy(e),setVerbose(e){return e===ii?`Detailed agent activity is already ${e?"on":"off"}.`:(_l(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"?(Ft.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 Ft.command(e),Yr(await Ft.refresh()))}};co=Zg({ui:Ie,snapshot:uj,actions:fj});co&&console.log(Qg());await Ey();var uy=new Set;async function Ey(){if(Ne||Dt)return;console.log(`Connecting ${x.name} to ${x.server_url}`),Dt=!1,rt=void 0;let e=new WebSocket(x.server_url);Ae=e;let t=sg(e,x.server_url,{onTimeout:r=>{Ae===e&&(rt=r,console.error(r),ml())}});by=t,e.addEventListener("open",()=>{if(Ae!==e){e.close();return}try{if(Zh(Ae,e,fr))return;throw new Error("The WebSocket was not open when authentication started.")}catch(r){rt=Fe(r),console.error(`Could not authenticate the WebSocket connection: ${rt}`);try{e.close()}catch{}ml()}}),e.addEventListener("message",r=>{if(Ae!==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: ${Fe(s)}`)})});let n=async r=>{if(r.type==="authenticated"&&r.connector?.capabilities?.http_updates!==!0){Ne=!0,Dt=!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=so?.connector_id===r.connector.id;if(x=zl(x,so,r.connector.id,r.token),await Gt(x),r.connector?.capabilities?.http_updates!==!0){Ne=!0,Dt=!0,console.error("Pairing saved. Update the EngineerOS backend for HTTP updates, then start this connector again."),e.close();return}fr={type:"authenticate",connector_id:x.connector_id,token:x.token,capabilities:Te},console.log(s?`Reconnected existing workspace connector ${x.connector_id}; assessment history is preserved.`:`Paired. Connector ${x.connector_id} is online.`),py(r);return}if(r.type==="authenticated"){t(),console.log("Connected and waiting for EngineerOS runs."),py(r);return}if(r.type==="provider.login"||r.type==="provider.logout"){ai||hj(r);return}if(r.type==="workspace.refresh"){vl();return}if(r.type==="workers.update"){try{console.log(`EngineerOS changed the workers. ${await xy(r.worker_limit??"auto")}`)}catch(s){console.error(`Workers were not changed: ${s.message}`)}return}if(r.type==="logging.update"){_l(r.activity_log_enabled===!0);return}if(r.type==="tools.update"){try{Te.tool_inventory=await $a(x.workspace,r,void 0,{confirmLocal:s=>co?.confirm(s)??!1}),e.send(JSON.stringify({type:"tools.updated",command_id:r.command_id,inventory:Te.tool_inventory})),_t(),console.log(`Tool registry updated: ${r.action} ${r.provider_id}.`)}catch(s){let i=s instanceof Error?s.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:i})),console.error(`Tool registry update rejected: ${i}`)}return}if(r.type==="tools.auth"){try{let s=await Ta(x.workspace,r,{onStatus:async()=>{Te.tool_inventory=await Ve(x.workspace),_t()}});Te.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:Te.tool_inventory})),_t(),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"){yr(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===Zw){cy(aj(r).then(s=>(s.error&&console.error(`${r.provider} ${r.operation} failed: ${s.error}`),ty(x,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}`;lc(ur,Me.get(s),r)==="deferred"&&console.log(`Assessment stage ${r.stage} is already running here; EngineerOS will be answered when it finishes.`),lo();return}if(r.type==="prompt.execute"){let s=je.get(r.prompt_id);s?Ry(r)>s.executionRevision&&await bj(s,r):Ty(r);return}if(r.type==="prompt.cancel"){let s=je.get(r.prompt_id);s&&await bl(s);return}if(r.type==="run.available"){try{let s=await vy.dispatch(r);s.blocked?console.error(s.message):console.log(`Goal ${r.run_id} queued for the independent runner. Logs: ${Re.join(x.workspace,".engineeros","runs",r.run_id,"activity.log")}`)}catch(s){console.error(`Goal dispatch failed: ${Fe(s)}`)}return}if(r.type==="goal.cleanup"){try{await vg(x.workspace),await nr(x.workspace)}catch(s){console.error(`Goal cleanup is pending: ${s.message}`)}return}if(r.type==="run.accepted"){xj(r);return}if(r.type==="run.cancelled"){await vc(x.workspace,r.run_id);return}if(r.type===$w){ay??=Aw({getConfig:()=>x}),cy(ay.handle(r));return}if(r.type==="connector.update"){mj(e,r);return}if(r.type==="connector.disconnect"){console.log(r.message),await ao();return}if(r.type==="connector.revoked"){Ne=!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||(lr=!1);return}if(r.type==="connection.error"){Dt=!0,console.error(`EngineerOS: ${r.message}`);return}let o=String(r.type??"(missing)").replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,120);uy.has(o)||(uy.add(o),console.warn(`Unknown EngineerOS message type ${o}; connector ${on}. Update the connector and backend to compatible versions.`))};e.addEventListener("close",r=>{if(t(),Ae!==e||dr)return;let o=eg(r);if(!o.retry||Dt||Ne){console.error(o.message),o.retry&&Dt&&console.error("Connection rejected. Create a new pairing command in EngineerOS if this connector was revoked."),ao();return}rt=rt?`${o.message} ${rt}`:o.message,ml()}),e.addEventListener("error",r=>{Ae===e&&(rt=Qh(r),console.error(`WebSocket connection to ${x.server_url} failed: ${rt}`))})}async function mj(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=Ft.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 Ft.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 hj(e){let t=e.request_id,n=e.type==="provider.logout"?"logout":"login";ai=!0,console.log(`Starting interactive ${ee.name} provider ${n}.`);try{await(n==="logout"?og:rg)(ee,x.workspace),ee=await Es(x,x.workspace),Te=$c(x,ee,Te.tool_inventory),fr.capabilities=Te,Ae.readyState===WebSocket.OPEN&&(Ae.send(JSON.stringify({type:`provider.${n}.completed`,request_id:t,session:Te.agent_session})),Ae.close(1e3,`Provider ${n} completed`)),console.log(`${ee.name} provider ${n} completed.`)}catch(r){let o=Fe(r).slice(0,500);Ae.readyState===WebSocket.OPEN&&Ae.send(JSON.stringify({type:`provider.${n}.failed`,request_id:t,message:o})),console.error(`Provider ${n} failed: ${o}`)}finally{ai=!1}}function ml(){if(Ne||Dt||ri)return;let e=rt?` Last error: ${rt}`:"";console.error(`Connection unavailable.${e} Retrying in ${Math.round(ro/1e3)}s.`),ri=setTimeout(()=>{ri=void 0,Ey()},ro),ro=Math.min(3e4,ro*2)}async function vl(){if(!(lr||Ae.readyState!==WebSocket.OPEN)){lr=!0,console.log("Inspecting the workspace without executing its code.");try{let e=await qh(x.workspace),t=await fetch(jn(x.server_url,x.connector_id),{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${x.token}`},body:JSON.stringify(e)});if(!t.ok)throw new Error(await Ts(t,"the workspace"));let n=await t.json();x={...x,onboarding_pending:!1},await Gt(x),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.`);let r=n.connector?.capabilities?.execution_profiles,o=r?.model_selection===!0&&Array.isArray(r.models)&&r.models.length>0;console.log(o?`Workspace inventory registered as ${n.workspace_kind}. Select the assessment model in EngineerOS to continue.`:`Workspace inventory registered as ${n.workspace_kind}. This agent did not advertise selectable models; update it and reconnect before starting the baseline assessment.`);try{let s=await Mi(x.workspace,x.connector_id);console.log(`Built the local context index: ${s.total_files.toLocaleString()} file(s) ready for assignment context.`)}catch(s){console.error(`Local context index build failed: ${s.message}`)}lr=!1}catch(e){lr=!1,console.error(`Workspace assessment failed: ${Fe(e)}`)}}}function _t(){let e=Nh(Me);dy.update({type:"assessment.workers",assessment_workers:e,tool_inventory:Te.tool_inventory,runtime_update:Te.runtime_update,...xs(x.worker_limit)}),dy.flush().catch(t=>console.error(`Assessment status: ${t.message}`))}async function xy(e){let t=Ct(e);return t===Ct(x.worker_limit)?t===null?"Workers are already automatic.":`Workers are already set to ${t}.`:(x={...x,worker_limit:t},await Gt(x),lo(),_t(),t===null?`Workers are automatic again: up to ${Yn()} side by side for this machine's CPU and memory, for assessment stages, generation, test design and Goals (an assessment may ask for fewer). A Goal that uses your working folder still runs alone.`:`Up to ${t} worker${t===1?"":"s"} now run side by side: assessment stages, generation, test design and Goals. A Goal that uses your working folder still runs alone. Running work finishes; waiting work starts as workers free up.`)}function _l(e){if(e!==ii){if(ii=e,!e)for(let t of Me.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."),_t()}}function ky(e,t){Ie.step(e,t)&&ii&&console.log(`[${e}] ${t}`)}function gj(){clearInterval(ti);let e=!1,t=()=>{e||Me.size>0||je.size>0||(e=!0,mr(x,x.workspace).finally(()=>{e=!1}))};t(),ti=setInterval(t,rj),ti.unref?.()}async function mr(e,t,n=zt?.healthChecks()??[]){let r=await Ag({config:e,workspace:t,version:on,insights:n,agentSession:tn,probes:{inspectAgent:(o,s)=>Ne?ee:Es(o,s),inspectTools:o=>Ne?Te.tool_inventory:Ve(o),runnerStatus:Yt}});try{wy=(await Tg(e,r,jt))?.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 $y(e){if(Ne)return dr;let t=e instanceof Error?e.message:String(e),n=await mr(x,x.workspace).catch(()=>null);n&&console.error(xc(n)),le(t)}function py(e){_l(e.connector?.activity_log_enabled===!0),io=e.project_url??null,ro=1e3,wj(),Ft.confirm().catch(t=>console.error(`Connector update state: ${t.message}`)),yj(),x.onboarding_pending&&vl()}async function wj(){if(tn?.state!=="checking"){tn={state:"checking",detail:`Asking ${ee.name} one question to confirm its session.`},console.log(`Checking that ${ee.name} can answer before accepting work.`);try{await Fh(x,ee.name),tn={state:"ready",detail:`${ee.name} answered; its session is usable.`},console.log(tn.detail)}catch(e){let t=ee.sessionStatus?.login_command;tn={state:"failed",detail:e instanceof Error?e.message:String(e),remedy:t?`Sign in to ${ee.name} with Log in on the connected workspace, or run ${t} in ${x.workspace}.`:`Sign in to ${ee.name} in ${x.workspace}, then restart this connector.`},console.error(`${tn.detail}
|
|
840
840
|
${tn.remedy}`)}await mr(x,x.workspace).catch(()=>null)}}function yj(){clearInterval(gl);let e=!1,t=0,n=0,r=!1,o=()=>{Ft.tick(),!r&&Gr(cl.id)&&(r=!0,vy.flush().then(()=>ei(cl)).catch(s=>Zs(cl,s)).finally(()=>{r=!1})),Me.size>0&&_t(),!vt&&Date.now()-t>=sj&&Gr(sl.id)&&(t=Date.now(),Ay().then(()=>ei(sl)).catch(s=>Zs(sl,s))),wy&&!ni&&Gr(il.id)&&Date.now()-_y>=Ap&&(ni=!0,vj().then(()=>ei(il)).catch(s=>Zs(il,s)).finally(()=>{ni=!1})),!e&&Date.now()-n>=ij&&Gr(al.id)&&(e=!0,n=Date.now(),Ve(x.workspace).then(s=>{Te.tool_inventory=s,_t(),ei(al)}).catch(s=>Zs(al,s)).finally(()=>{e=!1}))};o(),gl=setInterval(o,1e4),gj()}function Zs(e,t){let n=Eg(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 ei(e){xg(e.id)&&console.log(`${e.title} recovered.`)}async function vj(){if(!await Sy())return;_y=Date.now();let{jobs:e}=await Yt(x.workspace).catch(()=>({jobs:[]})),t=await Tp(x.workspace,{jobs:e});if(!Rp(t))return;let n=`${t.fingerprint}:${pl.join(",")}`,r=ul?.key===n,o=r?ul.candidates:await Hh(x,t,pl);ul={key:n,candidates:o};let s=await pr(Op(t,o,{version:on}));Array.isArray(s?.refused)&&(pl=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 nn=null,fy=null;async function Ay(){if(vt)return vt;vt=(async()=>{let e=await bp(x,{knownRevision:nn?.revision??null});if(e.unchanged||(nn=e),fy===nn.revision)return nn;let{jobs:t}=await Yt(x.workspace);return!t.some(r=>si.includes(r.status))&&rn===0&&Me.size===0&&(await Tr(x.workspace,nn),fy=nn.revision),nn})();try{return await vt}finally{vt=null,lo()}}function my(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)),je.get(e)?.events.push(n)}var hy=null;function lo(){let e=Ae.readyState===WebSocket.OPEN,t=Me.values().next().value,n=Ct(x.worker_limit)??Math.min(Yn(),uc(t?.workerLimit??ur[0]?.worker_limit)),r=e&&!vt&&rn===0?kh(ur,Me.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:uc(s.worker_limit),lastActivityAt:Date.now(),eventCount:0,lastDetail:null};Me.set(i,a),Ej(s,a)}r.length>0&&_t();let o=$h({queued:ur,running:Me.size,workerLimit:n,connected:e,designSync:!!vt,integrations:rn});o&&o!==hy&&console.log(o),hy=o}function ci(e){let t=pc(e);return t?`${ee.name} on ${t}`:ee.name}async function Ty(e){let t=e.prompt_id,n=`prompt:${String(t).slice(0,8)}`,r=e.purpose||"project",o=Date.now(),s={runId:t,purpose:r,startedAt:o,child:null,controller:null,cancelled:!1,stoppedHere:!1,cancellation:new AbortController,events:dg(pr),executionRevision:Ry(e),sessionKey:ks(e),sessionId:null,replacement:null};je.set(t,s);let i,a=h=>{let w=h?JSON.stringify(h):null;!w||w===i||je.get(t)!==s||(i=w,my(t,h))},c=`${r} \xB7 ${ci(e)}`,l=Dh(e,ee.name);my(t,{kind:"status",message:l});let d=Number(e.answer_within_seconds),p=d>0?o+d*1e3:void 0;console.log([`[${n}] ${l} for ${r}.`,`${ee.name} can reason for several minutes without reporting a step.`,...p?[Cc(p,o)]:[]].join(" ")),Ie.status(n,c,o,{link:io,answerBy:p});let u=h=>{let w=Sh(h),g=cc(h);je.get(t)===s&&ky(n,g??w?.message);let b=h.type==="forge.output"?null:g;a(w??(b?{kind:"status",message:b}:null))},f="failed",m=[r];try{$s(e)||(u({type:"connector.step",message:"Syncing the design context from EngineerOS"}),e={...e,design_context:await xp(Ay,{pinned:!!e.local_design_context,last:nn,onFallback:(b,v)=>u({type:"connector.step",message:`Design context not refreshed (${b.message}); continuing with ${v?"the copy synced earlier":"none"}`})})});let h=await gh(e,x,{onProcess:b=>{je.get(t)===s&&(s.child=b)},onController:b=>{je.get(t)===s&&(s.controller=b)},onSession:b=>{s.sessionId=b},onEvent:u},{signal:s.cancellation.signal});if(s.stoppedHere)throw new Error(gy);let w=h.singleTurn?Ul(x.sessions,h.sessionKey):hi(x.sessions,h.sessionKey,h.sessionId);if(JSON.stringify(w)!==JSON.stringify(x.sessions||{})&&(x={...x,sessions:w},await Gt(x)),s.cancelled)return;await s.events.close().catch(b=>{console.error(`[${n}] Prompt progress delivery: ${b.message} The agent has finished; submitting its complete response separately.`)});let g=await Is(pr,{type:"prompt.completed",prompt_id:t,execution_revision:s.executionRevision,content:h.content,model:h.model,session_id:h.sessionId,usage:h.usage});g||console.error(`[${n}] ${wc}`),oo.record("prompt","completed",{durationMs:Date.now()-o,usage:h.usage}),f=g?"finished":"undelivered",m=[_j(h.usage),r]}catch(h){let w=s.stoppedHere?gy:Fe(h);if(oo.record("prompt","failed",{durationMs:Date.now()-o}),s.stoppedHere&&(f="cancelled"),!s.cancelled){try{await Is(pr,{type:"prompt.failed",prompt_id:t,execution_revision:s.executionRevision,message:w})||console.error(`[${n}] ${wc}`)}catch(g){console.error(`[${n}] Prompt failure delivery: ${g.message}`)}console.error(w)}}finally{s.events.stop();let h=s.replacement;h?(f="replaced",m=[`continuing on ${ci(h)}`,r]):s.cancelled&&(f="cancelled"),Ie.finish(n,f,m),je.get(t)===s&&je.delete(t),h&&Sj(s,h)}}var gy="Cancelled from the connector terminal by the person running it.";function _j(e){let t=Number(e?.total_tokens)||(Number(e?.input_tokens)||0)+(Number(e?.output_tokens)||0);return t?`${t.toLocaleString()} tokens`:null}async function bl(e){e.cancelled=!0,e.cancellation.abort(),await e.controller?.completed.catch(()=>{})}function Ry(e){return Number(e.execution_revision)||1}async function bj(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 ${ci(t)}.`),await bl(e))}function Sj(e,t){e.sessionId&&(x={...x,sessions:hi(x.sessions,e.sessionKey,e.sessionId)},Gt(x).catch(n=>console.error(`Could not save the agent session: ${n.message}`))),Ty(t)}async function Ej(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 ${ci(e)}.`),!dl.has(n)){dl.add(n);try{let y=await vh(x.workspace);if(!y.exists)console.log("No accepted assessment exists yet; this run establishes the baseline.");else{let _=y.accepted_head_revision?y.current_head_revision?y.current_head_revision!==y.accepted_head_revision?`The workspace is now at commit \`${y.current_head_revision}\`; the accepted assessment is from \`${y.accepted_head_revision}\`.`:"The accepted assessment is already at the current commit.":`The accepted assessment is from \`${y.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 ${y.stages.length||"no"} section(s). ${_}`)}}catch(y){console.error(`Assessment freshness check failed: ${y.message}`)}}let o=t.startedAt,s=`assessment:${r}`,i=!1,a=!1,c=5,l=!1,d=!1,p=null,u=null,f=null,m=new Set,h=()=>!Ne&&Me.get(t.key)===t,w=async y=>{try{return await Is(pr,y)||console.warn(`[${s}] ${cg}`),!0}catch(_){return console.error(`Assessment failure delivery: ${_.message}`),!1}},g=(y,{milestone:_=!0}={})=>{if(!h()||_&&f===y)return;_&&(f=y,m.has(y)||(m.add(y),c=Math.min(90,c+10)),console.log(`[assessment:${r}] ${y}.`));let E=String(y).slice(0,500);t.progressPercent=c,t.lastMessage=E,Ie.status(s,E,o,{link:io})};g(`Starting ${r} assessment stage`);let b=setInterval(()=>{let y=Date.now(),_=y-t.lastActivityAt,E=i&&!a?bh(r,_):null;if(!p&&E){p=E,console.error(`[assessment:${r}] ${p}`),fc(t.controller,t.child);return}p||zt.observe({at:y,level:"info",message:Ie.status(s,`${t.lastMessage} \xB7 last agent activity ${be(_)} ago (${t.eventCount.toLocaleString()} events)`,o)})},15e3),v={onSession:async y=>{h()&&(u=String(y),await nu(x.workspace,n,r,y,{sourceRevision:e.source_revision,targetHeadRevision:e.target_head_revision}))},onController:y=>{h()&&(t.controller=y)},onProcess:y=>{h()&&(t.child=y,i=!0,t.phase!=="correcting"&&(t.phase="running",g("Connected agent process started")),t.lastActivityAt=Date.now())},onEvent:y=>{t.lastActivityAt=Date.now(),t.eventCount+=1;let _=_h(y);if(_&&g(_),!h())return;let E=cc(y);!E||E===t.lastDetail||(t.lastDetail=E,ky(s,E))}},$=(y,_)=>ic(y,_,x,v,{draftPath:Re.relative(x.workspace,Re.join(qe(x.workspace,n),y.report_file)).split(Re.sep).join("/")});try{let y=ll-Date.now();y>0&&(g(`Waiting ${Math.ceil(y/1e3)}s for the model provider's rate limit to clear`),await new Promise(R=>setTimeout(R,y+Math.floor(Math.random()*3e3)))),e.assessment_mode==="incremental"&&(c=15,g("Calculating changed files and affected behavior"));let _=await au(x.workspace,e),E=await zi(x.workspace,n,r,{expectedHeadRevision:e.target_head_revision,expectedSourceRevision:e.source_revision});if(E)$(E,_),g("Recovered completed stage report from connector storage");else{if(u=await ru(x.workspace,n,r,{expectedHeadRevision:e.target_head_revision,expectedSourceRevision:e.source_revision}),u&&g("Restoring interrupted agent session"),E=await hh(_,x,v,{previousSessionId:u}),p)throw new Error(p);a=!0,await Fi(x.workspace,n,_,E)}a=!0,t.phase="delivering",t.progressPercent=95,t.lastMessage=r==="synthesis"?"Delivering completed assessment bundle":"Checkpointing connector-local stage result";let O=R=>fetch(Bl(x.server_url,x.connector_id,n),{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${x.token}`},body:JSON.stringify(R),signal:AbortSignal.timeout(ih)}),L=await Lh(E,{submit:R=>Ph(R,O,{isActive:()=>h()&&!Ne,onRetry:(C,S)=>{g("Completed result is waiting for EngineerOS",{milestone:!1}),console.warn(`[assessment:${r}] Completed result delivery failed: ${Fe(C)} Retrying in ${Math.round(S/1e3)}s without rerunning the agent.`)}}),payloadFor:R=>r==="synthesis"?Ui(x.workspace,n,R,{expectedSourceRevision:e.source_revision}):uu(R),rejectionFor:R=>Ts(R,"the assessment"),correct:async(R,C)=>{if(a=!1,t.phase="correcting",t.lastMessage="Correcting a rejected stage result",!R.correctAfterRejection)throw new Error(`${C} The connector could not start the required agent correction.`);return R.correctAfterRejection(C)},onCorrected:async R=>{if(p)throw new Error(p);a=!0,await su(x.workspace,n,r);let C=await Fi(x.workspace,n,_,R);return $(C,_),t.phase="delivering",t.lastMessage="Delivering corrected stage result",C}});if(p)throw new Error(p);E=L.result;let I=L.response;if(!I.ok)throw new Error(await Ts(I,"the assessment"));if(l=!0,oo.record("assessment stage","completed",{durationMs:Date.now()-o,usage:E.usage}),r==="synthesis"){let R=await I.json(),C=await cu(x.workspace,n,e,E,R.report_markdown);console.log(`Workspace assessment ${n} was accepted by EngineerOS and saved to ${Re.relative(x.workspace,C)}.`);try{let S=await ho(x.workspace);S.committed&&console.log(`Assessment committed to Git as ${S.revision.slice(0,8)}.`)}catch(S){console.error(`The assessment is saved locally but could not be committed to Git: ${S.message}`)}}else console.log(`Workspace assessment stage ${r} was checkpointed by EngineerOS.`)}catch(y){let _=p||Fe(y),E=Ih(e,y),O=jh(y),A=Th(y);O&&(await ou(x.workspace,n,r).catch(I=>{console.error(`[assessment:${r}] Could not discard the unusable agent session checkpoint: ${I.message}`)}),u=null);let L=!p&&(u||O)&&(O||Ah(y))&&E<A;if(h()&&L){t.phase="starting",t.lastMessage=O?"Agent session became unusable; restarting from saved assessment work":"Agent session interrupted; resuming checkpoint",t.resumeAssignment=Ch(e,y);let I=Oh(y,E);Lr(y)&&(ll=Math.max(ll,Date.now()+I)),console.warn(`[assessment:${r}] ${O?"Agent session became unusable":"Agent session interrupted"}: ${_} ${O?"Starting a fresh session from the saved draft":`Resuming session ${u}`} in ${Math.round(I/1e3)}s (${E+1}/${A}).`),await new Promise(R=>setTimeout(R,I))}else h()&&(d=await w({type:"workspace.assessment.failed",assessment_id:n,stage:r,message:_}));L||(oo.record("assessment stage","failed",{durationMs:Date.now()-o}),console.error(`[assessment:${r}] ${_}`))}finally{clearInterval(b),Ie.clearStatus(s),r==="synthesis"&&l&&dl.delete(n),h()&&(Me.delete(t.key),Mh(ur,t,{accepted:l,failureReported:d})&&console.log(`Resuming interrupted agent session for assessment stage ${r} from its checkpoint.`),lo())}}async function xj(e){let t=String(e.run_id||"");rn+=1;try{vt&&await vt;let n=await ch(x.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 vl();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: ${Fe(n)}`)}finally{rn-=1,lo()}}function kj(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{le('--agent-args must be a JSON array, for example: --agent-args "[\\"acp\\"]"')}}function le(e){console.error(e),process.exit(1)}
|