@great-arrow/cli 0.1.39 → 0.1.41
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 +230 -120
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -706,7 +706,7 @@ var require_graceful_fs = __commonJS({
|
|
|
706
706
|
}
|
|
707
707
|
function ReadStream$open() {
|
|
708
708
|
var that = this;
|
|
709
|
-
|
|
709
|
+
open2(that.path, that.flags, that.mode, function(err, fd) {
|
|
710
710
|
if (err) {
|
|
711
711
|
if (that.autoClose)
|
|
712
712
|
that.destroy();
|
|
@@ -726,7 +726,7 @@ var require_graceful_fs = __commonJS({
|
|
|
726
726
|
}
|
|
727
727
|
function WriteStream$open() {
|
|
728
728
|
var that = this;
|
|
729
|
-
|
|
729
|
+
open2(that.path, that.flags, that.mode, function(err, fd) {
|
|
730
730
|
if (err) {
|
|
731
731
|
that.destroy();
|
|
732
732
|
that.emit("error", err);
|
|
@@ -743,8 +743,8 @@ var require_graceful_fs = __commonJS({
|
|
|
743
743
|
return new fs7.WriteStream(path10, options);
|
|
744
744
|
}
|
|
745
745
|
var fs$open = fs7.open;
|
|
746
|
-
fs7.open =
|
|
747
|
-
function
|
|
746
|
+
fs7.open = open2;
|
|
747
|
+
function open2(path10, flags, mode, cb) {
|
|
748
748
|
if (typeof mode === "function")
|
|
749
749
|
cb = mode, mode = null;
|
|
750
750
|
return go$open(path10, flags, mode, cb);
|
|
@@ -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 join8 = __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
|
+
join8(etc, name, "config"),
|
|
1993
|
+
join8(etc, name + "rc")
|
|
1994
1994
|
].forEach(addConfigFile);
|
|
1995
1995
|
if (home)
|
|
1996
1996
|
[
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
1997
|
+
join8(home, ".config", name, "config"),
|
|
1998
|
+
join8(home, ".config", name),
|
|
1999
|
+
join8(home, "." + name, "config"),
|
|
2000
|
+
join8(home, "." + name + "rc")
|
|
2001
2001
|
].forEach(addConfigFile);
|
|
2002
2002
|
addConfigFile(cc.find("." + name + "rc"));
|
|
2003
2003
|
if (env4.config) addConfigFile(env4.config);
|
|
@@ -2680,7 +2680,7 @@ var require_graceful_fs2 = __commonJS({
|
|
|
2680
2680
|
}
|
|
2681
2681
|
function ReadStream$open() {
|
|
2682
2682
|
var that = this;
|
|
2683
|
-
|
|
2683
|
+
open2(that.path, that.flags, that.mode, function(err, fd) {
|
|
2684
2684
|
if (err) {
|
|
2685
2685
|
if (that.autoClose)
|
|
2686
2686
|
that.destroy();
|
|
@@ -2700,7 +2700,7 @@ var require_graceful_fs2 = __commonJS({
|
|
|
2700
2700
|
}
|
|
2701
2701
|
function WriteStream$open() {
|
|
2702
2702
|
var that = this;
|
|
2703
|
-
|
|
2703
|
+
open2(that.path, that.flags, that.mode, function(err, fd) {
|
|
2704
2704
|
if (err) {
|
|
2705
2705
|
that.destroy();
|
|
2706
2706
|
that.emit("error", err);
|
|
@@ -2717,8 +2717,8 @@ var require_graceful_fs2 = __commonJS({
|
|
|
2717
2717
|
return new fs7.WriteStream(path10, options);
|
|
2718
2718
|
}
|
|
2719
2719
|
var fs$open = fs7.open;
|
|
2720
|
-
fs7.open =
|
|
2721
|
-
function
|
|
2720
|
+
fs7.open = open2;
|
|
2721
|
+
function open2(path10, flags, mode, cb) {
|
|
2722
2722
|
if (typeof mode === "function")
|
|
2723
2723
|
cb = mode, mode = null;
|
|
2724
2724
|
return go$open(path10, flags, mode, cb);
|
|
@@ -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.41";
|
|
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";
|
|
@@ -10000,10 +10000,10 @@ function isColorEnabled(noColorFlag) {
|
|
|
10000
10000
|
}
|
|
10001
10001
|
function createColor(noColorFlag) {
|
|
10002
10002
|
const enabled2 = isColorEnabled(noColorFlag);
|
|
10003
|
-
const wrap = (
|
|
10003
|
+
const wrap = (open2, close) => {
|
|
10004
10004
|
return (text2) => {
|
|
10005
10005
|
if (!enabled2) return text2;
|
|
10006
|
-
return `\x1B[${
|
|
10006
|
+
return `\x1B[${open2}m${text2}\x1B[${close}m`;
|
|
10007
10007
|
};
|
|
10008
10008
|
};
|
|
10009
10009
|
return {
|
|
@@ -10306,9 +10306,68 @@ var logoutCommand = new Command("logout").description("Remove stored authenticat
|
|
|
10306
10306
|
});
|
|
10307
10307
|
|
|
10308
10308
|
// src/lib/auth.ts
|
|
10309
|
+
import { mkdir as mkdir3, open, rm, stat } from "node:fs/promises";
|
|
10310
|
+
import { homedir as homedir3 } from "node:os";
|
|
10311
|
+
import { join as join3 } from "node:path";
|
|
10309
10312
|
var DEFAULT_API_URL2 = "https://www.greatarrow.ai";
|
|
10310
10313
|
var REFRESH_SKEW_MS = 12e4;
|
|
10311
10314
|
var inflightRefresh = null;
|
|
10315
|
+
var REFRESH_LOCK_STALE_MS = 15e3;
|
|
10316
|
+
var REFRESH_LOCK_WAIT_MS = 5e3;
|
|
10317
|
+
var REFRESH_LOCK_POLL_MS = 100;
|
|
10318
|
+
function refreshLockPath() {
|
|
10319
|
+
return join3(homedir3(), ".great-arrow", "refresh.lock");
|
|
10320
|
+
}
|
|
10321
|
+
async function acquireRefreshLock() {
|
|
10322
|
+
const path10 = refreshLockPath();
|
|
10323
|
+
try {
|
|
10324
|
+
await mkdir3(join3(homedir3(), ".great-arrow"), { recursive: true });
|
|
10325
|
+
} catch (err) {
|
|
10326
|
+
debugSwallow("refresh-lock.mkdir", err);
|
|
10327
|
+
}
|
|
10328
|
+
const deadline = Date.now() + REFRESH_LOCK_WAIT_MS;
|
|
10329
|
+
for (; ; ) {
|
|
10330
|
+
try {
|
|
10331
|
+
const handle = await open(path10, "wx");
|
|
10332
|
+
await handle.writeFile(String(process.pid));
|
|
10333
|
+
await handle.close();
|
|
10334
|
+
return true;
|
|
10335
|
+
} catch (err) {
|
|
10336
|
+
if (err.code !== "EEXIST") return true;
|
|
10337
|
+
}
|
|
10338
|
+
const age = await stat(path10).then((st) => Date.now() - st.mtimeMs).catch(() => Number.POSITIVE_INFINITY);
|
|
10339
|
+
if (age > REFRESH_LOCK_STALE_MS) {
|
|
10340
|
+
try {
|
|
10341
|
+
await rm(path10, { force: true });
|
|
10342
|
+
} catch (err) {
|
|
10343
|
+
debugSwallow("refresh-lock.stale-rm", err);
|
|
10344
|
+
}
|
|
10345
|
+
continue;
|
|
10346
|
+
}
|
|
10347
|
+
if (Date.now() >= deadline) return false;
|
|
10348
|
+
await new Promise((r) => setTimeout(r, REFRESH_LOCK_POLL_MS));
|
|
10349
|
+
}
|
|
10350
|
+
}
|
|
10351
|
+
async function releaseRefreshLock() {
|
|
10352
|
+
try {
|
|
10353
|
+
await rm(refreshLockPath(), { force: true });
|
|
10354
|
+
} catch (err) {
|
|
10355
|
+
debugSwallow("refresh-lock.release", err);
|
|
10356
|
+
}
|
|
10357
|
+
}
|
|
10358
|
+
async function rotatedByAnotherProcess(ours) {
|
|
10359
|
+
let stored = null;
|
|
10360
|
+
try {
|
|
10361
|
+
stored = await loadStoredCredential();
|
|
10362
|
+
} catch (err) {
|
|
10363
|
+
debugSwallow("refresh.reread", err);
|
|
10364
|
+
}
|
|
10365
|
+
if (stored?.kind !== "oauth") return null;
|
|
10366
|
+
const theirs = stored.credential;
|
|
10367
|
+
if (theirs.refreshToken === ours.refreshToken) return null;
|
|
10368
|
+
if (Date.now() >= theirs.accessExpiresAt - REFRESH_SKEW_MS) return null;
|
|
10369
|
+
return theirs;
|
|
10370
|
+
}
|
|
10312
10371
|
async function resolveAuth() {
|
|
10313
10372
|
const config = await loadConfig();
|
|
10314
10373
|
const configApiUrl = config.api_url || DEFAULT_API_URL2;
|
|
@@ -10367,7 +10426,10 @@ async function ensureFreshAccessToken(credential) {
|
|
|
10367
10426
|
}
|
|
10368
10427
|
}
|
|
10369
10428
|
async function doRefresh(credential) {
|
|
10429
|
+
const held = await acquireRefreshLock();
|
|
10370
10430
|
try {
|
|
10431
|
+
const theirs = await rotatedByAnotherProcess(credential);
|
|
10432
|
+
if (theirs) return theirs;
|
|
10371
10433
|
const refreshed = await refreshTokens({
|
|
10372
10434
|
apiUrl: credential.apiUrl,
|
|
10373
10435
|
clientId: credential.clientId,
|
|
@@ -10381,6 +10443,8 @@ async function doRefresh(credential) {
|
|
|
10381
10443
|
throw sessionExpired();
|
|
10382
10444
|
}
|
|
10383
10445
|
throw err;
|
|
10446
|
+
} finally {
|
|
10447
|
+
if (held) await releaseRefreshLock();
|
|
10384
10448
|
}
|
|
10385
10449
|
}
|
|
10386
10450
|
function sessionExpired() {
|
|
@@ -12198,7 +12262,7 @@ var work_default = workCommand;
|
|
|
12198
12262
|
// src/commands/worktree.ts
|
|
12199
12263
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
12200
12264
|
import { existsSync, readFileSync as readFileSync2, statSync, writeFileSync } from "node:fs";
|
|
12201
|
-
import { basename, dirname as dirname3, isAbsolute, join as
|
|
12265
|
+
import { basename, dirname as dirname3, isAbsolute, join as join4, resolve } from "node:path";
|
|
12202
12266
|
var realExec = (cmd, args, opts) => {
|
|
12203
12267
|
const out = execFileSync3(cmd, args, {
|
|
12204
12268
|
cwd: opts?.cwd,
|
|
@@ -12220,9 +12284,9 @@ function parseDefaultBranch(symbolicRef) {
|
|
|
12220
12284
|
return match ? match[1] : null;
|
|
12221
12285
|
}
|
|
12222
12286
|
function detectPackageManager(repoRoot) {
|
|
12223
|
-
if (existsSync(
|
|
12224
|
-
if (existsSync(
|
|
12225
|
-
if (existsSync(
|
|
12287
|
+
if (existsSync(join4(repoRoot, "pnpm-lock.yaml"))) return "pnpm";
|
|
12288
|
+
if (existsSync(join4(repoRoot, "bun.lockb"))) return "bun";
|
|
12289
|
+
if (existsSync(join4(repoRoot, "yarn.lock"))) return "yarn";
|
|
12226
12290
|
return "npm";
|
|
12227
12291
|
}
|
|
12228
12292
|
function defaultWorktreeDir(repoRoot, branch) {
|
|
@@ -12230,7 +12294,7 @@ function defaultWorktreeDir(repoRoot, branch) {
|
|
|
12230
12294
|
/[^A-Za-z0-9._-]+/g,
|
|
12231
12295
|
"-"
|
|
12232
12296
|
);
|
|
12233
|
-
return
|
|
12297
|
+
return join4(dirname3(repoRoot), `${basename(repoRoot)}-${slug}`);
|
|
12234
12298
|
}
|
|
12235
12299
|
var AGENT_PROCESS_RE = /(^|\/)(claude|kiro|cursor|codex)/i;
|
|
12236
12300
|
function psField(pid, field) {
|
|
@@ -12253,7 +12317,7 @@ function findAgentPid(startPid) {
|
|
|
12253
12317
|
return null;
|
|
12254
12318
|
}
|
|
12255
12319
|
function ownGitDir(worktreeDir) {
|
|
12256
|
-
const dotGit =
|
|
12320
|
+
const dotGit = join4(worktreeDir, ".git");
|
|
12257
12321
|
if (!existsSync(dotGit)) return null;
|
|
12258
12322
|
if (statSync(dotGit).isDirectory()) return dotGit;
|
|
12259
12323
|
const match = readFileSync2(dotGit, "utf8").trim().match(/^gitdir:\s*(.+)$/m);
|
|
@@ -12268,7 +12332,7 @@ function stampWorktreeOwner(worktreeDir) {
|
|
|
12268
12332
|
const ownerPid = findAgentPid(process.ppid);
|
|
12269
12333
|
if (!ownerPid) return null;
|
|
12270
12334
|
writeFileSync(
|
|
12271
|
-
|
|
12335
|
+
join4(gitDir, "agent-owner.json"),
|
|
12272
12336
|
JSON.stringify(
|
|
12273
12337
|
{
|
|
12274
12338
|
ownerPid,
|
|
@@ -12362,7 +12426,7 @@ function createTaskWorktree(opts) {
|
|
|
12362
12426
|
const stampedPid = opts.stamp === false ? null : stampWorktreeOwner(dir);
|
|
12363
12427
|
const packageManager = detectPackageManager(repoRoot);
|
|
12364
12428
|
let installed = false;
|
|
12365
|
-
if (opts.install !== false && existsSync(
|
|
12429
|
+
if (opts.install !== false && existsSync(join4(repoRoot, "package.json"))) {
|
|
12366
12430
|
exec2(packageManager, ["install"], { cwd: dir, inherit: true });
|
|
12367
12431
|
installed = true;
|
|
12368
12432
|
}
|
|
@@ -12431,7 +12495,7 @@ import {
|
|
|
12431
12495
|
readFileSync as readFileSync3,
|
|
12432
12496
|
writeFileSync as writeFileSync2
|
|
12433
12497
|
} from "node:fs";
|
|
12434
|
-
import { isAbsolute as isAbsolute2, join as
|
|
12498
|
+
import { isAbsolute as isAbsolute2, join as join5, resolve as resolve2 } from "node:path";
|
|
12435
12499
|
var GUARD_MARKER = "# gad-agent-guard v1";
|
|
12436
12500
|
var SCHEMA_AUDIT_MARKER = "# gad-schema-audit v1";
|
|
12437
12501
|
var GUARD_FILE = "gad-commit-guard.mjs";
|
|
@@ -12614,22 +12678,22 @@ function installCommitGuard(opts) {
|
|
|
12614
12678
|
);
|
|
12615
12679
|
}
|
|
12616
12680
|
if (!isAbsolute2(commonDir)) commonDir = resolve2(repoRoot, commonDir);
|
|
12617
|
-
const hooksDir =
|
|
12681
|
+
const hooksDir = join5(commonDir, "hooks");
|
|
12618
12682
|
mkdirSync(hooksDir, { recursive: true });
|
|
12619
|
-
const guardPath =
|
|
12683
|
+
const guardPath = join5(hooksDir, GUARD_FILE);
|
|
12620
12684
|
writeFileSync2(guardPath, buildGuardScript());
|
|
12621
12685
|
chmodSync(guardPath, 493);
|
|
12622
|
-
const huskyHook =
|
|
12623
|
-
const hookPath = existsSync2(huskyHook) ? huskyHook :
|
|
12686
|
+
const huskyHook = join5(repoRoot, ".husky", "pre-commit");
|
|
12687
|
+
const hookPath = existsSync2(huskyHook) ? huskyHook : join5(hooksDir, "pre-commit");
|
|
12624
12688
|
const existing = existsSync2(hookPath) ? readFileSync3(hookPath, "utf8") : null;
|
|
12625
12689
|
const plan = planHookInstall(existing);
|
|
12626
12690
|
if (plan.action !== "noop") {
|
|
12627
12691
|
writeFileSync2(hookPath, plan.content);
|
|
12628
12692
|
}
|
|
12629
12693
|
chmodSync(hookPath, 493);
|
|
12630
|
-
const huskyDir =
|
|
12631
|
-
const huskyPrePush =
|
|
12632
|
-
const schemaAuditHookPath = existsSync2(huskyPrePush) || existsSync2(huskyDir) ? huskyPrePush :
|
|
12694
|
+
const huskyDir = join5(repoRoot, ".husky");
|
|
12695
|
+
const huskyPrePush = join5(huskyDir, "pre-push");
|
|
12696
|
+
const schemaAuditHookPath = existsSync2(huskyPrePush) || existsSync2(huskyDir) ? huskyPrePush : join5(hooksDir, "pre-push");
|
|
12633
12697
|
const existingSchemaAuditHook = existsSync2(schemaAuditHookPath) ? readFileSync3(schemaAuditHookPath, "utf8") : null;
|
|
12634
12698
|
const schemaAuditPlan = planSchemaAuditHookInstall(existingSchemaAuditHook);
|
|
12635
12699
|
if (schemaAuditPlan.action !== "noop") {
|
|
@@ -12752,9 +12816,9 @@ function guardrailsCommand() {
|
|
|
12752
12816
|
|
|
12753
12817
|
// src/commands/doctor.ts
|
|
12754
12818
|
import { existsSync as existsSync3 } from "node:fs";
|
|
12755
|
-
import { copyFile, mkdir as
|
|
12756
|
-
import { homedir as
|
|
12757
|
-
import { dirname as dirname4, join as
|
|
12819
|
+
import { copyFile, mkdir as mkdir4, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
|
|
12820
|
+
import { homedir as homedir4 } from "node:os";
|
|
12821
|
+
import { dirname as dirname4, join as join6 } from "node:path";
|
|
12758
12822
|
|
|
12759
12823
|
// src/lib/codex-config.ts
|
|
12760
12824
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
@@ -13543,6 +13607,53 @@ function inspectConfiguredHooks(hooks, deps) {
|
|
|
13543
13607
|
|
|
13544
13608
|
// src/lib/mcp-doctor.ts
|
|
13545
13609
|
import { createHash as createHash2 } from "node:crypto";
|
|
13610
|
+
|
|
13611
|
+
// src/lib/mcp-target.ts
|
|
13612
|
+
var GREAT_ARROW_HOSTS = /* @__PURE__ */ new Set([
|
|
13613
|
+
"greatarrow.ai",
|
|
13614
|
+
"www.greatarrow.ai",
|
|
13615
|
+
"greatarrowdigital.com",
|
|
13616
|
+
"www.greatarrowdigital.com"
|
|
13617
|
+
]);
|
|
13618
|
+
function isGreatArrowEndpoint(value) {
|
|
13619
|
+
if (typeof value !== "string") return false;
|
|
13620
|
+
try {
|
|
13621
|
+
const url = new URL(value);
|
|
13622
|
+
return (url.protocol === "https:" || url.protocol === "http:") && GREAT_ARROW_HOSTS.has(url.hostname) && /^\/api\/mcp\/?$/.test(url.pathname);
|
|
13623
|
+
} catch {
|
|
13624
|
+
return false;
|
|
13625
|
+
}
|
|
13626
|
+
}
|
|
13627
|
+
function isGreatArrowExecutable(value) {
|
|
13628
|
+
if (typeof value !== "string") return false;
|
|
13629
|
+
return /^@great-arrow\/(?:cli|mcp-server)(?:@[^\s]+)?$/.test(value) || /(?:^|[/\\])(?:\.great-arrow|great-arrow-digital[/\\]scripts)[/\\]mcp-server\.mjs$/.test(
|
|
13630
|
+
value
|
|
13631
|
+
);
|
|
13632
|
+
}
|
|
13633
|
+
function tomlString(raw) {
|
|
13634
|
+
if (raw.startsWith("'")) return raw.slice(1, -1);
|
|
13635
|
+
try {
|
|
13636
|
+
const value = JSON.parse(raw);
|
|
13637
|
+
return typeof value === "string" ? value : void 0;
|
|
13638
|
+
} catch {
|
|
13639
|
+
return void 0;
|
|
13640
|
+
}
|
|
13641
|
+
}
|
|
13642
|
+
function codexTransportFields(body) {
|
|
13643
|
+
const entry = {};
|
|
13644
|
+
for (const match of body.matchAll(
|
|
13645
|
+
/^\s*(url|command)\s*=\s*("(?:\\.|[^"\\\r\n])*"|'[^'\r\n]*')/gm
|
|
13646
|
+
)) {
|
|
13647
|
+
entry[match[1]] = tomlString(match[2]);
|
|
13648
|
+
}
|
|
13649
|
+
const args = body.match(/^\s*args\s*=\s*\[([\s\S]*?)\]/m)?.[1];
|
|
13650
|
+
if (args !== void 0) {
|
|
13651
|
+
entry.args = [...args.matchAll(/"(?:\\.|[^"\\])*"|'[^']*'|#[^\r\n]*/g)].filter((match) => !match[0].startsWith("#")).map((match) => tomlString(match[0]));
|
|
13652
|
+
}
|
|
13653
|
+
return entry;
|
|
13654
|
+
}
|
|
13655
|
+
|
|
13656
|
+
// src/lib/mcp-doctor.ts
|
|
13546
13657
|
var MCP_FAILURE_MESSAGE = {
|
|
13547
13658
|
auth: "MCP rejected this machine's credential (401/403)",
|
|
13548
13659
|
network: "Could not reach the MCP endpoint",
|
|
@@ -13665,21 +13776,17 @@ function knownConfigLocations(home, cwd, platform = process.platform, appData) {
|
|
|
13665
13776
|
];
|
|
13666
13777
|
}
|
|
13667
13778
|
var GREAT_ARROW_NAME = /great[-_ ]?arrow|ai[-_]memory/i;
|
|
13668
|
-
var GREAT_ARROW_REF = /great[-_ ]?arrow|greatarrow|greatarrowdigital/i;
|
|
13669
13779
|
function asObject2(value) {
|
|
13670
13780
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
13671
13781
|
}
|
|
13672
13782
|
function isGreatArrowServer(name, entry) {
|
|
13673
13783
|
if (GREAT_ARROW_NAME.test(name)) return true;
|
|
13674
|
-
|
|
13675
|
-
|
|
13676
|
-
|
|
13677
|
-
|
|
13678
|
-
|
|
13679
|
-
|
|
13680
|
-
entry.env
|
|
13681
|
-
]);
|
|
13682
|
-
return GREAT_ARROW_REF.test(target);
|
|
13784
|
+
if ([entry.url, entry.httpUrl, entry.serverUrl].some(isGreatArrowEndpoint)) {
|
|
13785
|
+
return true;
|
|
13786
|
+
}
|
|
13787
|
+
return [entry.command, ...Array.isArray(entry.args) ? entry.args : []].some(
|
|
13788
|
+
isGreatArrowExecutable
|
|
13789
|
+
);
|
|
13683
13790
|
}
|
|
13684
13791
|
function classifySurface(entry, clientId, hooksInstalled) {
|
|
13685
13792
|
if (typeof entry.command === "string" && entry.command.length > 0) {
|
|
@@ -13706,15 +13813,18 @@ function serverMapsFromJson(parsed, serversKey) {
|
|
|
13706
13813
|
}
|
|
13707
13814
|
function findCodexEntries(location, content) {
|
|
13708
13815
|
const entries = [];
|
|
13709
|
-
const sections = content.split(/^\s*\[
|
|
13816
|
+
const sections = content.split(/^\s*\[/m).slice(1);
|
|
13710
13817
|
const seen = /* @__PURE__ */ new Set();
|
|
13711
13818
|
for (const raw of sections) {
|
|
13712
13819
|
const header = raw.slice(0, raw.indexOf("]"));
|
|
13713
|
-
const match = header.match(
|
|
13714
|
-
|
|
13820
|
+
const match = header.match(
|
|
13821
|
+
/^mcp_servers\.(?:"([^"]+)"|'([^']+)'|([^.\s\]]+))$/
|
|
13822
|
+
);
|
|
13823
|
+
const name = match?.[1] ?? match?.[2] ?? match?.[3];
|
|
13715
13824
|
if (!name || seen.has(name)) continue;
|
|
13716
13825
|
const body = raw.slice(raw.indexOf("]") + 1);
|
|
13717
|
-
|
|
13826
|
+
const transport = codexTransportFields(body);
|
|
13827
|
+
if (!isGreatArrowServer(name, transport)) continue;
|
|
13718
13828
|
seen.add(name);
|
|
13719
13829
|
entries.push({
|
|
13720
13830
|
clientId: location.clientId,
|
|
@@ -13722,7 +13832,7 @@ function findCodexEntries(location, content) {
|
|
|
13722
13832
|
scope: location.scope,
|
|
13723
13833
|
path: location.path,
|
|
13724
13834
|
serverName: name,
|
|
13725
|
-
surface:
|
|
13835
|
+
surface: typeof transport.command === "string" ? "stdio" : "http"
|
|
13726
13836
|
});
|
|
13727
13837
|
}
|
|
13728
13838
|
return entries;
|
|
@@ -14239,7 +14349,7 @@ async function checkMcp(auth) {
|
|
|
14239
14349
|
}
|
|
14240
14350
|
}
|
|
14241
14351
|
function defaultCodexConfigPath() {
|
|
14242
|
-
return
|
|
14352
|
+
return join6(homedir4(), ".codex", "config.toml");
|
|
14243
14353
|
}
|
|
14244
14354
|
function codexIssuesToChecks(issues) {
|
|
14245
14355
|
return issues.map((issue) => {
|
|
@@ -14283,7 +14393,7 @@ function codexCommand() {
|
|
|
14283
14393
|
if (options.enforce) {
|
|
14284
14394
|
const apiUrl = extractCodexGreatArrowApiUrl(content) ?? (await resolveAuth()).apiUrl;
|
|
14285
14395
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
14286
|
-
await
|
|
14396
|
+
await mkdir4(dirname4(configPath), { recursive: true });
|
|
14287
14397
|
if (content.trim()) {
|
|
14288
14398
|
backupPath = `${configPath}.bak.${timestamp}`;
|
|
14289
14399
|
await copyFile(configPath, backupPath);
|
|
@@ -14377,12 +14487,12 @@ function claudeCommand() {
|
|
|
14377
14487
|
isTTY: isTTY(),
|
|
14378
14488
|
noColor: g.noColor
|
|
14379
14489
|
});
|
|
14380
|
-
const home =
|
|
14381
|
-
const gaDir =
|
|
14382
|
-
const userConfigPath =
|
|
14383
|
-
const settingsPath =
|
|
14384
|
-
const hookConfigPath =
|
|
14385
|
-
const glanceHookPath =
|
|
14490
|
+
const home = homedir4();
|
|
14491
|
+
const gaDir = join6(home, ".great-arrow");
|
|
14492
|
+
const userConfigPath = join6(home, ".claude.json");
|
|
14493
|
+
const settingsPath = join6(home, ".claude", "settings.json");
|
|
14494
|
+
const hookConfigPath = join6(gaDir, "hook-config.json");
|
|
14495
|
+
const glanceHookPath = join6(gaDir, "claude-glance-hook.mjs");
|
|
14386
14496
|
const checks = [];
|
|
14387
14497
|
const repairs = [];
|
|
14388
14498
|
const backups = [];
|
|
@@ -14404,7 +14514,7 @@ function claudeCommand() {
|
|
|
14404
14514
|
await copyFile(path10, backupPath);
|
|
14405
14515
|
backups.push(backupPath);
|
|
14406
14516
|
}
|
|
14407
|
-
await
|
|
14517
|
+
await mkdir4(dirname4(path10), { recursive: true });
|
|
14408
14518
|
await writeFile3(path10, content, "utf8");
|
|
14409
14519
|
};
|
|
14410
14520
|
let auth = null;
|
|
@@ -14451,7 +14561,7 @@ function claudeCommand() {
|
|
|
14451
14561
|
{ signal: AbortSignal.timeout(1e4) }
|
|
14452
14562
|
);
|
|
14453
14563
|
if (res.ok) {
|
|
14454
|
-
await
|
|
14564
|
+
await mkdir4(gaDir, { recursive: true });
|
|
14455
14565
|
await writeFile3(glanceHookPath, await res.text(), {
|
|
14456
14566
|
mode: 493
|
|
14457
14567
|
});
|
|
@@ -14590,8 +14700,8 @@ function claudeCommand() {
|
|
|
14590
14700
|
file: "/Library/Application Support/ClaudeCode/managed-settings.json"
|
|
14591
14701
|
},
|
|
14592
14702
|
{ scope: "user", file: settingsPath },
|
|
14593
|
-
{ scope: "project", file:
|
|
14594
|
-
{ scope: "local", file:
|
|
14703
|
+
{ scope: "project", file: join6(cwd, ".claude", "settings.json") },
|
|
14704
|
+
{ scope: "local", file: join6(cwd, ".claude", "settings.local.json") }
|
|
14595
14705
|
];
|
|
14596
14706
|
const configured = [];
|
|
14597
14707
|
for (const { scope, file } of scopes) {
|
|
@@ -14660,12 +14770,12 @@ function claudeCommand() {
|
|
|
14660
14770
|
});
|
|
14661
14771
|
}
|
|
14662
14772
|
function defaultJsonClientConfigs() {
|
|
14663
|
-
const home =
|
|
14773
|
+
const home = homedir4();
|
|
14664
14774
|
return [
|
|
14665
|
-
{ name: "Claude Code", path:
|
|
14666
|
-
{ name: "Cursor", path:
|
|
14667
|
-
{ name: "Kiro", path:
|
|
14668
|
-
{ name: "Gemini CLI", path:
|
|
14775
|
+
{ name: "Claude Code", path: join6(home, ".claude.json") },
|
|
14776
|
+
{ name: "Cursor", path: join6(home, ".cursor", "mcp.json") },
|
|
14777
|
+
{ name: "Kiro", path: join6(home, ".kiro", "settings", "mcp.json") },
|
|
14778
|
+
{ name: "Gemini CLI", path: join6(home, ".gemini", "settings.json") }
|
|
14669
14779
|
];
|
|
14670
14780
|
}
|
|
14671
14781
|
function clientsCommand() {
|
|
@@ -15311,14 +15421,14 @@ async function pathExists(path10) {
|
|
|
15311
15421
|
}
|
|
15312
15422
|
}
|
|
15313
15423
|
async function installCodexConfig(apiUrl, token, repoUrl) {
|
|
15314
|
-
const { homedir:
|
|
15315
|
-
const { join:
|
|
15316
|
-
const { chmod, copyFile: copyFile2, mkdir:
|
|
15317
|
-
const codexDir =
|
|
15318
|
-
const configPath =
|
|
15319
|
-
const envPath =
|
|
15424
|
+
const { homedir: homedir6 } = await import("node:os");
|
|
15425
|
+
const { join: join8 } = await import("node:path");
|
|
15426
|
+
const { chmod, copyFile: copyFile2, mkdir: mkdir6, readFile: readFile5, writeFile: writeFile5 } = await import("node:fs/promises");
|
|
15427
|
+
const codexDir = join8(homedir6(), ".codex");
|
|
15428
|
+
const configPath = join8(codexDir, "config.toml");
|
|
15429
|
+
const envPath = join8(codexDir, ".env");
|
|
15320
15430
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
15321
|
-
await
|
|
15431
|
+
await mkdir6(codexDir, { recursive: true });
|
|
15322
15432
|
const existingConfig = await pathExists(configPath) ? await readFile5(configPath, "utf8") : "";
|
|
15323
15433
|
if (existingConfig.trim()) {
|
|
15324
15434
|
await copyFile2(configPath, `${configPath}.bak.${timestamp}`);
|
|
@@ -15614,12 +15724,12 @@ var installCommand = new Command("install").description("Generate MCP configurat
|
|
|
15614
15724
|
process.stdout.write(configJson2 + "\n");
|
|
15615
15725
|
return;
|
|
15616
15726
|
}
|
|
15617
|
-
const { homedir:
|
|
15618
|
-
const { join:
|
|
15619
|
-
const { mkdir:
|
|
15620
|
-
const geminiDir =
|
|
15621
|
-
const mcpPath =
|
|
15622
|
-
await
|
|
15727
|
+
const { homedir: homedir6 } = await import("node:os");
|
|
15728
|
+
const { join: join9 } = await import("node:path");
|
|
15729
|
+
const { mkdir: mkdir6, readFile: readFile5, writeFile: writeFile6 } = await import("node:fs/promises");
|
|
15730
|
+
const geminiDir = join9(homedir6(), ".gemini");
|
|
15731
|
+
const mcpPath = join9(geminiDir, "settings.json");
|
|
15732
|
+
await mkdir6(geminiDir, { recursive: true });
|
|
15623
15733
|
let existingConfig = {};
|
|
15624
15734
|
try {
|
|
15625
15735
|
const content = await readFile5(mcpPath, "utf-8");
|
|
@@ -15640,14 +15750,14 @@ var installCommand = new Command("install").description("Generate MCP configurat
|
|
|
15640
15750
|
"utf-8"
|
|
15641
15751
|
);
|
|
15642
15752
|
fmt.success(`Wrote gemini MCP config to ${mcpPath}`);
|
|
15643
|
-
const agyMcpDir =
|
|
15753
|
+
const agyMcpDir = join9(
|
|
15644
15754
|
geminiDir,
|
|
15645
15755
|
"antigravity-cli",
|
|
15646
15756
|
"mcp",
|
|
15647
15757
|
MCP_SERVER_NAME
|
|
15648
15758
|
);
|
|
15649
|
-
await
|
|
15650
|
-
const instructionsPath =
|
|
15759
|
+
await mkdir6(agyMcpDir, { recursive: true });
|
|
15760
|
+
const instructionsPath = join9(agyMcpDir, "instructions.md");
|
|
15651
15761
|
const instructionsContent = `You are connected to greatarrow.ai - the user's private workspace memory + integrations brain.
|
|
15652
15762
|
|
|
15653
15763
|
CRITICAL DIRECTIVE (MANDATORY STANDARD):
|
|
@@ -15679,8 +15789,8 @@ Always assume full autonomy to leverage these tools to their maximum extent.`;
|
|
|
15679
15789
|
return;
|
|
15680
15790
|
}
|
|
15681
15791
|
const { writeFile: writeFile5 } = await import("node:fs/promises");
|
|
15682
|
-
const { join:
|
|
15683
|
-
const outputPath =
|
|
15792
|
+
const { join: join8 } = await import("node:path");
|
|
15793
|
+
const outputPath = join8(process.cwd(), ".mcp.json");
|
|
15684
15794
|
await writeFile5(outputPath, configJson + "\n", { mode: 384 });
|
|
15685
15795
|
fmt.success(`Wrote ${clientName} MCP config to .mcp.json`);
|
|
15686
15796
|
if (await mcpJsonAtRiskOfCommit(process.cwd())) {
|
|
@@ -15711,13 +15821,13 @@ async function readKeychainOnly() {
|
|
|
15711
15821
|
}
|
|
15712
15822
|
}
|
|
15713
15823
|
async function resolveProxyScript(override) {
|
|
15714
|
-
const { homedir:
|
|
15715
|
-
const { join:
|
|
15824
|
+
const { homedir: homedir6 } = await import("node:os");
|
|
15825
|
+
const { join: join8 } = await import("node:path");
|
|
15716
15826
|
const candidates = [
|
|
15717
15827
|
override,
|
|
15718
15828
|
process.env.GAD_PROXY_SCRIPT,
|
|
15719
|
-
|
|
15720
|
-
|
|
15829
|
+
join8(homedir6(), ".great-arrow", "mcp-server.mjs"),
|
|
15830
|
+
join8(process.cwd(), "scripts", "mcp-server.mjs")
|
|
15721
15831
|
].filter((c) => Boolean(c));
|
|
15722
15832
|
for (const candidate of candidates) {
|
|
15723
15833
|
if (await pathExists(candidate)) return candidate;
|
|
@@ -15741,13 +15851,13 @@ async function runProxyDiagnostics(scriptPath) {
|
|
|
15741
15851
|
}
|
|
15742
15852
|
}
|
|
15743
15853
|
async function findLegacyStores(cwd) {
|
|
15744
|
-
const { join:
|
|
15854
|
+
const { join: join8 } = await import("node:path");
|
|
15745
15855
|
const { readdir } = await import("node:fs/promises");
|
|
15746
15856
|
const dirs = /* @__PURE__ */ new Set([cwd]);
|
|
15747
15857
|
try {
|
|
15748
|
-
const worktreeRoot =
|
|
15858
|
+
const worktreeRoot = join8(cwd, ".claude", "worktrees");
|
|
15749
15859
|
for (const entry of await readdir(worktreeRoot, { withFileTypes: true })) {
|
|
15750
|
-
if (entry.isDirectory()) dirs.add(
|
|
15860
|
+
if (entry.isDirectory()) dirs.add(join8(worktreeRoot, entry.name));
|
|
15751
15861
|
}
|
|
15752
15862
|
} catch (err) {
|
|
15753
15863
|
debugSwallow("mcp.findLegacyStores(worktrees)", err);
|
|
@@ -15769,18 +15879,18 @@ async function findLegacyStores(cwd) {
|
|
|
15769
15879
|
}
|
|
15770
15880
|
const stores = [];
|
|
15771
15881
|
for (const dir of dirs) {
|
|
15772
|
-
const path10 =
|
|
15882
|
+
const path10 = join8(dir, ".mcp", OAUTH_CRED_FILENAME);
|
|
15773
15883
|
const raw = await readIfExists(path10);
|
|
15774
15884
|
if (raw !== null) stores.push({ path: path10, raw });
|
|
15775
15885
|
}
|
|
15776
15886
|
return stores;
|
|
15777
15887
|
}
|
|
15778
15888
|
async function scanConnections() {
|
|
15779
|
-
const { homedir:
|
|
15780
|
-
const { join:
|
|
15781
|
-
const home =
|
|
15889
|
+
const { homedir: homedir6 } = await import("node:os");
|
|
15890
|
+
const { join: join8 } = await import("node:path");
|
|
15891
|
+
const home = homedir6();
|
|
15782
15892
|
const hookSettings = await readIfExists(
|
|
15783
|
-
|
|
15893
|
+
join8(home, ".claude", "settings.json")
|
|
15784
15894
|
);
|
|
15785
15895
|
const hooksInstalled = hookSettings ? hasGreatArrowHooks(hookSettings) : false;
|
|
15786
15896
|
const entries = [];
|
|
@@ -15813,16 +15923,16 @@ async function probeEndpoint() {
|
|
|
15813
15923
|
}
|
|
15814
15924
|
}
|
|
15815
15925
|
async function applyMigration(plan) {
|
|
15816
|
-
const { homedir:
|
|
15817
|
-
const { join:
|
|
15818
|
-
const { mkdir:
|
|
15926
|
+
const { homedir: homedir6 } = await import("node:os");
|
|
15927
|
+
const { join: join8 } = await import("node:path");
|
|
15928
|
+
const { mkdir: mkdir6, rename, writeFile: writeFile5 } = await import("node:fs/promises");
|
|
15819
15929
|
const applied = [];
|
|
15820
|
-
const dir =
|
|
15821
|
-
await
|
|
15930
|
+
const dir = join8(homedir6(), ".great-arrow");
|
|
15931
|
+
await mkdir6(dir, { recursive: true, mode: 448 });
|
|
15822
15932
|
if (plan.seedFrom) {
|
|
15823
15933
|
const raw = await readIfExists(plan.seedFrom);
|
|
15824
15934
|
if (raw !== null) {
|
|
15825
|
-
const target =
|
|
15935
|
+
const target = join8(dir, OAUTH_CRED_FILENAME);
|
|
15826
15936
|
const tmp = `${target}.tmp`;
|
|
15827
15937
|
await writeFile5(tmp, raw, { mode: 384 });
|
|
15828
15938
|
await rename(tmp, target);
|
|
@@ -15832,7 +15942,7 @@ async function applyMigration(plan) {
|
|
|
15832
15942
|
if (plan.syncKeychainToFile) {
|
|
15833
15943
|
const raw = await readKeychainOnly();
|
|
15834
15944
|
if (raw) {
|
|
15835
|
-
const target =
|
|
15945
|
+
const target = join8(dir, "credential");
|
|
15836
15946
|
const tmp = `${target}.tmp`;
|
|
15837
15947
|
await writeFile5(tmp, raw, { mode: 384 });
|
|
15838
15948
|
await rename(tmp, target);
|
|
@@ -15858,19 +15968,19 @@ var doctorSubcommand = new Command("doctor").description(
|
|
|
15858
15968
|
noColor: false
|
|
15859
15969
|
});
|
|
15860
15970
|
const c = createColor(jsonFlag);
|
|
15861
|
-
const { homedir:
|
|
15862
|
-
const { join:
|
|
15863
|
-
const home =
|
|
15971
|
+
const { homedir: homedir6 } = await import("node:os");
|
|
15972
|
+
const { join: join8 } = await import("node:path");
|
|
15973
|
+
const home = homedir6();
|
|
15864
15974
|
const proxyPath = await resolveProxyScript(options.proxy);
|
|
15865
15975
|
const diagnostics = proxyPath ? await runProxyDiagnostics(proxyPath) : null;
|
|
15866
15976
|
const entries = await scanConnections();
|
|
15867
15977
|
const duplicates = detectDuplicates(entries);
|
|
15868
15978
|
const keychain = await readKeychainOnly();
|
|
15869
15979
|
const credentialFile = await readIfExists(
|
|
15870
|
-
|
|
15980
|
+
join8(home, ".great-arrow", "credential")
|
|
15871
15981
|
);
|
|
15872
15982
|
const userStore = await readIfExists(
|
|
15873
|
-
|
|
15983
|
+
join8(home, ".great-arrow", OAUTH_CRED_FILENAME)
|
|
15874
15984
|
);
|
|
15875
15985
|
const legacyStores = await findLegacyStores(process.cwd());
|
|
15876
15986
|
const findings = [
|
|
@@ -16287,9 +16397,9 @@ function askCommand() {
|
|
|
16287
16397
|
}
|
|
16288
16398
|
|
|
16289
16399
|
// src/lib/glance-footer.ts
|
|
16290
|
-
import { readFile as readFile4, writeFile as writeFile4, mkdir as
|
|
16291
|
-
import { homedir as
|
|
16292
|
-
import { join as
|
|
16400
|
+
import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir5 } from "node:fs/promises";
|
|
16401
|
+
import { homedir as homedir5 } from "node:os";
|
|
16402
|
+
import { join as join7, dirname as dirname5 } from "node:path";
|
|
16293
16403
|
|
|
16294
16404
|
// src/lib/seen.ts
|
|
16295
16405
|
var SEEN_TIMEOUT_MS = 1e3;
|
|
@@ -16619,7 +16729,7 @@ function shouldRequestTip(input) {
|
|
|
16619
16729
|
return now - state.lastTipAt >= TIP_THROTTLE_INTERVAL_MS;
|
|
16620
16730
|
}
|
|
16621
16731
|
function getGlanceStatePath() {
|
|
16622
|
-
return
|
|
16732
|
+
return join7(homedir5(), ".gad", "glance-state.json");
|
|
16623
16733
|
}
|
|
16624
16734
|
async function loadGlanceState() {
|
|
16625
16735
|
try {
|
|
@@ -16635,7 +16745,7 @@ async function loadGlanceState() {
|
|
|
16635
16745
|
}
|
|
16636
16746
|
async function saveGlanceState(state) {
|
|
16637
16747
|
const path10 = getGlanceStatePath();
|
|
16638
|
-
await
|
|
16748
|
+
await mkdir5(dirname5(path10), { recursive: true });
|
|
16639
16749
|
await writeFile4(path10, JSON.stringify(state), "utf-8");
|
|
16640
16750
|
}
|
|
16641
16751
|
function glanceItemUrl(href, apiUrl) {
|
|
@@ -19680,18 +19790,18 @@ var proto = Object.defineProperties(() => {
|
|
|
19680
19790
|
}
|
|
19681
19791
|
}
|
|
19682
19792
|
});
|
|
19683
|
-
var createStyler = (
|
|
19793
|
+
var createStyler = (open2, close, parent) => {
|
|
19684
19794
|
let openAll;
|
|
19685
19795
|
let closeAll;
|
|
19686
19796
|
if (parent === void 0) {
|
|
19687
|
-
openAll =
|
|
19797
|
+
openAll = open2;
|
|
19688
19798
|
closeAll = close;
|
|
19689
19799
|
} else {
|
|
19690
|
-
openAll = parent.openAll +
|
|
19800
|
+
openAll = parent.openAll + open2;
|
|
19691
19801
|
closeAll = close + parent.closeAll;
|
|
19692
19802
|
}
|
|
19693
19803
|
return {
|
|
19694
|
-
open,
|
|
19804
|
+
open: open2,
|
|
19695
19805
|
close,
|
|
19696
19806
|
openAll,
|
|
19697
19807
|
closeAll,
|