@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.
Files changed (2) hide show
  1. package/dist/index.js +63 -14
  2. 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.43";
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.deleteToken(file)", err);
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/commands/login.ts
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 = config.api_url || DEFAULT_API_URL;
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 || DEFAULT_API_URL2;
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 DEFAULT_API_URL3 = "https://www.greatarrow.ai";
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 || DEFAULT_API_URL3;
15175
+ return config.api_url || DEFAULT_API_URL2;
15135
15176
  } catch {
15136
- return DEFAULT_API_URL3;
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(auth.apiUrl, repoUrl));
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
- auth.apiUrl,
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
- auth.apiUrl,
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
- auth.apiUrl,
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
- return { kind: "error", message: record.error };
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") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@great-arrow/cli",
3
- "version": "0.1.43",
3
+ "version": "0.1.45",
4
4
  "description": "GreatArrow.ai CLI tool",
5
5
  "type": "module",
6
6
  "bin": {