@netlify/agent-runner-cli 1.92.3 → 1.92.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin-local.js CHANGED
@@ -5,7 +5,7 @@ import G from"process";import Xr from"path";import Zr from"fs";import $i from"mi
5
5
  ${s}
6
6
  </extracted_error_chunk>`).join(`
7
7
 
8
- `);return o.length>e.length*.8?e:o}import{execSync as Qn}from"child_process";import kr from"fs/promises";import ei from"path";import _e from"process";import{getTracer as ti}from"@netlify/otel";import $e from"process";var te=class extends Error{constructor(r,i,n,o=!1){super(r);this.statusCode=i;this.userMessage=n;this.isCreditLimitExceeded=o;this.name="GracefulShutdownError"}},qe=e=>e instanceof te;var Be=$e.env.NETLIFY_API_URL,He=$e.env.NETLIFY_API_TOKEN,W=T("api"),Te=()=>$e.env.NETLIFY_LOCAL_MODE==="true",ue=async(e,t={})=>{if(!Be||!He)throw new Error("No API URL or token");let r=new URL(e,Be),i={...t,headers:{...t.headers,Authorization:`Bearer ${He}`}};$e.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),o=n.ok&&n.status<=299;if($e.env.AGENT_RUNNERS_DEBUG==="true")W.log(`Response headers for ${r}:`),n.headers.forEach((a,l)=>{W.log(` ${l}: ${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(o||W.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 s=await(n.headers.get("content-type")?.includes("application/json")?n.json():n.text());if(!o){let a=typeof s=="string"?s:JSON.stringify(s);throw n.status===404?new te(`API request failed: 404 - ${a}`,404,"The site associated with this agent run no longer exists."):n.status===503&&t.gracefulOn503&&a.toLowerCase().includes("usage exceeded")?new te(`API request failed: 503 - ${a}`,503,"Credit limit reached. Please add more credits to continue using Agent Runners.",!0):new Error(`API request failed: ${n.status} - ${a}`)}return s},Bt=e=>{W.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Be=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(He=e.constants.NETLIFY_API_TOKEN)},Ht=()=>({apiUrl:Be,token:He}),Oe=async(e,t)=>Te()?(W.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):ue(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),K=async(e,t,r)=>Te()?(W.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):ue(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var Wt=async e=>Te()?(W.log("Mock API: getSite called",{siteId:e}),{id:e,published_deploy:{id:"id"}}):ue(`/api/v1/sites/${e}`),Kt=async(e,t)=>Te()?(W.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):ue(`/api/v1/agent_runners/${e}/sessions/${t}`),Jt=(e,t,r)=>ue(`/api/v1/accounts/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),Vt=(e,t,r)=>ue(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),zt=async(e,t)=>Te()?(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"}}):ue(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),Xt=async(e,t)=>Te()?(W.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):ue(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),pt=async(e,t,{maxRetries:r=3,baseDelayMs:i=500}={})=>{W.log(`Uploading diff to S3: ${e.substring(0,50)}...`);for(let n=1;n<=r;n++)try{let o=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!o.ok)throw new Error(`S3 upload failed with status ${o.status}`);return o}catch(o){if(n===r)throw o;let s=i*2**(n-1);W.warn(`S3 upload attempt ${n}/${r} failed: ${o.message}. Retrying in ${s}ms...`),await new Promise(a=>setTimeout(a,s))}};var Ie=T("ai_gateway"),mt=null;var We=async()=>{if(mt)return mt;Ie.log("Fetching available AI gateway providers");let e=await fetch(`${Ht().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 mt=t,Ie.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},an=async(e,t)=>{let i=(await We()).providers[e];if(!i)return Ie.log(`Provider '${e}' not found`),!1;let n=i.models.includes(t);return Ie.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},Zt=async({config:e})=>{let t,r,i,n,o=!e.site?.published_deploy;if(!(o?e.accountId:e.siteId))throw new Error(`No entity id for ${o?"account":"site"}`);let a=async()=>{clearTimeout(i),Ie.log("Requesting AI gateway information");let c=await(o?Jt(e.accountId,e.id,e.sessionId):Vt(e.siteId,e.id,e.sessionId));if({token:t,url:n}=c,r=c.expires_at?c.expires_at*1e3:void 0,Ie.log("Got AI gateway information",{token:!!t,expiresAt:r,url:n}),r){let u=r-Date.now()-6e4;u>0&&(i=setTimeout(()=>{a()},u))}};return await Promise.all([a(),We()]),{get url(){return n},get token(){return t},isModelAvailableForProvider:an}};import ne from"process";import se from"path";import Je from"fs";import{fileURLToPath as fn}from"url";import{createRequire as hn}from"module";import{execa as yn,execaCommand as mo}from"execa";import{Transform as ln}from"stream";function cn(){let e=process.env.NETLIFY_SENSITIVE_ENV_KEYS;return e?e.split(",").map(t=>t.trim()).filter(Boolean):[]}function un(e){let t=e.toLowerCase();return t==="true"||t==="false"?!0:e.trim().length<4}function dn(){let t=cn().map(r=>process.env[r]).filter(r=>!(!r||un(r)));return[...new Set(t)].sort((r,i)=>i.length-r.length)}function oe(e){if(typeof e!="string")return e;let t=dn();if(t.length===0)return e;let r=e;return t.forEach(i=>{let n=new RegExp(pn(i),"g");r=r.replace(n,"******")}),r}function pn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Se=class extends ln{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,i){let n=t.toString(),o=oe(n);i(null,o)}};function Qt(){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,o){let s=typeof i=="string"?oe(i):i;return typeof n=="function"?t(s,n):t(s,n,o)},process.stderr.write=function(i,n,o){let s=typeof i=="string"?oe(i):i;return typeof n=="function"?r(s,n):r(s,n,o)}}var Fe=null,er=e=>(Fe&&Fe.destroy(),Fe=new de({totalAllowedTime:e}),Fe),tr=()=>Fe;var de=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.`)}),o=null,s=null;i!==void 0&&(s=new Promise((a,l)=>{o=setTimeout(()=>{l(new Error(`${t} stage exceeded its maximum duration of ${i}ms`))},i)}));try{return s?await Promise.race([r(),s]):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 rr="netlify-agent-runner-context.md",gt="task-history",re=".netlify",fe="results.md",ft="assets";var nr="free";var he=1800*1e3,mn=["\\.claude","\\.gemini","\\.codex"],Ke=new RegExp(`(^|/)(${mn.join("|")})/skills/`),f={Environment:"environment",UserMessage:"user-message",AgentMessage:"agent-message",Task:"task",RunCommand:"run-command",Explore:"explore",Plan:"plan",FileRead:"file-read",FileWrite:"file-write",Notebook:"notebook",Web:"web",Todo:"todo",Reasoning:"reasoning",Skill:"skill",Memorize:"memorize",Deployment:"deployment",SiteGeneration:"site-generation"};var ir={name:"@netlify/agent-runner-cli",type:"module",version:"1.92.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","test:integration:skill-invocation":"vitest run test/integration/skill-invocation.test.ts","check:types":"tsc --noEmit",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.63","@anthropic-ai/sdk":"0.78.0","@google/gemini-cli":"0.31.0","@netlify/otel":"^5.1.5","@netlify/ts-cli":"^1.0.3","@openai/codex":"0.115.0","@opentelemetry/exporter-trace-otlp-grpc":"0.57.2",execa:"^9.6.1",minimist:"^1.2.8",openai:"6.26.0"}};var wn=fn(import.meta.url),_n=se.dirname(wn),En=hn(import.meta.url),ve=T("shell"),ht=new Set,xn={preferLocal:!0},P=(e,t,r)=>{let[i,n]=Tn(t,r),o={...xn,...n},s=yn(e,i,o);In(s,o),vn(s);let a=r?.idleTimeout;return a&&a>0&&Sn(s,a),s};var Tn=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},In=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(ne.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new Se).pipe(ne.stdout),e.stdout?.pipe(new Se).pipe(ne.stdout),e.stderr?.pipe(new Se).pipe(ne.stderr);return}e.stdout?.pipe(ne.stdout),e.stderr?.pipe(ne.stderr)},yt=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(ne.kill(-e.pid,t),ve.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return ve.error("Error killing process:",r),!1}},or=e=>yt(e,"SIGKILL"),Sn=(e,t)=>{let r=null,i=()=>{ve.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),yt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ve.log(`Force killing idle process ${e.pid}`),or(e))},5e3)},n=()=>{r&&clearTimeout(r),r=setTimeout(i,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)},vn=e=>{ht.add(e);let t=tr();if(t){let r=t.onTimesUp(()=>{ve.log(`Global timer expired, killing process ${e.pid}`),yt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ve.log(`Force killing process ${e.pid} after timeout`),or(e))},5e3)});e.on("exit",()=>{ht.delete(e),r()}),e.on("error",()=>{ht.delete(e),r()})}};function Ve(e,t){return!!ae(e,t)}function ae(e,t){if(!ne.env.NETLIFY_LOCAL_MODE)try{let n=En.resolve(ir.name),o=se.dirname(n);for(;o!==se.dirname(o);){let s=se.dirname(o);if(se.basename(s)==="node_modules"){let a=se.join(s,".bin",t);if(Je.existsSync(a))return a;break}o=s}}catch(n){console.error("Could not resolve package.json",n)}if(ne.env.NODE_PATH){let n=se.join(ne.env.NODE_PATH,".bin",t);if(Je.existsSync(n))return n}let r=se.join(e,"node_modules",".bin",t);if(Je.existsSync(r))return r;let i=se.join(_n,"..","node_modules",".bin",t);if(Je.existsSync(i))return i}var bn=T("utils"),Rn=e=>new Promise(t=>{setTimeout(t,e)}),ze=(e,t=3e3)=>{let r=!1,i=null,n=[],o=null,s=(...a)=>{if(r)return i=a,new Promise(u=>{n.push(u)});r=!0;let l,c=new Promise(u=>{l=u});return o=(async()=>{await Promise.resolve();let u=await e(...a);for(l(u);;){if(await Rn(t),!i)return r=!1,o=null,u;let d=i,p=n;i=null,n=[],u=await e(...d),p.forEach(g=>{g(u)})}})(),c};return s.flush=async()=>{if((r||i)&&o)return await o,s.flush()},s},be=(e,t,r=!1)=>{let i=null,n=null,o=null,s=function(...a){n=a,o=this;let l=r&&!i;clearTimeout(i),i=setTimeout(()=>{i=null,r||(e.apply(o,n),n=null,o=null)},t),l&&(e.apply(o,n),n=null,o=null)};return s.cancel=()=>{clearTimeout(i),i=null,n=null,o=null},s.flush=()=>{if(i){clearTimeout(i);let a=n,l=o;i=null,n=null,o=null,e.apply(l,a)}},s},sr=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(i){t&&(r?.error?r.error("Could not parse JSON",i):bn.error("Could not parse JSON",i))}},wt=e=>e.charAt(0).toUpperCase()+e.slice(1),pe=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():wt(t)).join(" ");function ye(e,t){t&&e.log(`Skill invoked: ${t}`)}var ar=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),lr=(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 l=60-a.length;if(l<=0)return"";if(l>=o.length+6){let c=Math.min(l-o.length,e.length);return`${o}${e.slice(0,c)}`}return e.slice(0,l)};var An=1e4,_t=(e,t=An)=>{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 cr}from"buffer";import Cn from"path";var ur=T("repo"),pr=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{ur.info("Getting runner diffs");let i=await Pn(r),{hasChanges:n}=i,{status:o}=i;if(!n)return{hasChanges:!1};if(!t){let _=$n(o);await On(_,r)}ur.info("Changes after processing"),await xt(r);let s=await Tt(o,r);if(await Et(s,r),n=await Nn(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await P("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},l=await P("git",["diff",e.runSha,"HEAD"],a),c=String(l.stdout??"");if(n=!!c,!n)return await dr(r),{hasChanges:!1,ignored:s};let u=await P("git",["diff",e.runSha,"HEAD","--binary"],a),d=String(u.stdout??""),p,g;if(e.sha){let _=await P("git",["diff",e.sha,"HEAD"],a);p=String(_.stdout??"");let x=await P("git",["diff",e.sha,"HEAD","--binary"],a),w=String(x.stdout??"");p!==w&&(g=cr.from(w).toString("base64"))}await dr(r);let I={hasChanges:!0,diff:c,resultDiff:p,ignored:s};return c!==d&&(I.diffBinary=cr.from(d).toString("base64")),g&&(I.resultDiffBinary=g),I},dr=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await P("git",["reset","--soft","HEAD~1"],{cwd:e})},Et=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await P("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},xt=async(e=process.cwd())=>{let t=await P("git",["status","-s"],{cwd:e});return String(t.stdout??"")},mr=/.. (.+)?\.log$/,kn=[mr],Pn=async(e=process.cwd())=>{let t=await xt(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
8
+ `);return o.length>e.length*.8?e:o}import{execSync as Qn}from"child_process";import kr from"fs/promises";import ei from"path";import _e from"process";import{getTracer as ti}from"@netlify/otel";import $e from"process";var te=class extends Error{constructor(r,i,n,o=!1){super(r);this.statusCode=i;this.userMessage=n;this.isCreditLimitExceeded=o;this.name="GracefulShutdownError"}},qe=e=>e instanceof te;var Be=$e.env.NETLIFY_API_URL,He=$e.env.NETLIFY_API_TOKEN,W=T("api"),Te=()=>$e.env.NETLIFY_LOCAL_MODE==="true",ue=async(e,t={})=>{if(!Be||!He)throw new Error("No API URL or token");let r=new URL(e,Be),i={...t,headers:{...t.headers,Authorization:`Bearer ${He}`}};$e.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),o=n.ok&&n.status<=299;if($e.env.AGENT_RUNNERS_DEBUG==="true")W.log(`Response headers for ${r}:`),n.headers.forEach((a,l)=>{W.log(` ${l}: ${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(o||W.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 s=await(n.headers.get("content-type")?.includes("application/json")?n.json():n.text());if(!o){let a=typeof s=="string"?s:JSON.stringify(s);throw n.status===404?new te(`API request failed: 404 - ${a}`,404,"The site associated with this agent run no longer exists."):n.status===503&&t.gracefulOn503&&a.toLowerCase().includes("usage exceeded")?new te(`API request failed: 503 - ${a}`,503,"Credit limit reached. Please add more credits to continue using Agent Runners.",!0):new Error(`API request failed: ${n.status} - ${a}`)}return s},Bt=e=>{W.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Be=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(He=e.constants.NETLIFY_API_TOKEN)},Ht=()=>({apiUrl:Be,token:He}),Oe=async(e,t)=>Te()?(W.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):ue(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),K=async(e,t,r)=>Te()?(W.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):ue(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var Wt=async e=>Te()?(W.log("Mock API: getSite called",{siteId:e}),{id:e,published_deploy:{id:"id"}}):ue(`/api/v1/sites/${e}`),Kt=async(e,t)=>Te()?(W.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):ue(`/api/v1/agent_runners/${e}/sessions/${t}`),Jt=(e,t,r)=>ue(`/api/v1/accounts/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),Vt=(e,t,r)=>ue(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),zt=async(e,t)=>Te()?(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"}}):ue(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),Xt=async(e,t)=>Te()?(W.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):ue(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),pt=async(e,t,{maxRetries:r=3,baseDelayMs:i=500}={})=>{W.log(`Uploading diff to S3: ${e.substring(0,50)}...`);for(let n=1;n<=r;n++)try{let o=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!o.ok)throw new Error(`S3 upload failed with status ${o.status}`);return o}catch(o){if(n===r)throw o;let s=i*2**(n-1);W.warn(`S3 upload attempt ${n}/${r} failed: ${o.message}. Retrying in ${s}ms...`),await new Promise(a=>setTimeout(a,s))}};var Ie=T("ai_gateway"),mt=null;var We=async()=>{if(mt)return mt;Ie.log("Fetching available AI gateway providers");let e=await fetch(`${Ht().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 mt=t,Ie.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},an=async(e,t)=>{let i=(await We()).providers[e];if(!i)return Ie.log(`Provider '${e}' not found`),!1;let n=i.models.includes(t);return Ie.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},Zt=async({config:e})=>{let t,r,i,n,o=!e.site?.published_deploy;if(!(o?e.accountId:e.siteId))throw new Error(`No entity id for ${o?"account":"site"}`);let a=async()=>{clearTimeout(i),Ie.log("Requesting AI gateway information");let c=await(o?Jt(e.accountId,e.id,e.sessionId):Vt(e.siteId,e.id,e.sessionId));if({token:t,url:n}=c,r=c.expires_at?c.expires_at*1e3:void 0,Ie.log("Got AI gateway information",{token:!!t,expiresAt:r,url:n}),r){let u=r-Date.now()-6e4;u>0&&(i=setTimeout(()=>{a()},u))}};return await Promise.all([a(),We()]),{get url(){return n},get token(){return t},isModelAvailableForProvider:an}};import ne from"process";import se from"path";import Je from"fs";import{fileURLToPath as fn}from"url";import{createRequire as hn}from"module";import{execa as yn,execaCommand as mo}from"execa";import{Transform as ln}from"stream";function cn(){let e=process.env.NETLIFY_SENSITIVE_ENV_KEYS;return e?e.split(",").map(t=>t.trim()).filter(Boolean):[]}function un(e){let t=e.toLowerCase();return t==="true"||t==="false"?!0:e.trim().length<4}function dn(){let t=cn().map(r=>process.env[r]).filter(r=>!(!r||un(r)));return[...new Set(t)].sort((r,i)=>i.length-r.length)}function oe(e){if(typeof e!="string")return e;let t=dn();if(t.length===0)return e;let r=e;return t.forEach(i=>{let n=new RegExp(pn(i),"g");r=r.replace(n,"******")}),r}function pn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Se=class extends ln{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,i){let n=t.toString(),o=oe(n);i(null,o)}};function Qt(){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,o){let s=typeof i=="string"?oe(i):i;return typeof n=="function"?t(s,n):t(s,n,o)},process.stderr.write=function(i,n,o){let s=typeof i=="string"?oe(i):i;return typeof n=="function"?r(s,n):r(s,n,o)}}var Fe=null,er=e=>(Fe&&Fe.destroy(),Fe=new de({totalAllowedTime:e}),Fe),tr=()=>Fe;var de=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.`)}),o=null,s=null;i!==void 0&&(s=new Promise((a,l)=>{o=setTimeout(()=>{l(new Error(`${t} stage exceeded its maximum duration of ${i}ms`))},i)}));try{return s?await Promise.race([r(),s]):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 rr="netlify-agent-runner-context.md",gt="task-history",re=".netlify",fe="results.md",ft="assets";var nr="free";var he=1800*1e3,mn=["\\.claude","\\.gemini","\\.codex"],Ke=new RegExp(`(^|/)(${mn.join("|")})/skills/`),f={Environment:"environment",UserMessage:"user-message",AgentMessage:"agent-message",Task:"task",RunCommand:"run-command",Explore:"explore",Plan:"plan",FileRead:"file-read",FileWrite:"file-write",Notebook:"notebook",Web:"web",Todo:"todo",Reasoning:"reasoning",Skill:"skill",Memorize:"memorize",Deployment:"deployment",SiteGeneration:"site-generation"};var ir={name:"@netlify/agent-runner-cli",type:"module",version:"1.92.4",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","test:integration:skill-invocation":"vitest run test/integration/skill-invocation.test.ts","check:types":"tsc --noEmit",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.63","@anthropic-ai/sdk":"0.78.0","@google/gemini-cli":"0.31.0","@netlify/otel":"^5.1.5","@netlify/ts-cli":"^1.0.3","@openai/codex":"0.115.0","@opentelemetry/exporter-trace-otlp-grpc":"0.57.2",execa:"^9.6.1",minimist:"^1.2.8",openai:"6.26.0"}};var wn=fn(import.meta.url),_n=se.dirname(wn),En=hn(import.meta.url),ve=T("shell"),ht=new Set,xn={preferLocal:!0},P=(e,t,r)=>{let[i,n]=Tn(t,r),o={...xn,...n},s=yn(e,i,o);In(s,o),vn(s);let a=r?.idleTimeout;return a&&a>0&&Sn(s,a),s};var Tn=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},In=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(ne.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new Se).pipe(ne.stdout),e.stdout?.pipe(new Se).pipe(ne.stdout),e.stderr?.pipe(new Se).pipe(ne.stderr);return}e.stdout?.pipe(ne.stdout),e.stderr?.pipe(ne.stderr)},yt=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(ne.kill(-e.pid,t),ve.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return ve.error("Error killing process:",r),!1}},or=e=>yt(e,"SIGKILL"),Sn=(e,t)=>{let r=null,i=()=>{ve.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),yt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ve.log(`Force killing idle process ${e.pid}`),or(e))},5e3)},n=()=>{r&&clearTimeout(r),r=setTimeout(i,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)},vn=e=>{ht.add(e);let t=tr();if(t){let r=t.onTimesUp(()=>{ve.log(`Global timer expired, killing process ${e.pid}`),yt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ve.log(`Force killing process ${e.pid} after timeout`),or(e))},5e3)});e.on("exit",()=>{ht.delete(e),r()}),e.on("error",()=>{ht.delete(e),r()})}};function Ve(e,t){return!!ae(e,t)}function ae(e,t){if(!ne.env.NETLIFY_LOCAL_MODE)try{let n=En.resolve(ir.name),o=se.dirname(n);for(;o!==se.dirname(o);){let s=se.dirname(o);if(se.basename(s)==="node_modules"){let a=se.join(s,".bin",t);if(Je.existsSync(a))return a;break}o=s}}catch(n){console.error("Could not resolve package.json",n)}if(ne.env.NODE_PATH){let n=se.join(ne.env.NODE_PATH,".bin",t);if(Je.existsSync(n))return n}let r=se.join(e,"node_modules",".bin",t);if(Je.existsSync(r))return r;let i=se.join(_n,"..","node_modules",".bin",t);if(Je.existsSync(i))return i}var bn=T("utils"),Rn=e=>new Promise(t=>{setTimeout(t,e)}),ze=(e,t=3e3)=>{let r=!1,i=null,n=[],o=null,s=(...a)=>{if(r)return i=a,new Promise(u=>{n.push(u)});r=!0;let l,c=new Promise(u=>{l=u});return o=(async()=>{await Promise.resolve();let u=await e(...a);for(l(u);;){if(await Rn(t),!i)return r=!1,o=null,u;let d=i,p=n;i=null,n=[],u=await e(...d),p.forEach(g=>{g(u)})}})(),c};return s.flush=async()=>{if((r||i)&&o)return await o,s.flush()},s},be=(e,t,r=!1)=>{let i=null,n=null,o=null,s=function(...a){n=a,o=this;let l=r&&!i;clearTimeout(i),i=setTimeout(()=>{i=null,r||(e.apply(o,n),n=null,o=null)},t),l&&(e.apply(o,n),n=null,o=null)};return s.cancel=()=>{clearTimeout(i),i=null,n=null,o=null},s.flush=()=>{if(i){clearTimeout(i);let a=n,l=o;i=null,n=null,o=null,e.apply(l,a)}},s},sr=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(i){t&&(r?.error?r.error("Could not parse JSON",i):bn.error("Could not parse JSON",i))}},wt=e=>e.charAt(0).toUpperCase()+e.slice(1),pe=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():wt(t)).join(" ");function ye(e,t){t&&e.log(`Skill invoked: ${t}`)}var ar=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),lr=(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 l=60-a.length;if(l<=0)return"";if(l>=o.length+6){let c=Math.min(l-o.length,e.length);return`${o}${e.slice(0,c)}`}return e.slice(0,l)};var An=1e4,_t=(e,t=An)=>{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 cr}from"buffer";import Cn from"path";var ur=T("repo"),pr=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{ur.info("Getting runner diffs");let i=await Pn(r),{hasChanges:n}=i,{status:o}=i;if(!n)return{hasChanges:!1};if(!t){let _=$n(o);await On(_,r)}ur.info("Changes after processing"),await xt(r);let s=await Tt(o,r);if(await Et(s,r),n=await Nn(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await P("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},l=await P("git",["diff",e.runSha,"HEAD"],a),c=String(l.stdout??"");if(n=!!c,!n)return await dr(r),{hasChanges:!1,ignored:s};let u=await P("git",["diff",e.runSha,"HEAD","--binary"],a),d=String(u.stdout??""),p,g;if(e.sha){let _=await P("git",["diff",e.sha,"HEAD"],a);p=String(_.stdout??"");let x=await P("git",["diff",e.sha,"HEAD","--binary"],a),w=String(x.stdout??"");p!==w&&(g=cr.from(w).toString("base64"))}await dr(r);let I={hasChanges:!0,diff:c,resultDiff:p,ignored:s};return c!==d&&(I.diffBinary=cr.from(d).toString("base64")),g&&(I.resultDiffBinary=g),I},dr=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await P("git",["reset","--soft","HEAD~1"],{cwd:e})},Et=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await P("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},xt=async(e=process.cwd())=>{let t=await P("git",["status","-s"],{cwd:e});return String(t.stdout??"")},mr=/.. (.+)?\.log$/,kn=[mr],Pn=async(e=process.cwd())=>{let t=await xt(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
9
9
  `).filter(n=>kn.some(s=>s instanceof RegExp?s.test(n):n===s)?!1:n[1]?.trim()!=="")).length!==0,status:t}},Nn=async(e=process.cwd())=>{try{return await P("git",["diff","--staged","--quiet"],{cwd:e}),!1}catch{return!0}},Le=async(e=process.cwd())=>{let{stdout:t}=await P("git",["rev-parse","HEAD"],{cwd:e});return String(t??"").trim()},gr=async(e=process.cwd())=>{let{stdout:t}=await P("git",["rev-list","--max-parents=0","HEAD"],{cwd:e});return String(t??"").trim()},Tt=async(e,t=process.cwd())=>{e||=await xt(t);let r=[".netlify","node_modules","dist",".next","out",".nuxt",".output",".cache",".turbo",".parcel-cache","coverage",".nyc_output","storybook-static","public/build","CLAUDE.local.md"],i=[];return e.split(`
10
10
  `).forEach(n=>{r.forEach(s=>{let a=n===`?? ${s}`,l=n.startsWith(`?? ${s}/`)||n.startsWith(`?? ${s}${Cn.sep}`);(a||l)&&i.push(`:!${s}`)});let o=n.match(mr)?.[1];o&&i.push(`:!${o}.log`)}),i},It=async(e=process.cwd())=>{await P("git",["reset","--hard","HEAD"],{cwd:e})},$n=e=>{let t=e.split(`
11
11
  `).reduce((r,i)=>{if(!i)return r;let[n,o,,...s]=i,a=s.join(""),l=n.trim(),c=o.trim();return r[a]?r[a].change=c:r[a]={filePath:a,stage:l,change:c},r},{});return Object.values(t)},On=async(e,t=process.cwd())=>{let r=e.filter(i=>i.stage&&!i.change).map(i=>i.filePath);r.length!==0&&await P("git",["restore","--staged","--worktree","--pathspec-from-file=-"],{cwd:t,input:r.join(`
@@ -173,7 +173,7 @@ Deploy failed failed. Here are the errors to review on the latest build:
173
173
  Below are all of the logs with potential issues that we extracted. Some of them may be false positives, discern them carefully and ensure fixes are relevant.
174
174
 
175
175
  ${e.pop()}
176
- `;import wi from"process";import{getTracer as Ot}from"@netlify/otel";import{getTracer as hi}from"@netlify/otel";var Ge=T("deploy"),Lr=async e=>await $(hi(),"create-preview-deploy",async t=>yi(e,t)),yi=async({netlify:e,hasRepo:t,skipBuild:r,message:i="Agent Preview",deploySubdomain:n,cliPath:o,filter:s,prodDeploy:a},l)=>{try{let c=["deploy","--message",`"${i}"`,"--json","--verbose",a?"--prod":"--draft"];t||(Ge.log("Deploy: Uploading source zip"),c.push("--upload-source-zip")),n&&!a&&c.push("--alias",n),s&&c.push("--filter",s),r?(Ge.log("Deploy: Skipping build"),c.push("--no-build")):c.push("--context",a?"production":"deploy-preview");let u=o||"netlify";Ge.log(`Running: ${u} ${c.join(" ")}`),l?.setAttributes({cmd:u,args:c});let d=await e.utils.run(u,c,{stdio:["ignore","pipe","pipe"]}),p=JSON.parse(String(d.stdout??"").trim());l?.setAttributes({success:!0,deployId:p.deploy_id,deployUrl:p.deploy_url,siteId:p.site_id}),Ge.log(`
176
+ `;import wi from"process";import{getTracer as Ot}from"@netlify/otel";import{getTracer as hi}from"@netlify/otel";var Ge=T("deploy"),Lr=async e=>await $(hi(),"create-preview-deploy",async t=>yi(e,t)),yi=async({netlify:e,hasRepo:t,skipBuild:r,message:i="Agent Preview",deploySubdomain:n,cliPath:o,filter:s,prodDeploy:a},l)=>{try{let c=["deploy","--message",`"${i}"`,"--json","--verbose",a?"--prod":"--draft"];Ge.log("Deploy: Uploading source zip"),c.push("--upload-source-zip"),n&&!a&&c.push("--alias",n),s&&c.push("--filter",s),r?(Ge.log("Deploy: Skipping build"),c.push("--no-build")):c.push("--context",a?"production":"deploy-preview");let u=o||"netlify";Ge.log(`Running: ${u} ${c.join(" ")}`),l?.setAttributes({cmd:u,args:c});let d=await e.utils.run(u,c,{stdio:["ignore","pipe","pipe"]}),p=JSON.parse(String(d.stdout??"").trim());l?.setAttributes({success:!0,deployId:p.deploy_id,deployUrl:p.deploy_url,siteId:p.site_id}),Ge.log(`
177
177
  Preview deploy created successfully:`,{deployId:p.deploy_id,deployUrl:p.deploy_url,siteId:p.site_id});let g={deployId:p.deploy_id,previewUrl:p.deploy_url,logsUrl:p.logs,siteId:p.site_id};return t||(g.sourceZipFilename=p.source_zip_filename),g}catch(c){throw Ge.error("Failed to create preview deploy via CLI:",c),l?.setAttributes({success:!1,error:c.message}),c}};var Dr=e=>["dtn-prod-iteration","create"].includes(e);var ot=class{scanDiffForForms(t){let r=[],i=null,n=[],o=t.split(`
178
178
  `);for(let s of o)if(s.startsWith("diff --git")){if(i&&n.length>0){let l=this.containsNetlifyForm(n,i);l&&r.push(l)}let a=s.split(" ");i=a[a.length-1].replace(/^b\//,""),n=[],Ke.test(i)&&(i=null)}else s.startsWith("+")&&!s.startsWith("+++")&&n.push(s.slice(1));if(i&&n.length>0){let s=this.containsNetlifyForm(n,i);s&&r.push(s)}return{detected:r.length>0,matches:r}}containsNetlifyForm(t,r){let i=t.join(`
179
179
  `),n=[{pattern:/<[\w-]*form[\s\S]*?(data-)?netlify/i,name:"standard form element"},{pattern:/<[A-Z][\w]*[\s\S]*?component\s*=\s*["']form["'][\s\S]*?(data-)?netlify/i,name:"component with form prop"}];for(let{pattern:o,name:s}of n){let a=i.match(o);if(a){let l=a.index||0,c=Math.max(0,l-20),u=Math.min(i.length,l+a[0].length+20),d=i.slice(c,u).trim();return d=d.replace(/\s+/g," "),d.length>100&&(d=d.slice(0,97)+"..."),{file:r,snippet:`[${s}] ${d}`}}}return null}};var st=class{scanDiffForIdentity(t){let r=[],i=null,n=[],o=t.split(`
package/dist/bin.js CHANGED
@@ -5,7 +5,7 @@ import jt from"process";import Ko from"minimist";import{createRequire as Lo}from
5
5
  ${s}
6
6
  </extracted_error_chunk>`).join(`
7
7
 
8
- `);return i.length>e.length*.8?e:i}import{execSync as oo}from"child_process";import Lr from"fs/promises";import io from"path";import ye from"process";import{getTracer as so}from"@netlify/otel";import Ne from"process";var Q=class extends Error{constructor(r,o,n,i=!1){super(r);this.statusCode=o;this.userMessage=n;this.isCreditLimitExceeded=i;this.name="GracefulShutdownError"}},Ye=e=>e instanceof Q;var qe=Ne.env.NETLIFY_API_URL,Be=Ne.env.NETLIFY_API_TOKEN,H=I("api"),we=()=>Ne.env.NETLIFY_LOCAL_MODE==="true",ae=async(e,t={})=>{if(!qe||!Be)throw new Error("No API URL or token");let r=new URL(e,qe),o={...t,headers:{...t.headers,Authorization:`Bearer ${Be}`}};Ne.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(Ne.env.AGENT_RUNNERS_DEBUG==="true")H.log(`Response headers for ${r}:`),n.headers.forEach((a,l)=>{H.log(` ${l}: ${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 Q(`API request failed: 404 - ${a}`,404,"The site associated with this agent run no longer exists."):n.status===503&&t.gracefulOn503&&a.toLowerCase().includes("usage exceeded")?new Q(`API request failed: 503 - ${a}`,503,"Credit limit reached. Please add more credits to continue using Agent Runners.",!0):new Error(`API request failed: ${n.status} - ${a}`)}return s},Kt=e=>{H.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(qe=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(Be=e.constants.NETLIFY_API_TOKEN)},Vt=()=>({apiUrl:qe,token:Be}),Oe=async(e,t)=>we()?(H.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):ae(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),W=async(e,t,r)=>we()?(H.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):ae(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var Jt=async e=>we()?(H.log("Mock API: getSite called",{siteId:e}),{id:e,published_deploy:{id:"id"}}):ae(`/api/v1/sites/${e}`),zt=async(e,t)=>we()?(H.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):ae(`/api/v1/agent_runners/${e}/sessions/${t}`),Xt=(e,t,r)=>ae(`/api/v1/accounts/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),Zt=(e,t,r)=>ae(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),Qt=async(e,t)=>we()?(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"}}):ae(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),er=async(e,t)=>we()?(H.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):ae(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),dt=async(e,t,{maxRetries:r=3,baseDelayMs:o=500}={})=>{H.log(`Uploading diff to S3: ${e.substring(0,50)}...`);for(let n=1;n<=r;n++)try{let i=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!i.ok)throw new Error(`S3 upload failed with status ${i.status}`);return i}catch(i){if(n===r)throw i;let s=o*2**(n-1);H.warn(`S3 upload attempt ${n}/${r} failed: ${i.message}. Retrying in ${s}ms...`),await new Promise(a=>setTimeout(a,s))}};var Te=I("ai_gateway"),pt=null;var He=async()=>{if(pt)return pt;Te.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 pt=t,Te.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},pn=async(e,t)=>{let o=(await He()).providers[e];if(!o)return Te.log(`Provider '${e}' not found`),!1;let n=o.models.includes(t);return Te.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},tr=async({config:e})=>{let t,r,o,n,i=!e.site?.published_deploy;if(!(i?e.accountId:e.siteId))throw new Error(`No entity id for ${i?"account":"site"}`);let a=async()=>{clearTimeout(o),Te.log("Requesting AI gateway information");let c=await(i?Xt(e.accountId,e.id,e.sessionId):Zt(e.siteId,e.id,e.sessionId));if({token:t,url:n}=c,r=c.expires_at?c.expires_at*1e3:void 0,Te.log("Got AI gateway information",{token:!!t,expiresAt:r,url:n}),r){let d=r-Date.now()-6e4;d>0&&(o=setTimeout(()=>{a()},d))}};return await Promise.all([a(),He()]),{get url(){return n},get token(){return t},isModelAvailableForProvider:pn}};import te from"process";import oe from"path";import Ke from"fs";import{fileURLToPath as wn}from"url";import{createRequire as Tn}from"module";import{execa as xn,execaCommand as vi}from"execa";import{Transform as mn}from"stream";function gn(){let e=process.env.NETLIFY_SENSITIVE_ENV_KEYS;return e?e.split(",").map(t=>t.trim()).filter(Boolean):[]}function fn(e){let t=e.toLowerCase();return t==="true"||t==="false"?!0:e.trim().length<4}function hn(){let t=gn().map(r=>process.env[r]).filter(r=>!(!r||fn(r)));return[...new Set(t)].sort((r,o)=>o.length-r.length)}function ne(e){if(typeof e!="string")return e;let t=hn();if(t.length===0)return e;let r=e;return t.forEach(o=>{let n=new RegExp(yn(o),"g");r=r.replace(n,"******")}),r}function yn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var xe=class extends mn{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,o){let n=t.toString(),i=ne(n);o(null,i)}};function rr(){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"?ne(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"?ne(o):o;return typeof n=="function"?r(s,n):r(s,n,i)}}var $e=null,nr=e=>($e&&$e.destroy(),$e=new le({totalAllowedTime:e}),$e),or=()=>$e;var le=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,l)=>{i=setTimeout(()=>{l(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 ir="netlify-agent-runner-context.md",mt="task-history",ee=".netlify",me="results.md",gt="assets",ft="other",ht="personal";var yt="enterprise",Fe="free",sr=[ht,"pro",yt,Fe],ar=["normal","redeploy","create","ask","dtn-prod-iteration","rebase"],lr="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.",ge=1800*1e3,_n=["\\.claude","\\.gemini","\\.codex"],We=new RegExp(`(^|/)(${_n.join("|")})/skills/`),f={Environment:"environment",UserMessage:"user-message",AgentMessage:"agent-message",Task:"task",RunCommand:"run-command",Explore:"explore",Plan:"plan",FileRead:"file-read",FileWrite:"file-write",Notebook:"notebook",Web:"web",Todo:"todo",Reasoning:"reasoning",Skill:"skill",Memorize:"memorize",Deployment:"deployment",SiteGeneration:"site-generation"};var cr={name:"@netlify/agent-runner-cli",type:"module",version:"1.92.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","test:integration:skill-invocation":"vitest run test/integration/skill-invocation.test.ts","check:types":"tsc --noEmit",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.63","@anthropic-ai/sdk":"0.78.0","@google/gemini-cli":"0.31.0","@netlify/otel":"^5.1.5","@netlify/ts-cli":"^1.0.3","@openai/codex":"0.115.0","@opentelemetry/exporter-trace-otlp-grpc":"0.57.2",execa:"^9.6.1",minimist:"^1.2.8",openai:"6.26.0"}};var In=wn(import.meta.url),Sn=oe.dirname(In),vn=Tn(import.meta.url),Ie=I("shell"),_t=new Set,Rn={preferLocal:!0},O=(e,t,r)=>{let[o,n]=An(t,r),i={...Rn,...n},s=xn(e,o,i);bn(s,i),Pn(s);let a=r?.idleTimeout;return a&&a>0&&Cn(s,a),s};var An=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},bn=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(te.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new xe).pipe(te.stdout),e.stdout?.pipe(new xe).pipe(te.stdout),e.stderr?.pipe(new xe).pipe(te.stderr);return}e.stdout?.pipe(te.stdout),e.stderr?.pipe(te.stderr)},Et=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(te.kill(-e.pid,t),Ie.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return Ie.error("Error killing process:",r),!1}},ur=e=>Et(e,"SIGKILL"),Cn=(e,t)=>{let r=null,o=()=>{Ie.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),Et(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(Ie.log(`Force killing idle process ${e.pid}`),ur(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)},Pn=e=>{_t.add(e);let t=or();if(t){let r=t.onTimesUp(()=>{Ie.log(`Global timer expired, killing process ${e.pid}`),Et(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(Ie.log(`Force killing process ${e.pid} after timeout`),ur(e))},5e3)});e.on("exit",()=>{_t.delete(e),r()}),e.on("error",()=>{_t.delete(e),r()})}};function ce(e,t){if(!te.env.NETLIFY_LOCAL_MODE)try{let n=vn.resolve(cr.name),i=oe.dirname(n);for(;i!==oe.dirname(i);){let s=oe.dirname(i);if(oe.basename(s)==="node_modules"){let a=oe.join(s,".bin",t);if(Ke.existsSync(a))return a;break}i=s}}catch(n){console.error("Could not resolve package.json",n)}if(te.env.NODE_PATH){let n=oe.join(te.env.NODE_PATH,".bin",t);if(Ke.existsSync(n))return n}let r=oe.join(e,"node_modules",".bin",t);if(Ke.existsSync(r))return r;let o=oe.join(Sn,"..","node_modules",".bin",t);if(Ke.existsSync(o))return o}var dr=I("utils"),kn=e=>new Promise(t=>{setTimeout(t,e)}),Ve=(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 l,c=new Promise(d=>{l=d});return i=(async()=>{await Promise.resolve();let d=await e(...a);for(l(d);;){if(await kn(t),!o)return r=!1,i=null,d;let u=o,p=n;o=null,n=[],d=await e(...u),p.forEach(g=>{g(d)})}})(),c};return s.flush=async()=>{if((r||o)&&i)return await i,s.flush()},s},Se=(e,t,r=!1)=>{let o=null,n=null,i=null,s=function(...a){n=a,i=this;let l=r&&!o;clearTimeout(o),o=setTimeout(()=>{o=null,r||(e.apply(i,n),n=null,i=null)},t),l&&(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,l=i;o=null,n=null,i=null,e.apply(l,a)}},s},Je=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(o){t&&(r?.error?r.error("Could not parse JSON",o):dr.error("Could not parse JSON",o))}},wt=e=>e.charAt(0).toUpperCase()+e.slice(1),ue=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():wt(t)).join(" ");function fe(e,t){t&&e.log(`Skill invoked: ${t}`)}var pr=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),mr=(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 l=60-a.length;if(l<=0)return"";if(l>=i.length+6){let c=Math.min(l-i.length,e.length);return`${i}${e.slice(0,c)}`}return e.slice(0,l)},Nn=e=>!e||typeof e!="object"||Array.isArray(e)||Object.keys(e).length===0?!1:!!sr.some(t=>t in e),gr=()=>{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);Nn(i)&&(e[r]=i)}catch(i){let a=i instanceof SyntaxError?"Invalid JSON":i.message;dr.error(`Could not parse ${r} model version override from ${n}: ${a}`)}}}),e},On=1e4,Tt=(e,t=On)=>{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 fr}from"buffer";import $n from"path";var hr=I("repo"),_r=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{hr.info("Getting runner diffs");let o=await Ln(r),{hasChanges:n}=o,{status:i}=o;if(!n)return{hasChanges:!1};if(!t){let E=Mn(i);await Un(E,r)}hr.info("Changes after processing"),await It(r);let s=await vt(i,r);if(await xt(s,r),n=await Dn(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await O("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},l=await O("git",["diff",e.runSha,"HEAD"],a),c=String(l.stdout??"");if(n=!!c,!n)return await yr(r),{hasChanges:!1,ignored:s};let d=await O("git",["diff",e.runSha,"HEAD","--binary"],a),u=String(d.stdout??""),p,g;if(e.sha){let E=await O("git",["diff",e.sha,"HEAD"],a);p=String(E.stdout??"");let T=await O("git",["diff",e.sha,"HEAD","--binary"],a),y=String(T.stdout??"");p!==y&&(g=fr.from(y).toString("base64"))}await yr(r);let S={hasChanges:!0,diff:c,resultDiff:p,ignored:s};return c!==u&&(S.diffBinary=fr.from(u).toString("base64")),g&&(S.resultDiffBinary=g),S},yr=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await O("git",["reset","--soft","HEAD~1"],{cwd:e})},xt=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await O("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},It=async(e=process.cwd())=>{let t=await O("git",["status","-s"],{cwd:e});return String(t.stdout??"")},Er=/.. (.+)?\.log$/,Fn=[Er],Ln=async(e=process.cwd())=>{let t=await It(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
8
+ `);return i.length>e.length*.8?e:i}import{execSync as oo}from"child_process";import Lr from"fs/promises";import io from"path";import ye from"process";import{getTracer as so}from"@netlify/otel";import Ne from"process";var Q=class extends Error{constructor(r,o,n,i=!1){super(r);this.statusCode=o;this.userMessage=n;this.isCreditLimitExceeded=i;this.name="GracefulShutdownError"}},Ye=e=>e instanceof Q;var qe=Ne.env.NETLIFY_API_URL,Be=Ne.env.NETLIFY_API_TOKEN,H=I("api"),we=()=>Ne.env.NETLIFY_LOCAL_MODE==="true",ae=async(e,t={})=>{if(!qe||!Be)throw new Error("No API URL or token");let r=new URL(e,qe),o={...t,headers:{...t.headers,Authorization:`Bearer ${Be}`}};Ne.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(Ne.env.AGENT_RUNNERS_DEBUG==="true")H.log(`Response headers for ${r}:`),n.headers.forEach((a,l)=>{H.log(` ${l}: ${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 Q(`API request failed: 404 - ${a}`,404,"The site associated with this agent run no longer exists."):n.status===503&&t.gracefulOn503&&a.toLowerCase().includes("usage exceeded")?new Q(`API request failed: 503 - ${a}`,503,"Credit limit reached. Please add more credits to continue using Agent Runners.",!0):new Error(`API request failed: ${n.status} - ${a}`)}return s},Kt=e=>{H.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(qe=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(Be=e.constants.NETLIFY_API_TOKEN)},Vt=()=>({apiUrl:qe,token:Be}),Oe=async(e,t)=>we()?(H.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):ae(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),W=async(e,t,r)=>we()?(H.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):ae(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var Jt=async e=>we()?(H.log("Mock API: getSite called",{siteId:e}),{id:e,published_deploy:{id:"id"}}):ae(`/api/v1/sites/${e}`),zt=async(e,t)=>we()?(H.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):ae(`/api/v1/agent_runners/${e}/sessions/${t}`),Xt=(e,t,r)=>ae(`/api/v1/accounts/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),Zt=(e,t,r)=>ae(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),Qt=async(e,t)=>we()?(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"}}):ae(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),er=async(e,t)=>we()?(H.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):ae(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),dt=async(e,t,{maxRetries:r=3,baseDelayMs:o=500}={})=>{H.log(`Uploading diff to S3: ${e.substring(0,50)}...`);for(let n=1;n<=r;n++)try{let i=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!i.ok)throw new Error(`S3 upload failed with status ${i.status}`);return i}catch(i){if(n===r)throw i;let s=o*2**(n-1);H.warn(`S3 upload attempt ${n}/${r} failed: ${i.message}. Retrying in ${s}ms...`),await new Promise(a=>setTimeout(a,s))}};var Te=I("ai_gateway"),pt=null;var He=async()=>{if(pt)return pt;Te.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 pt=t,Te.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},pn=async(e,t)=>{let o=(await He()).providers[e];if(!o)return Te.log(`Provider '${e}' not found`),!1;let n=o.models.includes(t);return Te.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},tr=async({config:e})=>{let t,r,o,n,i=!e.site?.published_deploy;if(!(i?e.accountId:e.siteId))throw new Error(`No entity id for ${i?"account":"site"}`);let a=async()=>{clearTimeout(o),Te.log("Requesting AI gateway information");let c=await(i?Xt(e.accountId,e.id,e.sessionId):Zt(e.siteId,e.id,e.sessionId));if({token:t,url:n}=c,r=c.expires_at?c.expires_at*1e3:void 0,Te.log("Got AI gateway information",{token:!!t,expiresAt:r,url:n}),r){let d=r-Date.now()-6e4;d>0&&(o=setTimeout(()=>{a()},d))}};return await Promise.all([a(),He()]),{get url(){return n},get token(){return t},isModelAvailableForProvider:pn}};import te from"process";import oe from"path";import Ke from"fs";import{fileURLToPath as wn}from"url";import{createRequire as Tn}from"module";import{execa as xn,execaCommand as vi}from"execa";import{Transform as mn}from"stream";function gn(){let e=process.env.NETLIFY_SENSITIVE_ENV_KEYS;return e?e.split(",").map(t=>t.trim()).filter(Boolean):[]}function fn(e){let t=e.toLowerCase();return t==="true"||t==="false"?!0:e.trim().length<4}function hn(){let t=gn().map(r=>process.env[r]).filter(r=>!(!r||fn(r)));return[...new Set(t)].sort((r,o)=>o.length-r.length)}function ne(e){if(typeof e!="string")return e;let t=hn();if(t.length===0)return e;let r=e;return t.forEach(o=>{let n=new RegExp(yn(o),"g");r=r.replace(n,"******")}),r}function yn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var xe=class extends mn{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,o){let n=t.toString(),i=ne(n);o(null,i)}};function rr(){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"?ne(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"?ne(o):o;return typeof n=="function"?r(s,n):r(s,n,i)}}var $e=null,nr=e=>($e&&$e.destroy(),$e=new le({totalAllowedTime:e}),$e),or=()=>$e;var le=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,l)=>{i=setTimeout(()=>{l(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 ir="netlify-agent-runner-context.md",mt="task-history",ee=".netlify",me="results.md",gt="assets",ft="other",ht="personal";var yt="enterprise",Fe="free",sr=[ht,"pro",yt,Fe],ar=["normal","redeploy","create","ask","dtn-prod-iteration","rebase"],lr="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.",ge=1800*1e3,_n=["\\.claude","\\.gemini","\\.codex"],We=new RegExp(`(^|/)(${_n.join("|")})/skills/`),f={Environment:"environment",UserMessage:"user-message",AgentMessage:"agent-message",Task:"task",RunCommand:"run-command",Explore:"explore",Plan:"plan",FileRead:"file-read",FileWrite:"file-write",Notebook:"notebook",Web:"web",Todo:"todo",Reasoning:"reasoning",Skill:"skill",Memorize:"memorize",Deployment:"deployment",SiteGeneration:"site-generation"};var cr={name:"@netlify/agent-runner-cli",type:"module",version:"1.92.4",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","test:integration:skill-invocation":"vitest run test/integration/skill-invocation.test.ts","check:types":"tsc --noEmit",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.63","@anthropic-ai/sdk":"0.78.0","@google/gemini-cli":"0.31.0","@netlify/otel":"^5.1.5","@netlify/ts-cli":"^1.0.3","@openai/codex":"0.115.0","@opentelemetry/exporter-trace-otlp-grpc":"0.57.2",execa:"^9.6.1",minimist:"^1.2.8",openai:"6.26.0"}};var In=wn(import.meta.url),Sn=oe.dirname(In),vn=Tn(import.meta.url),Ie=I("shell"),_t=new Set,Rn={preferLocal:!0},O=(e,t,r)=>{let[o,n]=An(t,r),i={...Rn,...n},s=xn(e,o,i);bn(s,i),Pn(s);let a=r?.idleTimeout;return a&&a>0&&Cn(s,a),s};var An=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},bn=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(te.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new xe).pipe(te.stdout),e.stdout?.pipe(new xe).pipe(te.stdout),e.stderr?.pipe(new xe).pipe(te.stderr);return}e.stdout?.pipe(te.stdout),e.stderr?.pipe(te.stderr)},Et=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(te.kill(-e.pid,t),Ie.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return Ie.error("Error killing process:",r),!1}},ur=e=>Et(e,"SIGKILL"),Cn=(e,t)=>{let r=null,o=()=>{Ie.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),Et(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(Ie.log(`Force killing idle process ${e.pid}`),ur(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)},Pn=e=>{_t.add(e);let t=or();if(t){let r=t.onTimesUp(()=>{Ie.log(`Global timer expired, killing process ${e.pid}`),Et(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(Ie.log(`Force killing process ${e.pid} after timeout`),ur(e))},5e3)});e.on("exit",()=>{_t.delete(e),r()}),e.on("error",()=>{_t.delete(e),r()})}};function ce(e,t){if(!te.env.NETLIFY_LOCAL_MODE)try{let n=vn.resolve(cr.name),i=oe.dirname(n);for(;i!==oe.dirname(i);){let s=oe.dirname(i);if(oe.basename(s)==="node_modules"){let a=oe.join(s,".bin",t);if(Ke.existsSync(a))return a;break}i=s}}catch(n){console.error("Could not resolve package.json",n)}if(te.env.NODE_PATH){let n=oe.join(te.env.NODE_PATH,".bin",t);if(Ke.existsSync(n))return n}let r=oe.join(e,"node_modules",".bin",t);if(Ke.existsSync(r))return r;let o=oe.join(Sn,"..","node_modules",".bin",t);if(Ke.existsSync(o))return o}var dr=I("utils"),kn=e=>new Promise(t=>{setTimeout(t,e)}),Ve=(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 l,c=new Promise(d=>{l=d});return i=(async()=>{await Promise.resolve();let d=await e(...a);for(l(d);;){if(await kn(t),!o)return r=!1,i=null,d;let u=o,p=n;o=null,n=[],d=await e(...u),p.forEach(g=>{g(d)})}})(),c};return s.flush=async()=>{if((r||o)&&i)return await i,s.flush()},s},Se=(e,t,r=!1)=>{let o=null,n=null,i=null,s=function(...a){n=a,i=this;let l=r&&!o;clearTimeout(o),o=setTimeout(()=>{o=null,r||(e.apply(i,n),n=null,i=null)},t),l&&(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,l=i;o=null,n=null,i=null,e.apply(l,a)}},s},Je=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(o){t&&(r?.error?r.error("Could not parse JSON",o):dr.error("Could not parse JSON",o))}},wt=e=>e.charAt(0).toUpperCase()+e.slice(1),ue=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():wt(t)).join(" ");function fe(e,t){t&&e.log(`Skill invoked: ${t}`)}var pr=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),mr=(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 l=60-a.length;if(l<=0)return"";if(l>=i.length+6){let c=Math.min(l-i.length,e.length);return`${i}${e.slice(0,c)}`}return e.slice(0,l)},Nn=e=>!e||typeof e!="object"||Array.isArray(e)||Object.keys(e).length===0?!1:!!sr.some(t=>t in e),gr=()=>{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);Nn(i)&&(e[r]=i)}catch(i){let a=i instanceof SyntaxError?"Invalid JSON":i.message;dr.error(`Could not parse ${r} model version override from ${n}: ${a}`)}}}),e},On=1e4,Tt=(e,t=On)=>{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 fr}from"buffer";import $n from"path";var hr=I("repo"),_r=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{hr.info("Getting runner diffs");let o=await Ln(r),{hasChanges:n}=o,{status:i}=o;if(!n)return{hasChanges:!1};if(!t){let E=Mn(i);await Un(E,r)}hr.info("Changes after processing"),await It(r);let s=await vt(i,r);if(await xt(s,r),n=await Dn(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await O("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},l=await O("git",["diff",e.runSha,"HEAD"],a),c=String(l.stdout??"");if(n=!!c,!n)return await yr(r),{hasChanges:!1,ignored:s};let d=await O("git",["diff",e.runSha,"HEAD","--binary"],a),u=String(d.stdout??""),p,g;if(e.sha){let E=await O("git",["diff",e.sha,"HEAD"],a);p=String(E.stdout??"");let T=await O("git",["diff",e.sha,"HEAD","--binary"],a),y=String(T.stdout??"");p!==y&&(g=fr.from(y).toString("base64"))}await yr(r);let S={hasChanges:!0,diff:c,resultDiff:p,ignored:s};return c!==u&&(S.diffBinary=fr.from(u).toString("base64")),g&&(S.resultDiffBinary=g),S},yr=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await O("git",["reset","--soft","HEAD~1"],{cwd:e})},xt=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await O("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},It=async(e=process.cwd())=>{let t=await O("git",["status","-s"],{cwd:e});return String(t.stdout??"")},Er=/.. (.+)?\.log$/,Fn=[Er],Ln=async(e=process.cwd())=>{let t=await It(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
9
9
  `).filter(n=>Fn.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 O("git",["diff","--staged","--quiet"],{cwd:e}),!1}catch{return!0}},St=async(e=process.cwd())=>{let{stdout:t}=await O("git",["rev-parse","HEAD"],{cwd:e});return String(t??"").trim()},wr=async(e=process.cwd())=>{let{stdout:t}=await O("git",["rev-list","--max-parents=0","HEAD"],{cwd:e});return String(t??"").trim()},vt=async(e,t=process.cwd())=>{e||=await It(t);let r=[".netlify","node_modules","dist",".next","out",".nuxt",".output",".cache",".turbo",".parcel-cache","coverage",".nyc_output","storybook-static","public/build","CLAUDE.local.md"],o=[];return e.split(`
10
10
  `).forEach(n=>{r.forEach(s=>{let a=n===`?? ${s}`,l=n.startsWith(`?? ${s}/`)||n.startsWith(`?? ${s}${$n.sep}`);(a||l)&&o.push(`:!${s}`)});let i=n.match(Er)?.[1];i&&o.push(`:!${i}.log`)}),o},Rt=async(e=process.cwd())=>{await O("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(""),l=n.trim(),c=i.trim();return r[a]?r[a].change=c:r[a]={filePath:a,stage:l,change:c},r},{});return Object.values(t)},Un=async(e,t=process.cwd())=>{let r=e.filter(o=>o.stage&&!o.change).map(o=>o.filePath);r.length!==0&&await O("git",["restore","--staged","--worktree","--pathspec-from-file=-"],{cwd:t,input:r.join(`
@@ -173,7 +173,7 @@ Deploy failed failed. Here are the errors to review on the latest build:
173
173
  Below are all of the logs with potential issues that we extracted. Some of them may be false positives, discern them carefully and ensure fixes are relevant.
174
174
 
175
175
  ${e.pop()}
176
- `;import So from"process";import{getTracer as Dt}from"@netlify/otel";import{getTracer as xo}from"@netlify/otel";var Ue=I("deploy"),Yr=async e=>await N(xo(),"create-preview-deploy",async t=>Io(e,t)),Io=async({netlify:e,hasRepo:t,skipBuild:r,message:o="Agent Preview",deploySubdomain:n,cliPath:i,filter:s,prodDeploy:a},l)=>{try{let c=["deploy","--message",`"${o}"`,"--json","--verbose",a?"--prod":"--draft"];t||(Ue.log("Deploy: Uploading source zip"),c.push("--upload-source-zip")),n&&!a&&c.push("--alias",n),s&&c.push("--filter",s),r?(Ue.log("Deploy: Skipping build"),c.push("--no-build")):c.push("--context",a?"production":"deploy-preview");let d=i||"netlify";Ue.log(`Running: ${d} ${c.join(" ")}`),l?.setAttributes({cmd:d,args:c});let u=await e.utils.run(d,c,{stdio:["ignore","pipe","pipe"]}),p=JSON.parse(String(u.stdout??"").trim());l?.setAttributes({success:!0,deployId:p.deploy_id,deployUrl:p.deploy_url,siteId:p.site_id}),Ue.log(`
176
+ `;import So from"process";import{getTracer as Dt}from"@netlify/otel";import{getTracer as xo}from"@netlify/otel";var Ue=I("deploy"),Yr=async e=>await N(xo(),"create-preview-deploy",async t=>Io(e,t)),Io=async({netlify:e,hasRepo:t,skipBuild:r,message:o="Agent Preview",deploySubdomain:n,cliPath:i,filter:s,prodDeploy:a},l)=>{try{let c=["deploy","--message",`"${o}"`,"--json","--verbose",a?"--prod":"--draft"];Ue.log("Deploy: Uploading source zip"),c.push("--upload-source-zip"),n&&!a&&c.push("--alias",n),s&&c.push("--filter",s),r?(Ue.log("Deploy: Skipping build"),c.push("--no-build")):c.push("--context",a?"production":"deploy-preview");let d=i||"netlify";Ue.log(`Running: ${d} ${c.join(" ")}`),l?.setAttributes({cmd:d,args:c});let u=await e.utils.run(d,c,{stdio:["ignore","pipe","pipe"]}),p=JSON.parse(String(u.stdout??"").trim());l?.setAttributes({success:!0,deployId:p.deploy_id,deployUrl:p.deploy_url,siteId:p.site_id}),Ue.log(`
177
177
  Preview deploy created successfully:`,{deployId:p.deploy_id,deployUrl:p.deploy_url,siteId:p.site_id});let g={deployId:p.deploy_id,previewUrl:p.deploy_url,logsUrl:p.logs,siteId:p.site_id};return t||(g.sourceZipFilename=p.source_zip_filename),g}catch(c){throw Ue.error("Failed to create preview deploy via CLI:",c),l?.setAttributes({success:!1,error:c.message}),c}};var qr=e=>["dtn-prod-iteration","create"].includes(e);var ot=class{scanDiffForForms(t){let r=[],o=null,n=[],i=t.split(`
178
178
  `);for(let s of i)if(s.startsWith("diff --git")){if(o&&n.length>0){let l=this.containsNetlifyForm(n,o);l&&r.push(l)}let a=s.split(" ");o=a[a.length-1].replace(/^b\//,""),n=[],We.test(o)&&(o=null)}else s.startsWith("+")&&!s.startsWith("+++")&&n.push(s.slice(1));if(o&&n.length>0){let s=this.containsNetlifyForm(n,o);s&&r.push(s)}return{detected:r.length>0,matches:r}}containsNetlifyForm(t,r){let o=t.join(`
179
179
  `),n=[{pattern:/<[\w-]*form[\s\S]*?(data-)?netlify/i,name:"standard form element"},{pattern:/<[A-Z][\w]*[\s\S]*?component\s*=\s*["']form["'][\s\S]*?(data-)?netlify/i,name:"component with form prop"}];for(let{pattern:i,name:s}of n){let a=o.match(i);if(a){let l=a.index||0,c=Math.max(0,l-20),d=Math.min(o.length,l+a[0].length+20),u=o.slice(c,d).trim();return u=u.replace(/\s+/g," "),u.length>100&&(u=u.slice(0,97)+"..."),{file:r,snippet:`[${s}] ${u}`}}}return null}};var it=class{scanDiffForIdentity(t){let r=[],o=null,n=[],i=t.split(`
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import{createRequire as Ei}from"module";import{createTracerProvider as Br}from"@
4
4
  ${s}
5
5
  </extracted_error_chunk>`).join(`
6
6
 
7
- `);return o.length>e.length*.8?e:o}import{execSync as qn}from"child_process";import Ir from"fs/promises";import Bn from"path";import he from"process";import{getTracer as Hn}from"@netlify/otel";import ke from"process";var Z=class extends Error{constructor(r,i,n,o=!1){super(r);this.statusCode=i;this.userMessage=n;this.isCreditLimitExceeded=o;this.name="GracefulShutdownError"}},Ue=e=>e instanceof Z;var Ge=ke.env.NETLIFY_API_URL,je=ke.env.NETLIFY_API_TOKEN,B=I("api"),_e=()=>ke.env.NETLIFY_LOCAL_MODE==="true",se=async(e,t={})=>{if(!Ge||!je)throw new Error("No API URL or token");let r=new URL(e,Ge),i={...t,headers:{...t.headers,Authorization:`Bearer ${je}`}};ke.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),o=n.ok&&n.status<=299;if(ke.env.AGENT_RUNNERS_DEBUG==="true")B.log(`Response headers for ${r}:`),n.headers.forEach((a,l)=>{B.log(` ${l}: ${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 s=await(n.headers.get("content-type")?.includes("application/json")?n.json():n.text());if(!o){let a=typeof s=="string"?s:JSON.stringify(s);throw n.status===404?new Z(`API request failed: 404 - ${a}`,404,"The site associated with this agent run no longer exists."):n.status===503&&t.gracefulOn503&&a.toLowerCase().includes("usage exceeded")?new Z(`API request failed: 503 - ${a}`,503,"Credit limit reached. Please add more credits to continue using Agent Runners.",!0):new Error(`API request failed: ${n.status} - ${a}`)}return s},Mt=e=>{B.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Ge=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(je=e.constants.NETLIFY_API_TOKEN)},Ut=()=>({apiUrl:Ge,token:je}),Pe=async(e,t)=>_e()?(B.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):se(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),H=async(e,t,r)=>_e()?(B.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):se(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var Gt=async e=>_e()?(B.log("Mock API: getSite called",{siteId:e}),{id:e,published_deploy:{id:"id"}}):se(`/api/v1/sites/${e}`),jt=async(e,t)=>_e()?(B.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):se(`/api/v1/agent_runners/${e}/sessions/${t}`),Yt=(e,t,r)=>se(`/api/v1/accounts/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),qt=(e,t,r)=>se(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),Bt=async(e,t)=>_e()?(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"}}):se(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),Ht=async(e,t)=>_e()?(B.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):se(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),at=async(e,t,{maxRetries:r=3,baseDelayMs:i=500}={})=>{B.log(`Uploading diff to S3: ${e.substring(0,50)}...`);for(let n=1;n<=r;n++)try{let o=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!o.ok)throw new Error(`S3 upload failed with status ${o.status}`);return o}catch(o){if(n===r)throw o;let s=i*2**(n-1);B.warn(`S3 upload attempt ${n}/${r} failed: ${o.message}. Retrying in ${s}ms...`),await new Promise(a=>setTimeout(a,s))}};var Ee=I("ai_gateway"),lt=null;var Ye=async()=>{if(lt)return lt;Ee.log("Fetching available AI gateway providers");let e=await fetch(`${Ut().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 lt=t,Ee.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},zr=async(e,t)=>{let i=(await Ye()).providers[e];if(!i)return Ee.log(`Provider '${e}' not found`),!1;let n=i.models.includes(t);return Ee.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},Wt=async({config:e})=>{let t,r,i,n,o=!e.site?.published_deploy;if(!(o?e.accountId:e.siteId))throw new Error(`No entity id for ${o?"account":"site"}`);let a=async()=>{clearTimeout(i),Ee.log("Requesting AI gateway information");let c=await(o?Yt(e.accountId,e.id,e.sessionId):qt(e.siteId,e.id,e.sessionId));if({token:t,url:n}=c,r=c.expires_at?c.expires_at*1e3:void 0,Ee.log("Got AI gateway information",{token:!!t,expiresAt:r,url:n}),r){let d=r-Date.now()-6e4;d>0&&(i=setTimeout(()=>{a()},d))}};return await Promise.all([a(),Ye()]),{get url(){return n},get token(){return t},isModelAvailableForProvider:zr}};import ee from"process";import ne from"path";import Be from"fs";import{fileURLToPath as on}from"url";import{createRequire as sn}from"module";import{execa as an,execaCommand as eo}from"execa";import{Transform as Xr}from"stream";function Zr(){let e=process.env.NETLIFY_SENSITIVE_ENV_KEYS;return e?e.split(",").map(t=>t.trim()).filter(Boolean):[]}function Qr(e){let t=e.toLowerCase();return t==="true"||t==="false"?!0:e.trim().length<4}function en(){let t=Zr().map(r=>process.env[r]).filter(r=>!(!r||Qr(r)));return[...new Set(t)].sort((r,i)=>i.length-r.length)}function re(e){if(typeof e!="string")return e;let t=en();if(t.length===0)return e;let r=e;return t.forEach(i=>{let n=new RegExp(tn(i),"g");r=r.replace(n,"******")}),r}function tn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var xe=class extends Xr{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,i){let n=t.toString(),o=re(n);i(null,o)}};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(i,n,o){let s=typeof i=="string"?re(i):i;return typeof n=="function"?t(s,n):t(s,n,o)},process.stderr.write=function(i,n,o){let s=typeof i=="string"?re(i):i;return typeof n=="function"?r(s,n):r(s,n,o)}}var Ne=null,Jt=e=>(Ne&&Ne.destroy(),Ne=new ae({totalAllowedTime:e}),Ne),Vt=()=>Ne;var ae=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.`)}),o=null,s=null;i!==void 0&&(s=new Promise((a,l)=>{o=setTimeout(()=>{l(new Error(`${t} stage exceeded its maximum duration of ${i}ms`))},i)}));try{return s?await Promise.race([r(),s]):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 zt="netlify-agent-runner-context.md",ct="task-history",Q=".netlify",pe="results.md",ut="assets";var Xt="free";var me=1800*1e3,rn=["\\.claude","\\.gemini","\\.codex"],qe=new RegExp(`(^|/)(${rn.join("|")})/skills/`),f={Environment:"environment",UserMessage:"user-message",AgentMessage:"agent-message",Task:"task",RunCommand:"run-command",Explore:"explore",Plan:"plan",FileRead:"file-read",FileWrite:"file-write",Notebook:"notebook",Web:"web",Todo:"todo",Reasoning:"reasoning",Skill:"skill",Memorize:"memorize",Deployment:"deployment",SiteGeneration:"site-generation"};var Zt={name:"@netlify/agent-runner-cli",type:"module",version:"1.92.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","test:integration:skill-invocation":"vitest run test/integration/skill-invocation.test.ts","check:types":"tsc --noEmit",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.63","@anthropic-ai/sdk":"0.78.0","@google/gemini-cli":"0.31.0","@netlify/otel":"^5.1.5","@netlify/ts-cli":"^1.0.3","@openai/codex":"0.115.0","@opentelemetry/exporter-trace-otlp-grpc":"0.57.2",execa:"^9.6.1",minimist:"^1.2.8",openai:"6.26.0"}};var ln=on(import.meta.url),cn=ne.dirname(ln),un=sn(import.meta.url),Te=I("shell"),dt=new Set,dn={preferLocal:!0},$=(e,t,r)=>{let[i,n]=pn(t,r),o={...dn,...n},s=an(e,i,o);mn(s,o),fn(s);let a=r?.idleTimeout;return a&&a>0&&gn(s,a),s};var pn=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},mn=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(ee.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new xe).pipe(ee.stdout),e.stdout?.pipe(new xe).pipe(ee.stdout),e.stderr?.pipe(new xe).pipe(ee.stderr);return}e.stdout?.pipe(ee.stdout),e.stderr?.pipe(ee.stderr)},pt=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(ee.kill(-e.pid,t),Te.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return Te.error("Error killing process:",r),!1}},Qt=e=>pt(e,"SIGKILL"),gn=(e,t)=>{let r=null,i=()=>{Te.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),pt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(Te.log(`Force killing idle process ${e.pid}`),Qt(e))},5e3)},n=()=>{r&&clearTimeout(r),r=setTimeout(i,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)},fn=e=>{dt.add(e);let t=Vt();if(t){let r=t.onTimesUp(()=>{Te.log(`Global timer expired, killing process ${e.pid}`),pt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(Te.log(`Force killing process ${e.pid} after timeout`),Qt(e))},5e3)});e.on("exit",()=>{dt.delete(e),r()}),e.on("error",()=>{dt.delete(e),r()})}};function le(e,t){if(!ee.env.NETLIFY_LOCAL_MODE)try{let n=un.resolve(Zt.name),o=ne.dirname(n);for(;o!==ne.dirname(o);){let s=ne.dirname(o);if(ne.basename(s)==="node_modules"){let a=ne.join(s,".bin",t);if(Be.existsSync(a))return a;break}o=s}}catch(n){console.error("Could not resolve package.json",n)}if(ee.env.NODE_PATH){let n=ne.join(ee.env.NODE_PATH,".bin",t);if(Be.existsSync(n))return n}let r=ne.join(e,"node_modules",".bin",t);if(Be.existsSync(r))return r;let i=ne.join(cn,"..","node_modules",".bin",t);if(Be.existsSync(i))return i}var hn=I("utils"),yn=e=>new Promise(t=>{setTimeout(t,e)}),He=(e,t=3e3)=>{let r=!1,i=null,n=[],o=null,s=(...a)=>{if(r)return i=a,new Promise(d=>{n.push(d)});r=!0;let l,c=new Promise(d=>{l=d});return o=(async()=>{await Promise.resolve();let d=await e(...a);for(l(d);;){if(await yn(t),!i)return r=!1,o=null,d;let u=i,p=n;i=null,n=[],d=await e(...u),p.forEach(g=>{g(d)})}})(),c};return s.flush=async()=>{if((r||i)&&o)return await o,s.flush()},s},Se=(e,t,r=!1)=>{let i=null,n=null,o=null,s=function(...a){n=a,o=this;let l=r&&!i;clearTimeout(i),i=setTimeout(()=>{i=null,r||(e.apply(o,n),n=null,o=null)},t),l&&(e.apply(o,n),n=null,o=null)};return s.cancel=()=>{clearTimeout(i),i=null,n=null,o=null},s.flush=()=>{if(i){clearTimeout(i);let a=n,l=o;i=null,n=null,o=null,e.apply(l,a)}},s},er=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(i){t&&(r?.error?r.error("Could not parse JSON",i):hn.error("Could not parse JSON",i))}},mt=e=>e.charAt(0).toUpperCase()+e.slice(1),ce=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():mt(t)).join(" ");function ge(e,t){t&&e.log(`Skill invoked: ${t}`)}var tr=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),rr=(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 l=60-a.length;if(l<=0)return"";if(l>=o.length+6){let c=Math.min(l-o.length,e.length);return`${o}${e.slice(0,c)}`}return e.slice(0,l)};var wn=1e4,gt=(e,t=wn)=>{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 nr}from"buffer";import _n from"path";var ir=I("repo"),sr=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{ir.info("Getting runner diffs");let i=await xn(r),{hasChanges:n}=i,{status:o}=i;if(!n)return{hasChanges:!1};if(!t){let _=Sn(o);await In(_,r)}ir.info("Changes after processing"),await ht(r);let s=await wt(o,r);if(await ft(s,r),n=await Tn(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await $("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},l=await $("git",["diff",e.runSha,"HEAD"],a),c=String(l.stdout??"");if(n=!!c,!n)return await or(r),{hasChanges:!1,ignored:s};let d=await $("git",["diff",e.runSha,"HEAD","--binary"],a),u=String(d.stdout??""),p,g;if(e.sha){let _=await $("git",["diff",e.sha,"HEAD"],a);p=String(_.stdout??"");let x=await $("git",["diff",e.sha,"HEAD","--binary"],a),w=String(x.stdout??"");p!==w&&(g=nr.from(w).toString("base64"))}await or(r);let T={hasChanges:!0,diff:c,resultDiff:p,ignored:s};return c!==u&&(T.diffBinary=nr.from(u).toString("base64")),g&&(T.resultDiffBinary=g),T},or=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await $("git",["reset","--soft","HEAD~1"],{cwd:e})},ft=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await $("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},ht=async(e=process.cwd())=>{let t=await $("git",["status","-s"],{cwd:e});return String(t.stdout??"")},ar=/.. (.+)?\.log$/,En=[ar],xn=async(e=process.cwd())=>{let t=await ht(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
7
+ `);return o.length>e.length*.8?e:o}import{execSync as qn}from"child_process";import Ir from"fs/promises";import Bn from"path";import he from"process";import{getTracer as Hn}from"@netlify/otel";import ke from"process";var Z=class extends Error{constructor(r,i,n,o=!1){super(r);this.statusCode=i;this.userMessage=n;this.isCreditLimitExceeded=o;this.name="GracefulShutdownError"}},Ue=e=>e instanceof Z;var Ge=ke.env.NETLIFY_API_URL,je=ke.env.NETLIFY_API_TOKEN,B=I("api"),_e=()=>ke.env.NETLIFY_LOCAL_MODE==="true",se=async(e,t={})=>{if(!Ge||!je)throw new Error("No API URL or token");let r=new URL(e,Ge),i={...t,headers:{...t.headers,Authorization:`Bearer ${je}`}};ke.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),o=n.ok&&n.status<=299;if(ke.env.AGENT_RUNNERS_DEBUG==="true")B.log(`Response headers for ${r}:`),n.headers.forEach((a,l)=>{B.log(` ${l}: ${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 s=await(n.headers.get("content-type")?.includes("application/json")?n.json():n.text());if(!o){let a=typeof s=="string"?s:JSON.stringify(s);throw n.status===404?new Z(`API request failed: 404 - ${a}`,404,"The site associated with this agent run no longer exists."):n.status===503&&t.gracefulOn503&&a.toLowerCase().includes("usage exceeded")?new Z(`API request failed: 503 - ${a}`,503,"Credit limit reached. Please add more credits to continue using Agent Runners.",!0):new Error(`API request failed: ${n.status} - ${a}`)}return s},Mt=e=>{B.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Ge=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(je=e.constants.NETLIFY_API_TOKEN)},Ut=()=>({apiUrl:Ge,token:je}),Pe=async(e,t)=>_e()?(B.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):se(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),H=async(e,t,r)=>_e()?(B.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):se(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var Gt=async e=>_e()?(B.log("Mock API: getSite called",{siteId:e}),{id:e,published_deploy:{id:"id"}}):se(`/api/v1/sites/${e}`),jt=async(e,t)=>_e()?(B.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):se(`/api/v1/agent_runners/${e}/sessions/${t}`),Yt=(e,t,r)=>se(`/api/v1/accounts/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),qt=(e,t,r)=>se(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),Bt=async(e,t)=>_e()?(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"}}):se(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),Ht=async(e,t)=>_e()?(B.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):se(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),at=async(e,t,{maxRetries:r=3,baseDelayMs:i=500}={})=>{B.log(`Uploading diff to S3: ${e.substring(0,50)}...`);for(let n=1;n<=r;n++)try{let o=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!o.ok)throw new Error(`S3 upload failed with status ${o.status}`);return o}catch(o){if(n===r)throw o;let s=i*2**(n-1);B.warn(`S3 upload attempt ${n}/${r} failed: ${o.message}. Retrying in ${s}ms...`),await new Promise(a=>setTimeout(a,s))}};var Ee=I("ai_gateway"),lt=null;var Ye=async()=>{if(lt)return lt;Ee.log("Fetching available AI gateway providers");let e=await fetch(`${Ut().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 lt=t,Ee.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},zr=async(e,t)=>{let i=(await Ye()).providers[e];if(!i)return Ee.log(`Provider '${e}' not found`),!1;let n=i.models.includes(t);return Ee.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},Wt=async({config:e})=>{let t,r,i,n,o=!e.site?.published_deploy;if(!(o?e.accountId:e.siteId))throw new Error(`No entity id for ${o?"account":"site"}`);let a=async()=>{clearTimeout(i),Ee.log("Requesting AI gateway information");let c=await(o?Yt(e.accountId,e.id,e.sessionId):qt(e.siteId,e.id,e.sessionId));if({token:t,url:n}=c,r=c.expires_at?c.expires_at*1e3:void 0,Ee.log("Got AI gateway information",{token:!!t,expiresAt:r,url:n}),r){let d=r-Date.now()-6e4;d>0&&(i=setTimeout(()=>{a()},d))}};return await Promise.all([a(),Ye()]),{get url(){return n},get token(){return t},isModelAvailableForProvider:zr}};import ee from"process";import ne from"path";import Be from"fs";import{fileURLToPath as on}from"url";import{createRequire as sn}from"module";import{execa as an,execaCommand as eo}from"execa";import{Transform as Xr}from"stream";function Zr(){let e=process.env.NETLIFY_SENSITIVE_ENV_KEYS;return e?e.split(",").map(t=>t.trim()).filter(Boolean):[]}function Qr(e){let t=e.toLowerCase();return t==="true"||t==="false"?!0:e.trim().length<4}function en(){let t=Zr().map(r=>process.env[r]).filter(r=>!(!r||Qr(r)));return[...new Set(t)].sort((r,i)=>i.length-r.length)}function re(e){if(typeof e!="string")return e;let t=en();if(t.length===0)return e;let r=e;return t.forEach(i=>{let n=new RegExp(tn(i),"g");r=r.replace(n,"******")}),r}function tn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var xe=class extends Xr{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,i){let n=t.toString(),o=re(n);i(null,o)}};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(i,n,o){let s=typeof i=="string"?re(i):i;return typeof n=="function"?t(s,n):t(s,n,o)},process.stderr.write=function(i,n,o){let s=typeof i=="string"?re(i):i;return typeof n=="function"?r(s,n):r(s,n,o)}}var Ne=null,Jt=e=>(Ne&&Ne.destroy(),Ne=new ae({totalAllowedTime:e}),Ne),Vt=()=>Ne;var ae=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.`)}),o=null,s=null;i!==void 0&&(s=new Promise((a,l)=>{o=setTimeout(()=>{l(new Error(`${t} stage exceeded its maximum duration of ${i}ms`))},i)}));try{return s?await Promise.race([r(),s]):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 zt="netlify-agent-runner-context.md",ct="task-history",Q=".netlify",pe="results.md",ut="assets";var Xt="free";var me=1800*1e3,rn=["\\.claude","\\.gemini","\\.codex"],qe=new RegExp(`(^|/)(${rn.join("|")})/skills/`),f={Environment:"environment",UserMessage:"user-message",AgentMessage:"agent-message",Task:"task",RunCommand:"run-command",Explore:"explore",Plan:"plan",FileRead:"file-read",FileWrite:"file-write",Notebook:"notebook",Web:"web",Todo:"todo",Reasoning:"reasoning",Skill:"skill",Memorize:"memorize",Deployment:"deployment",SiteGeneration:"site-generation"};var Zt={name:"@netlify/agent-runner-cli",type:"module",version:"1.92.4",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","test:integration:skill-invocation":"vitest run test/integration/skill-invocation.test.ts","check:types":"tsc --noEmit",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.63","@anthropic-ai/sdk":"0.78.0","@google/gemini-cli":"0.31.0","@netlify/otel":"^5.1.5","@netlify/ts-cli":"^1.0.3","@openai/codex":"0.115.0","@opentelemetry/exporter-trace-otlp-grpc":"0.57.2",execa:"^9.6.1",minimist:"^1.2.8",openai:"6.26.0"}};var ln=on(import.meta.url),cn=ne.dirname(ln),un=sn(import.meta.url),Te=I("shell"),dt=new Set,dn={preferLocal:!0},$=(e,t,r)=>{let[i,n]=pn(t,r),o={...dn,...n},s=an(e,i,o);mn(s,o),fn(s);let a=r?.idleTimeout;return a&&a>0&&gn(s,a),s};var pn=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},mn=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(ee.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new xe).pipe(ee.stdout),e.stdout?.pipe(new xe).pipe(ee.stdout),e.stderr?.pipe(new xe).pipe(ee.stderr);return}e.stdout?.pipe(ee.stdout),e.stderr?.pipe(ee.stderr)},pt=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(ee.kill(-e.pid,t),Te.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return Te.error("Error killing process:",r),!1}},Qt=e=>pt(e,"SIGKILL"),gn=(e,t)=>{let r=null,i=()=>{Te.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),pt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(Te.log(`Force killing idle process ${e.pid}`),Qt(e))},5e3)},n=()=>{r&&clearTimeout(r),r=setTimeout(i,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)},fn=e=>{dt.add(e);let t=Vt();if(t){let r=t.onTimesUp(()=>{Te.log(`Global timer expired, killing process ${e.pid}`),pt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(Te.log(`Force killing process ${e.pid} after timeout`),Qt(e))},5e3)});e.on("exit",()=>{dt.delete(e),r()}),e.on("error",()=>{dt.delete(e),r()})}};function le(e,t){if(!ee.env.NETLIFY_LOCAL_MODE)try{let n=un.resolve(Zt.name),o=ne.dirname(n);for(;o!==ne.dirname(o);){let s=ne.dirname(o);if(ne.basename(s)==="node_modules"){let a=ne.join(s,".bin",t);if(Be.existsSync(a))return a;break}o=s}}catch(n){console.error("Could not resolve package.json",n)}if(ee.env.NODE_PATH){let n=ne.join(ee.env.NODE_PATH,".bin",t);if(Be.existsSync(n))return n}let r=ne.join(e,"node_modules",".bin",t);if(Be.existsSync(r))return r;let i=ne.join(cn,"..","node_modules",".bin",t);if(Be.existsSync(i))return i}var hn=I("utils"),yn=e=>new Promise(t=>{setTimeout(t,e)}),He=(e,t=3e3)=>{let r=!1,i=null,n=[],o=null,s=(...a)=>{if(r)return i=a,new Promise(d=>{n.push(d)});r=!0;let l,c=new Promise(d=>{l=d});return o=(async()=>{await Promise.resolve();let d=await e(...a);for(l(d);;){if(await yn(t),!i)return r=!1,o=null,d;let u=i,p=n;i=null,n=[],d=await e(...u),p.forEach(g=>{g(d)})}})(),c};return s.flush=async()=>{if((r||i)&&o)return await o,s.flush()},s},Se=(e,t,r=!1)=>{let i=null,n=null,o=null,s=function(...a){n=a,o=this;let l=r&&!i;clearTimeout(i),i=setTimeout(()=>{i=null,r||(e.apply(o,n),n=null,o=null)},t),l&&(e.apply(o,n),n=null,o=null)};return s.cancel=()=>{clearTimeout(i),i=null,n=null,o=null},s.flush=()=>{if(i){clearTimeout(i);let a=n,l=o;i=null,n=null,o=null,e.apply(l,a)}},s},er=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(i){t&&(r?.error?r.error("Could not parse JSON",i):hn.error("Could not parse JSON",i))}},mt=e=>e.charAt(0).toUpperCase()+e.slice(1),ce=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():mt(t)).join(" ");function ge(e,t){t&&e.log(`Skill invoked: ${t}`)}var tr=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),rr=(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 l=60-a.length;if(l<=0)return"";if(l>=o.length+6){let c=Math.min(l-o.length,e.length);return`${o}${e.slice(0,c)}`}return e.slice(0,l)};var wn=1e4,gt=(e,t=wn)=>{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 nr}from"buffer";import _n from"path";var ir=I("repo"),sr=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{ir.info("Getting runner diffs");let i=await xn(r),{hasChanges:n}=i,{status:o}=i;if(!n)return{hasChanges:!1};if(!t){let _=Sn(o);await In(_,r)}ir.info("Changes after processing"),await ht(r);let s=await wt(o,r);if(await ft(s,r),n=await Tn(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await $("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},l=await $("git",["diff",e.runSha,"HEAD"],a),c=String(l.stdout??"");if(n=!!c,!n)return await or(r),{hasChanges:!1,ignored:s};let d=await $("git",["diff",e.runSha,"HEAD","--binary"],a),u=String(d.stdout??""),p,g;if(e.sha){let _=await $("git",["diff",e.sha,"HEAD"],a);p=String(_.stdout??"");let x=await $("git",["diff",e.sha,"HEAD","--binary"],a),w=String(x.stdout??"");p!==w&&(g=nr.from(w).toString("base64"))}await or(r);let T={hasChanges:!0,diff:c,resultDiff:p,ignored:s};return c!==u&&(T.diffBinary=nr.from(u).toString("base64")),g&&(T.resultDiffBinary=g),T},or=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await $("git",["reset","--soft","HEAD~1"],{cwd:e})},ft=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await $("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},ht=async(e=process.cwd())=>{let t=await $("git",["status","-s"],{cwd:e});return String(t.stdout??"")},ar=/.. (.+)?\.log$/,En=[ar],xn=async(e=process.cwd())=>{let t=await ht(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
8
8
  `).filter(n=>En.some(s=>s instanceof RegExp?s.test(n):n===s)?!1:n[1]?.trim()!=="")).length!==0,status:t}},Tn=async(e=process.cwd())=>{try{return await $("git",["diff","--staged","--quiet"],{cwd:e}),!1}catch{return!0}},yt=async(e=process.cwd())=>{let{stdout:t}=await $("git",["rev-parse","HEAD"],{cwd:e});return String(t??"").trim()},lr=async(e=process.cwd())=>{let{stdout:t}=await $("git",["rev-list","--max-parents=0","HEAD"],{cwd:e});return String(t??"").trim()},wt=async(e,t=process.cwd())=>{e||=await ht(t);let r=[".netlify","node_modules","dist",".next","out",".nuxt",".output",".cache",".turbo",".parcel-cache","coverage",".nyc_output","storybook-static","public/build","CLAUDE.local.md"],i=[];return e.split(`
9
9
  `).forEach(n=>{r.forEach(s=>{let a=n===`?? ${s}`,l=n.startsWith(`?? ${s}/`)||n.startsWith(`?? ${s}${_n.sep}`);(a||l)&&i.push(`:!${s}`)});let o=n.match(ar)?.[1];o&&i.push(`:!${o}.log`)}),i},_t=async(e=process.cwd())=>{await $("git",["reset","--hard","HEAD"],{cwd:e})},Sn=e=>{let t=e.split(`
10
10
  `).reduce((r,i)=>{if(!i)return r;let[n,o,,...s]=i,a=s.join(""),l=n.trim(),c=o.trim();return r[a]?r[a].change=c:r[a]={filePath:a,stage:l,change:c},r},{});return Object.values(t)},In=async(e,t=process.cwd())=>{let r=e.filter(i=>i.stage&&!i.change).map(i=>i.filePath);r.length!==0&&await $("git",["restore","--staged","--worktree","--pathspec-from-file=-"],{cwd:t,input:r.join(`
@@ -172,7 +172,7 @@ Deploy failed failed. Here are the errors to review on the latest build:
172
172
  Below are all of the logs with potential issues that we extracted. Some of them may be false positives, discern them carefully and ensure fixes are relevant.
173
173
 
174
174
  ${e.pop()}
175
- `;import li from"process";import{getTracer as kt}from"@netlify/otel";import{getTracer as si}from"@netlify/otel";var Le=I("deploy"),kr=async e=>await N(si(),"create-preview-deploy",async t=>ai(e,t)),ai=async({netlify:e,hasRepo:t,skipBuild:r,message:i="Agent Preview",deploySubdomain:n,cliPath:o,filter:s,prodDeploy:a},l)=>{try{let c=["deploy","--message",`"${i}"`,"--json","--verbose",a?"--prod":"--draft"];t||(Le.log("Deploy: Uploading source zip"),c.push("--upload-source-zip")),n&&!a&&c.push("--alias",n),s&&c.push("--filter",s),r?(Le.log("Deploy: Skipping build"),c.push("--no-build")):c.push("--context",a?"production":"deploy-preview");let d=o||"netlify";Le.log(`Running: ${d} ${c.join(" ")}`),l?.setAttributes({cmd:d,args:c});let u=await e.utils.run(d,c,{stdio:["ignore","pipe","pipe"]}),p=JSON.parse(String(u.stdout??"").trim());l?.setAttributes({success:!0,deployId:p.deploy_id,deployUrl:p.deploy_url,siteId:p.site_id}),Le.log(`
175
+ `;import li from"process";import{getTracer as kt}from"@netlify/otel";import{getTracer as si}from"@netlify/otel";var Le=I("deploy"),kr=async e=>await N(si(),"create-preview-deploy",async t=>ai(e,t)),ai=async({netlify:e,hasRepo:t,skipBuild:r,message:i="Agent Preview",deploySubdomain:n,cliPath:o,filter:s,prodDeploy:a},l)=>{try{let c=["deploy","--message",`"${i}"`,"--json","--verbose",a?"--prod":"--draft"];Le.log("Deploy: Uploading source zip"),c.push("--upload-source-zip"),n&&!a&&c.push("--alias",n),s&&c.push("--filter",s),r?(Le.log("Deploy: Skipping build"),c.push("--no-build")):c.push("--context",a?"production":"deploy-preview");let d=o||"netlify";Le.log(`Running: ${d} ${c.join(" ")}`),l?.setAttributes({cmd:d,args:c});let u=await e.utils.run(d,c,{stdio:["ignore","pipe","pipe"]}),p=JSON.parse(String(u.stdout??"").trim());l?.setAttributes({success:!0,deployId:p.deploy_id,deployUrl:p.deploy_url,siteId:p.site_id}),Le.log(`
176
176
  Preview deploy created successfully:`,{deployId:p.deploy_id,deployUrl:p.deploy_url,siteId:p.site_id});let g={deployId:p.deploy_id,previewUrl:p.deploy_url,logsUrl:p.logs,siteId:p.site_id};return t||(g.sourceZipFilename=p.source_zip_filename),g}catch(c){throw Le.error("Failed to create preview deploy via CLI:",c),l?.setAttributes({success:!1,error:c.message}),c}};var Pr=e=>["dtn-prod-iteration","create"].includes(e);var et=class{scanDiffForForms(t){let r=[],i=null,n=[],o=t.split(`
177
177
  `);for(let s of o)if(s.startsWith("diff --git")){if(i&&n.length>0){let l=this.containsNetlifyForm(n,i);l&&r.push(l)}let a=s.split(" ");i=a[a.length-1].replace(/^b\//,""),n=[],qe.test(i)&&(i=null)}else s.startsWith("+")&&!s.startsWith("+++")&&n.push(s.slice(1));if(i&&n.length>0){let s=this.containsNetlifyForm(n,i);s&&r.push(s)}return{detected:r.length>0,matches:r}}containsNetlifyForm(t,r){let i=t.join(`
178
178
  `),n=[{pattern:/<[\w-]*form[\s\S]*?(data-)?netlify/i,name:"standard form element"},{pattern:/<[A-Z][\w]*[\s\S]*?component\s*=\s*["']form["'][\s\S]*?(data-)?netlify/i,name:"component with form prop"}];for(let{pattern:o,name:s}of n){let a=i.match(o);if(a){let l=a.index||0,c=Math.max(0,l-20),d=Math.min(i.length,l+a[0].length+20),u=i.slice(c,d).trim();return u=u.replace(/\s+/g," "),u.length>100&&(u=u.slice(0,97)+"..."),{file:r,snippet:`[${s}] ${u}`}}}return null}};var tt=class{scanDiffForIdentity(t){let r=[],i=null,n=[],o=t.split(`
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@netlify/agent-runner-cli",
3
3
  "type": "module",
4
- "version": "1.92.3",
4
+ "version": "1.92.4",
5
5
  "description": "CLI tool for running Netlify agents",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",