@netlify/agent-runner-cli 1.137.0 → 1.138.0-pty.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.
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ 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);
3
+ var q=Object.create;var U=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var Z=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty;var V=(t,o)=>()=>(o||t((o={exports:{}}).exports,o),o.exports);var X=(t,o,e,f)=>{if(o&&typeof o=="object"||typeof o=="function")for(let c of Q(o))!G.call(t,c)&&c!==e&&U(t,c,{get:()=>o[c],enumerable:!(f=H(o,c))||f.enumerable});return t};var x=(t,o,e)=>(e=t!=null?q(Z(t)):{},X(o||!t||!t.__esModule?U(e,"default",{value:t,enumerable:!0}):e,t));var g=V((lt,W)=>{"use strict";function y(t,o){var e=t;o.slice(0,-1).forEach(function(c){e=e[c]||{}});var f=o[o.length-1];return f in e}function Y(t){return typeof t=="number"||/^0x[0-9a-f]+$/i.test(t)?!0:/^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(t)}function z(t,o){return o==="constructor"&&typeof t[o]=="function"||o==="__proto__"}W.exports=function(t,o){o||(o={});var e={bools:{},strings:{},unknownFn:null};typeof o.unknown=="function"&&(e.unknownFn=o.unknown),typeof o.boolean=="boolean"&&o.boolean?e.allBools=!0:[].concat(o.boolean).filter(Boolean).forEach(function(n){e.bools[n]=!0});var f={};function c(n){return f[n].some(function(l){return e.bools[l]})}Object.keys(o.alias||{}).forEach(function(n){f[n]=[].concat(o.alias[n]),f[n].forEach(function(l){f[l]=[n].concat(f[n].filter(function(b){return l!==b}))})}),[].concat(o.string).filter(Boolean).forEach(function(n){e.strings[n]=!0,f[n]&&[].concat(f[n]).forEach(function(l){e.strings[l]=!0})});var _=o.default||{},m={_:[]};function J(n,l){return e.allBools&&/^--[^=]+$/.test(l)||e.strings[n]||e.bools[n]||f[n]}function $(n,l,b){for(var i=n,T=0;T<l.length-1;T++){var w=l[T];if(z(i,w))return;i[w]===void 0&&(i[w]={}),(i[w]===Object.prototype||i[w]===Number.prototype||i[w]===String.prototype)&&(i[w]={}),i[w]===Array.prototype&&(i[w]=[]),i=i[w]}var O=l[l.length-1];z(i,O)||((i===Object.prototype||i===Number.prototype||i===String.prototype)&&(i={}),i===Array.prototype&&(i=[]),i[O]===void 0||e.bools[O]||typeof i[O]=="boolean"?i[O]=b:Array.isArray(i[O])?i[O].push(b):i[O]=[i[O],b])}function d(n,l,b){if(!(b&&e.unknownFn&&!J(n,b)&&e.unknownFn(b)===!1)){var i=!e.strings[n]&&Y(l)?Number(l):l;$(m,n.split("."),i),(f[n]||[]).forEach(function(T){$(m,T.split("."),i)})}}Object.keys(e.bools).forEach(function(n){d(n,_[n]===void 0?!1:_[n])});var N=[];t.indexOf("--")!==-1&&(N=t.slice(t.indexOf("--")+1),t=t.slice(0,t.indexOf("--")));for(var a=0;a<t.length;a++){var r=t[a],s,h;if(/^--.+=/.test(r)){var R=r.match(/^--([^=]+)=([\s\S]*)$/);s=R[1];var P=R[2];e.bools[s]&&(P=P!=="false"),d(s,P,r)}else if(/^--no-.+/.test(r))s=r.match(/^--no-(.+)/)[1],d(s,!1,r);else if(/^--.+/.test(r))s=r.match(/^--(.+)/)[1],h=t[a+1],h!==void 0&&!/^(-|--)[^-]/.test(h)&&!e.bools[s]&&!e.allBools&&(!f[s]||!c(s))?(d(s,h,r),a+=1):/^(true|false)$/.test(h)?(d(s,h==="true",r),a+=1):d(s,e.strings[s]?"":!0,r);else if(/^-[^-]+/.test(r)){for(var v=r.slice(1,-1).split(""),A=!1,p=0;p<v.length;p++){if(h=r.slice(p+2),h==="-"){d(v[p],h,r);continue}if(/[A-Za-z]/.test(v[p])&&h[0]==="="){d(v[p],h.slice(1),r),A=!0;break}if(/[A-Za-z]/.test(v[p])&&/-?\d+(\.\d*)?(e-?\d+)?$/.test(h)){d(v[p],h,r),A=!0;break}if(v[p+1]&&v[p+1].match(/\W/)){d(v[p],r.slice(p+2),r),A=!0;break}else d(v[p],e.strings[v[p]]?"":!0,r)}s=r.slice(-1)[0],!A&&s!=="-"&&(t[a+1]&&!/^(-|--)[^-]/.test(t[a+1])&&!e.bools[s]&&(!f[s]||!c(s))?(d(s,t[a+1],r),a+=1):t[a+1]&&/^(true|false)$/.test(t[a+1])?(d(s,t[a+1]==="true",r),a+=1):d(s,e.strings[s]?"":!0,r))}else if((!e.unknownFn||e.unknownFn(r)!==!1)&&m._.push(e.strings._||!Y(r)?r:Number(r)),o.stopEarly){m._.push.apply(m._,t.slice(a+1));break}}return Object.keys(_).forEach(function(n){y(m,n.split("."))||($(m,n.split("."),_[n]),(f[n]||[]).forEach(function(l){$(m,l.split("."),_[n])}))}),o["--"]?m["--"]=N.slice():N.forEach(function(n){m._.push(n)}),m}});var M=x(g(),1);import j from"fs";import k from"path";import u from"process";import B from"ws";var tt=29,et=()=>{try{let t=j.readFileSync(k.join(u.cwd(),".env"),"utf8");for(let o of t.split(`
4
+ `)){let e=o.trim();if(!e||e.startsWith("#"))continue;let f=e.indexOf("=");if(f===-1||e.slice(0,f).trim()!=="PTY_COOKIE")continue;let c=e.slice(f+1).trim();if(/^(".*"|'.*')$/.test(c)&&(c=c.slice(1,-1)),c)return c}}catch{}return u.env.PTY_COOKIE||void 0},S=(0,M.default)(u.argv.slice(2),{string:["url","host","port","cwd","model"],boolean:["help"],alias:{h:"help"}}),ot=()=>{u.stdout.write(`
5
+ agent-runner-pty - Interactive terminal client for a remote Claude PTY
6
+
7
+ USAGE:
8
+ agent-runner-pty [options]
9
+
10
+ OPTIONS:
11
+ --url <ws-url> Full WebSocket URL (overrides --host/--port)
12
+ --host <host> Server host (default: localhost)
13
+ --port <port> Server port (default: 8888)
14
+ --cwd <path> Directory Claude should run in on the server
15
+ --model <name> Model to run Claude with
16
+ --help, -h Show this help message
17
+
18
+ AUTH:
19
+ PTY_COOKIE (from a .env file in the working directory, or the environment)
20
+ is sent as a Cookie header on the connection when set.
21
+
22
+ QUIT:
23
+ Exit Claude normally (e.g. /exit), or press Ctrl-] to force quit.
24
+ `)};S.help&&(ot(),u.exit(0));var nt=()=>{if(S.url)return S.url;let t=S.host||"localhost",o=S.port||"8888",e=new URLSearchParams;return S.cwd&&e.set("cwd",S.cwd),S.model&&e.set("model",S.model),e.set("cols",String(u.stdout.columns||80)),e.set("rows",String(u.stdout.rows||24)),`ws://${t}:${o}/pty?${e.toString()}`},rt=nt(),L=et(),C=new B(rt,L?{headers:{Cookie:`PTY_COOKIE=${L}`}}:void 0),E=u.stdin,F=!1,I=0,K=()=>{F&&E.isTTY&&(E.setRawMode(!1),F=!1),E.pause()},D=t=>{K(),E.removeAllListeners("data"),u.stdout.removeAllListeners("resize"),u.exit(t)},it=()=>{C.readyState===B.OPEN&&C.send(JSON.stringify({type:"resize",cols:u.stdout.columns||80,rows:u.stdout.rows||24}))},st=t=>{if(t.length===1&&t[0]===tt){D(0);return}C.readyState===B.OPEN&&C.send(JSON.stringify({type:"stdin",data:t.toString("utf8")}))};C.on("open",()=>{E.isTTY&&(E.setRawMode(!0),F=!0),E.resume(),E.on("data",st),u.stdout.on("resize",it)});C.on("message",(t,o)=>{if(o){u.stdout.write(t);return}try{let e=JSON.parse(t.toString());e.type==="exit"?I=e.code??0:e.type==="error"&&(K(),u.stderr.write(`
25
+ [agent-runner-pty] ${e.message??"server error"}
26
+ `),I=1)}catch{}});C.on("close",()=>{D(I)});C.on("error",t=>{K(),u.stderr.write(`
27
+ [agent-runner-pty] connection error: ${t.message}
28
+ `),u.exit(1)});
29
+ //# sourceMappingURL=pty-client.js.map
package/package.json CHANGED
@@ -1,14 +1,15 @@
1
1
  {
2
2
  "name": "@netlify/agent-runner-cli",
3
3
  "type": "module",
4
- "version": "1.137.0",
4
+ "version": "1.138.0-pty.1",
5
5
  "description": "CLI tool for running Netlify agents",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "exports": "./dist/index.js",
9
9
  "bin": {
10
10
  "agent-runner-cli": "./dist/bin.js",
11
- "agent-runner-cli-local": "./dist/bin-local.js"
11
+ "agent-runner-cli-local": "./dist/bin-local.js",
12
+ "agent-runner-pty": "./dist/pty-client.js"
12
13
  },
13
14
  "files": [
14
15
  "dist/**/*.js",
@@ -63,6 +64,7 @@
63
64
  "@netlify/axis": "^1.17.0",
64
65
  "@netlify/eslint-config-node": "^7.0.1",
65
66
  "@types/node": "^24.5.0",
67
+ "@types/ws": "^8.5.12",
66
68
  "@typescript-eslint/eslint-plugin": "^8.0.0",
67
69
  "@typescript-eslint/parser": "^8.0.0",
68
70
  "@vitest/coverage-v8": "^4.1.5",
@@ -92,6 +94,8 @@
92
94
  "execa": "^9.6.1",
93
95
  "fastify": "5.8.5",
94
96
  "minimist": "^1.2.8",
95
- "openai": "6.34.0"
97
+ "node-pty": "1.1.0",
98
+ "openai": "6.34.0",
99
+ "ws": "8.21.0"
96
100
  }
97
101
  }
