@netlify/agent-runner-cli 1.82.0-alpha.0 → 1.82.0-alpha.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 +2 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/bin-local.js
CHANGED
|
@@ -5,7 +5,7 @@ import U from"process";import Yr from"path";import Br from"fs";import Ro from"mi
|
|
|
5
5
|
${s}
|
|
6
6
|
</extracted_error_chunk>`).join(`
|
|
7
7
|
|
|
8
|
-
`);return i.length>e.length*.8?e:i}import{execSync as qn}from"child_process";import Tr from"fs/promises";import Hn from"path";import le from"process";import{getTracer as Wn}from"@netlify/otel";import Ae from"process";var oe=class extends Error{constructor(r,o,n,i=!1){super(r);this.statusCode=o;this.userMessage=n;this.isCreditLimitExceeded=i;this.name="GracefulShutdownError"}},$t=e=>e instanceof oe;var De=Ae.env.NETLIFY_API_URL,Me=Ae.env.NETLIFY_API_TOKEN,J=E("api"),be=()=>Ae.env.NETLIFY_LOCAL_MODE==="true",fe=async(e,t={})=>{if(!De||!Me)throw new Error("No API URL or token");let r=new URL(e,De),o={...t,headers:{...t.headers,Authorization:`Bearer ${Me}`}};Ae.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(Ae.env.AGENT_RUNNERS_DEBUG==="true")J.log(`Response headers for ${r}:`),n.headers.forEach((a,c)=>{J.log(` ${c}: ${a}`)});else{let a=n.headers.get("x-request-id")||n.headers.get("x-nf-request-id");J.log(`Request ID for ${r}: ${a||"N/A"}`)}if(i||J.error(`Got status ${n.status} for request ${r}`),t.raw){if(!i)throw new Error(`API request failed: ${n.status} ${n.statusText}`);return n}let s=await(n.headers.get("content-type")?.includes("application/json")?n.json():n.text());if(!i){let a=typeof s=="string"?s:JSON.stringify(s);throw n.status===404?new oe(`API request failed: 404 - ${a}`,404,"The site associated with this agent run no longer exists."):n.status===503&&t.gracefulOn503&&a.toLowerCase().includes("usage exceeded")?new oe(`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},Lt=e=>{J.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(De=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(Me=e.constants.NETLIFY_API_TOKEN)},Ft=()=>({apiUrl:De,token:Me}),Ce=async(e,t)=>be()?(J.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):fe(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),H=async(e,t,r)=>be()?(J.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):fe(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var Dt=async(e,t)=>be()?(J.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):fe(`/api/v1/agent_runners/${e}/sessions/${t}`),Mt=(e,t,r)=>fe(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),Ut=async(e,t)=>be()?(J.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"}}):fe(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),Gt=async(e,t)=>be()?(J.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):fe(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),ot=async(e,t)=>{J.log(`Uploading diff to S3: ${e.substring(0,50)}...`);let r=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!r.ok)throw new Error(`S3 upload failed with status ${r.status}`);return r};var he=E("ai_gateway"),it=null;var jt=async()=>{if(it)return it;he.log("Fetching available AI gateway providers");let e=await fetch(`${Ft().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 it=t,he.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},Xr=async(e,t)=>{let o=(await jt()).providers[e];if(!o)return he.log(`Provider '${e}' not found`),!1;let n=o.models.includes(t);return he.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},Yt=async({netlify:e,config:t})=>{let r,o,n,i,s=e.constants?.SITE_ID;if(!s)throw new Error("No site id");let a=async()=>{clearTimeout(n),he.log("Requesting AI gateway information");let c=await Mt(s,t.id,t.sessionId);if({token:r,url:i}=c,o=c.expires_at?c.expires_at*1e3:void 0,he.log("Got AI gateway information",{token:!!r,expiresAt:o,url:i}),o){let d=o-Date.now()-6e4;d>0&&(n=setTimeout(()=>{a()},d))}};return await Promise.all([a(),jt()]),{get url(){return i},get token(){return r},isModelAvailableForProvider:Xr}};import X from"process";import re from"path";import Ue from"fs";import{fileURLToPath as on}from"url";import{createRequire as sn}from"module";import{execa as an,execaCommand as oi}from"execa";import{Transform as Zr}from"stream";var Qr=new Set(["NODE_ENV","PATH","HOME","USER","USERNAME","SHELL","PWD","OLDPWD","TMPDIR","TMP","TEMP","LANG","TERM","EDITOR","PAGER","OS","PROCESSOR_ARCHITECTURE","PROCESSOR_IDENTIFIER","SYSTEMROOT","WINDIR","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","APPDATA","LOCALAPPDATA","NODE_OPTIONS","NODE_PATH","NODE_DEBUG","NODE_NO_WARNINGS","npm_config_registry","npm_config_cache","npm_execpath","npm_node_execpath","CI","GITHUB_ACTIONS","GITHUB_WORKSPACE","GITHUB_REPOSITORY","GITHUB_REF","BUILDKITE","BUILDKITE_BRANCH","BUILDKITE_COMMIT","BUILDKITE_BUILD_NUMBER","JENKINS_URL","TRAVIS","CIRCLECI","DISPLAY","COLORTERM","TERM_PROGRAM","TERM_PROGRAM_VERSION","COLUMNS","LINES","HISTSIZE","HISTFILE","NETLIFY_AGENT_RUNNER_ID","NETLIFY_AGENT_RUNNER_SESSION_ID","NETLIFY_AGENT_RUNNER_PROMPT","NETLIFY_AGENT_RUNNER_AGENT","NETLIFY_AGENT_RUNNER_MODEL","NETLIFY_AGENT_RUNNER_CONTEXT","NETLIFY_AGENT_RUNNER_HAS_REPO","NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED","NETLIFY_AGENT_RUNNER_SHA","NETLIFY_TEAM_TYPE","AGENT_RUNNERS_DEBUG","NETLIFY_TEAM_ID","NETLIFY_AGENT_RUNNER_USER_ID","SITE_NAME"]),en=new Set(["true","false","undefined","null","deploy","project","claude","gemini","codex",""]);function tn(){return Object.entries(process.env).filter(([e,t])=>!(!t||Qr.has(e)||en.has(t)||!isNaN(Number(t))||t.length<5)).map(([,e])=>e).filter(Boolean)}function te(e){if(typeof e!="string")return e;let t=tn();if(t.length===0)return e;let r=e;return t.forEach(o=>{let n=new RegExp(rn(o),"g");r=r.replace(n,"******")}),r}function rn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ye=class extends Zr{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,o){let n=t.toString(),i=te(n);o(null,i)}};function Bt(){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"?te(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"?te(o):o;return typeof n=="function"?r(s,n):r(s,n,i)}}var Pe=null,qt=e=>(Pe&&Pe.destroy(),Pe=new ie({totalAllowedTime:e}),Pe),Ht=()=>Pe;var ie=class{constructor({totalAllowedTime:t}){this.withStageTimer=async(t,r,o)=>{if(this.isTimeExpired())throw new Error(`${t} stage did not complete in the allowed time. Time has already expired.`);let n=this.onTimesUp(()=>{throw new Error(`${t} stage did not complete in the allowed time.`)}),i=null,s=null;o!==void 0&&(s=new Promise((a,c)=>{i=setTimeout(()=>{c(new Error(`${t} stage exceeded its maximum duration of ${o}ms`))},o)}));try{return s?await Promise.race([r(),s]):await r()}finally{n(),i&&clearTimeout(i)}};this.startTime=Date.now(),this.totalAllowedTime=t,this.globalTimeoutId=null,this.subscribers=[],this.hasTimedOut=!1,this.setupGlobalTimeout()}getElapsedTime(){return Date.now()-this.startTime}getRemainingTime(){let t=this.getElapsedTime(),r=this.totalAllowedTime-t;return Math.max(0,r)}isTimeExpired(){return this.getRemainingTime()===0||this.hasTimedOut}setupGlobalTimeout(){this.globalTimeoutId&&clearTimeout(this.globalTimeoutId),this.globalTimeoutId=setTimeout(()=>{this.notifyTimeUp()},this.totalAllowedTime)}notifyTimeUp(){this.hasTimedOut=!0;for(let t=this.subscribers.length-1;t>=0;t--)try{this.subscribers[t]()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}}onTimesUp(t){if(this.subscribers.push(t),this.hasTimedOut)try{t()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}return()=>{let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}}off(t){let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}clearSubscribers(){this.subscribers.length=0}getSubscriberCount(){return this.subscribers.length}destroy(){this.globalTimeoutId&&(clearTimeout(this.globalTimeoutId),this.globalTimeoutId=null),this.clearSubscribers()}static{this.timeUnits={seconds:t=>t*1e3,minutes:t=>t*60*1e3,hours:t=>t*60*60*1e3}}};var Wt="netlify-agent-runner-context.md",st="task-history",z=".netlify",ue="results.md",at="assets";var de=1800*1e3,y={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 Kt={name:"@netlify/agent-runner-cli",type:"module",version:"1.82.0-alpha.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",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.52","@anthropic-ai/sdk":"0.77.0","@google/gemini-cli":"0.29.3","@netlify/otel":"^5.1.1","@openai/codex":"0.104.0","@opentelemetry/exporter-trace-otlp-grpc":"^0.212.0",execa:"^9.6.1",kaddidlehopper:"^0.7.0",minimist:"^1.2.8",openai:"6.22.0"}};var ln=on(import.meta.url),cn=re.dirname(ln),un=sn(import.meta.url),_e=E("shell"),lt=new Set,dn={preferLocal:!0},R=(e,t,r)=>{let[o,n]=pn(t,r),i={...dn,...n},s=an(e,o,i);mn(s,i),fn(s);let a=r?.idleTimeout;return a&&a>0&&gn(s,a),s};var pn=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},mn=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(X.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new ye).pipe(X.stdout),e.stdout?.pipe(new ye).pipe(X.stdout),e.stderr?.pipe(new ye).pipe(X.stderr);return}e.stdout?.pipe(X.stdout),e.stderr?.pipe(X.stderr)},ct=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(X.kill(-e.pid,t),_e.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return _e.error("Error killing process:",r),!1}},Jt=e=>ct(e,"SIGKILL"),gn=(e,t)=>{let r=null,o=()=>{_e.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),ct(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(_e.log(`Force killing idle process ${e.pid}`),Jt(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)},fn=e=>{lt.add(e);let t=Ht();if(t){let r=t.onTimesUp(()=>{_e.log(`Global timer expired, killing process ${e.pid}`),ct(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(_e.log(`Force killing process ${e.pid} after timeout`),Jt(e))},5e3)});e.on("exit",()=>{lt.delete(e),r()}),e.on("error",()=>{lt.delete(e),r()})}};function Ge(e,t){return!!ne(e,t)}function ne(e,t){if(!X.env.NETLIFY_LOCAL_MODE)try{let n=un.resolve(Kt.name),i=re.dirname(n);for(;i!==re.dirname(i);){let s=re.dirname(i);if(re.basename(s)==="node_modules"){let a=re.join(s,".bin",t);if(Ue.existsSync(a))return a;break}i=s}}catch(n){console.error("Could not resolve package.json",n)}if(X.env.NODE_PATH){let n=re.join(X.env.NODE_PATH,".bin",t);if(Ue.existsSync(n))return n}let r=re.join(e,"node_modules",".bin",t);if(Ue.existsSync(r))return r;let o=re.join(cn,"..","node_modules",".bin",t);if(Ue.existsSync(o))return o}var hn=E("utils"),yn=e=>new Promise(t=>{setTimeout(t,e)}),je=(e,t=3e3)=>{let r=!1,o=null,n=[],i=null,s=(...a)=>{if(r)return o=a,new Promise(p=>{n.push(p)});r=!0;let c,d=new Promise(p=>{c=p});return i=(async()=>{await Promise.resolve();let p=await e(...a);for(c(p);;){if(await yn(t),!o)return r=!1,i=null,p;let u=o,g=n;o=null,n=[],p=await e(...u),g.forEach(h=>{h(p)})}})(),d};return s.flush=async()=>{if((r||o)&&i)return await i,s.flush()},s},Ee=(e,t,r=!1)=>{let o=null,n=null,i=null,s=function(...a){n=a,i=this;let c=r&&!o;clearTimeout(o),o=setTimeout(()=>{o=null,r||(e.apply(i,n),n=null,i=null)},t),c&&(e.apply(i,n),n=null,i=null)};return s.cancel=()=>{clearTimeout(o),o=null,n=null,i=null},s.flush=()=>{if(o){clearTimeout(o);let a=n,c=i;o=null,n=null,i=null,e.apply(c,a)}},s},Vt=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(o){t&&(r?.error?r.error("Could not parse JSON",o):hn.error("Could not parse JSON",o))}},ut=e=>e.charAt(0).toUpperCase()+e.slice(1),se=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():ut(t)).join(" ");function pe(e,t){t&&e.log(`Skill invoked: ${t}`)}var zt=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),Xt=(e,t)=>{let n=".netlify.app",i="agent-";if(!t)return`${i}${e.slice(0,6)}`;let a=`--${t}${n}`;if(a.length>55)return"";let c=60-a.length;if(c<=0)return"";if(c>=i.length+6){let d=Math.min(c-i.length,e.length);return`${i}${e.slice(0,d)}`}return e.slice(0,c)};var _n=50*1024,dt=(e,t=_n)=>{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 Zt}from"buffer";import En from"path";var Qt=E("repo"),tr=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{Qt.info("Getting runner diffs");let o=await Tn(r),{hasChanges:n}=o,{status:i}=o;if(!n)return{hasChanges:!1};if(!t){let w=xn(i);await Sn(w,r)}Qt.info("Changes after processing"),await mt(r);let s=await gt(i,r);if(await pt(s,r),n=await In(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await R("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},c=await R("git",["diff",e.runSha,"HEAD"],a),d=String(c.stdout??"");if(n=!!d,!n)return await er(r),{hasChanges:!1,ignored:s};let p=await R("git",["diff",e.runSha,"HEAD","--binary"],a),u=String(p.stdout??""),g,h;if(e.sha){let w=await R("git",["diff",e.sha,"HEAD"],a);g=String(w.stdout??"");let _=await R("git",["diff",e.sha,"HEAD","--binary"],a),T=String(_.stdout??"");g!==T&&(h=Zt.from(T).toString("base64"))}await er(r);let I={hasChanges:!0,diff:d,resultDiff:g,ignored:s};return d!==u&&(I.diffBinary=Zt.from(u).toString("base64")),h&&(I.resultDiffBinary=h),I},er=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await R("git",["reset","--soft","HEAD~1"],{cwd:e})},pt=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await R("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},mt=async(e=process.cwd())=>{let t=await R("git",["status","-s"],{cwd:e});return String(t.stdout??"")},rr=/.. (.+)?\.log$/,wn=[rr],Tn=async(e=process.cwd())=>{let t=await mt(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
|
|
8
|
+
`);return i.length>e.length*.8?e:i}import{execSync as qn}from"child_process";import Tr from"fs/promises";import Hn from"path";import le from"process";import{getTracer as Wn}from"@netlify/otel";import Ae from"process";var oe=class extends Error{constructor(r,o,n,i=!1){super(r);this.statusCode=o;this.userMessage=n;this.isCreditLimitExceeded=i;this.name="GracefulShutdownError"}},$t=e=>e instanceof oe;var De=Ae.env.NETLIFY_API_URL,Me=Ae.env.NETLIFY_API_TOKEN,J=E("api"),be=()=>Ae.env.NETLIFY_LOCAL_MODE==="true",fe=async(e,t={})=>{if(!De||!Me)throw new Error("No API URL or token");let r=new URL(e,De),o={...t,headers:{...t.headers,Authorization:`Bearer ${Me}`}};Ae.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(Ae.env.AGENT_RUNNERS_DEBUG==="true")J.log(`Response headers for ${r}:`),n.headers.forEach((a,c)=>{J.log(` ${c}: ${a}`)});else{let a=n.headers.get("x-request-id")||n.headers.get("x-nf-request-id");J.log(`Request ID for ${r}: ${a||"N/A"}`)}if(i||J.error(`Got status ${n.status} for request ${r}`),t.raw){if(!i)throw new Error(`API request failed: ${n.status} ${n.statusText}`);return n}let s=await(n.headers.get("content-type")?.includes("application/json")?n.json():n.text());if(!i){let a=typeof s=="string"?s:JSON.stringify(s);throw n.status===404?new oe(`API request failed: 404 - ${a}`,404,"The site associated with this agent run no longer exists."):n.status===503&&t.gracefulOn503&&a.toLowerCase().includes("usage exceeded")?new oe(`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},Lt=e=>{J.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(De=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(Me=e.constants.NETLIFY_API_TOKEN)},Ft=()=>({apiUrl:De,token:Me}),Ce=async(e,t)=>be()?(J.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):fe(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),H=async(e,t,r)=>be()?(J.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):fe(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var Dt=async(e,t)=>be()?(J.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):fe(`/api/v1/agent_runners/${e}/sessions/${t}`),Mt=(e,t,r)=>fe(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),Ut=async(e,t)=>be()?(J.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"}}):fe(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),Gt=async(e,t)=>be()?(J.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):fe(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),ot=async(e,t)=>{J.log(`Uploading diff to S3: ${e.substring(0,50)}...`);let r=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!r.ok)throw new Error(`S3 upload failed with status ${r.status}`);return r};var he=E("ai_gateway"),it=null;var jt=async()=>{if(it)return it;he.log("Fetching available AI gateway providers");let e=await fetch(`${Ft().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 it=t,he.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},Xr=async(e,t)=>{let o=(await jt()).providers[e];if(!o)return he.log(`Provider '${e}' not found`),!1;let n=o.models.includes(t);return he.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},Yt=async({netlify:e,config:t})=>{let r,o,n,i,s=e.constants?.SITE_ID;if(!s)throw new Error("No site id");let a=async()=>{clearTimeout(n),he.log("Requesting AI gateway information");let c=await Mt(s,t.id,t.sessionId);if({token:r,url:i}=c,o=c.expires_at?c.expires_at*1e3:void 0,he.log("Got AI gateway information",{token:!!r,expiresAt:o,url:i}),o){let d=o-Date.now()-6e4;d>0&&(n=setTimeout(()=>{a()},d))}};return await Promise.all([a(),jt()]),{get url(){return i},get token(){return r},isModelAvailableForProvider:Xr}};import X from"process";import re from"path";import Ue from"fs";import{fileURLToPath as on}from"url";import{createRequire as sn}from"module";import{execa as an,execaCommand as oi}from"execa";import{Transform as Zr}from"stream";var Qr=new Set(["NODE_ENV","PATH","HOME","USER","USERNAME","SHELL","PWD","OLDPWD","TMPDIR","TMP","TEMP","LANG","TERM","EDITOR","PAGER","OS","PROCESSOR_ARCHITECTURE","PROCESSOR_IDENTIFIER","SYSTEMROOT","WINDIR","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","APPDATA","LOCALAPPDATA","NODE_OPTIONS","NODE_PATH","NODE_DEBUG","NODE_NO_WARNINGS","npm_config_registry","npm_config_cache","npm_execpath","npm_node_execpath","CI","GITHUB_ACTIONS","GITHUB_WORKSPACE","GITHUB_REPOSITORY","GITHUB_REF","BUILDKITE","BUILDKITE_BRANCH","BUILDKITE_COMMIT","BUILDKITE_BUILD_NUMBER","JENKINS_URL","TRAVIS","CIRCLECI","DISPLAY","COLORTERM","TERM_PROGRAM","TERM_PROGRAM_VERSION","COLUMNS","LINES","HISTSIZE","HISTFILE","NETLIFY_AGENT_RUNNER_ID","NETLIFY_AGENT_RUNNER_SESSION_ID","NETLIFY_AGENT_RUNNER_PROMPT","NETLIFY_AGENT_RUNNER_AGENT","NETLIFY_AGENT_RUNNER_MODEL","NETLIFY_AGENT_RUNNER_CONTEXT","NETLIFY_AGENT_RUNNER_HAS_REPO","NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED","NETLIFY_AGENT_RUNNER_SHA","NETLIFY_TEAM_TYPE","AGENT_RUNNERS_DEBUG","NETLIFY_TEAM_ID","NETLIFY_AGENT_RUNNER_USER_ID","SITE_NAME"]),en=new Set(["true","false","undefined","null","deploy","project","claude","gemini","codex",""]);function tn(){return Object.entries(process.env).filter(([e,t])=>!(!t||Qr.has(e)||en.has(t)||!isNaN(Number(t))||t.length<5)).map(([,e])=>e).filter(Boolean)}function te(e){if(typeof e!="string")return e;let t=tn();if(t.length===0)return e;let r=e;return t.forEach(o=>{let n=new RegExp(rn(o),"g");r=r.replace(n,"******")}),r}function rn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ye=class extends Zr{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,o){let n=t.toString(),i=te(n);o(null,i)}};function Bt(){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"?te(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"?te(o):o;return typeof n=="function"?r(s,n):r(s,n,i)}}var Pe=null,qt=e=>(Pe&&Pe.destroy(),Pe=new ie({totalAllowedTime:e}),Pe),Ht=()=>Pe;var ie=class{constructor({totalAllowedTime:t}){this.withStageTimer=async(t,r,o)=>{if(this.isTimeExpired())throw new Error(`${t} stage did not complete in the allowed time. Time has already expired.`);let n=this.onTimesUp(()=>{throw new Error(`${t} stage did not complete in the allowed time.`)}),i=null,s=null;o!==void 0&&(s=new Promise((a,c)=>{i=setTimeout(()=>{c(new Error(`${t} stage exceeded its maximum duration of ${o}ms`))},o)}));try{return s?await Promise.race([r(),s]):await r()}finally{n(),i&&clearTimeout(i)}};this.startTime=Date.now(),this.totalAllowedTime=t,this.globalTimeoutId=null,this.subscribers=[],this.hasTimedOut=!1,this.setupGlobalTimeout()}getElapsedTime(){return Date.now()-this.startTime}getRemainingTime(){let t=this.getElapsedTime(),r=this.totalAllowedTime-t;return Math.max(0,r)}isTimeExpired(){return this.getRemainingTime()===0||this.hasTimedOut}setupGlobalTimeout(){this.globalTimeoutId&&clearTimeout(this.globalTimeoutId),this.globalTimeoutId=setTimeout(()=>{this.notifyTimeUp()},this.totalAllowedTime)}notifyTimeUp(){this.hasTimedOut=!0;for(let t=this.subscribers.length-1;t>=0;t--)try{this.subscribers[t]()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}}onTimesUp(t){if(this.subscribers.push(t),this.hasTimedOut)try{t()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}return()=>{let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}}off(t){let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}clearSubscribers(){this.subscribers.length=0}getSubscriberCount(){return this.subscribers.length}destroy(){this.globalTimeoutId&&(clearTimeout(this.globalTimeoutId),this.globalTimeoutId=null),this.clearSubscribers()}static{this.timeUnits={seconds:t=>t*1e3,minutes:t=>t*60*1e3,hours:t=>t*60*60*1e3}}};var Wt="netlify-agent-runner-context.md",st="task-history",z=".netlify",ue="results.md",at="assets";var de=1800*1e3,y={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 Kt={name:"@netlify/agent-runner-cli",type:"module",version:"1.82.0-alpha.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",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.52","@anthropic-ai/sdk":"0.77.0","@google/gemini-cli":"0.29.3","@netlify/otel":"^5.1.1","@openai/codex":"0.104.0","@opentelemetry/exporter-trace-otlp-grpc":"^0.212.0",execa:"^9.6.1",kaddidlehopper:"^0.7.0",minimist:"^1.2.8",openai:"6.22.0"}};var ln=on(import.meta.url),cn=re.dirname(ln),un=sn(import.meta.url),_e=E("shell"),lt=new Set,dn={preferLocal:!0},R=(e,t,r)=>{let[o,n]=pn(t,r),i={...dn,...n},s=an(e,o,i);mn(s,i),fn(s);let a=r?.idleTimeout;return a&&a>0&&gn(s,a),s};var pn=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},mn=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(X.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new ye).pipe(X.stdout),e.stdout?.pipe(new ye).pipe(X.stdout),e.stderr?.pipe(new ye).pipe(X.stderr);return}e.stdout?.pipe(X.stdout),e.stderr?.pipe(X.stderr)},ct=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(X.kill(-e.pid,t),_e.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return _e.error("Error killing process:",r),!1}},Jt=e=>ct(e,"SIGKILL"),gn=(e,t)=>{let r=null,o=()=>{_e.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),ct(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(_e.log(`Force killing idle process ${e.pid}`),Jt(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)},fn=e=>{lt.add(e);let t=Ht();if(t){let r=t.onTimesUp(()=>{_e.log(`Global timer expired, killing process ${e.pid}`),ct(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(_e.log(`Force killing process ${e.pid} after timeout`),Jt(e))},5e3)});e.on("exit",()=>{lt.delete(e),r()}),e.on("error",()=>{lt.delete(e),r()})}};function Ge(e,t){return!!ne(e,t)}function ne(e,t){if(!X.env.NETLIFY_LOCAL_MODE)try{let n=un.resolve(Kt.name),i=re.dirname(n);for(;i!==re.dirname(i);){let s=re.dirname(i);if(re.basename(s)==="node_modules"){let a=re.join(s,".bin",t);if(Ue.existsSync(a))return a;break}i=s}}catch(n){console.error("Could not resolve package.json",n)}if(X.env.NODE_PATH){let n=re.join(X.env.NODE_PATH,".bin",t);if(Ue.existsSync(n))return n}let r=re.join(e,"node_modules",".bin",t);if(Ue.existsSync(r))return r;let o=re.join(cn,"..","node_modules",".bin",t);if(Ue.existsSync(o))return o}var hn=E("utils"),yn=e=>new Promise(t=>{setTimeout(t,e)}),je=(e,t=3e3)=>{let r=!1,o=null,n=[],i=null,s=(...a)=>{if(r)return o=a,new Promise(p=>{n.push(p)});r=!0;let c,d=new Promise(p=>{c=p});return i=(async()=>{await Promise.resolve();let p=await e(...a);for(c(p);;){if(await yn(t),!o)return r=!1,i=null,p;let u=o,g=n;o=null,n=[],p=await e(...u),g.forEach(h=>{h(p)})}})(),d};return s.flush=async()=>{if((r||o)&&i)return await i,s.flush()},s},Ee=(e,t,r=!1)=>{let o=null,n=null,i=null,s=function(...a){n=a,i=this;let c=r&&!o;clearTimeout(o),o=setTimeout(()=>{o=null,r||(e.apply(i,n),n=null,i=null)},t),c&&(e.apply(i,n),n=null,i=null)};return s.cancel=()=>{clearTimeout(o),o=null,n=null,i=null},s.flush=()=>{if(o){clearTimeout(o);let a=n,c=i;o=null,n=null,i=null,e.apply(c,a)}},s},Vt=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(o){t&&(r?.error?r.error("Could not parse JSON",o):hn.error("Could not parse JSON",o))}},ut=e=>e.charAt(0).toUpperCase()+e.slice(1),se=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():ut(t)).join(" ");function pe(e,t){t&&e.log(`Skill invoked: ${t}`)}var zt=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),Xt=(e,t)=>{let n=".netlify.app",i="agent-";if(!t)return`${i}${e.slice(0,6)}`;let a=`--${t}${n}`;if(a.length>55)return"";let c=60-a.length;if(c<=0)return"";if(c>=i.length+6){let d=Math.min(c-i.length,e.length);return`${i}${e.slice(0,d)}`}return e.slice(0,c)};var _n=50*1024,dt=(e,t=_n)=>{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 Zt}from"buffer";import En from"path";var Qt=E("repo"),tr=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{Qt.info("Getting runner diffs");let o=await Tn(r),{hasChanges:n}=o,{status:i}=o;if(!n)return{hasChanges:!1};if(!t){let w=xn(i);await Sn(w,r)}Qt.info("Changes after processing"),await mt(r);let s=await gt(i,r);if(await pt(s,r),n=await In(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await R("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},c=await R("git",["diff",e.runSha,"HEAD"],a),d=String(c.stdout??"");if(n=!!d,!n)return await er(r),{hasChanges:!1,ignored:s};let p=await R("git",["diff",e.runSha,"HEAD","--binary"],a),u=String(p.stdout??""),g,h;if(e.sha){let w=await R("git",["diff",e.sha,"HEAD"],a);g=String(w.stdout??"");let _=await R("git",["diff",e.sha,"HEAD","--binary"],a),T=String(_.stdout??"");g!==T&&(h=Zt.from(T).toString("base64"))}await er(r);let I={hasChanges:!0,diff:d,resultDiff:g,ignored:s};return d!==u&&(I.diffBinary=Zt.from(u).toString("base64")),h&&(I.resultDiffBinary=h),I},er=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await R("git",["reset","--soft","HEAD~1"],{cwd:e})},pt=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await R("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},mt=async(e=process.cwd())=>{let t=await R("git",["status","-s"],{cwd:e});return String(t.stdout??"")},rr=/.. (.+)?\.log$/,wn=[rr],Tn=async(e=process.cwd())=>{let t=await mt(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
|
|
9
9
|
`).filter(n=>wn.some(s=>s instanceof RegExp?s.test(n):n===s)?!1:n[1]?.trim()!=="")).length!==0,status:t}},In=async(e=process.cwd())=>{try{return await R("git",["diff","--staged","--quiet"],{cwd:e}),!1}catch{return!0}},Ne=async(e=process.cwd())=>{let{stdout:t}=await R("git",["rev-parse","HEAD"],{cwd:e});return String(t??"").trim()},nr=async(e=process.cwd())=>{let{stdout:t}=await R("git",["rev-list","--max-parents=0","HEAD"],{cwd:e});return String(t??"").trim()},gt=async(e,t=process.cwd())=>{e||=await mt(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}`,c=n.startsWith(`?? ${s}/`)||n.startsWith(`?? ${s}${En.sep}`);(a||c)&&o.push(`:!${s}`)});let i=n.match(rr)?.[1];i&&o.push(`:!${i}.log`)}),o},ft=async(e=process.cwd())=>{await R("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(""),c=n.trim(),d=i.trim();return r[a]?r[a].change=d:r[a]={filePath:a,stage:c,change:d},r},{});return Object.values(t)},Sn=async(e,t=process.cwd())=>{let r=e.filter(o=>o.stage&&!o.change).map(o=>o.filePath);r.length!==0&&await R("git",["restore","--staged","--worktree","--pathspec-from-file=-"],{cwd:t,input:r.join(`
|
package/dist/bin.js
CHANGED
|
@@ -5,7 +5,7 @@ import Pt from"process";import Uo from"minimist";import{createRequire as Co}from
|
|
|
5
5
|
${s}
|
|
6
6
|
</extracted_error_chunk>`).join(`
|
|
7
7
|
|
|
8
|
-
`);return i.length>e.length*.8?e:i}import{execSync as zn}from"child_process";import Cr from"fs/promises";import Xn from"path";import se from"process";import{getTracer as Zn}from"@netlify/otel";import ve 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"}},$t=e=>e instanceof te;var Le=ve.env.NETLIFY_API_URL,De=ve.env.NETLIFY_API_TOKEN,W=_("api"),Ae=()=>ve.env.NETLIFY_LOCAL_MODE==="true",me=async(e,t={})=>{if(!Le||!De)throw new Error("No API URL or token");let r=new URL(e,Le),o={...t,headers:{...t.headers,Authorization:`Bearer ${De}`}};ve.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(ve.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(i||W.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},Mt=e=>{W.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Le=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(De=e.constants.NETLIFY_API_TOKEN)},Ut=()=>({apiUrl:Le,token:De}),Ce=async(e,t)=>Ae()?(W.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):me(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),B=async(e,t,r)=>Ae()?(W.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):me(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var Gt=async(e,t)=>Ae()?(W.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):me(`/api/v1/agent_runners/${e}/sessions/${t}`),jt=(e,t,r)=>me(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),Yt=async(e,t)=>Ae()?(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"}}):me(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),Bt=async(e,t)=>Ae()?(W.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):me(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),rt=async(e,t)=>{W.log(`Uploading diff to S3: ${e.substring(0,50)}...`);let r=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!r.ok)throw new Error(`S3 upload failed with status ${r.status}`);return r};var ge=_("ai_gateway"),nt=null;var Ht=async()=>{if(nt)return nt;ge.log("Fetching available AI gateway providers");let e=await fetch(`${Ut().apiUrl}/api/v1/ai-gateway/providers`);if(!e.ok)throw new Error(`Failed to fetch AI gateway providers: ${e.statusText}`);let t=await e.json();return nt=t,ge.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},nn=async(e,t)=>{let o=(await Ht()).providers[e];if(!o)return ge.log(`Provider '${e}' not found`),!1;let n=o.models.includes(t);return ge.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},qt=async({netlify:e,config:t})=>{let r,o,n,i,s=e.constants?.SITE_ID;if(!s)throw new Error("No site id");let a=async()=>{clearTimeout(n),ge.log("Requesting AI gateway information");let c=await jt(s,t.id,t.sessionId);if({token:r,url:i}=c,o=c.expires_at?c.expires_at*1e3:void 0,ge.log("Got AI gateway information",{token:!!r,expiresAt:o,url:i}),o){let d=o-Date.now()-6e4;d>0&&(n=setTimeout(()=>{a()},d))}};return await Promise.all([a(),Ht()]),{get url(){return i},get token(){return r},isModelAvailableForProvider:nn}};import J from"process";import ee from"path";import $e from"fs";import{fileURLToPath as dn}from"url";import{createRequire as pn}from"module";import{execa as mn,execaCommand as yi}from"execa";import{Transform as on}from"stream";var sn=new Set(["NODE_ENV","PATH","HOME","USER","USERNAME","SHELL","PWD","OLDPWD","TMPDIR","TMP","TEMP","LANG","TERM","EDITOR","PAGER","OS","PROCESSOR_ARCHITECTURE","PROCESSOR_IDENTIFIER","SYSTEMROOT","WINDIR","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","APPDATA","LOCALAPPDATA","NODE_OPTIONS","NODE_PATH","NODE_DEBUG","NODE_NO_WARNINGS","npm_config_registry","npm_config_cache","npm_execpath","npm_node_execpath","CI","GITHUB_ACTIONS","GITHUB_WORKSPACE","GITHUB_REPOSITORY","GITHUB_REF","BUILDKITE","BUILDKITE_BRANCH","BUILDKITE_COMMIT","BUILDKITE_BUILD_NUMBER","JENKINS_URL","TRAVIS","CIRCLECI","DISPLAY","COLORTERM","TERM_PROGRAM","TERM_PROGRAM_VERSION","COLUMNS","LINES","HISTSIZE","HISTFILE","NETLIFY_AGENT_RUNNER_ID","NETLIFY_AGENT_RUNNER_SESSION_ID","NETLIFY_AGENT_RUNNER_PROMPT","NETLIFY_AGENT_RUNNER_AGENT","NETLIFY_AGENT_RUNNER_MODEL","NETLIFY_AGENT_RUNNER_CONTEXT","NETLIFY_AGENT_RUNNER_HAS_REPO","NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED","NETLIFY_AGENT_RUNNER_SHA","NETLIFY_TEAM_TYPE","AGENT_RUNNERS_DEBUG","NETLIFY_TEAM_ID","NETLIFY_AGENT_RUNNER_USER_ID","SITE_NAME"]),an=new Set(["true","false","undefined","null","deploy","project","claude","gemini","codex",""]);function ln(){return Object.entries(process.env).filter(([e,t])=>!(!t||sn.has(e)||an.has(t)||!isNaN(Number(t))||t.length<5)).map(([,e])=>e).filter(Boolean)}function Q(e){if(typeof e!="string")return e;let t=ln();if(t.length===0)return e;let r=e;return t.forEach(o=>{let n=new RegExp(cn(o),"g");r=r.replace(n,"******")}),r}function cn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var fe=class extends on{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,o){let n=t.toString(),i=Q(n);o(null,i)}};function Wt(){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"?Q(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"?Q(o):o;return typeof n=="function"?r(s,n):r(s,n,i)}}var Ne=null,Kt=e=>(Ne&&Ne.destroy(),Ne=new re({totalAllowedTime:e}),Ne),Vt=()=>Ne;var re=class{constructor({totalAllowedTime:t}){this.withStageTimer=async(t,r,o)=>{if(this.isTimeExpired())throw new Error(`${t} stage did not complete in the allowed time. Time has already expired.`);let n=this.onTimesUp(()=>{throw new Error(`${t} stage did not complete in the allowed time.`)}),i=null,s=null;o!==void 0&&(s=new Promise((a,c)=>{i=setTimeout(()=>{c(new Error(`${t} stage exceeded its maximum duration of ${o}ms`))},o)}));try{return s?await Promise.race([r(),s]):await r()}finally{n(),i&&clearTimeout(i)}};this.startTime=Date.now(),this.totalAllowedTime=t,this.globalTimeoutId=null,this.subscribers=[],this.hasTimedOut=!1,this.setupGlobalTimeout()}getElapsedTime(){return Date.now()-this.startTime}getRemainingTime(){let t=this.getElapsedTime(),r=this.totalAllowedTime-t;return Math.max(0,r)}isTimeExpired(){return this.getRemainingTime()===0||this.hasTimedOut}setupGlobalTimeout(){this.globalTimeoutId&&clearTimeout(this.globalTimeoutId),this.globalTimeoutId=setTimeout(()=>{this.notifyTimeUp()},this.totalAllowedTime)}notifyTimeUp(){this.hasTimedOut=!0;for(let t=this.subscribers.length-1;t>=0;t--)try{this.subscribers[t]()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}}onTimesUp(t){if(this.subscribers.push(t),this.hasTimedOut)try{t()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}return()=>{let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}}off(t){let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}clearSubscribers(){this.subscribers.length=0}getSubscriberCount(){return this.subscribers.length}destroy(){this.globalTimeoutId&&(clearTimeout(this.globalTimeoutId),this.globalTimeoutId=null),this.clearSubscribers()}static{this.timeUnits={seconds:t=>t*1e3,minutes:t=>t*60*1e3,hours:t=>t*60*60*1e3}}};var Jt="netlify-agent-runner-context.md",ot="task-history",V=".netlify",le="results.md",it="assets",st="other",at="personal";var lt="enterprise",ct="free",zt=[at,"pro",lt,ct],Xt=["normal","redeploy","create","ask","dtn-prod-iteration","rebase"],Zt="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.",ce=1800*1e3,y={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 Qt={name:"@netlify/agent-runner-cli",type:"module",version:"1.82.0-alpha.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",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.52","@anthropic-ai/sdk":"0.77.0","@google/gemini-cli":"0.29.3","@netlify/otel":"^5.1.1","@openai/codex":"0.104.0","@opentelemetry/exporter-trace-otlp-grpc":"^0.212.0",execa:"^9.6.1",kaddidlehopper:"^0.7.0",minimist:"^1.2.8",openai:"6.22.0"}};var gn=dn(import.meta.url),fn=ee.dirname(gn),hn=pn(import.meta.url),he=_("shell"),ut=new Set,yn={preferLocal:!0},C=(e,t,r)=>{let[o,n]=En(t,r),i={...yn,...n},s=mn(e,o,i);_n(s,i),Tn(s);let a=r?.idleTimeout;return a&&a>0&&wn(s,a),s};var En=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},_n=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(J.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new fe).pipe(J.stdout),e.stdout?.pipe(new fe).pipe(J.stdout),e.stderr?.pipe(new fe).pipe(J.stderr);return}e.stdout?.pipe(J.stdout),e.stderr?.pipe(J.stderr)},dt=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(J.kill(-e.pid,t),he.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return he.error("Error killing process:",r),!1}},er=e=>dt(e,"SIGKILL"),wn=(e,t)=>{let r=null,o=()=>{he.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),dt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(he.log(`Force killing idle process ${e.pid}`),er(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)},Tn=e=>{ut.add(e);let t=Vt();if(t){let r=t.onTimesUp(()=>{he.log(`Global timer expired, killing process ${e.pid}`),dt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(he.log(`Force killing process ${e.pid} after timeout`),er(e))},5e3)});e.on("exit",()=>{ut.delete(e),r()}),e.on("error",()=>{ut.delete(e),r()})}};function ne(e,t){if(!J.env.NETLIFY_LOCAL_MODE)try{let n=hn.resolve(Qt.name),i=ee.dirname(n);for(;i!==ee.dirname(i);){let s=ee.dirname(i);if(ee.basename(s)==="node_modules"){let a=ee.join(s,".bin",t);if($e.existsSync(a))return a;break}i=s}}catch(n){console.error("Could not resolve package.json",n)}if(J.env.NODE_PATH){let n=ee.join(J.env.NODE_PATH,".bin",t);if($e.existsSync(n))return n}let r=ee.join(e,"node_modules",".bin",t);if($e.existsSync(r))return r;let o=ee.join(fn,"..","node_modules",".bin",t);if($e.existsSync(o))return o}var tr=_("utils"),xn=e=>new Promise(t=>{setTimeout(t,e)}),Me=(e,t=3e3)=>{let r=!1,o=null,n=[],i=null,s=(...a)=>{if(r)return o=a,new Promise(p=>{n.push(p)});r=!0;let c,d=new Promise(p=>{c=p});return i=(async()=>{await Promise.resolve();let p=await e(...a);for(c(p);;){if(await xn(t),!o)return r=!1,i=null,p;let u=o,g=n;o=null,n=[],p=await e(...u),g.forEach(h=>{h(p)})}})(),d};return s.flush=async()=>{if((r||o)&&i)return await i,s.flush()},s},ye=(e,t,r=!1)=>{let o=null,n=null,i=null,s=function(...a){n=a,i=this;let c=r&&!o;clearTimeout(o),o=setTimeout(()=>{o=null,r||(e.apply(i,n),n=null,i=null)},t),c&&(e.apply(i,n),n=null,i=null)};return s.cancel=()=>{clearTimeout(o),o=null,n=null,i=null},s.flush=()=>{if(o){clearTimeout(o);let a=n,c=i;o=null,n=null,i=null,e.apply(c,a)}},s},Ue=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(o){t&&(r?.error?r.error("Could not parse JSON",o):tr.error("Could not parse JSON",o))}},pt=e=>e.charAt(0).toUpperCase()+e.slice(1),oe=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():pt(t)).join(" ");function ue(e,t){t&&e.log(`Skill invoked: ${t}`)}var rr=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),nr=(e,t)=>{let n=".netlify.app",i="agent-";if(!t)return`${i}${e.slice(0,6)}`;let a=`--${t}${n}`;if(a.length>55)return"";let c=60-a.length;if(c<=0)return"";if(c>=i.length+6){let d=Math.min(c-i.length,e.length);return`${i}${e.slice(0,d)}`}return e.slice(0,c)},Rn=e=>!e||typeof e!="object"||Array.isArray(e)||Object.keys(e).length===0?!1:!!zt.some(t=>t in e),or=()=>{let e={},t={codex:process.env.NETLIFY_FF_AGENT_RUNNER_CODEX_VERSION,claude:process.env.NETLIFY_FF_AGENT_RUNNER_CLAUDE_VERSION,gemini:process.env.NETLIFY_FF_AGENT_RUNNER_GEMINI_VERSION};return Object.entries(t).forEach(([r,o])=>{if(o){let n=`NETLIFY_FF_AGENT_RUNNER_${r.toUpperCase()}_VERSION`;try{let i=JSON.parse(o);Rn(i)&&(e[r]=i)}catch(i){let a=i instanceof SyntaxError?"Invalid JSON":i.message;tr.error(`Could not parse ${r} model version override from ${n}: ${a}`)}}}),e},In=50*1024,mt=(e,t=In)=>{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 ir}from"buffer";import Sn from"path";var sr=_("repo"),lr=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{sr.info("Getting runner diffs");let o=await An(r),{hasChanges:n}=o,{status:i}=o;if(!n)return{hasChanges:!1};if(!t){let w=Nn(i);await bn(w,r)}sr.info("Changes after processing"),await ft(r);let s=await yt(i,r);if(await gt(s,r),n=await Cn(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),d=String(c.stdout??"");if(n=!!d,!n)return await ar(r),{hasChanges:!1,ignored:s};let p=await C("git",["diff",e.runSha,"HEAD","--binary"],a),u=String(p.stdout??""),g,h;if(e.sha){let w=await C("git",["diff",e.sha,"HEAD"],a);g=String(w.stdout??"");let E=await C("git",["diff",e.sha,"HEAD","--binary"],a),T=String(E.stdout??"");g!==T&&(h=ir.from(T).toString("base64"))}await ar(r);let x={hasChanges:!0,diff:d,resultDiff:g,ignored:s};return d!==u&&(x.diffBinary=ir.from(u).toString("base64")),h&&(x.resultDiffBinary=h),x},ar=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await C("git",["reset","--soft","HEAD~1"],{cwd:e})},gt=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"}},ft=async(e=process.cwd())=>{let t=await C("git",["status","-s"],{cwd:e});return String(t.stdout??"")},cr=/.. (.+)?\.log$/,vn=[cr],An=async(e=process.cwd())=>{let t=await ft(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
|
|
8
|
+
`);return i.length>e.length*.8?e:i}import{execSync as zn}from"child_process";import Cr from"fs/promises";import Xn from"path";import se from"process";import{getTracer as Zn}from"@netlify/otel";import ve 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"}},$t=e=>e instanceof te;var Le=ve.env.NETLIFY_API_URL,De=ve.env.NETLIFY_API_TOKEN,W=_("api"),Ae=()=>ve.env.NETLIFY_LOCAL_MODE==="true",me=async(e,t={})=>{if(!Le||!De)throw new Error("No API URL or token");let r=new URL(e,Le),o={...t,headers:{...t.headers,Authorization:`Bearer ${De}`}};ve.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(ve.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(i||W.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},Mt=e=>{W.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Le=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&(De=e.constants.NETLIFY_API_TOKEN)},Ut=()=>({apiUrl:Le,token:De}),Ce=async(e,t)=>Ae()?(W.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):me(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),B=async(e,t,r)=>Ae()?(W.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):me(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var Gt=async(e,t)=>Ae()?(W.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):me(`/api/v1/agent_runners/${e}/sessions/${t}`),jt=(e,t,r)=>me(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),Yt=async(e,t)=>Ae()?(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"}}):me(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),Bt=async(e,t)=>Ae()?(W.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):me(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),rt=async(e,t)=>{W.log(`Uploading diff to S3: ${e.substring(0,50)}...`);let r=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!r.ok)throw new Error(`S3 upload failed with status ${r.status}`);return r};var ge=_("ai_gateway"),nt=null;var Ht=async()=>{if(nt)return nt;ge.log("Fetching available AI gateway providers");let e=await fetch(`${Ut().apiUrl}/api/v1/ai-gateway/providers`);if(!e.ok)throw new Error(`Failed to fetch AI gateway providers: ${e.statusText}`);let t=await e.json();return nt=t,ge.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},nn=async(e,t)=>{let o=(await Ht()).providers[e];if(!o)return ge.log(`Provider '${e}' not found`),!1;let n=o.models.includes(t);return ge.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},qt=async({netlify:e,config:t})=>{let r,o,n,i,s=e.constants?.SITE_ID;if(!s)throw new Error("No site id");let a=async()=>{clearTimeout(n),ge.log("Requesting AI gateway information");let c=await jt(s,t.id,t.sessionId);if({token:r,url:i}=c,o=c.expires_at?c.expires_at*1e3:void 0,ge.log("Got AI gateway information",{token:!!r,expiresAt:o,url:i}),o){let d=o-Date.now()-6e4;d>0&&(n=setTimeout(()=>{a()},d))}};return await Promise.all([a(),Ht()]),{get url(){return i},get token(){return r},isModelAvailableForProvider:nn}};import J from"process";import ee from"path";import $e from"fs";import{fileURLToPath as dn}from"url";import{createRequire as pn}from"module";import{execa as mn,execaCommand as yi}from"execa";import{Transform as on}from"stream";var sn=new Set(["NODE_ENV","PATH","HOME","USER","USERNAME","SHELL","PWD","OLDPWD","TMPDIR","TMP","TEMP","LANG","TERM","EDITOR","PAGER","OS","PROCESSOR_ARCHITECTURE","PROCESSOR_IDENTIFIER","SYSTEMROOT","WINDIR","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","APPDATA","LOCALAPPDATA","NODE_OPTIONS","NODE_PATH","NODE_DEBUG","NODE_NO_WARNINGS","npm_config_registry","npm_config_cache","npm_execpath","npm_node_execpath","CI","GITHUB_ACTIONS","GITHUB_WORKSPACE","GITHUB_REPOSITORY","GITHUB_REF","BUILDKITE","BUILDKITE_BRANCH","BUILDKITE_COMMIT","BUILDKITE_BUILD_NUMBER","JENKINS_URL","TRAVIS","CIRCLECI","DISPLAY","COLORTERM","TERM_PROGRAM","TERM_PROGRAM_VERSION","COLUMNS","LINES","HISTSIZE","HISTFILE","NETLIFY_AGENT_RUNNER_ID","NETLIFY_AGENT_RUNNER_SESSION_ID","NETLIFY_AGENT_RUNNER_PROMPT","NETLIFY_AGENT_RUNNER_AGENT","NETLIFY_AGENT_RUNNER_MODEL","NETLIFY_AGENT_RUNNER_CONTEXT","NETLIFY_AGENT_RUNNER_HAS_REPO","NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED","NETLIFY_AGENT_RUNNER_SHA","NETLIFY_TEAM_TYPE","AGENT_RUNNERS_DEBUG","NETLIFY_TEAM_ID","NETLIFY_AGENT_RUNNER_USER_ID","SITE_NAME"]),an=new Set(["true","false","undefined","null","deploy","project","claude","gemini","codex",""]);function ln(){return Object.entries(process.env).filter(([e,t])=>!(!t||sn.has(e)||an.has(t)||!isNaN(Number(t))||t.length<5)).map(([,e])=>e).filter(Boolean)}function Q(e){if(typeof e!="string")return e;let t=ln();if(t.length===0)return e;let r=e;return t.forEach(o=>{let n=new RegExp(cn(o),"g");r=r.replace(n,"******")}),r}function cn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var fe=class extends on{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,o){let n=t.toString(),i=Q(n);o(null,i)}};function Wt(){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"?Q(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"?Q(o):o;return typeof n=="function"?r(s,n):r(s,n,i)}}var Ne=null,Kt=e=>(Ne&&Ne.destroy(),Ne=new re({totalAllowedTime:e}),Ne),Vt=()=>Ne;var re=class{constructor({totalAllowedTime:t}){this.withStageTimer=async(t,r,o)=>{if(this.isTimeExpired())throw new Error(`${t} stage did not complete in the allowed time. Time has already expired.`);let n=this.onTimesUp(()=>{throw new Error(`${t} stage did not complete in the allowed time.`)}),i=null,s=null;o!==void 0&&(s=new Promise((a,c)=>{i=setTimeout(()=>{c(new Error(`${t} stage exceeded its maximum duration of ${o}ms`))},o)}));try{return s?await Promise.race([r(),s]):await r()}finally{n(),i&&clearTimeout(i)}};this.startTime=Date.now(),this.totalAllowedTime=t,this.globalTimeoutId=null,this.subscribers=[],this.hasTimedOut=!1,this.setupGlobalTimeout()}getElapsedTime(){return Date.now()-this.startTime}getRemainingTime(){let t=this.getElapsedTime(),r=this.totalAllowedTime-t;return Math.max(0,r)}isTimeExpired(){return this.getRemainingTime()===0||this.hasTimedOut}setupGlobalTimeout(){this.globalTimeoutId&&clearTimeout(this.globalTimeoutId),this.globalTimeoutId=setTimeout(()=>{this.notifyTimeUp()},this.totalAllowedTime)}notifyTimeUp(){this.hasTimedOut=!0;for(let t=this.subscribers.length-1;t>=0;t--)try{this.subscribers[t]()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}}onTimesUp(t){if(this.subscribers.push(t),this.hasTimedOut)try{t()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}return()=>{let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}}off(t){let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}clearSubscribers(){this.subscribers.length=0}getSubscriberCount(){return this.subscribers.length}destroy(){this.globalTimeoutId&&(clearTimeout(this.globalTimeoutId),this.globalTimeoutId=null),this.clearSubscribers()}static{this.timeUnits={seconds:t=>t*1e3,minutes:t=>t*60*1e3,hours:t=>t*60*60*1e3}}};var Jt="netlify-agent-runner-context.md",ot="task-history",V=".netlify",le="results.md",it="assets",st="other",at="personal";var lt="enterprise",ct="free",zt=[at,"pro",lt,ct],Xt=["normal","redeploy","create","ask","dtn-prod-iteration","rebase"],Zt="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.",ce=1800*1e3,y={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 Qt={name:"@netlify/agent-runner-cli",type:"module",version:"1.82.0-alpha.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",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.52","@anthropic-ai/sdk":"0.77.0","@google/gemini-cli":"0.29.3","@netlify/otel":"^5.1.1","@openai/codex":"0.104.0","@opentelemetry/exporter-trace-otlp-grpc":"^0.212.0",execa:"^9.6.1",kaddidlehopper:"^0.7.0",minimist:"^1.2.8",openai:"6.22.0"}};var gn=dn(import.meta.url),fn=ee.dirname(gn),hn=pn(import.meta.url),he=_("shell"),ut=new Set,yn={preferLocal:!0},C=(e,t,r)=>{let[o,n]=En(t,r),i={...yn,...n},s=mn(e,o,i);_n(s,i),Tn(s);let a=r?.idleTimeout;return a&&a>0&&wn(s,a),s};var En=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},_n=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(J.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new fe).pipe(J.stdout),e.stdout?.pipe(new fe).pipe(J.stdout),e.stderr?.pipe(new fe).pipe(J.stderr);return}e.stdout?.pipe(J.stdout),e.stderr?.pipe(J.stderr)},dt=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(J.kill(-e.pid,t),he.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return he.error("Error killing process:",r),!1}},er=e=>dt(e,"SIGKILL"),wn=(e,t)=>{let r=null,o=()=>{he.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),dt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(he.log(`Force killing idle process ${e.pid}`),er(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)},Tn=e=>{ut.add(e);let t=Vt();if(t){let r=t.onTimesUp(()=>{he.log(`Global timer expired, killing process ${e.pid}`),dt(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(he.log(`Force killing process ${e.pid} after timeout`),er(e))},5e3)});e.on("exit",()=>{ut.delete(e),r()}),e.on("error",()=>{ut.delete(e),r()})}};function ne(e,t){if(!J.env.NETLIFY_LOCAL_MODE)try{let n=hn.resolve(Qt.name),i=ee.dirname(n);for(;i!==ee.dirname(i);){let s=ee.dirname(i);if(ee.basename(s)==="node_modules"){let a=ee.join(s,".bin",t);if($e.existsSync(a))return a;break}i=s}}catch(n){console.error("Could not resolve package.json",n)}if(J.env.NODE_PATH){let n=ee.join(J.env.NODE_PATH,".bin",t);if($e.existsSync(n))return n}let r=ee.join(e,"node_modules",".bin",t);if($e.existsSync(r))return r;let o=ee.join(fn,"..","node_modules",".bin",t);if($e.existsSync(o))return o}var tr=_("utils"),xn=e=>new Promise(t=>{setTimeout(t,e)}),Me=(e,t=3e3)=>{let r=!1,o=null,n=[],i=null,s=(...a)=>{if(r)return o=a,new Promise(p=>{n.push(p)});r=!0;let c,d=new Promise(p=>{c=p});return i=(async()=>{await Promise.resolve();let p=await e(...a);for(c(p);;){if(await xn(t),!o)return r=!1,i=null,p;let u=o,g=n;o=null,n=[],p=await e(...u),g.forEach(h=>{h(p)})}})(),d};return s.flush=async()=>{if((r||o)&&i)return await i,s.flush()},s},ye=(e,t,r=!1)=>{let o=null,n=null,i=null,s=function(...a){n=a,i=this;let c=r&&!o;clearTimeout(o),o=setTimeout(()=>{o=null,r||(e.apply(i,n),n=null,i=null)},t),c&&(e.apply(i,n),n=null,i=null)};return s.cancel=()=>{clearTimeout(o),o=null,n=null,i=null},s.flush=()=>{if(o){clearTimeout(o);let a=n,c=i;o=null,n=null,i=null,e.apply(c,a)}},s},Ue=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(o){t&&(r?.error?r.error("Could not parse JSON",o):tr.error("Could not parse JSON",o))}},pt=e=>e.charAt(0).toUpperCase()+e.slice(1),oe=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():pt(t)).join(" ");function ue(e,t){t&&e.log(`Skill invoked: ${t}`)}var rr=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),nr=(e,t)=>{let n=".netlify.app",i="agent-";if(!t)return`${i}${e.slice(0,6)}`;let a=`--${t}${n}`;if(a.length>55)return"";let c=60-a.length;if(c<=0)return"";if(c>=i.length+6){let d=Math.min(c-i.length,e.length);return`${i}${e.slice(0,d)}`}return e.slice(0,c)},Rn=e=>!e||typeof e!="object"||Array.isArray(e)||Object.keys(e).length===0?!1:!!zt.some(t=>t in e),or=()=>{let e={},t={codex:process.env.NETLIFY_FF_AGENT_RUNNER_CODEX_VERSION,claude:process.env.NETLIFY_FF_AGENT_RUNNER_CLAUDE_VERSION,gemini:process.env.NETLIFY_FF_AGENT_RUNNER_GEMINI_VERSION};return Object.entries(t).forEach(([r,o])=>{if(o){let n=`NETLIFY_FF_AGENT_RUNNER_${r.toUpperCase()}_VERSION`;try{let i=JSON.parse(o);Rn(i)&&(e[r]=i)}catch(i){let a=i instanceof SyntaxError?"Invalid JSON":i.message;tr.error(`Could not parse ${r} model version override from ${n}: ${a}`)}}}),e},In=50*1024,mt=(e,t=In)=>{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 ir}from"buffer";import Sn from"path";var sr=_("repo"),lr=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{sr.info("Getting runner diffs");let o=await An(r),{hasChanges:n}=o,{status:i}=o;if(!n)return{hasChanges:!1};if(!t){let w=Nn(i);await bn(w,r)}sr.info("Changes after processing"),await ft(r);let s=await yt(i,r);if(await gt(s,r),n=await Cn(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),d=String(c.stdout??"");if(n=!!d,!n)return await ar(r),{hasChanges:!1,ignored:s};let p=await C("git",["diff",e.runSha,"HEAD","--binary"],a),u=String(p.stdout??""),g,h;if(e.sha){let w=await C("git",["diff",e.sha,"HEAD"],a);g=String(w.stdout??"");let E=await C("git",["diff",e.sha,"HEAD","--binary"],a),T=String(E.stdout??"");g!==T&&(h=ir.from(T).toString("base64"))}await ar(r);let x={hasChanges:!0,diff:d,resultDiff:g,ignored:s};return d!==u&&(x.diffBinary=ir.from(u).toString("base64")),h&&(x.resultDiffBinary=h),x},ar=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await C("git",["reset","--soft","HEAD~1"],{cwd:e})},gt=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"}},ft=async(e=process.cwd())=>{let t=await C("git",["status","-s"],{cwd:e});return String(t.stdout??"")},cr=/.. (.+)?\.log$/,vn=[cr],An=async(e=process.cwd())=>{let t=await ft(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
|
|
9
9
|
`).filter(n=>vn.some(s=>s instanceof RegExp?s.test(n):n===s)?!1:n[1]?.trim()!=="")).length!==0,status:t}},Cn=async(e=process.cwd())=>{try{return await C("git",["diff","--staged","--quiet"],{cwd:e}),!1}catch{return!0}},ht=async(e=process.cwd())=>{let{stdout:t}=await C("git",["rev-parse","HEAD"],{cwd:e});return String(t??"").trim()},ur=async(e=process.cwd())=>{let{stdout:t}=await C("git",["rev-list","--max-parents=0","HEAD"],{cwd:e});return String(t??"").trim()},yt=async(e,t=process.cwd())=>{e||=await ft(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}`,c=n.startsWith(`?? ${s}/`)||n.startsWith(`?? ${s}${Sn.sep}`);(a||c)&&o.push(`:!${s}`)});let i=n.match(cr)?.[1];i&&o.push(`:!${i}.log`)}),o},Et=async(e=process.cwd())=>{await C("git",["reset","--hard","HEAD"],{cwd:e})},Nn=e=>{let t=e.split(`
|
|
11
11
|
`).reduce((r,o)=>{if(!o)return r;let[n,i,,...s]=o,a=s.join(""),c=n.trim(),d=i.trim();return r[a]?r[a].change=d:r[a]={filePath:a,stage:c,change:d},r},{});return Object.values(t)},bn=async(e,t=process.cwd())=>{let r=e.filter(o=>o.stage&&!o.change).map(o=>o.filePath);r.length!==0&&await C("git",["restore","--staged","--worktree","--pathspec-from-file=-"],{cwd:t,input:r.join(`
|
|
@@ -195,5 +195,5 @@ ${JSON.stringify(e,null,2)}`,vo=async({config:e,aiGateway:t,addons:r,prompt:o,ag
|
|
|
195
195
|
|
|
196
196
|
\`\`\`
|
|
197
197
|
${E}
|
|
198
|
-
\`\`\``,M.info("Generated project structure for agent context"))}catch(E){console.log(123,E),M.warn("Failed to generate project structure",E.message)}let w=performance.now()-n;return o?.setAttributes({"create.framework":u?.framework,"create.addons":u?.addons,"create.duration.ms":w,"create.status":"success"}),{...u??{addons:[],newPrompt:"",packageManager:"",framework:""},additionalContext:x}});var Ze=_("usage_tracker"),Ao=4e3,Br=(e,t,r)=>{let o=!1,n=!1,i=!1,a=Me(async()=>{try{let p=await Bt(e,t);Ze.log("Usage update response",{usage:p?.usage}),r!=null&&p?.usage?.total_credits_cost!=null&&p.usage.total_credits_cost>=r&&(Ze.log("Credit limit exceeded",{totalCreditsCost:p.usage.total_credits_cost,enforcedCreditsRemaining:r}),i=!0)}catch(p){Ze.warn("Failed to update usage",{error:p?.message||p})}},Ao);return{onAgentOutput:()=>{if(i)throw new te("AI credit usage exceeded enforced limit.",503,"Credit limit reached. Your team has configured an enforced credit limit for AI usage. Increase this limit to continue.",!0);n||(o=!0,a())},stop:async()=>{n||(n=!0,o&&(Ze.log("Sending final usage update"),a(),await a.flush()))}}};var bo=Co(import.meta.url),Wr=bo("../package.json"),Ie=_("pipeline_index"),Qe=3,Kr=async({config:e,apiToken:t,cliPath:r="netlify",cwd:o,filter:n,tracing:i={}})=>{let s,a,{withStageTimer:c}=Kt(re.timeUnits.hours(4)),d=await Lt(Wr.version,e.id,i);try{await qr(Hr(),"run-pipeline",{},d,async()=>{let{aiGateway:p,context:u,persistSteps:g,runner:h,sha:x}=await c("init",()=>Nr({config:e,apiToken:t,cliPath:r,cwd:o,filter:n,runnerVersion:Wr.version}),re.timeUnits.minutes(10));s=h.clean,a=Br(e.id,e.sessionId,e.enforcedAICreditsRemaining);let w=Object.assign(async m=>(a?.onAgentOutput(),g(m)),{flush:g.flush.bind(g)});if(e.sha=x,e.mode==="redeploy"){let m=await c("deploy",()=>Ve({cliPath:r,config:e,context:u,result:"Redeploy completed",filter:n,isRetry:!1}));m.deployError&&Ie.warn(`Redeploy deploy failed: ${m.deployError}`);let{diff:l,resultDiff:f,previewInfo:I,diffBinary:L,resultDiffBinary:K}=m;await a?.stop(),await c("cleanup",()=>Nt({config:e,diff:l,result:"Redeploy completed",duration:0,resultDiff:f,diffBinary:L,resultDiffBinary:K,previewInfo:I}),re.timeUnits.minutes(10)),process.env.NETLIFY_LOCAL_MODE||(await s?.(),await Et());return}let E;e.mode==="create"&&(E=(await c("create",()=>Yr({config:e,aiGateway:p,cwd:o}))).additionalContext);let{runnerResult:T}=await c("inference",()=>Ke({cliPath:r,config:e,context:u,runner:h.runner,persistSteps:w,aiGateway:p,additionalContext:E,cwd:o})),R=await c("deploy",()=>Ve({cliPath:r,config:e,context:u,result:T.result,filter:n,isRetry:!1})),v=T,$=[];if(R.hasChanges&&R.deployError){$.push(Dt(R.deployError));let m=1,l=!1;for(;m<=Qe&&!R.previewInfo&&!l;)Ie.log(`Deploy attempt had errors. Retrying. ${m}/${Qe}`),await qr(Hr(),"deploy-stage",async f=>{f?.setAttributes({"stage.attempt":m});let I;try{I=(await c(`inference-retry-${m}`,()=>Ke({cliPath:r,config:e,context:u,runner:h.runner,persistSteps:w,aiGateway:p,buildErrors:$,priorAgentSessionId:T.agentSessionId}))).runnerResult}catch(L){Ie.warn(`Inference retry ${m} failed, stopping deploy retries:`,L),l=!0;return}v={...I,steps:[...v.steps||[],...I.steps||[]],duration:(v.duration||0)+(I.duration||0)},R=await c(`deploy-retry-${m}`,()=>Ve({cliPath:r,config:e,context:u,result:I.result,filter:n,isRetry:!0})),R.deployError&&$.push(R.deployError),m++});m>Qe&&!R.previewInfo&&console.warn(`Deploy validation failed after ${Qe} attempts`)}let{diff:P,resultDiff:k,previewInfo:S,diffBinary:O,resultDiffBinary:F}=R;await a?.stop(),await c("cleanup",()=>Nt({config:e,diff:P,result:v.result,duration:v.duration,resultDiff:k,diffBinary:O,resultDiffBinary:F,previewInfo:S}),re.timeUnits.minutes(10)),process.env.NETLIFY_LOCAL_MODE||(await s?.(),await Et())})}catch(p){if($t(p)){Ie.info("Agent run terminated gracefully",{statusCode:p.statusCode,reason:p.message}),await a?.stop(),await s?.();try{await B(e.id,e.sessionId,{result:p.userMessage,state:p.isCreditLimitExceeded?"cancelled":"error",...p.isCreditLimitExceeded&&{credit_limit_exceeded:!0}})}catch{Ie.info("Could not update session (site may have been deleted)")}return}Ie.error("Got error while running pipeline",p),await a?.stop(),await s?.();let u=p instanceof Error&&p.message;throw await B(e.id,e.sessionId,{result:u||"Encountered error when running agent",state:"error"}),p}finally{await No()}};import q from"process";var ko="claude",Oo=e=>typeof e.request=="string"&&typeof e.response=="string",Fo=e=>typeof e.site_context=="string",Lo=e=>(e??[]).filter(Oo),Do=e=>(e??[]).filter(Fo),bt=_("config"),Vr=()=>{let e=q.env.NETLIFY_AGENT_RUNNER_ID,t=q.env.NETLIFY_AGENT_RUNNER_SESSION_ID;if(!e||!t)throw new Error("ID of agent runner is not provided");let r=q.env.NETLIFY_AGENT_RUNNER_MODE||"normal";if(!Xt.includes(r))throw new Error(`Mode ${r} is not supported`);let o=q.env.NETLIFY_AGENT_RUNNER_PROMPT,n=r==="rebase"?Zt:o;if(r!=="redeploy"&&!n)throw new Error("Prompt is not provided");let i=q.env.NETLIFY_AGENT_RUNNER_AGENT||ko,s=q.env.NETLIFY_AGENT_RUNNER_MODEL,a=Ue(q.env.NETLIFY_AGENT_RUNNER_CONTEXT,!0,bt),c=Lo(a),d=Do(a),p=q.env.NETLIFY_AGENT_RUNNER_HAS_REPO!=="0",u=!q.env.NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED,g=q.env.NETLIFY_AGENT_RUNNER_SHA,h=$o(),x=or(),w=Mo(),E={id:e,sessionId:t,runner:i,model:s,sessionHistoryContext:c,siteContext:d,hasRepo:p,useGateway:u,sha:g,runSha:"",accountType:h,modelVersionOverrides:x,enforcedAICreditsRemaining:w},T=r==="redeploy"?{...E,mode:r}:{...E,mode:r,prompt:n};return bt.log({fullConfig:T}),T},$o=()=>{let e=q.env.NETLIFY_TEAM_TYPE;return e?e.includes("personal")?at:e.includes("pro")?"pro":e.startsWith("enterprise")?lt:e.
|
|
198
|
+
\`\`\``,M.info("Generated project structure for agent context"))}catch(E){console.log(123,E),M.warn("Failed to generate project structure",E.message)}let w=performance.now()-n;return o?.setAttributes({"create.framework":u?.framework,"create.addons":u?.addons,"create.duration.ms":w,"create.status":"success"}),{...u??{addons:[],newPrompt:"",packageManager:"",framework:""},additionalContext:x}});var Ze=_("usage_tracker"),Ao=4e3,Br=(e,t,r)=>{let o=!1,n=!1,i=!1,a=Me(async()=>{try{let p=await Bt(e,t);Ze.log("Usage update response",{usage:p?.usage}),r!=null&&p?.usage?.total_credits_cost!=null&&p.usage.total_credits_cost>=r&&(Ze.log("Credit limit exceeded",{totalCreditsCost:p.usage.total_credits_cost,enforcedCreditsRemaining:r}),i=!0)}catch(p){Ze.warn("Failed to update usage",{error:p?.message||p})}},Ao);return{onAgentOutput:()=>{if(i)throw new te("AI credit usage exceeded enforced limit.",503,"Credit limit reached. Your team has configured an enforced credit limit for AI usage. Increase this limit to continue.",!0);n||(o=!0,a())},stop:async()=>{n||(n=!0,o&&(Ze.log("Sending final usage update"),a(),await a.flush()))}}};var bo=Co(import.meta.url),Wr=bo("../package.json"),Ie=_("pipeline_index"),Qe=3,Kr=async({config:e,apiToken:t,cliPath:r="netlify",cwd:o,filter:n,tracing:i={}})=>{let s,a,{withStageTimer:c}=Kt(re.timeUnits.hours(4)),d=await Lt(Wr.version,e.id,i);try{await qr(Hr(),"run-pipeline",{},d,async()=>{let{aiGateway:p,context:u,persistSteps:g,runner:h,sha:x}=await c("init",()=>Nr({config:e,apiToken:t,cliPath:r,cwd:o,filter:n,runnerVersion:Wr.version}),re.timeUnits.minutes(10));s=h.clean,a=Br(e.id,e.sessionId,e.enforcedAICreditsRemaining);let w=Object.assign(async m=>(a?.onAgentOutput(),g(m)),{flush:g.flush.bind(g)});if(e.sha=x,e.mode==="redeploy"){let m=await c("deploy",()=>Ve({cliPath:r,config:e,context:u,result:"Redeploy completed",filter:n,isRetry:!1}));m.deployError&&Ie.warn(`Redeploy deploy failed: ${m.deployError}`);let{diff:l,resultDiff:f,previewInfo:I,diffBinary:L,resultDiffBinary:K}=m;await a?.stop(),await c("cleanup",()=>Nt({config:e,diff:l,result:"Redeploy completed",duration:0,resultDiff:f,diffBinary:L,resultDiffBinary:K,previewInfo:I}),re.timeUnits.minutes(10)),process.env.NETLIFY_LOCAL_MODE||(await s?.(),await Et());return}let E;e.mode==="create"&&(E=(await c("create",()=>Yr({config:e,aiGateway:p,cwd:o}))).additionalContext);let{runnerResult:T}=await c("inference",()=>Ke({cliPath:r,config:e,context:u,runner:h.runner,persistSteps:w,aiGateway:p,additionalContext:E,cwd:o})),R=await c("deploy",()=>Ve({cliPath:r,config:e,context:u,result:T.result,filter:n,isRetry:!1})),v=T,$=[];if(R.hasChanges&&R.deployError){$.push(Dt(R.deployError));let m=1,l=!1;for(;m<=Qe&&!R.previewInfo&&!l;)Ie.log(`Deploy attempt had errors. Retrying. ${m}/${Qe}`),await qr(Hr(),"deploy-stage",async f=>{f?.setAttributes({"stage.attempt":m});let I;try{I=(await c(`inference-retry-${m}`,()=>Ke({cliPath:r,config:e,context:u,runner:h.runner,persistSteps:w,aiGateway:p,buildErrors:$,priorAgentSessionId:T.agentSessionId}))).runnerResult}catch(L){Ie.warn(`Inference retry ${m} failed, stopping deploy retries:`,L),l=!0;return}v={...I,steps:[...v.steps||[],...I.steps||[]],duration:(v.duration||0)+(I.duration||0)},R=await c(`deploy-retry-${m}`,()=>Ve({cliPath:r,config:e,context:u,result:I.result,filter:n,isRetry:!0})),R.deployError&&$.push(R.deployError),m++});m>Qe&&!R.previewInfo&&console.warn(`Deploy validation failed after ${Qe} attempts`)}let{diff:P,resultDiff:k,previewInfo:S,diffBinary:O,resultDiffBinary:F}=R;await a?.stop(),await c("cleanup",()=>Nt({config:e,diff:P,result:v.result,duration:v.duration,resultDiff:k,diffBinary:O,resultDiffBinary:F,previewInfo:S}),re.timeUnits.minutes(10)),process.env.NETLIFY_LOCAL_MODE||(await s?.(),await Et())})}catch(p){if($t(p)){Ie.info("Agent run terminated gracefully",{statusCode:p.statusCode,reason:p.message}),await a?.stop(),await s?.();try{await B(e.id,e.sessionId,{result:p.userMessage,state:p.isCreditLimitExceeded?"cancelled":"error",...p.isCreditLimitExceeded&&{credit_limit_exceeded:!0}})}catch{Ie.info("Could not update session (site may have been deleted)")}return}Ie.error("Got error while running pipeline",p),await a?.stop(),await s?.();let u=p instanceof Error&&p.message;throw await B(e.id,e.sessionId,{result:u||"Encountered error when running agent",state:"error"}),p}finally{await No()}};import q from"process";var ko="claude",Oo=e=>typeof e.request=="string"&&typeof e.response=="string",Fo=e=>typeof e.site_context=="string",Lo=e=>(e??[]).filter(Oo),Do=e=>(e??[]).filter(Fo),bt=_("config"),Vr=()=>{let e=q.env.NETLIFY_AGENT_RUNNER_ID,t=q.env.NETLIFY_AGENT_RUNNER_SESSION_ID;if(!e||!t)throw new Error("ID of agent runner is not provided");let r=q.env.NETLIFY_AGENT_RUNNER_MODE||"normal";if(!Xt.includes(r))throw new Error(`Mode ${r} is not supported`);let o=q.env.NETLIFY_AGENT_RUNNER_PROMPT,n=r==="rebase"?Zt:o;if(r!=="redeploy"&&!n)throw new Error("Prompt is not provided");let i=q.env.NETLIFY_AGENT_RUNNER_AGENT||ko,s=q.env.NETLIFY_AGENT_RUNNER_MODEL,a=Ue(q.env.NETLIFY_AGENT_RUNNER_CONTEXT,!0,bt),c=Lo(a),d=Do(a),p=q.env.NETLIFY_AGENT_RUNNER_HAS_REPO!=="0",u=!q.env.NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED,g=q.env.NETLIFY_AGENT_RUNNER_SHA,h=$o(),x=or(),w=Mo(),E={id:e,sessionId:t,runner:i,model:s,sessionHistoryContext:c,siteContext:d,hasRepo:p,useGateway:u,sha:g,runSha:"",accountType:h,modelVersionOverrides:x,enforcedAICreditsRemaining:w},T=r==="redeploy"?{...E,mode:r}:{...E,mode:r,prompt:n};return bt.log({fullConfig:T}),T},$o=()=>{let e=q.env.NETLIFY_TEAM_TYPE;return e?e.includes("personal")?at:e.includes("pro")?"pro":e.startsWith("enterprise")?lt:e.endsWith("free")?ct:st:st},Mo=()=>{let e=q.env.ACC_ENFORCED_AI_CREDITS_REMAINING;if(e==null)return;let t=parseInt(e,10);if(Number.isNaN(t)){bt.warn("Invalid ACC_ENFORCED_AI_CREDITS_REMAINING value, ignoring",{raw:e});return}return t};var Jr=_("bin_cmd"),Se=Uo(Pt.argv.slice(2),{string:["auth","cwd","cli-path","filter","trace-exporter-url","traceparent"]});try{let e=Vr();await Kr({config:e,apiToken:Se.auth,cwd:Se.cwd,cliPath:Se["cli-path"],filter:Se.filter,tracing:{exporterUrl:Se["trace-exporter-url"],traceparent:Se.traceparent}}),Jr.info("Finished agent"),Pt.exit(0)}catch(e){Jr.error("Error running agent pipeline:",e),Pt.exit(1)}
|
|
199
199
|
//# sourceMappingURL=bin.js.map
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import{createRequire as po}from"module";import{createTracerProvider as Fr}from"@
|
|
|
4
4
|
${s}
|
|
5
5
|
</extracted_error_chunk>`).join(`
|
|
6
6
|
|
|
7
|
-
`);return i.length>e.length*.8?e:i}import{execSync as $n}from"child_process";import fr from"fs/promises";import Fn from"path";import ie from"process";import{getTracer as Dn}from"@netlify/otel";import Re from"process";var ee=class extends Error{constructor(r,o,n,i=!1){super(r);this.statusCode=o;this.userMessage=n;this.isCreditLimitExceeded=i;this.name="GracefulShutdownError"}},bt=e=>e instanceof ee;var Oe=Re.env.NETLIFY_API_URL,$e=Re.env.NETLIFY_API_TOKEN,H=T("api"),Se=()=>Re.env.NETLIFY_LOCAL_MODE==="true",pe=async(e,t={})=>{if(!Oe||!$e)throw new Error("No API URL or token");let r=new URL(e,Oe),o={...t,headers:{...t.headers,Authorization:`Bearer ${$e}`}};Re.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(Re.env.AGENT_RUNNERS_DEBUG==="true")H.log(`Response headers for ${r}:`),n.headers.forEach((a,c)=>{H.log(` ${c}: ${a}`)});else{let a=n.headers.get("x-request-id")||n.headers.get("x-nf-request-id");H.log(`Request ID for ${r}: ${a||"N/A"}`)}if(i||H.error(`Got status ${n.status} for request ${r}`),t.raw){if(!i)throw new Error(`API request failed: ${n.status} ${n.statusText}`);return n}let s=await(n.headers.get("content-type")?.includes("application/json")?n.json():n.text());if(!i){let a=typeof s=="string"?s:JSON.stringify(s);throw n.status===404?new 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},Ct=e=>{H.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Oe=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&($e=e.constants.NETLIFY_API_TOKEN)},Pt=()=>({apiUrl:Oe,token:$e}),ve=async(e,t)=>Se()?(H.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):pe(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),B=async(e,t,r)=>Se()?(H.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):pe(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var Nt=async(e,t)=>Se()?(H.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):pe(`/api/v1/agent_runners/${e}/sessions/${t}`),kt=(e,t,r)=>pe(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),Ot=async(e,t)=>Se()?(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"}}):pe(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),$t=async(e,t)=>Se()?(H.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):pe(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),Qe=async(e,t)=>{H.log(`Uploading diff to S3: ${e.substring(0,50)}...`);let r=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!r.ok)throw new Error(`S3 upload failed with status ${r.status}`);return r};var me=T("ai_gateway"),et=null;var Ft=async()=>{if(et)return et;me.log("Fetching available AI gateway providers");let e=await fetch(`${Pt().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 et=t,me.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},jr=async(e,t)=>{let o=(await Ft()).providers[e];if(!o)return me.log(`Provider '${e}' not found`),!1;let n=o.models.includes(t);return me.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},Dt=async({netlify:e,config:t})=>{let r,o,n,i,s=e.constants?.SITE_ID;if(!s)throw new Error("No site id");let a=async()=>{clearTimeout(n),me.log("Requesting AI gateway information");let c=await kt(s,t.id,t.sessionId);if({token:r,url:i}=c,o=c.expires_at?c.expires_at*1e3:void 0,me.log("Got AI gateway information",{token:!!r,expiresAt:o,url:i}),o){let d=o-Date.now()-6e4;d>0&&(n=setTimeout(()=>{a()},d))}};return await Promise.all([a(),Ft()]),{get url(){return i},get token(){return r},isModelAvailableForProvider:jr}};import J from"process";import Q from"path";import Fe from"fs";import{fileURLToPath as Jr}from"url";import{createRequire as Vr}from"module";import{execa as zr,execaCommand as Wo}from"execa";import{Transform as Yr}from"stream";var Br=new Set(["NODE_ENV","PATH","HOME","USER","USERNAME","SHELL","PWD","OLDPWD","TMPDIR","TMP","TEMP","LANG","TERM","EDITOR","PAGER","OS","PROCESSOR_ARCHITECTURE","PROCESSOR_IDENTIFIER","SYSTEMROOT","WINDIR","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","APPDATA","LOCALAPPDATA","NODE_OPTIONS","NODE_PATH","NODE_DEBUG","NODE_NO_WARNINGS","npm_config_registry","npm_config_cache","npm_execpath","npm_node_execpath","CI","GITHUB_ACTIONS","GITHUB_WORKSPACE","GITHUB_REPOSITORY","GITHUB_REF","BUILDKITE","BUILDKITE_BRANCH","BUILDKITE_COMMIT","BUILDKITE_BUILD_NUMBER","JENKINS_URL","TRAVIS","CIRCLECI","DISPLAY","COLORTERM","TERM_PROGRAM","TERM_PROGRAM_VERSION","COLUMNS","LINES","HISTSIZE","HISTFILE","NETLIFY_AGENT_RUNNER_ID","NETLIFY_AGENT_RUNNER_SESSION_ID","NETLIFY_AGENT_RUNNER_PROMPT","NETLIFY_AGENT_RUNNER_AGENT","NETLIFY_AGENT_RUNNER_MODEL","NETLIFY_AGENT_RUNNER_CONTEXT","NETLIFY_AGENT_RUNNER_HAS_REPO","NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED","NETLIFY_AGENT_RUNNER_SHA","NETLIFY_TEAM_TYPE","AGENT_RUNNERS_DEBUG","NETLIFY_TEAM_ID","NETLIFY_AGENT_RUNNER_USER_ID","SITE_NAME"]),qr=new Set(["true","false","undefined","null","deploy","project","claude","gemini","codex",""]);function Hr(){return Object.entries(process.env).filter(([e,t])=>!(!t||Br.has(e)||qr.has(t)||!isNaN(Number(t))||t.length<5)).map(([,e])=>e).filter(Boolean)}function Z(e){if(typeof e!="string")return e;let t=Hr();if(t.length===0)return e;let r=e;return t.forEach(o=>{let n=new RegExp(Wr(o),"g");r=r.replace(n,"******")}),r}function Wr(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ge=class extends Yr{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,o){let n=t.toString(),i=Z(n);o(null,i)}};function Lt(){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"?Z(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"?Z(o):o;return typeof n=="function"?r(s,n):r(s,n,i)}}var Ae=null,Mt=e=>(Ae&&Ae.destroy(),Ae=new te({totalAllowedTime:e}),Ae),Ut=()=>Ae;var te=class{constructor({totalAllowedTime:t}){this.withStageTimer=async(t,r,o)=>{if(this.isTimeExpired())throw new Error(`${t} stage did not complete in the allowed time. Time has already expired.`);let n=this.onTimesUp(()=>{throw new Error(`${t} stage did not complete in the allowed time.`)}),i=null,s=null;o!==void 0&&(s=new Promise((a,c)=>{i=setTimeout(()=>{c(new Error(`${t} stage exceeded its maximum duration of ${o}ms`))},o)}));try{return s?await Promise.race([r(),s]):await r()}finally{n(),i&&clearTimeout(i)}};this.startTime=Date.now(),this.totalAllowedTime=t,this.globalTimeoutId=null,this.subscribers=[],this.hasTimedOut=!1,this.setupGlobalTimeout()}getElapsedTime(){return Date.now()-this.startTime}getRemainingTime(){let t=this.getElapsedTime(),r=this.totalAllowedTime-t;return Math.max(0,r)}isTimeExpired(){return this.getRemainingTime()===0||this.hasTimedOut}setupGlobalTimeout(){this.globalTimeoutId&&clearTimeout(this.globalTimeoutId),this.globalTimeoutId=setTimeout(()=>{this.notifyTimeUp()},this.totalAllowedTime)}notifyTimeUp(){this.hasTimedOut=!0;for(let t=this.subscribers.length-1;t>=0;t--)try{this.subscribers[t]()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}}onTimesUp(t){if(this.subscribers.push(t),this.hasTimedOut)try{t()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}return()=>{let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}}off(t){let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}clearSubscribers(){this.subscribers.length=0}getSubscriberCount(){return this.subscribers.length}destroy(){this.globalTimeoutId&&(clearTimeout(this.globalTimeoutId),this.globalTimeoutId=null),this.clearSubscribers()}static{this.timeUnits={seconds:t=>t*1e3,minutes:t=>t*60*1e3,hours:t=>t*60*60*1e3}}};var Gt="netlify-agent-runner-context.md",tt="task-history",K=".netlify",ae="results.md",rt="assets";var le=1800*1e3,y={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 jt={name:"@netlify/agent-runner-cli",type:"module",version:"1.82.0-alpha.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",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.52","@anthropic-ai/sdk":"0.77.0","@google/gemini-cli":"0.29.3","@netlify/otel":"^5.1.1","@openai/codex":"0.104.0","@opentelemetry/exporter-trace-otlp-grpc":"^0.212.0",execa:"^9.6.1",kaddidlehopper:"^0.7.0",minimist:"^1.2.8",openai:"6.22.0"}};var Xr=Jr(import.meta.url),Zr=Q.dirname(Xr),Qr=Vr(import.meta.url),fe=T("shell"),nt=new Set,en={preferLocal:!0},b=(e,t,r)=>{let[o,n]=tn(t,r),i={...en,...n},s=zr(e,o,i);rn(s,i),on(s);let a=r?.idleTimeout;return a&&a>0&&nn(s,a),s};var tn=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},rn=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(J.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new ge).pipe(J.stdout),e.stdout?.pipe(new ge).pipe(J.stdout),e.stderr?.pipe(new ge).pipe(J.stderr);return}e.stdout?.pipe(J.stdout),e.stderr?.pipe(J.stderr)},ot=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(J.kill(-e.pid,t),fe.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return fe.error("Error killing process:",r),!1}},Yt=e=>ot(e,"SIGKILL"),nn=(e,t)=>{let r=null,o=()=>{fe.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),ot(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(fe.log(`Force killing idle process ${e.pid}`),Yt(e))},5e3)},n=()=>{r&&clearTimeout(r),r=setTimeout(o,t)};n(),e.stdout?.on("data",n),e.stderr?.on("data",n);let i=()=>{r&&(clearTimeout(r),r=null)};e.on("exit",i),e.on("error",i)},on=e=>{nt.add(e);let t=Ut();if(t){let r=t.onTimesUp(()=>{fe.log(`Global timer expired, killing process ${e.pid}`),ot(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(fe.log(`Force killing process ${e.pid} after timeout`),Yt(e))},5e3)});e.on("exit",()=>{nt.delete(e),r()}),e.on("error",()=>{nt.delete(e),r()})}};function re(e,t){if(!J.env.NETLIFY_LOCAL_MODE)try{let n=Qr.resolve(jt.name),i=Q.dirname(n);for(;i!==Q.dirname(i);){let s=Q.dirname(i);if(Q.basename(s)==="node_modules"){let a=Q.join(s,".bin",t);if(Fe.existsSync(a))return a;break}i=s}}catch(n){console.error("Could not resolve package.json",n)}if(J.env.NODE_PATH){let n=Q.join(J.env.NODE_PATH,".bin",t);if(Fe.existsSync(n))return n}let r=Q.join(e,"node_modules",".bin",t);if(Fe.existsSync(r))return r;let o=Q.join(Zr,"..","node_modules",".bin",t);if(Fe.existsSync(o))return o}var sn=T("utils"),an=e=>new Promise(t=>{setTimeout(t,e)}),De=(e,t=3e3)=>{let r=!1,o=null,n=[],i=null,s=(...a)=>{if(r)return o=a,new Promise(p=>{n.push(p)});r=!0;let c,d=new Promise(p=>{c=p});return i=(async()=>{await Promise.resolve();let p=await e(...a);for(c(p);;){if(await an(t),!o)return r=!1,i=null,p;let u=o,g=n;o=null,n=[],p=await e(...u),g.forEach(h=>{h(p)})}})(),d};return s.flush=async()=>{if((r||o)&&i)return await i,s.flush()},s},he=(e,t,r=!1)=>{let o=null,n=null,i=null,s=function(...a){n=a,i=this;let c=r&&!o;clearTimeout(o),o=setTimeout(()=>{o=null,r||(e.apply(i,n),n=null,i=null)},t),c&&(e.apply(i,n),n=null,i=null)};return s.cancel=()=>{clearTimeout(o),o=null,n=null,i=null},s.flush=()=>{if(o){clearTimeout(o);let a=n,c=i;o=null,n=null,i=null,e.apply(c,a)}},s},Bt=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(o){t&&(r?.error?r.error("Could not parse JSON",o):sn.error("Could not parse JSON",o))}},it=e=>e.charAt(0).toUpperCase()+e.slice(1),ne=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():it(t)).join(" ");function ce(e,t){t&&e.log(`Skill invoked: ${t}`)}var qt=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),Ht=(e,t)=>{let n=".netlify.app",i="agent-";if(!t)return`${i}${e.slice(0,6)}`;let a=`--${t}${n}`;if(a.length>55)return"";let c=60-a.length;if(c<=0)return"";if(c>=i.length+6){let d=Math.min(c-i.length,e.length);return`${i}${e.slice(0,d)}`}return e.slice(0,c)};var ln=50*1024,st=(e,t=ln)=>{if(!e||typeof e!="string"||e.length<=t)return e;let o=e.startsWith("```")?"\n... [truncated]\n```":"... [truncated]";return e.slice(0,t)+o};import{Buffer as Wt}from"buffer";import cn from"path";var Kt=T("repo"),Vt=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{Kt.info("Getting runner diffs");let o=await dn(r),{hasChanges:n}=o,{status:i}=o;if(!n)return{hasChanges:!1};if(!t){let E=mn(i);await gn(E,r)}Kt.info("Changes after processing"),await lt(r);let s=await ut(i,r);if(await at(s,r),n=await pn(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await b("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},c=await b("git",["diff",e.runSha,"HEAD"],a),d=String(c.stdout??"");if(n=!!d,!n)return await Jt(r),{hasChanges:!1,ignored:s};let p=await b("git",["diff",e.runSha,"HEAD","--binary"],a),u=String(p.stdout??""),g,h;if(e.sha){let E=await b("git",["diff",e.sha,"HEAD"],a);g=String(E.stdout??"");let _=await b("git",["diff",e.sha,"HEAD","--binary"],a),w=String(_.stdout??"");g!==w&&(h=Wt.from(w).toString("base64"))}await Jt(r);let x={hasChanges:!0,diff:d,resultDiff:g,ignored:s};return d!==u&&(x.diffBinary=Wt.from(u).toString("base64")),h&&(x.resultDiffBinary=h),x},Jt=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await b("git",["reset","--soft","HEAD~1"],{cwd:e})},at=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await b("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},lt=async(e=process.cwd())=>{let t=await b("git",["status","-s"],{cwd:e});return String(t.stdout??"")},zt=/.. (.+)?\.log$/,un=[zt],dn=async(e=process.cwd())=>{let t=await lt(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
|
|
7
|
+
`);return i.length>e.length*.8?e:i}import{execSync as $n}from"child_process";import fr from"fs/promises";import Fn from"path";import ie from"process";import{getTracer as Dn}from"@netlify/otel";import Re from"process";var ee=class extends Error{constructor(r,o,n,i=!1){super(r);this.statusCode=o;this.userMessage=n;this.isCreditLimitExceeded=i;this.name="GracefulShutdownError"}},bt=e=>e instanceof ee;var Oe=Re.env.NETLIFY_API_URL,$e=Re.env.NETLIFY_API_TOKEN,H=T("api"),Se=()=>Re.env.NETLIFY_LOCAL_MODE==="true",pe=async(e,t={})=>{if(!Oe||!$e)throw new Error("No API URL or token");let r=new URL(e,Oe),o={...t,headers:{...t.headers,Authorization:`Bearer ${$e}`}};Re.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(Re.env.AGENT_RUNNERS_DEBUG==="true")H.log(`Response headers for ${r}:`),n.headers.forEach((a,c)=>{H.log(` ${c}: ${a}`)});else{let a=n.headers.get("x-request-id")||n.headers.get("x-nf-request-id");H.log(`Request ID for ${r}: ${a||"N/A"}`)}if(i||H.error(`Got status ${n.status} for request ${r}`),t.raw){if(!i)throw new Error(`API request failed: ${n.status} ${n.statusText}`);return n}let s=await(n.headers.get("content-type")?.includes("application/json")?n.json():n.text());if(!i){let a=typeof s=="string"?s:JSON.stringify(s);throw n.status===404?new 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},Ct=e=>{H.log("Setting details for api",{apiUrl:e?.constants?.NETLIFY_API_HOST,token:!!e?.constants?.NETLIFY_API_TOKEN}),e?.constants?.NETLIFY_API_HOST&&(Oe=`https://${e.constants.NETLIFY_API_HOST}`),e?.constants?.NETLIFY_API_TOKEN&&($e=e.constants.NETLIFY_API_TOKEN)},Pt=()=>({apiUrl:Oe,token:$e}),ve=async(e,t)=>Se()?(H.log("Mock API: updateRunner called",{runnerId:e,data:t}),{id:e,...t}):pe(`/api/v1/agent_runners/${e}`,{method:"PUT",json:t}),B=async(e,t,r)=>Se()?(H.log("Mock API: updateRunnerSession called",JSON.stringify({runnerId:e,sessionId:t,data:r},null,2)),{id:e,sessionId:t,...r}):pe(`/api/v1/agent_runners/${e}/sessions/${t}`,{method:"PUT",json:r});var Nt=async(e,t)=>Se()?(H.log("Mock API: getRunnerSession called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,state:"running"}):pe(`/api/v1/agent_runners/${e}/sessions/${t}`),kt=(e,t,r)=>pe(`/api/v1/sites/${e}/ai-gateway/token`,{headers:{"X-Nf-Agent-Runner-Id":t,"X-Nf-Agent-Runner-Session-Id":r},gracefulOn503:!0}),Ot=async(e,t)=>Se()?(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"}}):pe(`/api/v1/agent_runners/${e}/sessions/${t}/diff/upload_urls`,{method:"POST"}),$t=async(e,t)=>Se()?(H.log("Mock API: updateSessionUsage called",{runnerId:e,sessionId:t}),{id:t,runnerId:e,usage:0}):pe(`/api/v1/agent_runners/${e}/sessions/${t}/update_usage`,{method:"POST"}),Qe=async(e,t)=>{H.log(`Uploading diff to S3: ${e.substring(0,50)}...`);let r=await fetch(e,{method:"PUT",body:t,headers:{"Content-Type":"text/plain"}});if(!r.ok)throw new Error(`S3 upload failed with status ${r.status}`);return r};var me=T("ai_gateway"),et=null;var Ft=async()=>{if(et)return et;me.log("Fetching available AI gateway providers");let e=await fetch(`${Pt().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 et=t,me.log("Cached AI gateway providers",{providerCount:Object.keys(t.providers).length}),t},jr=async(e,t)=>{let o=(await Ft()).providers[e];if(!o)return me.log(`Provider '${e}' not found`),!1;let n=o.models.includes(t);return me.log(`Model validation for ${e}/${t}`,{isAvailable:n}),n},Dt=async({netlify:e,config:t})=>{let r,o,n,i,s=e.constants?.SITE_ID;if(!s)throw new Error("No site id");let a=async()=>{clearTimeout(n),me.log("Requesting AI gateway information");let c=await kt(s,t.id,t.sessionId);if({token:r,url:i}=c,o=c.expires_at?c.expires_at*1e3:void 0,me.log("Got AI gateway information",{token:!!r,expiresAt:o,url:i}),o){let d=o-Date.now()-6e4;d>0&&(n=setTimeout(()=>{a()},d))}};return await Promise.all([a(),Ft()]),{get url(){return i},get token(){return r},isModelAvailableForProvider:jr}};import J from"process";import Q from"path";import Fe from"fs";import{fileURLToPath as Jr}from"url";import{createRequire as Vr}from"module";import{execa as zr,execaCommand as Wo}from"execa";import{Transform as Yr}from"stream";var Br=new Set(["NODE_ENV","PATH","HOME","USER","USERNAME","SHELL","PWD","OLDPWD","TMPDIR","TMP","TEMP","LANG","TERM","EDITOR","PAGER","OS","PROCESSOR_ARCHITECTURE","PROCESSOR_IDENTIFIER","SYSTEMROOT","WINDIR","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","APPDATA","LOCALAPPDATA","NODE_OPTIONS","NODE_PATH","NODE_DEBUG","NODE_NO_WARNINGS","npm_config_registry","npm_config_cache","npm_execpath","npm_node_execpath","CI","GITHUB_ACTIONS","GITHUB_WORKSPACE","GITHUB_REPOSITORY","GITHUB_REF","BUILDKITE","BUILDKITE_BRANCH","BUILDKITE_COMMIT","BUILDKITE_BUILD_NUMBER","JENKINS_URL","TRAVIS","CIRCLECI","DISPLAY","COLORTERM","TERM_PROGRAM","TERM_PROGRAM_VERSION","COLUMNS","LINES","HISTSIZE","HISTFILE","NETLIFY_AGENT_RUNNER_ID","NETLIFY_AGENT_RUNNER_SESSION_ID","NETLIFY_AGENT_RUNNER_PROMPT","NETLIFY_AGENT_RUNNER_AGENT","NETLIFY_AGENT_RUNNER_MODEL","NETLIFY_AGENT_RUNNER_CONTEXT","NETLIFY_AGENT_RUNNER_HAS_REPO","NETLIFY_FF_AGENT_RUNNER_BYOK_ENABLED","NETLIFY_AGENT_RUNNER_SHA","NETLIFY_TEAM_TYPE","AGENT_RUNNERS_DEBUG","NETLIFY_TEAM_ID","NETLIFY_AGENT_RUNNER_USER_ID","SITE_NAME"]),qr=new Set(["true","false","undefined","null","deploy","project","claude","gemini","codex",""]);function Hr(){return Object.entries(process.env).filter(([e,t])=>!(!t||Br.has(e)||qr.has(t)||!isNaN(Number(t))||t.length<5)).map(([,e])=>e).filter(Boolean)}function Z(e){if(typeof e!="string")return e;let t=Hr();if(t.length===0)return e;let r=e;return t.forEach(o=>{let n=new RegExp(Wr(o),"g");r=r.replace(n,"******")}),r}function Wr(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ge=class extends Yr{constructor(t={}){super({...t,objectMode:!1})}_transform(t,r,o){let n=t.toString(),i=Z(n);o(null,i)}};function Lt(){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"?Z(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"?Z(o):o;return typeof n=="function"?r(s,n):r(s,n,i)}}var Ae=null,Mt=e=>(Ae&&Ae.destroy(),Ae=new te({totalAllowedTime:e}),Ae),Ut=()=>Ae;var te=class{constructor({totalAllowedTime:t}){this.withStageTimer=async(t,r,o)=>{if(this.isTimeExpired())throw new Error(`${t} stage did not complete in the allowed time. Time has already expired.`);let n=this.onTimesUp(()=>{throw new Error(`${t} stage did not complete in the allowed time.`)}),i=null,s=null;o!==void 0&&(s=new Promise((a,c)=>{i=setTimeout(()=>{c(new Error(`${t} stage exceeded its maximum duration of ${o}ms`))},o)}));try{return s?await Promise.race([r(),s]):await r()}finally{n(),i&&clearTimeout(i)}};this.startTime=Date.now(),this.totalAllowedTime=t,this.globalTimeoutId=null,this.subscribers=[],this.hasTimedOut=!1,this.setupGlobalTimeout()}getElapsedTime(){return Date.now()-this.startTime}getRemainingTime(){let t=this.getElapsedTime(),r=this.totalAllowedTime-t;return Math.max(0,r)}isTimeExpired(){return this.getRemainingTime()===0||this.hasTimedOut}setupGlobalTimeout(){this.globalTimeoutId&&clearTimeout(this.globalTimeoutId),this.globalTimeoutId=setTimeout(()=>{this.notifyTimeUp()},this.totalAllowedTime)}notifyTimeUp(){this.hasTimedOut=!0;for(let t=this.subscribers.length-1;t>=0;t--)try{this.subscribers[t]()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}}onTimesUp(t){if(this.subscribers.push(t),this.hasTimedOut)try{t()}catch(r){console.error("TimeKeeper: Error in time up callback:",r)}return()=>{let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}}off(t){let r=this.subscribers.indexOf(t);r>-1&&this.subscribers.splice(r,1)}clearSubscribers(){this.subscribers.length=0}getSubscriberCount(){return this.subscribers.length}destroy(){this.globalTimeoutId&&(clearTimeout(this.globalTimeoutId),this.globalTimeoutId=null),this.clearSubscribers()}static{this.timeUnits={seconds:t=>t*1e3,minutes:t=>t*60*1e3,hours:t=>t*60*60*1e3}}};var Gt="netlify-agent-runner-context.md",tt="task-history",K=".netlify",ae="results.md",rt="assets";var le=1800*1e3,y={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 jt={name:"@netlify/agent-runner-cli",type:"module",version:"1.82.0-alpha.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",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.52","@anthropic-ai/sdk":"0.77.0","@google/gemini-cli":"0.29.3","@netlify/otel":"^5.1.1","@openai/codex":"0.104.0","@opentelemetry/exporter-trace-otlp-grpc":"^0.212.0",execa:"^9.6.1",kaddidlehopper:"^0.7.0",minimist:"^1.2.8",openai:"6.22.0"}};var Xr=Jr(import.meta.url),Zr=Q.dirname(Xr),Qr=Vr(import.meta.url),fe=T("shell"),nt=new Set,en={preferLocal:!0},b=(e,t,r)=>{let[o,n]=tn(t,r),i={...en,...n},s=zr(e,o,i);rn(s,i),on(s);let a=r?.idleTimeout;return a&&a>0&&nn(s,a),s};var tn=function(e,t){return Array.isArray(e)?[e,t]:typeof e=="object"&&e!==null?[[],e]:[[],void 0]},rn=(e,t)=>{if(t.stdio!==void 0||t.stdout!==void 0||t.stderr!==void 0)return;if(J.env.NETLIFY_MASK_LOGS!=="false"){e.all?.pipe(new ge).pipe(J.stdout),e.stdout?.pipe(new ge).pipe(J.stdout),e.stderr?.pipe(new ge).pipe(J.stderr);return}e.stdout?.pipe(J.stdout),e.stderr?.pipe(J.stderr)},ot=(e,t="SIGTERM")=>{try{return e.pid&&!e.killed?(J.kill(-e.pid,t),fe.log(`Killed process ${e.pid} with signal ${t}`),!0):!1}catch(r){return fe.error("Error killing process:",r),!1}},Yt=e=>ot(e,"SIGKILL"),nn=(e,t)=>{let r=null,o=()=>{fe.log(`Process ${e.pid} killed due to idle timeout (no output for ${t}ms)`),ot(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(fe.log(`Force killing idle process ${e.pid}`),Yt(e))},5e3)},n=()=>{r&&clearTimeout(r),r=setTimeout(o,t)};n(),e.stdout?.on("data",n),e.stderr?.on("data",n);let i=()=>{r&&(clearTimeout(r),r=null)};e.on("exit",i),e.on("error",i)},on=e=>{nt.add(e);let t=Ut();if(t){let r=t.onTimesUp(()=>{fe.log(`Global timer expired, killing process ${e.pid}`),ot(e,"SIGTERM"),setTimeout(()=>{e.pid&&!e.killed&&(fe.log(`Force killing process ${e.pid} after timeout`),Yt(e))},5e3)});e.on("exit",()=>{nt.delete(e),r()}),e.on("error",()=>{nt.delete(e),r()})}};function re(e,t){if(!J.env.NETLIFY_LOCAL_MODE)try{let n=Qr.resolve(jt.name),i=Q.dirname(n);for(;i!==Q.dirname(i);){let s=Q.dirname(i);if(Q.basename(s)==="node_modules"){let a=Q.join(s,".bin",t);if(Fe.existsSync(a))return a;break}i=s}}catch(n){console.error("Could not resolve package.json",n)}if(J.env.NODE_PATH){let n=Q.join(J.env.NODE_PATH,".bin",t);if(Fe.existsSync(n))return n}let r=Q.join(e,"node_modules",".bin",t);if(Fe.existsSync(r))return r;let o=Q.join(Zr,"..","node_modules",".bin",t);if(Fe.existsSync(o))return o}var sn=T("utils"),an=e=>new Promise(t=>{setTimeout(t,e)}),De=(e,t=3e3)=>{let r=!1,o=null,n=[],i=null,s=(...a)=>{if(r)return o=a,new Promise(p=>{n.push(p)});r=!0;let c,d=new Promise(p=>{c=p});return i=(async()=>{await Promise.resolve();let p=await e(...a);for(c(p);;){if(await an(t),!o)return r=!1,i=null,p;let u=o,g=n;o=null,n=[],p=await e(...u),g.forEach(h=>{h(p)})}})(),d};return s.flush=async()=>{if((r||o)&&i)return await i,s.flush()},s},he=(e,t,r=!1)=>{let o=null,n=null,i=null,s=function(...a){n=a,i=this;let c=r&&!o;clearTimeout(o),o=setTimeout(()=>{o=null,r||(e.apply(i,n),n=null,i=null)},t),c&&(e.apply(i,n),n=null,i=null)};return s.cancel=()=>{clearTimeout(o),o=null,n=null,i=null},s.flush=()=>{if(o){clearTimeout(o);let a=n,c=i;o=null,n=null,i=null,e.apply(c,a)}},s},Bt=(e,t=!0,r)=>{if(e)try{return JSON.parse(e)}catch(o){t&&(r?.error?r.error("Could not parse JSON",o):sn.error("Could not parse JSON",o))}},it=e=>e.charAt(0).toUpperCase()+e.slice(1),ne=e=>e.split("-").map(t=>t.length===2?t.toUpperCase():it(t)).join(" ");function ce(e,t){t&&e.log(`Skill invoked: ${t}`)}var qt=e=>Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0)),Ht=(e,t)=>{let n=".netlify.app",i="agent-";if(!t)return`${i}${e.slice(0,6)}`;let a=`--${t}${n}`;if(a.length>55)return"";let c=60-a.length;if(c<=0)return"";if(c>=i.length+6){let d=Math.min(c-i.length,e.length);return`${i}${e.slice(0,d)}`}return e.slice(0,c)};var ln=50*1024,st=(e,t=ln)=>{if(!e||typeof e!="string"||e.length<=t)return e;let o=e.startsWith("```")?"\n... [truncated]\n```":"... [truncated]";return e.slice(0,t)+o};import{Buffer as Wt}from"buffer";import cn from"path";var Kt=T("repo"),Vt=async({config:e,isRetry:t,cwd:r=process.cwd()})=>{Kt.info("Getting runner diffs");let o=await dn(r),{hasChanges:n}=o,{status:i}=o;if(!n)return{hasChanges:!1};if(!t){let E=mn(i);await gn(E,r)}Kt.info("Changes after processing"),await lt(r);let s=await ut(i,r);if(await at(s,r),n=await pn(r),!n)return{hasChanges:!1,ignored:s};process.env.NETLIFY_INTERNAL_GIT="1";try{await b("git",["commit","-m","Agent runner"],{cwd:r})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}let a={stdio:["ignore","pipe","pipe"],cwd:r},c=await b("git",["diff",e.runSha,"HEAD"],a),d=String(c.stdout??"");if(n=!!d,!n)return await Jt(r),{hasChanges:!1,ignored:s};let p=await b("git",["diff",e.runSha,"HEAD","--binary"],a),u=String(p.stdout??""),g,h;if(e.sha){let E=await b("git",["diff",e.sha,"HEAD"],a);g=String(E.stdout??"");let _=await b("git",["diff",e.sha,"HEAD","--binary"],a),w=String(_.stdout??"");g!==w&&(h=Wt.from(w).toString("base64"))}await Jt(r);let x={hasChanges:!0,diff:d,resultDiff:g,ignored:s};return d!==u&&(x.diffBinary=Wt.from(u).toString("base64")),h&&(x.resultDiffBinary=h),x},Jt=async(e=process.cwd())=>{process.env.NETLIFY_LOCAL_MODE&&await b("git",["reset","--soft","HEAD~1"],{cwd:e})},at=async(e=[],t=process.cwd())=>{process.env.NETLIFY_INTERNAL_GIT="1";try{await b("git",["add",".",...e],{cwd:t})}finally{process.env.NETLIFY_INTERNAL_GIT="0"}},lt=async(e=process.cwd())=>{let t=await b("git",["status","-s"],{cwd:e});return String(t.stdout??"")},zt=/.. (.+)?\.log$/,un=[zt],dn=async(e=process.cwd())=>{let t=await lt(e);return{hasChanges:(t.trim().length===0?[]:t.split(`
|
|
8
8
|
`).filter(n=>un.some(s=>s instanceof RegExp?s.test(n):n===s)?!1:n[1]?.trim()!=="")).length!==0,status:t}},pn=async(e=process.cwd())=>{try{return await b("git",["diff","--staged","--quiet"],{cwd:e}),!1}catch{return!0}},ct=async(e=process.cwd())=>{let{stdout:t}=await b("git",["rev-parse","HEAD"],{cwd:e});return String(t??"").trim()},Xt=async(e=process.cwd())=>{let{stdout:t}=await b("git",["rev-list","--max-parents=0","HEAD"],{cwd:e});return String(t??"").trim()},ut=async(e,t=process.cwd())=>{e||=await lt(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(`
|
|
9
9
|
`).forEach(n=>{r.forEach(s=>{let a=n===`?? ${s}`,c=n.startsWith(`?? ${s}/`)||n.startsWith(`?? ${s}${cn.sep}`);(a||c)&&o.push(`:!${s}`)});let i=n.match(zt)?.[1];i&&o.push(`:!${i}.log`)}),o},dt=async(e=process.cwd())=>{await b("git",["reset","--hard","HEAD"],{cwd:e})},mn=e=>{let t=e.split(`
|
|
10
10
|
`).reduce((r,o)=>{if(!o)return r;let[n,i,,...s]=o,a=s.join(""),c=n.trim(),d=i.trim();return r[a]?r[a].change=d:r[a]={filePath:a,stage:c,change:d},r},{});return Object.values(t)},gn=async(e,t=process.cwd())=>{let r=e.filter(o=>o.stage&&!o.change).map(o=>o.filePath);r.length!==0&&await b("git",["restore","--staged","--worktree","--pathspec-from-file=-"],{cwd:t,input:r.join(`
|
package/package.json
CHANGED