@tiens.nguyen/gu-cli 1.0.799 → 1.0.801
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/cli-token.mjs +4 -1
- package/device-login.mjs +1 -1
- package/gu-repl.mjs +34 -2
- package/package.json +1 -1
package/cli-token.mjs
CHANGED
|
@@ -299,7 +299,7 @@ export async function promptForToken({
|
|
|
299
299
|
? [`The gu service${trialHost(hostedBase)} sent an answer without a token — Enter on an empty line tries again.`]
|
|
300
300
|
: []),
|
|
301
301
|
getOne,
|
|
302
|
-
required ? "Paste it here, then Enter." : "Paste it here — or Enter to skip for now.",
|
|
302
|
+
required ? "Paste it here, then Enter. /exit or Ctrl+C quits gu." : "Paste it here — or Enter to skip for now.",
|
|
303
303
|
];
|
|
304
304
|
if (why) {
|
|
305
305
|
const pricingUrl = `${String(site).replace(/^https?:\/\//, "")}/pricing`;
|
|
@@ -323,6 +323,9 @@ export async function promptForToken({
|
|
|
323
323
|
const ask1 = () => ask("Input token: ", { prefill: shown, hint, atomic: true, noCancel: required });
|
|
324
324
|
for (let round = 0; required ? round < maxRounds : round < 2; round++) {
|
|
325
325
|
const typed = String((await ask1()) ?? "").trim();
|
|
326
|
+
// A way OUT of a required question (task #17): "/exit" is not a token, and treating it as one
|
|
327
|
+
// ("That token was not saved…" and the same question again) left no way to leave gu at all.
|
|
328
|
+
if (/^\/(exit|quit)$/i.test(typed)) return { ok: false, why: "quit" };
|
|
326
329
|
if (!typed) {
|
|
327
330
|
if (!required) return { ok: false, why: "skipped" };
|
|
328
331
|
if (!trialOk) await offer(); // no default: maybe the service is back, or the trial exists now
|
package/device-login.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { homedir, platform } from "node:os";
|
|
|
8
8
|
import { join } from "node:path";
|
|
9
9
|
import dotenv from "dotenv";
|
|
10
10
|
|
|
11
|
-
export const DEFAULT_API_BASE = "https://chat-api-v2.
|
|
11
|
+
export const DEFAULT_API_BASE = "https://chat-api-v2.gucli.com";
|
|
12
12
|
const ENV_FILE = join(homedir(), ".gonext", "worker.env");
|
|
13
13
|
const POLL_INTERVAL_MS = 2500;
|
|
14
14
|
const POLL_TIMEOUT_MS = 10 * 60_000; // matches the server's pairing TTL
|
package/gu-repl.mjs
CHANGED
|
@@ -864,7 +864,7 @@ if (!workerKey || !apiBase) {
|
|
|
864
864
|
console.error(red(`gu: setup failed: ${e instanceof Error ? e.message : e}`));
|
|
865
865
|
if (e && e.code === "PAIRING_UNSUPPORTED") {
|
|
866
866
|
console.error(
|
|
867
|
-
"Configure manually: gu-cli set <workerKey> --api-base https://chat-api-v2.
|
|
867
|
+
"Configure manually: gu-cli set <workerKey> --api-base https://chat-api-v2.gucli.com"
|
|
868
868
|
);
|
|
869
869
|
}
|
|
870
870
|
if (e && (e.code === "KEY_REJECTED" || e.code === "KEY_UNCHECKED")) {
|
|
@@ -879,7 +879,7 @@ if (!workerKey || !apiBase) {
|
|
|
879
879
|
console.error(
|
|
880
880
|
red("gu: no worker key / API base found.") +
|
|
881
881
|
`\nRun ${accent("gu-cli login")} to sign in, or configure manually:` +
|
|
882
|
-
"\n gu-cli set <workerKey> --api-base https://chat-api-v2.
|
|
882
|
+
"\n gu-cli set <workerKey> --api-base https://chat-api-v2.gucli.com"
|
|
883
883
|
);
|
|
884
884
|
process.exit(1);
|
|
885
885
|
}
|
|
@@ -10839,6 +10839,29 @@ async function ensureTokenForTurn() {
|
|
|
10839
10839
|
*/
|
|
10840
10840
|
async function askForCliToken(ct, dir, { why = "" } = {}) {
|
|
10841
10841
|
console.log("");
|
|
10842
|
+
tokenPromptActive = true; // Ctrl+C now quits gu (see onInterrupt) — task #17
|
|
10843
|
+
try {
|
|
10844
|
+
return await askForCliTokenInner(ct, dir, why);
|
|
10845
|
+
} finally {
|
|
10846
|
+
tokenPromptActive = false;
|
|
10847
|
+
}
|
|
10848
|
+
}
|
|
10849
|
+
|
|
10850
|
+
/**
|
|
10851
|
+
* True while the required token question is on screen. The main loop — the only place "/exit" was
|
|
10852
|
+
* handled — has not started yet, so Ctrl+C and "/exit" must quit from here, or gu cannot be left.
|
|
10853
|
+
*/
|
|
10854
|
+
let tokenPromptActive = false;
|
|
10855
|
+
|
|
10856
|
+
/** Leave gu from the token question, the same way "/exit" leaves the main loop. */
|
|
10857
|
+
function quitFromTokenPrompt() {
|
|
10858
|
+
tokenPromptActive = false;
|
|
10859
|
+
releaseScreenAtExit();
|
|
10860
|
+
rl.close();
|
|
10861
|
+
process.exit(0);
|
|
10862
|
+
}
|
|
10863
|
+
|
|
10864
|
+
async function askForCliTokenInner(ct, dir, why) {
|
|
10842
10865
|
const hostedBase = await tokenHostedBase();
|
|
10843
10866
|
const pk = ct.publicKey();
|
|
10844
10867
|
const site = ct.siteUrl();
|
|
@@ -10866,6 +10889,7 @@ async function askForCliToken(ct, dir, { why = "" } = {}) {
|
|
|
10866
10889
|
},
|
|
10867
10890
|
});
|
|
10868
10891
|
console.log("");
|
|
10892
|
+
if (r.why === "quit") quitFromTokenPrompt();
|
|
10869
10893
|
if (r.ok) {
|
|
10870
10894
|
licenceBlock = null; // the row only lets an entitled token through
|
|
10871
10895
|
licenceDecided = true;
|
|
@@ -13271,6 +13295,14 @@ async function main() {
|
|
|
13271
13295
|
// Ctrl+C while the approval picker is up = decline it (and fall through to also
|
|
13272
13296
|
// cancel the turn) — otherwise the poll loop stays blocked awaiting a choice.
|
|
13273
13297
|
if (approvalActive) finishApproval(false);
|
|
13298
|
+
// Ctrl+C at the required token question (task #17): there is nothing to cancel and no ">>" to
|
|
13299
|
+
// go back to, and re-asking ("(/exit to quit)") trapped the user — so it quits gu.
|
|
13300
|
+
if (tokenPromptActive && !following) {
|
|
13301
|
+
eraseFooter();
|
|
13302
|
+
process.stdout.write("\n" + GUTTER + red("^C ") + "\n");
|
|
13303
|
+
quitFromTokenPrompt();
|
|
13304
|
+
return;
|
|
13305
|
+
}
|
|
13274
13306
|
if (following) {
|
|
13275
13307
|
// Cancel AND clear. One press does both: the turn stops, and nothing the user typed
|
|
13276
13308
|
// while waiting survives to appear in the box or fire as the next turn.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiens.nguyen/gu-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.801",
|
|
4
4
|
"description": "Gu CLI — the gu terminal plus the local worker that runs agent / OCR / PDF / embedding jobs on your Mac (Ollama / MLX / OpenAI-compatible).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|