esque-bridge 0.4.0 → 0.6.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/index.js +65 -5
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* through the configured agent adapter, returning stdout
|
|
14
14
|
*
|
|
15
15
|
* npx esque-bridge # default: claude
|
|
16
|
+
* npx esque-bridge --agent codex # OpenAI Codex (ChatGPT) on this repo
|
|
16
17
|
* npx esque-bridge --agent aider # Aider against the current repo
|
|
17
18
|
* npx esque-bridge --agent custom --cmd 'mycli --prompt {prompt}'
|
|
18
19
|
*/
|
|
@@ -26,6 +27,10 @@ const fs = require('fs');
|
|
|
26
27
|
const path = require('path');
|
|
27
28
|
const os = require('os');
|
|
28
29
|
|
|
30
|
+
// Windows has no POSIX process groups or `.cmd`-aware spawn, so several
|
|
31
|
+
// process-management paths below branch on this.
|
|
32
|
+
const isWindows = process.platform === 'win32';
|
|
33
|
+
|
|
29
34
|
// --- Config ---------------------------------------------------------------
|
|
30
35
|
|
|
31
36
|
const argv = parseArgs(process.argv.slice(2));
|
|
@@ -36,13 +41,15 @@ if (argv.help || argv.h) {
|
|
|
36
41
|
Esque Bridge — pair your phone with a local coding-agent CLI.
|
|
37
42
|
|
|
38
43
|
USAGE
|
|
39
|
-
esque-bridge [--agent claude|aider|custom] [--port 3030] [--workdir .]
|
|
44
|
+
esque-bridge [--agent claude|codex|aider|custom] [--port 3030] [--workdir .]
|
|
40
45
|
[--cmd 'tool --prompt {prompt}'] [--bin <binary>]
|
|
41
46
|
[--timeout 300000]
|
|
42
47
|
|
|
43
48
|
AGENT ADAPTERS
|
|
44
49
|
claude (default) — uses Claude Code CLI (\`claude --print --output-format json\`).
|
|
45
50
|
Persists session ids so each conversation continues via --resume.
|
|
51
|
+
codex — uses OpenAI Codex CLI (\`codex exec\`, headless, auto-approve).
|
|
52
|
+
Drive ChatGPT's coding agent with your ChatGPT plan or API key.
|
|
46
53
|
aider — uses Aider CLI (\`aider --message ... --yes-always --no-stream\`).
|
|
47
54
|
Conversation continuity is handled by aider's own .aider.chat.history.md.
|
|
48
55
|
custom — runs an arbitrary command. Pass --cmd 'tool --prompt {prompt}'
|
|
@@ -59,6 +66,7 @@ OPTIONS
|
|
|
59
66
|
|
|
60
67
|
PREREQS
|
|
61
68
|
Claude: npm install -g @anthropic-ai/claude-code && claude /login
|
|
69
|
+
Codex: npm install -g @openai/codex && codex login
|
|
62
70
|
Aider: python -m pip install aider-chat
|
|
63
71
|
|
|
64
72
|
OUTPUT
|
|
@@ -201,6 +209,37 @@ const ADAPTERS = {
|
|
|
201
209
|
},
|
|
202
210
|
},
|
|
203
211
|
|
|
212
|
+
codex: {
|
|
213
|
+
label: 'Codex',
|
|
214
|
+
defaultBin: 'codex',
|
|
215
|
+
install:
|
|
216
|
+
'npm install -g @openai/codex, then `codex login` (ChatGPT plan or API key).',
|
|
217
|
+
// `exec` is Codex's non-interactive mode. The bypass flag is Codex's
|
|
218
|
+
// analogue of Claude's --dangerously-skip-permissions: in headless mode
|
|
219
|
+
// there's no human to approve file writes / shell commands (incl. the
|
|
220
|
+
// network installs a fresh scaffold needs), so without it the agent
|
|
221
|
+
// looks busy but can't touch the disk. Access is already gated by the
|
|
222
|
+
// pairing secret + the startup workdir confirmation. --skip-git-repo-check
|
|
223
|
+
// lets it run in a brand-new (not-yet-git) project dir for `fresh` builds.
|
|
224
|
+
buildArgs(_prompt, _prevSessionId) {
|
|
225
|
+
return [
|
|
226
|
+
'exec',
|
|
227
|
+
'--dangerously-bypass-approvals-and-sandbox',
|
|
228
|
+
'--skip-git-repo-check',
|
|
229
|
+
];
|
|
230
|
+
},
|
|
231
|
+
parseOutput(stdout) {
|
|
232
|
+
// `codex exec` streams its run to stdout and logs to stderr; the trimmed
|
|
233
|
+
// stdout is the agent's reply. (Codex has no stable resume-by-id we rely
|
|
234
|
+
// on here, so each turn is self-contained — Esque re-sends repo context.)
|
|
235
|
+
return {
|
|
236
|
+
text: stdout.trim() || '(codex returned no output)',
|
|
237
|
+
cliSessionId: null,
|
|
238
|
+
isError: false,
|
|
239
|
+
};
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
|
|
204
243
|
aider: {
|
|
205
244
|
label: 'Aider',
|
|
206
245
|
defaultBin: 'aider',
|
|
@@ -296,14 +335,19 @@ function runAgent(prompt, esqueSessionId) {
|
|
|
296
335
|
usesStdin = !argv.some((a) => a.includes(prompt));
|
|
297
336
|
}
|
|
298
337
|
|
|
299
|
-
//
|
|
300
|
-
// agent
|
|
301
|
-
//
|
|
338
|
+
// POSIX: detach into its own process group so we can kill the WHOLE tree
|
|
339
|
+
// (the agent spawns subprocesses) on timeout instead of orphaning zombies.
|
|
340
|
+
// Windows: no detach (it would pop a console window) — we kill the tree
|
|
341
|
+
// via `taskkill /T` instead; and `shell: true` so spawn can resolve the
|
|
342
|
+
// `.cmd` shims npm installs global bins as (claude.cmd / codex.cmd). Our
|
|
343
|
+
// built-in adapters pass fixed flag args (the prompt rides via stdin), so
|
|
344
|
+
// there's no shell-injection surface here.
|
|
302
345
|
const child = spawn(bin, argv, {
|
|
303
346
|
cwd: WORKDIR,
|
|
304
347
|
env: process.env,
|
|
305
348
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
306
|
-
detached:
|
|
349
|
+
detached: !isWindows,
|
|
350
|
+
shell: isWindows,
|
|
307
351
|
});
|
|
308
352
|
|
|
309
353
|
const MAX_BUF = 16 * 1024 * 1024; // hard cap so a runaway agent can't OOM the bridge
|
|
@@ -321,6 +365,22 @@ function runAgent(prompt, esqueSessionId) {
|
|
|
321
365
|
const rejectOnce = settle(reject);
|
|
322
366
|
|
|
323
367
|
const killTree = (signal) => {
|
|
368
|
+
if (isWindows) {
|
|
369
|
+
// No process groups on Windows; force-kill the whole tree by PID.
|
|
370
|
+
// Signals don't map, so SIGTERM/SIGKILL both become a /F force-kill.
|
|
371
|
+
try {
|
|
372
|
+
spawn('taskkill', ['/pid', String(child.pid), '/T', '/F'], {
|
|
373
|
+
stdio: 'ignore',
|
|
374
|
+
});
|
|
375
|
+
} catch {
|
|
376
|
+
try {
|
|
377
|
+
child.kill();
|
|
378
|
+
} catch {
|
|
379
|
+
/* already gone */
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
324
384
|
try {
|
|
325
385
|
process.kill(-child.pid, signal);
|
|
326
386
|
} catch {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "esque-bridge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Desktop-side receiver for the Esque Agent mobile app. Pairs your phone with a local coding-agent CLI (Claude Code, Aider, or any custom command) via a tunnel + QR code, so prompts run through your subscription instead of per-token API billing.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"esque-bridge": "index.js"
|