pi-bridge 0.2.9 → 0.3.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.
- package/package.json +1 -1
- package/src/local/child-process-patch.js +43 -12
package/package.json
CHANGED
|
@@ -5,19 +5,18 @@ const path = require('path');
|
|
|
5
5
|
const { isFakePath, toRemotePath } = require('./path-mapper');
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Patch child_process
|
|
8
|
+
* Patch child_process spawn/spawnSync/execSync/execFileSync so that commands
|
|
9
9
|
* whose cwd lands inside fakeRoot are transparently redirected to run on
|
|
10
10
|
* the remote machine via SSH.
|
|
11
11
|
*
|
|
12
|
-
* Pi's bash tool uses spawn/spawnSync exclusively, so this covers all shell
|
|
13
|
-
* command execution (ls, cat, grep, npm run, etc.).
|
|
14
|
-
*
|
|
15
12
|
* @param {string} fakeRoot - Local fake root directory (real path, no symlinks)
|
|
16
13
|
* @param {string} remote - SSH target, e.g. 'user@host'
|
|
17
14
|
*/
|
|
18
15
|
function patchChildProcess(fakeRoot, remote) {
|
|
19
|
-
const origSpawn
|
|
20
|
-
const origSpawnSync
|
|
16
|
+
const origSpawn = cp.spawn.bind(cp);
|
|
17
|
+
const origSpawnSync = cp.spawnSync.bind(cp);
|
|
18
|
+
const origExecSync = cp.execSync.bind(cp);
|
|
19
|
+
const origExecFileSync = cp.execFileSync.bind(cp);
|
|
21
20
|
|
|
22
21
|
/**
|
|
23
22
|
* Resolve the effective cwd from spawn options.
|
|
@@ -44,6 +43,7 @@ function patchChildProcess(fakeRoot, remote) {
|
|
|
44
43
|
* - node / node.exe: pi's internal tooling (session export, compaction, …)
|
|
45
44
|
* spawns Node with large payloads as args; redirecting those over SSH would
|
|
46
45
|
* produce an ENAMETOOLONG error on Windows and is never correct anyway.
|
|
46
|
+
* - pi / pii: need local internet access for the Claude API and auth.
|
|
47
47
|
*/
|
|
48
48
|
function isLocalOnly(file) {
|
|
49
49
|
const name = normalizeCmd(file).toLowerCase();
|
|
@@ -51,15 +51,14 @@ function patchChildProcess(fakeRoot, remote) {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
|
-
* Build
|
|
55
|
-
*
|
|
54
|
+
* Build SSH args for a file + args invocation:
|
|
55
|
+
* cd to remote cwd, then run the command with shell-quoted arguments.
|
|
56
56
|
*/
|
|
57
57
|
function buildSshArgs(file, args, opts) {
|
|
58
58
|
file = normalizeCmd(file);
|
|
59
|
-
const fakeCwd
|
|
60
|
-
const remoteCwd
|
|
59
|
+
const fakeCwd = effectiveCwd(opts);
|
|
60
|
+
const remoteCwd = toRemotePath(fakeCwd, fakeRoot);
|
|
61
61
|
|
|
62
|
-
// Reconstruct the command string with shell-safe quoting
|
|
63
62
|
const argStr = (args || [])
|
|
64
63
|
.map(function(a) { return "'" + String(a).replace(/'/g, "'\\''") + "'"; })
|
|
65
64
|
.join(' ');
|
|
@@ -68,10 +67,19 @@ function patchChildProcess(fakeRoot, remote) {
|
|
|
68
67
|
return ['-o', 'BatchMode=yes', remote, remoteCmd];
|
|
69
68
|
}
|
|
70
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Build SSH args for a raw shell command string (used by execSync).
|
|
72
|
+
*/
|
|
73
|
+
function buildSshArgsForShell(command, opts) {
|
|
74
|
+
const fakeCwd = effectiveCwd(opts);
|
|
75
|
+
const remoteCwd = toRemotePath(fakeCwd, fakeRoot);
|
|
76
|
+
const remoteCmd = 'cd ' + JSON.stringify(remoteCwd) + ' && ' + command;
|
|
77
|
+
return ['-o', 'BatchMode=yes', remote, remoteCmd];
|
|
78
|
+
}
|
|
79
|
+
|
|
71
80
|
// ── spawn ────────────────────────────────────────────────────────────────────
|
|
72
81
|
|
|
73
82
|
cp.spawn = function patchedSpawn(file, args, opts) {
|
|
74
|
-
// Normalise overloaded signature: spawn(file) / spawn(file, opts) / spawn(file, args, opts)
|
|
75
83
|
if (!Array.isArray(args)) { opts = args; args = []; }
|
|
76
84
|
opts = opts || {};
|
|
77
85
|
|
|
@@ -92,6 +100,29 @@ function patchChildProcess(fakeRoot, remote) {
|
|
|
92
100
|
|
|
93
101
|
return origSpawnSync('ssh', buildSshArgs(file, args, opts), Object.assign({}, opts, { cwd: undefined }));
|
|
94
102
|
};
|
|
103
|
+
|
|
104
|
+
// ── execSync ─────────────────────────────────────────────────────────────────
|
|
105
|
+
|
|
106
|
+
cp.execSync = function patchedExecSync(command, opts) {
|
|
107
|
+
opts = opts || {};
|
|
108
|
+
|
|
109
|
+
const cwd = effectiveCwd(opts);
|
|
110
|
+
if (!isFakePath(cwd, fakeRoot)) return origExecSync(command, opts);
|
|
111
|
+
|
|
112
|
+
return origExecFileSync('ssh', buildSshArgsForShell(command, opts), Object.assign({}, opts, { cwd: undefined }));
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// ── execFileSync ─────────────────────────────────────────────────────────────
|
|
116
|
+
|
|
117
|
+
cp.execFileSync = function patchedExecFileSync(file, args, opts) {
|
|
118
|
+
if (!Array.isArray(args)) { opts = args; args = []; }
|
|
119
|
+
opts = opts || {};
|
|
120
|
+
|
|
121
|
+
const cwd = effectiveCwd(opts);
|
|
122
|
+
if (!isFakePath(cwd, fakeRoot) || isLocalOnly(file)) return origExecFileSync(file, args, opts);
|
|
123
|
+
|
|
124
|
+
return origExecFileSync('ssh', buildSshArgs(file, args, opts), Object.assign({}, opts, { cwd: undefined }));
|
|
125
|
+
};
|
|
95
126
|
}
|
|
96
127
|
|
|
97
128
|
module.exports = { patchChildProcess };
|