@great-arrow/cli 0.1.46 → 0.1.48
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 +7 -0
- package/dist/index.js +319 -149
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,6 +38,13 @@ gad whoami
|
|
|
38
38
|
|
|
39
39
|
# Revoke the session server-side and remove stored credentials
|
|
40
40
|
gad logout
|
|
41
|
+
|
|
42
|
+
# For tools, not humans: print a fresh access token through the CLI's locked
|
|
43
|
+
# refresh path (~/.great-arrow/refresh.lock), so other programs never refresh
|
|
44
|
+
# this credential themselves. --json prints {accessToken, accessExpiresAt,
|
|
45
|
+
# apiUrl}. Exit 2: session expired or not signed in. Exit 3: the stored
|
|
46
|
+
# credential is a personal token (nothing to refresh).
|
|
47
|
+
gad auth token [--json]
|
|
41
48
|
```
|
|
42
49
|
|
|
43
50
|
Credentials live in your OS keychain (Keychain Access / libsecret / Credential
|
package/dist/index.js
CHANGED
|
@@ -1964,7 +1964,7 @@ var require_minimist = __commonJS({
|
|
|
1964
1964
|
var require_rc = __commonJS({
|
|
1965
1965
|
"node_modules/.pnpm/rc@1.2.8/node_modules/rc/index.js"(exports, module) {
|
|
1966
1966
|
var cc = require_utils();
|
|
1967
|
-
var
|
|
1967
|
+
var join9 = __require("path").join;
|
|
1968
1968
|
var deepExtend = require_deep_extend();
|
|
1969
1969
|
var etc = "/etc";
|
|
1970
1970
|
var win = process.platform === "win32";
|
|
@@ -1989,15 +1989,15 @@ var require_rc = __commonJS({
|
|
|
1989
1989
|
}
|
|
1990
1990
|
if (!win)
|
|
1991
1991
|
[
|
|
1992
|
-
|
|
1993
|
-
|
|
1992
|
+
join9(etc, name, "config"),
|
|
1993
|
+
join9(etc, name + "rc")
|
|
1994
1994
|
].forEach(addConfigFile);
|
|
1995
1995
|
if (home)
|
|
1996
1996
|
[
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
1997
|
+
join9(home, ".config", name, "config"),
|
|
1998
|
+
join9(home, ".config", name),
|
|
1999
|
+
join9(home, "." + name, "config"),
|
|
2000
|
+
join9(home, "." + name + "rc")
|
|
2001
2001
|
].forEach(addConfigFile);
|
|
2002
2002
|
addConfigFile(cc.find("." + name + "rc"));
|
|
2003
2003
|
if (env4.config) addConfigFile(env4.config);
|
|
@@ -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.48";
|
|
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";
|
|
@@ -9538,10 +9538,55 @@ async function clearStoredCredential() {
|
|
|
9538
9538
|
await deleteToken();
|
|
9539
9539
|
}
|
|
9540
9540
|
|
|
9541
|
+
// src/lib/cli-locator.ts
|
|
9542
|
+
import {
|
|
9543
|
+
chmodSync,
|
|
9544
|
+
mkdirSync,
|
|
9545
|
+
realpathSync,
|
|
9546
|
+
renameSync,
|
|
9547
|
+
rmSync,
|
|
9548
|
+
writeFileSync
|
|
9549
|
+
} from "node:fs";
|
|
9550
|
+
import { homedir as homedir2 } from "node:os";
|
|
9551
|
+
import { join as join2 } from "node:path";
|
|
9552
|
+
function writeCliLocator(home = homedir2(), entry = process.argv[1]) {
|
|
9553
|
+
if (!entry) return;
|
|
9554
|
+
const dir = join2(home, ".great-arrow");
|
|
9555
|
+
const target = join2(dir, "cli-bin.json");
|
|
9556
|
+
const tmp = `${target}.${process.pid}.tmp`;
|
|
9557
|
+
try {
|
|
9558
|
+
let resolved = entry;
|
|
9559
|
+
try {
|
|
9560
|
+
resolved = realpathSync(entry);
|
|
9561
|
+
} catch (err) {
|
|
9562
|
+
debugSwallow("cli-locator.realpath", err);
|
|
9563
|
+
}
|
|
9564
|
+
mkdirSync(dir, { recursive: true });
|
|
9565
|
+
writeFileSync(
|
|
9566
|
+
tmp,
|
|
9567
|
+
JSON.stringify({
|
|
9568
|
+
node: process.execPath,
|
|
9569
|
+
entry: resolved,
|
|
9570
|
+
version: CLI_VERSION
|
|
9571
|
+
}),
|
|
9572
|
+
{ mode: 384 }
|
|
9573
|
+
);
|
|
9574
|
+
chmodSync(tmp, 384);
|
|
9575
|
+
renameSync(tmp, target);
|
|
9576
|
+
} catch (err) {
|
|
9577
|
+
debugSwallow("cli-locator.write", err);
|
|
9578
|
+
try {
|
|
9579
|
+
rmSync(tmp, { force: true });
|
|
9580
|
+
} catch (cleanupErr) {
|
|
9581
|
+
debugSwallow("cli-locator.cleanup", cleanupErr);
|
|
9582
|
+
}
|
|
9583
|
+
}
|
|
9584
|
+
}
|
|
9585
|
+
|
|
9541
9586
|
// src/lib/config.ts
|
|
9542
9587
|
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "node:fs/promises";
|
|
9543
|
-
import { homedir as
|
|
9544
|
-
import { join as
|
|
9588
|
+
import { homedir as homedir3 } from "node:os";
|
|
9589
|
+
import { join as join3, dirname as dirname2 } from "node:path";
|
|
9545
9590
|
var DEFAULTS = {
|
|
9546
9591
|
api_url: "https://www.greatarrow.ai",
|
|
9547
9592
|
default_workspace: "",
|
|
@@ -9552,7 +9597,7 @@ var DEFAULTS = {
|
|
|
9552
9597
|
telemetry_enabled: false
|
|
9553
9598
|
};
|
|
9554
9599
|
function getConfigPath() {
|
|
9555
|
-
return
|
|
9600
|
+
return join3(homedir3(), ".gadrc");
|
|
9556
9601
|
}
|
|
9557
9602
|
function parseConfig(content) {
|
|
9558
9603
|
const config = {};
|
|
@@ -9820,6 +9865,10 @@ function trimSlash(url) {
|
|
|
9820
9865
|
}
|
|
9821
9866
|
|
|
9822
9867
|
// src/lib/oauth/token-exchange.ts
|
|
9868
|
+
var TOKEN_HEADERS = {
|
|
9869
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
9870
|
+
"user-agent": `gad-cli/${CLI_VERSION}`
|
|
9871
|
+
};
|
|
9823
9872
|
var RefreshRejected = class extends Error {
|
|
9824
9873
|
constructor(message) {
|
|
9825
9874
|
super(message);
|
|
@@ -9849,11 +9898,13 @@ function toCredential(env4, apiUrl, clientId, now) {
|
|
|
9849
9898
|
apiUrl: trimSlash2(apiUrl)
|
|
9850
9899
|
};
|
|
9851
9900
|
}
|
|
9852
|
-
|
|
9901
|
+
var TOKEN_POST_TIMEOUT_MS = 8e3;
|
|
9902
|
+
async function postToken(apiUrl, form, fetchImpl, timeoutMs = TOKEN_POST_TIMEOUT_MS) {
|
|
9853
9903
|
const res = await fetchImpl(`${trimSlash2(apiUrl)}/api/oauth/token`, {
|
|
9854
9904
|
method: "POST",
|
|
9855
|
-
headers:
|
|
9856
|
-
body: new URLSearchParams(form).toString()
|
|
9905
|
+
headers: TOKEN_HEADERS,
|
|
9906
|
+
body: new URLSearchParams(form).toString(),
|
|
9907
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
9857
9908
|
});
|
|
9858
9909
|
const json = await res.json().catch(() => ({}));
|
|
9859
9910
|
return { ok: res.ok, status: res.status, json };
|
|
@@ -9893,8 +9944,9 @@ async function revokeToken(opts) {
|
|
|
9893
9944
|
try {
|
|
9894
9945
|
const res = await doFetch(`${trimSlash2(opts.apiUrl)}/api/oauth/revoke`, {
|
|
9895
9946
|
method: "POST",
|
|
9896
|
-
headers:
|
|
9897
|
-
body: new URLSearchParams(form).toString()
|
|
9947
|
+
headers: TOKEN_HEADERS,
|
|
9948
|
+
body: new URLSearchParams(form).toString(),
|
|
9949
|
+
signal: AbortSignal.timeout(TOKEN_POST_TIMEOUT_MS)
|
|
9898
9950
|
});
|
|
9899
9951
|
return res.ok;
|
|
9900
9952
|
} catch {
|
|
@@ -9910,7 +9962,8 @@ async function refreshTokens(opts) {
|
|
|
9910
9962
|
client_id: opts.clientId,
|
|
9911
9963
|
refresh_token: opts.refreshToken
|
|
9912
9964
|
},
|
|
9913
|
-
opts.fetchImpl ?? fetch
|
|
9965
|
+
opts.fetchImpl ?? fetch,
|
|
9966
|
+
opts.timeoutMs
|
|
9914
9967
|
);
|
|
9915
9968
|
if (!ok) {
|
|
9916
9969
|
const desc = String(json.error_description ?? json.error ?? "unknown");
|
|
@@ -10284,6 +10337,7 @@ var loginCommand = new Command("login").description("Authenticate the CLI with y
|
|
|
10284
10337
|
process.exitCode = 1;
|
|
10285
10338
|
return;
|
|
10286
10339
|
}
|
|
10340
|
+
writeCliLocator();
|
|
10287
10341
|
config.cli_client_id = result.clientId;
|
|
10288
10342
|
config.cli_redirect_uri = result.redirectUri;
|
|
10289
10343
|
config.api_url = DEFAULT_API_URL;
|
|
@@ -10303,52 +10357,22 @@ var loginCommand = new Command("login").description("Authenticate the CLI with y
|
|
|
10303
10357
|
);
|
|
10304
10358
|
var login_default = loginCommand;
|
|
10305
10359
|
|
|
10306
|
-
// src/commands/logout.ts
|
|
10307
|
-
var logoutCommand = new Command("logout").description("Remove stored authentication credentials").action(async (_options, cmd) => {
|
|
10308
|
-
const parent = cmd.parent;
|
|
10309
|
-
const json = parent?.opts().json ?? false;
|
|
10310
|
-
const quiet = parent?.opts().quiet ?? false;
|
|
10311
|
-
const noColor = parent?.opts().noColor ?? false;
|
|
10312
|
-
const fmt = createFormatter({
|
|
10313
|
-
json,
|
|
10314
|
-
quiet,
|
|
10315
|
-
isTTY: isTTY(),
|
|
10316
|
-
noColor
|
|
10317
|
-
});
|
|
10318
|
-
const stored = await loadStoredCredential();
|
|
10319
|
-
if (stored?.kind === "oauth") {
|
|
10320
|
-
await revokeToken({
|
|
10321
|
-
apiUrl: stored.credential.apiUrl,
|
|
10322
|
-
clientId: stored.credential.clientId,
|
|
10323
|
-
token: stored.credential.refreshToken,
|
|
10324
|
-
tokenTypeHint: "refresh_token"
|
|
10325
|
-
});
|
|
10326
|
-
}
|
|
10327
|
-
await clearStoredCredential();
|
|
10328
|
-
const config = await loadConfig();
|
|
10329
|
-
if (config.token) {
|
|
10330
|
-
config.token = "";
|
|
10331
|
-
await saveConfig(config);
|
|
10332
|
-
}
|
|
10333
|
-
fmt.success("Logged out successfully.");
|
|
10334
|
-
});
|
|
10335
|
-
|
|
10336
10360
|
// src/lib/auth.ts
|
|
10337
10361
|
import { mkdir as mkdir3, open, rm, stat } from "node:fs/promises";
|
|
10338
|
-
import { homedir as
|
|
10339
|
-
import { join as
|
|
10362
|
+
import { homedir as homedir4 } from "node:os";
|
|
10363
|
+
import { join as join4 } from "node:path";
|
|
10340
10364
|
var REFRESH_SKEW_MS = 12e4;
|
|
10341
10365
|
var inflightRefresh = null;
|
|
10342
10366
|
var REFRESH_LOCK_STALE_MS = 15e3;
|
|
10343
10367
|
var REFRESH_LOCK_WAIT_MS = 5e3;
|
|
10344
10368
|
var REFRESH_LOCK_POLL_MS = 100;
|
|
10345
10369
|
function refreshLockPath() {
|
|
10346
|
-
return
|
|
10370
|
+
return join4(homedir4(), ".great-arrow", "refresh.lock");
|
|
10347
10371
|
}
|
|
10348
10372
|
async function acquireRefreshLock() {
|
|
10349
10373
|
const path10 = refreshLockPath();
|
|
10350
10374
|
try {
|
|
10351
|
-
await mkdir3(
|
|
10375
|
+
await mkdir3(join4(homedir4(), ".great-arrow"), { recursive: true });
|
|
10352
10376
|
} catch (err) {
|
|
10353
10377
|
debugSwallow("refresh-lock.mkdir", err);
|
|
10354
10378
|
}
|
|
@@ -10382,7 +10406,7 @@ async function releaseRefreshLock() {
|
|
|
10382
10406
|
debugSwallow("refresh-lock.release", err);
|
|
10383
10407
|
}
|
|
10384
10408
|
}
|
|
10385
|
-
async function
|
|
10409
|
+
async function storedPairOtherThan(ours) {
|
|
10386
10410
|
let stored = null;
|
|
10387
10411
|
try {
|
|
10388
10412
|
stored = await loadStoredCredential();
|
|
@@ -10390,8 +10414,11 @@ async function rotatedByAnotherProcess(ours) {
|
|
|
10390
10414
|
debugSwallow("refresh.reread", err);
|
|
10391
10415
|
}
|
|
10392
10416
|
if (stored?.kind !== "oauth") return null;
|
|
10393
|
-
|
|
10394
|
-
|
|
10417
|
+
return stored.credential.refreshToken === ours.refreshToken ? null : stored.credential;
|
|
10418
|
+
}
|
|
10419
|
+
async function rotatedByAnotherProcess(ours) {
|
|
10420
|
+
const theirs = await storedPairOtherThan(ours);
|
|
10421
|
+
if (!theirs) return null;
|
|
10395
10422
|
if (Date.now() >= theirs.accessExpiresAt - REFRESH_SKEW_MS) return null;
|
|
10396
10423
|
return theirs;
|
|
10397
10424
|
}
|
|
@@ -10434,11 +10461,40 @@ async function resolveAuth() {
|
|
|
10434
10461
|
tokenType: "personal"
|
|
10435
10462
|
});
|
|
10436
10463
|
}
|
|
10464
|
+
const codexEnvToken = process.env.GREAT_ARROW_TOKEN;
|
|
10465
|
+
if (codexEnvToken) {
|
|
10466
|
+
return withWorkspace({
|
|
10467
|
+
token: codexEnvToken,
|
|
10468
|
+
apiUrl: configApiUrl,
|
|
10469
|
+
tokenType: "personal"
|
|
10470
|
+
});
|
|
10471
|
+
}
|
|
10437
10472
|
throw authError(
|
|
10438
10473
|
"No authentication token found.",
|
|
10439
10474
|
"Run 'gad login' to authenticate, or set the GAD_TOKEN environment variable."
|
|
10440
10475
|
);
|
|
10441
10476
|
}
|
|
10477
|
+
var NotOAuthCredential = class extends Error {
|
|
10478
|
+
code = "not_oauth";
|
|
10479
|
+
};
|
|
10480
|
+
async function getFreshOAuthAccessToken() {
|
|
10481
|
+
const stored = await loadStoredCredential();
|
|
10482
|
+
if (!stored) {
|
|
10483
|
+
throw authError(
|
|
10484
|
+
"Session expired. Not signed in.",
|
|
10485
|
+
"Run 'gad login' to authenticate."
|
|
10486
|
+
);
|
|
10487
|
+
}
|
|
10488
|
+
if (stored.kind !== "oauth") {
|
|
10489
|
+
throw new NotOAuthCredential("stored credential is not OAuth");
|
|
10490
|
+
}
|
|
10491
|
+
const fresh = await ensureFreshAccessToken(stored.credential);
|
|
10492
|
+
return {
|
|
10493
|
+
accessToken: fresh.accessToken,
|
|
10494
|
+
accessExpiresAt: fresh.accessExpiresAt,
|
|
10495
|
+
apiUrl: fresh.apiUrl
|
|
10496
|
+
};
|
|
10497
|
+
}
|
|
10442
10498
|
async function ensureFreshAccessToken(credential) {
|
|
10443
10499
|
if (Date.now() < credential.accessExpiresAt - REFRESH_SKEW_MS) {
|
|
10444
10500
|
return credential;
|
|
@@ -10468,6 +10524,8 @@ async function doRefresh(credential) {
|
|
|
10468
10524
|
return refreshed;
|
|
10469
10525
|
} catch (err) {
|
|
10470
10526
|
if (err instanceof RefreshRejected) {
|
|
10527
|
+
const theirs = await storedPairOtherThan(credential);
|
|
10528
|
+
if (theirs) return theirs;
|
|
10471
10529
|
await clearStoredCredential();
|
|
10472
10530
|
throw sessionExpired();
|
|
10473
10531
|
}
|
|
@@ -10480,6 +10538,70 @@ function sessionExpired() {
|
|
|
10480
10538
|
return authError("Session expired.", "Run 'gad login' to re-authenticate.");
|
|
10481
10539
|
}
|
|
10482
10540
|
|
|
10541
|
+
// src/commands/auth.ts
|
|
10542
|
+
var EXIT_SESSION_EXPIRED = 2;
|
|
10543
|
+
var EXIT_NOT_OAUTH = 3;
|
|
10544
|
+
function authCommand() {
|
|
10545
|
+
const cmd = new Command("auth").description("Authentication helpers");
|
|
10546
|
+
cmd.command("token").description("Print a fresh OAuth access token, refreshing it if needed").option("--json", "Output {accessToken, accessExpiresAt, apiUrl} as JSON").action(async (options) => {
|
|
10547
|
+
try {
|
|
10548
|
+
const t = await getFreshOAuthAccessToken();
|
|
10549
|
+
writeCliLocator();
|
|
10550
|
+
process.stdout.write(
|
|
10551
|
+
options.json ? `${JSON.stringify(t)}
|
|
10552
|
+
` : `${t.accessToken}
|
|
10553
|
+
`
|
|
10554
|
+
);
|
|
10555
|
+
} catch (error) {
|
|
10556
|
+
if (error instanceof NotOAuthCredential) {
|
|
10557
|
+
process.stderr.write(`${error.message}
|
|
10558
|
+
`);
|
|
10559
|
+
process.exitCode = EXIT_NOT_OAUTH;
|
|
10560
|
+
return;
|
|
10561
|
+
}
|
|
10562
|
+
if (error instanceof CliError && error.code === 1) {
|
|
10563
|
+
const hint = error.hint ? ` ${error.hint}` : "";
|
|
10564
|
+
process.stderr.write(`${error.message}${hint}
|
|
10565
|
+
`);
|
|
10566
|
+
process.exitCode = EXIT_SESSION_EXPIRED;
|
|
10567
|
+
return;
|
|
10568
|
+
}
|
|
10569
|
+
throw error;
|
|
10570
|
+
}
|
|
10571
|
+
});
|
|
10572
|
+
return cmd;
|
|
10573
|
+
}
|
|
10574
|
+
|
|
10575
|
+
// src/commands/logout.ts
|
|
10576
|
+
var logoutCommand = new Command("logout").description("Remove stored authentication credentials").action(async (_options, cmd) => {
|
|
10577
|
+
const parent = cmd.parent;
|
|
10578
|
+
const json = parent?.opts().json ?? false;
|
|
10579
|
+
const quiet = parent?.opts().quiet ?? false;
|
|
10580
|
+
const noColor = parent?.opts().noColor ?? false;
|
|
10581
|
+
const fmt = createFormatter({
|
|
10582
|
+
json,
|
|
10583
|
+
quiet,
|
|
10584
|
+
isTTY: isTTY(),
|
|
10585
|
+
noColor
|
|
10586
|
+
});
|
|
10587
|
+
const stored = await loadStoredCredential();
|
|
10588
|
+
if (stored?.kind === "oauth") {
|
|
10589
|
+
await revokeToken({
|
|
10590
|
+
apiUrl: stored.credential.apiUrl,
|
|
10591
|
+
clientId: stored.credential.clientId,
|
|
10592
|
+
token: stored.credential.refreshToken,
|
|
10593
|
+
tokenTypeHint: "refresh_token"
|
|
10594
|
+
});
|
|
10595
|
+
}
|
|
10596
|
+
await clearStoredCredential();
|
|
10597
|
+
const config = await loadConfig();
|
|
10598
|
+
if (config.token) {
|
|
10599
|
+
config.token = "";
|
|
10600
|
+
await saveConfig(config);
|
|
10601
|
+
}
|
|
10602
|
+
fmt.success("Logged out successfully.");
|
|
10603
|
+
});
|
|
10604
|
+
|
|
10483
10605
|
// src/lib/client.ts
|
|
10484
10606
|
import { execSync } from "node:child_process";
|
|
10485
10607
|
|
|
@@ -10641,6 +10763,46 @@ function isRetryable(error) {
|
|
|
10641
10763
|
}
|
|
10642
10764
|
return false;
|
|
10643
10765
|
}
|
|
10766
|
+
var RETRY_SAFE_TOOLS = /* @__PURE__ */ new Set([
|
|
10767
|
+
"workspace_introspect",
|
|
10768
|
+
"mcp_capabilities",
|
|
10769
|
+
"tools_discover",
|
|
10770
|
+
"memory_search",
|
|
10771
|
+
"memory_list",
|
|
10772
|
+
"memory_get",
|
|
10773
|
+
"memory_tags",
|
|
10774
|
+
"todo_list",
|
|
10775
|
+
"todo_get",
|
|
10776
|
+
"workspace_list",
|
|
10777
|
+
"workspace_settings_get",
|
|
10778
|
+
"surfaces_list",
|
|
10779
|
+
"agent_list",
|
|
10780
|
+
"engineering_guardrails_list",
|
|
10781
|
+
"model_local_get",
|
|
10782
|
+
"glance",
|
|
10783
|
+
"did_you_know"
|
|
10784
|
+
]);
|
|
10785
|
+
var CONNECTION_PHASE_CODES = /* @__PURE__ */ new Set([
|
|
10786
|
+
"ECONNREFUSED",
|
|
10787
|
+
"ENOTFOUND",
|
|
10788
|
+
"EAI_AGAIN",
|
|
10789
|
+
"ENETUNREACH",
|
|
10790
|
+
"EHOSTUNREACH",
|
|
10791
|
+
"UND_ERR_CONNECT_TIMEOUT"
|
|
10792
|
+
]);
|
|
10793
|
+
function hasConnectionPhaseCode(value) {
|
|
10794
|
+
if (!value || typeof value !== "object") return false;
|
|
10795
|
+
const errors = value.errors;
|
|
10796
|
+
if (Array.isArray(errors) && errors.length > 0) {
|
|
10797
|
+
return errors.every(hasConnectionPhaseCode);
|
|
10798
|
+
}
|
|
10799
|
+
const code = value.code;
|
|
10800
|
+
return typeof code === "string" && CONNECTION_PHASE_CODES.has(code);
|
|
10801
|
+
}
|
|
10802
|
+
function isConnectionPhaseFailure(error) {
|
|
10803
|
+
if (!(error instanceof TypeError)) return false;
|
|
10804
|
+
return hasConnectionPhaseCode(error.cause);
|
|
10805
|
+
}
|
|
10644
10806
|
function isRetryableStatus(status) {
|
|
10645
10807
|
return status >= 500 && status < 600;
|
|
10646
10808
|
}
|
|
@@ -10696,7 +10858,7 @@ var GadClient = class {
|
|
|
10696
10858
|
/**
|
|
10697
10859
|
* Execute a fetch request with timeout and retry logic.
|
|
10698
10860
|
*/
|
|
10699
|
-
async fetchWithRetry(url, init, timeoutMs) {
|
|
10861
|
+
async fetchWithRetry(url, init, timeoutMs, policy = "transient") {
|
|
10700
10862
|
const effectiveTimeout = timeoutMs ?? this.timeout;
|
|
10701
10863
|
let lastError;
|
|
10702
10864
|
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
@@ -10708,7 +10870,7 @@ var GadClient = class {
|
|
|
10708
10870
|
signal: controller.signal
|
|
10709
10871
|
});
|
|
10710
10872
|
clearTimeout(timer);
|
|
10711
|
-
if (isRetryableStatus(response.status)) {
|
|
10873
|
+
if (policy === "transient" && isRetryableStatus(response.status)) {
|
|
10712
10874
|
lastError = response;
|
|
10713
10875
|
if (attempt < MAX_RETRIES - 1) {
|
|
10714
10876
|
await sleep(retryDelay(attempt));
|
|
@@ -10720,7 +10882,8 @@ var GadClient = class {
|
|
|
10720
10882
|
} catch (error) {
|
|
10721
10883
|
clearTimeout(timer);
|
|
10722
10884
|
lastError = error;
|
|
10723
|
-
|
|
10885
|
+
const retryable = policy === "transient" ? isRetryable(error) : isConnectionPhaseFailure(error);
|
|
10886
|
+
if (retryable && attempt < MAX_RETRIES - 1) {
|
|
10724
10887
|
await sleep(retryDelay(attempt));
|
|
10725
10888
|
continue;
|
|
10726
10889
|
}
|
|
@@ -10789,7 +10952,8 @@ var GadClient = class {
|
|
|
10789
10952
|
headers: this.buildHeaders(),
|
|
10790
10953
|
body
|
|
10791
10954
|
},
|
|
10792
|
-
timeoutMs
|
|
10955
|
+
timeoutMs,
|
|
10956
|
+
RETRY_SAFE_TOOLS.has(toolName) ? "transient" : "connection-only"
|
|
10793
10957
|
);
|
|
10794
10958
|
} catch (error) {
|
|
10795
10959
|
if (error instanceof CliError) throw error;
|
|
@@ -10881,11 +11045,16 @@ var GadClient = class {
|
|
|
10881
11045
|
const url = `${this.apiUrl}${path10}`;
|
|
10882
11046
|
let response;
|
|
10883
11047
|
try {
|
|
10884
|
-
response = await this.fetchWithRetry(
|
|
10885
|
-
|
|
10886
|
-
|
|
10887
|
-
|
|
10888
|
-
|
|
11048
|
+
response = await this.fetchWithRetry(
|
|
11049
|
+
url,
|
|
11050
|
+
{
|
|
11051
|
+
method: "POST",
|
|
11052
|
+
headers: this.buildHeaders(),
|
|
11053
|
+
body: JSON.stringify(body)
|
|
11054
|
+
},
|
|
11055
|
+
void 0,
|
|
11056
|
+
"connection-only"
|
|
11057
|
+
);
|
|
10889
11058
|
} catch (error) {
|
|
10890
11059
|
if (error instanceof CliError) throw error;
|
|
10891
11060
|
void captureCliEvent({
|
|
@@ -12302,8 +12471,8 @@ var work_default = workCommand;
|
|
|
12302
12471
|
|
|
12303
12472
|
// src/commands/worktree.ts
|
|
12304
12473
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
12305
|
-
import { existsSync, readFileSync as readFileSync2, statSync, writeFileSync } from "node:fs";
|
|
12306
|
-
import { basename, dirname as dirname3, isAbsolute, join as
|
|
12474
|
+
import { existsSync, readFileSync as readFileSync2, statSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
12475
|
+
import { basename, dirname as dirname3, isAbsolute, join as join5, resolve } from "node:path";
|
|
12307
12476
|
var realExec = (cmd, args, opts) => {
|
|
12308
12477
|
const out = execFileSync3(cmd, args, {
|
|
12309
12478
|
cwd: opts?.cwd,
|
|
@@ -12325,9 +12494,9 @@ function parseDefaultBranch(symbolicRef) {
|
|
|
12325
12494
|
return match ? match[1] : null;
|
|
12326
12495
|
}
|
|
12327
12496
|
function detectPackageManager(repoRoot) {
|
|
12328
|
-
if (existsSync(
|
|
12329
|
-
if (existsSync(
|
|
12330
|
-
if (existsSync(
|
|
12497
|
+
if (existsSync(join5(repoRoot, "pnpm-lock.yaml"))) return "pnpm";
|
|
12498
|
+
if (existsSync(join5(repoRoot, "bun.lockb"))) return "bun";
|
|
12499
|
+
if (existsSync(join5(repoRoot, "yarn.lock"))) return "yarn";
|
|
12331
12500
|
return "npm";
|
|
12332
12501
|
}
|
|
12333
12502
|
function defaultWorktreeDir(repoRoot, branch) {
|
|
@@ -12335,7 +12504,7 @@ function defaultWorktreeDir(repoRoot, branch) {
|
|
|
12335
12504
|
/[^A-Za-z0-9._-]+/g,
|
|
12336
12505
|
"-"
|
|
12337
12506
|
);
|
|
12338
|
-
return
|
|
12507
|
+
return join5(dirname3(repoRoot), `${basename(repoRoot)}-${slug}`);
|
|
12339
12508
|
}
|
|
12340
12509
|
var AGENT_PROCESS_RE = /(^|\/)(claude|kiro|cursor|codex)/i;
|
|
12341
12510
|
function psField(pid, field) {
|
|
@@ -12358,7 +12527,7 @@ function findAgentPid(startPid) {
|
|
|
12358
12527
|
return null;
|
|
12359
12528
|
}
|
|
12360
12529
|
function ownGitDir(worktreeDir) {
|
|
12361
|
-
const dotGit =
|
|
12530
|
+
const dotGit = join5(worktreeDir, ".git");
|
|
12362
12531
|
if (!existsSync(dotGit)) return null;
|
|
12363
12532
|
if (statSync(dotGit).isDirectory()) return dotGit;
|
|
12364
12533
|
const match = readFileSync2(dotGit, "utf8").trim().match(/^gitdir:\s*(.+)$/m);
|
|
@@ -12372,8 +12541,8 @@ function stampWorktreeOwner(worktreeDir) {
|
|
|
12372
12541
|
if (!gitDir) return null;
|
|
12373
12542
|
const ownerPid = findAgentPid(process.ppid);
|
|
12374
12543
|
if (!ownerPid) return null;
|
|
12375
|
-
|
|
12376
|
-
|
|
12544
|
+
writeFileSync2(
|
|
12545
|
+
join5(gitDir, "agent-owner.json"),
|
|
12377
12546
|
JSON.stringify(
|
|
12378
12547
|
{
|
|
12379
12548
|
ownerPid,
|
|
@@ -12467,7 +12636,7 @@ function createTaskWorktree(opts) {
|
|
|
12467
12636
|
const stampedPid = opts.stamp === false ? null : stampWorktreeOwner(dir);
|
|
12468
12637
|
const packageManager = detectPackageManager(repoRoot);
|
|
12469
12638
|
let installed = false;
|
|
12470
|
-
if (opts.install !== false && existsSync(
|
|
12639
|
+
if (opts.install !== false && existsSync(join5(repoRoot, "package.json"))) {
|
|
12471
12640
|
exec2(packageManager, ["install"], { cwd: dir, inherit: true });
|
|
12472
12641
|
installed = true;
|
|
12473
12642
|
}
|
|
@@ -12530,13 +12699,13 @@ var worktree_default = worktreeCommand;
|
|
|
12530
12699
|
// src/commands/install-hooks.ts
|
|
12531
12700
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
12532
12701
|
import {
|
|
12533
|
-
chmodSync,
|
|
12702
|
+
chmodSync as chmodSync2,
|
|
12534
12703
|
existsSync as existsSync2,
|
|
12535
|
-
mkdirSync,
|
|
12704
|
+
mkdirSync as mkdirSync2,
|
|
12536
12705
|
readFileSync as readFileSync3,
|
|
12537
|
-
writeFileSync as
|
|
12706
|
+
writeFileSync as writeFileSync3
|
|
12538
12707
|
} from "node:fs";
|
|
12539
|
-
import { isAbsolute as isAbsolute2, join as
|
|
12708
|
+
import { isAbsolute as isAbsolute2, join as join6, resolve as resolve2 } from "node:path";
|
|
12540
12709
|
var GUARD_MARKER = "# gad-agent-guard v1";
|
|
12541
12710
|
var SCHEMA_AUDIT_MARKER = "# gad-schema-audit v1";
|
|
12542
12711
|
var GUARD_FILE = "gad-commit-guard.mjs";
|
|
@@ -12719,28 +12888,28 @@ function installCommitGuard(opts) {
|
|
|
12719
12888
|
);
|
|
12720
12889
|
}
|
|
12721
12890
|
if (!isAbsolute2(commonDir)) commonDir = resolve2(repoRoot, commonDir);
|
|
12722
|
-
const hooksDir =
|
|
12723
|
-
|
|
12724
|
-
const guardPath =
|
|
12725
|
-
|
|
12726
|
-
|
|
12727
|
-
const huskyHook =
|
|
12728
|
-
const hookPath = existsSync2(huskyHook) ? huskyHook :
|
|
12891
|
+
const hooksDir = join6(commonDir, "hooks");
|
|
12892
|
+
mkdirSync2(hooksDir, { recursive: true });
|
|
12893
|
+
const guardPath = join6(hooksDir, GUARD_FILE);
|
|
12894
|
+
writeFileSync3(guardPath, buildGuardScript());
|
|
12895
|
+
chmodSync2(guardPath, 493);
|
|
12896
|
+
const huskyHook = join6(repoRoot, ".husky", "pre-commit");
|
|
12897
|
+
const hookPath = existsSync2(huskyHook) ? huskyHook : join6(hooksDir, "pre-commit");
|
|
12729
12898
|
const existing = existsSync2(hookPath) ? readFileSync3(hookPath, "utf8") : null;
|
|
12730
12899
|
const plan = planHookInstall(existing);
|
|
12731
12900
|
if (plan.action !== "noop") {
|
|
12732
|
-
|
|
12901
|
+
writeFileSync3(hookPath, plan.content);
|
|
12733
12902
|
}
|
|
12734
|
-
|
|
12735
|
-
const huskyDir =
|
|
12736
|
-
const huskyPrePush =
|
|
12737
|
-
const schemaAuditHookPath = existsSync2(huskyPrePush) || existsSync2(huskyDir) ? huskyPrePush :
|
|
12903
|
+
chmodSync2(hookPath, 493);
|
|
12904
|
+
const huskyDir = join6(repoRoot, ".husky");
|
|
12905
|
+
const huskyPrePush = join6(huskyDir, "pre-push");
|
|
12906
|
+
const schemaAuditHookPath = existsSync2(huskyPrePush) || existsSync2(huskyDir) ? huskyPrePush : join6(hooksDir, "pre-push");
|
|
12738
12907
|
const existingSchemaAuditHook = existsSync2(schemaAuditHookPath) ? readFileSync3(schemaAuditHookPath, "utf8") : null;
|
|
12739
12908
|
const schemaAuditPlan = planSchemaAuditHookInstall(existingSchemaAuditHook);
|
|
12740
12909
|
if (schemaAuditPlan.action !== "noop") {
|
|
12741
|
-
|
|
12910
|
+
writeFileSync3(schemaAuditHookPath, schemaAuditPlan.content);
|
|
12742
12911
|
}
|
|
12743
|
-
|
|
12912
|
+
chmodSync2(schemaAuditHookPath, 493);
|
|
12744
12913
|
return {
|
|
12745
12914
|
guardPath,
|
|
12746
12915
|
hookPath,
|
|
@@ -12858,8 +13027,8 @@ function guardrailsCommand() {
|
|
|
12858
13027
|
// src/commands/doctor.ts
|
|
12859
13028
|
import { existsSync as existsSync3 } from "node:fs";
|
|
12860
13029
|
import { copyFile, mkdir as mkdir4, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
|
|
12861
|
-
import { homedir as
|
|
12862
|
-
import { dirname as dirname4, join as
|
|
13030
|
+
import { homedir as homedir5 } from "node:os";
|
|
13031
|
+
import { dirname as dirname4, join as join7 } from "node:path";
|
|
12863
13032
|
|
|
12864
13033
|
// src/lib/codex-config.ts
|
|
12865
13034
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
@@ -14390,7 +14559,7 @@ async function checkMcp(auth) {
|
|
|
14390
14559
|
}
|
|
14391
14560
|
}
|
|
14392
14561
|
function defaultCodexConfigPath() {
|
|
14393
|
-
return
|
|
14562
|
+
return join7(homedir5(), ".codex", "config.toml");
|
|
14394
14563
|
}
|
|
14395
14564
|
function codexIssuesToChecks(issues) {
|
|
14396
14565
|
return issues.map((issue) => {
|
|
@@ -14528,12 +14697,12 @@ function claudeCommand() {
|
|
|
14528
14697
|
isTTY: isTTY(),
|
|
14529
14698
|
noColor: g.noColor
|
|
14530
14699
|
});
|
|
14531
|
-
const home =
|
|
14532
|
-
const gaDir =
|
|
14533
|
-
const userConfigPath =
|
|
14534
|
-
const settingsPath =
|
|
14535
|
-
const hookConfigPath =
|
|
14536
|
-
const glanceHookPath =
|
|
14700
|
+
const home = homedir5();
|
|
14701
|
+
const gaDir = join7(home, ".great-arrow");
|
|
14702
|
+
const userConfigPath = join7(home, ".claude.json");
|
|
14703
|
+
const settingsPath = join7(home, ".claude", "settings.json");
|
|
14704
|
+
const hookConfigPath = join7(gaDir, "hook-config.json");
|
|
14705
|
+
const glanceHookPath = join7(gaDir, "claude-glance-hook.mjs");
|
|
14537
14706
|
const checks = [];
|
|
14538
14707
|
const repairs = [];
|
|
14539
14708
|
const backups = [];
|
|
@@ -14741,8 +14910,8 @@ function claudeCommand() {
|
|
|
14741
14910
|
file: "/Library/Application Support/ClaudeCode/managed-settings.json"
|
|
14742
14911
|
},
|
|
14743
14912
|
{ scope: "user", file: settingsPath },
|
|
14744
|
-
{ scope: "project", file:
|
|
14745
|
-
{ scope: "local", file:
|
|
14913
|
+
{ scope: "project", file: join7(cwd, ".claude", "settings.json") },
|
|
14914
|
+
{ scope: "local", file: join7(cwd, ".claude", "settings.local.json") }
|
|
14746
14915
|
];
|
|
14747
14916
|
const configured = [];
|
|
14748
14917
|
for (const { scope, file } of scopes) {
|
|
@@ -14811,12 +14980,12 @@ function claudeCommand() {
|
|
|
14811
14980
|
});
|
|
14812
14981
|
}
|
|
14813
14982
|
function defaultJsonClientConfigs() {
|
|
14814
|
-
const home =
|
|
14983
|
+
const home = homedir5();
|
|
14815
14984
|
return [
|
|
14816
|
-
{ name: "Claude Code", path:
|
|
14817
|
-
{ name: "Cursor", path:
|
|
14818
|
-
{ name: "Kiro", path:
|
|
14819
|
-
{ name: "Gemini CLI", path:
|
|
14985
|
+
{ name: "Claude Code", path: join7(home, ".claude.json") },
|
|
14986
|
+
{ name: "Cursor", path: join7(home, ".cursor", "mcp.json") },
|
|
14987
|
+
{ name: "Kiro", path: join7(home, ".kiro", "settings", "mcp.json") },
|
|
14988
|
+
{ name: "Gemini CLI", path: join7(home, ".gemini", "settings.json") }
|
|
14820
14989
|
];
|
|
14821
14990
|
}
|
|
14822
14991
|
function clientsCommand() {
|
|
@@ -15462,12 +15631,12 @@ async function pathExists(path10) {
|
|
|
15462
15631
|
}
|
|
15463
15632
|
}
|
|
15464
15633
|
async function installCodexConfig(apiUrl, token, repoUrl) {
|
|
15465
|
-
const { homedir:
|
|
15466
|
-
const { join:
|
|
15634
|
+
const { homedir: homedir7 } = await import("node:os");
|
|
15635
|
+
const { join: join9 } = await import("node:path");
|
|
15467
15636
|
const { chmod, copyFile: copyFile2, mkdir: mkdir6, readFile: readFile5, writeFile: writeFile5 } = await import("node:fs/promises");
|
|
15468
|
-
const codexDir =
|
|
15469
|
-
const configPath =
|
|
15470
|
-
const envPath =
|
|
15637
|
+
const codexDir = join9(homedir7(), ".codex");
|
|
15638
|
+
const configPath = join9(codexDir, "config.toml");
|
|
15639
|
+
const envPath = join9(codexDir, ".env");
|
|
15471
15640
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
15472
15641
|
await mkdir6(codexDir, { recursive: true });
|
|
15473
15642
|
const existingConfig = await pathExists(configPath) ? await readFile5(configPath, "utf8") : "";
|
|
@@ -15766,11 +15935,11 @@ var installCommand = new Command("install").description("Generate MCP configurat
|
|
|
15766
15935
|
process.stdout.write(configJson2 + "\n");
|
|
15767
15936
|
return;
|
|
15768
15937
|
}
|
|
15769
|
-
const { homedir:
|
|
15770
|
-
const { join:
|
|
15938
|
+
const { homedir: homedir7 } = await import("node:os");
|
|
15939
|
+
const { join: join10 } = await import("node:path");
|
|
15771
15940
|
const { mkdir: mkdir6, readFile: readFile5, writeFile: writeFile6 } = await import("node:fs/promises");
|
|
15772
|
-
const geminiDir =
|
|
15773
|
-
const mcpPath =
|
|
15941
|
+
const geminiDir = join10(homedir7(), ".gemini");
|
|
15942
|
+
const mcpPath = join10(geminiDir, "settings.json");
|
|
15774
15943
|
await mkdir6(geminiDir, { recursive: true });
|
|
15775
15944
|
let existingConfig = {};
|
|
15776
15945
|
try {
|
|
@@ -15792,14 +15961,14 @@ var installCommand = new Command("install").description("Generate MCP configurat
|
|
|
15792
15961
|
"utf-8"
|
|
15793
15962
|
);
|
|
15794
15963
|
fmt.success(`Wrote gemini MCP config to ${mcpPath}`);
|
|
15795
|
-
const agyMcpDir =
|
|
15964
|
+
const agyMcpDir = join10(
|
|
15796
15965
|
geminiDir,
|
|
15797
15966
|
"antigravity-cli",
|
|
15798
15967
|
"mcp",
|
|
15799
15968
|
MCP_SERVER_NAME
|
|
15800
15969
|
);
|
|
15801
15970
|
await mkdir6(agyMcpDir, { recursive: true });
|
|
15802
|
-
const instructionsPath =
|
|
15971
|
+
const instructionsPath = join10(agyMcpDir, "instructions.md");
|
|
15803
15972
|
const instructionsContent = `You are connected to greatarrow.ai - the user's private workspace memory + integrations brain.
|
|
15804
15973
|
|
|
15805
15974
|
CRITICAL DIRECTIVE (MANDATORY STANDARD):
|
|
@@ -15831,8 +16000,8 @@ Always assume full autonomy to leverage these tools to their maximum extent.`;
|
|
|
15831
16000
|
return;
|
|
15832
16001
|
}
|
|
15833
16002
|
const { writeFile: writeFile5 } = await import("node:fs/promises");
|
|
15834
|
-
const { join:
|
|
15835
|
-
const outputPath =
|
|
16003
|
+
const { join: join9 } = await import("node:path");
|
|
16004
|
+
const outputPath = join9(process.cwd(), ".mcp.json");
|
|
15836
16005
|
await writeFile5(outputPath, configJson + "\n", { mode: 384 });
|
|
15837
16006
|
fmt.success(`Wrote ${clientName} MCP config to .mcp.json`);
|
|
15838
16007
|
if (await mcpJsonAtRiskOfCommit(process.cwd())) {
|
|
@@ -15863,13 +16032,13 @@ async function readKeychainOnly() {
|
|
|
15863
16032
|
}
|
|
15864
16033
|
}
|
|
15865
16034
|
async function resolveProxyScript(override) {
|
|
15866
|
-
const { homedir:
|
|
15867
|
-
const { join:
|
|
16035
|
+
const { homedir: homedir7 } = await import("node:os");
|
|
16036
|
+
const { join: join9 } = await import("node:path");
|
|
15868
16037
|
const candidates = [
|
|
15869
16038
|
override,
|
|
15870
16039
|
process.env.GAD_PROXY_SCRIPT,
|
|
15871
|
-
|
|
15872
|
-
|
|
16040
|
+
join9(homedir7(), ".great-arrow", "mcp-server.mjs"),
|
|
16041
|
+
join9(process.cwd(), "scripts", "mcp-server.mjs")
|
|
15873
16042
|
].filter((c) => Boolean(c));
|
|
15874
16043
|
for (const candidate of candidates) {
|
|
15875
16044
|
if (await pathExists(candidate)) return candidate;
|
|
@@ -15893,13 +16062,13 @@ async function runProxyDiagnostics(scriptPath) {
|
|
|
15893
16062
|
}
|
|
15894
16063
|
}
|
|
15895
16064
|
async function findLegacyStores(cwd) {
|
|
15896
|
-
const { join:
|
|
16065
|
+
const { join: join9 } = await import("node:path");
|
|
15897
16066
|
const { readdir } = await import("node:fs/promises");
|
|
15898
16067
|
const dirs = /* @__PURE__ */ new Set([cwd]);
|
|
15899
16068
|
try {
|
|
15900
|
-
const worktreeRoot =
|
|
16069
|
+
const worktreeRoot = join9(cwd, ".claude", "worktrees");
|
|
15901
16070
|
for (const entry of await readdir(worktreeRoot, { withFileTypes: true })) {
|
|
15902
|
-
if (entry.isDirectory()) dirs.add(
|
|
16071
|
+
if (entry.isDirectory()) dirs.add(join9(worktreeRoot, entry.name));
|
|
15903
16072
|
}
|
|
15904
16073
|
} catch (err) {
|
|
15905
16074
|
debugSwallow("mcp.findLegacyStores(worktrees)", err);
|
|
@@ -15921,18 +16090,18 @@ async function findLegacyStores(cwd) {
|
|
|
15921
16090
|
}
|
|
15922
16091
|
const stores = [];
|
|
15923
16092
|
for (const dir of dirs) {
|
|
15924
|
-
const path10 =
|
|
16093
|
+
const path10 = join9(dir, ".mcp", OAUTH_CRED_FILENAME);
|
|
15925
16094
|
const raw = await readIfExists(path10);
|
|
15926
16095
|
if (raw !== null) stores.push({ path: path10, raw });
|
|
15927
16096
|
}
|
|
15928
16097
|
return stores;
|
|
15929
16098
|
}
|
|
15930
16099
|
async function scanConnections() {
|
|
15931
|
-
const { homedir:
|
|
15932
|
-
const { join:
|
|
15933
|
-
const home =
|
|
16100
|
+
const { homedir: homedir7 } = await import("node:os");
|
|
16101
|
+
const { join: join9 } = await import("node:path");
|
|
16102
|
+
const home = homedir7();
|
|
15934
16103
|
const hookSettings = await readIfExists(
|
|
15935
|
-
|
|
16104
|
+
join9(home, ".claude", "settings.json")
|
|
15936
16105
|
);
|
|
15937
16106
|
const hooksInstalled = hookSettings ? hasGreatArrowHooks(hookSettings) : false;
|
|
15938
16107
|
const entries = [];
|
|
@@ -15965,16 +16134,16 @@ async function probeEndpoint() {
|
|
|
15965
16134
|
}
|
|
15966
16135
|
}
|
|
15967
16136
|
async function applyMigration(plan) {
|
|
15968
|
-
const { homedir:
|
|
15969
|
-
const { join:
|
|
16137
|
+
const { homedir: homedir7 } = await import("node:os");
|
|
16138
|
+
const { join: join9 } = await import("node:path");
|
|
15970
16139
|
const { mkdir: mkdir6, rename, writeFile: writeFile5 } = await import("node:fs/promises");
|
|
15971
16140
|
const applied = [];
|
|
15972
|
-
const dir =
|
|
16141
|
+
const dir = join9(homedir7(), ".great-arrow");
|
|
15973
16142
|
await mkdir6(dir, { recursive: true, mode: 448 });
|
|
15974
16143
|
if (plan.seedFrom) {
|
|
15975
16144
|
const raw = await readIfExists(plan.seedFrom);
|
|
15976
16145
|
if (raw !== null) {
|
|
15977
|
-
const target =
|
|
16146
|
+
const target = join9(dir, OAUTH_CRED_FILENAME);
|
|
15978
16147
|
const tmp = `${target}.tmp`;
|
|
15979
16148
|
await writeFile5(tmp, raw, { mode: 384 });
|
|
15980
16149
|
await rename(tmp, target);
|
|
@@ -15984,7 +16153,7 @@ async function applyMigration(plan) {
|
|
|
15984
16153
|
if (plan.syncKeychainToFile) {
|
|
15985
16154
|
const raw = await readKeychainOnly();
|
|
15986
16155
|
if (raw) {
|
|
15987
|
-
const target =
|
|
16156
|
+
const target = join9(dir, "credential");
|
|
15988
16157
|
const tmp = `${target}.tmp`;
|
|
15989
16158
|
await writeFile5(tmp, raw, { mode: 384 });
|
|
15990
16159
|
await rename(tmp, target);
|
|
@@ -16010,19 +16179,19 @@ var doctorSubcommand = new Command("doctor").description(
|
|
|
16010
16179
|
noColor: false
|
|
16011
16180
|
});
|
|
16012
16181
|
const c = createColor(jsonFlag);
|
|
16013
|
-
const { homedir:
|
|
16014
|
-
const { join:
|
|
16015
|
-
const home =
|
|
16182
|
+
const { homedir: homedir7 } = await import("node:os");
|
|
16183
|
+
const { join: join9 } = await import("node:path");
|
|
16184
|
+
const home = homedir7();
|
|
16016
16185
|
const proxyPath = await resolveProxyScript(options.proxy);
|
|
16017
16186
|
const diagnostics = proxyPath ? await runProxyDiagnostics(proxyPath) : null;
|
|
16018
16187
|
const entries = await scanConnections();
|
|
16019
16188
|
const duplicates = detectDuplicates(entries);
|
|
16020
16189
|
const keychain = await readKeychainOnly();
|
|
16021
16190
|
const credentialFile = await readIfExists(
|
|
16022
|
-
|
|
16191
|
+
join9(home, ".great-arrow", "credential")
|
|
16023
16192
|
);
|
|
16024
16193
|
const userStore = await readIfExists(
|
|
16025
|
-
|
|
16194
|
+
join9(home, ".great-arrow", OAUTH_CRED_FILENAME)
|
|
16026
16195
|
);
|
|
16027
16196
|
const legacyStores = await findLegacyStores(process.cwd());
|
|
16028
16197
|
const findings = [
|
|
@@ -16447,8 +16616,8 @@ function askCommand() {
|
|
|
16447
16616
|
|
|
16448
16617
|
// src/lib/glance-footer.ts
|
|
16449
16618
|
import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir5 } from "node:fs/promises";
|
|
16450
|
-
import { homedir as
|
|
16451
|
-
import { join as
|
|
16619
|
+
import { homedir as homedir6 } from "node:os";
|
|
16620
|
+
import { join as join8, dirname as dirname5 } from "node:path";
|
|
16452
16621
|
|
|
16453
16622
|
// src/lib/seen.ts
|
|
16454
16623
|
var SEEN_TIMEOUT_MS = 1e3;
|
|
@@ -16835,7 +17004,7 @@ function shouldRequestTip(input) {
|
|
|
16835
17004
|
return now - state.lastTipAt >= TIP_THROTTLE_INTERVAL_MS;
|
|
16836
17005
|
}
|
|
16837
17006
|
function getGlanceStatePath() {
|
|
16838
|
-
return
|
|
17007
|
+
return join8(homedir6(), ".gad", "glance-state.json");
|
|
16839
17008
|
}
|
|
16840
17009
|
async function loadGlanceState() {
|
|
16841
17010
|
try {
|
|
@@ -19082,9 +19251,9 @@ node_default(Temp.purgeSyncAll);
|
|
|
19082
19251
|
var temp_default = Temp;
|
|
19083
19252
|
|
|
19084
19253
|
// node_modules/.pnpm/atomically@2.1.1/node_modules/atomically/dist/index.js
|
|
19085
|
-
function
|
|
19254
|
+
function writeFileSync4(filePath, data, options = DEFAULT_WRITE_OPTIONS) {
|
|
19086
19255
|
if (isString(options))
|
|
19087
|
-
return
|
|
19256
|
+
return writeFileSync4(filePath, data, { encoding: options });
|
|
19088
19257
|
const timeout2 = options.timeout ?? DEFAULT_TIMEOUT_SYNC;
|
|
19089
19258
|
const retryOptions = { timeout: timeout2 };
|
|
19090
19259
|
let tempDisposer = null;
|
|
@@ -19411,7 +19580,7 @@ var Configstore = class {
|
|
|
19411
19580
|
}
|
|
19412
19581
|
if (error.name === "SyntaxError") {
|
|
19413
19582
|
if (this._clearInvalidConfig) {
|
|
19414
|
-
|
|
19583
|
+
writeFileSync4(this._path, "", writeFileOptions);
|
|
19415
19584
|
return {};
|
|
19416
19585
|
}
|
|
19417
19586
|
throw error;
|
|
@@ -19423,7 +19592,7 @@ var Configstore = class {
|
|
|
19423
19592
|
set all(value) {
|
|
19424
19593
|
try {
|
|
19425
19594
|
import_graceful_fs.default.mkdirSync(path5.dirname(this._path), mkdirOptions);
|
|
19426
|
-
|
|
19595
|
+
writeFileSync4(this._path, JSON.stringify(value, void 0, " "), writeFileOptions);
|
|
19427
19596
|
} catch (error) {
|
|
19428
19597
|
handlePermissionError(error);
|
|
19429
19598
|
}
|
|
@@ -22130,6 +22299,7 @@ void captureCliEvent({
|
|
|
22130
22299
|
});
|
|
22131
22300
|
program2.addCommand(login_default);
|
|
22132
22301
|
program2.addCommand(logoutCommand);
|
|
22302
|
+
program2.addCommand(authCommand());
|
|
22133
22303
|
program2.addCommand(whoamiCommand());
|
|
22134
22304
|
program2.addCommand(memoryCommand);
|
|
22135
22305
|
program2.addCommand(workspace_default);
|