@netlify/agent-runner-cli 1.69.3 → 1.70.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.
package/dist/bin-local.js CHANGED
@@ -5,7 +5,7 @@ import L from"process";import vr from"path";import Ar from"fs";import ai from"mi
5
5
  ${o}
6
6
  </extracted_error_chunk>`).join(`
7
7
 
8
- `);return s.length>e.length*.8?e:s}import{execSync as vn}from"child_process";import cr from"fs/promises";import An from"path";import te from"process";import{getTracer as bn}from"@netlify/otel";import Ie from"process";var se=class extends Error{constructor(r,i,n){super(r);this.statusCode=i;this.userMessage=n;this.name="GracefulShutdownError"}},Tt=e=>e instanceof se;var Ce=Ie.env.NETLIFY_API_URL,Ne=Ie.env.NETLIFY_API_TOKEN,W=E("api"),Pe=()=>Ie.env.NETLIFY_LOCAL_MODE==="true",Te=async(e,t={})=>{if(!Ce||!Ne)throw new Error("No API URL or token");let r=new URL(e,Ce),i={...t,headers:{...t.headers,Authorization:`Bearer ${Ne}`}};Ie.env.AGENT_RUNNERS_DEBUG==="true"&&(i.headers["x-nf-debug-logging"]="true"),t.json&&(i.headers||={},i.headers["Content-Type"]="application/json",i.body=JSON.stringify(t.json));let n=await fetch(r,i),s=n.ok&&n.status<=299;if(Ie.env.AGENT_RUNNERS_DEBUG==="true")W.log(`Response headers for ${r}:`),n.headers.forEach((a,c)=>{W.log(` ${c}: ${a}`)});else{let a=n.headers.get("x-request-id")||n.headers.get("x-nf-request-id");W.log(`Request ID for ${r}: ${a||"N/A"}`)}if(s||W.error(`Got status ${n.status} for request ${r}`),t.raw){if(!s)throw new Error(`API request failed: ${n.status} ${n.statusText}`);return n}let o=await(n.headers.get("content-type")?.includes("application/json")?n.json():n.text());if(!s){let a=typeof o=="string"?o:JSON.stringify(o);throw n.status===404?new se(`API request failed: 404 - ${a}`,404,"The site associated with this agent run no longer exists."):n.status===403&&t.gracefulOn403?new se(`API request failed: 403 - ${a}`,403,"Credit limit reached. Please add more credits to continue using Agent Runners."):new Error(`API request failed: ${n.status} - ${a}`)}return o},xt=e=>{W.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Ce=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(Ne=e.constants.NETLIFY_API_TOKEN)},Rt=()=>({apiUrl:Ce,token:Ne}),xe=async(e,t)=>Pe()?(W.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):Te(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),U=async(e,t,r)=>Pe()?(W.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):Te(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var St=async(e,t)=>Pe()?(W.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):Te(`/api/v1/agent_runners/${e}/sessions/${t}`),vt=(e,t,r)=>Te(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn403:!0}),At=async(e,t)=>Pe()?(W.log("Mock API: getDiffUploadUrls called",{runnerId:e,sessionId:t}),{result:{upload_url:"https://s3.mock.com/mock-upload-url-result",s3_key:"mock-s3-key-result"},cumulative:{upload_url:"https://s3.mock.com/mock-upload-url-cumulative",s3_key:"mock-s3-key-cumulative"}}):Te(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),Ke=async(e,t)=>{W.log(`Uploading diff to S3: ${e.substring(0,50)}...`);let r=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!r.ok)throw new Error(`S3 upload failed with status ${r.status}`);return r};var ae=E("ai_gateway"),Je=null;var bt=async()=>{if(Je)return Je;ae.log("Fetching available AI gateway providers");let e=await fetch(`${Rt().apiUrl}/api/v1/ai-gateway/providers`);if(!e.ok)throw new Error(`Failed to fetch AI gateway providers: ${e.statusText}`);let t=await e.json();return Je=t,ae.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},Lr=async(e,t)=>{let i=(await bt()).providers[e];if(!i)return ae.log(`Provider '${e}' not found`),!1;let n=i.models.includes(t);return ae.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},Ct=async({netlify:e,config:t})=>{let r,i,n,s,o=e.constants?.SITE_ID;if(!o)throw new Error("No site id");let a=async()=>{clearTimeout(n),ae.log("Requesting AI gateway information");let c=await vt(o,t.id,t.sessionId);if({token:r,url:s}=c,i=c.expires_at?c.expires_at*1e3:void 0,ae.log("Got AI gateway information",{token:!!r,expiresAt:i,url:s}),i){let u=i-Date.now()-6e4;u>0&&(n=setTimeout(()=>{a()},u))}};return await Promise.all([a(),bt()]),{get url(){return s},get token(){return r},isModelAvailableForProvider:Lr}};import J from"process";import Z from"path";import ke from"fs";import{fileURLToPath as Yr}from"url";import{createRequire as Br}from"module";import{execa as qr,execaCommand as Gi}from"execa";import{Transform as Fr}from"stream";var Dr=new Set(["NODE_ENV","PATH","HOME","USER","USERNAME","SHELL","PWD","OLDPWD","TMPDIR","TMP","TEMP","LANG","TERM","EDITOR","PAGER","OS","PROCESSOR_ARCHITECTURE","PROCESSOR_IDENTIFIER","SYSTEMROOT","WINDIR","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","APPDATA","LOCALAPPDATA","NODE_OPTIONS","NODE_PATH","NODE_DEBUG","NODE_NO_WARNINGS","npm_config_registry","npm_config_cache","npm_execpath","npm_node_execpath","CI","GITHUB_ACTIONS","GITHUB_WORKSPACE","GITHUB_REPOSITORY","GITHUB_REF","BUILDKITE","BUILDKITE_BRANCH","BUILDKITE_COMMIT","BUILDKITE_BUILD_NUMBER","JENKINS_URL","TRAVIS","CIRCLECI","DISPLAY","COLORTERM","TERM_PROGRAM","TERM_PROGRAM_VERSION","COLUMNS","LINES","HISTSIZE","HISTFILE","NETLIFY_AGENT_RUNNER_ID","NETLIFY_AGENT_RUNNER_SESSION_ID","NETLIFY_AGENT_RUNNER_PROMPT","NETLIFY_AGENT_RUNNER_AGENT","NETLIFY_AGENT_RUNNER_MODEL","NETLIFY_AGENT_RUNNER_CONTEXT","NETLIFY_AGENT_RUNNER_HAS_REPO","NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED","NETLIFY_AGENT_RUNNER_SHA","NETLIFY_TEAM_TYPE","AGENT_RUNNERS_DEBUG","NETLIFY_TEAM_ID","NETLIFY_AGENT_RUNNER_USER_ID","SITE_NAME"]),Mr=new Set(["true","false","undefined","null","deploy","project","claude","gemini","codex",""]);function Ur(){return Object.entries(process.env).filter(([e,t])=>!(!t||Dr.has(e)||Mr.has(t)||!isNaN(Number(t))||t.length<5)).map(([,e])=>e).filter(Boolean)}function z(e){if(typeof e!="string")return e;let t=Ur();if(t.length===0)return e;let r=e;return t.forEach(i=>{let n=new RegExp(Gr(i),"g");r=r.replace(n,"******")}),r}function Gr(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var le=class extends Fr{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,i){let n=t.toString(),s=z(n);i(null,s)}};function Nt(){if(!(process.env.NETLIFY_MASK_LOGS!=="false"))return;let t=process.stdout.write.bind(process.stdout),r=process.stderr.write.bind(process.stderr);process.stdout.write=function(i,n,s){let o=typeof i=="string"?z(i):i;return typeof n=="function"?t(o,n):t(o,n,s)},process.stderr.write=function(i,n,s){let o=typeof i=="string"?z(i):i;return typeof n=="function"?r(o,n):r(o,n,s)}}var Re=null,Pt=e=>(Re&&Re.destroy(),Re=new ee({totalAllowedTime:e}),Re),kt=()=>Re;var ee=class{constructor({totalAllowedTime:t}){this.withStageTimer=async(t,r,i)=>{if(this.isTimeExpired())throw new Error(`${t} stage did not complete in the allowed time. Time has already expired.`);let n=this.onTimesUp(()=>{throw new Error(`${t} stage did not complete in the allowed time.`)}),s=null,o=null;i!==void 0&&(o=new Promise((a,c)=>{s=setTimeout(()=>{c(new Error(`${t} stage exceeded its maximum duration of ${i}ms`))},i)}));try{return o?await Promise.race([r(),o]):await r()}finally{n(),s&&clearTimeout(s)}};this.startTime=Date.now(),this.totalAllowedTime=t,this.globalTimeoutId=null,this.subscribers=[],this.hasTimedOut=!1,this.setupGlobalTimeout()}getElapsedTime(){return Date.now()-this.startTime}getRemainingTime(){let t=this.getElapsedTime(),r=this.totalAllowedTime-t;return Math.max(0,r)}isTimeExpired(){return this.getRemainingTime()===0||this.hasTimedOut}setupGlobalTimeout(){this.globalTimeoutId&&clearTimeout(this.globalTimeoutId),this.globalTimeoutId=setTimeout(()=>{this.notifyTimeUp()},this.totalAllowedTime)}notifyTimeUp(){this.hasTimedOut=!0;for(let t=this.subscribers.length-1;t>=0;t--)try{this.subscribers[t]()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}}onTimesUp(t){if(this.subscribers.push(t),this.hasTimedOut)try{t()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}return()=>{let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}}off(t){let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}clearSubscribers(){this.subscribers.length=0}getSubscriberCount(){return this.subscribers.length}destroy(){this.globalTimeoutId&&(clearTimeout(this.globalTimeoutId),this.globalTimeoutId=null),this.clearSubscribers()}static{this.timeUnits={seconds:t=>t*1e3,minutes:t=>t*60*1e3,hours:t=>t*60*60*1e3}}};var Ot="netlify-agent-runner-context.md",Ve="task-history",K=".netlify",re="results.md",Xe="assets";var ne=1800*1e3;var $t={name:"@netlify/agent-runner-cli",type:"module",version:"1.69.3",description:"CLI tool for running Netlify agents",main:"./dist/index.js",types:"./dist/index.d.ts",exports:"./dist/index.js",bin:{"agent-runner-cli":"./dist/bin.js","agent-runner-cli-local":"./dist/bin-local.js"},files:["dist/**/*.js","dist/**/*.d.ts","dist/skills/**","patches","scripts"],scripts:{build:"tsup",dev:"tsup --watch",prepare:"husky install node_modules/@netlify/eslint-config-node/.husky/",prepublishOnly:"npm ci && npm test",prepack:"npm run build",test:"run-s build format test:dev",format:"run-s build format:check-fix:*","format:ci":"run-s build format:check:*","format:check-fix:lint":"run-e format:check:lint format:fix:lint","format:check:lint":"cross-env-shell eslint $npm_package_config_eslint","format:fix:lint":"cross-env-shell eslint --fix $npm_package_config_eslint","format:check-fix:prettier":"run-e format:check:prettier format:fix:prettier","format:check:prettier":"cross-env-shell prettier --check $npm_package_config_prettier","format:fix:prettier":"cross-env-shell prettier --write $npm_package_config_prettier","test:dev":"run-s build test:dev:*","test:ci":"run-s build test:ci:*","test:dev:vitest":"LOG=0 vitest --exclude '**/integration/**'","test:ci:vitest":"LOG=0 c8 -r lcovonly -r text -r json vitest --exclude '**/integration/**'","test:integration":"vitest run test/integration/","test:integration:codex":"vitest run test/integration/codex.test.ts","test:integration:claude":"vitest run test/integration/claude.test.ts","test:integration:gemini":"vitest run test/integration/gemini.test.ts","test:integration:create-stage":"vitest run test/integration/create.test.ts",postinstall:"node scripts/postinstall.js"},config:{eslint:'--cache --format=codeframe --max-warnings=0 "{src,scripts,test,.github}/**/*.{js,ts,md,html}"',prettier:'--ignore-path .gitignore --loglevel=warn "{src,scripts,test,.github}/**/*.{js,ts,md,yml,json,html}" "*.{js,ts,yml,json,html}" ".*.{js,ts,yml,json,html}" "!**/package-lock.json" "!package-lock.json" "!src/skills/**/*.md"'},keywords:[],license:"MIT",repository:"netlify/agent-runner-cli",bugs:{url:"https://github.com/netlify/agent-runner-cli/issues"},author:"Netlify Inc.",directories:{test:"test"},devDependencies:{"@commitlint/cli":"^20.0.0","@commitlint/config-conventional":"^20.0.0","@eslint/compat":"^2.0.0","@eslint/js":"^9.35.0","@netlify/eslint-config-node":"^7.0.1","@types/node":"^24.5.0","@typescript-eslint/eslint-plugin":"^8.0.0","@typescript-eslint/parser":"^8.0.0","@vitest/eslint-plugin":"^1.6.6",c8:"^10.0.0","eslint-config-prettier":"^10.1.8","eslint-plugin-n":"^17.0.0",husky:"^9.0.0","patch-package":"^8.0.0",tsup:"^8.5.0",typescript:"^5.0.0","typescript-eslint":"^8.44.0",vitest:"^4.0.16"},dependencies:{"@anthropic-ai/claude-code":"2.1.37","@anthropic-ai/sdk":"0.72.1","@google/gemini-cli":"0.27.3","@netlify/otel":"^5.1.1","@openai/codex":"0.93.0","@opentelemetry/exporter-trace-otlp-grpc":"^0.208.0",execa:"^9.6.1",kaddidlehopper:"^0.1.2",minimist:"^1.2.8",openai:"6.17.0"}};var Hr=Yr(import.meta.url),Wr=Z.dirname(Hr),Kr=Br(import.meta.url),ce=E("shell"),ze=new Set,Jr={preferLocal:!0},x=(e,t,r)=>{let[i,n]=Vr(t,r),s={...Jr,...n},o=qr(e,i,s);Xr(o,s),Zr(o);let a=r?.idleTimeout;return a&&a>0&&zr(o,a),o};var Vr=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},Xr=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(J.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new le).pipe(J.stdout),e.stdout?.pipe(new le).pipe(J.stdout),e.stderr?.pipe(new le).pipe(J.stderr);return}e.stdout?.pipe(J.stdout),e.stderr?.pipe(J.stderr)},Ze=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(J.kill(-e.pid,t),ce.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return ce.error("Error killing process:",r),!1}},Lt=e=>Ze(e,"SIGKILL"),zr=(e,t)=>{let r=null,i=()=>{ce.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),Ze(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ce.log(`Force killing idle process ${e.pid}`),Lt(e))},5e3)},n=()=>{r&&clearTimeout(r),r=setTimeout(i,t)};n(),e.stdout?.on("data",n),e.stderr?.on("data",n);let s=()=>{r&&(clearTimeout(r),r=null)};e.on("exit",s),e.on("error",s)},Zr=e=>{ze.add(e);let t=kt();if(t){let r=t.onTimesUp(()=>{ce.log(`Global timer expired, killing process ${e.pid}`),Ze(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ce.log(`Force killing process ${e.pid} after timeout`),Lt(e))},5e3)});e.on("exit",()=>{ze.delete(e),r()}),e.on("error",()=>{ze.delete(e),r()})}};function Oe(e,t){return!!Q(e,t)}function Q(e,t){if(!J.env.NETLIFY_LOCAL_MODE)try{let n=Kr.resolve($t.name),s=Z.dirname(n);for(;s!==Z.dirname(s);){let o=Z.dirname(s);if(Z.basename(o)==="node_modules"){let a=Z.join(o,".bin",t);if(ke.existsSync(a))return a;break}s=o}}catch(n){console.error("Could not resolve package.json",n)}if(J.env.NODE_PATH){let n=Z.join(J.env.NODE_PATH,".bin",t);if(ke.existsSync(n))return n}let r=Z.join(e,"node_modules",".bin",t);if(ke.existsSync(r))return r;let i=Z.join(Wr,"..","node_modules",".bin",t);if(ke.existsSync(i))return i}var Qr=E("utils"),en=e=>new Promise(t=>{setTimeout(t,e)}),Ft=(e,t=3e3)=>{let r=!1,i=null,n=[],s=null,o=(...a)=>{if(r)return i=a,new Promise(d=>{n.push(d)});r=!0;let c,u=new Promise(d=>{c=d});return s=(async()=>{await Promise.resolve();let d=await e(...a);for(c(d);;){if(await en(t),!i)return r=!1,s=null,d;let p=i,m=n;i=null,n=[],d=await e(...p),m.forEach(y=>{y(d)})}})(),u};return o.flush=async()=>{if((r||i)&&s)return await s,o.flush()},o},ue=(e,t,r=!1)=>{let i=null,n=null,s=null,o=function(...a){n=a,s=this;let c=r&&!i;clearTimeout(i),i=setTimeout(()=>{i=null,r||(e.apply(s,n),n=null,s=null)},t),c&&(e.apply(s,n),n=null,s=null)};return o.cancel=()=>{clearTimeout(i),i=null,n=null,s=null},o.flush=()=>{if(i){clearTimeout(i);let a=n,c=s;i=null,n=null,s=null,e.apply(c,a)}},o},Dt=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(i){t&&(r?.error?r.error("Could not parse JSON",i):Qr.error("Could not parse JSON",i))}},Mt=(e,t)=>{let n=".netlify.app",s="agent-";if(!t)return`${s}${e.slice(0,6)}`;let a=`--${t}${n}`;if(a.length>55)return"";let c=60-a.length;if(c<=0)return"";if(c>=s.length+6){let u=Math.min(c-s.length,e.length);return`${s}${e.slice(0,u)}`}return e.slice(0,c)};var tn=50*1024,Qe=(e,t=tn)=>{if(!e||typeof e!="string"||e.length<=t)return e;let i=e.startsWith("```")?"\n... [truncated]\n```":"... [truncated]";return e.slice(0,t)+i};import{Buffer as Ut}from"buffer";import rn from"path";var Gt=E("repo"),Yt=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{Gt.info("Getting runner diffs");let i=await on(r),{hasChanges:n}=i,{status:s}=i;if(!n)return{hasChanges:!1};if(!t){let _=an(s);await ln(_,r)}Gt.info("Changes after processing"),await tt(r);let o=await rt(s,r);if(await et(o,r),n=await sn(r),!n)return{hasChanges:!1,ignored:o};process.env.NETLIFY_INTERNAL_GIT="1";try{await x("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},c=await x("git",["diff",e.runSha,"HEAD"],a),u=String(c.stdout??"");if(n=!!u,!n)return await jt(r),{hasChanges:!1,ignored:o};let d=await x("git",["diff",e.runSha,"HEAD","--binary"],a),p=String(d.stdout??""),m,y;if(e.sha){let _=await x("git",["diff",e.sha,"HEAD"],a);m=String(_.stdout??"");let I=await x("git",["diff",e.sha,"HEAD","--binary"],a),w=String(I.stdout??"");m!==w&&(y=Ut.from(w).toString("base64"))}await jt(r);let h={hasChanges:!0,diff:u,resultDiff:m,ignored:o};return u!==p&&(h.diffBinary=Ut.from(p).toString("base64")),y&&(h.resultDiffBinary=y),h},jt=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await x("git",["reset","--soft","HEAD~1"],{cwd:e})},et=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await x("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},tt=async(e=process.cwd())=>{let t=await x("git",["status","-s"],{cwd:e});return String(t.stdout??"")},Bt=/.. (.+)?\.log$/,nn=[Bt],on=async(e=process.cwd())=>{let t=await tt(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
8
+ `);return s.length>e.length*.8?e:s}import{execSync as vn}from"child_process";import cr from"fs/promises";import An from"path";import te from"process";import{getTracer as bn}from"@netlify/otel";import Ie from"process";var se=class extends Error{constructor(r,i,n){super(r);this.statusCode=i;this.userMessage=n;this.name="GracefulShutdownError"}},Tt=e=>e instanceof se;var Ce=Ie.env.NETLIFY_API_URL,Ne=Ie.env.NETLIFY_API_TOKEN,W=E("api"),Pe=()=>Ie.env.NETLIFY_LOCAL_MODE==="true",Te=async(e,t={})=>{if(!Ce||!Ne)throw new Error("No API URL or token");let r=new URL(e,Ce),i={...t,headers:{...t.headers,Authorization:`Bearer ${Ne}`}};Ie.env.AGENT_RUNNERS_DEBUG==="true"&&(i.headers["x-nf-debug-logging"]="true"),t.json&&(i.headers||={},i.headers["Content-Type"]="application/json",i.body=JSON.stringify(t.json));let n=await fetch(r,i),s=n.ok&&n.status<=299;if(Ie.env.AGENT_RUNNERS_DEBUG==="true")W.log(`Response headers for ${r}:`),n.headers.forEach((a,c)=>{W.log(` ${c}: ${a}`)});else{let a=n.headers.get("x-request-id")||n.headers.get("x-nf-request-id");W.log(`Request ID for ${r}: ${a||"N/A"}`)}if(s||W.error(`Got status ${n.status} for request ${r}`),t.raw){if(!s)throw new Error(`API request failed: ${n.status} ${n.statusText}`);return n}let o=await(n.headers.get("content-type")?.includes("application/json")?n.json():n.text());if(!s){let a=typeof o=="string"?o:JSON.stringify(o);throw n.status===404?new se(`API request failed: 404 - ${a}`,404,"The site associated with this agent run no longer exists."):n.status===403&&t.gracefulOn403?new se(`API request failed: 403 - ${a}`,403,"Credit limit reached. Please add more credits to continue using Agent Runners."):new Error(`API request failed: ${n.status} - ${a}`)}return o},xt=e=>{W.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Ce=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(Ne=e.constants.NETLIFY_API_TOKEN)},Rt=()=>({apiUrl:Ce,token:Ne}),xe=async(e,t)=>Pe()?(W.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):Te(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),U=async(e,t,r)=>Pe()?(W.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):Te(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var St=async(e,t)=>Pe()?(W.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):Te(`/api/v1/agent_runners/${e}/sessions/${t}`),vt=(e,t,r)=>Te(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn403:!0}),At=async(e,t)=>Pe()?(W.log("Mock API: getDiffUploadUrls called",{runnerId:e,sessionId:t}),{result:{upload_url:"https://s3.mock.com/mock-upload-url-result",s3_key:"mock-s3-key-result"},cumulative:{upload_url:"https://s3.mock.com/mock-upload-url-cumulative",s3_key:"mock-s3-key-cumulative"}}):Te(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),Ke=async(e,t)=>{W.log(`Uploading diff to S3: ${e.substring(0,50)}...`);let r=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!r.ok)throw new Error(`S3 upload failed with status ${r.status}`);return r};var ae=E("ai_gateway"),Je=null;var bt=async()=>{if(Je)return Je;ae.log("Fetching available AI gateway providers");let e=await fetch(`${Rt().apiUrl}/api/v1/ai-gateway/providers`);if(!e.ok)throw new Error(`Failed to fetch AI gateway providers: ${e.statusText}`);let t=await e.json();return Je=t,ae.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},Lr=async(e,t)=>{let i=(await bt()).providers[e];if(!i)return ae.log(`Provider '${e}' not found`),!1;let n=i.models.includes(t);return ae.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},Ct=async({netlify:e,config:t})=>{let r,i,n,s,o=e.constants?.SITE_ID;if(!o)throw new Error("No site id");let a=async()=>{clearTimeout(n),ae.log("Requesting AI gateway information");let c=await vt(o,t.id,t.sessionId);if({token:r,url:s}=c,i=c.expires_at?c.expires_at*1e3:void 0,ae.log("Got AI gateway information",{token:!!r,expiresAt:i,url:s}),i){let u=i-Date.now()-6e4;u>0&&(n=setTimeout(()=>{a()},u))}};return await Promise.all([a(),bt()]),{get url(){return s},get token(){return r},isModelAvailableForProvider:Lr}};import J from"process";import Z from"path";import ke from"fs";import{fileURLToPath as Yr}from"url";import{createRequire as Br}from"module";import{execa as qr,execaCommand as Gi}from"execa";import{Transform as Fr}from"stream";var Dr=new Set(["NODE_ENV","PATH","HOME","USER","USERNAME","SHELL","PWD","OLDPWD","TMPDIR","TMP","TEMP","LANG","TERM","EDITOR","PAGER","OS","PROCESSOR_ARCHITECTURE","PROCESSOR_IDENTIFIER","SYSTEMROOT","WINDIR","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","APPDATA","LOCALAPPDATA","NODE_OPTIONS","NODE_PATH","NODE_DEBUG","NODE_NO_WARNINGS","npm_config_registry","npm_config_cache","npm_execpath","npm_node_execpath","CI","GITHUB_ACTIONS","GITHUB_WORKSPACE","GITHUB_REPOSITORY","GITHUB_REF","BUILDKITE","BUILDKITE_BRANCH","BUILDKITE_COMMIT","BUILDKITE_BUILD_NUMBER","JENKINS_URL","TRAVIS","CIRCLECI","DISPLAY","COLORTERM","TERM_PROGRAM","TERM_PROGRAM_VERSION","COLUMNS","LINES","HISTSIZE","HISTFILE","NETLIFY_AGENT_RUNNER_ID","NETLIFY_AGENT_RUNNER_SESSION_ID","NETLIFY_AGENT_RUNNER_PROMPT","NETLIFY_AGENT_RUNNER_AGENT","NETLIFY_AGENT_RUNNER_MODEL","NETLIFY_AGENT_RUNNER_CONTEXT","NETLIFY_AGENT_RUNNER_HAS_REPO","NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED","NETLIFY_AGENT_RUNNER_SHA","NETLIFY_TEAM_TYPE","AGENT_RUNNERS_DEBUG","NETLIFY_TEAM_ID","NETLIFY_AGENT_RUNNER_USER_ID","SITE_NAME"]),Mr=new Set(["true","false","undefined","null","deploy","project","claude","gemini","codex",""]);function Ur(){return Object.entries(process.env).filter(([e,t])=>!(!t||Dr.has(e)||Mr.has(t)||!isNaN(Number(t))||t.length<5)).map(([,e])=>e).filter(Boolean)}function z(e){if(typeof e!="string")return e;let t=Ur();if(t.length===0)return e;let r=e;return t.forEach(i=>{let n=new RegExp(Gr(i),"g");r=r.replace(n,"******")}),r}function Gr(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var le=class extends Fr{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,i){let n=t.toString(),s=z(n);i(null,s)}};function Nt(){if(!(process.env.NETLIFY_MASK_LOGS!=="false"))return;let t=process.stdout.write.bind(process.stdout),r=process.stderr.write.bind(process.stderr);process.stdout.write=function(i,n,s){let o=typeof i=="string"?z(i):i;return typeof n=="function"?t(o,n):t(o,n,s)},process.stderr.write=function(i,n,s){let o=typeof i=="string"?z(i):i;return typeof n=="function"?r(o,n):r(o,n,s)}}var Re=null,Pt=e=>(Re&&Re.destroy(),Re=new ee({totalAllowedTime:e}),Re),kt=()=>Re;var ee=class{constructor({totalAllowedTime:t}){this.withStageTimer=async(t,r,i)=>{if(this.isTimeExpired())throw new Error(`${t} stage did not complete in the allowed time. Time has already expired.`);let n=this.onTimesUp(()=>{throw new Error(`${t} stage did not complete in the allowed time.`)}),s=null,o=null;i!==void 0&&(o=new Promise((a,c)=>{s=setTimeout(()=>{c(new Error(`${t} stage exceeded its maximum duration of ${i}ms`))},i)}));try{return o?await Promise.race([r(),o]):await r()}finally{n(),s&&clearTimeout(s)}};this.startTime=Date.now(),this.totalAllowedTime=t,this.globalTimeoutId=null,this.subscribers=[],this.hasTimedOut=!1,this.setupGlobalTimeout()}getElapsedTime(){return Date.now()-this.startTime}getRemainingTime(){let t=this.getElapsedTime(),r=this.totalAllowedTime-t;return Math.max(0,r)}isTimeExpired(){return this.getRemainingTime()===0||this.hasTimedOut}setupGlobalTimeout(){this.globalTimeoutId&&clearTimeout(this.globalTimeoutId),this.globalTimeoutId=setTimeout(()=>{this.notifyTimeUp()},this.totalAllowedTime)}notifyTimeUp(){this.hasTimedOut=!0;for(let t=this.subscribers.length-1;t>=0;t--)try{this.subscribers[t]()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}}onTimesUp(t){if(this.subscribers.push(t),this.hasTimedOut)try{t()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}return()=>{let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}}off(t){let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}clearSubscribers(){this.subscribers.length=0}getSubscriberCount(){return this.subscribers.length}destroy(){this.globalTimeoutId&&(clearTimeout(this.globalTimeoutId),this.globalTimeoutId=null),this.clearSubscribers()}static{this.timeUnits={seconds:t=>t*1e3,minutes:t=>t*60*1e3,hours:t=>t*60*60*1e3}}};var Ot="netlify-agent-runner-context.md",Ve="task-history",K=".netlify",re="results.md",Xe="assets";var ne=1800*1e3;var $t={name:"@netlify/agent-runner-cli",type:"module",version:"1.70.0",description:"CLI tool for running Netlify agents",main:"./dist/index.js",types:"./dist/index.d.ts",exports:"./dist/index.js",bin:{"agent-runner-cli":"./dist/bin.js","agent-runner-cli-local":"./dist/bin-local.js"},files:["dist/**/*.js","dist/**/*.d.ts","dist/skills/**","patches","scripts"],scripts:{build:"tsup",dev:"tsup --watch",prepare:"husky install node_modules/@netlify/eslint-config-node/.husky/",prepublishOnly:"npm ci && npm test",prepack:"npm run build",test:"run-s build format test:dev",format:"run-s build format:check-fix:*","format:ci":"run-s build format:check:*","format:check-fix:lint":"run-e format:check:lint format:fix:lint","format:check:lint":"cross-env-shell eslint $npm_package_config_eslint","format:fix:lint":"cross-env-shell eslint --fix $npm_package_config_eslint","format:check-fix:prettier":"run-e format:check:prettier format:fix:prettier","format:check:prettier":"cross-env-shell prettier --check $npm_package_config_prettier","format:fix:prettier":"cross-env-shell prettier --write $npm_package_config_prettier","test:dev":"run-s build test:dev:*","test:ci":"run-s build test:ci:*","test:dev:vitest":"LOG=0 vitest --exclude '**/integration/**'","test:ci:vitest":"LOG=0 c8 -r lcovonly -r text -r json vitest --exclude '**/integration/**'","test:integration":"vitest run test/integration/","test:integration:codex":"vitest run test/integration/codex.test.ts","test:integration:claude":"vitest run test/integration/claude.test.ts","test:integration:gemini":"vitest run test/integration/gemini.test.ts","test:integration:create-stage":"vitest run test/integration/create.test.ts",postinstall:"node scripts/postinstall.js"},config:{eslint:'--cache --format=codeframe --max-warnings=0 "{src,scripts,test,.github}/**/*.{js,ts,md,html}"',prettier:'--ignore-path .gitignore --loglevel=warn "{src,scripts,test,.github}/**/*.{js,ts,md,yml,json,html}" "*.{js,ts,yml,json,html}" ".*.{js,ts,yml,json,html}" "!**/package-lock.json" "!package-lock.json" "!src/skills/**/*.md"'},keywords:[],license:"MIT",repository:"netlify/agent-runner-cli",bugs:{url:"https://github.com/netlify/agent-runner-cli/issues"},author:"Netlify Inc.",directories:{test:"test"},devDependencies:{"@commitlint/cli":"^20.0.0","@commitlint/config-conventional":"^20.0.0","@eslint/compat":"^2.0.0","@eslint/js":"^9.35.0","@netlify/eslint-config-node":"^7.0.1","@types/node":"^24.5.0","@typescript-eslint/eslint-plugin":"^8.0.0","@typescript-eslint/parser":"^8.0.0","@vitest/eslint-plugin":"^1.6.6",c8:"^10.0.0","eslint-config-prettier":"^10.1.8","eslint-plugin-n":"^17.0.0",husky:"^9.0.0","patch-package":"^8.0.0",tsup:"^8.5.0",typescript:"^5.0.0","typescript-eslint":"^8.44.0",vitest:"^4.0.16"},dependencies:{"@anthropic-ai/claude-code":"2.1.37","@anthropic-ai/sdk":"0.72.1","@google/gemini-cli":"0.27.3","@netlify/otel":"^5.1.1","@openai/codex":"0.93.0","@opentelemetry/exporter-trace-otlp-grpc":"^0.208.0",execa:"^9.6.1",kaddidlehopper:"^0.1.2",minimist:"^1.2.8",openai:"6.17.0"}};var Hr=Yr(import.meta.url),Wr=Z.dirname(Hr),Kr=Br(import.meta.url),ce=E("shell"),ze=new Set,Jr={preferLocal:!0},x=(e,t,r)=>{let[i,n]=Vr(t,r),s={...Jr,...n},o=qr(e,i,s);Xr(o,s),Zr(o);let a=r?.idleTimeout;return a&&a>0&&zr(o,a),o};var Vr=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},Xr=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(J.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new le).pipe(J.stdout),e.stdout?.pipe(new le).pipe(J.stdout),e.stderr?.pipe(new le).pipe(J.stderr);return}e.stdout?.pipe(J.stdout),e.stderr?.pipe(J.stderr)},Ze=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(J.kill(-e.pid,t),ce.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return ce.error("Error killing process:",r),!1}},Lt=e=>Ze(e,"SIGKILL"),zr=(e,t)=>{let r=null,i=()=>{ce.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),Ze(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ce.log(`Force killing idle process ${e.pid}`),Lt(e))},5e3)},n=()=>{r&&clearTimeout(r),r=setTimeout(i,t)};n(),e.stdout?.on("data",n),e.stderr?.on("data",n);let s=()=>{r&&(clearTimeout(r),r=null)};e.on("exit",s),e.on("error",s)},Zr=e=>{ze.add(e);let t=kt();if(t){let r=t.onTimesUp(()=>{ce.log(`Global timer expired, killing process ${e.pid}`),Ze(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ce.log(`Force killing process ${e.pid} after timeout`),Lt(e))},5e3)});e.on("exit",()=>{ze.delete(e),r()}),e.on("error",()=>{ze.delete(e),r()})}};function Oe(e,t){return!!Q(e,t)}function Q(e,t){if(!J.env.NETLIFY_LOCAL_MODE)try{let n=Kr.resolve($t.name),s=Z.dirname(n);for(;s!==Z.dirname(s);){let o=Z.dirname(s);if(Z.basename(o)==="node_modules"){let a=Z.join(o,".bin",t);if(ke.existsSync(a))return a;break}s=o}}catch(n){console.error("Could not resolve package.json",n)}if(J.env.NODE_PATH){let n=Z.join(J.env.NODE_PATH,".bin",t);if(ke.existsSync(n))return n}let r=Z.join(e,"node_modules",".bin",t);if(ke.existsSync(r))return r;let i=Z.join(Wr,"..","node_modules",".bin",t);if(ke.existsSync(i))return i}var Qr=E("utils"),en=e=>new Promise(t=>{setTimeout(t,e)}),Ft=(e,t=3e3)=>{let r=!1,i=null,n=[],s=null,o=(...a)=>{if(r)return i=a,new Promise(d=>{n.push(d)});r=!0;let c,u=new Promise(d=>{c=d});return s=(async()=>{await Promise.resolve();let d=await e(...a);for(c(d);;){if(await en(t),!i)return r=!1,s=null,d;let p=i,m=n;i=null,n=[],d=await e(...p),m.forEach(y=>{y(d)})}})(),u};return o.flush=async()=>{if((r||i)&&s)return await s,o.flush()},o},ue=(e,t,r=!1)=>{let i=null,n=null,s=null,o=function(...a){n=a,s=this;let c=r&&!i;clearTimeout(i),i=setTimeout(()=>{i=null,r||(e.apply(s,n),n=null,s=null)},t),c&&(e.apply(s,n),n=null,s=null)};return o.cancel=()=>{clearTimeout(i),i=null,n=null,s=null},o.flush=()=>{if(i){clearTimeout(i);let a=n,c=s;i=null,n=null,s=null,e.apply(c,a)}},o},Dt=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(i){t&&(r?.error?r.error("Could not parse JSON",i):Qr.error("Could not parse JSON",i))}},Mt=(e,t)=>{let n=".netlify.app",s="agent-";if(!t)return`${s}${e.slice(0,6)}`;let a=`--${t}${n}`;if(a.length>55)return"";let c=60-a.length;if(c<=0)return"";if(c>=s.length+6){let u=Math.min(c-s.length,e.length);return`${s}${e.slice(0,u)}`}return e.slice(0,c)};var tn=50*1024,Qe=(e,t=tn)=>{if(!e||typeof e!="string"||e.length<=t)return e;let i=e.startsWith("```")?"\n... [truncated]\n```":"... [truncated]";return e.slice(0,t)+i};import{Buffer as Ut}from"buffer";import rn from"path";var Gt=E("repo"),Yt=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{Gt.info("Getting runner diffs");let i=await on(r),{hasChanges:n}=i,{status:s}=i;if(!n)return{hasChanges:!1};if(!t){let _=an(s);await ln(_,r)}Gt.info("Changes after processing"),await tt(r);let o=await rt(s,r);if(await et(o,r),n=await sn(r),!n)return{hasChanges:!1,ignored:o};process.env.NETLIFY_INTERNAL_GIT="1";try{await x("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},c=await x("git",["diff",e.runSha,"HEAD"],a),u=String(c.stdout??"");if(n=!!u,!n)return await jt(r),{hasChanges:!1,ignored:o};let d=await x("git",["diff",e.runSha,"HEAD","--binary"],a),p=String(d.stdout??""),m,y;if(e.sha){let _=await x("git",["diff",e.sha,"HEAD"],a);m=String(_.stdout??"");let I=await x("git",["diff",e.sha,"HEAD","--binary"],a),w=String(I.stdout??"");m!==w&&(y=Ut.from(w).toString("base64"))}await jt(r);let h={hasChanges:!0,diff:u,resultDiff:m,ignored:o};return u!==p&&(h.diffBinary=Ut.from(p).toString("base64")),y&&(h.resultDiffBinary=y),h},jt=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await x("git",["reset","--soft","HEAD~1"],{cwd:e})},et=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await x("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},tt=async(e=process.cwd())=>{let t=await x("git",["status","-s"],{cwd:e});return String(t.stdout??"")},Bt=/.. (.+)?\.log$/,nn=[Bt],on=async(e=process.cwd())=>{let t=await tt(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
9
9
  `).filter(n=>nn.some(o=>o instanceof RegExp?o.test(n):n===o)?!1:n[1]?.trim()!=="")).length!==0,status:t}},sn=async(e=process.cwd())=>{try{return await x("git",["diff","--staged","--quiet"],{cwd:e}),!1}catch{return!0}},Se=async(e=process.cwd())=>{let{stdout:t}=await x("git",["rev-parse","HEAD"],{cwd:e});return String(t??"").trim()},qt=async(e=process.cwd())=>{let{stdout:t}=await x("git",["rev-list","--max-parents=0","HEAD"],{cwd:e});return String(t??"").trim()},rt=async(e,t=process.cwd())=>{e||=await tt(t);let r=[".netlify","node_modules","dist",".next","out",".nuxt",".output",".cache",".turbo",".parcel-cache","coverage",".nyc_output","storybook-static","public/build"],i=[];return e.split(`
10
10
  `).forEach(n=>{r.forEach(o=>{let a=n===`?? ${o}`,c=n.startsWith(`?? ${o}/`)||n.startsWith(`?? ${o}${rn.sep}`);(a||c)&&i.push(`:!${o}`)});let s=n.match(Bt)?.[1];s&&i.push(`:!${s}.log`)}),i},nt=async(e=process.cwd())=>{await x("git",["reset","--hard","HEAD"],{cwd:e})},an=e=>{let t=e.split(`
11
11
  `).reduce((r,i)=>{if(!i)return r;let[n,s,,...o]=i,a=o.join(""),c=n.trim(),u=s.trim();return r[a]?r[a].change=u:r[a]={filePath:a,stage:c,change:u},r},{});return Object.values(t)},ln=async(e,t=process.cwd())=>{let r=e.filter(i=>i.stage&&!i.change).map(i=>i.filePath);r.length!==0&&await x("git",["restore","--staged","--worktree","--pathspec-from-file=-"],{cwd:t,input:r.join(`
package/dist/bin.js CHANGED
@@ -5,7 +5,7 @@ import Et from"process";import To from"minimist";import{createRequire as uo}from
5
5
  ${s}
6
6
  </extracted_error_chunk>`).join(`
7
7
 
8
- `);return i.length>e.length*.8?e:i}import{execSync as kn}from"child_process";import gr from"fs/promises";import On from"path";import Q from"process";import{getTracer as Ln}from"@netlify/otel";import we from"process";var oe=class extends Error{constructor(r,o,n){super(r);this.statusCode=o;this.userMessage=n;this.name="GracefulShutdownError"}},Rt=e=>e instanceof oe;var Ae=we.env.NETLIFY_API_URL,be=we.env.NETLIFY_API_TOKEN,H=_("api"),Ce=()=>we.env.NETLIFY_LOCAL_MODE==="true",Te=async(e,t={})=>{if(!Ae||!be)throw new Error("No API URL or token");let r=new URL(e,Ae),o={...t,headers:{...t.headers,Authorization:`Bearer ${be}`}};we.env.AGENT_RUNNERS_DEBUG==="true"&&(o.headers["x-nf-debug-logging"]="true"),t.json&&(o.headers||={},o.headers["Content-Type"]="application/json",o.body=JSON.stringify(t.json));let n=await fetch(r,o),i=n.ok&&n.status<=299;if(we.env.AGENT_RUNNERS_DEBUG==="true")H.log(`Response headers for ${r}:`),n.headers.forEach((a,c)=>{H.log(` ${c}: ${a}`)});else{let a=n.headers.get("x-request-id")||n.headers.get("x-nf-request-id");H.log(`Request ID for ${r}: ${a||"N/A"}`)}if(i||H.error(`Got status ${n.status} for request ${r}`),t.raw){if(!i)throw new Error(`API request failed: ${n.status} ${n.statusText}`);return n}let s=await(n.headers.get("content-type")?.includes("application/json")?n.json():n.text());if(!i){let a=typeof s=="string"?s:JSON.stringify(s);throw n.status===404?new oe(`API request failed: 404 - ${a}`,404,"The site associated with this agent run no longer exists."):n.status===403&&t.gracefulOn403?new oe(`API request failed: 403 - ${a}`,403,"Credit limit reached. Please add more credits to continue using Agent Runners."):new Error(`API request failed: ${n.status} - ${a}`)}return s},St=e=>{H.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Ae=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(be=e.constants.NETLIFY_API_TOKEN)},vt=()=>({apiUrl:Ae,token:be}),xe=async(e,t)=>Ce()?(H.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):Te(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),D=async(e,t,r)=>Ce()?(H.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):Te(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var At=async(e,t)=>Ce()?(H.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):Te(`/api/v1/agent_runners/${e}/sessions/${t}`),bt=(e,t,r)=>Te(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn403:!0}),Ct=async(e,t)=>Ce()?(H.log("Mock API: getDiffUploadUrls called",{runnerId:e,sessionId:t}),{result:{upload_url:"https://s3.mock.com/mock-upload-url-result",s3_key:"mock-s3-key-result"},cumulative:{upload_url:"https://s3.mock.com/mock-upload-url-cumulative",s3_key:"mock-s3-key-cumulative"}}):Te(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),qe=async(e,t)=>{H.log(`Uploading diff to S3: ${e.substring(0,50)}...`);let r=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!r.ok)throw new Error(`S3 upload failed with status ${r.status}`);return r};var se=_("ai_gateway"),We=null;var Nt=async()=>{if(We)return We;se.log("Fetching available AI gateway providers");let e=await fetch(`${vt().apiUrl}/api/v1/ai-gateway/providers`);if(!e.ok)throw new Error(`Failed to fetch AI gateway providers: ${e.statusText}`);let t=await e.json();return We=t,se.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},jr=async(e,t)=>{let o=(await Nt()).providers[e];if(!o)return se.log(`Provider '${e}' not found`),!1;let n=o.models.includes(t);return se.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},Pt=async({netlify:e,config:t})=>{let r,o,n,i,s=e.constants?.SITE_ID;if(!s)throw new Error("No site id");let a=async()=>{clearTimeout(n),se.log("Requesting AI gateway information");let c=await bt(s,t.id,t.sessionId);if({token:r,url:i}=c,o=c.expires_at?c.expires_at*1e3:void 0,se.log("Got AI gateway information",{token:!!r,expiresAt:o,url:i}),o){let u=o-Date.now()-6e4;u>0&&(n=setTimeout(()=>{a()},u))}};return await Promise.all([a(),Nt()]),{get url(){return i},get token(){return r},isModelAvailableForProvider:jr}};import W from"process";import X from"path";import Ne from"fs";import{fileURLToPath as Vr}from"url";import{createRequire as Jr}from"module";import{execa as Xr,execaCommand as Qo}from"execa";import{Transform as Yr}from"stream";var Br=new Set(["NODE_ENV","PATH","HOME","USER","USERNAME","SHELL","PWD","OLDPWD","TMPDIR","TMP","TEMP","LANG","TERM","EDITOR","PAGER","OS","PROCESSOR_ARCHITECTURE","PROCESSOR_IDENTIFIER","SYSTEMROOT","WINDIR","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","APPDATA","LOCALAPPDATA","NODE_OPTIONS","NODE_PATH","NODE_DEBUG","NODE_NO_WARNINGS","npm_config_registry","npm_config_cache","npm_execpath","npm_node_execpath","CI","GITHUB_ACTIONS","GITHUB_WORKSPACE","GITHUB_REPOSITORY","GITHUB_REF","BUILDKITE","BUILDKITE_BRANCH","BUILDKITE_COMMIT","BUILDKITE_BUILD_NUMBER","JENKINS_URL","TRAVIS","CIRCLECI","DISPLAY","COLORTERM","TERM_PROGRAM","TERM_PROGRAM_VERSION","COLUMNS","LINES","HISTSIZE","HISTFILE","NETLIFY_AGENT_RUNNER_ID","NETLIFY_AGENT_RUNNER_SESSION_ID","NETLIFY_AGENT_RUNNER_PROMPT","NETLIFY_AGENT_RUNNER_AGENT","NETLIFY_AGENT_RUNNER_MODEL","NETLIFY_AGENT_RUNNER_CONTEXT","NETLIFY_AGENT_RUNNER_HAS_REPO","NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED","NETLIFY_AGENT_RUNNER_SHA","NETLIFY_TEAM_TYPE","AGENT_RUNNERS_DEBUG","NETLIFY_TEAM_ID","NETLIFY_AGENT_RUNNER_USER_ID","SITE_NAME"]),Hr=new Set(["true","false","undefined","null","deploy","project","claude","gemini","codex",""]);function qr(){return Object.entries(process.env).filter(([e,t])=>!(!t||Br.has(e)||Hr.has(t)||!isNaN(Number(t))||t.length<5)).map(([,e])=>e).filter(Boolean)}function J(e){if(typeof e!="string")return e;let t=qr();if(t.length===0)return e;let r=e;return t.forEach(o=>{let n=new RegExp(Wr(o),"g");r=r.replace(n,"******")}),r}function Wr(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ie=class extends Yr{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,o){let n=t.toString(),i=J(n);o(null,i)}};function kt(){if(!(process.env.NETLIFY_MASK_LOGS!=="false"))return;let t=process.stdout.write.bind(process.stdout),r=process.stderr.write.bind(process.stderr);process.stdout.write=function(o,n,i){let s=typeof o=="string"?J(o):o;return typeof n=="function"?t(s,n):t(s,n,i)},process.stderr.write=function(o,n,i){let s=typeof o=="string"?J(o):o;return typeof n=="function"?r(s,n):r(s,n,i)}}var Ie=null,Ot=e=>(Ie&&Ie.destroy(),Ie=new z({totalAllowedTime:e}),Ie),Lt=()=>Ie;var z=class{constructor({totalAllowedTime:t}){this.withStageTimer=async(t,r,o)=>{if(this.isTimeExpired())throw new Error(`${t} stage did not complete in the allowed time. Time has already expired.`);let n=this.onTimesUp(()=>{throw new Error(`${t} stage did not complete in the allowed time.`)}),i=null,s=null;o!==void 0&&(s=new Promise((a,c)=>{i=setTimeout(()=>{c(new Error(`${t} stage exceeded its maximum duration of ${o}ms`))},o)}));try{return s?await Promise.race([r(),s]):await r()}finally{n(),i&&clearTimeout(i)}};this.startTime=Date.now(),this.totalAllowedTime=t,this.globalTimeoutId=null,this.subscribers=[],this.hasTimedOut=!1,this.setupGlobalTimeout()}getElapsedTime(){return Date.now()-this.startTime}getRemainingTime(){let t=this.getElapsedTime(),r=this.totalAllowedTime-t;return Math.max(0,r)}isTimeExpired(){return this.getRemainingTime()===0||this.hasTimedOut}setupGlobalTimeout(){this.globalTimeoutId&&clearTimeout(this.globalTimeoutId),this.globalTimeoutId=setTimeout(()=>{this.notifyTimeUp()},this.totalAllowedTime)}notifyTimeUp(){this.hasTimedOut=!0;for(let t=this.subscribers.length-1;t>=0;t--)try{this.subscribers[t]()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}}onTimesUp(t){if(this.subscribers.push(t),this.hasTimedOut)try{t()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}return()=>{let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}}off(t){let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}clearSubscribers(){this.subscribers.length=0}getSubscriberCount(){return this.subscribers.length}destroy(){this.globalTimeoutId&&(clearTimeout(this.globalTimeoutId),this.globalTimeoutId=null),this.clearSubscribers()}static{this.timeUnits={seconds:t=>t*1e3,minutes:t=>t*60*1e3,hours:t=>t*60*60*1e3}}};var $t="netlify-agent-runner-context.md",Ke="task-history",q=".netlify",ee="results.md",Ve="assets",Je="other",Xe="personal";var ze="enterprise",Ze="free",Ft=[Xe,"pro",ze,Ze],Dt=["normal","redeploy","create","ask","dtn-prod-iteration","rebase"],Mt="The production deploy has changed since you started working. Please reapply the changes to the current codebase, resolving any conflicts that arise. Use the attached diff file if present, otherwise review the previous session context to reproduce the changes.",te=1800*1e3;var Ut={name:"@netlify/agent-runner-cli",type:"module",version:"1.69.3",description:"CLI tool for running Netlify agents",main:"./dist/index.js",types:"./dist/index.d.ts",exports:"./dist/index.js",bin:{"agent-runner-cli":"./dist/bin.js","agent-runner-cli-local":"./dist/bin-local.js"},files:["dist/**/*.js","dist/**/*.d.ts","dist/skills/**","patches","scripts"],scripts:{build:"tsup",dev:"tsup --watch",prepare:"husky install node_modules/@netlify/eslint-config-node/.husky/",prepublishOnly:"npm ci && npm test",prepack:"npm run build",test:"run-s build format test:dev",format:"run-s build format:check-fix:*","format:ci":"run-s build format:check:*","format:check-fix:lint":"run-e format:check:lint format:fix:lint","format:check:lint":"cross-env-shell eslint $npm_package_config_eslint","format:fix:lint":"cross-env-shell eslint --fix $npm_package_config_eslint","format:check-fix:prettier":"run-e format:check:prettier format:fix:prettier","format:check:prettier":"cross-env-shell prettier --check $npm_package_config_prettier","format:fix:prettier":"cross-env-shell prettier --write $npm_package_config_prettier","test:dev":"run-s build test:dev:*","test:ci":"run-s build test:ci:*","test:dev:vitest":"LOG=0 vitest --exclude '**/integration/**'","test:ci:vitest":"LOG=0 c8 -r lcovonly -r text -r json vitest --exclude '**/integration/**'","test:integration":"vitest run test/integration/","test:integration:codex":"vitest run test/integration/codex.test.ts","test:integration:claude":"vitest run test/integration/claude.test.ts","test:integration:gemini":"vitest run test/integration/gemini.test.ts","test:integration:create-stage":"vitest run test/integration/create.test.ts",postinstall:"node scripts/postinstall.js"},config:{eslint:'--cache --format=codeframe --max-warnings=0 "{src,scripts,test,.github}/**/*.{js,ts,md,html}"',prettier:'--ignore-path .gitignore --loglevel=warn "{src,scripts,test,.github}/**/*.{js,ts,md,yml,json,html}" "*.{js,ts,yml,json,html}" ".*.{js,ts,yml,json,html}" "!**/package-lock.json" "!package-lock.json" "!src/skills/**/*.md"'},keywords:[],license:"MIT",repository:"netlify/agent-runner-cli",bugs:{url:"https://github.com/netlify/agent-runner-cli/issues"},author:"Netlify Inc.",directories:{test:"test"},devDependencies:{"@commitlint/cli":"^20.0.0","@commitlint/config-conventional":"^20.0.0","@eslint/compat":"^2.0.0","@eslint/js":"^9.35.0","@netlify/eslint-config-node":"^7.0.1","@types/node":"^24.5.0","@typescript-eslint/eslint-plugin":"^8.0.0","@typescript-eslint/parser":"^8.0.0","@vitest/eslint-plugin":"^1.6.6",c8:"^10.0.0","eslint-config-prettier":"^10.1.8","eslint-plugin-n":"^17.0.0",husky:"^9.0.0","patch-package":"^8.0.0",tsup:"^8.5.0",typescript:"^5.0.0","typescript-eslint":"^8.44.0",vitest:"^4.0.16"},dependencies:{"@anthropic-ai/claude-code":"2.1.37","@anthropic-ai/sdk":"0.72.1","@google/gemini-cli":"0.27.3","@netlify/otel":"^5.1.1","@openai/codex":"0.93.0","@opentelemetry/exporter-trace-otlp-grpc":"^0.208.0",execa:"^9.6.1",kaddidlehopper:"^0.1.2",minimist:"^1.2.8",openai:"6.17.0"}};var zr=Vr(import.meta.url),Zr=X.dirname(zr),Qr=Jr(import.meta.url),ae=_("shell"),Qe=new Set,en={preferLocal:!0},b=(e,t,r)=>{let[o,n]=tn(t,r),i={...en,...n},s=Xr(e,o,i);rn(s,i),on(s);let a=r?.idleTimeout;return a&&a>0&&nn(s,a),s};var tn=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},rn=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(W.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new ie).pipe(W.stdout),e.stdout?.pipe(new ie).pipe(W.stdout),e.stderr?.pipe(new ie).pipe(W.stderr);return}e.stdout?.pipe(W.stdout),e.stderr?.pipe(W.stderr)},et=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(W.kill(-e.pid,t),ae.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return ae.error("Error killing process:",r),!1}},Gt=e=>et(e,"SIGKILL"),nn=(e,t)=>{let r=null,o=()=>{ae.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),et(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ae.log(`Force killing idle process ${e.pid}`),Gt(e))},5e3)},n=()=>{r&&clearTimeout(r),r=setTimeout(o,t)};n(),e.stdout?.on("data",n),e.stderr?.on("data",n);let i=()=>{r&&(clearTimeout(r),r=null)};e.on("exit",i),e.on("error",i)},on=e=>{Qe.add(e);let t=Lt();if(t){let r=t.onTimesUp(()=>{ae.log(`Global timer expired, killing process ${e.pid}`),et(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ae.log(`Force killing process ${e.pid} after timeout`),Gt(e))},5e3)});e.on("exit",()=>{Qe.delete(e),r()}),e.on("error",()=>{Qe.delete(e),r()})}};function Z(e,t){if(!W.env.NETLIFY_LOCAL_MODE)try{let n=Qr.resolve(Ut.name),i=X.dirname(n);for(;i!==X.dirname(i);){let s=X.dirname(i);if(X.basename(s)==="node_modules"){let a=X.join(s,".bin",t);if(Ne.existsSync(a))return a;break}i=s}}catch(n){console.error("Could not resolve package.json",n)}if(W.env.NODE_PATH){let n=X.join(W.env.NODE_PATH,".bin",t);if(Ne.existsSync(n))return n}let r=X.join(e,"node_modules",".bin",t);if(Ne.existsSync(r))return r;let o=X.join(Zr,"..","node_modules",".bin",t);if(Ne.existsSync(o))return o}var jt=_("utils"),sn=e=>new Promise(t=>{setTimeout(t,e)}),Yt=(e,t=3e3)=>{let r=!1,o=null,n=[],i=null,s=(...a)=>{if(r)return o=a,new Promise(d=>{n.push(d)});r=!0;let c,u=new Promise(d=>{c=d});return i=(async()=>{await Promise.resolve();let d=await e(...a);for(c(d);;){if(await sn(t),!o)return r=!1,i=null,d;let p=o,m=n;o=null,n=[],d=await e(...p),m.forEach(y=>{y(d)})}})(),u};return s.flush=async()=>{if((r||o)&&i)return await i,s.flush()},s},le=(e,t,r=!1)=>{let o=null,n=null,i=null,s=function(...a){n=a,i=this;let c=r&&!o;clearTimeout(o),o=setTimeout(()=>{o=null,r||(e.apply(i,n),n=null,i=null)},t),c&&(e.apply(i,n),n=null,i=null)};return s.cancel=()=>{clearTimeout(o),o=null,n=null,i=null},s.flush=()=>{if(o){clearTimeout(o);let a=n,c=i;o=null,n=null,i=null,e.apply(c,a)}},s},Pe=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(o){t&&(r?.error?r.error("Could not parse JSON",o):jt.error("Could not parse JSON",o))}},Bt=(e,t)=>{let n=".netlify.app",i="agent-";if(!t)return`${i}${e.slice(0,6)}`;let a=`--${t}${n}`;if(a.length>55)return"";let c=60-a.length;if(c<=0)return"";if(c>=i.length+6){let u=Math.min(c-i.length,e.length);return`${i}${e.slice(0,u)}`}return e.slice(0,c)},an=e=>!e||typeof e!="object"||Array.isArray(e)||Object.keys(e).length===0?!1:!!Ft.some(t=>t in e),Ht=()=>{let e={},t={codex:process.env.NETLIFY_FF_AGENT_RUNNER_CODEX_VERSION,claude:process.env.NETLIFY_FF_AGENT_RUNNER_CLAUDE_VERSION,gemini:process.env.NETLIFY_FF_AGENT_RUNNER_GEMINI_VERSION};return Object.entries(t).forEach(([r,o])=>{if(o){let n=`NETLIFY_FF_AGENT_RUNNER_${r.toUpperCase()}_VERSION`;try{let i=JSON.parse(o);an(i)&&(e[r]=i)}catch(i){let a=i instanceof SyntaxError?"Invalid JSON":i.message;jt.error(`Could not parse ${r} model version override from ${n}: ${a}`)}}}),e},ln=50*1024,tt=(e,t=ln)=>{if(!e||typeof e!="string"||e.length<=t)return e;let o=e.startsWith("```")?"\n... [truncated]\n```":"... [truncated]";return e.slice(0,t)+o};import{Buffer as qt}from"buffer";import cn from"path";var Wt=_("repo"),Vt=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{Wt.info("Getting runner diffs");let o=await pn(r),{hasChanges:n}=o,{status:i}=o;if(!n)return{hasChanges:!1};if(!t){let w=mn(i);await fn(w,r)}Wt.info("Changes after processing"),await nt(r);let s=await st(i,r);if(await rt(s,r),n=await dn(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await b("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},c=await b("git",["diff",e.runSha,"HEAD"],a),u=String(c.stdout??"");if(n=!!u,!n)return await Kt(r),{hasChanges:!1,ignored:s};let d=await b("git",["diff",e.runSha,"HEAD","--binary"],a),p=String(d.stdout??""),m,y;if(e.sha){let w=await b("git",["diff",e.sha,"HEAD"],a);m=String(w.stdout??"");let T=await b("git",["diff",e.sha,"HEAD","--binary"],a),E=String(T.stdout??"");m!==E&&(y=qt.from(E).toString("base64"))}await Kt(r);let h={hasChanges:!0,diff:u,resultDiff:m,ignored:s};return u!==p&&(h.diffBinary=qt.from(p).toString("base64")),y&&(h.resultDiffBinary=y),h},Kt=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await b("git",["reset","--soft","HEAD~1"],{cwd:e})},rt=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await b("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},nt=async(e=process.cwd())=>{let t=await b("git",["status","-s"],{cwd:e});return String(t.stdout??"")},Jt=/.. (.+)?\.log$/,un=[Jt],pn=async(e=process.cwd())=>{let t=await nt(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
8
+ `);return i.length>e.length*.8?e:i}import{execSync as kn}from"child_process";import gr from"fs/promises";import On from"path";import Q from"process";import{getTracer as Ln}from"@netlify/otel";import we from"process";var oe=class extends Error{constructor(r,o,n){super(r);this.statusCode=o;this.userMessage=n;this.name="GracefulShutdownError"}},Rt=e=>e instanceof oe;var Ae=we.env.NETLIFY_API_URL,be=we.env.NETLIFY_API_TOKEN,H=_("api"),Ce=()=>we.env.NETLIFY_LOCAL_MODE==="true",Te=async(e,t={})=>{if(!Ae||!be)throw new Error("No API URL or token");let r=new URL(e,Ae),o={...t,headers:{...t.headers,Authorization:`Bearer ${be}`}};we.env.AGENT_RUNNERS_DEBUG==="true"&&(o.headers["x-nf-debug-logging"]="true"),t.json&&(o.headers||={},o.headers["Content-Type"]="application/json",o.body=JSON.stringify(t.json));let n=await fetch(r,o),i=n.ok&&n.status<=299;if(we.env.AGENT_RUNNERS_DEBUG==="true")H.log(`Response headers for ${r}:`),n.headers.forEach((a,c)=>{H.log(` ${c}: ${a}`)});else{let a=n.headers.get("x-request-id")||n.headers.get("x-nf-request-id");H.log(`Request ID for ${r}: ${a||"N/A"}`)}if(i||H.error(`Got status ${n.status} for request ${r}`),t.raw){if(!i)throw new Error(`API request failed: ${n.status} ${n.statusText}`);return n}let s=await(n.headers.get("content-type")?.includes("application/json")?n.json():n.text());if(!i){let a=typeof s=="string"?s:JSON.stringify(s);throw n.status===404?new oe(`API request failed: 404 - ${a}`,404,"The site associated with this agent run no longer exists."):n.status===403&&t.gracefulOn403?new oe(`API request failed: 403 - ${a}`,403,"Credit limit reached. Please add more credits to continue using Agent Runners."):new Error(`API request failed: ${n.status} - ${a}`)}return s},St=e=>{H.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Ae=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(be=e.constants.NETLIFY_API_TOKEN)},vt=()=>({apiUrl:Ae,token:be}),xe=async(e,t)=>Ce()?(H.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):Te(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),D=async(e,t,r)=>Ce()?(H.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):Te(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var At=async(e,t)=>Ce()?(H.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):Te(`/api/v1/agent_runners/${e}/sessions/${t}`),bt=(e,t,r)=>Te(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn403:!0}),Ct=async(e,t)=>Ce()?(H.log("Mock API: getDiffUploadUrls called",{runnerId:e,sessionId:t}),{result:{upload_url:"https://s3.mock.com/mock-upload-url-result",s3_key:"mock-s3-key-result"},cumulative:{upload_url:"https://s3.mock.com/mock-upload-url-cumulative",s3_key:"mock-s3-key-cumulative"}}):Te(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),qe=async(e,t)=>{H.log(`Uploading diff to S3: ${e.substring(0,50)}...`);let r=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!r.ok)throw new Error(`S3 upload failed with status ${r.status}`);return r};var se=_("ai_gateway"),We=null;var Nt=async()=>{if(We)return We;se.log("Fetching available AI gateway providers");let e=await fetch(`${vt().apiUrl}/api/v1/ai-gateway/providers`);if(!e.ok)throw new Error(`Failed to fetch AI gateway providers: ${e.statusText}`);let t=await e.json();return We=t,se.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},jr=async(e,t)=>{let o=(await Nt()).providers[e];if(!o)return se.log(`Provider '${e}' not found`),!1;let n=o.models.includes(t);return se.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},Pt=async({netlify:e,config:t})=>{let r,o,n,i,s=e.constants?.SITE_ID;if(!s)throw new Error("No site id");let a=async()=>{clearTimeout(n),se.log("Requesting AI gateway information");let c=await bt(s,t.id,t.sessionId);if({token:r,url:i}=c,o=c.expires_at?c.expires_at*1e3:void 0,se.log("Got AI gateway information",{token:!!r,expiresAt:o,url:i}),o){let u=o-Date.now()-6e4;u>0&&(n=setTimeout(()=>{a()},u))}};return await Promise.all([a(),Nt()]),{get url(){return i},get token(){return r},isModelAvailableForProvider:jr}};import W from"process";import X from"path";import Ne from"fs";import{fileURLToPath as Vr}from"url";import{createRequire as Jr}from"module";import{execa as Xr,execaCommand as Qo}from"execa";import{Transform as Yr}from"stream";var Br=new Set(["NODE_ENV","PATH","HOME","USER","USERNAME","SHELL","PWD","OLDPWD","TMPDIR","TMP","TEMP","LANG","TERM","EDITOR","PAGER","OS","PROCESSOR_ARCHITECTURE","PROCESSOR_IDENTIFIER","SYSTEMROOT","WINDIR","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","APPDATA","LOCALAPPDATA","NODE_OPTIONS","NODE_PATH","NODE_DEBUG","NODE_NO_WARNINGS","npm_config_registry","npm_config_cache","npm_execpath","npm_node_execpath","CI","GITHUB_ACTIONS","GITHUB_WORKSPACE","GITHUB_REPOSITORY","GITHUB_REF","BUILDKITE","BUILDKITE_BRANCH","BUILDKITE_COMMIT","BUILDKITE_BUILD_NUMBER","JENKINS_URL","TRAVIS","CIRCLECI","DISPLAY","COLORTERM","TERM_PROGRAM","TERM_PROGRAM_VERSION","COLUMNS","LINES","HISTSIZE","HISTFILE","NETLIFY_AGENT_RUNNER_ID","NETLIFY_AGENT_RUNNER_SESSION_ID","NETLIFY_AGENT_RUNNER_PROMPT","NETLIFY_AGENT_RUNNER_AGENT","NETLIFY_AGENT_RUNNER_MODEL","NETLIFY_AGENT_RUNNER_CONTEXT","NETLIFY_AGENT_RUNNER_HAS_REPO","NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED","NETLIFY_AGENT_RUNNER_SHA","NETLIFY_TEAM_TYPE","AGENT_RUNNERS_DEBUG","NETLIFY_TEAM_ID","NETLIFY_AGENT_RUNNER_USER_ID","SITE_NAME"]),Hr=new Set(["true","false","undefined","null","deploy","project","claude","gemini","codex",""]);function qr(){return Object.entries(process.env).filter(([e,t])=>!(!t||Br.has(e)||Hr.has(t)||!isNaN(Number(t))||t.length<5)).map(([,e])=>e).filter(Boolean)}function J(e){if(typeof e!="string")return e;let t=qr();if(t.length===0)return e;let r=e;return t.forEach(o=>{let n=new RegExp(Wr(o),"g");r=r.replace(n,"******")}),r}function Wr(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ie=class extends Yr{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,o){let n=t.toString(),i=J(n);o(null,i)}};function kt(){if(!(process.env.NETLIFY_MASK_LOGS!=="false"))return;let t=process.stdout.write.bind(process.stdout),r=process.stderr.write.bind(process.stderr);process.stdout.write=function(o,n,i){let s=typeof o=="string"?J(o):o;return typeof n=="function"?t(s,n):t(s,n,i)},process.stderr.write=function(o,n,i){let s=typeof o=="string"?J(o):o;return typeof n=="function"?r(s,n):r(s,n,i)}}var Ie=null,Ot=e=>(Ie&&Ie.destroy(),Ie=new z({totalAllowedTime:e}),Ie),Lt=()=>Ie;var z=class{constructor({totalAllowedTime:t}){this.withStageTimer=async(t,r,o)=>{if(this.isTimeExpired())throw new Error(`${t} stage did not complete in the allowed time. Time has already expired.`);let n=this.onTimesUp(()=>{throw new Error(`${t} stage did not complete in the allowed time.`)}),i=null,s=null;o!==void 0&&(s=new Promise((a,c)=>{i=setTimeout(()=>{c(new Error(`${t} stage exceeded its maximum duration of ${o}ms`))},o)}));try{return s?await Promise.race([r(),s]):await r()}finally{n(),i&&clearTimeout(i)}};this.startTime=Date.now(),this.totalAllowedTime=t,this.globalTimeoutId=null,this.subscribers=[],this.hasTimedOut=!1,this.setupGlobalTimeout()}getElapsedTime(){return Date.now()-this.startTime}getRemainingTime(){let t=this.getElapsedTime(),r=this.totalAllowedTime-t;return Math.max(0,r)}isTimeExpired(){return this.getRemainingTime()===0||this.hasTimedOut}setupGlobalTimeout(){this.globalTimeoutId&&clearTimeout(this.globalTimeoutId),this.globalTimeoutId=setTimeout(()=>{this.notifyTimeUp()},this.totalAllowedTime)}notifyTimeUp(){this.hasTimedOut=!0;for(let t=this.subscribers.length-1;t>=0;t--)try{this.subscribers[t]()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}}onTimesUp(t){if(this.subscribers.push(t),this.hasTimedOut)try{t()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}return()=>{let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}}off(t){let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}clearSubscribers(){this.subscribers.length=0}getSubscriberCount(){return this.subscribers.length}destroy(){this.globalTimeoutId&&(clearTimeout(this.globalTimeoutId),this.globalTimeoutId=null),this.clearSubscribers()}static{this.timeUnits={seconds:t=>t*1e3,minutes:t=>t*60*1e3,hours:t=>t*60*60*1e3}}};var $t="netlify-agent-runner-context.md",Ke="task-history",q=".netlify",ee="results.md",Ve="assets",Je="other",Xe="personal";var ze="enterprise",Ze="free",Ft=[Xe,"pro",ze,Ze],Dt=["normal","redeploy","create","ask","dtn-prod-iteration","rebase"],Mt="The production deploy has changed since you started working. Please reapply the changes to the current codebase, resolving any conflicts that arise. Use the attached diff file if present, otherwise review the previous session context to reproduce the changes.",te=1800*1e3;var Ut={name:"@netlify/agent-runner-cli",type:"module",version:"1.70.0",description:"CLI tool for running Netlify agents",main:"./dist/index.js",types:"./dist/index.d.ts",exports:"./dist/index.js",bin:{"agent-runner-cli":"./dist/bin.js","agent-runner-cli-local":"./dist/bin-local.js"},files:["dist/**/*.js","dist/**/*.d.ts","dist/skills/**","patches","scripts"],scripts:{build:"tsup",dev:"tsup --watch",prepare:"husky install node_modules/@netlify/eslint-config-node/.husky/",prepublishOnly:"npm ci && npm test",prepack:"npm run build",test:"run-s build format test:dev",format:"run-s build format:check-fix:*","format:ci":"run-s build format:check:*","format:check-fix:lint":"run-e format:check:lint format:fix:lint","format:check:lint":"cross-env-shell eslint $npm_package_config_eslint","format:fix:lint":"cross-env-shell eslint --fix $npm_package_config_eslint","format:check-fix:prettier":"run-e format:check:prettier format:fix:prettier","format:check:prettier":"cross-env-shell prettier --check $npm_package_config_prettier","format:fix:prettier":"cross-env-shell prettier --write $npm_package_config_prettier","test:dev":"run-s build test:dev:*","test:ci":"run-s build test:ci:*","test:dev:vitest":"LOG=0 vitest --exclude '**/integration/**'","test:ci:vitest":"LOG=0 c8 -r lcovonly -r text -r json vitest --exclude '**/integration/**'","test:integration":"vitest run test/integration/","test:integration:codex":"vitest run test/integration/codex.test.ts","test:integration:claude":"vitest run test/integration/claude.test.ts","test:integration:gemini":"vitest run test/integration/gemini.test.ts","test:integration:create-stage":"vitest run test/integration/create.test.ts",postinstall:"node scripts/postinstall.js"},config:{eslint:'--cache --format=codeframe --max-warnings=0 "{src,scripts,test,.github}/**/*.{js,ts,md,html}"',prettier:'--ignore-path .gitignore --loglevel=warn "{src,scripts,test,.github}/**/*.{js,ts,md,yml,json,html}" "*.{js,ts,yml,json,html}" ".*.{js,ts,yml,json,html}" "!**/package-lock.json" "!package-lock.json" "!src/skills/**/*.md"'},keywords:[],license:"MIT",repository:"netlify/agent-runner-cli",bugs:{url:"https://github.com/netlify/agent-runner-cli/issues"},author:"Netlify Inc.",directories:{test:"test"},devDependencies:{"@commitlint/cli":"^20.0.0","@commitlint/config-conventional":"^20.0.0","@eslint/compat":"^2.0.0","@eslint/js":"^9.35.0","@netlify/eslint-config-node":"^7.0.1","@types/node":"^24.5.0","@typescript-eslint/eslint-plugin":"^8.0.0","@typescript-eslint/parser":"^8.0.0","@vitest/eslint-plugin":"^1.6.6",c8:"^10.0.0","eslint-config-prettier":"^10.1.8","eslint-plugin-n":"^17.0.0",husky:"^9.0.0","patch-package":"^8.0.0",tsup:"^8.5.0",typescript:"^5.0.0","typescript-eslint":"^8.44.0",vitest:"^4.0.16"},dependencies:{"@anthropic-ai/claude-code":"2.1.37","@anthropic-ai/sdk":"0.72.1","@google/gemini-cli":"0.27.3","@netlify/otel":"^5.1.1","@openai/codex":"0.93.0","@opentelemetry/exporter-trace-otlp-grpc":"^0.208.0",execa:"^9.6.1",kaddidlehopper:"^0.1.2",minimist:"^1.2.8",openai:"6.17.0"}};var zr=Vr(import.meta.url),Zr=X.dirname(zr),Qr=Jr(import.meta.url),ae=_("shell"),Qe=new Set,en={preferLocal:!0},b=(e,t,r)=>{let[o,n]=tn(t,r),i={...en,...n},s=Xr(e,o,i);rn(s,i),on(s);let a=r?.idleTimeout;return a&&a>0&&nn(s,a),s};var tn=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},rn=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(W.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new ie).pipe(W.stdout),e.stdout?.pipe(new ie).pipe(W.stdout),e.stderr?.pipe(new ie).pipe(W.stderr);return}e.stdout?.pipe(W.stdout),e.stderr?.pipe(W.stderr)},et=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(W.kill(-e.pid,t),ae.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return ae.error("Error killing process:",r),!1}},Gt=e=>et(e,"SIGKILL"),nn=(e,t)=>{let r=null,o=()=>{ae.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),et(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ae.log(`Force killing idle process ${e.pid}`),Gt(e))},5e3)},n=()=>{r&&clearTimeout(r),r=setTimeout(o,t)};n(),e.stdout?.on("data",n),e.stderr?.on("data",n);let i=()=>{r&&(clearTimeout(r),r=null)};e.on("exit",i),e.on("error",i)},on=e=>{Qe.add(e);let t=Lt();if(t){let r=t.onTimesUp(()=>{ae.log(`Global timer expired, killing process ${e.pid}`),et(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ae.log(`Force killing process ${e.pid} after timeout`),Gt(e))},5e3)});e.on("exit",()=>{Qe.delete(e),r()}),e.on("error",()=>{Qe.delete(e),r()})}};function Z(e,t){if(!W.env.NETLIFY_LOCAL_MODE)try{let n=Qr.resolve(Ut.name),i=X.dirname(n);for(;i!==X.dirname(i);){let s=X.dirname(i);if(X.basename(s)==="node_modules"){let a=X.join(s,".bin",t);if(Ne.existsSync(a))return a;break}i=s}}catch(n){console.error("Could not resolve package.json",n)}if(W.env.NODE_PATH){let n=X.join(W.env.NODE_PATH,".bin",t);if(Ne.existsSync(n))return n}let r=X.join(e,"node_modules",".bin",t);if(Ne.existsSync(r))return r;let o=X.join(Zr,"..","node_modules",".bin",t);if(Ne.existsSync(o))return o}var jt=_("utils"),sn=e=>new Promise(t=>{setTimeout(t,e)}),Yt=(e,t=3e3)=>{let r=!1,o=null,n=[],i=null,s=(...a)=>{if(r)return o=a,new Promise(d=>{n.push(d)});r=!0;let c,u=new Promise(d=>{c=d});return i=(async()=>{await Promise.resolve();let d=await e(...a);for(c(d);;){if(await sn(t),!o)return r=!1,i=null,d;let p=o,m=n;o=null,n=[],d=await e(...p),m.forEach(y=>{y(d)})}})(),u};return s.flush=async()=>{if((r||o)&&i)return await i,s.flush()},s},le=(e,t,r=!1)=>{let o=null,n=null,i=null,s=function(...a){n=a,i=this;let c=r&&!o;clearTimeout(o),o=setTimeout(()=>{o=null,r||(e.apply(i,n),n=null,i=null)},t),c&&(e.apply(i,n),n=null,i=null)};return s.cancel=()=>{clearTimeout(o),o=null,n=null,i=null},s.flush=()=>{if(o){clearTimeout(o);let a=n,c=i;o=null,n=null,i=null,e.apply(c,a)}},s},Pe=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(o){t&&(r?.error?r.error("Could not parse JSON",o):jt.error("Could not parse JSON",o))}},Bt=(e,t)=>{let n=".netlify.app",i="agent-";if(!t)return`${i}${e.slice(0,6)}`;let a=`--${t}${n}`;if(a.length>55)return"";let c=60-a.length;if(c<=0)return"";if(c>=i.length+6){let u=Math.min(c-i.length,e.length);return`${i}${e.slice(0,u)}`}return e.slice(0,c)},an=e=>!e||typeof e!="object"||Array.isArray(e)||Object.keys(e).length===0?!1:!!Ft.some(t=>t in e),Ht=()=>{let e={},t={codex:process.env.NETLIFY_FF_AGENT_RUNNER_CODEX_VERSION,claude:process.env.NETLIFY_FF_AGENT_RUNNER_CLAUDE_VERSION,gemini:process.env.NETLIFY_FF_AGENT_RUNNER_GEMINI_VERSION};return Object.entries(t).forEach(([r,o])=>{if(o){let n=`NETLIFY_FF_AGENT_RUNNER_${r.toUpperCase()}_VERSION`;try{let i=JSON.parse(o);an(i)&&(e[r]=i)}catch(i){let a=i instanceof SyntaxError?"Invalid JSON":i.message;jt.error(`Could not parse ${r} model version override from ${n}: ${a}`)}}}),e},ln=50*1024,tt=(e,t=ln)=>{if(!e||typeof e!="string"||e.length<=t)return e;let o=e.startsWith("```")?"\n... [truncated]\n```":"... [truncated]";return e.slice(0,t)+o};import{Buffer as qt}from"buffer";import cn from"path";var Wt=_("repo"),Vt=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{Wt.info("Getting runner diffs");let o=await pn(r),{hasChanges:n}=o,{status:i}=o;if(!n)return{hasChanges:!1};if(!t){let w=mn(i);await fn(w,r)}Wt.info("Changes after processing"),await nt(r);let s=await st(i,r);if(await rt(s,r),n=await dn(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await b("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},c=await b("git",["diff",e.runSha,"HEAD"],a),u=String(c.stdout??"");if(n=!!u,!n)return await Kt(r),{hasChanges:!1,ignored:s};let d=await b("git",["diff",e.runSha,"HEAD","--binary"],a),p=String(d.stdout??""),m,y;if(e.sha){let w=await b("git",["diff",e.sha,"HEAD"],a);m=String(w.stdout??"");let T=await b("git",["diff",e.sha,"HEAD","--binary"],a),E=String(T.stdout??"");m!==E&&(y=qt.from(E).toString("base64"))}await Kt(r);let h={hasChanges:!0,diff:u,resultDiff:m,ignored:s};return u!==p&&(h.diffBinary=qt.from(p).toString("base64")),y&&(h.resultDiffBinary=y),h},Kt=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await b("git",["reset","--soft","HEAD~1"],{cwd:e})},rt=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await b("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},nt=async(e=process.cwd())=>{let t=await b("git",["status","-s"],{cwd:e});return String(t.stdout??"")},Jt=/.. (.+)?\.log$/,un=[Jt],pn=async(e=process.cwd())=>{let t=await nt(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
9
9
  `).filter(n=>un.some(s=>s instanceof RegExp?s.test(n):n===s)?!1:n[1]?.trim()!=="")).length!==0,status:t}},dn=async(e=process.cwd())=>{try{return await b("git",["diff","--staged","--quiet"],{cwd:e}),!1}catch{return!0}},ot=async(e=process.cwd())=>{let{stdout:t}=await b("git",["rev-parse","HEAD"],{cwd:e});return String(t??"").trim()},Xt=async(e=process.cwd())=>{let{stdout:t}=await b("git",["rev-list","--max-parents=0","HEAD"],{cwd:e});return String(t??"").trim()},st=async(e,t=process.cwd())=>{e||=await nt(t);let r=[".netlify","node_modules","dist",".next","out",".nuxt",".output",".cache",".turbo",".parcel-cache","coverage",".nyc_output","storybook-static","public/build"],o=[];return e.split(`
10
10
  `).forEach(n=>{r.forEach(s=>{let a=n===`?? ${s}`,c=n.startsWith(`?? ${s}/`)||n.startsWith(`?? ${s}${cn.sep}`);(a||c)&&o.push(`:!${s}`)});let i=n.match(Jt)?.[1];i&&o.push(`:!${i}.log`)}),o},it=async(e=process.cwd())=>{await b("git",["reset","--hard","HEAD"],{cwd:e})},mn=e=>{let t=e.split(`
11
11
  `).reduce((r,o)=>{if(!o)return r;let[n,i,,...s]=o,a=s.join(""),c=n.trim(),u=i.trim();return r[a]?r[a].change=u:r[a]={filePath:a,stage:c,change:u},r},{});return Object.values(t)},fn=async(e,t=process.cwd())=>{let r=e.filter(o=>o.stage&&!o.change).map(o=>o.filePath);r.length!==0&&await b("git",["restore","--staged","--worktree","--pathspec-from-file=-"],{cwd:t,input:r.join(`
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import{createRequire as Jn}from"module";import{createTracerProvider as _r}from"@
4
4
  ${i}
5
5
  </extracted_error_chunk>`).join(`
6
6
 
7
- `);return o.length>e.length*.8?e:o}import{execSync as hn}from"child_process";import nr from"fs/promises";import yn from"path";import Z from"process";import{getTracer as wn}from"@netlify/otel";import we from"process";var ne=class extends Error{constructor(r,s,n){super(r);this.statusCode=s;this.userMessage=n;this.name="GracefulShutdownError"}},ht=e=>e instanceof ne;var Se=we.env.NETLIFY_API_URL,ve=we.env.NETLIFY_API_TOKEN,B=_("api"),Ae=()=>we.env.NETLIFY_LOCAL_MODE==="true",_e=async(e,t={})=>{if(!Se||!ve)throw new Error("No API URL or token");let r=new URL(e,Se),s={...t,headers:{...t.headers,Authorization:`Bearer ${ve}`}};we.env.AGENT_RUNNERS_DEBUG==="true"&&(s.headers["x-nf-debug-logging"]="true"),t.json&&(s.headers||={},s.headers["Content-Type"]="application/json",s.body=JSON.stringify(t.json));let n=await fetch(r,s),o=n.ok&&n.status<=299;if(we.env.AGENT_RUNNERS_DEBUG==="true")B.log(`Response headers for ${r}:`),n.headers.forEach((a,c)=>{B.log(` ${c}: ${a}`)});else{let a=n.headers.get("x-request-id")||n.headers.get("x-nf-request-id");B.log(`Request ID for ${r}: ${a||"N/A"}`)}if(o||B.error(`Got status ${n.status} for request ${r}`),t.raw){if(!o)throw new Error(`API request failed: ${n.status} ${n.statusText}`);return n}let i=await(n.headers.get("content-type")?.includes("application/json")?n.json():n.text());if(!o){let a=typeof i=="string"?i:JSON.stringify(i);throw n.status===404?new ne(`API request failed: 404 - ${a}`,404,"The site associated with this agent run no longer exists."):n.status===403&&t.gracefulOn403?new ne(`API request failed: 403 - ${a}`,403,"Credit limit reached. Please add more credits to continue using Agent Runners."):new Error(`API request failed: ${n.status} - ${a}`)}return i},yt=e=>{B.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Se=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(ve=e.constants.NETLIFY_API_TOKEN)},wt=()=>({apiUrl:Se,token:ve}),Ee=async(e,t)=>Ae()?(B.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):_e(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),D=async(e,t,r)=>Ae()?(B.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):_e(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var _t=async(e,t)=>Ae()?(B.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):_e(`/api/v1/agent_runners/${e}/sessions/${t}`),Et=(e,t,r)=>_e(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn403:!0}),Tt=async(e,t)=>Ae()?(B.log("Mock API: getDiffUploadUrls called",{runnerId:e,sessionId:t}),{result:{upload_url:"https://s3.mock.com/mock-upload-url-result",s3_key:"mock-s3-key-result"},cumulative:{upload_url:"https://s3.mock.com/mock-upload-url-cumulative",s3_key:"mock-s3-key-cumulative"}}):_e(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),Ye=async(e,t)=>{B.log(`Uploading diff to S3: ${e.substring(0,50)}...`);let r=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!r.ok)throw new Error(`S3 upload failed with status ${r.status}`);return r};var se=_("ai_gateway"),Be=null;var It=async()=>{if(Be)return Be;se.log("Fetching available AI gateway providers");let e=await fetch(`${wt().apiUrl}/api/v1/ai-gateway/providers`);if(!e.ok)throw new Error(`Failed to fetch AI gateway providers: ${e.statusText}`);let t=await e.json();return Be=t,se.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},Sr=async(e,t)=>{let s=(await It()).providers[e];if(!s)return se.log(`Provider '${e}' not found`),!1;let n=s.models.includes(t);return se.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},xt=async({netlify:e,config:t})=>{let r,s,n,o,i=e.constants?.SITE_ID;if(!i)throw new Error("No site id");let a=async()=>{clearTimeout(n),se.log("Requesting AI gateway information");let c=await Et(i,t.id,t.sessionId);if({token:r,url:o}=c,s=c.expires_at?c.expires_at*1e3:void 0,se.log("Got AI gateway information",{token:!!r,expiresAt:s,url:o}),s){let u=s-Date.now()-6e4;u>0&&(n=setTimeout(()=>{a()},u))}};return await Promise.all([a(),It()]),{get url(){return o},get token(){return r},isModelAvailableForProvider:Sr}};import H from"process";import V from"path";import be from"fs";import{fileURLToPath as kr}from"url";import{createRequire as Or}from"module";import{execa as $r,execaCommand as bs}from"execa";import{Transform as vr}from"stream";var Ar=new Set(["NODE_ENV","PATH","HOME","USER","USERNAME","SHELL","PWD","OLDPWD","TMPDIR","TMP","TEMP","LANG","TERM","EDITOR","PAGER","OS","PROCESSOR_ARCHITECTURE","PROCESSOR_IDENTIFIER","SYSTEMROOT","WINDIR","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","APPDATA","LOCALAPPDATA","NODE_OPTIONS","NODE_PATH","NODE_DEBUG","NODE_NO_WARNINGS","npm_config_registry","npm_config_cache","npm_execpath","npm_node_execpath","CI","GITHUB_ACTIONS","GITHUB_WORKSPACE","GITHUB_REPOSITORY","GITHUB_REF","BUILDKITE","BUILDKITE_BRANCH","BUILDKITE_COMMIT","BUILDKITE_BUILD_NUMBER","JENKINS_URL","TRAVIS","CIRCLECI","DISPLAY","COLORTERM","TERM_PROGRAM","TERM_PROGRAM_VERSION","COLUMNS","LINES","HISTSIZE","HISTFILE","NETLIFY_AGENT_RUNNER_ID","NETLIFY_AGENT_RUNNER_SESSION_ID","NETLIFY_AGENT_RUNNER_PROMPT","NETLIFY_AGENT_RUNNER_AGENT","NETLIFY_AGENT_RUNNER_MODEL","NETLIFY_AGENT_RUNNER_CONTEXT","NETLIFY_AGENT_RUNNER_HAS_REPO","NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED","NETLIFY_AGENT_RUNNER_SHA","NETLIFY_TEAM_TYPE","AGENT_RUNNERS_DEBUG","NETLIFY_TEAM_ID","NETLIFY_AGENT_RUNNER_USER_ID","SITE_NAME"]),br=new Set(["true","false","undefined","null","deploy","project","claude","gemini","codex",""]);function Cr(){return Object.entries(process.env).filter(([e,t])=>!(!t||Ar.has(e)||br.has(t)||!isNaN(Number(t))||t.length<5)).map(([,e])=>e).filter(Boolean)}function J(e){if(typeof e!="string")return e;let t=Cr();if(t.length===0)return e;let r=e;return t.forEach(s=>{let n=new RegExp(Nr(s),"g");r=r.replace(n,"******")}),r}function Nr(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ie=class extends vr{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,s){let n=t.toString(),o=J(n);s(null,o)}};function Rt(){if(!(process.env.NETLIFY_MASK_LOGS!=="false"))return;let t=process.stdout.write.bind(process.stdout),r=process.stderr.write.bind(process.stderr);process.stdout.write=function(s,n,o){let i=typeof s=="string"?J(s):s;return typeof n=="function"?t(i,n):t(i,n,o)},process.stderr.write=function(s,n,o){let i=typeof s=="string"?J(s):s;return typeof n=="function"?r(i,n):r(i,n,o)}}var Te=null,St=e=>(Te&&Te.destroy(),Te=new X({totalAllowedTime:e}),Te),vt=()=>Te;var X=class{constructor({totalAllowedTime:t}){this.withStageTimer=async(t,r,s)=>{if(this.isTimeExpired())throw new Error(`${t} stage did not complete in the allowed time. Time has already expired.`);let n=this.onTimesUp(()=>{throw new Error(`${t} stage did not complete in the allowed time.`)}),o=null,i=null;s!==void 0&&(i=new Promise((a,c)=>{o=setTimeout(()=>{c(new Error(`${t} stage exceeded its maximum duration of ${s}ms`))},s)}));try{return i?await Promise.race([r(),i]):await r()}finally{n(),o&&clearTimeout(o)}};this.startTime=Date.now(),this.totalAllowedTime=t,this.globalTimeoutId=null,this.subscribers=[],this.hasTimedOut=!1,this.setupGlobalTimeout()}getElapsedTime(){return Date.now()-this.startTime}getRemainingTime(){let t=this.getElapsedTime(),r=this.totalAllowedTime-t;return Math.max(0,r)}isTimeExpired(){return this.getRemainingTime()===0||this.hasTimedOut}setupGlobalTimeout(){this.globalTimeoutId&&clearTimeout(this.globalTimeoutId),this.globalTimeoutId=setTimeout(()=>{this.notifyTimeUp()},this.totalAllowedTime)}notifyTimeUp(){this.hasTimedOut=!0;for(let t=this.subscribers.length-1;t>=0;t--)try{this.subscribers[t]()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}}onTimesUp(t){if(this.subscribers.push(t),this.hasTimedOut)try{t()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}return()=>{let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}}off(t){let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}clearSubscribers(){this.subscribers.length=0}getSubscriberCount(){return this.subscribers.length}destroy(){this.globalTimeoutId&&(clearTimeout(this.globalTimeoutId),this.globalTimeoutId=null),this.clearSubscribers()}static{this.timeUnits={seconds:t=>t*1e3,minutes:t=>t*60*1e3,hours:t=>t*60*60*1e3}}};var At="netlify-agent-runner-context.md",qe="task-history",q=".netlify",Q="results.md",He="assets";var ee=1800*1e3;var bt={name:"@netlify/agent-runner-cli",type:"module",version:"1.69.3",description:"CLI tool for running Netlify agents",main:"./dist/index.js",types:"./dist/index.d.ts",exports:"./dist/index.js",bin:{"agent-runner-cli":"./dist/bin.js","agent-runner-cli-local":"./dist/bin-local.js"},files:["dist/**/*.js","dist/**/*.d.ts","dist/skills/**","patches","scripts"],scripts:{build:"tsup",dev:"tsup --watch",prepare:"husky install node_modules/@netlify/eslint-config-node/.husky/",prepublishOnly:"npm ci && npm test",prepack:"npm run build",test:"run-s build format test:dev",format:"run-s build format:check-fix:*","format:ci":"run-s build format:check:*","format:check-fix:lint":"run-e format:check:lint format:fix:lint","format:check:lint":"cross-env-shell eslint $npm_package_config_eslint","format:fix:lint":"cross-env-shell eslint --fix $npm_package_config_eslint","format:check-fix:prettier":"run-e format:check:prettier format:fix:prettier","format:check:prettier":"cross-env-shell prettier --check $npm_package_config_prettier","format:fix:prettier":"cross-env-shell prettier --write $npm_package_config_prettier","test:dev":"run-s build test:dev:*","test:ci":"run-s build test:ci:*","test:dev:vitest":"LOG=0 vitest --exclude '**/integration/**'","test:ci:vitest":"LOG=0 c8 -r lcovonly -r text -r json vitest --exclude '**/integration/**'","test:integration":"vitest run test/integration/","test:integration:codex":"vitest run test/integration/codex.test.ts","test:integration:claude":"vitest run test/integration/claude.test.ts","test:integration:gemini":"vitest run test/integration/gemini.test.ts","test:integration:create-stage":"vitest run test/integration/create.test.ts",postinstall:"node scripts/postinstall.js"},config:{eslint:'--cache --format=codeframe --max-warnings=0 "{src,scripts,test,.github}/**/*.{js,ts,md,html}"',prettier:'--ignore-path .gitignore --loglevel=warn "{src,scripts,test,.github}/**/*.{js,ts,md,yml,json,html}" "*.{js,ts,yml,json,html}" ".*.{js,ts,yml,json,html}" "!**/package-lock.json" "!package-lock.json" "!src/skills/**/*.md"'},keywords:[],license:"MIT",repository:"netlify/agent-runner-cli",bugs:{url:"https://github.com/netlify/agent-runner-cli/issues"},author:"Netlify Inc.",directories:{test:"test"},devDependencies:{"@commitlint/cli":"^20.0.0","@commitlint/config-conventional":"^20.0.0","@eslint/compat":"^2.0.0","@eslint/js":"^9.35.0","@netlify/eslint-config-node":"^7.0.1","@types/node":"^24.5.0","@typescript-eslint/eslint-plugin":"^8.0.0","@typescript-eslint/parser":"^8.0.0","@vitest/eslint-plugin":"^1.6.6",c8:"^10.0.0","eslint-config-prettier":"^10.1.8","eslint-plugin-n":"^17.0.0",husky:"^9.0.0","patch-package":"^8.0.0",tsup:"^8.5.0",typescript:"^5.0.0","typescript-eslint":"^8.44.0",vitest:"^4.0.16"},dependencies:{"@anthropic-ai/claude-code":"2.1.37","@anthropic-ai/sdk":"0.72.1","@google/gemini-cli":"0.27.3","@netlify/otel":"^5.1.1","@openai/codex":"0.93.0","@opentelemetry/exporter-trace-otlp-grpc":"^0.208.0",execa:"^9.6.1",kaddidlehopper:"^0.1.2",minimist:"^1.2.8",openai:"6.17.0"}};var Lr=kr(import.meta.url),Fr=V.dirname(Lr),Dr=Or(import.meta.url),oe=_("shell"),We=new Set,Mr={preferLocal:!0},b=(e,t,r)=>{let[s,n]=Ur(t,r),o={...Mr,...n},i=$r(e,s,o);Gr(i,o),Yr(i);let a=r?.idleTimeout;return a&&a>0&&jr(i,a),i};var Ur=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},Gr=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(H.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new ie).pipe(H.stdout),e.stdout?.pipe(new ie).pipe(H.stdout),e.stderr?.pipe(new ie).pipe(H.stderr);return}e.stdout?.pipe(H.stdout),e.stderr?.pipe(H.stderr)},Ke=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(H.kill(-e.pid,t),oe.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return oe.error("Error killing process:",r),!1}},Ct=e=>Ke(e,"SIGKILL"),jr=(e,t)=>{let r=null,s=()=>{oe.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),Ke(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(oe.log(`Force killing idle process ${e.pid}`),Ct(e))},5e3)},n=()=>{r&&clearTimeout(r),r=setTimeout(s,t)};n(),e.stdout?.on("data",n),e.stderr?.on("data",n);let o=()=>{r&&(clearTimeout(r),r=null)};e.on("exit",o),e.on("error",o)},Yr=e=>{We.add(e);let t=vt();if(t){let r=t.onTimesUp(()=>{oe.log(`Global timer expired, killing process ${e.pid}`),Ke(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(oe.log(`Force killing process ${e.pid} after timeout`),Ct(e))},5e3)});e.on("exit",()=>{We.delete(e),r()}),e.on("error",()=>{We.delete(e),r()})}};function z(e,t){if(!H.env.NETLIFY_LOCAL_MODE)try{let n=Dr.resolve(bt.name),o=V.dirname(n);for(;o!==V.dirname(o);){let i=V.dirname(o);if(V.basename(i)==="node_modules"){let a=V.join(i,".bin",t);if(be.existsSync(a))return a;break}o=i}}catch(n){console.error("Could not resolve package.json",n)}if(H.env.NODE_PATH){let n=V.join(H.env.NODE_PATH,".bin",t);if(be.existsSync(n))return n}let r=V.join(e,"node_modules",".bin",t);if(be.existsSync(r))return r;let s=V.join(Fr,"..","node_modules",".bin",t);if(be.existsSync(s))return s}var Br=_("utils"),qr=e=>new Promise(t=>{setTimeout(t,e)}),Nt=(e,t=3e3)=>{let r=!1,s=null,n=[],o=null,i=(...a)=>{if(r)return s=a,new Promise(d=>{n.push(d)});r=!0;let c,u=new Promise(d=>{c=d});return o=(async()=>{await Promise.resolve();let d=await e(...a);for(c(d);;){if(await qr(t),!s)return r=!1,o=null,d;let p=s,m=n;s=null,n=[],d=await e(...p),m.forEach(y=>{y(d)})}})(),u};return i.flush=async()=>{if((r||s)&&o)return await o,i.flush()},i},ae=(e,t,r=!1)=>{let s=null,n=null,o=null,i=function(...a){n=a,o=this;let c=r&&!s;clearTimeout(s),s=setTimeout(()=>{s=null,r||(e.apply(o,n),n=null,o=null)},t),c&&(e.apply(o,n),n=null,o=null)};return i.cancel=()=>{clearTimeout(s),s=null,n=null,o=null},i.flush=()=>{if(s){clearTimeout(s);let a=n,c=o;s=null,n=null,o=null,e.apply(c,a)}},i},Pt=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(s){t&&(r?.error?r.error("Could not parse JSON",s):Br.error("Could not parse JSON",s))}},kt=(e,t)=>{let n=".netlify.app",o="agent-";if(!t)return`${o}${e.slice(0,6)}`;let a=`--${t}${n}`;if(a.length>55)return"";let c=60-a.length;if(c<=0)return"";if(c>=o.length+6){let u=Math.min(c-o.length,e.length);return`${o}${e.slice(0,u)}`}return e.slice(0,c)};var Hr=50*1024,Je=(e,t=Hr)=>{if(!e||typeof e!="string"||e.length<=t)return e;let s=e.startsWith("```")?"\n... [truncated]\n```":"... [truncated]";return e.slice(0,t)+s};import{Buffer as Ot}from"buffer";import Wr from"path";var $t=_("repo"),Ft=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{$t.info("Getting runner diffs");let s=await Jr(r),{hasChanges:n}=s,{status:o}=s;if(!n)return{hasChanges:!1};if(!t){let E=Xr(o);await zr(E,r)}$t.info("Changes after processing"),await Xe(r);let i=await Ze(o,r);if(await Ve(i,r),n=await Vr(r),!n)return{hasChanges:!1,ignored:i};process.env.NETLIFY_INTERNAL_GIT="1";try{await b("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},c=await b("git",["diff",e.runSha,"HEAD"],a),u=String(c.stdout??"");if(n=!!u,!n)return await Lt(r),{hasChanges:!1,ignored:i};let d=await b("git",["diff",e.runSha,"HEAD","--binary"],a),p=String(d.stdout??""),m,y;if(e.sha){let E=await b("git",["diff",e.sha,"HEAD"],a);m=String(E.stdout??"");let T=await b("git",["diff",e.sha,"HEAD","--binary"],a),w=String(T.stdout??"");m!==w&&(y=Ot.from(w).toString("base64"))}await Lt(r);let h={hasChanges:!0,diff:u,resultDiff:m,ignored:i};return u!==p&&(h.diffBinary=Ot.from(p).toString("base64")),y&&(h.resultDiffBinary=y),h},Lt=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await b("git",["reset","--soft","HEAD~1"],{cwd:e})},Ve=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await b("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},Xe=async(e=process.cwd())=>{let t=await b("git",["status","-s"],{cwd:e});return String(t.stdout??"")},Dt=/.. (.+)?\.log$/,Kr=[Dt],Jr=async(e=process.cwd())=>{let t=await Xe(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
7
+ `);return o.length>e.length*.8?e:o}import{execSync as hn}from"child_process";import nr from"fs/promises";import yn from"path";import Z from"process";import{getTracer as wn}from"@netlify/otel";import we from"process";var ne=class extends Error{constructor(r,s,n){super(r);this.statusCode=s;this.userMessage=n;this.name="GracefulShutdownError"}},ht=e=>e instanceof ne;var Se=we.env.NETLIFY_API_URL,ve=we.env.NETLIFY_API_TOKEN,B=_("api"),Ae=()=>we.env.NETLIFY_LOCAL_MODE==="true",_e=async(e,t={})=>{if(!Se||!ve)throw new Error("No API URL or token");let r=new URL(e,Se),s={...t,headers:{...t.headers,Authorization:`Bearer ${ve}`}};we.env.AGENT_RUNNERS_DEBUG==="true"&&(s.headers["x-nf-debug-logging"]="true"),t.json&&(s.headers||={},s.headers["Content-Type"]="application/json",s.body=JSON.stringify(t.json));let n=await fetch(r,s),o=n.ok&&n.status<=299;if(we.env.AGENT_RUNNERS_DEBUG==="true")B.log(`Response headers for ${r}:`),n.headers.forEach((a,c)=>{B.log(` ${c}: ${a}`)});else{let a=n.headers.get("x-request-id")||n.headers.get("x-nf-request-id");B.log(`Request ID for ${r}: ${a||"N/A"}`)}if(o||B.error(`Got status ${n.status} for request ${r}`),t.raw){if(!o)throw new Error(`API request failed: ${n.status} ${n.statusText}`);return n}let i=await(n.headers.get("content-type")?.includes("application/json")?n.json():n.text());if(!o){let a=typeof i=="string"?i:JSON.stringify(i);throw n.status===404?new ne(`API request failed: 404 - ${a}`,404,"The site associated with this agent run no longer exists."):n.status===403&&t.gracefulOn403?new ne(`API request failed: 403 - ${a}`,403,"Credit limit reached. Please add more credits to continue using Agent Runners."):new Error(`API request failed: ${n.status} - ${a}`)}return i},yt=e=>{B.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Se=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(ve=e.constants.NETLIFY_API_TOKEN)},wt=()=>({apiUrl:Se,token:ve}),Ee=async(e,t)=>Ae()?(B.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):_e(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),D=async(e,t,r)=>Ae()?(B.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):_e(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var _t=async(e,t)=>Ae()?(B.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):_e(`/api/v1/agent_runners/${e}/sessions/${t}`),Et=(e,t,r)=>_e(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn403:!0}),Tt=async(e,t)=>Ae()?(B.log("Mock API: getDiffUploadUrls called",{runnerId:e,sessionId:t}),{result:{upload_url:"https://s3.mock.com/mock-upload-url-result",s3_key:"mock-s3-key-result"},cumulative:{upload_url:"https://s3.mock.com/mock-upload-url-cumulative",s3_key:"mock-s3-key-cumulative"}}):_e(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),Ye=async(e,t)=>{B.log(`Uploading diff to S3: ${e.substring(0,50)}...`);let r=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!r.ok)throw new Error(`S3 upload failed with status ${r.status}`);return r};var se=_("ai_gateway"),Be=null;var It=async()=>{if(Be)return Be;se.log("Fetching available AI gateway providers");let e=await fetch(`${wt().apiUrl}/api/v1/ai-gateway/providers`);if(!e.ok)throw new Error(`Failed to fetch AI gateway providers: ${e.statusText}`);let t=await e.json();return Be=t,se.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},Sr=async(e,t)=>{let s=(await It()).providers[e];if(!s)return se.log(`Provider '${e}' not found`),!1;let n=s.models.includes(t);return se.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},xt=async({netlify:e,config:t})=>{let r,s,n,o,i=e.constants?.SITE_ID;if(!i)throw new Error("No site id");let a=async()=>{clearTimeout(n),se.log("Requesting AI gateway information");let c=await Et(i,t.id,t.sessionId);if({token:r,url:o}=c,s=c.expires_at?c.expires_at*1e3:void 0,se.log("Got AI gateway information",{token:!!r,expiresAt:s,url:o}),s){let u=s-Date.now()-6e4;u>0&&(n=setTimeout(()=>{a()},u))}};return await Promise.all([a(),It()]),{get url(){return o},get token(){return r},isModelAvailableForProvider:Sr}};import H from"process";import V from"path";import be from"fs";import{fileURLToPath as kr}from"url";import{createRequire as Or}from"module";import{execa as $r,execaCommand as bs}from"execa";import{Transform as vr}from"stream";var Ar=new Set(["NODE_ENV","PATH","HOME","USER","USERNAME","SHELL","PWD","OLDPWD","TMPDIR","TMP","TEMP","LANG","TERM","EDITOR","PAGER","OS","PROCESSOR_ARCHITECTURE","PROCESSOR_IDENTIFIER","SYSTEMROOT","WINDIR","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","APPDATA","LOCALAPPDATA","NODE_OPTIONS","NODE_PATH","NODE_DEBUG","NODE_NO_WARNINGS","npm_config_registry","npm_config_cache","npm_execpath","npm_node_execpath","CI","GITHUB_ACTIONS","GITHUB_WORKSPACE","GITHUB_REPOSITORY","GITHUB_REF","BUILDKITE","BUILDKITE_BRANCH","BUILDKITE_COMMIT","BUILDKITE_BUILD_NUMBER","JENKINS_URL","TRAVIS","CIRCLECI","DISPLAY","COLORTERM","TERM_PROGRAM","TERM_PROGRAM_VERSION","COLUMNS","LINES","HISTSIZE","HISTFILE","NETLIFY_AGENT_RUNNER_ID","NETLIFY_AGENT_RUNNER_SESSION_ID","NETLIFY_AGENT_RUNNER_PROMPT","NETLIFY_AGENT_RUNNER_AGENT","NETLIFY_AGENT_RUNNER_MODEL","NETLIFY_AGENT_RUNNER_CONTEXT","NETLIFY_AGENT_RUNNER_HAS_REPO","NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED","NETLIFY_AGENT_RUNNER_SHA","NETLIFY_TEAM_TYPE","AGENT_RUNNERS_DEBUG","NETLIFY_TEAM_ID","NETLIFY_AGENT_RUNNER_USER_ID","SITE_NAME"]),br=new Set(["true","false","undefined","null","deploy","project","claude","gemini","codex",""]);function Cr(){return Object.entries(process.env).filter(([e,t])=>!(!t||Ar.has(e)||br.has(t)||!isNaN(Number(t))||t.length<5)).map(([,e])=>e).filter(Boolean)}function J(e){if(typeof e!="string")return e;let t=Cr();if(t.length===0)return e;let r=e;return t.forEach(s=>{let n=new RegExp(Nr(s),"g");r=r.replace(n,"******")}),r}function Nr(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ie=class extends vr{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,s){let n=t.toString(),o=J(n);s(null,o)}};function Rt(){if(!(process.env.NETLIFY_MASK_LOGS!=="false"))return;let t=process.stdout.write.bind(process.stdout),r=process.stderr.write.bind(process.stderr);process.stdout.write=function(s,n,o){let i=typeof s=="string"?J(s):s;return typeof n=="function"?t(i,n):t(i,n,o)},process.stderr.write=function(s,n,o){let i=typeof s=="string"?J(s):s;return typeof n=="function"?r(i,n):r(i,n,o)}}var Te=null,St=e=>(Te&&Te.destroy(),Te=new X({totalAllowedTime:e}),Te),vt=()=>Te;var X=class{constructor({totalAllowedTime:t}){this.withStageTimer=async(t,r,s)=>{if(this.isTimeExpired())throw new Error(`${t} stage did not complete in the allowed time. Time has already expired.`);let n=this.onTimesUp(()=>{throw new Error(`${t} stage did not complete in the allowed time.`)}),o=null,i=null;s!==void 0&&(i=new Promise((a,c)=>{o=setTimeout(()=>{c(new Error(`${t} stage exceeded its maximum duration of ${s}ms`))},s)}));try{return i?await Promise.race([r(),i]):await r()}finally{n(),o&&clearTimeout(o)}};this.startTime=Date.now(),this.totalAllowedTime=t,this.globalTimeoutId=null,this.subscribers=[],this.hasTimedOut=!1,this.setupGlobalTimeout()}getElapsedTime(){return Date.now()-this.startTime}getRemainingTime(){let t=this.getElapsedTime(),r=this.totalAllowedTime-t;return Math.max(0,r)}isTimeExpired(){return this.getRemainingTime()===0||this.hasTimedOut}setupGlobalTimeout(){this.globalTimeoutId&&clearTimeout(this.globalTimeoutId),this.globalTimeoutId=setTimeout(()=>{this.notifyTimeUp()},this.totalAllowedTime)}notifyTimeUp(){this.hasTimedOut=!0;for(let t=this.subscribers.length-1;t>=0;t--)try{this.subscribers[t]()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}}onTimesUp(t){if(this.subscribers.push(t),this.hasTimedOut)try{t()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}return()=>{let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}}off(t){let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}clearSubscribers(){this.subscribers.length=0}getSubscriberCount(){return this.subscribers.length}destroy(){this.globalTimeoutId&&(clearTimeout(this.globalTimeoutId),this.globalTimeoutId=null),this.clearSubscribers()}static{this.timeUnits={seconds:t=>t*1e3,minutes:t=>t*60*1e3,hours:t=>t*60*60*1e3}}};var At="netlify-agent-runner-context.md",qe="task-history",q=".netlify",Q="results.md",He="assets";var ee=1800*1e3;var bt={name:"@netlify/agent-runner-cli",type:"module",version:"1.70.0",description:"CLI tool for running Netlify agents",main:"./dist/index.js",types:"./dist/index.d.ts",exports:"./dist/index.js",bin:{"agent-runner-cli":"./dist/bin.js","agent-runner-cli-local":"./dist/bin-local.js"},files:["dist/**/*.js","dist/**/*.d.ts","dist/skills/**","patches","scripts"],scripts:{build:"tsup",dev:"tsup --watch",prepare:"husky install node_modules/@netlify/eslint-config-node/.husky/",prepublishOnly:"npm ci && npm test",prepack:"npm run build",test:"run-s build format test:dev",format:"run-s build format:check-fix:*","format:ci":"run-s build format:check:*","format:check-fix:lint":"run-e format:check:lint format:fix:lint","format:check:lint":"cross-env-shell eslint $npm_package_config_eslint","format:fix:lint":"cross-env-shell eslint --fix $npm_package_config_eslint","format:check-fix:prettier":"run-e format:check:prettier format:fix:prettier","format:check:prettier":"cross-env-shell prettier --check $npm_package_config_prettier","format:fix:prettier":"cross-env-shell prettier --write $npm_package_config_prettier","test:dev":"run-s build test:dev:*","test:ci":"run-s build test:ci:*","test:dev:vitest":"LOG=0 vitest --exclude '**/integration/**'","test:ci:vitest":"LOG=0 c8 -r lcovonly -r text -r json vitest --exclude '**/integration/**'","test:integration":"vitest run test/integration/","test:integration:codex":"vitest run test/integration/codex.test.ts","test:integration:claude":"vitest run test/integration/claude.test.ts","test:integration:gemini":"vitest run test/integration/gemini.test.ts","test:integration:create-stage":"vitest run test/integration/create.test.ts",postinstall:"node scripts/postinstall.js"},config:{eslint:'--cache --format=codeframe --max-warnings=0 "{src,scripts,test,.github}/**/*.{js,ts,md,html}"',prettier:'--ignore-path .gitignore --loglevel=warn "{src,scripts,test,.github}/**/*.{js,ts,md,yml,json,html}" "*.{js,ts,yml,json,html}" ".*.{js,ts,yml,json,html}" "!**/package-lock.json" "!package-lock.json" "!src/skills/**/*.md"'},keywords:[],license:"MIT",repository:"netlify/agent-runner-cli",bugs:{url:"https://github.com/netlify/agent-runner-cli/issues"},author:"Netlify Inc.",directories:{test:"test"},devDependencies:{"@commitlint/cli":"^20.0.0","@commitlint/config-conventional":"^20.0.0","@eslint/compat":"^2.0.0","@eslint/js":"^9.35.0","@netlify/eslint-config-node":"^7.0.1","@types/node":"^24.5.0","@typescript-eslint/eslint-plugin":"^8.0.0","@typescript-eslint/parser":"^8.0.0","@vitest/eslint-plugin":"^1.6.6",c8:"^10.0.0","eslint-config-prettier":"^10.1.8","eslint-plugin-n":"^17.0.0",husky:"^9.0.0","patch-package":"^8.0.0",tsup:"^8.5.0",typescript:"^5.0.0","typescript-eslint":"^8.44.0",vitest:"^4.0.16"},dependencies:{"@anthropic-ai/claude-code":"2.1.37","@anthropic-ai/sdk":"0.72.1","@google/gemini-cli":"0.27.3","@netlify/otel":"^5.1.1","@openai/codex":"0.93.0","@opentelemetry/exporter-trace-otlp-grpc":"^0.208.0",execa:"^9.6.1",kaddidlehopper:"^0.1.2",minimist:"^1.2.8",openai:"6.17.0"}};var Lr=kr(import.meta.url),Fr=V.dirname(Lr),Dr=Or(import.meta.url),oe=_("shell"),We=new Set,Mr={preferLocal:!0},b=(e,t,r)=>{let[s,n]=Ur(t,r),o={...Mr,...n},i=$r(e,s,o);Gr(i,o),Yr(i);let a=r?.idleTimeout;return a&&a>0&&jr(i,a),i};var Ur=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},Gr=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(H.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new ie).pipe(H.stdout),e.stdout?.pipe(new ie).pipe(H.stdout),e.stderr?.pipe(new ie).pipe(H.stderr);return}e.stdout?.pipe(H.stdout),e.stderr?.pipe(H.stderr)},Ke=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(H.kill(-e.pid,t),oe.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return oe.error("Error killing process:",r),!1}},Ct=e=>Ke(e,"SIGKILL"),jr=(e,t)=>{let r=null,s=()=>{oe.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),Ke(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(oe.log(`Force killing idle process ${e.pid}`),Ct(e))},5e3)},n=()=>{r&&clearTimeout(r),r=setTimeout(s,t)};n(),e.stdout?.on("data",n),e.stderr?.on("data",n);let o=()=>{r&&(clearTimeout(r),r=null)};e.on("exit",o),e.on("error",o)},Yr=e=>{We.add(e);let t=vt();if(t){let r=t.onTimesUp(()=>{oe.log(`Global timer expired, killing process ${e.pid}`),Ke(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(oe.log(`Force killing process ${e.pid} after timeout`),Ct(e))},5e3)});e.on("exit",()=>{We.delete(e),r()}),e.on("error",()=>{We.delete(e),r()})}};function z(e,t){if(!H.env.NETLIFY_LOCAL_MODE)try{let n=Dr.resolve(bt.name),o=V.dirname(n);for(;o!==V.dirname(o);){let i=V.dirname(o);if(V.basename(i)==="node_modules"){let a=V.join(i,".bin",t);if(be.existsSync(a))return a;break}o=i}}catch(n){console.error("Could not resolve package.json",n)}if(H.env.NODE_PATH){let n=V.join(H.env.NODE_PATH,".bin",t);if(be.existsSync(n))return n}let r=V.join(e,"node_modules",".bin",t);if(be.existsSync(r))return r;let s=V.join(Fr,"..","node_modules",".bin",t);if(be.existsSync(s))return s}var Br=_("utils"),qr=e=>new Promise(t=>{setTimeout(t,e)}),Nt=(e,t=3e3)=>{let r=!1,s=null,n=[],o=null,i=(...a)=>{if(r)return s=a,new Promise(d=>{n.push(d)});r=!0;let c,u=new Promise(d=>{c=d});return o=(async()=>{await Promise.resolve();let d=await e(...a);for(c(d);;){if(await qr(t),!s)return r=!1,o=null,d;let p=s,m=n;s=null,n=[],d=await e(...p),m.forEach(y=>{y(d)})}})(),u};return i.flush=async()=>{if((r||s)&&o)return await o,i.flush()},i},ae=(e,t,r=!1)=>{let s=null,n=null,o=null,i=function(...a){n=a,o=this;let c=r&&!s;clearTimeout(s),s=setTimeout(()=>{s=null,r||(e.apply(o,n),n=null,o=null)},t),c&&(e.apply(o,n),n=null,o=null)};return i.cancel=()=>{clearTimeout(s),s=null,n=null,o=null},i.flush=()=>{if(s){clearTimeout(s);let a=n,c=o;s=null,n=null,o=null,e.apply(c,a)}},i},Pt=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(s){t&&(r?.error?r.error("Could not parse JSON",s):Br.error("Could not parse JSON",s))}},kt=(e,t)=>{let n=".netlify.app",o="agent-";if(!t)return`${o}${e.slice(0,6)}`;let a=`--${t}${n}`;if(a.length>55)return"";let c=60-a.length;if(c<=0)return"";if(c>=o.length+6){let u=Math.min(c-o.length,e.length);return`${o}${e.slice(0,u)}`}return e.slice(0,c)};var Hr=50*1024,Je=(e,t=Hr)=>{if(!e||typeof e!="string"||e.length<=t)return e;let s=e.startsWith("```")?"\n... [truncated]\n```":"... [truncated]";return e.slice(0,t)+s};import{Buffer as Ot}from"buffer";import Wr from"path";var $t=_("repo"),Ft=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{$t.info("Getting runner diffs");let s=await Jr(r),{hasChanges:n}=s,{status:o}=s;if(!n)return{hasChanges:!1};if(!t){let E=Xr(o);await zr(E,r)}$t.info("Changes after processing"),await Xe(r);let i=await Ze(o,r);if(await Ve(i,r),n=await Vr(r),!n)return{hasChanges:!1,ignored:i};process.env.NETLIFY_INTERNAL_GIT="1";try{await b("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},c=await b("git",["diff",e.runSha,"HEAD"],a),u=String(c.stdout??"");if(n=!!u,!n)return await Lt(r),{hasChanges:!1,ignored:i};let d=await b("git",["diff",e.runSha,"HEAD","--binary"],a),p=String(d.stdout??""),m,y;if(e.sha){let E=await b("git",["diff",e.sha,"HEAD"],a);m=String(E.stdout??"");let T=await b("git",["diff",e.sha,"HEAD","--binary"],a),w=String(T.stdout??"");m!==w&&(y=Ot.from(w).toString("base64"))}await Lt(r);let h={hasChanges:!0,diff:u,resultDiff:m,ignored:i};return u!==p&&(h.diffBinary=Ot.from(p).toString("base64")),y&&(h.resultDiffBinary=y),h},Lt=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await b("git",["reset","--soft","HEAD~1"],{cwd:e})},Ve=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await b("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},Xe=async(e=process.cwd())=>{let t=await b("git",["status","-s"],{cwd:e});return String(t.stdout??"")},Dt=/.. (.+)?\.log$/,Kr=[Dt],Jr=async(e=process.cwd())=>{let t=await Xe(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
8
8
  `).filter(n=>Kr.some(i=>i instanceof RegExp?i.test(n):n===i)?!1:n[1]?.trim()!=="")).length!==0,status:t}},Vr=async(e=process.cwd())=>{try{return await b("git",["diff","--staged","--quiet"],{cwd:e}),!1}catch{return!0}},ze=async(e=process.cwd())=>{let{stdout:t}=await b("git",["rev-parse","HEAD"],{cwd:e});return String(t??"").trim()},Mt=async(e=process.cwd())=>{let{stdout:t}=await b("git",["rev-list","--max-parents=0","HEAD"],{cwd:e});return String(t??"").trim()},Ze=async(e,t=process.cwd())=>{e||=await Xe(t);let r=[".netlify","node_modules","dist",".next","out",".nuxt",".output",".cache",".turbo",".parcel-cache","coverage",".nyc_output","storybook-static","public/build"],s=[];return e.split(`
9
9
  `).forEach(n=>{r.forEach(i=>{let a=n===`?? ${i}`,c=n.startsWith(`?? ${i}/`)||n.startsWith(`?? ${i}${Wr.sep}`);(a||c)&&s.push(`:!${i}`)});let o=n.match(Dt)?.[1];o&&s.push(`:!${o}.log`)}),s},Qe=async(e=process.cwd())=>{await b("git",["reset","--hard","HEAD"],{cwd:e})},Xr=e=>{let t=e.split(`
10
10
  `).reduce((r,s)=>{if(!s)return r;let[n,o,,...i]=s,a=i.join(""),c=n.trim(),u=o.trim();return r[a]?r[a].change=u:r[a]={filePath:a,stage:c,change:u},r},{});return Object.values(t)},zr=async(e,t=process.cwd())=>{let r=e.filter(s=>s.stage&&!s.change).map(s=>s.filePath);r.length!==0&&await b("git",["restore","--staged","--worktree","--pathspec-from-file=-"],{cwd:t,input:r.join(`