@great-arrow/cli 0.1.43 → 0.1.45
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/dist/index.js +63 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9399,7 +9399,7 @@ function isNodeError(value) {
|
|
|
9399
9399
|
|
|
9400
9400
|
// src/lib/version.ts
|
|
9401
9401
|
var CLI_PACKAGE_NAME = "@great-arrow/cli";
|
|
9402
|
-
var CLI_VERSION = "0.1.
|
|
9402
|
+
var CLI_VERSION = "0.1.45";
|
|
9403
9403
|
var GAD_INSTALL_VERSION = "2026.08.08";
|
|
9404
9404
|
var GAD_INSTALL_MIN_VERSION = "2026.06.22";
|
|
9405
9405
|
var GAD_INSTALL_HEADER = "X-GAD-Install-Version";
|
|
@@ -9461,10 +9461,17 @@ async function setToken(token) {
|
|
|
9461
9461
|
if (entry) {
|
|
9462
9462
|
try {
|
|
9463
9463
|
await entry.setPassword(token);
|
|
9464
|
+
await removeFileFallback();
|
|
9464
9465
|
return true;
|
|
9465
9466
|
} catch (err) {
|
|
9466
9467
|
debugSwallow("keychain.setToken", err);
|
|
9467
9468
|
}
|
|
9469
|
+
try {
|
|
9470
|
+
await entry.deletePassword();
|
|
9471
|
+
} catch (err) {
|
|
9472
|
+
debugSwallow("keychain.setToken(delete stale)", err);
|
|
9473
|
+
return false;
|
|
9474
|
+
}
|
|
9468
9475
|
}
|
|
9469
9476
|
try {
|
|
9470
9477
|
const path10 = credentialFilePath();
|
|
@@ -9484,11 +9491,14 @@ async function deleteToken() {
|
|
|
9484
9491
|
debugSwallow("keychain.deleteToken", err);
|
|
9485
9492
|
}
|
|
9486
9493
|
}
|
|
9494
|
+
await removeFileFallback();
|
|
9495
|
+
}
|
|
9496
|
+
async function removeFileFallback() {
|
|
9487
9497
|
try {
|
|
9488
9498
|
await unlink(credentialFilePath());
|
|
9489
9499
|
} catch (err) {
|
|
9490
9500
|
if (err?.code !== "ENOENT") {
|
|
9491
|
-
debugSwallow("keychain.
|
|
9501
|
+
debugSwallow("keychain.removeFileFallback", err);
|
|
9492
9502
|
}
|
|
9493
9503
|
}
|
|
9494
9504
|
}
|
|
@@ -10191,8 +10201,25 @@ function createFormatter(options) {
|
|
|
10191
10201
|
return new Formatter(options);
|
|
10192
10202
|
}
|
|
10193
10203
|
|
|
10194
|
-
// src/
|
|
10204
|
+
// src/lib/api-url.ts
|
|
10195
10205
|
var DEFAULT_API_URL = "https://www.greatarrow.ai";
|
|
10206
|
+
function isLegacyApiUrl(value) {
|
|
10207
|
+
try {
|
|
10208
|
+
const hostname2 = new URL(value).hostname.toLowerCase();
|
|
10209
|
+
return hostname2 === "www.greatarrowdigital.com" || hostname2 === "greatarrowdigital.com";
|
|
10210
|
+
} catch {
|
|
10211
|
+
return false;
|
|
10212
|
+
}
|
|
10213
|
+
}
|
|
10214
|
+
function warnLegacyApiUrl(apiUrl) {
|
|
10215
|
+
if (!isLegacyApiUrl(apiUrl)) return;
|
|
10216
|
+
process.stderr.write(
|
|
10217
|
+
`Warning: using legacy API host ${apiUrl}; existing configurations remain supported. New installs and logins use ${DEFAULT_API_URL}.
|
|
10218
|
+
`
|
|
10219
|
+
);
|
|
10220
|
+
}
|
|
10221
|
+
|
|
10222
|
+
// src/commands/login.ts
|
|
10196
10223
|
function maskToken(token) {
|
|
10197
10224
|
if (token.length <= 8) return "********...";
|
|
10198
10225
|
return token.slice(0, 8) + "...";
|
|
@@ -10220,7 +10247,7 @@ var loginCommand = new Command("login").description("Authenticate the CLI with y
|
|
|
10220
10247
|
noColor: false
|
|
10221
10248
|
});
|
|
10222
10249
|
const config = await loadConfig();
|
|
10223
|
-
const apiUrl =
|
|
10250
|
+
const apiUrl = DEFAULT_API_URL;
|
|
10224
10251
|
if (options.token) {
|
|
10225
10252
|
const stored = await savePatToken(options.token);
|
|
10226
10253
|
if (!stored) {
|
|
@@ -10259,6 +10286,7 @@ var loginCommand = new Command("login").description("Authenticate the CLI with y
|
|
|
10259
10286
|
}
|
|
10260
10287
|
config.cli_client_id = result.clientId;
|
|
10261
10288
|
config.cli_redirect_uri = result.redirectUri;
|
|
10289
|
+
config.api_url = DEFAULT_API_URL;
|
|
10262
10290
|
await saveConfig(config);
|
|
10263
10291
|
fmt.success(
|
|
10264
10292
|
"Signed in. Your session will refresh automatically \u2014 no need to log in again."
|
|
@@ -10309,7 +10337,6 @@ var logoutCommand = new Command("logout").description("Remove stored authenticat
|
|
|
10309
10337
|
import { mkdir as mkdir3, open, rm, stat } from "node:fs/promises";
|
|
10310
10338
|
import { homedir as homedir3 } from "node:os";
|
|
10311
10339
|
import { join as join3 } from "node:path";
|
|
10312
|
-
var DEFAULT_API_URL2 = "https://www.greatarrow.ai";
|
|
10313
10340
|
var REFRESH_SKEW_MS = 12e4;
|
|
10314
10341
|
var inflightRefresh = null;
|
|
10315
10342
|
var REFRESH_LOCK_STALE_MS = 15e3;
|
|
@@ -10370,7 +10397,8 @@ async function rotatedByAnotherProcess(ours) {
|
|
|
10370
10397
|
}
|
|
10371
10398
|
async function resolveAuth() {
|
|
10372
10399
|
const config = await loadConfig();
|
|
10373
|
-
const configApiUrl = config.api_url ||
|
|
10400
|
+
const configApiUrl = config.api_url || DEFAULT_API_URL;
|
|
10401
|
+
warnLegacyApiUrl(configApiUrl);
|
|
10374
10402
|
const activeWorkspace = config.default_workspace || void 0;
|
|
10375
10403
|
const withWorkspace = (base) => activeWorkspace ? { ...base, activeWorkspace } : base;
|
|
10376
10404
|
const envToken = process.env.GAD_TOKEN;
|
|
@@ -10384,6 +10412,7 @@ async function resolveAuth() {
|
|
|
10384
10412
|
const stored = await loadStoredCredential();
|
|
10385
10413
|
if (stored?.kind === "oauth") {
|
|
10386
10414
|
const fresh = await ensureFreshAccessToken(stored.credential);
|
|
10415
|
+
warnLegacyApiUrl(fresh.apiUrl);
|
|
10387
10416
|
return withWorkspace({
|
|
10388
10417
|
token: fresh.accessToken,
|
|
10389
10418
|
apiUrl: fresh.apiUrl,
|
|
@@ -10888,6 +10917,10 @@ function globalOutputOpts(cmd) {
|
|
|
10888
10917
|
}
|
|
10889
10918
|
|
|
10890
10919
|
// src/commands/whoami.ts
|
|
10920
|
+
function firstThingsToTry(data) {
|
|
10921
|
+
const o = data.onboarding;
|
|
10922
|
+
return o?.state === "empty" && Array.isArray(o.firstThingsToTry) ? o.firstThingsToTry : [];
|
|
10923
|
+
}
|
|
10891
10924
|
function maskToken2(token) {
|
|
10892
10925
|
if (token.length <= 8) {
|
|
10893
10926
|
return token + "...";
|
|
@@ -10939,6 +10972,8 @@ function whoamiCommand() {
|
|
|
10939
10972
|
if (auth.tokenType === "oauth" && auth.expiresAt) {
|
|
10940
10973
|
data.expires = new Date(auth.expiresAt).toISOString();
|
|
10941
10974
|
}
|
|
10975
|
+
const tryThese = firstThingsToTry(introspect);
|
|
10976
|
+
if (tryThese.length > 0) data.firstThingsToTry = tryThese;
|
|
10942
10977
|
const fields = [
|
|
10943
10978
|
{ key: "email", header: "Email" },
|
|
10944
10979
|
{ key: "workspace", header: "Workspace" },
|
|
@@ -10947,6 +10982,12 @@ function whoamiCommand() {
|
|
|
10947
10982
|
{ key: "expires", header: "Access expires" }
|
|
10948
10983
|
];
|
|
10949
10984
|
fmt.detail(data, fields);
|
|
10985
|
+
if (tryThese.length > 0 && !g.json) {
|
|
10986
|
+
fmt.info(
|
|
10987
|
+
`Try saying to your AI:
|
|
10988
|
+
${tryThese.map((t) => ` \u2022 ${t}`).join("\n")}`
|
|
10989
|
+
);
|
|
10990
|
+
}
|
|
10950
10991
|
});
|
|
10951
10992
|
return cmd;
|
|
10952
10993
|
}
|
|
@@ -15122,7 +15163,7 @@ import { createInterface as createInterface2 } from "node:readline";
|
|
|
15122
15163
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
15123
15164
|
import { randomUUID } from "node:crypto";
|
|
15124
15165
|
var BRIDGE_CLIENT_ID = "gad-cli";
|
|
15125
|
-
var
|
|
15166
|
+
var DEFAULT_API_URL2 = "https://www.greatarrow.ai";
|
|
15126
15167
|
var DEFAULT_TIMEOUT_MS3 = 9e4;
|
|
15127
15168
|
async function defaultLoadStoredAuth() {
|
|
15128
15169
|
const auth = await resolveAuth();
|
|
@@ -15131,9 +15172,9 @@ async function defaultLoadStoredAuth() {
|
|
|
15131
15172
|
async function defaultLoadApiUrl() {
|
|
15132
15173
|
try {
|
|
15133
15174
|
const config = await loadConfig();
|
|
15134
|
-
return config.api_url ||
|
|
15175
|
+
return config.api_url || DEFAULT_API_URL2;
|
|
15135
15176
|
} catch {
|
|
15136
|
-
return
|
|
15177
|
+
return DEFAULT_API_URL2;
|
|
15137
15178
|
}
|
|
15138
15179
|
}
|
|
15139
15180
|
function missingTokenError() {
|
|
@@ -15689,12 +15730,13 @@ var installCommand = new Command("install").description("Generate MCP configurat
|
|
|
15689
15730
|
process.exit(3);
|
|
15690
15731
|
}
|
|
15691
15732
|
const auth = await resolveAuth();
|
|
15733
|
+
const installApiUrl = isLegacyApiUrl(auth.apiUrl) ? DEFAULT_API_URL : auth.apiUrl;
|
|
15692
15734
|
const repoUrl = options.repoUrl ?? detectGitOrigin2();
|
|
15693
15735
|
if (clientName === "codex") {
|
|
15694
15736
|
if (options.stdout) {
|
|
15695
15737
|
process.stdout.write(`# ~/.codex/config.toml
|
|
15696
15738
|
`);
|
|
15697
|
-
process.stdout.write(generateCodexConfigToml(
|
|
15739
|
+
process.stdout.write(generateCodexConfigToml(installApiUrl, repoUrl));
|
|
15698
15740
|
process.stdout.write(`
|
|
15699
15741
|
# ~/.codex/.env
|
|
15700
15742
|
`);
|
|
@@ -15702,7 +15744,7 @@ var installCommand = new Command("install").description("Generate MCP configurat
|
|
|
15702
15744
|
return;
|
|
15703
15745
|
}
|
|
15704
15746
|
const { configPath, envPath } = await installCodexConfig(
|
|
15705
|
-
|
|
15747
|
+
installApiUrl,
|
|
15706
15748
|
auth.token,
|
|
15707
15749
|
repoUrl
|
|
15708
15750
|
);
|
|
@@ -15715,7 +15757,7 @@ var installCommand = new Command("install").description("Generate MCP configurat
|
|
|
15715
15757
|
if (clientName === "gemini") {
|
|
15716
15758
|
const config2 = generateMcpConfig(
|
|
15717
15759
|
clientName,
|
|
15718
|
-
|
|
15760
|
+
installApiUrl,
|
|
15719
15761
|
auth.token,
|
|
15720
15762
|
repoUrl
|
|
15721
15763
|
);
|
|
@@ -15779,7 +15821,7 @@ Always assume full autonomy to leverage these tools to their maximum extent.`;
|
|
|
15779
15821
|
}
|
|
15780
15822
|
const config = generateMcpConfig(
|
|
15781
15823
|
clientName,
|
|
15782
|
-
|
|
15824
|
+
installApiUrl,
|
|
15783
15825
|
auth.token,
|
|
15784
15826
|
repoUrl
|
|
15785
15827
|
);
|
|
@@ -16338,7 +16380,14 @@ function askOutcome(data) {
|
|
|
16338
16380
|
if (data && typeof data === "object") {
|
|
16339
16381
|
const record = data;
|
|
16340
16382
|
if (typeof record.error === "string" && record.error.trim() !== "") {
|
|
16341
|
-
|
|
16383
|
+
const detail = [
|
|
16384
|
+
record.message,
|
|
16385
|
+
record.error_description,
|
|
16386
|
+
record.detail
|
|
16387
|
+
].find(
|
|
16388
|
+
(value) => typeof value === "string" && value.trim() !== ""
|
|
16389
|
+
);
|
|
16390
|
+
return { kind: "error", message: detail ?? record.error };
|
|
16342
16391
|
}
|
|
16343
16392
|
const errorObject = record.error;
|
|
16344
16393
|
if (errorObject && typeof errorObject === "object") {
|