@oss-autopilot/core 1.12.1 → 1.13.0

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.
@@ -92,7 +92,7 @@ Capacity: ${e.hasCapacity?"\u2705 Ready for new work":"\u26A0\uFE0F Focus on ex
92
92
  `),n=[],o=[],r="Uncategorized",i=null,s=!1;for(let a of e){let c=a.match(/^#{1,3}\s+(.+)/);if(c){r=c[1].trim(),i=null;continue}if(!a.trim()||!/^\s*[-*+]|\s*\d+\.|\s*\[[ xX]\]/.test(a))continue;let u=uk(a);if(!u){if(i&&/^\s{2,}/.test(a)){let p=dk(a);if(p!==void 0&&(i.score=p),s&&(pk(a)||jI(a))){let g=n.indexOf(i);g!==-1&&(n.splice(g,1),o.push(i),s=!1)}}continue}let l=UI(a),d={repo:u.repo,number:u.number,title:l||`#${u.number}`,tier:r,url:u.url};lk(a)?(o.push(d),s=!1):(n.push(d),s=!0),i=d}return{available:n,completed:o,availableCount:n.length,completedCount:o.length}}function Qf(t,e=6){let n=t.split(`
93
93
  `),o=[],r=0,i=!1;for(let c=0;c<n.length;c++){let u=n[c];if(/^#{1,3}\s+/.test(u)){i=!1,o.push(u);continue}if(i&&/^\s{2,}/.test(u))continue;if(i=!1,/^\s*[-*+]\s/.test(u)&&lk(u)){r++,i=!0;continue}if(uk(u)){let p=!1,g=c+1;for(;g<n.length&&/^\s{2,}/.test(n[g]);){pk(n[g])&&(p=!0);let b=dk(n[g]);b!==void 0&&b<e&&(p=!0),g++}if(p){r++,i=!0;continue}}/^\s*skip\s*\(\d+\s*issues?\)/i.test(u.replace(/[#*]/g,"").trim())||/^---\s*$/.test(u)||/^\s*(###?\s*)?(Removed|Previously dropped)/i.test(u)||/^>\s/.test(u)||o.push(u)}let s=[];for(let c=0;c<o.length;c++){if(/^#{1,3}\s+/.test(o[c])){let l=c+1;for(;l<o.length&&o[l].trim()==="";)l++;if(l>=o.length||/^#{1,3}\s+/.test(o[l]))continue}s.push(o[c])}let a=[];for(let c of s)c.trim()===""&&a.length>0&&a[a.length-1].trim()===""||a.push(c);for(;a.length>0&&a[a.length-1].trim()==="";)a.pop();return{pruned:a.join(`
94
94
  `)+`
95
- `,removedCount:r}}async function eh(t){let e=ck.resolve(t.filePath);if(!Pc.existsSync(e))throw new Error(`File not found: ${e}`);let n;try{n=Pc.readFileSync(e,"utf-8")}catch(o){let r=A(o);throw new Error(`Failed to read file: ${r}`,{cause:o})}return Cc(n)}var Pc,ck,Ic=v(()=>{"use strict";Pc=K(require("fs"),1),ck=K(require("path"),1);Se()});function ji(){return fk.join(yt(),"dashboard-server.pid")}function Ac(t){_o.writeFileSync(ji(),JSON.stringify(t),{mode:384})}function wo(){try{let t=_o.readFileSync(ji(),"utf-8"),e=JSON.parse(t);return typeof e!="object"||e===null||typeof e.pid!="number"||!Number.isInteger(e.pid)||e.pid<=0||typeof e.port!="number"||typeof e.startedAt!="string"?(y(Oc,"PID file has invalid structure, ignoring"),null):e}catch(t){return t.code!=="ENOENT"&&y(Oc,`Failed to read PID file: ${t.message}`),null}}function Cr(){try{_o.unlinkSync(ji())}catch(t){t.code!=="ENOENT"&&y(Oc,`Failed to remove PID file: ${t.message}`)}}function Fi(t){return new Promise(e=>{let n=gk.get(`http://127.0.0.1:${t}/api/data`,{timeout:2e3},o=>{o.resume(),e(o.statusCode===200)});n.on("error",()=>e(!1)),n.on("timeout",()=>{n.destroy(),e(!1)})})}async function Dc(){let t=wo();if(!t)return null;try{process.kill(t.pid,0)}catch(e){let n=e.code;return n!=="ESRCH"&&n!=="EPERM"&&y(Oc,`Unexpected error checking PID ${t.pid}: ${e.message}`),Cr(),null}return await Fi(t.port)?{port:t.port,url:`http://oss.localhost:${t.port}`}:(Cr(),null)}var gk,_o,fk,Oc,Uc=v(()=>{"use strict";gk=K(require("http"),1),_o=K(require("fs"),1),fk=K(require("path"),1);be();$e();Oc="dashboard-server"});var So,hk=v(()=>{"use strict";So=class{maxRequests;windowMs;timestamps=[];constructor(e){this.maxRequests=e.maxRequests,this.windowMs=e.windowMs}check(){let e=Date.now(),n=e-this.windowMs;if(this.timestamps=this.timestamps.filter(o=>o>n),this.timestamps.length>=this.maxRequests){let r=this.timestamps[0]+this.windowMs-e;return{allowed:!1,retryAfterSeconds:Math.ceil(r/1e3)}}return this.timestamps.push(e),{allowed:!0}}}});var un={};oe(un,{VALID_TARGETS:()=>th,runMove:()=>FI});async function FI(t){Ue(t.prUrl),qe(t.prUrl,ar,"PR");let e=t.target;if(!th.includes(e))throw new Error(`Invalid target "${t.target}". Must be one of: ${th.join(", ")}`);let n=V();switch(e){case"attention":case"waiting":{let o=e==="attention"?"needs_addressing":"waiting_on_maintainer",r=e==="attention"?"Need Attention":"Waiting on Maintainer",i=new Date().toISOString();return n.batch(()=>{n.setStatusOverride(t.prUrl,o,i),n.unshelvePR(t.prUrl)}),{url:t.prUrl,target:e,description:`Moved to ${r}`}}case"shelved":return n.batch(()=>{n.shelvePR(t.prUrl),n.clearStatusOverride(t.prUrl)}),{url:t.prUrl,target:e,description:"Shelved \u2014 excluded from capacity and actionable items"};case"auto":return n.batch(()=>{n.clearStatusOverride(t.prUrl),n.unshelvePR(t.prUrl)}),{url:t.prUrl,target:e,description:"Reset to computed status"};default:{let o=e;throw new Error(`Unhandled move target: ${o}`)}}}var th,ln=v(()=>{"use strict";be();Ot();th=["attention","waiting","shelved","auto"]});var wk={};oe(wk,{findRunningDashboardServer:()=>Dc,getDashboardPidPath:()=>ji,isDashboardServerRunning:()=>Fi,readDashboardServerInfo:()=>wo,removeDashboardServerInfo:()=>Cr,startDashboardServer:()=>ZI,writeDashboardServerInfo:()=>Ac});function NI(){try{let t=$o();if(!t)return null;let e=Gi.readFileSync(t.path,"utf-8");return Cc(e)}catch(t){return y(Xe,`Failed to read vetted issue list: ${A(t)}`),null}}function zi(t,e,n,o,r){let i=W$(t,e),s=J$(i),{monthlyMerged:a,monthlyOpened:c,monthlyClosed:u}=K$(e),l=o??Wf(V().getMergedPRs()),d=r??Jf(V().getClosedPRs()),p=e.config.minStars??50,g=e.repoScores||{},b=R=>!Zt(g[R.repo]?.stargazersCount,p),S=l.filter(b),F=d.filter(b),T=B$(t,e,S.length,F.length),C=e.config.dismissedIssues||{},x=n.filter(R=>R.status==="new_response"&&!(R.url in C)),M={};for(let[R,L]of Object.entries(g))(L.stargazersCount!==void 0||L.language!==void 0)&&(M[R]={stars:L.stargazersCount,language:L.language});let j=NI();return j&&(T.availableIssues=j.availableCount),{stats:T,prsByRepo:i,topRepos:s.map(([R,L])=>({repo:R,...L})),monthlyMerged:a,monthlyOpened:c,monthlyClosed:u,activePRs:Rr(t.openPRs||[],e),shelvedPRUrls:e.config.shelvedPRUrls||[],recentlyMergedPRs:t.recentlyMergedPRs||[],recentlyClosedPRs:t.recentlyClosedPRs||[],autoUnshelvedPRs:t.autoUnshelvedPRs||[],commentedIssues:n,issueResponses:x,allMergedPRs:S,allClosedPRs:F,repoMetadata:M,vettedIssues:j}}function MI(t,e=zI){return new Promise((n,o)=>{let r=[],i=0,s=!1;t.on("data",a=>{if(!s){if(i+=a.length,i>e){s=!0,t.destroy(),o(new Error("Body too large"));return}r.push(a)}}),t.on("end",()=>{s||n(Buffer.concat(r).toString("utf-8"))}),t.on("error",a=>{s||o(a)})})}function _k(t){t.setHeader("X-Content-Type-Options","nosniff"),t.setHeader("X-Frame-Options","DENY"),t.setHeader("Content-Security-Policy","default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'"),t.setHeader("Referrer-Policy","strict-origin-when-cross-origin")}function yk(t,e){let n=t.headers.origin;return n?[`http://localhost:${e}`,`http://127.0.0.1:${e}`,`http://oss.localhost:${e}`].includes(n):!0}function jc(t,e,n){_k(t),t.setHeader("Cache-Control","no-store");let o=JSON.stringify(n);t.writeHead(e,{"Content-Type":"application/json","Content-Length":Buffer.byteLength(o)}),t.end(o)}function Ee(t,e,n){jc(t,e,{error:n})}async function ZI(t){let{port:e,assetsDir:n,token:o,open:r}=t,i=V(),s=Wt.resolve(n),a=i.getState().lastDigest,c=[];if(!a)throw new Error("No dashboard data available. Run the daily check first: GITHUB_TOKEN=$(gh auth token) npm start -- daily");let u;try{u=zi(a,i.getState(),c)}catch(j){throw new Error(`Failed to build dashboard data: ${A(j)}. State data may be corrupted \u2014 try running: daily --json`,{cause:j})}let l=new So({maxRequests:30,windowMs:6e4}),d=new So({maxRequests:10,windowMs:6e4}),p=new So({maxRequests:6,windowMs:6e4}),g=bk.createServer(async(j,R)=>{let L=j.method||"GET",Y=j.url||"/";try{if(Y==="/api/data"&&L==="GET"){let Z=l.check();if(!Z.allowed){R.setHeader("Retry-After",String(Z.retryAfterSeconds)),Ee(R,429,"Too many requests");return}let se=!1;if(i.isGistMode()?se=await i.refreshFromGist():se=i.reloadIfChanged(),se)try{u=zi(a,i.getState(),c)}catch(je){y(Xe,`Failed to rebuild dashboard data after state reload: ${A(je)}`)}jc(R,200,u);return}if(Y==="/api/action"&&L==="POST"){if(!yk(j,C)){Ee(R,403,"Invalid origin");return}let Z=d.check();if(!Z.allowed){R.setHeader("Retry-After",String(Z.retryAfterSeconds)),Ee(R,429,"Too many requests");return}await b(j,R);return}if(Y==="/api/refresh"&&L==="POST"){if(!yk(j,C)){Ee(R,403,"Invalid origin");return}let Z=p.check();if(!Z.allowed){R.setHeader("Retry-After",String(Z.retryAfterSeconds)),Ee(R,429,"Too many requests");return}await S(j,R);return}if(L==="GET"){F(Y,R);return}Ee(R,405,"Method not allowed")}catch(Z){y(Xe,`Unhandled request error: ${L} ${Y} ${A(Z)}`),R.headersSent||Ee(R,500,"Internal server error")}});g.requestTimeout=GI;async function b(j,R){i.isGistMode()?await i.refreshFromGist():i.reloadIfChanged();let L;try{let Z=await MI(j);L=JSON.parse(Z)}catch(Z){let se=Z instanceof Error&&Z.message==="Body too large";Ee(R,se?413:400,se?"Request body too large":"Invalid JSON body");return}if(!L.action||!vk.has(L.action)){Ee(R,400,`Invalid action. Must be one of: ${[...vk].join(", ")}`);return}if(!L.url||typeof L.url!="string"){Ee(R,400,'Missing or invalid "url" field');return}let Y=L.action==="dismiss_issue_response";try{Ue(L.url),qe(L.url,Y?cr:ar,Y?"issue":"PR")}catch(Z){Z instanceof we?Ee(R,400,Z.message):(y(Xe,`Unexpected error during URL validation: ${A(Z)}`),Ee(R,400,"Invalid URL"));return}try{if(L.action==="move"){let{VALID_TARGETS:Z,runMove:se}=await Promise.resolve().then(()=>(ln(),un));if(!L.target||!Z.includes(L.target)){Ee(R,400,`move requires a valid "target" field (${Z.join(", ")})`);return}await se({prUrl:L.url,target:L.target})}else i.dismissIssue(L.url,new Date().toISOString())}catch(Z){y(Xe,`Action failed: ${L.action} ${L.url} ${A(Z)}`),Ee(R,500,"Action failed");return}u=zi(a,i.getState(),c),jc(R,200,u)}async function S(j,R){let L=o||Mt();if(!L){Ee(R,401,"No GitHub token available. Cannot refresh data.");return}try{i.isGistMode()?await i.refreshFromGist():i.reloadIfChanged(),y(Xe,"Refreshing dashboard data from GitHub...");let Y=await Bf(L);a=Y.digest,c=Y.commentedIssues,u=zi(a,i.getState(),c,Y.allMergedPRs,Y.allClosedPRs),jc(R,200,u)}catch(Y){y(Xe,`Dashboard refresh failed: ${A(Y)}`),Ee(R,500,"Refresh failed")}}function F(j,R){let L;try{L=decodeURIComponent(j.split("?")[0])}catch{y(Xe,`Malformed URL received: ${j}`),Ee(R,400,"Malformed URL");return}if(L.includes("..")){Ee(R,403,"Forbidden");return}let Y=L==="/"?"index.html":L.replace(/^\/+/,""),Z=Wt.join(s,Y);if(!Z.startsWith(s+Wt.sep)&&Z!==s){Ee(R,403,"Forbidden");return}try{Gi.statSync(Z).isDirectory()&&(Z=Wt.join(s,"index.html"))}catch(_e){if(_e.code==="ENOENT")Z=Wt.join(s,"index.html");else{y(Xe,`Failed to stat file: ${Z}`),Ee(R,500,"Internal server error");return}}let se=Wt.extname(Z).toLowerCase(),je=LI[se]||"application/octet-stream";try{let _e=Gi.readFileSync(Z);_k(R),R.writeHead(200,{"Content-Type":je,"Content-Length":_e.length,"Cache-Control":"public, max-age=3600"}),R.end(_e)}catch(_e){_e.code==="ENOENT"?Ee(R,404,"Not found"):(y(Xe,`Failed to serve static file: ${Z}`),Ee(R,500,"Failed to read file"))}}let T=10,C=e;for(let j=0;j<T;j++)try{await new Promise((R,L)=>{g.once("error",L),g.listen(C,"127.0.0.1",()=>R())});break}catch(R){let L=R;if(L.code==="EADDRINUSE"&&j<T-1){y(Xe,`Port ${C} is in use, trying ${C+1}...`),C++;continue}throw new Error(`Failed to start server: ${L.message}`,{cause:R})}Ac({pid:process.pid,port:C,startedAt:new Date().toISOString(),version:xt()});let x=`http://oss.localhost:${C}`;y(Xe,`Dashboard server running at ${x} (also: http://localhost:${C})`),o&&Bf(o).then(async j=>{i.isGistMode()?await i.refreshFromGist():i.reloadIfChanged(),a=j.digest,c=j.commentedIssues,u=zi(a,i.getState(),c,j.allMergedPRs,j.allClosedPRs),y(Xe,"Background data refresh complete")}).catch(j=>{y(Xe,`Background data refresh failed (serving cached data): ${A(j)}`)}),r&&Fc(x);let M=()=>{y(Xe,"Shutting down dashboard server..."),Cr(),g.close(()=>{process.exit(0)}),setTimeout(()=>process.exit(0),3e3).unref()};process.on("SIGINT",M),process.on("SIGTERM",M)}var bk,Gi,Wt,vk,Xe,zI,GI,LI,Sk=v(()=>{"use strict";bk=K(require("http"),1),Gi=K(require("fs"),1),Wt=K(require("path"),1);be();Se();$e();Ot();Kf();zc();Ic();Uc();hk();wr();Uc();vk=new Set(["move","dismiss_issue_response"]),Xe="dashboard-server",zI=10240,GI=3e4,LI={".html":"text/html",".js":"application/javascript",".css":"text/css",".svg":"image/svg+xml",".json":"application/json",".png":"image/png",".ico":"image/x-icon"}});var $k={};oe($k,{resolveAssetsDir:()=>Lc,serveDashboard:()=>VI});function Lc(){let t=At.resolve(__dirname,"../../dashboard/dist");if(Gc.existsSync(At.join(t,"index.html")))return t;let e=At.resolve(At.dirname(process.argv[1]),"../../dashboard/dist");if(Gc.existsSync(At.join(e,"index.html")))return e;try{let n=require.resolve("@oss-autopilot/dashboard/package.json"),o=At.join(At.dirname(n),"dist");if(Gc.existsSync(At.join(o,"index.html")))return o}catch(n){n.code!=="MODULE_NOT_FOUND"&&console.error("Error resolving dashboard package:",n)}return null}async function VI(t){let e=Lc();e||(console.error("Could not find dashboard SPA assets."),console.error("Make sure packages/dashboard has been built:"),console.error(" cd packages/dashboard && pnpm run build"),process.exit(1));let n=Mt(),{startDashboardServer:o}=await Promise.resolve().then(()=>(Sk(),wk));await o({port:t.port,assetsDir:e,token:n,open:t.open})}var Gc,At,rh=v(()=>{"use strict";Gc=K(require("fs"),1),At=K(require("path"),1);be()});function WI(t){return new Promise(e=>setTimeout(e,t))}async function Tk(t){if(!Lc())return null;let n=await Dc();if(n){let c=wo(),u=xt();if(c)if(c.version&&u!=="0.0.0"&&c.version!==u){console.error(`[STARTUP] Dashboard server version mismatch (running: ${c.version}, current: ${u}). Restarting...`);let l=!1;try{process.kill(c.pid,"SIGTERM"),l=!0}catch(d){d.code==="ESRCH"?l=!0:console.error(`[STARTUP] Could not kill outdated dashboard (PID ${c.pid}): ${d.message}`)}if(l)Cr();else return{url:n.url,port:n.port,alreadyRunning:!0}}else return{url:n.url,port:n.port,alreadyRunning:!0}}let o=t?.port??HI,r=process.argv[1],i=(0,kk.spawn)("node",[r,"dashboard","serve","--port",String(o),"--no-open"],{detached:!0,stdio:"ignore"}),s=!1,a=!1;i.on("error",c=>{s=!0,console.error(`[STARTUP] Failed to spawn dashboard server: ${c.message}`)}),i.on("exit",c=>{a=!0,c!==0&&c!==null&&console.error(`[STARTUP] Dashboard server exited prematurely (code ${c})`)}),i.unref();for(let c=0;c<BI;c++){if(await WI(qI),s||a)return null;let u=wo();if(u&&await Fi(u.port))return{url:`http://oss.localhost:${u.port}`,port:u.port,alreadyRunning:!1}}if(console.error("[STARTUP] Dashboard server failed to start within 5 seconds"),i.pid)try{process.kill(i.pid,"SIGTERM")}catch(c){c.code!=="ESRCH"&&console.error(`[STARTUP] Failed to kill orphan dashboard process (PID ${i.pid}): ${c.message}`)}return null}var kk,HI,qI,BI,Rk=v(()=>{"use strict";kk=require("child_process");Uc();rh();be();HI=3e3,qI=200,BI=25});var Ck={};oe(Ck,{countIssueListItems:()=>Pk,detectIssueList:()=>$o,openInBrowser:()=>Fc,parseIssueListPathFromConfig:()=>xk,runStartup:()=>KI});function xk(t){let e=t.match(/^---\n([\s\S]*?)\n---/);if(!e)return;let o=e[1].match(/issueListPath:\s*["']?([^"'\n]+)["']?/);return o?o[1].trim():void 0}function Pk(t){let e=0,n=0,o=t.split(`
95
+ `,removedCount:r}}async function eh(t){let e=ck.resolve(t.filePath);if(!Pc.existsSync(e))throw new Error(`File not found: ${e}`);let n;try{n=Pc.readFileSync(e,"utf-8")}catch(o){let r=A(o);throw new Error(`Failed to read file: ${r}`,{cause:o})}return Cc(n)}var Pc,ck,Ic=v(()=>{"use strict";Pc=K(require("fs"),1),ck=K(require("path"),1);Se()});function ji(){return fk.join(yt(),"dashboard-server.pid")}function Ac(t){_o.writeFileSync(ji(),JSON.stringify(t),{mode:384})}function wo(){try{let t=_o.readFileSync(ji(),"utf-8"),e=JSON.parse(t);return typeof e!="object"||e===null||typeof e.pid!="number"||!Number.isInteger(e.pid)||e.pid<=0||typeof e.port!="number"||typeof e.startedAt!="string"?(y(Oc,"PID file has invalid structure, ignoring"),null):e}catch(t){return t.code!=="ENOENT"&&y(Oc,`Failed to read PID file: ${t.message}`),null}}function Cr(){try{_o.unlinkSync(ji())}catch(t){t.code!=="ENOENT"&&y(Oc,`Failed to remove PID file: ${t.message}`)}}function Fi(t){return new Promise(e=>{let n=gk.get(`http://127.0.0.1:${t}/api/data`,{timeout:2e3},o=>{o.resume(),e(o.statusCode===200)});n.on("error",()=>e(!1)),n.on("timeout",()=>{n.destroy(),e(!1)})})}async function Dc(){let t=wo();if(!t)return null;try{process.kill(t.pid,0)}catch(e){let n=e.code;return n!=="ESRCH"&&n!=="EPERM"&&y(Oc,`Unexpected error checking PID ${t.pid}: ${e.message}`),Cr(),null}return await Fi(t.port)?{port:t.port,url:`http://oss.localhost:${t.port}`}:(Cr(),null)}var gk,_o,fk,Oc,Uc=v(()=>{"use strict";gk=K(require("http"),1),_o=K(require("fs"),1),fk=K(require("path"),1);be();$e();Oc="dashboard-server"});var So,hk=v(()=>{"use strict";So=class{maxRequests;windowMs;timestamps=[];constructor(e){this.maxRequests=e.maxRequests,this.windowMs=e.windowMs}check(){let e=Date.now(),n=e-this.windowMs;if(this.timestamps=this.timestamps.filter(o=>o>n),this.timestamps.length>=this.maxRequests){let r=this.timestamps[0]+this.windowMs-e;return{allowed:!1,retryAfterSeconds:Math.ceil(r/1e3)}}return this.timestamps.push(e),{allowed:!0}}}});var un={};oe(un,{VALID_TARGETS:()=>th,runMove:()=>FI});async function FI(t){Ue(t.prUrl),qe(t.prUrl,ar,"PR");let e=t.target;if(!th.includes(e))throw new Error(`Invalid target "${t.target}". Must be one of: ${th.join(", ")}`);let n=V();switch(e){case"attention":case"waiting":{let o=e==="attention"?"needs_addressing":"waiting_on_maintainer",r=e==="attention"?"Need Attention":"Waiting on Maintainer",i=new Date().toISOString();return n.batch(()=>{n.setStatusOverride(t.prUrl,o,i),n.unshelvePR(t.prUrl)}),{url:t.prUrl,target:e,description:`Moved to ${r}`}}case"shelved":return n.batch(()=>{n.shelvePR(t.prUrl),n.clearStatusOverride(t.prUrl)}),{url:t.prUrl,target:e,description:"Shelved \u2014 excluded from capacity and actionable items"};case"auto":return n.batch(()=>{n.clearStatusOverride(t.prUrl),n.unshelvePR(t.prUrl)}),{url:t.prUrl,target:e,description:"Reset to computed status"};default:{let o=e;throw new Error(`Unhandled move target: ${o}`)}}}var th,ln=v(()=>{"use strict";be();Ot();th=["attention","waiting","shelved","auto"]});var wk={};oe(wk,{findRunningDashboardServer:()=>Dc,getDashboardPidPath:()=>ji,isDashboardServerRunning:()=>Fi,readDashboardServerInfo:()=>wo,removeDashboardServerInfo:()=>Cr,startDashboardServer:()=>ZI,writeDashboardServerInfo:()=>Ac});function NI(){try{let t=$o();if(!t)return null;let e=Gi.readFileSync(t.path,"utf-8");return Cc(e)}catch(t){return y(Xe,`Failed to read vetted issue list: ${A(t)}`),null}}function zi(t,e,n,o,r){let i=W$(t,e),s=J$(i),{monthlyMerged:a,monthlyOpened:c,monthlyClosed:u}=K$(e),l=o??Wf(V().getMergedPRs()),d=r??Jf(V().getClosedPRs()),p=e.config.minStars??50,g=e.repoScores||{},b=R=>!Zt(g[R.repo]?.stargazersCount,p),S=l.filter(b),F=d.filter(b),T=B$(t,e,S.length,F.length),C=e.config.dismissedIssues||{},x=n.filter(R=>R.status==="new_response"&&!(R.url in C)),M={};for(let[R,L]of Object.entries(g))(L.stargazersCount!==void 0||L.language!==void 0)&&(M[R]={stars:L.stargazersCount,language:L.language});let j=NI();return j&&(T.availableIssues=j.availableCount),{stats:T,prsByRepo:i,topRepos:s.map(([R,L])=>({repo:R,...L})),monthlyMerged:a,monthlyOpened:c,monthlyClosed:u,activePRs:Rr(t.openPRs||[],e),shelvedPRUrls:e.config.shelvedPRUrls||[],recentlyMergedPRs:t.recentlyMergedPRs||[],recentlyClosedPRs:t.recentlyClosedPRs||[],autoUnshelvedPRs:t.autoUnshelvedPRs||[],commentedIssues:n,issueResponses:x,allMergedPRs:S,allClosedPRs:F,repoMetadata:M,vettedIssues:j}}function MI(t,e=zI){return new Promise((n,o)=>{let r=[],i=0,s=!1;t.on("data",a=>{if(!s){if(i+=a.length,i>e){s=!0,t.destroy(),o(new Error("Body too large"));return}r.push(a)}}),t.on("end",()=>{s||n(Buffer.concat(r).toString("utf-8"))}),t.on("error",a=>{s||o(a)})})}function _k(t){t.setHeader("X-Content-Type-Options","nosniff"),t.setHeader("X-Frame-Options","DENY"),t.setHeader("Content-Security-Policy","default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data:; connect-src 'self'"),t.setHeader("Referrer-Policy","strict-origin-when-cross-origin")}function yk(t,e){let n=t.headers.origin;return n?[`http://localhost:${e}`,`http://127.0.0.1:${e}`,`http://oss.localhost:${e}`].includes(n):!0}function jc(t,e,n){_k(t),t.setHeader("Cache-Control","no-store");let o=JSON.stringify(n);t.writeHead(e,{"Content-Type":"application/json","Content-Length":Buffer.byteLength(o)}),t.end(o)}function Ee(t,e,n){jc(t,e,{error:n})}async function ZI(t){let{port:e,assetsDir:n,token:o,open:r}=t,i=V(),s=Wt.resolve(n),a=i.getState().lastDigest,c=[];if(!a)throw new Error("No dashboard data available. Run the daily check first: GITHUB_TOKEN=$(gh auth token) npm start -- daily");let u;try{u=zi(a,i.getState(),c)}catch(j){throw new Error(`Failed to build dashboard data: ${A(j)}. State data may be corrupted \u2014 try running: daily --json`,{cause:j})}let l=new So({maxRequests:30,windowMs:6e4}),d=new So({maxRequests:10,windowMs:6e4}),p=new So({maxRequests:6,windowMs:6e4}),g=bk.createServer(async(j,R)=>{let L=j.method||"GET",Y=j.url||"/";try{if(Y==="/api/data"&&L==="GET"){let Z=l.check();if(!Z.allowed){R.setHeader("Retry-After",String(Z.retryAfterSeconds)),Ee(R,429,"Too many requests");return}let se=!1;if(i.isGistMode()?se=await i.refreshFromGist():se=i.reloadIfChanged(),se)try{u=zi(a,i.getState(),c)}catch(je){y(Xe,`Failed to rebuild dashboard data after state reload: ${A(je)}`)}jc(R,200,u);return}if(Y==="/api/action"&&L==="POST"){if(!yk(j,C)){Ee(R,403,"Invalid origin");return}let Z=d.check();if(!Z.allowed){R.setHeader("Retry-After",String(Z.retryAfterSeconds)),Ee(R,429,"Too many requests");return}await b(j,R);return}if(Y==="/api/refresh"&&L==="POST"){if(!yk(j,C)){Ee(R,403,"Invalid origin");return}let Z=p.check();if(!Z.allowed){R.setHeader("Retry-After",String(Z.retryAfterSeconds)),Ee(R,429,"Too many requests");return}await S(j,R);return}if(L==="GET"){F(Y,R);return}Ee(R,405,"Method not allowed")}catch(Z){y(Xe,`Unhandled request error: ${L} ${Y} ${A(Z)}`),R.headersSent||Ee(R,500,"Internal server error")}});g.requestTimeout=GI;async function b(j,R){i.isGistMode()?await i.refreshFromGist():i.reloadIfChanged();let L;try{let Z=await MI(j);L=JSON.parse(Z)}catch(Z){let se=Z instanceof Error&&Z.message==="Body too large";Ee(R,se?413:400,se?"Request body too large":"Invalid JSON body");return}if(!L.action||!vk.has(L.action)){Ee(R,400,`Invalid action. Must be one of: ${[...vk].join(", ")}`);return}if(!L.url||typeof L.url!="string"){Ee(R,400,'Missing or invalid "url" field');return}let Y=L.action==="dismiss_issue_response";try{Ue(L.url),qe(L.url,Y?cr:ar,Y?"issue":"PR")}catch(Z){Z instanceof we?Ee(R,400,Z.message):(y(Xe,`Unexpected error during URL validation: ${A(Z)}`),Ee(R,400,"Invalid URL"));return}try{if(L.action==="move"){let{VALID_TARGETS:Z,runMove:se}=await Promise.resolve().then(()=>(ln(),un));if(!L.target||!Z.includes(L.target)){Ee(R,400,`move requires a valid "target" field (${Z.join(", ")})`);return}await se({prUrl:L.url,target:L.target})}else i.dismissIssue(L.url,new Date().toISOString())}catch(Z){y(Xe,`Action failed: ${L.action} ${L.url} ${A(Z)}`),Ee(R,500,"Action failed");return}u=zi(a,i.getState(),c),jc(R,200,u)}async function S(j,R){let L=o||Mt();if(!L){Ee(R,401,"No GitHub token available. Cannot refresh data.");return}try{i.isGistMode()?await i.refreshFromGist():i.reloadIfChanged(),y(Xe,"Refreshing dashboard data from GitHub...");let Y=await Bf(L);a=Y.digest,c=Y.commentedIssues,u=zi(a,i.getState(),c,Y.allMergedPRs,Y.allClosedPRs),jc(R,200,u)}catch(Y){y(Xe,`Dashboard refresh failed: ${A(Y)}`),Ee(R,500,"Refresh failed")}}function F(j,R){let L;try{L=decodeURIComponent(j.split("?")[0])}catch{y(Xe,`Malformed URL received: ${j}`),Ee(R,400,"Malformed URL");return}if(L.includes("..")){Ee(R,403,"Forbidden");return}let Y=L==="/"?"index.html":L.replace(/^\/+/,""),Z=Wt.join(s,Y);if(!Z.startsWith(s+Wt.sep)&&Z!==s){Ee(R,403,"Forbidden");return}try{Gi.statSync(Z).isDirectory()&&(Z=Wt.join(s,"index.html"))}catch(_e){if(_e.code==="ENOENT")Z=Wt.join(s,"index.html");else{y(Xe,`Failed to stat file: ${Z}`),Ee(R,500,"Internal server error");return}}let se=Wt.extname(Z).toLowerCase(),je=LI[se]||"application/octet-stream";try{let _e=Gi.readFileSync(Z);_k(R),R.writeHead(200,{"Content-Type":je,"Content-Length":_e.length,"Cache-Control":"public, max-age=3600"}),R.end(_e)}catch(_e){_e.code==="ENOENT"?Ee(R,404,"Not found"):(y(Xe,`Failed to serve static file: ${Z}`),Ee(R,500,"Failed to read file"))}}let T=10,C=e;for(let j=0;j<T;j++)try{await new Promise((R,L)=>{g.once("error",L),g.listen(C,"127.0.0.1",()=>R())});break}catch(R){let L=R;if(L.code==="EADDRINUSE"&&j<T-1){y(Xe,`Port ${C} is in use, trying ${C+1}...`),C++;continue}throw new Error(`Failed to start server: ${L.message}`,{cause:R})}Ac({pid:process.pid,port:C,startedAt:new Date().toISOString(),version:xt()});let x=`http://oss.localhost:${C}`;y(Xe,`Dashboard server running at ${x} (also: http://localhost:${C})`),o&&Bf(o).then(async j=>{i.isGistMode()?await i.refreshFromGist():i.reloadIfChanged(),a=j.digest,c=j.commentedIssues,u=zi(a,i.getState(),c,j.allMergedPRs,j.allClosedPRs),y(Xe,"Background data refresh complete")}).catch(j=>{y(Xe,`Background data refresh failed (serving cached data): ${A(j)}`)}),r&&Fc(x);let M=()=>{y(Xe,"Shutting down dashboard server..."),Cr(),g.close(()=>{process.exit(0)}),setTimeout(()=>process.exit(0),3e3).unref()};process.on("SIGINT",M),process.on("SIGTERM",M)}var bk,Gi,Wt,vk,Xe,zI,GI,LI,Sk=v(()=>{"use strict";bk=K(require("http"),1),Gi=K(require("fs"),1),Wt=K(require("path"),1);be();Se();$e();Ot();Kf();zc();Ic();Uc();hk();wr();Uc();vk=new Set(["move","dismiss_issue_response"]),Xe="dashboard-server",zI=10240,GI=3e4,LI={".html":"text/html",".js":"application/javascript",".css":"text/css",".svg":"image/svg+xml",".json":"application/json",".png":"image/png",".ico":"image/x-icon"}});var $k={};oe($k,{resolveAssetsDir:()=>Lc,serveDashboard:()=>VI});function Lc(){let t=At.resolve(__dirname,"../../dashboard/dist");if(Gc.existsSync(At.join(t,"index.html")))return t;let e=At.resolve(At.dirname(process.argv[1]),"../../dashboard/dist");if(Gc.existsSync(At.join(e,"index.html")))return e;try{let n=require.resolve("@oss-autopilot/dashboard/package.json"),o=At.join(At.dirname(n),"dist");if(Gc.existsSync(At.join(o,"index.html")))return o}catch(n){n.code!=="MODULE_NOT_FOUND"&&console.error("Error resolving dashboard package:",n)}return null}async function VI(t){let e=Lc();e||(console.error("Could not find dashboard SPA assets."),console.error("Make sure packages/dashboard has been built:"),console.error(" cd packages/dashboard && pnpm run build"),process.exit(1));let n=Mt(),{startDashboardServer:o}=await Promise.resolve().then(()=>(Sk(),wk));await o({port:t.port,assetsDir:e,token:n,open:t.open})}var Gc,At,rh=v(()=>{"use strict";Gc=K(require("fs"),1),At=K(require("path"),1);be()});function WI(t){return new Promise(e=>setTimeout(e,t))}async function Tk(t){if(!Lc())return null;let n=await Dc();if(n){let c=wo(),u=xt();if(c)if(c.version&&u!=="0.0.0"&&c.version!==u){console.error(`[STARTUP] Dashboard server version mismatch (running: ${c.version}, current: ${u}). Restarting...`);let l=!1;try{process.kill(c.pid,"SIGTERM"),l=!0}catch(d){d.code==="ESRCH"?l=!0:console.error(`[STARTUP] Could not kill outdated dashboard (PID ${c.pid}): ${d.message}`)}if(l)Cr();else return{url:n.url,port:n.port,alreadyRunning:!0}}else return{url:n.url,port:n.port,alreadyRunning:!0}}let o=t?.port??HI,r=process.argv[1],i=(0,kk.spawn)("node",[r,"dashboard","serve","--port",String(o),"--no-open"],{detached:!0,stdio:"ignore"}),s=!1,a=!1;i.on("error",c=>{s=!0,console.error(`[STARTUP] Failed to spawn dashboard server: ${c.message}`)}),i.on("exit",c=>{a=!0,c!==0&&c!==null&&console.error(`[STARTUP] Dashboard server exited prematurely (code ${c})`)}),i.unref();for(let c=0;c<BI;c++){if(await WI(qI),s||a)return null;let u=wo();if(u&&await Fi(u.port))return{url:`http://oss.localhost:${u.port}`,port:u.port,alreadyRunning:!1}}if(console.error("[STARTUP] Dashboard server failed to start within 5 seconds"),i.pid)try{process.kill(i.pid,"SIGTERM")}catch(c){c.code!=="ESRCH"&&console.error(`[STARTUP] Failed to kill orphan dashboard process (PID ${i.pid}): ${c.message}`)}return null}var kk,HI,qI,BI,Rk=v(()=>{"use strict";kk=require("child_process");Uc();rh();be();HI=3e3,qI=200,BI=25});var Ck={};oe(Ck,{countIssueListItems:()=>Pk,detectIssueList:()=>$o,openInBrowser:()=>Fc,parseIssueListPathFromConfig:()=>xk,runStartup:()=>KI});function xk(t){let e=t.match(/^---\n([\s\S]*?)\n---/);if(!e)return;let o=e[1].match(/issueListPath:\s*["']?([^"'\n]+)["']?/);return o?o[1].trim():void 0}function Pk(t){let e=0,n=0,o=t.split(`
96
96
  `);for(let r of o)/^\s*- (?:~~)?\[/.test(r)&&(/~~|\*\*Done\*\*/.test(r)?n++:e++);return{availableCount:e,completedCount:n}}function $o(){let t="",e="auto-detected";try{let s=V().getState().config.issueListPath;s&&Jt.existsSync(s)&&(t=s,e="configured")}catch(i){y("startup",`Could not read issueListPath from state: ${A(i)}`)}if(!t){let i=".claude/oss-autopilot/config.md";if(Jt.existsSync(i))try{let s=Jt.readFileSync(i,"utf-8"),a=xk(s);a&&Jt.existsSync(a)&&(t=a,e="configured")}catch(s){console.error("[STARTUP] Failed to read config:",A(s))}}if(!t){let i=["open-source/potential-issue-list.md","oss/issue-list.md","issues.md"];for(let s of i)if(Jt.existsSync(s)){t=s,e="auto-detected";break}}if(!t)return;let n=0,o=0;try{let i=Jt.readFileSync(t,"utf-8");({availableCount:n,completedCount:o}=Pk(i))}catch(i){console.error(`[STARTUP] Failed to read issue list at ${t}:`,A(i))}let r;try{let s=V().getState().config.skippedIssuesPath;s&&Jt.existsSync(s)&&(r=s)}catch{}if(!r&&t){let i=Nc.join(Nc.dirname(t),"skipped-issues.md");Jt.existsSync(i)&&(r=i)}return{path:t,source:e,availableCount:n,completedCount:o,skippedIssuesPath:r}}function Fc(t){let e,n;switch(process.platform){case"darwin":e="open",n=[t];break;case"win32":e="cmd",n=["/c","start","",t];break;default:e="xdg-open",n=[t];break}(0,Ek.execFile)(e,n,o=>{o&&console.error(`[STARTUP] Failed to open dashboard in browser: ${o.message}`)})}async function JI(t){try{let e=await fetch(`http://127.0.0.1:${t}/api/refresh`,{method:"POST",headers:{Origin:`http://oss.localhost:${t}`},signal:AbortSignal.timeout(5e3)});if(!e.ok){let n=await e.text().catch(()=>"");return console.error(`[STARTUP] Dashboard refresh returned ${e.status}: ${n}`),!1}return await e.text().catch(()=>{}),!0}catch(e){return console.error(`[STARTUP] Could not trigger dashboard refresh: ${A(e)}`),!1}}async function KI(){let t=xt(),e=V(),n=!1;if(!e.isSetupComplete()){let c=await hi();if(c)try{e.initializeWithDefaults(c),n=!0}catch(u){return console.error(`[STARTUP] Auto-detected username "${c}" but failed to save config:`,A(u)),{version:t,setupComplete:!1}}else return{version:t,setupComplete:!1}}let o=Mt();if(!o)return{version:t,setupComplete:!0,authError:'GitHub authentication required. Install GitHub CLI (https://cli.github.com/) and run "gh auth login", or set GITHUB_TOKEN.'};let r=await Tc(o),i,s;if(r.digest.summary.totalActivePRs>0)try{let c=await Tk();c?(i=c.url,c.alreadyRunning?s=await JI(c.port)?"refreshed":"running":(Fc(c.url),s="opened")):console.error("[STARTUP] Dashboard SPA assets not found. Build with: cd packages/dashboard && pnpm run build")}catch(c){console.error("[STARTUP] SPA dashboard launch failed:",A(c))}s==="opened"?r.briefSummary+=" | Dashboard opened in browser":s==="refreshed"?r.briefSummary+=" | Dashboard refreshed":s==="running"&&(r.briefSummary+=" | Dashboard running");let a=$o();return{version:t,setupComplete:!0,autoDetected:n,daily:r,dashboardUrl:i,issueList:a}}var Jt,Nc,Ek,zc=v(()=>{"use strict";Jt=K(require("fs"),1),Nc=K(require("path"),1),Ek=require("child_process");be();Se();$e();Ui();Rk()});var Ok={};oe(Ok,{classifyListStatus:()=>Ik,runVetList:()=>XI});function Ik(t){let e=t.reasonsToSkip.map(n=>n.toLowerCase());return e.some(n=>n.includes("closed"))?"closed":e.some(n=>n.includes("claimed")||n.includes("assigned"))?"claimed":e.some(n=>n.includes("existing pr")||n.includes("linked pr")||n.includes("pull request"))?"has_pr":(t.recommendation==="approve"||t.recommendation==="needs_review","still_available")}async function XI(t={}){let e=t.concurrency??5,n=t.issueListPath;if(!n){let p=$o();if(!p)throw new Error("No issue list found. Provide a path with --path or configure issueListPath in settings.");n=p.path}let o=await eh({filePath:n});if(o.available.length===0)return{results:[],summary:{total:0,stillAvailable:0,claimed:0,closed:0,hasPR:0,errors:0}};let r=await Pr(),i=[],s=o.available,a=0;async function c(){for(;a<s.length;){let p=s[a++];try{let g=await r.vetIssue(p.url),b={issue:{repo:g.issue.repo,number:g.issue.number,title:g.issue.title,url:g.issue.url,labels:g.issue.labels},recommendation:g.recommendation,reasonsToApprove:g.reasonsToApprove,reasonsToSkip:g.reasonsToSkip,projectHealth:g.projectHealth,vettingResult:g.vettingResult};i.push({...b,listStatus:Ik(b)})}catch(g){i.push({issue:{repo:p.repo,number:p.number,title:p.title,url:p.url,labels:[]},recommendation:"skip",reasonsToApprove:[],reasonsToSkip:[`Error: ${g instanceof Error?g.message:String(g)}`],projectHealth:{},vettingResult:{},listStatus:"error",errorMessage:g instanceof Error?g.message:String(g)})}}}let u=Array.from({length:Math.min(e,s.length)},()=>c());await Promise.all(u);let l={total:i.length,stillAvailable:i.filter(p=>p.listStatus==="still_available").length,claimed:i.filter(p=>p.listStatus==="claimed").length,closed:i.filter(p=>p.listStatus==="closed").length,hasPR:i.filter(p=>p.listStatus==="has_pr").length,errors:i.filter(p=>p.listStatus==="error").length},d;if(t.prune&&n)try{let p=Mc.readFileSync(n,"utf-8"),{pruned:g,removedCount:b}=Qf(p);g!==p&&Mc.writeFileSync(n,g,"utf-8"),d={removedCount:b}}catch(p){let g=p instanceof Error?p.message:String(p);console.error(`Warning: Failed to prune ${n}: ${g}`)}return{results:i,summary:l,pruneResult:d}}var Mc,Ak=v(()=>{"use strict";Mc=K(require("fs"),1);Di();Ic();zc()});var nh={};oe(nh,{runTrack:()=>YI,runUntrack:()=>QI});async function YI(t){Ue(t.prUrl),qe(t.prUrl,ar,"PR");let e=Me(),n=Ae(e),o=Ce(t.prUrl);if(!o||o.type!=="pull")throw new Error(`Invalid PR URL: ${t.prUrl}`);let{owner:r,repo:i,number:s}=o,{data:a}=await n.pulls.get({owner:r,repo:i,pull_number:s});return{pr:{repo:`${r}/${i}`,number:s,title:a.title,url:t.prUrl}}}async function QI(t){return Ue(t.prUrl),qe(t.prUrl,ar,"PR"),{removed:!1,url:t.prUrl,message:"In v2, PRs are fetched fresh on each daily run \u2014 there is no local tracking list to remove from."}}var oh=v(()=>{"use strict";be();Ot();Ze()});var Dk={};oe(Dk,{runRead:()=>eO});async function eO(t){if(!t.all&&!t.prUrl)throw new Error("PR URL or --all flag required");return t.prUrl&&Ue(t.prUrl),t.all?{markedAsRead:0,all:!0,message:"In v2, PR read state is not tracked locally."}:{marked:!1,url:t.prUrl,message:"In v2, PR read state is not tracked locally."}}var Uk=v(()=>{"use strict";Ot()});var Zc={};oe(Zc,{runClaim:()=>nO,runComments:()=>tO,runPost:()=>rO});async function tO(t){Ue(t.prUrl),qe(t.prUrl,ar,"PR");let e=Me(),n=V(),o=Ae(e),r=Ce(t.prUrl);if(!r||r.type!=="pull")throw new Error("Invalid PR URL format");let{owner:i,repo:s,number:a}=r,{data:c}=await o.pulls.get({owner:i,repo:s,pull_number:a}),[u,l,d]=await Promise.all([or(T=>o.pulls.listReviewComments({owner:i,repo:s,pull_number:a,per_page:100,page:T})),or(T=>o.issues.listComments({owner:i,repo:s,issue_number:a,per_page:100,page:T})),or(T=>o.pulls.listReviews({owner:i,repo:s,pull_number:a,per_page:100,page:T}))]),p=n.getState().config.githubUsername,g=T=>!(!T.user||T.user.login===p||T.user.type==="Bot"&&!t.showBots),b=u.filter(g).sort((T,C)=>new Date(C.created_at).getTime()-new Date(T.created_at).getTime()),S=l.filter(g).sort((T,C)=>new Date(C.created_at).getTime()-new Date(T.created_at).getTime()),F=d.filter(T=>g(T)&&T.body&&T.body.trim()).sort((T,C)=>new Date(C.submitted_at||0).getTime()-new Date(T.submitted_at||0).getTime());return{pr:{title:c.title,state:c.state,mergeable:c.mergeable,head:c.head.ref,base:c.base.ref,url:c.html_url},reviews:F.map(T=>({user:T.user?.login,state:T.state,body:T.body??null,submittedAt:T.submitted_at??null})),reviewComments:b.map(T=>({user:T.user?.login,body:T.body,path:T.path,createdAt:T.created_at})),issueComments:S.map(T=>({user:T.user?.login,body:T.body,createdAt:T.created_at})),summary:{reviewCount:F.length,inlineCommentCount:b.length,discussionCommentCount:S.length}}}async function rO(t){if(Ue(t.url),qe(t.url,ik,"issue or PR"),!t.message.trim())throw new Error("No message provided");Yf(t.message);let e=Me(),n=Ce(t.url);if(!n)throw new Error("Invalid GitHub URL format");let{owner:o,repo:r,number:i}=n,s=Ae(e),{data:a}=await s.issues.createComment({owner:o,repo:r,issue_number:i,body:t.message});return{commentUrl:a.html_url,url:t.url}}async function nO(t){Ue(t.issueUrl),qe(t.issueUrl,cr,"issue");let e=Me(),n=t.message||"Hi! I'd like to work on this issue. Could you assign it to me?";Yf(n);let o=Ce(t.issueUrl);if(!o||o.type!=="issues")throw new Error("Invalid issue URL format (must be an issue, not a PR)");let{owner:r,repo:i,number:s}=o,a=Ae(e),{data:c}=await a.issues.createComment({owner:r,repo:i,issue_number:s,body:n});try{let u=V();u.addIssue({id:s,url:t.issueUrl,repo:`${r}/${i}`,number:s,title:"(claimed)",status:"claimed",labels:[],createdAt:new Date().toISOString(),updatedAt:new Date().toISOString(),vetted:!1});try{u.isGistMode()&&await u.checkpoint()}catch{}}catch(u){console.error(`Warning: Comment posted on ${t.issueUrl} but failed to save to local state: ${u instanceof Error?u.message:u}`)}return{commentUrl:c.html_url,issueUrl:t.issueUrl}}var Vc=v(()=>{"use strict";be();ec();Ot()});var Fk={};oe(Fk,{runConfig:()=>oO});function jk(t){if(!qr.includes(t))throw new Error(`Invalid scope "${t}". Valid scopes: ${qr.join(", ")}`);return t}async function oO(t){let e=V(),n=e.getState().config;if(!t.key)return{config:n};if(!t.value)throw new Error("Value required");let o=t.value;switch(t.key){case"username":e.updateConfig({githubUsername:bo(o)});break;case"add-language":n.languages.includes(o)||e.updateConfig({languages:[...n.languages,o]});break;case"add-label":n.labels.includes(o)||e.updateConfig({labels:[...n.labels,o]});break;case"remove-label":if(!n.labels.includes(o))throw new Error(`Label "${o}" is not currently configured. Current labels: ${n.labels.join(", ")}`);e.updateConfig({labels:n.labels.filter(r=>r!==o)});break;case"add-scope":{let r=jk(o),i=n.scope??[];i.includes(r)||e.updateConfig({scope:[...i,r]});break}case"remove-scope":{let r=jk(o),i=n.scope??[];if(!i.includes(r))throw new Error(`Scope "${o}" is not currently set`);let s=i.filter(a=>a!==r);if(s.length===0)throw new Error("Cannot remove the last scope. Use setup to clear scopes entirely.");e.updateConfig({scope:s});break}case"exclude-repo":{let r=o.split("/");if(r.length!==2||!r[0]||!r[1])throw new Error(`Invalid repo format "${o}". Use "owner/repo" format. To exclude an entire org, use: config exclude-org ${o}`);let i=o.toLowerCase();n.excludeRepos.some(s=>s.toLowerCase()===i)||e.batch(()=>{e.updateConfig({excludeRepos:[...n.excludeRepos,o]}),e.cleanupExcludedData([o],[])});break}case"exclude-org":{if(o.includes("/"))throw new Error(`Invalid org name "${o}". Use just the org name (e.g., "facebook"), not "owner/repo" format. To exclude a specific repo, use: config exclude-repo ${o}`);let r=n.excludeOrgs??[];r.some(i=>i.toLowerCase()===o.toLowerCase())||e.batch(()=>{e.updateConfig({excludeOrgs:[...r,o]}),e.cleanupExcludedData([],[o])});break}case"issueListPath":e.updateConfig({issueListPath:o||void 0});break;case"diffTool":{if(!Br.includes(o))throw new Error(`Invalid diffTool "${o}". Valid options: ${Br.join(", ")}`);e.updateConfig({diffTool:o});break}case"diffToolCustomCommand":e.updateConfig({diffToolCustomCommand:o||void 0});break;default:throw new Error(`Unknown config key: ${t.key}`)}return{success:!0,key:t.key,value:o}}var zk=v(()=>{"use strict";be();wr();Ot()});var Gk={};oe(Gk,{runInit:()=>iO});async function iO(t){return bo(t.username),V().updateConfig({githubUsername:t.username}),{username:t.username,message:"Username saved. Run `daily` to fetch your open PRs from GitHub."}}var Lk=v(()=>{"use strict";be();Ot()});var sh={};oe(sh,{runCheckSetup:()=>aO,runSetup:()=>sO});function ih(t,e){let n=Number(t);if(!Number.isInteger(n)||n<1)throw new we(`Invalid value for ${e}: "${t}". Must be a positive integer.`);return n}async function sO(t){let e=V(),n=e.getState().config;if(t.set&&t.set.length>0){let o={},r=[];return e.batch(()=>{for(let i of t.set){let[s,...a]=i.split("="),c=a.join("=");switch(s){case"username":bo(c),e.updateConfig({githubUsername:c}),o[s]=c;break;case"maxActivePRs":{let u=ih(c,"maxActivePRs");e.updateConfig({maxActivePRs:u}),o[s]=String(u);break}case"dormantDays":{let u=ih(c,"dormantDays");e.updateConfig({dormantThresholdDays:u}),o[s]=String(u);break}case"approachingDays":{let u=ih(c,"approachingDays");e.updateConfig({approachingDormantDays:u}),o[s]=String(u);break}case"languages":e.updateConfig({languages:c.split(",").map(u=>u.trim())}),o[s]=c;break;case"labels":e.updateConfig({labels:c.split(",").map(u=>u.trim())}),o[s]=c;break;case"squashByDefault":c==="ask"?(e.updateConfig({squashByDefault:"ask"}),o[s]="ask"):(e.updateConfig({squashByDefault:c!=="false"}),o[s]=c!=="false"?"true":"false");break;case"minStars":{let u=Number(c);if(!Number.isInteger(u)||u<0)throw new we(`Invalid value for minStars: "${c}". Must be a non-negative integer.`);e.updateConfig({minStars:u}),o[s]=String(u);break}case"includeDocIssues":e.updateConfig({includeDocIssues:c==="true"}),o[s]=c==="true"?"true":"false";break;case"aiPolicyBlocklist":{let u=c.split(",").map(p=>p.trim()).filter(Boolean),l=[],d=[];for(let p of u){let g=p.replace(/\s+/g,"");/^[a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+$/.test(g)?l.push(g):d.push(p)}if(d.length>0&&(r.push(`Warning: Skipping invalid entries (expected "owner/repo" format): ${d.join(", ")}`),o.aiPolicyBlocklist_invalidEntries=d.join(", ")),l.length===0&&u.length>0){r.push("Warning: All entries were invalid. Blocklist not updated."),o[s]="(all entries invalid)";break}e.updateConfig({aiPolicyBlocklist:l}),o[s]=l.length>0?l.join(", "):"(empty)";break}case"projectCategories":{let u=c.split(",").map(g=>g.trim()).filter(Boolean),l=[],d=[];for(let g of u)Na.includes(g)?l.push(g):d.push(g);d.length>0&&r.push(`Unknown project categories: ${d.join(", ")}. Valid: ${Na.join(", ")}`);let p=[...new Set(l)];e.updateConfig({projectCategories:p}),o[s]=p.length>0?p.join(", "):"(empty)";break}case"preferredOrgs":{let u=c.split(",").map(p=>p.trim()).filter(Boolean),l=[];for(let p of u)p.includes("/")?r.push(`"${p}" looks like a repo path. Use org name only (e.g., "vercel" not "vercel/next.js").`):/^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$/.test(p)?l.push(p.toLowerCase()):r.push(`"${p}" is not a valid GitHub organization name. Skipping.`);let d=[...new Set(l)];e.updateConfig({preferredOrgs:d}),o[s]=d.length>0?d.join(", "):"(empty)";break}case"scope":{let u=c.split(",").map(g=>g.trim()).filter(Boolean),l=[],d=[];for(let g of u)qr.includes(g)?l.push(g):d.push(g);d.length>0&&r.push(`Unknown issue scopes: ${d.join(", ")}. Valid: ${qr.join(", ")}`);let p=[...new Set(l)];e.updateConfig({scope:p.length>0?p:void 0}),o[s]=p.length>0?p.join(", "):"(empty \u2014 using labels only)";break}case"persistence":if(c!=="local"&&c!=="gist")throw new we(`Invalid value for persistence: "${c}". Must be "local" or "gist".`);e.updateConfig({persistence:c}),o[s]=c;break;case"issueListPath":e.updateConfig({issueListPath:c||void 0}),o[s]=c||"(cleared)";break;case"diffTool":{if(!Br.includes(c)){r.push(`Invalid diffTool "${c}". Valid: ${Br.join(", ")}`);break}e.updateConfig({diffTool:c}),o[s]=c;break}case"diffToolCustomCommand":e.updateConfig({diffToolCustomCommand:c||void 0}),o[s]=c||"(cleared)";break;case"complete":c==="true"&&(e.markSetupComplete(),o[s]="true");break;default:r.push(`Unknown setting: ${s}`)}}}),{success:!0,settings:o,warnings:r.length>0?r:void 0}}return n.setupComplete&&!t.reset?{setupComplete:!0,config:{githubUsername:n.githubUsername,maxActivePRs:n.maxActivePRs,dormantThresholdDays:n.dormantThresholdDays,approachingDormantDays:n.approachingDormantDays,languages:n.languages,labels:n.labels,projectCategories:n.projectCategories??[],preferredOrgs:n.preferredOrgs??[],scope:n.scope??[],persistence:n.persistence??"local"}}:{setupRequired:!0,prompts:[{setting:"username",prompt:"What is your GitHub username?",current:n.githubUsername||null,required:!0,type:"string"},{setting:"maxActivePRs",prompt:"How many PRs do you want to work on at once?",current:n.maxActivePRs,default:10,type:"number"},{setting:"dormantDays",prompt:"After how many days of inactivity should a PR be considered dormant?",current:n.dormantThresholdDays,default:30,type:"number"},{setting:"approachingDays",prompt:"At how many days should we warn about approaching dormancy?",current:n.approachingDormantDays,default:25,type:"number"},{setting:"languages",prompt:"What programming languages do you want to contribute to?",current:n.languages,default:["typescript","javascript"],type:"list"},{setting:"labels",prompt:"What issue labels should we search for?",current:n.labels,default:["good first issue","help wanted"],type:"list"},{setting:"scope",prompt:"What scope of issues do you want to discover? (beginner, intermediate, advanced \u2014 leave empty for default labels only)",current:n.scope??[],default:[],type:"list"},{setting:"aiPolicyBlocklist",prompt:"Repos with anti-AI contribution policies to block (owner/repo, comma-separated)?",current:n.aiPolicyBlocklist??Dg.aiPolicyBlocklist??null,default:["matplotlib/matplotlib"],type:"list"},{setting:"projectCategories",prompt:"What types of projects interest you? (nonprofit, devtools, infrastructure, web-frameworks, data-ml, education)",current:n.projectCategories??[],default:[],type:"list"},{setting:"preferredOrgs",prompt:"Any GitHub organizations to prioritize? (org names, comma-separated)",current:n.preferredOrgs??[],default:[],type:"list"},{setting:"persistence",prompt:'Where should state be stored? "local" for file only, "gist" for GitHub Gist (survives device loss)',current:n.persistence??"local",default:"local",type:"string"}]}}async function aO(){let t=V();return{setupComplete:t.isSetupComplete(),username:t.getState().config.githubUsername}}var ah=v(()=>{"use strict";be();Se();Ot();wr()});var Nk={};oe(Nk,{runCheckIntegration:()=>pO});function lO(t){let e=pt.extname(t),n=pt.basename(t,e);return n==="index"?pt.basename(pt.dirname(t)):n}function dO(t,e){let n=pt.dirname(t),o=[];for(let i of[".ts",".tsx",".js",".jsx"]){let s=pt.join(n,`index${i}`);e.includes(s)&&o.push(s)}let r=pt.dirname(n);for(let i of[".ts",".tsx",".js",".jsx"]){let s=pt.join(r,`index${i}`);e.includes(s)&&o.push(s)}return[...new Set(o)]}async function pO(t){let e=t.base,n;try{let a=(0,Hc.execFileSync)("git",["diff","--name-only","--diff-filter=A",`${e}...HEAD`],{encoding:"utf-8",timeout:1e4}).trim();n=a?a.split(`
97
97
  `).filter(Boolean):[]}catch(a){let c=A(a);throw new Error(`Failed to run git diff: ${c}`,{cause:a})}let o=n.filter(a=>{let c=pt.extname(a);return cO.has(c)?!uO.some(u=>u.test(a)):!1});if(o.length===0)return{newFiles:[],unreferencedCount:0};let r;try{r=(0,Hc.execFileSync)("git",["ls-files"],{encoding:"utf-8",timeout:1e4}).trim().split(`
98
98
  `).filter(Boolean)}catch(a){k("check-integration","git ls-files failed, reference checking will be skipped",a),r=[]}let i=[];for(let a of o){let c=lO(a),u=a.replace(/\.[^.]+$/,""),l=[],d=[c];u.includes("/")&&d.push(u);for(let b of d)try{let S=(0,Hc.execFileSync)("git",["grep","-l","--",b],{encoding:"utf-8",timeout:1e4}).trim();if(S){let F=S.split(`
@@ -137,7 +137,7 @@ function readBody(req, maxBytes = MAX_BODY_BYTES) {
137
137
  function setSecurityHeaders(res) {
138
138
  res.setHeader('X-Content-Type-Options', 'nosniff');
139
139
  res.setHeader('X-Frame-Options', 'DENY');
140
- res.setHeader('Content-Security-Policy', "default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'");
140
+ res.setHeader('Content-Security-Policy', "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data:; connect-src 'self'");
141
141
  res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
142
142
  }
143
143
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oss-autopilot/core",
3
- "version": "1.12.1",
3
+ "version": "1.13.0",
4
4
  "description": "CLI and core library for managing open source contributions",
5
5
  "type": "module",
6
6
  "bin": {