@@ -13,6 +13,36 @@ console.log(`[postinstall] cwd=${cwd}`)
13
13
  console.log(`[postinstall] INIT_CWD=${initCwd}`)
14
14
  console.log('[postinstall] using patchesDir =', patchesDir)
15
15
 
16
+ // node-pty (used by the interactive PTY endpoint) ships a prebuilt
17
+ // `spawn-helper` that it execs to fork the child. Some install paths — notably
18
+ // the allow-scripts gate that blocks node-pty's own install step — drop the
19
+ // executable bit, and then every spawn fails with "posix_spawnp failed". Make
20
+ // it executable defensively; it's a no-op when already correct.
21
+ const ensureSpawnHelperExecutable = () => {
22
+ const candidates = [
23
+ path.join(cwd, '..', 'node-pty'),
24
+ path.join(cwd, 'node_modules', 'node-pty'),
25
+ path.join(targetCwd, 'node_modules', 'node-pty'),
26
+ ]
27
+ for (const ptyDir of candidates) {
28
+ const prebuildsDir = path.join(ptyDir, 'prebuilds')
29
+ if (!fs.existsSync(prebuildsDir)) continue
30
+ for (const platform of fs.readdirSync(prebuildsDir)) {
31
+ const helper = path.join(prebuildsDir, platform, 'spawn-helper')
32
+ try {
33
+ if (fs.existsSync(helper)) {
34
+ fs.chmodSync(helper, 0o755)
35
+ console.log(`[postinstall] chmod +x ${helper}`)
36
+ }
37
+ } catch (error) {
38
+ console.warn(`[postinstall] Failed to chmod ${helper}:`, error.message)
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ ensureSpawnHelperExecutable()
45
+
16
46
  if (fs.existsSync(patchesDir)) {
17
47
  const files = fs.readdirSync(patchesDir).filter((file) => file.endsWith('.patch'))
18
48