@netlify/agent-runner-cli 1.98.0 → 1.98.1
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 +1 -1
- package/dist/bin.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/bin-local.js
CHANGED
|
@@ -5,7 +5,7 @@ import j from"process";import pn from"path";import mn from"fs";import eo 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 pi}from"child_process";import jr from"fs/promises";import mi from"path";import xe from"process";import{getTracer as gi}from"@netlify/otel";import De from"process";var ne=class extends Error{constructor(r,i,n,o=!1){super(r);this.statusCode=i;this.userMessage=n;this.isCreditLimitExceeded=o;this.name="GracefulShutdownError"}},ze=e=>e instanceof ne,Ke=class extends Error{constructor(t){super(t),this.name="ProviderError"}};var Je=De.env.NETLIFY_API_URL,Xe=De.env.NETLIFY_API_TOKEN,W=v("api"),ve=()=>De.env.NETLIFY_LOCAL_MODE==="true",de=async(e,t={})=>{if(!Je||!Xe)throw new Error("No API URL or token");let r=new URL(e,Je),i={...t,headers:{...t.headers,Authorization:`Bearer ${Xe}`}};De.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(De.env.AGENT_RUNNERS_DEBUG==="true")W.log(`Response headers for ${r}:`),n.headers.forEach((a,c)=>{W.log(` ${c}: ${a}`)});else{let a=n.headers.get("x-request-id")||n.headers.get("x-nf-request-id");W.log(`Request ID for ${r}: ${a||"N/A"}`)}if(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 ne(`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 ne(`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},Xt=e=>{W.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Je=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(Xe=e.constants.NETLIFY_API_TOKEN)},Zt=()=>({apiUrl:Je,token:Xe}),Me=async(e,t)=>ve()?(W.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):de(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),K=async(e,t,r)=>ve()?(W.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):de(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var Qt=async e=>ve()?(W.log("Mock API: getSite called",{siteId:e}),{id:e,published_deploy:{id:"id"}}):de(`/api/v1/sites/${e}`),er=async(e,t)=>ve()?(W.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):de(`/api/v1/agent_runners/${e}/sessions/${t}`),tr=(e,t,r)=>de(`/api/v1/accounts/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),rr=(e,t,r)=>de(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),nr=async(e,t)=>ve()?(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"}}):de(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),ir=async(e,t)=>ve()?(W.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):de(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),gt=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 Se=v("ai_gateway"),ft=null;var Ze=async()=>{if(ft)return ft;Se.log("Fetching available AI gateway providers");let e=await fetch(`${Zt().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 ft=t,Se.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},xn=async(e,t)=>{let i=(await Ze()).providers[e];if(!i)return Se.log(`Provider '${e}' not found`),!1;let n=i.models.includes(t);return Se.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},or=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),Se.log("Requesting AI gateway information");let l=await(o?tr(e.accountId,e.id,e.sessionId):rr(e.siteId,e.id,e.sessionId));if({token:t,url:n}=l,r=l.expires_at?l.expires_at*1e3:void 0,Se.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(),Ze()]),{get url(){return n},get token(){return t},isModelAvailableForProvider:xn}};import ie from"process";import ae from"path";import Qe from"fs";import{fileURLToPath as An}from"url";import{createRequire as kn}from"module";import{execa as Cn,execaCommand as Pn}from"execa";import{Transform as Tn}from"stream";function vn(){let e=process.env.NETLIFY_SENSITIVE_ENV_KEYS;return e?e.split(",").map(t=>t.trim()).filter(Boolean):[]}function Sn(e){let t=e.toLowerCase();return t==="true"||t==="false"?!0:e.trim().length<4}function In(){let t=vn().map(r=>process.env[r]).filter(r=>!(!r||Sn(r)));return[...new Set(t)].sort((r,i)=>i.length-r.length)}function se(e){if(typeof e!="string")return e;let t=In();if(t.length===0)return e;let r=e;return t.forEach(i=>{let n=new RegExp(bn(i),"g");r=r.replace(n,"******")}),r}function bn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Ie=class extends Tn{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,i){let n=t.toString(),o=se(n);i(null,o)}};function sr(){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"?se(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"?se(i):i;return typeof n=="function"?r(s,n):r(s,n,o)}}var Ue=null,ar=e=>(Ue&&Ue.destroy(),Ue=new pe({totalAllowedTime:e}),Ue),lr=()=>Ue;var pe=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,c)=>{o=setTimeout(()=>{c(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 cr="netlify-agent-runner-context.md",ht="task-history",J=".netlify",he="results.md",yt="assets",ur="features";var dr="free";var ye=1800*1e3,h={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 pr={name:"@netlify/agent-runner-cli",type:"module",version:"1.98.0",description:"CLI tool for running Netlify agents",main:"./dist/index.js",types:"./dist/index.d.ts",exports:"./dist/index.js",bin:{"agent-runner-cli":"./dist/bin.js","agent-runner-cli-local":"./dist/bin-local.js"},files:["dist/**/*.js","dist/**/*.d.ts","dist/skills/**","patches","scripts"],scripts:{build:"tsup",dev:"tsup --watch",prepare:"husky install node_modules/@netlify/eslint-config-node/.husky/",prepublishOnly:"npm ci && npm test",prepack:"npm run build",test:"run-s build format test:dev",format:"run-s build format:check-fix:*","format:ci":"run-s build format:check:*","format:check-fix:lint":"run-e format:check:lint format:fix:lint","format:check:lint":"cross-env-shell eslint $npm_package_config_eslint","format:fix:lint":"cross-env-shell eslint --fix $npm_package_config_eslint","format:check-fix:prettier":"run-e format:check:prettier format:fix:prettier","format:check:prettier":"cross-env-shell prettier --check $npm_package_config_prettier","format:fix:prettier":"cross-env-shell prettier --write $npm_package_config_prettier","test:dev":"run-s build test:dev:*","test:ci":"run-s build test:ci:*","test:dev:vitest":"LOG=0 vitest --exclude '**/integration/**'","test:ci:vitest":"LOG=0 c8 -r lcovonly -r text -r json vitest --exclude '**/integration/**'","test:integration":"vitest run test/integration/","test:integration:codex":"vitest run test/integration/codex.test.ts","test:integration:claude":"vitest run test/integration/claude.test.ts","test:integration:gemini":"vitest run test/integration/gemini.test.ts","test:integration:create-stage":"vitest run test/integration/create.test.ts","test:integration:skill-invocation":"vitest run test/integration/skill-invocation.test.ts","test:integration:feature-enablement":"vitest run test/integration/feature-enablement.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.87","@anthropic-ai/sdk":"0.78.0","@google/gemini-cli":"0.31.0","@netlify/otel":"^5.1.5","@netlify/ts-cli":"^1.0.4","@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 Nn=An(import.meta.url),$n=ae.dirname(Nn),On=kn(import.meta.url),be=v("shell"),wt=new Set,mr={preferLocal:!0},C=(e,t,r)=>{let[i,n]=Fn(t,r),o={...mr,...n},s=Cn(e,i,o);fr(s,o),wr(s);let a=r?.idleTimeout;return a&&a>0&&yr(s,a),s},gr=(e,t)=>{let r={...mr,...t},i=Pn(e,r);return fr(i,r),wr(i),t?.idleTimeout&&t.idleTimeout>0&&yr(i,t.idleTimeout),i},Fn=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},fr=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(ie.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new Ie).pipe(ie.stdout),e.stdout?.pipe(new Ie).pipe(ie.stdout),e.stderr?.pipe(new Ie).pipe(ie.stderr);return}e.stdout?.pipe(ie.stdout),e.stderr?.pipe(ie.stderr)},_t=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(ie.kill(-e.pid,t),be.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return be.error("Error killing process:",r),!1}},hr=e=>_t(e,"SIGKILL"),yr=(e,t)=>{let r=null,i=()=>{be.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),_t(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(be.log(`Force killing idle process ${e.pid}`),hr(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)},wr=e=>{wt.add(e);let t=lr();if(t){let r=t.onTimesUp(()=>{be.log(`Global timer expired, killing process ${e.pid}`),_t(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(be.log(`Force killing process ${e.pid} after timeout`),hr(e))},5e3)});e.on("exit",()=>{wt.delete(e),r()}),e.on("error",()=>{wt.delete(e),r()})}};function et(e,t){return!!le(e,t)}function le(e,t){if(!ie.env.NETLIFY_LOCAL_MODE)try{let n=On.resolve(pr.name),o=ae.dirname(n);for(;o!==ae.dirname(o);){let s=ae.dirname(o);if(ae.basename(s)==="node_modules"){let a=ae.join(s,".bin",t);if(Qe.existsSync(a))return a;break}o=s}}catch(n){console.error("Could not resolve package.json",n)}if(ie.env.NODE_PATH){let n=ae.join(ie.env.NODE_PATH,".bin",t);if(Qe.existsSync(n))return n}let r=ae.join(e,"node_modules",".bin",t);if(Qe.existsSync(r))return r;let i=ae.join($n,"..","node_modules",".bin",t);if(Qe.existsSync(i))return i}import Ln from"process";var Dn="NETLIFY_FF_",we=()=>{let e={};for(let[t,r]of Object.entries(Ln.env))t.startsWith(Dn)&&r!==void 0&&(e[t]=r);return{byokEnabled:e.NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED==="true"||e.NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED==="1",skillVariations:Object.entries(e).filter(([t,r])=>t.startsWith("NETLIFY_FF_AGENT_RUNNER_SKILL_")&&(r==="true"||r==="1")).map(([t])=>t.replace("NETLIFY_FF_AGENT_RUNNER_SKILL_","").toLowerCase()),modelVersionOverrides:{codex:e.NETLIFY_FF_AGENT_RUNNER_CODEX_VERSION,claude:e.NETLIFY_FF_AGENT_RUNNER_CLAUDE_VERSION,gemini:e.NETLIFY_FF_AGENT_RUNNER_GEMINI_VERSION},raw:e}};var Mn=v("utils"),Un=e=>new Promise(t=>{setTimeout(t,e)}),tt=(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 c,l=new Promise(u=>{c=u});return o=(async()=>{await Promise.resolve();let u=await e(...a);for(c(u);;){if(await Un(t),!i)return r=!1,o=null,u;let p=i,d=n;i=null,n=[],u=await e(...p),d.forEach(g=>{g(u)})}})(),l};return s.flush=async()=>{if((r||i)&&o)return await o,s.flush()},s},Re=(e,t,r=!1)=>{let i=null,n=null,o=null,s=function(...a){n=a,o=this;let c=r&&!i;clearTimeout(i),i=setTimeout(()=>{i=null,r||(e.apply(o,n),n=null,o=null)},t),c&&(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,c=o;i=null,n=null,o=null,e.apply(c,a)}},s},_r=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(i){t&&(r?.error?r.error("Could not parse JSON",i):Mn.error("Could not parse JSON",i))}},Et=e=>e.charAt(0).toUpperCase()+e.slice(1),me=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():Et(t)).join(" ");function _e(e,t){t&&e.log(`Skill invoked: ${t}`)}var Er=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),xr=(e,t)=>{let n=".netlify.app",o="agent-";if(!t)return`${o}${e.slice(0,6)}`;let a=`--${t}${n}`;if(a.length>55)return"";let c=60-a.length;if(c<=0)return"";if(c>=o.length+6){let l=Math.min(c-o.length,e.length);return`${o}${e.slice(0,l)}`}return e.slice(0,c)};var Gn=1e4,xt=(e,t=Gn)=>{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 Tr}from"buffer";import jn from"path";var vr=v("repo"),Ir=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{vr.info("Getting runner diffs");let i=await Bn(r),{hasChanges:n}=i,{status:o}=i;if(!n)return{hasChanges:!1};if(!t){let T=Hn(o);await Vn(T,r)}vr.info("Changes after processing"),await vt(r);let s=await St(o,r);if(await Tt(s,r),n=await qn(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await C("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},c=await C("git",["diff",e.runSha,"HEAD"],a),l=String(c.stdout??"");if(n=!!l,!n)return await Sr(r),{hasChanges:!1,ignored:s};let u=await C("git",["diff",e.runSha,"HEAD","--binary"],a),p=String(u.stdout??""),d,g;if(e.sha){let T=await C("git",["diff",e.sha,"HEAD"],a);d=String(T.stdout??"");let w=await C("git",["diff",e.sha,"HEAD","--binary"],a),_=String(w.stdout??"");d!==_&&(g=Tr.from(_).toString("base64"))}await Sr(r);let S={hasChanges:!0,diff:l,resultDiff:d,ignored:s};return l!==p&&(S.diffBinary=Tr.from(p).toString("base64")),g&&(S.resultDiffBinary=g),S},Sr=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await C("git",["reset","--soft","HEAD~1"],{cwd:e})},Tt=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await C("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},vt=async(e=process.cwd())=>{let t=await C("git",["status","-s"],{cwd:e});return String(t.stdout??"")},br=/.. (.+)?\.log$/,Yn=[br],Bn=async(e=process.cwd())=>{let t=await vt(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
|
|
8
|
+
`);return o.length>e.length*.8?e:o}import{execSync as pi}from"child_process";import jr from"fs/promises";import mi from"path";import xe from"process";import{getTracer as gi}from"@netlify/otel";import De from"process";var ne=class extends Error{constructor(r,i,n,o=!1){super(r);this.statusCode=i;this.userMessage=n;this.isCreditLimitExceeded=o;this.name="GracefulShutdownError"}},ze=e=>e instanceof ne,Ke=class extends Error{constructor(t){super(t),this.name="ProviderError"}};var Je=De.env.NETLIFY_API_URL,Xe=De.env.NETLIFY_API_TOKEN,W=v("api"),ve=()=>De.env.NETLIFY_LOCAL_MODE==="true",de=async(e,t={})=>{if(!Je||!Xe)throw new Error("No API URL or token");let r=new URL(e,Je),i={...t,headers:{...t.headers,Authorization:`Bearer ${Xe}`}};De.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(De.env.AGENT_RUNNERS_DEBUG==="true")W.log(`Response headers for ${r}:`),n.headers.forEach((a,c)=>{W.log(` ${c}: ${a}`)});else{let a=n.headers.get("x-request-id")||n.headers.get("x-nf-request-id");W.log(`Request ID for ${r}: ${a||"N/A"}`)}if(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 ne(`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 ne(`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},Xt=e=>{W.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Je=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(Xe=e.constants.NETLIFY_API_TOKEN)},Zt=()=>({apiUrl:Je,token:Xe}),Me=async(e,t)=>ve()?(W.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):de(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),K=async(e,t,r)=>ve()?(W.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):de(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var Qt=async e=>ve()?(W.log("Mock API: getSite called",{siteId:e}),{id:e,published_deploy:{id:"id"}}):de(`/api/v1/sites/${e}`),er=async(e,t)=>ve()?(W.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):de(`/api/v1/agent_runners/${e}/sessions/${t}`),tr=(e,t,r)=>de(`/api/v1/accounts/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),rr=(e,t,r)=>de(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),nr=async(e,t)=>ve()?(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"}}):de(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),ir=async(e,t)=>ve()?(W.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):de(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),gt=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 Se=v("ai_gateway"),ft=null;var Ze=async()=>{if(ft)return ft;Se.log("Fetching available AI gateway providers");let e=await fetch(`${Zt().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 ft=t,Se.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},xn=async(e,t)=>{let i=(await Ze()).providers[e];if(!i)return Se.log(`Provider '${e}' not found`),!1;let n=i.models.includes(t);return Se.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},or=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),Se.log("Requesting AI gateway information");let l=await(o?tr(e.accountId,e.id,e.sessionId):rr(e.siteId,e.id,e.sessionId));if({token:t,url:n}=l,r=l.expires_at?l.expires_at*1e3:void 0,Se.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(),Ze()]),{get url(){return n},get token(){return t},isModelAvailableForProvider:xn}};import ie from"process";import ae from"path";import Qe from"fs";import{fileURLToPath as An}from"url";import{createRequire as kn}from"module";import{execa as Cn,execaCommand as Pn}from"execa";import{Transform as Tn}from"stream";function vn(){let e=process.env.NETLIFY_SENSITIVE_ENV_KEYS;return e?e.split(",").map(t=>t.trim()).filter(Boolean):[]}function Sn(e){let t=e.toLowerCase();return t==="true"||t==="false"?!0:e.trim().length<4}function In(){let t=vn().map(r=>process.env[r]).filter(r=>!(!r||Sn(r)));return[...new Set(t)].sort((r,i)=>i.length-r.length)}function se(e){if(typeof e!="string")return e;let t=In();if(t.length===0)return e;let r=e;return t.forEach(i=>{let n=new RegExp(bn(i),"g");r=r.replace(n,"******")}),r}function bn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Ie=class extends Tn{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,i){let n=t.toString(),o=se(n);i(null,o)}};function sr(){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"?se(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"?se(i):i;return typeof n=="function"?r(s,n):r(s,n,o)}}var Ue=null,ar=e=>(Ue&&Ue.destroy(),Ue=new pe({totalAllowedTime:e}),Ue),lr=()=>Ue;var pe=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,c)=>{o=setTimeout(()=>{c(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 cr="netlify-agent-runner-context.md",ht="task-history",J=".netlify",he="results.md",yt="assets",ur="features";var dr="free";var ye=1800*1e3,h={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 pr={name:"@netlify/agent-runner-cli",type:"module",version:"1.98.1",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","test:integration:feature-enablement":"vitest run test/integration/feature-enablement.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.87","@anthropic-ai/sdk":"0.78.0","@google/gemini-cli":"0.31.0","@netlify/otel":"^5.1.5","@netlify/ts-cli":"^1.0.4","@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 Nn=An(import.meta.url),$n=ae.dirname(Nn),On=kn(import.meta.url),be=v("shell"),wt=new Set,mr={preferLocal:!0},C=(e,t,r)=>{let[i,n]=Fn(t,r),o={...mr,...n},s=Cn(e,i,o);fr(s,o),wr(s);let a=r?.idleTimeout;return a&&a>0&&yr(s,a),s},gr=(e,t)=>{let r={...mr,...t},i=Pn(e,r);return fr(i,r),wr(i),t?.idleTimeout&&t.idleTimeout>0&&yr(i,t.idleTimeout),i},Fn=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},fr=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(ie.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new Ie).pipe(ie.stdout),e.stdout?.pipe(new Ie).pipe(ie.stdout),e.stderr?.pipe(new Ie).pipe(ie.stderr);return}e.stdout?.pipe(ie.stdout),e.stderr?.pipe(ie.stderr)},_t=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(ie.kill(-e.pid,t),be.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return be.error("Error killing process:",r),!1}},hr=e=>_t(e,"SIGKILL"),yr=(e,t)=>{let r=null,i=()=>{be.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),_t(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(be.log(`Force killing idle process ${e.pid}`),hr(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)},wr=e=>{wt.add(e);let t=lr();if(t){let r=t.onTimesUp(()=>{be.log(`Global timer expired, killing process ${e.pid}`),_t(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(be.log(`Force killing process ${e.pid} after timeout`),hr(e))},5e3)});e.on("exit",()=>{wt.delete(e),r()}),e.on("error",()=>{wt.delete(e),r()})}};function et(e,t){return!!le(e,t)}function le(e,t){if(!ie.env.NETLIFY_LOCAL_MODE)try{let n=On.resolve(pr.name),o=ae.dirname(n);for(;o!==ae.dirname(o);){let s=ae.dirname(o);if(ae.basename(s)==="node_modules"){let a=ae.join(s,".bin",t);if(Qe.existsSync(a))return a;break}o=s}}catch(n){console.error("Could not resolve package.json",n)}if(ie.env.NODE_PATH){let n=ae.join(ie.env.NODE_PATH,".bin",t);if(Qe.existsSync(n))return n}let r=ae.join(e,"node_modules",".bin",t);if(Qe.existsSync(r))return r;let i=ae.join($n,"..","node_modules",".bin",t);if(Qe.existsSync(i))return i}import Ln from"process";var Dn="NETLIFY_FF_",we=()=>{let e={};for(let[t,r]of Object.entries(Ln.env))t.startsWith(Dn)&&r!==void 0&&(e[t]=r);return{byokEnabled:e.NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED==="true"||e.NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED==="1",skillVariations:Object.entries(e).filter(([t,r])=>t.startsWith("NETLIFY_FF_AGENT_RUNNER_SKILL_")&&(r==="true"||r==="1")).map(([t])=>t.replace("NETLIFY_FF_AGENT_RUNNER_SKILL_","").toLowerCase()),modelVersionOverrides:{codex:e.NETLIFY_FF_AGENT_RUNNER_CODEX_VERSION,claude:e.NETLIFY_FF_AGENT_RUNNER_CLAUDE_VERSION,gemini:e.NETLIFY_FF_AGENT_RUNNER_GEMINI_VERSION},raw:e}};var Mn=v("utils"),Un=e=>new Promise(t=>{setTimeout(t,e)}),tt=(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 c,l=new Promise(u=>{c=u});return o=(async()=>{await Promise.resolve();let u=await e(...a);for(c(u);;){if(await Un(t),!i)return r=!1,o=null,u;let p=i,d=n;i=null,n=[],u=await e(...p),d.forEach(g=>{g(u)})}})(),l};return s.flush=async()=>{if((r||i)&&o)return await o,s.flush()},s},Re=(e,t,r=!1)=>{let i=null,n=null,o=null,s=function(...a){n=a,o=this;let c=r&&!i;clearTimeout(i),i=setTimeout(()=>{i=null,r||(e.apply(o,n),n=null,o=null)},t),c&&(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,c=o;i=null,n=null,o=null,e.apply(c,a)}},s},_r=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(i){t&&(r?.error?r.error("Could not parse JSON",i):Mn.error("Could not parse JSON",i))}},Et=e=>e.charAt(0).toUpperCase()+e.slice(1),me=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():Et(t)).join(" ");function _e(e,t){t&&e.log(`Skill invoked: ${t}`)}var Er=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),xr=(e,t)=>{let n=".netlify.app",o="agent-";if(!t)return`${o}${e.slice(0,6)}`;let a=`--${t}${n}`;if(a.length>55)return"";let c=60-a.length;if(c<=0)return"";if(c>=o.length+6){let l=Math.min(c-o.length,e.length);return`${o}${e.slice(0,l)}`}return e.slice(0,c)};var Gn=1e4,xt=(e,t=Gn)=>{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 Tr}from"buffer";import jn from"path";var vr=v("repo"),Ir=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{vr.info("Getting runner diffs");let i=await Bn(r),{hasChanges:n}=i,{status:o}=i;if(!n)return{hasChanges:!1};if(!t){let T=Hn(o);await Vn(T,r)}vr.info("Changes after processing"),await vt(r);let s=await St(o,r);if(await Tt(s,r),n=await qn(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await C("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},c=await C("git",["diff",e.runSha,"HEAD"],a),l=String(c.stdout??"");if(n=!!l,!n)return await Sr(r),{hasChanges:!1,ignored:s};let u=await C("git",["diff",e.runSha,"HEAD","--binary"],a),p=String(u.stdout??""),d,g;if(e.sha){let T=await C("git",["diff",e.sha,"HEAD"],a);d=String(T.stdout??"");let w=await C("git",["diff",e.sha,"HEAD","--binary"],a),_=String(w.stdout??"");d!==_&&(g=Tr.from(_).toString("base64"))}await Sr(r);let S={hasChanges:!0,diff:l,resultDiff:d,ignored:s};return l!==p&&(S.diffBinary=Tr.from(p).toString("base64")),g&&(S.resultDiffBinary=g),S},Sr=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await C("git",["reset","--soft","HEAD~1"],{cwd:e})},Tt=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await C("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},vt=async(e=process.cwd())=>{let t=await C("git",["status","-s"],{cwd:e});return String(t.stdout??"")},br=/.. (.+)?\.log$/,Yn=[br],Bn=async(e=process.cwd())=>{let t=await vt(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
|
|
9
9
|
`).filter(n=>Yn.some(s=>s instanceof RegExp?s.test(n):n===s)?!1:n[1]?.trim()!=="")).length!==0,status:t}},qn=async(e=process.cwd())=>{try{return await C("git",["diff","--staged","--quiet"],{cwd:e}),!1}catch{return!0}},Ge=async(e=process.cwd())=>{let{stdout:t}=await C("git",["rev-parse","HEAD"],{cwd:e});return String(t??"").trim()},Rr=async(e=process.cwd())=>{let{stdout:t}=await C("git",["rev-list","--max-parents=0","HEAD"],{cwd:e});return String(t??"").trim()},St=async(e,t=process.cwd())=>{e||=await vt(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}`,c=n.startsWith(`?? ${s}/`)||n.startsWith(`?? ${s}${jn.sep}`);(a||c)&&i.push(`:!${s}`)});let o=n.match(br)?.[1];o&&i.push(`:!${o}.log`)}),i},It=async(e=process.cwd())=>{await C("git",["reset","--hard","HEAD"],{cwd:e})},Hn=e=>{let t=e.split(`
|
|
11
11
|
`).reduce((r,i)=>{if(!i)return r;let[n,o,,...s]=i,a=s.join(""),c=n.trim(),l=o.trim();return r[a]?r[a].change=l:r[a]={filePath:a,stage:c,change:l},r},{});return Object.values(t)},Vn=async(e,t=process.cwd())=>{let r=e.filter(i=>i.stage&&!i.change).map(i=>i.filePath);r.length!==0&&await C("git",["restore","--staged","--worktree","--pathspec-from-file=-"],{cwd:t,input:r.join(`
|
package/dist/bin.js
CHANGED
|
@@ -5,7 +5,7 @@ import Kt from"process";import fi from"minimist";import{createRequire as oi}from
|
|
|
5
5
|
${s}
|
|
6
6
|
</extracted_error_chunk>`).join(`
|
|
7
7
|
|
|
8
|
-
`);return i.length>e.length*.8?e:i}import{execSync as _o}from"child_process";import Kr from"fs/promises";import wo from"path";import _e from"process";import{getTracer as To}from"@netlify/otel";import De from"process";var te=class extends Error{constructor(r,o,n,i=!1){super(r);this.statusCode=o;this.userMessage=n;this.isCreditLimitExceeded=i;this.name="GracefulShutdownError"}},Ke=e=>e instanceof te,Le=class extends Error{constructor(t){super(t),this.name="ProviderError"}},er=e=>e instanceof Le;var ze=De.env.NETLIFY_API_URL,Je=De.env.NETLIFY_API_TOKEN,H=v("api"),Te=()=>De.env.NETLIFY_LOCAL_MODE==="true",ce=async(e,t={})=>{if(!ze||!Je)throw new Error("No API URL or token");let r=new URL(e,ze),o={...t,headers:{...t.headers,Authorization:`Bearer ${Je}`}};De.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(De.env.AGENT_RUNNERS_DEBUG==="true")H.log(`Response headers for ${r}:`),n.headers.forEach((a,d)=>{H.log(` ${d}: ${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 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},tr=e=>{H.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(ze=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(Je=e.constants.NETLIFY_API_TOKEN)},rr=()=>({apiUrl:ze,token:Je}),Me=async(e,t)=>Te()?(H.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):ce(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),V=async(e,t,r)=>Te()?(H.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):ce(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var nr=async e=>Te()?(H.log("Mock API: getSite called",{siteId:e}),{id:e,published_deploy:{id:"id"}}):ce(`/api/v1/sites/${e}`),or=async(e,t)=>Te()?(H.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):ce(`/api/v1/agent_runners/${e}/sessions/${t}`),ir=(e,t,r)=>ce(`/api/v1/accounts/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),sr=(e,t,r)=>ce(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),ar=async(e,t)=>Te()?(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"}}):ce(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),lr=async(e,t)=>Te()?(H.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):ce(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),mt=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 xe=v("ai_gateway"),gt=null;var Xe=async()=>{if(gt)return gt;xe.log("Fetching available AI gateway providers");let e=await fetch(`${rr().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 gt=t,xe.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},bn=async(e,t)=>{let o=(await Xe()).providers[e];if(!o)return xe.log(`Provider '${e}' not found`),!1;let n=o.models.includes(t);return xe.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},cr=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),xe.log("Requesting AI gateway information");let l=await(i?ir(e.accountId,e.id,e.sessionId):sr(e.siteId,e.id,e.sessionId));if({token:t,url:n}=l,r=l.expires_at?l.expires_at*1e3:void 0,xe.log("Got AI gateway information",{token:!!t,expiresAt:r,url:n}),r){let u=r-Date.now()-6e4;u>0&&(o=setTimeout(()=>{a()},u))}};return await Promise.all([a(),Xe()]),{get url(){return n},get token(){return t},isModelAvailableForProvider:bn}};import re from"process";import se from"path";import Ze from"fs";import{fileURLToPath as Fn}from"url";import{createRequire as $n}from"module";import{execa as Ln,execaCommand as Dn}from"execa";import{Transform as An}from"stream";function Cn(){let e=process.env.NETLIFY_SENSITIVE_ENV_KEYS;return e?e.split(",").map(t=>t.trim()).filter(Boolean):[]}function kn(e){let t=e.toLowerCase();return t==="true"||t==="false"?!0:e.trim().length<4}function Nn(){let t=Cn().map(r=>process.env[r]).filter(r=>!(!r||kn(r)));return[...new Set(t)].sort((r,o)=>o.length-r.length)}function ie(e){if(typeof e!="string")return e;let t=Nn();if(t.length===0)return e;let r=e;return t.forEach(o=>{let n=new RegExp(Pn(o),"g");r=r.replace(n,"******")}),r}function Pn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ve=class extends An{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,o){let n=t.toString(),i=ie(n);o(null,i)}};function ur(){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"?ie(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"?ie(o):o;return typeof n=="function"?r(s,n):r(s,n,i)}}var Ue=null,dr=e=>(Ue&&Ue.destroy(),Ue=new ue({totalAllowedTime:e}),Ue),pr=()=>Ue;var ue=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,d)=>{i=setTimeout(()=>{d(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 mr="netlify-agent-runner-context.md",ft="task-history",z=".netlify",fe="results.md",ht="assets",gr="features",yt="other",Et="personal";var _t="enterprise",Ge="free",fr=[Et,"pro",_t,Ge],hr=["normal","redeploy","create","ask","dtn-prod-iteration","rebase"],yr="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.",he=1800*1e3,h={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 Er={name:"@netlify/agent-runner-cli",type:"module",version:"1.98.0",description:"CLI tool for running Netlify agents",main:"./dist/index.js",types:"./dist/index.d.ts",exports:"./dist/index.js",bin:{"agent-runner-cli":"./dist/bin.js","agent-runner-cli-local":"./dist/bin-local.js"},files:["dist/**/*.js","dist/**/*.d.ts","dist/skills/**","patches","scripts"],scripts:{build:"tsup",dev:"tsup --watch",prepare:"husky install node_modules/@netlify/eslint-config-node/.husky/",prepublishOnly:"npm ci && npm test",prepack:"npm run build",test:"run-s build format test:dev",format:"run-s build format:check-fix:*","format:ci":"run-s build format:check:*","format:check-fix:lint":"run-e format:check:lint format:fix:lint","format:check:lint":"cross-env-shell eslint $npm_package_config_eslint","format:fix:lint":"cross-env-shell eslint --fix $npm_package_config_eslint","format:check-fix:prettier":"run-e format:check:prettier format:fix:prettier","format:check:prettier":"cross-env-shell prettier --check $npm_package_config_prettier","format:fix:prettier":"cross-env-shell prettier --write $npm_package_config_prettier","test:dev":"run-s build test:dev:*","test:ci":"run-s build test:ci:*","test:dev:vitest":"LOG=0 vitest --exclude '**/integration/**'","test:ci:vitest":"LOG=0 c8 -r lcovonly -r text -r json vitest --exclude '**/integration/**'","test:integration":"vitest run test/integration/","test:integration:codex":"vitest run test/integration/codex.test.ts","test:integration:claude":"vitest run test/integration/claude.test.ts","test:integration:gemini":"vitest run test/integration/gemini.test.ts","test:integration:create-stage":"vitest run test/integration/create.test.ts","test:integration:skill-invocation":"vitest run test/integration/skill-invocation.test.ts","test:integration:feature-enablement":"vitest run test/integration/feature-enablement.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.87","@anthropic-ai/sdk":"0.78.0","@google/gemini-cli":"0.31.0","@netlify/otel":"^5.1.5","@netlify/ts-cli":"^1.0.4","@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 Mn=Fn(import.meta.url),Un=se.dirname(Mn),Gn=$n(import.meta.url),Ie=v("shell"),wt=new Set,_r={preferLocal:!0},P=(e,t,r)=>{let[o,n]=jn(t,r),i={..._r,...n},s=Ln(e,o,i);Tr(s,i),Ir(s);let a=r?.idleTimeout;return a&&a>0&&vr(s,a),s},wr=(e,t)=>{let r={..._r,...t},o=Dn(e,r);return Tr(o,r),Ir(o),t?.idleTimeout&&t.idleTimeout>0&&vr(o,t.idleTimeout),o},jn=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},Tr=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(re.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new ve).pipe(re.stdout),e.stdout?.pipe(new ve).pipe(re.stdout),e.stderr?.pipe(new ve).pipe(re.stderr);return}e.stdout?.pipe(re.stdout),e.stderr?.pipe(re.stderr)},Tt=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(re.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}},xr=e=>Tt(e,"SIGKILL"),vr=(e,t)=>{let r=null,o=()=>{Ie.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),Tt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(Ie.log(`Force killing idle process ${e.pid}`),xr(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)},Ir=e=>{wt.add(e);let t=pr();if(t){let r=t.onTimesUp(()=>{Ie.log(`Global timer expired, killing process ${e.pid}`),Tt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(Ie.log(`Force killing process ${e.pid} after timeout`),xr(e))},5e3)});e.on("exit",()=>{wt.delete(e),r()}),e.on("error",()=>{wt.delete(e),r()})}};function de(e,t){if(!re.env.NETLIFY_LOCAL_MODE)try{let n=Gn.resolve(Er.name),i=se.dirname(n);for(;i!==se.dirname(i);){let s=se.dirname(i);if(se.basename(s)==="node_modules"){let a=se.join(s,".bin",t);if(Ze.existsSync(a))return a;break}i=s}}catch(n){console.error("Could not resolve package.json",n)}if(re.env.NODE_PATH){let n=se.join(re.env.NODE_PATH,".bin",t);if(Ze.existsSync(n))return n}let r=se.join(e,"node_modules",".bin",t);if(Ze.existsSync(r))return r;let o=se.join(Un,"..","node_modules",".bin",t);if(Ze.existsSync(o))return o}import Yn from"process";var Bn="NETLIFY_FF_",ne=()=>{let e={};for(let[t,r]of Object.entries(Yn.env))t.startsWith(Bn)&&r!==void 0&&(e[t]=r);return{byokEnabled:e.NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED==="true"||e.NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED==="1",skillVariations:Object.entries(e).filter(([t,r])=>t.startsWith("NETLIFY_FF_AGENT_RUNNER_SKILL_")&&(r==="true"||r==="1")).map(([t])=>t.replace("NETLIFY_FF_AGENT_RUNNER_SKILL_","").toLowerCase()),modelVersionOverrides:{codex:e.NETLIFY_FF_AGENT_RUNNER_CODEX_VERSION,claude:e.NETLIFY_FF_AGENT_RUNNER_CLAUDE_VERSION,gemini:e.NETLIFY_FF_AGENT_RUNNER_GEMINI_VERSION},raw:e}};var Sr=v("utils"),qn=e=>new Promise(t=>{setTimeout(t,e)}),Qe=(e,t=3e3)=>{let r=!1,o=null,n=[],i=null,s=(...a)=>{if(r)return o=a,new Promise(u=>{n.push(u)});r=!0;let d,l=new Promise(u=>{d=u});return i=(async()=>{await Promise.resolve();let u=await e(...a);for(d(u);;){if(await qn(t),!o)return r=!1,i=null,u;let p=o,c=n;o=null,n=[],u=await e(...p),c.forEach(g=>{g(u)})}})(),l};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 d=r&&!o;clearTimeout(o),o=setTimeout(()=>{o=null,r||(e.apply(i,n),n=null,i=null)},t),d&&(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,d=i;o=null,n=null,i=null,e.apply(d,a)}},s},et=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(o){t&&(r?.error?r.error("Could not parse JSON",o):Sr.error("Could not parse JSON",o))}},xt=e=>e.charAt(0).toUpperCase()+e.slice(1),pe=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():xt(t)).join(" ");function ye(e,t){t&&e.log(`Skill invoked: ${t}`)}var Rr=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),br=(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 d=60-a.length;if(d<=0)return"";if(d>=i.length+6){let l=Math.min(d-i.length,e.length);return`${i}${e.slice(0,l)}`}return e.slice(0,d)},Hn=e=>!e||typeof e!="object"||Array.isArray(e)||Object.keys(e).length===0?!1:!!fr.some(t=>t in e),Ar=()=>{let e={},t=ne().modelVersionOverrides;return Object.entries(t).forEach(([r,o])=>{if(o)try{let n=JSON.parse(o);Hn(n)&&(e[r]=n)}catch(n){let s=n instanceof SyntaxError?"Invalid JSON":n.message;Sr.error(`Could not parse ${r} model version override from feature flag: ${s}`)}}),e},Vn=1e4,vt=(e,t=Vn)=>{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 Cr}from"buffer";import Wn from"path";var kr=v("repo"),Pr=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{kr.info("Getting runner diffs");let o=await zn(r),{hasChanges:n}=o,{status:i}=o;if(!n)return{hasChanges:!1};if(!t){let x=Xn(i);await Zn(x,r)}kr.info("Changes after processing"),await St(r);let s=await bt(i,r);if(await It(s,r),n=await Jn(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},d=await P("git",["diff",e.runSha,"HEAD"],a),l=String(d.stdout??"");if(n=!!l,!n)return await Nr(r),{hasChanges:!1,ignored:s};let u=await P("git",["diff",e.runSha,"HEAD","--binary"],a),p=String(u.stdout??""),c,g;if(e.sha){let x=await P("git",["diff",e.sha,"HEAD"],a);c=String(x.stdout??"");let E=await P("git",["diff",e.sha,"HEAD","--binary"],a),_=String(E.stdout??"");c!==_&&(g=Cr.from(_).toString("base64"))}await Nr(r);let I={hasChanges:!0,diff:l,resultDiff:c,ignored:s};return l!==p&&(I.diffBinary=Cr.from(p).toString("base64")),g&&(I.resultDiffBinary=g),I},Nr=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await P("git",["reset","--soft","HEAD~1"],{cwd:e})},It=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"}},St=async(e=process.cwd())=>{let t=await P("git",["status","-s"],{cwd:e});return String(t.stdout??"")},Or=/.. (.+)?\.log$/,Kn=[Or],zn=async(e=process.cwd())=>{let t=await St(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
|
|
8
|
+
`);return i.length>e.length*.8?e:i}import{execSync as _o}from"child_process";import Kr from"fs/promises";import wo from"path";import _e from"process";import{getTracer as To}from"@netlify/otel";import De from"process";var te=class extends Error{constructor(r,o,n,i=!1){super(r);this.statusCode=o;this.userMessage=n;this.isCreditLimitExceeded=i;this.name="GracefulShutdownError"}},Ke=e=>e instanceof te,Le=class extends Error{constructor(t){super(t),this.name="ProviderError"}},er=e=>e instanceof Le;var ze=De.env.NETLIFY_API_URL,Je=De.env.NETLIFY_API_TOKEN,H=v("api"),Te=()=>De.env.NETLIFY_LOCAL_MODE==="true",ce=async(e,t={})=>{if(!ze||!Je)throw new Error("No API URL or token");let r=new URL(e,ze),o={...t,headers:{...t.headers,Authorization:`Bearer ${Je}`}};De.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(De.env.AGENT_RUNNERS_DEBUG==="true")H.log(`Response headers for ${r}:`),n.headers.forEach((a,d)=>{H.log(` ${d}: ${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 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},tr=e=>{H.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(ze=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(Je=e.constants.NETLIFY_API_TOKEN)},rr=()=>({apiUrl:ze,token:Je}),Me=async(e,t)=>Te()?(H.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):ce(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),V=async(e,t,r)=>Te()?(H.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):ce(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var nr=async e=>Te()?(H.log("Mock API: getSite called",{siteId:e}),{id:e,published_deploy:{id:"id"}}):ce(`/api/v1/sites/${e}`),or=async(e,t)=>Te()?(H.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):ce(`/api/v1/agent_runners/${e}/sessions/${t}`),ir=(e,t,r)=>ce(`/api/v1/accounts/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),sr=(e,t,r)=>ce(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),ar=async(e,t)=>Te()?(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"}}):ce(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),lr=async(e,t)=>Te()?(H.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):ce(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),mt=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 xe=v("ai_gateway"),gt=null;var Xe=async()=>{if(gt)return gt;xe.log("Fetching available AI gateway providers");let e=await fetch(`${rr().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 gt=t,xe.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},bn=async(e,t)=>{let o=(await Xe()).providers[e];if(!o)return xe.log(`Provider '${e}' not found`),!1;let n=o.models.includes(t);return xe.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},cr=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),xe.log("Requesting AI gateway information");let l=await(i?ir(e.accountId,e.id,e.sessionId):sr(e.siteId,e.id,e.sessionId));if({token:t,url:n}=l,r=l.expires_at?l.expires_at*1e3:void 0,xe.log("Got AI gateway information",{token:!!t,expiresAt:r,url:n}),r){let u=r-Date.now()-6e4;u>0&&(o=setTimeout(()=>{a()},u))}};return await Promise.all([a(),Xe()]),{get url(){return n},get token(){return t},isModelAvailableForProvider:bn}};import re from"process";import se from"path";import Ze from"fs";import{fileURLToPath as Fn}from"url";import{createRequire as $n}from"module";import{execa as Ln,execaCommand as Dn}from"execa";import{Transform as An}from"stream";function Cn(){let e=process.env.NETLIFY_SENSITIVE_ENV_KEYS;return e?e.split(",").map(t=>t.trim()).filter(Boolean):[]}function kn(e){let t=e.toLowerCase();return t==="true"||t==="false"?!0:e.trim().length<4}function Nn(){let t=Cn().map(r=>process.env[r]).filter(r=>!(!r||kn(r)));return[...new Set(t)].sort((r,o)=>o.length-r.length)}function ie(e){if(typeof e!="string")return e;let t=Nn();if(t.length===0)return e;let r=e;return t.forEach(o=>{let n=new RegExp(Pn(o),"g");r=r.replace(n,"******")}),r}function Pn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ve=class extends An{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,o){let n=t.toString(),i=ie(n);o(null,i)}};function ur(){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"?ie(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"?ie(o):o;return typeof n=="function"?r(s,n):r(s,n,i)}}var Ue=null,dr=e=>(Ue&&Ue.destroy(),Ue=new ue({totalAllowedTime:e}),Ue),pr=()=>Ue;var ue=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,d)=>{i=setTimeout(()=>{d(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 mr="netlify-agent-runner-context.md",ft="task-history",z=".netlify",fe="results.md",ht="assets",gr="features",yt="other",Et="personal";var _t="enterprise",Ge="free",fr=[Et,"pro",_t,Ge],hr=["normal","redeploy","create","ask","dtn-prod-iteration","rebase"],yr="The base code 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.",he=1800*1e3,h={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 Er={name:"@netlify/agent-runner-cli",type:"module",version:"1.98.1",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","test:integration:feature-enablement":"vitest run test/integration/feature-enablement.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.87","@anthropic-ai/sdk":"0.78.0","@google/gemini-cli":"0.31.0","@netlify/otel":"^5.1.5","@netlify/ts-cli":"^1.0.4","@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 Mn=Fn(import.meta.url),Un=se.dirname(Mn),Gn=$n(import.meta.url),Ie=v("shell"),wt=new Set,_r={preferLocal:!0},P=(e,t,r)=>{let[o,n]=jn(t,r),i={..._r,...n},s=Ln(e,o,i);Tr(s,i),Ir(s);let a=r?.idleTimeout;return a&&a>0&&vr(s,a),s},wr=(e,t)=>{let r={..._r,...t},o=Dn(e,r);return Tr(o,r),Ir(o),t?.idleTimeout&&t.idleTimeout>0&&vr(o,t.idleTimeout),o},jn=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},Tr=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(re.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new ve).pipe(re.stdout),e.stdout?.pipe(new ve).pipe(re.stdout),e.stderr?.pipe(new ve).pipe(re.stderr);return}e.stdout?.pipe(re.stdout),e.stderr?.pipe(re.stderr)},Tt=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(re.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}},xr=e=>Tt(e,"SIGKILL"),vr=(e,t)=>{let r=null,o=()=>{Ie.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),Tt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(Ie.log(`Force killing idle process ${e.pid}`),xr(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)},Ir=e=>{wt.add(e);let t=pr();if(t){let r=t.onTimesUp(()=>{Ie.log(`Global timer expired, killing process ${e.pid}`),Tt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(Ie.log(`Force killing process ${e.pid} after timeout`),xr(e))},5e3)});e.on("exit",()=>{wt.delete(e),r()}),e.on("error",()=>{wt.delete(e),r()})}};function de(e,t){if(!re.env.NETLIFY_LOCAL_MODE)try{let n=Gn.resolve(Er.name),i=se.dirname(n);for(;i!==se.dirname(i);){let s=se.dirname(i);if(se.basename(s)==="node_modules"){let a=se.join(s,".bin",t);if(Ze.existsSync(a))return a;break}i=s}}catch(n){console.error("Could not resolve package.json",n)}if(re.env.NODE_PATH){let n=se.join(re.env.NODE_PATH,".bin",t);if(Ze.existsSync(n))return n}let r=se.join(e,"node_modules",".bin",t);if(Ze.existsSync(r))return r;let o=se.join(Un,"..","node_modules",".bin",t);if(Ze.existsSync(o))return o}import Yn from"process";var Bn="NETLIFY_FF_",ne=()=>{let e={};for(let[t,r]of Object.entries(Yn.env))t.startsWith(Bn)&&r!==void 0&&(e[t]=r);return{byokEnabled:e.NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED==="true"||e.NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED==="1",skillVariations:Object.entries(e).filter(([t,r])=>t.startsWith("NETLIFY_FF_AGENT_RUNNER_SKILL_")&&(r==="true"||r==="1")).map(([t])=>t.replace("NETLIFY_FF_AGENT_RUNNER_SKILL_","").toLowerCase()),modelVersionOverrides:{codex:e.NETLIFY_FF_AGENT_RUNNER_CODEX_VERSION,claude:e.NETLIFY_FF_AGENT_RUNNER_CLAUDE_VERSION,gemini:e.NETLIFY_FF_AGENT_RUNNER_GEMINI_VERSION},raw:e}};var Sr=v("utils"),qn=e=>new Promise(t=>{setTimeout(t,e)}),Qe=(e,t=3e3)=>{let r=!1,o=null,n=[],i=null,s=(...a)=>{if(r)return o=a,new Promise(u=>{n.push(u)});r=!0;let d,l=new Promise(u=>{d=u});return i=(async()=>{await Promise.resolve();let u=await e(...a);for(d(u);;){if(await qn(t),!o)return r=!1,i=null,u;let p=o,c=n;o=null,n=[],u=await e(...p),c.forEach(g=>{g(u)})}})(),l};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 d=r&&!o;clearTimeout(o),o=setTimeout(()=>{o=null,r||(e.apply(i,n),n=null,i=null)},t),d&&(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,d=i;o=null,n=null,i=null,e.apply(d,a)}},s},et=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(o){t&&(r?.error?r.error("Could not parse JSON",o):Sr.error("Could not parse JSON",o))}},xt=e=>e.charAt(0).toUpperCase()+e.slice(1),pe=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():xt(t)).join(" ");function ye(e,t){t&&e.log(`Skill invoked: ${t}`)}var Rr=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),br=(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 d=60-a.length;if(d<=0)return"";if(d>=i.length+6){let l=Math.min(d-i.length,e.length);return`${i}${e.slice(0,l)}`}return e.slice(0,d)},Hn=e=>!e||typeof e!="object"||Array.isArray(e)||Object.keys(e).length===0?!1:!!fr.some(t=>t in e),Ar=()=>{let e={},t=ne().modelVersionOverrides;return Object.entries(t).forEach(([r,o])=>{if(o)try{let n=JSON.parse(o);Hn(n)&&(e[r]=n)}catch(n){let s=n instanceof SyntaxError?"Invalid JSON":n.message;Sr.error(`Could not parse ${r} model version override from feature flag: ${s}`)}}),e},Vn=1e4,vt=(e,t=Vn)=>{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 Cr}from"buffer";import Wn from"path";var kr=v("repo"),Pr=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{kr.info("Getting runner diffs");let o=await zn(r),{hasChanges:n}=o,{status:i}=o;if(!n)return{hasChanges:!1};if(!t){let x=Xn(i);await Zn(x,r)}kr.info("Changes after processing"),await St(r);let s=await bt(i,r);if(await It(s,r),n=await Jn(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},d=await P("git",["diff",e.runSha,"HEAD"],a),l=String(d.stdout??"");if(n=!!l,!n)return await Nr(r),{hasChanges:!1,ignored:s};let u=await P("git",["diff",e.runSha,"HEAD","--binary"],a),p=String(u.stdout??""),c,g;if(e.sha){let x=await P("git",["diff",e.sha,"HEAD"],a);c=String(x.stdout??"");let E=await P("git",["diff",e.sha,"HEAD","--binary"],a),_=String(E.stdout??"");c!==_&&(g=Cr.from(_).toString("base64"))}await Nr(r);let I={hasChanges:!0,diff:l,resultDiff:c,ignored:s};return l!==p&&(I.diffBinary=Cr.from(p).toString("base64")),g&&(I.resultDiffBinary=g),I},Nr=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await P("git",["reset","--soft","HEAD~1"],{cwd:e})},It=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"}},St=async(e=process.cwd())=>{let t=await P("git",["status","-s"],{cwd:e});return String(t.stdout??"")},Or=/.. (.+)?\.log$/,Kn=[Or],zn=async(e=process.cwd())=>{let t=await St(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}},Jn=async(e=process.cwd())=>{try{return await P("git",["diff","--staged","--quiet"],{cwd:e}),!1}catch{return!0}},Rt=async(e=process.cwd())=>{let{stdout:t}=await P("git",["rev-parse","HEAD"],{cwd:e});return String(t??"").trim()},Fr=async(e=process.cwd())=>{let{stdout:t}=await P("git",["rev-list","--max-parents=0","HEAD"],{cwd:e});return String(t??"").trim()},bt=async(e,t=process.cwd())=>{e||=await St(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}`,d=n.startsWith(`?? ${s}/`)||n.startsWith(`?? ${s}${Wn.sep}`);(a||d)&&o.push(`:!${s}`)});let i=n.match(Or)?.[1];i&&o.push(`:!${i}.log`)}),o},At=async(e=process.cwd())=>{await P("git",["reset","--hard","HEAD"],{cwd:e})},Xn=e=>{let t=e.split(`
|
|
11
11
|
`).reduce((r,o)=>{if(!o)return r;let[n,i,,...s]=o,a=s.join(""),d=n.trim(),l=i.trim();return r[a]?r[a].change=l:r[a]={filePath:a,stage:d,change:l},r},{});return Object.values(t)},Zn=async(e,t=process.cwd())=>{let r=e.filter(o=>o.stage&&!o.change).map(o=>o.filePath);r.length!==0&&await P("git",["restore","--staged","--worktree","--pathspec-from-file=-"],{cwd:t,input:r.join(`
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import{createRequire as ji}from"module";import{createTracerProvider as on}from"@
|
|
|
4
4
|
${s}
|
|
5
5
|
</extracted_error_chunk>`).join(`
|
|
6
6
|
|
|
7
|
-
`);return o.length>e.length*.8?e:o}import{execSync as ri}from"child_process";import Or from"fs/promises";import ni from"path";import we from"process";import{getTracer as ii}from"@netlify/otel";import Fe from"process";var ee=class extends Error{constructor(r,i,n,o=!1){super(r);this.statusCode=i;this.userMessage=n;this.isCreditLimitExceeded=o;this.name="GracefulShutdownError"}},He=e=>e instanceof ee,qe=class extends Error{constructor(t){super(t),this.name="ProviderError"}};var We=Fe.env.NETLIFY_API_URL,Ve=Fe.env.NETLIFY_API_TOKEN,H=v("api"),Ee=()=>Fe.env.NETLIFY_LOCAL_MODE==="true",ae=async(e,t={})=>{if(!We||!Ve)throw new Error("No API URL or token");let r=new URL(e,We),i={...t,headers:{...t.headers,Authorization:`Bearer ${Ve}`}};Fe.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(Fe.env.AGENT_RUNNERS_DEBUG==="true")H.log(`Response headers for ${r}:`),n.headers.forEach((a,d)=>{H.log(` ${d}: ${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(o||H.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 ee(`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 ee(`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},Ht=e=>{H.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(We=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(Ve=e.constants.NETLIFY_API_TOKEN)},Wt=()=>({apiUrl:We,token:Ve}),Oe=async(e,t)=>Ee()?(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)=>Ee()?(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 Vt=async e=>Ee()?(H.log("Mock API: getSite called",{siteId:e}),{id:e,published_deploy:{id:"id"}}):ae(`/api/v1/sites/${e}`),Kt=async(e,t)=>Ee()?(H.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):ae(`/api/v1/agent_runners/${e}/sessions/${t}`),zt=(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}),Jt=(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}),Xt=async(e,t)=>Ee()?(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"}),Zt=async(e,t)=>Ee()?(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"}),ut=async(e,t,{maxRetries:r=3,baseDelayMs:i=500}={})=>{H.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);H.warn(`S3 upload attempt ${n}/${r} failed: ${o.message}. Retrying in ${s}ms...`),await new Promise(a=>setTimeout(a,s))}};var xe=v("ai_gateway"),ct=null;var Ke=async()=>{if(ct)return ct;xe.log("Fetching available AI gateway providers");let e=await fetch(`${Wt().apiUrl}/api/v1/ai-gateway/providers`);if(!e.ok)throw new Error(`Failed to fetch AI gateway providers: ${e.statusText}`);let t=await e.json();return ct=t,xe.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},dn=async(e,t)=>{let i=(await Ke()).providers[e];if(!i)return xe.log(`Provider '${e}' not found`),!1;let n=i.models.includes(t);return xe.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},Qt=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),xe.log("Requesting AI gateway information");let l=await(o?zt(e.accountId,e.id,e.sessionId):Jt(e.siteId,e.id,e.sessionId));if({token:t,url:n}=l,r=l.expires_at?l.expires_at*1e3:void 0,xe.log("Got AI gateway information",{token:!!t,expiresAt:r,url:n}),r){let c=r-Date.now()-6e4;c>0&&(i=setTimeout(()=>{a()},c))}};return await Promise.all([a(),Ke()]),{get url(){return n},get token(){return t},isModelAvailableForProvider:dn}};import te from"process";import ie from"path";import ze from"fs";import{fileURLToPath as wn}from"url";import{createRequire as _n}from"module";import{execa as En,execaCommand as xn}from"execa";import{Transform as pn}from"stream";function mn(){let e=process.env.NETLIFY_SENSITIVE_ENV_KEYS;return e?e.split(",").map(t=>t.trim()).filter(Boolean):[]}function gn(e){let t=e.toLowerCase();return t==="true"||t==="false"?!0:e.trim().length<4}function fn(){let t=mn().map(r=>process.env[r]).filter(r=>!(!r||gn(r)));return[...new Set(t)].sort((r,i)=>i.length-r.length)}function ne(e){if(typeof e!="string")return e;let t=fn();if(t.length===0)return e;let r=e;return t.forEach(i=>{let n=new RegExp(hn(i),"g");r=r.replace(n,"******")}),r}function hn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Te=class extends pn{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,i){let n=t.toString(),o=ne(n);i(null,o)}};function er(){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"?ne(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"?ne(i):i;return typeof n=="function"?r(s,n):r(s,n,o)}}var Le=null,tr=e=>(Le&&Le.destroy(),Le=new le({totalAllowedTime:e}),Le),rr=()=>Le;var le=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,d)=>{o=setTimeout(()=>{d(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 nr="netlify-agent-runner-context.md",dt="task-history",K=".netlify",me="results.md",pt="assets",ir="features";var or="free";var ge=1800*1e3,h={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 sr={name:"@netlify/agent-runner-cli",type:"module",version:"1.98.0",description:"CLI tool for running Netlify agents",main:"./dist/index.js",types:"./dist/index.d.ts",exports:"./dist/index.js",bin:{"agent-runner-cli":"./dist/bin.js","agent-runner-cli-local":"./dist/bin-local.js"},files:["dist/**/*.js","dist/**/*.d.ts","dist/skills/**","patches","scripts"],scripts:{build:"tsup",dev:"tsup --watch",prepare:"husky install node_modules/@netlify/eslint-config-node/.husky/",prepublishOnly:"npm ci && npm test",prepack:"npm run build",test:"run-s build format test:dev",format:"run-s build format:check-fix:*","format:ci":"run-s build format:check:*","format:check-fix:lint":"run-e format:check:lint format:fix:lint","format:check:lint":"cross-env-shell eslint $npm_package_config_eslint","format:fix:lint":"cross-env-shell eslint --fix $npm_package_config_eslint","format:check-fix:prettier":"run-e format:check:prettier format:fix:prettier","format:check:prettier":"cross-env-shell prettier --check $npm_package_config_prettier","format:fix:prettier":"cross-env-shell prettier --write $npm_package_config_prettier","test:dev":"run-s build test:dev:*","test:ci":"run-s build test:ci:*","test:dev:vitest":"LOG=0 vitest --exclude '**/integration/**'","test:ci:vitest":"LOG=0 c8 -r lcovonly -r text -r json vitest --exclude '**/integration/**'","test:integration":"vitest run test/integration/","test:integration:codex":"vitest run test/integration/codex.test.ts","test:integration:claude":"vitest run test/integration/claude.test.ts","test:integration:gemini":"vitest run test/integration/gemini.test.ts","test:integration:create-stage":"vitest run test/integration/create.test.ts","test:integration:skill-invocation":"vitest run test/integration/skill-invocation.test.ts","test:integration:feature-enablement":"vitest run test/integration/feature-enablement.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.87","@anthropic-ai/sdk":"0.78.0","@google/gemini-cli":"0.31.0","@netlify/otel":"^5.1.5","@netlify/ts-cli":"^1.0.4","@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 Tn=wn(import.meta.url),vn=ie.dirname(Tn),Sn=_n(import.meta.url),ve=v("shell"),mt=new Set,ar={preferLocal:!0},N=(e,t,r)=>{let[i,n]=In(t,r),o={...ar,...n},s=En(e,i,o);ur(s,o),pr(s);let a=r?.idleTimeout;return a&&a>0&&dr(s,a),s},lr=(e,t)=>{let r={...ar,...t},i=xn(e,r);return ur(i,r),pr(i),t?.idleTimeout&&t.idleTimeout>0&&dr(i,t.idleTimeout),i},In=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},ur=(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 Te).pipe(te.stdout),e.stdout?.pipe(new Te).pipe(te.stdout),e.stderr?.pipe(new Te).pipe(te.stderr);return}e.stdout?.pipe(te.stdout),e.stderr?.pipe(te.stderr)},gt=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(te.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}},cr=e=>gt(e,"SIGKILL"),dr=(e,t)=>{let r=null,i=()=>{ve.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),gt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ve.log(`Force killing idle process ${e.pid}`),cr(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)},pr=e=>{mt.add(e);let t=rr();if(t){let r=t.onTimesUp(()=>{ve.log(`Global timer expired, killing process ${e.pid}`),gt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ve.log(`Force killing process ${e.pid} after timeout`),cr(e))},5e3)});e.on("exit",()=>{mt.delete(e),r()}),e.on("error",()=>{mt.delete(e),r()})}};function ue(e,t){if(!te.env.NETLIFY_LOCAL_MODE)try{let n=Sn.resolve(sr.name),o=ie.dirname(n);for(;o!==ie.dirname(o);){let s=ie.dirname(o);if(ie.basename(s)==="node_modules"){let a=ie.join(s,".bin",t);if(ze.existsSync(a))return a;break}o=s}}catch(n){console.error("Could not resolve package.json",n)}if(te.env.NODE_PATH){let n=ie.join(te.env.NODE_PATH,".bin",t);if(ze.existsSync(n))return n}let r=ie.join(e,"node_modules",".bin",t);if(ze.existsSync(r))return r;let i=ie.join(vn,"..","node_modules",".bin",t);if(ze.existsSync(i))return i}import bn from"process";var Rn="NETLIFY_FF_",fe=()=>{let e={};for(let[t,r]of Object.entries(bn.env))t.startsWith(Rn)&&r!==void 0&&(e[t]=r);return{byokEnabled:e.NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED==="true"||e.NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED==="1",skillVariations:Object.entries(e).filter(([t,r])=>t.startsWith("NETLIFY_FF_AGENT_RUNNER_SKILL_")&&(r==="true"||r==="1")).map(([t])=>t.replace("NETLIFY_FF_AGENT_RUNNER_SKILL_","").toLowerCase()),modelVersionOverrides:{codex:e.NETLIFY_FF_AGENT_RUNNER_CODEX_VERSION,claude:e.NETLIFY_FF_AGENT_RUNNER_CLAUDE_VERSION,gemini:e.NETLIFY_FF_AGENT_RUNNER_GEMINI_VERSION},raw:e}};var An=v("utils"),kn=e=>new Promise(t=>{setTimeout(t,e)}),Je=(e,t=3e3)=>{let r=!1,i=null,n=[],o=null,s=(...a)=>{if(r)return i=a,new Promise(c=>{n.push(c)});r=!0;let d,l=new Promise(c=>{d=c});return o=(async()=>{await Promise.resolve();let c=await e(...a);for(d(c);;){if(await kn(t),!i)return r=!1,o=null,c;let p=i,u=n;i=null,n=[],c=await e(...p),u.forEach(g=>{g(c)})}})(),l};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 d=r&&!i;clearTimeout(i),i=setTimeout(()=>{i=null,r||(e.apply(o,n),n=null,o=null)},t),d&&(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,d=o;i=null,n=null,o=null,e.apply(d,a)}},s},mr=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(i){t&&(r?.error?r.error("Could not parse JSON",i):An.error("Could not parse JSON",i))}},ft=e=>e.charAt(0).toUpperCase()+e.slice(1),ce=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():ft(t)).join(" ");function he(e,t){t&&e.log(`Skill invoked: ${t}`)}var gr=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),fr=(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 d=60-a.length;if(d<=0)return"";if(d>=o.length+6){let l=Math.min(d-o.length,e.length);return`${o}${e.slice(0,l)}`}return e.slice(0,d)};var Cn=1e4,ht=(e,t=Cn)=>{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 hr}from"buffer";import Pn from"path";var yr=v("repo"),_r=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{yr.info("Getting runner diffs");let i=await $n(r),{hasChanges:n}=i,{status:o}=i;if(!n)return{hasChanges:!1};if(!t){let T=On(o);await Ln(T,r)}yr.info("Changes after processing"),await wt(r);let s=await Et(o,r);if(await yt(s,r),n=await Fn(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await N("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},d=await N("git",["diff",e.runSha,"HEAD"],a),l=String(d.stdout??"");if(n=!!l,!n)return await wr(r),{hasChanges:!1,ignored:s};let c=await N("git",["diff",e.runSha,"HEAD","--binary"],a),p=String(c.stdout??""),u,g;if(e.sha){let T=await N("git",["diff",e.sha,"HEAD"],a);u=String(T.stdout??"");let w=await N("git",["diff",e.sha,"HEAD","--binary"],a),_=String(w.stdout??"");u!==_&&(g=hr.from(_).toString("base64"))}await wr(r);let S={hasChanges:!0,diff:l,resultDiff:u,ignored:s};return l!==p&&(S.diffBinary=hr.from(p).toString("base64")),g&&(S.resultDiffBinary=g),S},wr=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await N("git",["reset","--soft","HEAD~1"],{cwd:e})},yt=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await N("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},wt=async(e=process.cwd())=>{let t=await N("git",["status","-s"],{cwd:e});return String(t.stdout??"")},Er=/.. (.+)?\.log$/,Nn=[Er],$n=async(e=process.cwd())=>{let t=await wt(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
|
|
7
|
+
`);return o.length>e.length*.8?e:o}import{execSync as ri}from"child_process";import Or from"fs/promises";import ni from"path";import we from"process";import{getTracer as ii}from"@netlify/otel";import Fe from"process";var ee=class extends Error{constructor(r,i,n,o=!1){super(r);this.statusCode=i;this.userMessage=n;this.isCreditLimitExceeded=o;this.name="GracefulShutdownError"}},He=e=>e instanceof ee,qe=class extends Error{constructor(t){super(t),this.name="ProviderError"}};var We=Fe.env.NETLIFY_API_URL,Ve=Fe.env.NETLIFY_API_TOKEN,H=v("api"),Ee=()=>Fe.env.NETLIFY_LOCAL_MODE==="true",ae=async(e,t={})=>{if(!We||!Ve)throw new Error("No API URL or token");let r=new URL(e,We),i={...t,headers:{...t.headers,Authorization:`Bearer ${Ve}`}};Fe.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(Fe.env.AGENT_RUNNERS_DEBUG==="true")H.log(`Response headers for ${r}:`),n.headers.forEach((a,d)=>{H.log(` ${d}: ${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(o||H.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 ee(`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 ee(`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},Ht=e=>{H.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(We=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(Ve=e.constants.NETLIFY_API_TOKEN)},Wt=()=>({apiUrl:We,token:Ve}),Oe=async(e,t)=>Ee()?(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)=>Ee()?(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 Vt=async e=>Ee()?(H.log("Mock API: getSite called",{siteId:e}),{id:e,published_deploy:{id:"id"}}):ae(`/api/v1/sites/${e}`),Kt=async(e,t)=>Ee()?(H.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):ae(`/api/v1/agent_runners/${e}/sessions/${t}`),zt=(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}),Jt=(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}),Xt=async(e,t)=>Ee()?(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"}),Zt=async(e,t)=>Ee()?(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"}),ut=async(e,t,{maxRetries:r=3,baseDelayMs:i=500}={})=>{H.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);H.warn(`S3 upload attempt ${n}/${r} failed: ${o.message}. Retrying in ${s}ms...`),await new Promise(a=>setTimeout(a,s))}};var xe=v("ai_gateway"),ct=null;var Ke=async()=>{if(ct)return ct;xe.log("Fetching available AI gateway providers");let e=await fetch(`${Wt().apiUrl}/api/v1/ai-gateway/providers`);if(!e.ok)throw new Error(`Failed to fetch AI gateway providers: ${e.statusText}`);let t=await e.json();return ct=t,xe.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},dn=async(e,t)=>{let i=(await Ke()).providers[e];if(!i)return xe.log(`Provider '${e}' not found`),!1;let n=i.models.includes(t);return xe.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},Qt=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),xe.log("Requesting AI gateway information");let l=await(o?zt(e.accountId,e.id,e.sessionId):Jt(e.siteId,e.id,e.sessionId));if({token:t,url:n}=l,r=l.expires_at?l.expires_at*1e3:void 0,xe.log("Got AI gateway information",{token:!!t,expiresAt:r,url:n}),r){let c=r-Date.now()-6e4;c>0&&(i=setTimeout(()=>{a()},c))}};return await Promise.all([a(),Ke()]),{get url(){return n},get token(){return t},isModelAvailableForProvider:dn}};import te from"process";import ie from"path";import ze from"fs";import{fileURLToPath as wn}from"url";import{createRequire as _n}from"module";import{execa as En,execaCommand as xn}from"execa";import{Transform as pn}from"stream";function mn(){let e=process.env.NETLIFY_SENSITIVE_ENV_KEYS;return e?e.split(",").map(t=>t.trim()).filter(Boolean):[]}function gn(e){let t=e.toLowerCase();return t==="true"||t==="false"?!0:e.trim().length<4}function fn(){let t=mn().map(r=>process.env[r]).filter(r=>!(!r||gn(r)));return[...new Set(t)].sort((r,i)=>i.length-r.length)}function ne(e){if(typeof e!="string")return e;let t=fn();if(t.length===0)return e;let r=e;return t.forEach(i=>{let n=new RegExp(hn(i),"g");r=r.replace(n,"******")}),r}function hn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Te=class extends pn{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,i){let n=t.toString(),o=ne(n);i(null,o)}};function er(){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"?ne(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"?ne(i):i;return typeof n=="function"?r(s,n):r(s,n,o)}}var Le=null,tr=e=>(Le&&Le.destroy(),Le=new le({totalAllowedTime:e}),Le),rr=()=>Le;var le=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,d)=>{o=setTimeout(()=>{d(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 nr="netlify-agent-runner-context.md",dt="task-history",K=".netlify",me="results.md",pt="assets",ir="features";var or="free";var ge=1800*1e3,h={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 sr={name:"@netlify/agent-runner-cli",type:"module",version:"1.98.1",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","test:integration:feature-enablement":"vitest run test/integration/feature-enablement.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.87","@anthropic-ai/sdk":"0.78.0","@google/gemini-cli":"0.31.0","@netlify/otel":"^5.1.5","@netlify/ts-cli":"^1.0.4","@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 Tn=wn(import.meta.url),vn=ie.dirname(Tn),Sn=_n(import.meta.url),ve=v("shell"),mt=new Set,ar={preferLocal:!0},N=(e,t,r)=>{let[i,n]=In(t,r),o={...ar,...n},s=En(e,i,o);ur(s,o),pr(s);let a=r?.idleTimeout;return a&&a>0&&dr(s,a),s},lr=(e,t)=>{let r={...ar,...t},i=xn(e,r);return ur(i,r),pr(i),t?.idleTimeout&&t.idleTimeout>0&&dr(i,t.idleTimeout),i},In=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},ur=(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 Te).pipe(te.stdout),e.stdout?.pipe(new Te).pipe(te.stdout),e.stderr?.pipe(new Te).pipe(te.stderr);return}e.stdout?.pipe(te.stdout),e.stderr?.pipe(te.stderr)},gt=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(te.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}},cr=e=>gt(e,"SIGKILL"),dr=(e,t)=>{let r=null,i=()=>{ve.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),gt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ve.log(`Force killing idle process ${e.pid}`),cr(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)},pr=e=>{mt.add(e);let t=rr();if(t){let r=t.onTimesUp(()=>{ve.log(`Global timer expired, killing process ${e.pid}`),gt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(ve.log(`Force killing process ${e.pid} after timeout`),cr(e))},5e3)});e.on("exit",()=>{mt.delete(e),r()}),e.on("error",()=>{mt.delete(e),r()})}};function ue(e,t){if(!te.env.NETLIFY_LOCAL_MODE)try{let n=Sn.resolve(sr.name),o=ie.dirname(n);for(;o!==ie.dirname(o);){let s=ie.dirname(o);if(ie.basename(s)==="node_modules"){let a=ie.join(s,".bin",t);if(ze.existsSync(a))return a;break}o=s}}catch(n){console.error("Could not resolve package.json",n)}if(te.env.NODE_PATH){let n=ie.join(te.env.NODE_PATH,".bin",t);if(ze.existsSync(n))return n}let r=ie.join(e,"node_modules",".bin",t);if(ze.existsSync(r))return r;let i=ie.join(vn,"..","node_modules",".bin",t);if(ze.existsSync(i))return i}import bn from"process";var Rn="NETLIFY_FF_",fe=()=>{let e={};for(let[t,r]of Object.entries(bn.env))t.startsWith(Rn)&&r!==void 0&&(e[t]=r);return{byokEnabled:e.NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED==="true"||e.NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED==="1",skillVariations:Object.entries(e).filter(([t,r])=>t.startsWith("NETLIFY_FF_AGENT_RUNNER_SKILL_")&&(r==="true"||r==="1")).map(([t])=>t.replace("NETLIFY_FF_AGENT_RUNNER_SKILL_","").toLowerCase()),modelVersionOverrides:{codex:e.NETLIFY_FF_AGENT_RUNNER_CODEX_VERSION,claude:e.NETLIFY_FF_AGENT_RUNNER_CLAUDE_VERSION,gemini:e.NETLIFY_FF_AGENT_RUNNER_GEMINI_VERSION},raw:e}};var An=v("utils"),kn=e=>new Promise(t=>{setTimeout(t,e)}),Je=(e,t=3e3)=>{let r=!1,i=null,n=[],o=null,s=(...a)=>{if(r)return i=a,new Promise(c=>{n.push(c)});r=!0;let d,l=new Promise(c=>{d=c});return o=(async()=>{await Promise.resolve();let c=await e(...a);for(d(c);;){if(await kn(t),!i)return r=!1,o=null,c;let p=i,u=n;i=null,n=[],c=await e(...p),u.forEach(g=>{g(c)})}})(),l};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 d=r&&!i;clearTimeout(i),i=setTimeout(()=>{i=null,r||(e.apply(o,n),n=null,o=null)},t),d&&(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,d=o;i=null,n=null,o=null,e.apply(d,a)}},s},mr=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(i){t&&(r?.error?r.error("Could not parse JSON",i):An.error("Could not parse JSON",i))}},ft=e=>e.charAt(0).toUpperCase()+e.slice(1),ce=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():ft(t)).join(" ");function he(e,t){t&&e.log(`Skill invoked: ${t}`)}var gr=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),fr=(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 d=60-a.length;if(d<=0)return"";if(d>=o.length+6){let l=Math.min(d-o.length,e.length);return`${o}${e.slice(0,l)}`}return e.slice(0,d)};var Cn=1e4,ht=(e,t=Cn)=>{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 hr}from"buffer";import Pn from"path";var yr=v("repo"),_r=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{yr.info("Getting runner diffs");let i=await $n(r),{hasChanges:n}=i,{status:o}=i;if(!n)return{hasChanges:!1};if(!t){let T=On(o);await Ln(T,r)}yr.info("Changes after processing"),await wt(r);let s=await Et(o,r);if(await yt(s,r),n=await Fn(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await N("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},d=await N("git",["diff",e.runSha,"HEAD"],a),l=String(d.stdout??"");if(n=!!l,!n)return await wr(r),{hasChanges:!1,ignored:s};let c=await N("git",["diff",e.runSha,"HEAD","--binary"],a),p=String(c.stdout??""),u,g;if(e.sha){let T=await N("git",["diff",e.sha,"HEAD"],a);u=String(T.stdout??"");let w=await N("git",["diff",e.sha,"HEAD","--binary"],a),_=String(w.stdout??"");u!==_&&(g=hr.from(_).toString("base64"))}await wr(r);let S={hasChanges:!0,diff:l,resultDiff:u,ignored:s};return l!==p&&(S.diffBinary=hr.from(p).toString("base64")),g&&(S.resultDiffBinary=g),S},wr=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await N("git",["reset","--soft","HEAD~1"],{cwd:e})},yt=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await N("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},wt=async(e=process.cwd())=>{let t=await N("git",["status","-s"],{cwd:e});return String(t.stdout??"")},Er=/.. (.+)?\.log$/,Nn=[Er],$n=async(e=process.cwd())=>{let t=await wt(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
|
|
8
8
|
`).filter(n=>Nn.some(s=>s instanceof RegExp?s.test(n):n===s)?!1:n[1]?.trim()!=="")).length!==0,status:t}},Fn=async(e=process.cwd())=>{try{return await N("git",["diff","--staged","--quiet"],{cwd:e}),!1}catch{return!0}},_t=async(e=process.cwd())=>{let{stdout:t}=await N("git",["rev-parse","HEAD"],{cwd:e});return String(t??"").trim()},xr=async(e=process.cwd())=>{let{stdout:t}=await N("git",["rev-list","--max-parents=0","HEAD"],{cwd:e});return String(t??"").trim()},Et=async(e,t=process.cwd())=>{e||=await wt(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}`,d=n.startsWith(`?? ${s}/`)||n.startsWith(`?? ${s}${Pn.sep}`);(a||d)&&i.push(`:!${s}`)});let o=n.match(Er)?.[1];o&&i.push(`:!${o}.log`)}),i},xt=async(e=process.cwd())=>{await N("git",["reset","--hard","HEAD"],{cwd:e})},On=e=>{let t=e.split(`
|
|
10
10
|
`).reduce((r,i)=>{if(!i)return r;let[n,o,,...s]=i,a=s.join(""),d=n.trim(),l=o.trim();return r[a]?r[a].change=l:r[a]={filePath:a,stage:d,change:l},r},{});return Object.values(t)},Ln=async(e,t=process.cwd())=>{let r=e.filter(i=>i.stage&&!i.change).map(i=>i.filePath);r.length!==0&&await N("git",["restore","--staged","--worktree","--pathspec-from-file=-"],{cwd:t,input:r.join(`
|