@amdahl/cli 0.3.2 → 0.3.3
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 +11 -4
- package/dist/amdahl.js +66 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -68,6 +68,7 @@ Set up in:
|
|
|
68
68
|
[ ] Codex
|
|
69
69
|
(Use the arrow keys, Space to tick or untick, then Enter)
|
|
70
70
|
Opening your browser…
|
|
71
|
+
Browser didn't open? Press Enter for the link.
|
|
71
72
|
✓ Signed in · Acme
|
|
72
73
|
✓ Added to Claude Code
|
|
73
74
|
Try it: in Claude Code, run /mcp once to connect, then say "make this email sound less like AI"
|
|
@@ -76,10 +77,16 @@ Try it: in Claude Code, run /mcp once to connect, then say "make this email soun
|
|
|
76
77
|
It finds Claude Code, Cursor and Codex by their command on your PATH
|
|
77
78
|
(`claude`, `cursor`, `codex`) or their folder in your home folder (`.claude`,
|
|
78
79
|
`.cursor`, `.codex`), and ticks the ones it finds. Enter accepts. If you are
|
|
79
|
-
not signed in, it signs you in through the browser first.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
not signed in, it signs you in through the browser first. Under "Opening
|
|
81
|
+
your browser…" it prints one short line. In a terminal that shows links
|
|
82
|
+
(iTerm2, VS Code, Warp, Terminal, WezTerm, Ghostty, Windows Terminal, VTE 0.50
|
|
83
|
+
or later) it reads "Browser didn't open? Open the sign-in page" and the last
|
|
84
|
+
words are a link; elsewhere it says to press Enter for the link.
|
|
85
|
+
`FORCE_HYPERLINK=1` or `0` overrides the guess, and `NO_COLOR` turns the link
|
|
86
|
+
off. Either way, Enter prints the full sign-in link once. If the browser
|
|
87
|
+
could not be opened, or with `--no-browser`, the full link prints at once.
|
|
88
|
+
It waits up to 15 minutes, so someone new can create their workspace on the
|
|
89
|
+
way and land back in the same setup. If the server
|
|
83
90
|
rejects a key set in
|
|
84
91
|
`AMDAHL_KEY` (or `AMDAHL_API_KEY`, `AMDAHL_ACCESS_TOKEN`, `--api-key`), it says
|
|
85
92
|
so and skips the browser sign-in, since that key would still win. Then it
|
package/dist/amdahl.js
CHANGED
|
@@ -7478,6 +7478,42 @@ function multiSelectMenu(input, output, question, choices, options = {}) {
|
|
|
7478
7478
|
return "redraw";
|
|
7479
7479
|
});
|
|
7480
7480
|
}
|
|
7481
|
+
function listenForEnter(input, onEnter, onCancel) {
|
|
7482
|
+
const wasRaw = input.isRaw === true;
|
|
7483
|
+
let done = false;
|
|
7484
|
+
const stop = () => {
|
|
7485
|
+
if (done) return;
|
|
7486
|
+
done = true;
|
|
7487
|
+
input.removeListener("keypress", onKeypress);
|
|
7488
|
+
input.removeListener("error", stop);
|
|
7489
|
+
process.removeListener("SIGINT", cancel);
|
|
7490
|
+
try {
|
|
7491
|
+
input.setRawMode?.(wasRaw);
|
|
7492
|
+
} catch {
|
|
7493
|
+
}
|
|
7494
|
+
input.pause();
|
|
7495
|
+
};
|
|
7496
|
+
const cancel = () => {
|
|
7497
|
+
if (done) return;
|
|
7498
|
+
stop();
|
|
7499
|
+
onCancel();
|
|
7500
|
+
};
|
|
7501
|
+
const onKeypress = (_text, key) => {
|
|
7502
|
+
if (key?.ctrl && key.name === "c") cancel();
|
|
7503
|
+
else if (key?.name === "return" || key?.name === "enter") onEnter();
|
|
7504
|
+
};
|
|
7505
|
+
try {
|
|
7506
|
+
emitKeypressEvents(input);
|
|
7507
|
+
input.setRawMode?.(true);
|
|
7508
|
+
input.on("keypress", onKeypress);
|
|
7509
|
+
input.on("error", stop);
|
|
7510
|
+
process.on("SIGINT", cancel);
|
|
7511
|
+
input.resume();
|
|
7512
|
+
} catch {
|
|
7513
|
+
stop();
|
|
7514
|
+
}
|
|
7515
|
+
return stop;
|
|
7516
|
+
}
|
|
7481
7517
|
|
|
7482
7518
|
// src/io.ts
|
|
7483
7519
|
var PromptCancelled = class extends Error {
|
|
@@ -7563,6 +7599,7 @@ function realIo() {
|
|
|
7563
7599
|
...options,
|
|
7564
7600
|
trueColor: /^(truecolor|24bit)$/i.test(process.env.COLORTERM ?? "")
|
|
7565
7601
|
}),
|
|
7602
|
+
listenForEnter: (onEnter, onCancel) => listenForEnter(process.stdin, onEnter, onCancel),
|
|
7566
7603
|
uninterruptible,
|
|
7567
7604
|
run: runProcess,
|
|
7568
7605
|
openUrl: async (url) => {
|
|
@@ -7576,7 +7613,6 @@ function realIo() {
|
|
|
7576
7613
|
now: () => Date.now(),
|
|
7577
7614
|
sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
|
|
7578
7615
|
loginTimeoutMs: 9e5,
|
|
7579
|
-
browserGraceMs: 6e4,
|
|
7580
7616
|
fetchTimeoutMs: 15e3
|
|
7581
7617
|
};
|
|
7582
7618
|
}
|
|
@@ -8545,6 +8581,18 @@ var CONTROL_RE = /[\u0000-\u001f\u007f-\u009f]/g;
|
|
|
8545
8581
|
function printable(text2) {
|
|
8546
8582
|
return text2.replace(CONTROL_RE, "");
|
|
8547
8583
|
}
|
|
8584
|
+
var HYPERLINK_TERMINALS = /* @__PURE__ */ new Set(["iTerm.app", "vscode", "WarpTerminal", "Apple_Terminal", "WezTerm", "ghostty"]);
|
|
8585
|
+
function supportsHyperlinks(env, color) {
|
|
8586
|
+
if (env.FORCE_HYPERLINK === "0") return false;
|
|
8587
|
+
if (env.FORCE_HYPERLINK === "1") return true;
|
|
8588
|
+
if (!color) return false;
|
|
8589
|
+
if (HYPERLINK_TERMINALS.has(env.TERM_PROGRAM ?? "")) return true;
|
|
8590
|
+
if (Number(env.VTE_VERSION) >= 5e3) return true;
|
|
8591
|
+
return Boolean(env.WT_SESSION);
|
|
8592
|
+
}
|
|
8593
|
+
function hyperlink(text2, url) {
|
|
8594
|
+
return `\x1B]8;;${printable(url)}\x1B\\${text2}\x1B]8;;\x1B\\`;
|
|
8595
|
+
}
|
|
8548
8596
|
function createOutput(io, json, noColor) {
|
|
8549
8597
|
const color = !noColor && !io.env.NO_COLOR && io.env.TERM !== "dumb" && io.stderrIsTTY && !json;
|
|
8550
8598
|
return {
|
|
@@ -8593,7 +8641,8 @@ async function browserSignIn(ctx) {
|
|
|
8593
8641
|
const endpoints = await discover(ctx.apiUrl);
|
|
8594
8642
|
const pkce = createPkce();
|
|
8595
8643
|
const consoleUrl = consoleUrlFor(io, ctx.apiUrl);
|
|
8596
|
-
let
|
|
8644
|
+
let stopKeys = () => {
|
|
8645
|
+
};
|
|
8597
8646
|
let linkShown = false;
|
|
8598
8647
|
const loopback = await startLoopback(io, {
|
|
8599
8648
|
port,
|
|
@@ -8602,7 +8651,6 @@ async function browserSignIn(ctx) {
|
|
|
8602
8651
|
timeoutMs: io.loginTimeoutMs,
|
|
8603
8652
|
// The page carries the way on; the authorize link would only sign in as the same address again.
|
|
8604
8653
|
onSignInAgain: (reason, retry) => {
|
|
8605
|
-
clearTimeout(timer);
|
|
8606
8654
|
linkShown = true;
|
|
8607
8655
|
out.info(signInAgainLine(reason, retry));
|
|
8608
8656
|
}
|
|
@@ -8619,18 +8667,27 @@ async function browserSignIn(ctx) {
|
|
|
8619
8667
|
${url}
|
|
8620
8668
|
`);
|
|
8621
8669
|
};
|
|
8670
|
+
let cancelled;
|
|
8622
8671
|
if (flags["no-browser"]) {
|
|
8623
8672
|
showLink("Open this URL in a browser to sign in:");
|
|
8624
8673
|
} else {
|
|
8625
8674
|
out.info("Opening your browser\u2026");
|
|
8675
|
+
if (!ctx.nonInteractive && io.stderrIsTTY) {
|
|
8676
|
+
const fallback = supportsHyperlinks(io.env, out.color) ? hyperlink("Open the sign-in page", url) : "Press Enter for the link.";
|
|
8677
|
+
out.info(`Browser didn't open? ${fallback}`);
|
|
8678
|
+
cancelled = new Promise((_, reject) => {
|
|
8679
|
+
stopKeys = io.listenForEnter(
|
|
8680
|
+
() => showLink("Open this link to sign in:"),
|
|
8681
|
+
() => reject(new PromptCancelled())
|
|
8682
|
+
);
|
|
8683
|
+
});
|
|
8684
|
+
}
|
|
8626
8685
|
void io.openUrl(url).then((opened) => {
|
|
8627
8686
|
if (!opened) showLink("Your browser did not open. Open this link to sign in:");
|
|
8628
8687
|
});
|
|
8629
|
-
timer = setTimeout(() => showLink("Finish in your browser, or open this link:"), io.browserGraceMs);
|
|
8630
|
-
timer.unref?.();
|
|
8631
8688
|
}
|
|
8632
|
-
const callback = await loopback.result;
|
|
8633
|
-
|
|
8689
|
+
const callback = await (cancelled ? Promise.race([loopback.result, cancelled]) : loopback.result);
|
|
8690
|
+
stopKeys();
|
|
8634
8691
|
linkShown = true;
|
|
8635
8692
|
if (callback.kind === "no_business") {
|
|
8636
8693
|
throw new CliError("no_business", noBusinessMessage(consoleUrl, callback.mayCreate, callback.reason), EXIT.noWorkspace);
|
|
@@ -8664,7 +8721,7 @@ async function browserSignIn(ctx) {
|
|
|
8664
8721
|
ctx.saveConfig();
|
|
8665
8722
|
return { profile: name, me, workspace: ws };
|
|
8666
8723
|
} finally {
|
|
8667
|
-
|
|
8724
|
+
stopKeys();
|
|
8668
8725
|
loopback.close();
|
|
8669
8726
|
}
|
|
8670
8727
|
}
|
|
@@ -10363,7 +10420,7 @@ async function workspaceUse(ctx, args) {
|
|
|
10363
10420
|
}
|
|
10364
10421
|
|
|
10365
10422
|
// src/version.ts
|
|
10366
|
-
var VERSION = "0.3.
|
|
10423
|
+
var VERSION = "0.3.3";
|
|
10367
10424
|
|
|
10368
10425
|
// src/main.ts
|
|
10369
10426
|
var COMMANDS = {
|
package/package.json
CHANGED