@zeph-to/cli 2.12.1 → 2.13.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/README.md +5 -2
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +23 -3
- package/dist/tmux-install.d.ts +44 -0
- package/dist/tmux-install.d.ts.map +1 -0
- package/dist/tmux-install.js +65 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -200,8 +200,11 @@ block here.
|
|
|
200
200
|
### Setup
|
|
201
201
|
|
|
202
202
|
1. **Install tmux.** The listener uses `send-keys`; the wrapper spawns
|
|
203
|
-
named sessions. `
|
|
204
|
-
|
|
203
|
+
named sessions. `zeph install` checks for it and, on macOS with Homebrew,
|
|
204
|
+
offers to run `brew install tmux` for you. Elsewhere it prints the line to
|
|
205
|
+
run — `sudo apt install tmux` on Debian/Ubuntu, and so on — because
|
|
206
|
+
installing with `sudo` is not something an installer should do on your
|
|
207
|
+
behalf. tmux has no Windows build, so `zeph cc` needs WSL there.
|
|
205
208
|
|
|
206
209
|
2. **Add `wsUrl` to `~/.zeph/config.json`** (the WebSocket endpoint of
|
|
207
210
|
your Zeph backend — CDK output `WsApiUrl`):
|
package/dist/installer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AA+BzC;;;GAGG;AACH;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,YAAY,MAAM,GAAG,SAAS,EAAE,SAAS,OAAO,KAAG,OACxD,CAAC;AAoBzB;6EAC6E;AAC7E,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,EAAE,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAqBhF,CAAC;AAsCF;mEACmE;AACnE,eAAO,MAAM,cAAc,GAAI,UAAU,MAAM,EAAE,KAAK,MAAM,EAAE,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAQ9F,CAAC;AAmPF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,KAAK,EAAE,EAAE,MAAM,MAAM,KAAG,KAAK,EAKxE,CAAC;AA8EF;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,GAC/B,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EACtC,gBAAgB,OAAO,KACtB,KAAK,GAAG,IAAI,GAAG,KAKjB,CAAC;AAgCF,eAAO,MAAM,aAAa,GAAU,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CA0I1F,CAAC"}
|
package/dist/installer.js
CHANGED
|
@@ -10,6 +10,7 @@ const zeph_hook_js_1 = require("./zeph-hook.js");
|
|
|
10
10
|
const config_js_1 = require("./config.js");
|
|
11
11
|
const login_js_1 = require("./login.js");
|
|
12
12
|
const agents_js_1 = require("./agents.js");
|
|
13
|
+
const tmux_install_js_1 = require("./tmux-install.js");
|
|
13
14
|
const mcp_command_js_1 = require("./mcp-command.js");
|
|
14
15
|
const listener_service_js_1 = require("./listener-service.js");
|
|
15
16
|
const templates_js_1 = require("./templates.js");
|
|
@@ -464,7 +465,7 @@ const applyServiceChoice = async (choice) => {
|
|
|
464
465
|
try {
|
|
465
466
|
const { confirm } = await import('@inquirer/prompts');
|
|
466
467
|
wanted = await confirm({
|
|
467
|
-
message: 'Start the listener at every login
|
|
468
|
+
message: 'Start the listener at every login, so the phone sees this machine after a reboot? (enter to confirm)',
|
|
468
469
|
default: true,
|
|
469
470
|
});
|
|
470
471
|
}
|
|
@@ -551,6 +552,7 @@ const handleInstall = async (args) => {
|
|
|
551
552
|
if (selected.length === 0) {
|
|
552
553
|
console.log(' (no agents selected — only the config file will be saved)');
|
|
553
554
|
}
|
|
555
|
+
console.log(' - Check tmux (`zeph cc` runs agents inside it)');
|
|
554
556
|
if ((0, exports.serviceInstallChoice)(args, nonInteractive) !== 'no') {
|
|
555
557
|
console.log(' - Offer to start the listener at every login');
|
|
556
558
|
}
|
|
@@ -577,10 +579,28 @@ const handleInstall = async (args) => {
|
|
|
577
579
|
if (installer)
|
|
578
580
|
installer();
|
|
579
581
|
}
|
|
580
|
-
// 7.
|
|
582
|
+
// 7. tmux — `zeph cc` is tmux or nothing, so check before claiming success.
|
|
583
|
+
console.log('\n Checking tmux...');
|
|
584
|
+
await (0, tmux_install_js_1.ensureTmux)({
|
|
585
|
+
plan: (0, tmux_install_js_1.planTmuxInstall)({ resolve: agents_js_1.resolveCommand, platform: process.platform }),
|
|
586
|
+
nonInteractive,
|
|
587
|
+
askConfirm: async (message) => {
|
|
588
|
+
try {
|
|
589
|
+
const { confirm } = await import('@inquirer/prompts');
|
|
590
|
+
return await confirm({ message, default: true });
|
|
591
|
+
}
|
|
592
|
+
catch {
|
|
593
|
+
// Ctrl-C or no TTY — an unanswered question is not a yes.
|
|
594
|
+
return false;
|
|
595
|
+
}
|
|
596
|
+
},
|
|
597
|
+
run: (argv) => { (0, child_process_1.execFileSync)(argv[0], argv.slice(1), { stdio: 'inherit' }); },
|
|
598
|
+
report: { ok, fail, note: skipNote },
|
|
599
|
+
});
|
|
600
|
+
// 8. Login-time service — the only thing that makes the phone see this
|
|
581
601
|
// machine after a reboot without a terminal being opened first.
|
|
582
602
|
await applyServiceChoice((0, exports.serviceInstallChoice)(args, nonInteractive));
|
|
583
|
-
//
|
|
603
|
+
// 9. Test connection
|
|
584
604
|
console.log('\n Testing connection...');
|
|
585
605
|
await testConnection(apiKey, baseUrl);
|
|
586
606
|
console.log('\n Done! Restart your agents.\n');
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tmux is not optional for `zeph cc` — every remote-agent subcommand runs the
|
|
3
|
+
* agent inside a named tmux session so the listener (and the phone picker) can
|
|
4
|
+
* reach it. Nothing in the install flow used to mention that, so a machine
|
|
5
|
+
* without tmux looked fully set up until the first `zeph cc` failed with an
|
|
6
|
+
* error from a program the user was never told they needed.
|
|
7
|
+
*/
|
|
8
|
+
/** What this machine can do about a missing tmux. */
|
|
9
|
+
export type TmuxInstallPlan = {
|
|
10
|
+
readonly kind: 'present';
|
|
11
|
+
readonly path: string;
|
|
12
|
+
}
|
|
13
|
+
/** Safe to run unattended — no root, user-writable prefix. */
|
|
14
|
+
| {
|
|
15
|
+
readonly kind: 'command';
|
|
16
|
+
readonly run: readonly string[];
|
|
17
|
+
readonly label: string;
|
|
18
|
+
}
|
|
19
|
+
/** Needs root, or there is no package manager we recognise. Tell, don't do. */
|
|
20
|
+
| {
|
|
21
|
+
readonly kind: 'manual';
|
|
22
|
+
readonly hint: string;
|
|
23
|
+
};
|
|
24
|
+
export declare const planTmuxInstall: (deps: {
|
|
25
|
+
resolve: (cmd: string) => string | null;
|
|
26
|
+
platform: NodeJS.Platform;
|
|
27
|
+
}) => TmuxInstallPlan;
|
|
28
|
+
/**
|
|
29
|
+
* Act on the plan. Everything the outside world touches is injected, because
|
|
30
|
+
* the interesting branch — "offer, then run a package manager" — is otherwise
|
|
31
|
+
* only reachable through an interactive install that no test can drive.
|
|
32
|
+
*/
|
|
33
|
+
export declare const ensureTmux: (deps: {
|
|
34
|
+
plan: TmuxInstallPlan;
|
|
35
|
+
nonInteractive: boolean;
|
|
36
|
+
askConfirm: (message: string) => Promise<boolean>;
|
|
37
|
+
run: (argv: readonly string[]) => void;
|
|
38
|
+
report: {
|
|
39
|
+
ok: (m: string) => void;
|
|
40
|
+
fail: (m: string) => void;
|
|
41
|
+
note: (m: string) => void;
|
|
42
|
+
};
|
|
43
|
+
}) => Promise<void>;
|
|
44
|
+
//# sourceMappingURL=tmux-install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tmux-install.d.ts","sourceRoot":"","sources":["../src/tmux-install.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,qDAAqD;AACrD,MAAM,MAAM,eAAe,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AACrD,8DAA8D;GAC5D;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AACvF,+EAA+E;GAC7E;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAWzD,eAAO,MAAM,eAAe,GAAI,MAAM;IAClC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACxC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC7B,KAAG,eAoBH,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAU,MAAM;IACnC,IAAI,EAAE,eAAe,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,GAAG,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,CAAC;IACvC,MAAM,EAAE;QAAE,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;CAC7F,KAAG,OAAO,CAAC,IAAI,CAsBf,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* tmux is not optional for `zeph cc` — every remote-agent subcommand runs the
|
|
4
|
+
* agent inside a named tmux session so the listener (and the phone picker) can
|
|
5
|
+
* reach it. Nothing in the install flow used to mention that, so a machine
|
|
6
|
+
* without tmux looked fully set up until the first `zeph cc` failed with an
|
|
7
|
+
* error from a program the user was never told they needed.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.ensureTmux = exports.planTmuxInstall = void 0;
|
|
11
|
+
/** Package managers that need root, and the line to hand the user for each. */
|
|
12
|
+
const ROOT_PACKAGE_MANAGERS = [
|
|
13
|
+
{ bin: 'apt-get', hint: 'sudo apt install tmux' },
|
|
14
|
+
{ bin: 'dnf', hint: 'sudo dnf install tmux' },
|
|
15
|
+
{ bin: 'pacman', hint: 'sudo pacman -S tmux' },
|
|
16
|
+
{ bin: 'zypper', hint: 'sudo zypper install tmux' },
|
|
17
|
+
{ bin: 'apk', hint: 'sudo apk add tmux' },
|
|
18
|
+
];
|
|
19
|
+
const planTmuxInstall = (deps) => {
|
|
20
|
+
const path = deps.resolve('tmux');
|
|
21
|
+
if (path)
|
|
22
|
+
return { kind: 'present', path };
|
|
23
|
+
// tmux has no native Windows build. `zeph cc` is POSIX-only by way of tmux,
|
|
24
|
+
// so point at WSL rather than at a package that cannot be installed.
|
|
25
|
+
if (deps.platform === 'win32') {
|
|
26
|
+
return { kind: 'manual', hint: '`zeph cc` needs tmux, which has no Windows build — run it under WSL' };
|
|
27
|
+
}
|
|
28
|
+
if (deps.platform === 'darwin') {
|
|
29
|
+
return deps.resolve('brew')
|
|
30
|
+
? { kind: 'command', run: ['brew', 'install', 'tmux'], label: 'brew install tmux' }
|
|
31
|
+
: { kind: 'manual', hint: 'install Homebrew (brew.sh), then: brew install tmux' };
|
|
32
|
+
}
|
|
33
|
+
const rootManager = ROOT_PACKAGE_MANAGERS.find((pm) => deps.resolve(pm.bin));
|
|
34
|
+
if (rootManager)
|
|
35
|
+
return { kind: 'manual', hint: rootManager.hint };
|
|
36
|
+
return { kind: 'manual', hint: 'install tmux with this system\'s package manager' };
|
|
37
|
+
};
|
|
38
|
+
exports.planTmuxInstall = planTmuxInstall;
|
|
39
|
+
/**
|
|
40
|
+
* Act on the plan. Everything the outside world touches is injected, because
|
|
41
|
+
* the interesting branch — "offer, then run a package manager" — is otherwise
|
|
42
|
+
* only reachable through an interactive install that no test can drive.
|
|
43
|
+
*/
|
|
44
|
+
const ensureTmux = async (deps) => {
|
|
45
|
+
const { plan, report } = deps;
|
|
46
|
+
if (plan.kind === 'present')
|
|
47
|
+
return report.ok(`tmux found (${plan.path})`);
|
|
48
|
+
if (plan.kind === 'manual')
|
|
49
|
+
return report.fail(`tmux not found — \`zeph cc\` needs it. ${plan.hint}`);
|
|
50
|
+
if (deps.nonInteractive) {
|
|
51
|
+
return report.note(`tmux not found — \`zeph cc\` needs it. Run: ${plan.label}`);
|
|
52
|
+
}
|
|
53
|
+
const wanted = await deps.askConfirm(`tmux is missing and \`zeph cc\` needs it — run \`${plan.label}\`? (enter to confirm)`);
|
|
54
|
+
if (!wanted) {
|
|
55
|
+
return report.note(`tmux not installed — \`zeph cc\` will not work until you run: ${plan.label}`);
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
deps.run(plan.run);
|
|
59
|
+
report.ok('tmux installed');
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
report.fail(`\`${plan.label}\` failed — run it by hand`);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
exports.ensureTmux = ensureTmux;
|