@netlify/agent-runner-cli 1.136.0 → 1.138.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,4 @@
1
+ import { createRequire as __cr } from 'node:module'; import { fileURLToPath as __ftu } from 'node:url'; import { dirname as __dnn } from 'node:path'; const require = __cr(import.meta.url); const __filename = __ftu(import.meta.url); const __dirname = __dnn(__filename);
1
2
  import{spawnSync as w}from"child_process";import{existsSync as I,readdirSync as A,readFileSync as N,statSync as E,writeFileSync as x,mkdirSync as F}from"fs";import{createRequire as v}from"module";import i from"path";import e from"process";var L=".axis-scaffold-skip-install",S=v(import.meta.url);function b(){let t=S("@netlify/ts-cli/package.json"),n=i.dirname(S.resolve("@netlify/ts-cli/package.json"));return i.join(n,t.bin)}function C(t){let n=t.slice(2),s=n[0];(!s||s.startsWith("--"))&&(console.error("Usage: scaffold.js <template-id> [--package-manager npm|pnpm|yarn]"),e.exit(1));let o=n.indexOf("--package-manager"),r=o!==-1?n[o+1]??"":"";return{templateId:s,packageManager:r}}var $=new Set(["node_modules",".git",".netlify",".claude",".next","dist","build",".cache"]),T=["package.json","app.config.ts","app.config.js","vite.config.ts","vite.config.js","next.config.ts","next.config.js","next.config.mjs","remix.config.js","nuxt.config.ts","app/routes/__root.tsx","app/routes/__root.jsx","app/root.tsx","app/root.jsx","src/main.tsx","src/main.ts","src/App.tsx","app/layout.tsx","pages/_app.tsx"],D=4,j=1e4;function M(t){let n=[];for(let s of T){if(n.length>=D)break;let o=i.join(t,s);try{if(!I(o))continue;let r=N(o,"utf8");n.push({filePath:s,content:r.length>j?r.slice(0,j)+`
2
3
  \u2026 (truncated)`:r})}catch{}}return n}function O(t,n=4){let s=[];function o(r,a){if(a>n)return;let f;try{f=A(r).sort()}catch{return}for(let m of f){if($.has(m))continue;let p=i.join(r,m),y=i.relative(t,p),h;try{h=E(p).isDirectory()}catch{continue}h?(s.push(y+"/"),o(p,a+1)):s.push(y)}}return o(t,0),s.join(`
3
4
  `)}function P(t){let n=O(t),s=M(t),o=a=>i.extname(a).slice(1)||"text";return["## File tree\n\n```\n"+n+"\n```",...s.map(({filePath:a,content:f})=>`## ${a}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@netlify/agent-runner-cli",
3
3
  "type": "module",
4
- "version": "1.136.0",
4
+ "version": "1.138.0",
5
5
  "description": "CLI tool for running Netlify agents",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -36,6 +36,7 @@
36
36
  "test:ci": "run-s build test:ci:*",
37
37
  "test:dev:vitest": "LOG=0 vitest --exclude '**/integration/**'",
38
38
  "test:ci:vitest": "LOG=0 vitest run --coverage --exclude '**/integration/**'",
39
+ "test:smoke": "node scripts/smoke-dist.js",
39
40
  "test:integration": "vitest run test/integration/",
40
41
  "test:integration:codex": "vitest run test/integration/codex.test.ts",
41
42
  "test:integration:claude": "vitest run test/integration/claude.test.ts",
@@ -81,6 +82,7 @@
81
82
  "@anthropic-ai/claude-code": "2.1.197",
82
83
  "@anthropic-ai/sdk": "0.91.1",
83
84
  "@google/gemini-cli": "0.42.0",
85
+ "@netlify/cache-utils": "^6.0.5",
84
86
  "@netlify/database-proxy": "^0.1.5",
85
87
  "@netlify/otel": "^6.0.3",
86
88
  "@netlify/ts-cli": "^1.2.0",
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Smoke test for the bundled artifact (dist/), which no other test exercises:
3
+ * vitest imports from src/, and a clean tsup build only proves static
4
+ * resolution. Runs dist/bin.js and fails on bundling-only errors (unresolved
5
+ * dynamic require, missing require/__dirname shim, missing runtime asset) on
6
+ * two paths:
7
+ * 1. flag off — the module graph loads and the pipeline reaches init.
8
+ * 2. flag on — the fastify server compiles ajv route schemas, exercising the
9
+ * only surviving runtime requires (ajv/dist/runtime/*, fast-json-stringify).
10
+ * Each run is expected to stop at a config/credentials error, not a bundling one.
11
+ */
12
+ import { spawn } from 'node:child_process'
13
+ import { existsSync } from 'node:fs'
14
+ import path from 'node:path'
15
+ import process from 'node:process'
16
+ import { fileURLToPath } from 'node:url'
17
+
18
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
19
+ const root = path.resolve(__dirname, '..')
20
+ const binPath = path.join(root, 'dist', 'bin.js')
21
+
22
+ if (!existsSync(binPath)) {
23
+ console.error(`[smoke] ${binPath} not found — run \`npm run build\` first`)
24
+ process.exit(1)
25
+ }
26
+
27
+ // Output that means the bundle itself is broken, not a missing-credentials
28
+ // failure. "Dynamic require of X" is esbuild's stub; the ReferenceErrors fire
29
+ // when the banner shims are absent.
30
+ const BUNDLING_FAILURE = [
31
+ /Dynamic require of/i,
32
+ /require is not defined/i,
33
+ /__dirname is not defined/i,
34
+ /__filename is not defined/i,
35
+ /Cannot find module/i,
36
+ /ERR_MODULE_NOT_FOUND/i,
37
+ /ERR_REQUIRE_ESM/i,
38
+ /ENOENT[\s\S]{0,80}\.proto/i,
39
+ /\.proto[\s\S]{0,80}ENOENT/i,
40
+ ]
41
+
42
+ // A minimally-valid config so getConfig() succeeds and execution reaches the
43
+ // pipeline (and, with the flag on, startServer). HAS_REPO=0 keeps init off the
44
+ // git path; no API token means it stops at the expected credentials error.
45
+ const baseEnv = {
46
+ ...process.env,
47
+ NETLIFY_AGENT_RUNNER_SESSION_ID: 'smoke',
48
+ NETLIFY_AGENT_RUNNER_ID: 'smoke',
49
+ NETLIFY_TEAM_ID: 'smoke',
50
+ NETLIFY_AGENT_RUNNER_PROMPT: 'smoke test — no real work',
51
+ NETLIFY_AGENT_RUNNER_MODE: 'normal',
52
+ NETLIFY_AGENT_RUNNER_HAS_REPO: '0',
53
+ }
54
+
55
+ /**
56
+ * Spawn the bundle and capture output. `stop` is triggered once `readyRe` (or a
57
+ * bundling failure) appears, or after `timeoutMs`; the flag-on run keeps a
58
+ * server up, so we resolve only after the child has actually exited — SIGTERM,
59
+ * then SIGKILL if it lingers — otherwise it would orphan and hold the port.
60
+ */
61
+ const runBundle = (label, extraEnv, { readyRe, timeoutMs }) =>
62
+ new Promise((resolve) => {
63
+ const child = spawn(process.execPath, [binPath], {
64
+ cwd: root,
65
+ env: { ...baseEnv, ...extraEnv },
66
+ stdio: ['ignore', 'pipe', 'pipe'],
67
+ })
68
+ let out = ''
69
+ let reason = 'exit'
70
+ let hardKill
71
+ const stop = (why) => {
72
+ reason = why
73
+ if (child.exitCode === null && child.signalCode === null) {
74
+ child.kill('SIGTERM')
75
+ hardKill = setTimeout(() => child.kill('SIGKILL'), 2000)
76
+ }
77
+ }
78
+ const onData = (d) => {
79
+ out += d
80
+ if (BUNDLING_FAILURE.some((re) => re.test(out))) stop('bundling-failure')
81
+ else if (readyRe && readyRe.test(out)) stop('ready')
82
+ }
83
+ child.stdout.on('data', onData)
84
+ child.stderr.on('data', onData)
85
+ child.once('error', (err) => {
86
+ out += `\nspawn error: ${err.message}`
87
+ resolve({ label, out, reason: 'spawn-error' })
88
+ })
89
+ const timer = setTimeout(() => stop('timeout'), timeoutMs)
90
+ child.once('exit', () => {
91
+ clearTimeout(timer)
92
+ clearTimeout(hardKill)
93
+ resolve({ label, out, reason })
94
+ })
95
+ })
96
+
97
+ const check = ({ label, out }, { require: required }) => {
98
+ const failure = BUNDLING_FAILURE.find((re) => re.test(out))
99
+ // Any structured app log (`[AR]-…`) proves the bundle evaluated and app code
100
+ // ran — a module-eval crash produces a bare Node stack and none of these.
101
+ const ranAppCode = /\[AR\]-/.test(out)
102
+ const met = required.test(out)
103
+ const ok = !failure && ranAppCode && met
104
+ console.log(`\n=== [${label}] ${ok ? 'PASS' : 'FAIL'} ===`)
105
+ if (failure) console.log(` ✗ bundling-failure signature: ${failure}`)
106
+ if (!ranAppCode) console.log(' ✗ no app output — bundle likely crashed during module evaluation')
107
+ if (!met) console.log(` ✗ never observed expected marker: ${required}`)
108
+ if (ok) console.log(` ✓ bundle ran, no bundling failure, saw ${required}`)
109
+ if (!ok) console.log(' --- last output ---\n' + out.split('\n').slice(-20).join('\n'))
110
+ return ok
111
+ }
112
+
113
+ const results = []
114
+
115
+ // Flag off: module graph loads, pipeline reaches init, stops at the creds error.
116
+ results.push(
117
+ check(
118
+ await runBundle('flag-off: module-load + pipeline', {}, { readyRe: /No API URL or token/i, timeoutMs: 30_000 }),
119
+ {
120
+ require: /No API URL or token/i,
121
+ },
122
+ ),
123
+ )
124
+
125
+ // Flag on: fastify compiles ajv route schemas (the surviving runtime requires).
126
+ results.push(
127
+ check(
128
+ await runBundle(
129
+ 'flag-on: fastify + ajv dynamic requires',
130
+ { NETLIFY_FF_AGENT_RUNNER_IDLE_TIMEOUT: 'true' },
131
+ { readyRe: /HTTP server listening/i, timeoutMs: 30_000 },
132
+ ),
133
+ { require: /HTTP server listening/i },
134
+ ),
135
+ )
136
+
137
+ if (results.every(Boolean)) {
138
+ console.log('\n[smoke] PASS — bundled artifact is runnable end-to-end')
139
+ process.exit(0)
140
+ }
141
+ console.error('\n[smoke] FAIL — bundle broke at runtime (see above)')
142
+ process.exit(1)