pi-bridge 0.3.0 → 0.3.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/bin/pii.js CHANGED
@@ -63,6 +63,11 @@ if (!pi) {
63
63
  process.exit(1);
64
64
  }
65
65
 
66
+ // Expose resolved pi paths so child-process-patch can re-spawn pi correctly
67
+ // when the review skill (or any internal tool) calls `pi` as a subprocess.
68
+ process.env.PI_BRIDGE_CLI = pi.cli;
69
+ process.env.PI_BRIDGE_NODE = pi.nodeExe;
70
+
66
71
  const result = spawnSync(
67
72
  pi.nodeExe,
68
73
  ['--require', preload, pi.cli, ...process.argv.slice(2)],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-bridge",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Transparent filesystem bridge that makes pi run natively on a remote machine over SSH",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -50,6 +50,22 @@ function patchChildProcess(fakeRoot, remote) {
50
50
  return name === 'node' || name === 'pi' || name === 'pii';
51
51
  }
52
52
 
53
+ /**
54
+ * When pi spawns 'pi' or 'pii' as a subprocess (e.g. the /review skill),
55
+ * the bare command name won't be found in PATH on Windows because pi is a
56
+ * JS file located by pii's findPi(). pii.js sets PI_BRIDGE_CLI / PI_BRIDGE_NODE
57
+ * in the environment so we can resolve the correct executable here.
58
+ *
59
+ * Returns { nodeExe, cli } when applicable, null otherwise.
60
+ */
61
+ function resolvePiExe(file) {
62
+ const name = normalizeCmd(file).toLowerCase();
63
+ if (name !== 'pi' && name !== 'pii') return null;
64
+ const cli = process.env.PI_BRIDGE_CLI;
65
+ if (!cli) return null;
66
+ return { nodeExe: process.env.PI_BRIDGE_NODE || process.execPath, cli };
67
+ }
68
+
53
69
  /**
54
70
  * Build SSH args for a file + args invocation:
55
71
  * cd to remote cwd, then run the command with shell-quoted arguments.
@@ -84,7 +100,11 @@ function patchChildProcess(fakeRoot, remote) {
84
100
  opts = opts || {};
85
101
 
86
102
  const cwd = effectiveCwd(opts);
87
- if (!isFakePath(cwd, fakeRoot) || isLocalOnly(file)) return origSpawn(file, args, opts);
103
+ if (!isFakePath(cwd, fakeRoot) || isLocalOnly(file)) {
104
+ const piExe = resolvePiExe(file);
105
+ if (piExe) return origSpawn(piExe.nodeExe, [piExe.cli, ...args], opts);
106
+ return origSpawn(file, args, opts);
107
+ }
88
108
 
89
109
  return origSpawn('ssh', buildSshArgs(file, args, opts), Object.assign({}, opts, { cwd: undefined }));
90
110
  };
@@ -96,7 +116,11 @@ function patchChildProcess(fakeRoot, remote) {
96
116
  opts = opts || {};
97
117
 
98
118
  const cwd = effectiveCwd(opts);
99
- if (!isFakePath(cwd, fakeRoot) || isLocalOnly(file)) return origSpawnSync(file, args, opts);
119
+ if (!isFakePath(cwd, fakeRoot) || isLocalOnly(file)) {
120
+ const piExe = resolvePiExe(file);
121
+ if (piExe) return origSpawnSync(piExe.nodeExe, [piExe.cli, ...args], opts);
122
+ return origSpawnSync(file, args, opts);
123
+ }
100
124
 
101
125
  return origSpawnSync('ssh', buildSshArgs(file, args, opts), Object.assign({}, opts, { cwd: undefined }));
102
126
  };
@@ -119,7 +143,11 @@ function patchChildProcess(fakeRoot, remote) {
119
143
  opts = opts || {};
120
144
 
121
145
  const cwd = effectiveCwd(opts);
122
- if (!isFakePath(cwd, fakeRoot) || isLocalOnly(file)) return origExecFileSync(file, args, opts);
146
+ if (!isFakePath(cwd, fakeRoot) || isLocalOnly(file)) {
147
+ const piExe = resolvePiExe(file);
148
+ if (piExe) return origExecFileSync(piExe.nodeExe, [piExe.cli, ...args], opts);
149
+ return origExecFileSync(file, args, opts);
150
+ }
123
151
 
124
152
  return origExecFileSync('ssh', buildSshArgs(file, args, opts), Object.assign({}, opts, { cwd: undefined }));
125
153
  };
@@ -93,31 +93,37 @@ req.on('error', (e) => {
93
93
  * @throws - On HTTP errors or non-2xx status codes
94
94
  */
95
95
  function httpPost(port, token, urlPath, body) {
96
+ // Body is passed via stdin (not embedded in the script) to avoid ENAMETOOLONG
97
+ // on Windows when writing large files such as session exports.
96
98
  const script = `
97
99
  const http = require('http');
98
- const body = ${JSON.stringify(body)};
99
- const bodyBuf = Buffer.from(body, 'utf8');
100
- let resBody = '';
101
- let statusCode = 0;
102
- const req = http.request(
103
- { method:'POST', hostname:'127.0.0.1', port:${JSON.stringify(port)}, path:${JSON.stringify(urlPath)},
104
- headers:{'x-token':${JSON.stringify(token)},'Content-Type':'text/plain; charset=utf-8','Content-Length':bodyBuf.length} },
105
- (res) => {
106
- statusCode = res.statusCode;
107
- res.setEncoding('utf8');
108
- res.on('data', (d) => { resBody += d; });
109
- res.on('end', () => {
110
- process.stdout.write(JSON.stringify({ ok: statusCode >= 200 && statusCode < 300, status: statusCode, body: resBody }));
111
- });
112
- }
113
- );
114
- req.on('error', (e) => {
115
- process.stdout.write(JSON.stringify({ ok: false, status: 0, body: e.message }));
100
+ let raw = '';
101
+ process.stdin.setEncoding('utf8');
102
+ process.stdin.on('data', (d) => { raw += d; });
103
+ process.stdin.on('end', () => {
104
+ const bodyBuf = Buffer.from(raw, 'utf8');
105
+ let resBody = '';
106
+ let statusCode = 0;
107
+ const req = http.request(
108
+ { method:'POST', hostname:'127.0.0.1', port:${JSON.stringify(port)}, path:${JSON.stringify(urlPath)},
109
+ headers:{'x-token':${JSON.stringify(token)},'Content-Type':'text/plain; charset=utf-8','Content-Length':bodyBuf.length} },
110
+ (res) => {
111
+ statusCode = res.statusCode;
112
+ res.setEncoding('utf8');
113
+ res.on('data', (d) => { resBody += d; });
114
+ res.on('end', () => {
115
+ process.stdout.write(JSON.stringify({ ok: statusCode >= 200 && statusCode < 300, status: statusCode, body: resBody }));
116
+ });
117
+ }
118
+ );
119
+ req.on('error', (e) => {
120
+ process.stdout.write(JSON.stringify({ ok: false, status: 0, body: e.message }));
121
+ });
122
+ req.write(bodyBuf);
123
+ req.end();
116
124
  });
117
- req.write(bodyBuf);
118
- req.end();
119
125
  `;
120
- const raw = withRetry(() => execFileSync(process.execPath, ['-e', script], { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }));
126
+ const raw = withRetry(() => execFileSync(process.execPath, ['-e', script], { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], input: body }));
121
127
  const result = JSON.parse(raw);
122
128
  if (!result.ok) {
123
129
  const err = new Error('HTTP ' + result.status + ': ' + result.body);