oh-my-pr 2.8.0 → 2.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/tui.mjs +101 -99
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -905,7 +905,7 @@ ${e}`:e}function Ii(t,e){return[t,...e].join(" ")}function ur(t){return t.stderr
|
|
|
905
905
|
`)).join(`
|
|
906
906
|
`);return["Respond with ONLY valid JSON and nothing else.","Schema:",'{"shouldRelease":boolean,"reason":string,"bump":"patch"|"minor"|"major"|null,"title":string|null,"notes":string|null}',"","You are deciding whether a merged set of pull requests should be published as a GitHub release.","Be conservative. Release only when the merged changes are meaningful enough for users or operators to care about.","",`Repository: ${t.repo}`,`Release branch: ${t.baseBranch}`,`Latest release tag: ${t.latestTag??"none"}`,"",`Trigger PR: #${t.triggerPr.number} "${t.triggerPr.title}"`,`Trigger merged at: ${t.triggerPr.mergedAt}`,`Trigger merge SHA: ${t.triggerPr.mergeSha}`,"","Merged PRs included in this candidate release:",e||"(none)","","Decision rules:","- shouldRelease=true only when the merged changes are worth announcing as a GitHub release.","- bump must be null when shouldRelease=false.","- bump must be one of patch, minor, or major when shouldRelease=true.","- Use patch for fixes or small improvements, minor for additive user-facing features, and major for breaking changes.","- title should be short and release-note ready when shouldRelease=true, else null.","- notes should be GitHub-release Markdown focused on user-visible/operator-visible impact when shouldRelease=true, else null.","- notes must have exactly TWO sections in this order:"," 1. '## Why This Matters' \u2014 a user-friendly, value-driven summary at the top that explains how the release makes users' lives better."," 2. '## Detailed Changes' \u2014 a line-by-line changelog of the included changes in plain English, more detailed than a headline but not deeply technical.","- notes should mention the key merged PRs in plain language, not internal process commentary.","- Prefer user outcomes, workflow improvements, and visible behavior over implementation details."].join(`
|
|
907
907
|
`)}function zv(t){let e=cC(t.trim());if(!e||typeof e!="object")throw new Error(`Could not parse release evaluation JSON: ${t.slice(0,500)}`);let a=e;if(typeof a.shouldRelease!="boolean")throw new Error("Release evaluation missing boolean 'shouldRelease'");if(typeof a.reason!="string"||a.reason.trim().length===0)throw new Error("Release evaluation missing string 'reason'");if(!a.shouldRelease)return{shouldRelease:!1,reason:a.reason.trim(),bump:null,title:null,notes:null};if(a.bump!=="patch"&&a.bump!=="minor"&&a.bump!=="major")throw new Error("Release evaluation returned invalid 'bump'");if(typeof a.title!="string"||a.title.trim().length===0)throw new Error("Release evaluation missing non-empty 'title'");if(typeof a.notes!="string"||a.notes.trim().length===0)throw new Error("Release evaluation missing non-empty 'notes'");return{shouldRelease:!0,reason:a.reason.trim(),bump:a.bump,title:a.title.trim(),notes:a.notes.trim()}}function cC(t){try{return JSON.parse(t)}catch{}let e=t.indexOf("{"),a=t.lastIndexOf("}");if(e===-1||a===-1||a<=e)return null;try{return JSON.parse(t.slice(e,a+1))}catch{return null}}var Fi=class{storage;github;evaluateRelease;scheduleBackgroundJob;inProgress=new Set;repoLocks=new Map;constructor(e,a){this.storage=e,this.github=a.github,this.evaluateRelease=a.evaluateRelease??Jv,this.scheduleBackgroundJob=a.scheduleBackgroundJob}getActiveRunCount(){return this.inProgress.size}async waitForIdle(e=12e4){let a=Date.now();for(;this.inProgress.size>0;){if(Date.now()-a>=e)return!1;await fC(50)}return!0}async enqueueMergedPullReleaseEvaluation(e){let a=await this.storage.getReleaseRunByTrigger(e.repo,e.triggerPrNumber,e.triggerMergeSha);if(a)return mC(a.status)||this.scheduleProcessing(a.id),a;let r=await this.storage.createReleaseRun({repo:e.repo,baseBranch:e.baseBranch,triggerPrNumber:e.triggerPrNumber,triggerPrTitle:e.triggerPrTitle,triggerPrUrl:e.triggerPrUrl,triggerMergeSha:e.triggerMergeSha,triggerMergedAt:e.triggerMergedAt,status:"detected",decisionReason:null,recommendedBump:null,proposedVersion:null,releaseTitle:null,releaseNotes:null,includedPrs:[],targetSha:e.triggerMergeSha,githubReleaseId:null,githubReleaseUrl:null,error:null,completedAt:null});return this.scheduleProcessing(r.id),r}async retryReleaseRun(e){if(!await this.storage.getReleaseRun(e))return;let r=await this.storage.updateReleaseRun(e,{status:"detected",error:null,completedAt:null});if(r)return this.scheduleProcessing(e),r}async processReleaseRun(e){let a=await this.storage.getReleaseRun(e);if(a)return this.withRepoLock(a.repo,async()=>{if(this.inProgress.has(e))return this.storage.getReleaseRun(e);this.inProgress.add(e);try{let r=await this.storage.getReleaseRun(e);if(!r)return;if(r.status==="published"||r.status==="skipped")return r;let n=Ve(r.repo);if(!n)return this.failRun(e,`Invalid repository slug: ${r.repo}`);let i=await this.storage.getConfig();if(!i.autoCreateReleases)return await this.storage.updateReleaseRun(e,{status:"skipped",decisionReason:"Automatic release creation is disabled in settings",completedAt:new Date().toISOString()})??void 0;await this.storage.updateReleaseRun(e,{status:"evaluating",error:null,completedAt:null});let s=await this.github.buildOctokit(i),o=await this.github.findLatestSemverReleaseTag(s,n),u=uC(r),c=await this.loadIncludedPulls(s,n,r,u),l=c.map(lC),p=await this.evaluateRelease({preferredAgent:i.codingAgent,repo:r.repo,baseBranch:r.baseBranch,latestTag:o,triggerPr:u,includedPulls:c});if(!p.shouldRelease)return await this.storage.updateReleaseRun(e,{status:"skipped",decisionReason:p.reason,recommendedBump:null,proposedVersion:null,releaseTitle:null,releaseNotes:null,includedPrs:l,targetSha:r.triggerMergeSha,completedAt:new Date().toISOString()})??void 0;if(!p.bump)throw new Error("Release evaluation approved publishing but did not provide a semver bump");let d=this.github.bumpReleaseTag(o,p.bump),g=pC(p,d),v=p.notes??`Release ${d}`;await this.storage.updateReleaseRun(e,{status:"proposed",decisionReason:p.reason,recommendedBump:p.bump,proposedVersion:d,releaseTitle:g,releaseNotes:v,includedPrs:l,targetSha:r.triggerMergeSha});let h=this.github.findReleaseByTag?await this.github.findReleaseByTag(s,n,d):null;if(h)return await this.storage.updateReleaseRun(e,{status:"published",githubReleaseId:h.id,githubReleaseUrl:h.url,completedAt:new Date().toISOString()})??void 0;await this.storage.updateReleaseRun(e,{status:"publishing"});let b=await this.github.createGitHubRelease(s,n,{tagName:d,targetCommitish:r.triggerMergeSha,name:g,body:v});return await this.storage.updateReleaseRun(e,{status:"published",githubReleaseId:b.id,githubReleaseUrl:b.url,completedAt:new Date().toISOString()})??void 0}catch(r){return this.failRun(e,dC(r))}finally{this.inProgress.delete(e)}})}async loadIncludedPulls(e,a,r,n){if(!this.github.listMergedPullsForReleaseCandidate)return[n];let i=await this.github.listMergedPullsForReleaseCandidate(e,a,{baseBranch:r.baseBranch,untilMergedAt:r.triggerMergedAt,triggerPr:n}),s=new Map;for(let o of i)s.set(o.mergeSha||`${o.repo}#${o.number}`,o);return s.has(n.mergeSha)||s.set(n.mergeSha,n),Array.from(s.values()).sort((o,u)=>o.mergedAt.localeCompare(u.mergedAt))}async failRun(e,a){return this.storage.updateReleaseRun(e,{status:"error",error:a,completedAt:new Date().toISOString()})}async withRepoLock(e,a){let r=this.repoLocks.get(e)??Promise.resolve(),n,i=new Promise(o=>{n=()=>o()}),s=r.then(()=>i);this.repoLocks.set(e,s),await r;try{return await a()}finally{n?.(),this.repoLocks.get(e)===s&&this.repoLocks.delete(e)}}scheduleProcessing(e){if(this.scheduleBackgroundJob){this.scheduleBackgroundJob("process_release_run",e,nt("process_release_run",e),{releaseRunId:e}).catch(a=>{console.error(`Failed to schedule release run ${e}:`,a)});return}this.processReleaseRun(e).catch(()=>{})}};function uC(t){return{number:t.triggerPrNumber,title:t.triggerPrTitle,url:t.triggerPrUrl,author:"unknown",repo:t.repo,mergedAt:t.triggerMergedAt,mergeSha:t.triggerMergeSha}}function lC(t){return{number:t.number,title:t.title,url:t.url,author:t.author,mergedAt:t.mergedAt,mergeSha:t.mergeSha}}function pC(t,e){let a=t.title?.trim();return a?a.startsWith(e)?a:`${e} - ${a}`:e}function dC(t){return(t instanceof Error?t.message:String(t)).trim().slice(0,2e3)}function mC(t){return t==="skipped"||t==="published"}function fC(t){return new Promise(e=>setTimeout(e,t))}var gC=["fix_submitted","escalated"],hC={monitoring:["failed","escalated"],failed:["fixing","escalated"],fixing:["fix_submitted","escalated"],fix_submitted:[],escalated:[]},Di=class{constructor(e,a=()=>new Date){this.storage=e;this.clock=a}async createSession(e){return this.storage.createDeploymentHealingSession({...e,deploymentId:null,deploymentLog:null,fixBranch:null,fixPrNumber:null,fixPrUrl:null,state:"monitoring",error:null,completedAt:null})}async ensureSession(e){let a=await this.storage.getDeploymentHealingSessionByRepoAndMergeSha(e.repo,e.mergeSha);return a||this.createSession(e)}async transitionTo(e,a,r={}){let n=await this.storage.getDeploymentHealingSession(e);if(!n)throw new Error(`Deployment healing session not found: ${e}`);if(n.state===a){let o=await this.storage.updateDeploymentHealingSession(e,r);if(!o)throw new Error(`Deployment healing session not found: ${e}`);return o}if(!hC[n.state].includes(a))throw new Error(`Illegal deployment healing transition: ${n.state} -> ${a}`);let i={...r,state:a};gC.includes(a)&&(i.completedAt=r.completedAt??this.clock().toISOString());let s=await this.storage.updateDeploymentHealingSession(e,i);if(!s)throw new Error(`Deployment healing session not found: ${e}`);return s}};var Se=class extends Error{statusCode;constructor(e,a){super(a),this.name="AppRuntimeError",this.statusCode=e}};function Xv(t){return t instanceof Error?t.message:String(t)}function ye(t,e){if(t===void 0)throw new Se(404,e);return t}function Vv(t={}){let e=t.storage??hh(),a=new Wv.EventEmitter,r=t.backgroundJobQueue??new Ai(e),n,i=async(...f)=>{let w=await r.enqueue(...f);return n.wake(),w},s=t.deploymentHealingManager??new Di(e),o=t.releaseManager??new Fi(e,{github:{buildOctokit:rt,findLatestSemverReleaseTag:jh,bumpReleaseTag:Lh,listMergedPullsForReleaseCandidate:async(f,w,x)=>{let k=await Kh(f,w,{baseRef:x.baseBranch}),E=Date.parse(x.untilMergedAt);return k.filter(F=>!Number.isFinite(E)||Date.parse(F.mergedAt)<=E).map(F=>({number:F.number,title:F.title,url:F.url,author:F.author,repo:F.repo,mergedAt:F.mergedAt,mergeSha:F.mergeCommitSha??`${F.repo}#${F.number}`}))},findReleaseByTag:async(f,w,x)=>{let E=(await yi(f,w)).find(F=>!F.draft&&F.tagName===x);return E?{id:E.id,url:E.htmlUrl,tagName:E.tagName,name:E.name}:null},createGitHubRelease:async(f,w,x)=>{let k=await Hh(f,w,{tagName:x.tagName,targetCommitish:x.targetCommitish,name:x.name,body:x.body});return{id:k.id,url:k.htmlUrl,tagName:k.tagName,name:k.name}}},scheduleBackgroundJob:i}),u=t.babysitter??new Oi(e,void 0,void 0,o,i,s);n=t.backgroundJobDispatcher??new Ni({storage:e,queue:r,handlers:Bv({storage:e,babysitter:u,releaseManager:o,deploymentHealingManager:s})});let c=null,l=0,p=t.watcherScheduler??qv(async()=>{await i("sync_watched_repos","runtime:1",nt("sync_watched_repos","runtime:1"))},f=>{console.error("Repository babysitter watcher failed",f)}),d=p.run,g=t.startBackgroundServices??!0,v=t.startWatcher??g,h=!1,b=()=>{a.emit("change")},C=async()=>({...await e.getRuntimeState(),activeRuns:n.getActiveRunCount()}),O=async f=>{let[w,x,k]=await Promise.all([n.waitForIdle(f),u.waitForIdle(f),o.waitForIdle(f)]);return w&&x&&k},A=async()=>{let f=await e.getConfig(),w=Math.max(1e4,f.pollIntervalMs||12e4);c&&l===w||(c&&(clearInterval(c),c=null),l=w,c=setInterval(()=>{d()},w))},I=async(f,w)=>{await i("babysit_pr",f,nt("babysit_pr",f),{preferredAgent:w})},L={async start(){h||(h=!0,g&&await n.start(),v&&(await A(),u.resumeInterruptedRuns(),d()))},stop(){h=!1,n.stop(),c&&(clearInterval(c),c=null)},subscribe(f){return a.on("change",f),()=>{a.off("change",f)}},getRuntimeSnapshot:C,async setDrainMode(f){let w=await e.updateRuntimeState({drainMode:f.enabled,drainRequestedAt:f.enabled?new Date().toISOString():null,drainReason:f.enabled?f.reason??null:null});if(f.enabled&&f.waitForIdle){let k=await O(f.timeoutMs??12e4),E=await C();return b(),{...w,...E,drained:k}}let x=await C();return b(),{...w,...x}},async listRepos(){let f=await e.getConfig(),w=await e.getPRs();return Array.from(new Set([...f.watchedRepos,...w.map(x=>x.repo)])).sort((x,k)=>x.localeCompare(k))},async addRepo(f){let w=Ve(f);if(!w)throw new Se(400,"Invalid repository. Use owner/repo or https://github.com/owner/repo");let x=ha(w),k=await e.getConfig();return k.watchedRepos.includes(x)||await e.updateConfig({watchedRepos:[...k.watchedRepos,x].sort((E,F)=>E.localeCompare(F))}),d(),b(),{repo:x}},async syncRepos(){if((await e.getRuntimeState()).drainMode)throw new Se(409,"Drain mode is enabled. Sync-triggered runs are blocked until drain mode is disabled.");return await p.runAndReportErrors(),b(),{ok:!0}},async listPRs(f="active"){return f==="archived"?e.getArchivedPRs():e.getPRs()},async getPR(f){return await e.getPR(f)??null},async addPR(f){let w;try{({url:w}=oh.parse({url:f}))}catch(Q){throw Q instanceof m.ZodError?new Se(400,Q.errors[0]?.message??"Invalid PR URL"):Q}let x=hi(w);if(!x)throw new Se(400,"Invalid GitHub PR URL. Expected: https://github.com/owner/repo/pull/123");let k=`${x.owner}/${x.repo}`,E=await e.getPRByRepoAndNumber(k,x.number);if(E)return E;let F=await e.getConfig(),R=await rt(F),U=await bi(R,x),z=await e.addPR({number:x.number,title:U.title,repo:k,branch:U.branch,author:U.author,url:U.url,status:"watching",feedbackItems:[],accepted:0,rejected:0,flagged:0,testsPassed:null,lintPassed:null,lastChecked:null});return await e.addLog(z.id,"info",`Registered PR #${x.number} from ${k}`),await e.addLog(z.id,"info",`Repository ${k} added to auto-babysit watch list`),F.watchedRepos.includes(k)||await e.updateConfig({watchedRepos:[...F.watchedRepos,k].sort((Q,Y)=>Q.localeCompare(Y))}),await I(z.id,F.codingAgent),b(),z},async removePR(f){if(!await e.removePR(f))throw new Se(404,"PR not found");return b(),{ok:!0}},async setPRWatchEnabled(f,w){let x=ye(await e.getPR(f),"PR not found"),k=await e.updatePR(x.id,{watchEnabled:w}),E=ye(k,"PR not found");return x.watchEnabled!==w&&(await e.addLog(x.id,"info",w?"Background watch resumed":"Background watch paused"),w&&d()),b(),E},async setWatchEnabled(f,w){return L.setPRWatchEnabled(f,w)},async fetchPRFeedback(f){let w=ye(await e.getPR(f),"PR not found");await e.updatePR(w.id,{status:"processing",lastChecked:new Date().toISOString()}),await e.addLog(w.id,"info","Syncing GitHub comments/reviews...");try{let x=await u.syncFeedbackForPR(w.id);return b(),x}catch(x){let k=Xv(x);throw await e.updatePR(w.id,{status:"error",lastChecked:new Date().toISOString()}),await e.addLog(w.id,"error",`Fetch failed: ${k}`),x}},async triagePR(f){let w=ye(await e.getPR(f),"PR not found");await e.updatePR(w.id,{status:"processing"}),await e.addLog(w.id,"info","Triaging feedback...");let x=w.feedbackItems.map(U=>{if(U.decision)return U;let z=U.body.toLowerCase();return z.includes("lgtm")||z.includes("looks good")?ya(U,!1,"Acknowledgement, no code change requested"):z.includes("please")||z.includes("should")||z.includes("fix")||z.includes("error")||z.includes("fail")?{...ya(U,!0,"Likely actionable request"),action:U.body}:wv(U,"Unclear actionability, flagged for manual review")}),k=x.filter(U=>U.decision==="accept").length,E=x.filter(U=>U.decision==="reject").length,F=x.filter(U=>U.decision==="flag").length,R=await e.updatePR(w.id,{feedbackItems:x,accepted:k,rejected:E,flagged:F,status:"watching"});return await e.addLog(w.id,"info",`Triage complete: ${k} accept, ${E} reject, ${F} flag`),b(),ye(R,"PR not found")},async applyPR(f){let w=ye(await e.getPR(f),"PR not found");if((await e.getRuntimeState()).drainMode)throw new Se(409,"Drain mode is enabled. Manual runs are blocked until drain mode is disabled.");let k=await e.getConfig();await e.updatePR(w.id,{status:"processing"}),await e.addLog(w.id,"info",`Launching autonomous babysitter run using ${k.codingAgent}`),await I(w.id,k.codingAgent);let E=await e.getPR(w.id);return b(),ye(E,"PR disappeared after apply run")},async babysitPR(f){let w=ye(await e.getPR(f),"PR not found");if((await e.getRuntimeState()).drainMode)throw new Se(409,"Drain mode is enabled. Manual runs are blocked until drain mode is disabled.");let k=await e.getConfig();await e.addLog(w.id,"info",`Manual babysitter trigger using ${k.codingAgent}`),await I(w.id,k.codingAgent);let E=await e.getPR(w.id);return b(),ye(E,"PR disappeared after babysit run")},async queueBabysit(f){return L.babysitPR(f)},async setFeedbackDecision(f,w,x){let k=ye(await e.getPR(f),"PR not found"),E=await Fv({storage:e,pr:k,feedbackId:w,decision:x});return b(),ye(E,"PR not found")},async retryFeedback(f,w){let x=await u.retryFeedbackItem(f,w);if(x.kind==="pr_not_found")throw new Se(404,"PR not found");if(x.kind==="feedback_not_found")throw new Se(404,"Feedback item not found");if(x.kind==="feedback_not_retryable")throw new Se(400,"Only failed or warning items can be retried");await e.addLog(f,"info",`Feedback item ${w} queued for retry`);let k=await e.getConfig();return await I(f,k.codingAgent),b(),x.updated},async listPRQuestions(f){return ye(await e.getPR(f),"PR not found"),e.getQuestions(f)},async askQuestion(f,w){ye(await e.getPR(f),"PR not found");let x;try{x=uh.parse({question:w})}catch(E){throw E instanceof m.ZodError?new Se(400,E.errors[0]?.message??"Invalid question"):E}let k=await e.addQuestion(f,x.question);try{await i("answer_pr_question",k.id,nt("answer_pr_question",k.id),{prId:f})}catch(E){let F=Xv(E);throw await e.updateQuestion(k.id,{status:"error",error:F.trim().slice(0,2e3)}),E}return b(),k},async listLogs(f){return e.getLogs(f)},async getOnboardingStatus(){let f=await e.getConfig();return Oh(f,f.watchedRepos)},async installReviewWorkflow(f,w){let x=await e.getConfig();return Nh(x,f,w)},async listHealingSessions(){return e.listHealingSessions()},async getHealingSession(f){return ye(await e.getHealingSession(f),"Healing session not found")},async listDeploymentHealingSessions(f){return e.listDeploymentHealingSessions(f?{repo:f}:void 0)},async getDeploymentHealingSession(f){return ye(await e.getDeploymentHealingSession(f),"Deployment healing session not found")},async getConfig(){return e.getConfig()},async updateConfig(f){let w=await e.updateConfig(f);return v&&h&&await A(),b(),w},async listSocialChangelogs(){return e.getSocialChangelogs()},async getSocialChangelog(f){return ye(await e.getSocialChangelog(f),"Changelog not found")},async listReleaseRuns(){return e.listReleaseRuns()},async getReleaseRun(f){return ye(await e.getReleaseRun(f),"Release run not found")},async retryReleaseRun(f){let w=await o.retryReleaseRun(f);if(!w)throw new Se(404,"Release run not found");return b(),w}};return L}function Kv(t){return t instanceof Se}function vC(t){return t instanceof Error?t.message:String(t)}function Z(t,e){if(e instanceof m.ZodError){t.status(400).json({error:e.errors[0]?.message??"Invalid request"});return}if(e instanceof ce){t.status(e.statusCode).json({error:e.message});return}if(Kv(e)){t.status(e.statusCode).json({error:e.message});return}t.status(500).json({error:vC(e)})}function Qv(t){return{...t,githubToken:t.githubToken?`***${t.githubToken.slice(-4)}`:""}}async function Yv(t,e,a={}){let r=a.runtime??Vv(a);return await r.start(),t.on("close",()=>{r.stop()}),e.get("/api/runtime",async(n,i)=>{i.json(await r.getRuntimeSnapshot())}),e.post("/api/runtime/drain",async(n,i)=>{try{let s=m.object({enabled:m.boolean(),reason:m.string().optional(),waitForIdle:m.boolean().optional(),timeoutMs:m.number().int().positive().max(6e5).optional()}).parse(n.body),o=await r.setDrainMode(s);if(s.enabled&&s.waitForIdle&&o.drained===!1)return i.status(202).json(o);i.json(o)}catch(s){Z(i,s)}}),e.get("/api/repos",async(n,i)=>{i.json(await r.listRepos())}),e.post("/api/repos",async(n,i)=>{try{let{repo:s}=m.object({repo:m.string().min(1)}).parse(n.body);i.status(201).json(await r.addRepo(s))}catch(s){Z(i,s)}}),e.post("/api/repos/sync",async(n,i)=>{try{i.json(await r.syncRepos())}catch(s){Z(i,s)}}),e.get("/api/prs",async(n,i)=>{i.json(await r.listPRs("active"))}),e.get("/api/prs/archived",async(n,i)=>{i.json(await r.listPRs("archived"))}),e.get("/api/prs/:id",async(n,i)=>{let s=await r.getPR(n.params.id);if(!s)return i.status(404).json({error:"PR not found"});i.json(s)}),e.post("/api/prs",async(n,i)=>{try{i.status(201).json(await r.addPR(n.body?.url))}catch(s){Z(i,s)}}),e.delete("/api/prs/:id",async(n,i)=>{try{i.json(await r.removePR(n.params.id))}catch(s){Z(i,s)}}),e.patch("/api/prs/:id/watch",async(n,i)=>{try{let{enabled:s}=m.object({enabled:m.boolean()}).parse(n.body);i.json(await r.setPRWatchEnabled(n.params.id,s))}catch(s){Z(i,s)}}),e.post("/api/prs/:id/fetch",async(n,i)=>{try{i.json(await r.fetchPRFeedback(n.params.id))}catch(s){Z(i,s)}}),e.post("/api/prs/:id/triage",async(n,i)=>{try{i.json(await r.triagePR(n.params.id))}catch(s){Z(i,s)}}),e.post("/api/prs/:id/apply",async(n,i)=>{try{i.json(await r.applyPR(n.params.id))}catch(s){Z(i,s)}}),e.post("/api/prs/:id/babysit",async(n,i)=>{try{i.json(await r.babysitPR(n.params.id))}catch(s){Z(i,s)}}),e.patch("/api/prs/:id/feedback/:feedbackId",async(n,i)=>{try{let{decision:s}=m.object({decision:m.enum(["accept","reject","flag"])}).parse(n.body);i.json(await r.setFeedbackDecision(n.params.id,n.params.feedbackId,s))}catch(s){Z(i,s)}}),e.post("/api/prs/:id/feedback/:feedbackId/retry",async(n,i)=>{try{i.json(await r.retryFeedback(n.params.id,n.params.feedbackId))}catch(s){Z(i,s)}}),e.get("/api/prs/:id/questions",async(n,i)=>{try{i.json(await r.listPRQuestions(n.params.id))}catch(s){Z(i,s)}}),e.post("/api/prs/:id/questions",async(n,i)=>{try{i.status(201).json(await r.askQuestion(n.params.id,n.body?.question))}catch(s){Z(i,s)}}),e.get("/api/logs",async(n,i)=>{let s=typeof n.query.prId=="string"?n.query.prId:void 0;i.json(await r.listLogs(s))}),e.get("/api/onboarding/status",async(n,i)=>{try{i.json(await r.getOnboardingStatus())}catch(s){Z(i,s)}}),e.post("/api/onboarding/install-review",async(n,i)=>{try{let{repo:s,tool:o}=m.object({repo:m.string().min(1),tool:m.enum(["claude","codex"])}).parse(n.body);i.json(await r.installReviewWorkflow(s,o))}catch(s){Z(i,s)}}),e.get("/api/healing-sessions",async(n,i)=>{try{i.json(await r.listHealingSessions())}catch(s){Z(i,s)}}),e.get("/api/healing-sessions/:id",async(n,i)=>{try{i.json(await r.getHealingSession(n.params.id))}catch(s){Z(i,s)}}),e.get("/api/deployment-healing-sessions",async(n,i)=>{try{let s=typeof n.query.repo=="string"?n.query.repo:void 0;i.json(await r.listDeploymentHealingSessions(s))}catch(s){Z(i,s)}}),e.get("/api/deployment-healing-sessions/:id",async(n,i)=>{try{i.json(await r.getDeploymentHealingSession(n.params.id))}catch(s){Z(i,s)}}),e.get("/api/config",async(n,i)=>{i.json(Qv(await r.getConfig()))}),e.get("/api/changelogs",async(n,i)=>{try{i.json(await r.listSocialChangelogs())}catch(s){Z(i,s)}}),e.get("/api/changelogs/:id",async(n,i)=>{try{i.json(await r.getSocialChangelog(n.params.id))}catch(s){Z(i,s)}}),e.get("/api/releases",async(n,i)=>{try{i.json(await r.listReleaseRuns())}catch(s){Z(i,s)}}),e.get("/api/releases/:id",async(n,i)=>{try{i.json(await r.getReleaseRun(n.params.id))}catch(s){Z(i,s)}}),e.post("/api/releases/:id/retry",async(n,i)=>{try{i.json(await r.retryReleaseRun(n.params.id))}catch(s){Z(i,s)}}),e.patch("/api/config",async(n,i)=>{try{let s=di.partial().parse(n.body);i.json(Qv(await r.updateConfig(s)))}catch(s){Z(i,s)}}),t}var Zv=Ie(tc(),1),eb=Ie(require("fs"),1),tu=Ie(require("path"),1);function tb(t){let e=tu.default.resolve(__dirname,"public");if(!eb.default.existsSync(e))throw new Error(`Could not find the build directory: ${e}, make sure to build the client first`);t.use(Zv.default.static(e)),t.use("/{*path}",(a,r)=>{r.sendFile(tu.default.resolve(e,"index.html"))})}var bC=new Set(["127.0.0.1","::1","::ffff:127.0.0.1","localhost"]);function yC(t){if(!t)return!1;let e=t.replace(/^\[|\]$/g,"");return bC.has(e)?!0:e.startsWith("::ffff:")?e.slice(7).startsWith("127."):!!e.startsWith("127.")}function ab(t,e,a){let r=t.ip??t.socket?.remoteAddress;if(!yC(r)){e.status(403).json({error:"Forbidden",message:"Code Factory only accepts connections from the local machine. External access is not permitted."});return}a()}var nb=require("http"),ib=Ie(require("open"),1),xa=(0,Li.default)(),rb=(0,nb.createServer)(xa);xa.use(Li.default.json({verify:(t,e,a)=>{t.rawBody=a}}));xa.use(Li.default.urlencoded({extended:!1}));xa.use("/api",ab);function sb(t,e="express"){let a=new Date().toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit",second:"2-digit",hour12:!0});console.log(`${a} [${e}] ${t}`)}(async()=>{await Yv(rb,xa),xa.use((e,a,r,n)=>{let i=e,s=i.status||i.statusCode||500,o=i.message||"Internal Server Error";return console.error("Internal Server Error:",e),r.headersSent?n(e):r.status(s).json({message:o})}),tb(xa);let t=parseInt(process.env.PORT||"5001",10);rb.listen({port:t,host:"0.0.0.0"},()=>{let e=`http://localhost:${t}`;console.log(`
|
|
908
|
-
oh-my-pr v2.8.
|
|
908
|
+
oh-my-pr v2.8.2
|
|
909
909
|
Dashboard: ${e}
|
|
910
910
|
`),process.env.TAURI_DEV||(0,ib.default)(e).catch(r=>{sb(`Could not open browser automatically: ${r.message}`)})})})();0&&(module.exports={log});
|
|
911
911
|
/*! Bundled license information:
|