@great-arrow/cli 0.1.52 → 0.1.54
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 +348 -76
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9402,7 +9402,7 @@ function isNodeError(value) {
|
|
|
9402
9402
|
|
|
9403
9403
|
// src/lib/version.ts
|
|
9404
9404
|
var CLI_PACKAGE_NAME = "@great-arrow/cli";
|
|
9405
|
-
var CLI_VERSION = "0.1.
|
|
9405
|
+
var CLI_VERSION = "0.1.54";
|
|
9406
9406
|
var GAD_INSTALL_VERSION = "2026.08.08";
|
|
9407
9407
|
var GAD_INSTALL_MIN_VERSION = "2026.06.22";
|
|
9408
9408
|
var GAD_INSTALL_HEADER = "X-GAD-Install-Version";
|
|
@@ -9411,6 +9411,9 @@ var GAD_CLI_VERSION_HEADER = "X-GAD-CLI-Version";
|
|
|
9411
9411
|
// src/commands/login.ts
|
|
9412
9412
|
import { execFile } from "node:child_process";
|
|
9413
9413
|
|
|
9414
|
+
// src/lib/credentials.ts
|
|
9415
|
+
import { randomUUID } from "node:crypto";
|
|
9416
|
+
|
|
9414
9417
|
// src/lib/keychain.ts
|
|
9415
9418
|
import { mkdir, writeFile, readFile, unlink } from "node:fs/promises";
|
|
9416
9419
|
import { homedir } from "node:os";
|
|
@@ -9532,7 +9535,12 @@ async function loadStoredCredential() {
|
|
|
9532
9535
|
return parseStoredValue(await getToken());
|
|
9533
9536
|
}
|
|
9534
9537
|
async function saveOAuthCredential(credential) {
|
|
9535
|
-
return setToken(
|
|
9538
|
+
return setToken(
|
|
9539
|
+
JSON.stringify({
|
|
9540
|
+
...credential,
|
|
9541
|
+
localSessionId: credential.localSessionId || randomUUID()
|
|
9542
|
+
})
|
|
9543
|
+
);
|
|
9536
9544
|
}
|
|
9537
9545
|
async function savePatToken(token) {
|
|
9538
9546
|
return setToken(token);
|
|
@@ -9903,14 +9911,33 @@ function toCredential(env4, apiUrl, clientId, now) {
|
|
|
9903
9911
|
}
|
|
9904
9912
|
var TOKEN_POST_TIMEOUT_MS = 8e3;
|
|
9905
9913
|
async function postToken(apiUrl, form, fetchImpl, timeoutMs = TOKEN_POST_TIMEOUT_MS) {
|
|
9906
|
-
const
|
|
9907
|
-
|
|
9908
|
-
|
|
9909
|
-
|
|
9910
|
-
|
|
9914
|
+
const controller = new AbortController();
|
|
9915
|
+
let timer;
|
|
9916
|
+
const deadline = new Promise((_resolve, reject) => {
|
|
9917
|
+
timer = setTimeout(() => {
|
|
9918
|
+
const error = new DOMException(
|
|
9919
|
+
"Token exchange timed out.",
|
|
9920
|
+
"TimeoutError"
|
|
9921
|
+
);
|
|
9922
|
+
controller.abort(error);
|
|
9923
|
+
reject(error);
|
|
9924
|
+
}, timeoutMs);
|
|
9911
9925
|
});
|
|
9912
|
-
const
|
|
9913
|
-
|
|
9926
|
+
const request = async () => {
|
|
9927
|
+
const res = await fetchImpl(`${trimSlash2(apiUrl)}/api/oauth/token`, {
|
|
9928
|
+
method: "POST",
|
|
9929
|
+
headers: TOKEN_HEADERS,
|
|
9930
|
+
body: new URLSearchParams(form).toString(),
|
|
9931
|
+
signal: controller.signal
|
|
9932
|
+
});
|
|
9933
|
+
const json = await res.json().catch(() => ({}));
|
|
9934
|
+
return { ok: res.ok, status: res.status, json };
|
|
9935
|
+
};
|
|
9936
|
+
try {
|
|
9937
|
+
return await Promise.race([request(), deadline]);
|
|
9938
|
+
} finally {
|
|
9939
|
+
if (timer) clearTimeout(timer);
|
|
9940
|
+
}
|
|
9914
9941
|
}
|
|
9915
9942
|
async function exchangeCode(opts) {
|
|
9916
9943
|
const now = opts.now ?? Date.now();
|
|
@@ -10364,6 +10391,20 @@ var login_default = loginCommand;
|
|
|
10364
10391
|
import { mkdir as mkdir3, open, rm, stat } from "node:fs/promises";
|
|
10365
10392
|
import { homedir as homedir4 } from "node:os";
|
|
10366
10393
|
import { join as join4 } from "node:path";
|
|
10394
|
+
|
|
10395
|
+
// src/lib/oauth/session-identity.ts
|
|
10396
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
10397
|
+
function credentialSessionId(credential) {
|
|
10398
|
+
return credential.localSessionId || createHash2("sha256").update(
|
|
10399
|
+
JSON.stringify([
|
|
10400
|
+
credential.clientId,
|
|
10401
|
+
credential.apiUrl,
|
|
10402
|
+
credential.refreshToken
|
|
10403
|
+
])
|
|
10404
|
+
).digest("hex");
|
|
10405
|
+
}
|
|
10406
|
+
|
|
10407
|
+
// src/lib/auth.ts
|
|
10367
10408
|
var REFRESH_SKEW_MS = 12e4;
|
|
10368
10409
|
var inflightRefresh = null;
|
|
10369
10410
|
var REFRESH_LOCK_STALE_MS = 15e3;
|
|
@@ -10387,7 +10428,12 @@ async function acquireRefreshLock() {
|
|
|
10387
10428
|
await handle.close();
|
|
10388
10429
|
return true;
|
|
10389
10430
|
} catch (err) {
|
|
10390
|
-
if (err.code !== "EEXIST")
|
|
10431
|
+
if (err.code !== "EEXIST") {
|
|
10432
|
+
throw networkError(
|
|
10433
|
+
"Could not lock session renewal.",
|
|
10434
|
+
"Check local credential storage and retry; your session has been kept."
|
|
10435
|
+
);
|
|
10436
|
+
}
|
|
10391
10437
|
}
|
|
10392
10438
|
const age = await stat(path10).then((st) => Date.now() - st.mtimeMs).catch(() => Number.POSITIVE_INFINITY);
|
|
10393
10439
|
if (age > REFRESH_LOCK_STALE_MS) {
|
|
@@ -10416,8 +10462,13 @@ async function storedPairOtherThan(ours) {
|
|
|
10416
10462
|
} catch (err) {
|
|
10417
10463
|
debugSwallow("refresh.reread", err);
|
|
10418
10464
|
}
|
|
10419
|
-
if (stored?.kind !== "oauth")
|
|
10420
|
-
|
|
10465
|
+
if (stored?.kind !== "oauth") {
|
|
10466
|
+
throw authError(
|
|
10467
|
+
"The original session changed or ended during renewal.",
|
|
10468
|
+
"Restart this command with your current connection."
|
|
10469
|
+
);
|
|
10470
|
+
}
|
|
10471
|
+
if (ours.localSessionId && credentialSessionId(stored.credential) !== credentialSessionId(ours) || stored.credential.clientId !== ours.clientId || stored.credential.apiUrl.replace(/\/$/, "") !== ours.apiUrl.replace(/\/$/, "")) {
|
|
10421
10472
|
throw networkError(
|
|
10422
10473
|
"The stored session changed while renewing it.",
|
|
10423
10474
|
"Retry the command with the current session."
|
|
@@ -10443,11 +10494,32 @@ async function resolveAuth() {
|
|
|
10443
10494
|
if (stored?.kind === "oauth") {
|
|
10444
10495
|
const fresh = await ensureFreshAccessToken(stored.credential);
|
|
10445
10496
|
warnLegacyApiUrl(fresh.apiUrl);
|
|
10497
|
+
const originalSessionId = credentialSessionId(fresh);
|
|
10498
|
+
const originalApiUrl = fresh.apiUrl;
|
|
10499
|
+
const originalClientId = fresh.clientId;
|
|
10446
10500
|
return withWorkspace({
|
|
10447
10501
|
token: fresh.accessToken,
|
|
10448
10502
|
apiUrl: fresh.apiUrl,
|
|
10449
10503
|
tokenType: "oauth",
|
|
10450
|
-
expiresAt: fresh.accessExpiresAt
|
|
10504
|
+
expiresAt: fresh.accessExpiresAt,
|
|
10505
|
+
getToken: async () => {
|
|
10506
|
+
const latestConfig = await loadConfig();
|
|
10507
|
+
const latest = await loadStoredCredential();
|
|
10508
|
+
if ((latestConfig.api_url || DEFAULT_API_URL) !== configApiUrl || (latestConfig.default_workspace || void 0) !== activeWorkspace || process.env.GAD_TOKEN || latest?.kind !== "oauth" || credentialSessionId(latest.credential) !== originalSessionId || latest.credential.apiUrl !== originalApiUrl || latest.credential.clientId !== originalClientId) {
|
|
10509
|
+
throw authError(
|
|
10510
|
+
"The original session or workspace changed or ended.",
|
|
10511
|
+
"Restart this command with your current connection."
|
|
10512
|
+
);
|
|
10513
|
+
}
|
|
10514
|
+
const renewed = await ensureFreshAccessToken(latest.credential);
|
|
10515
|
+
if (credentialSessionId(renewed) !== originalSessionId) {
|
|
10516
|
+
throw authError(
|
|
10517
|
+
"The original session changed.",
|
|
10518
|
+
"Restart this command with your current connection."
|
|
10519
|
+
);
|
|
10520
|
+
}
|
|
10521
|
+
return renewed.accessToken;
|
|
10522
|
+
}
|
|
10451
10523
|
});
|
|
10452
10524
|
}
|
|
10453
10525
|
if (stored?.kind === "pat") {
|
|
@@ -10502,10 +10574,6 @@ async function ensureFreshAccessToken(credential) {
|
|
|
10502
10574
|
if (Date.now() < credential.accessExpiresAt - REFRESH_SKEW_MS) {
|
|
10503
10575
|
return credential;
|
|
10504
10576
|
}
|
|
10505
|
-
if (Date.now() >= credential.refreshExpiresAt) {
|
|
10506
|
-
await clearStoredCredential();
|
|
10507
|
-
throw sessionExpired();
|
|
10508
|
-
}
|
|
10509
10577
|
inflightRefresh ??= doRefresh(credential);
|
|
10510
10578
|
try {
|
|
10511
10579
|
return await inflightRefresh;
|
|
@@ -10529,12 +10597,32 @@ async function doRefresh(credential) {
|
|
|
10529
10597
|
"Retry shortly; your saved session has been kept."
|
|
10530
10598
|
);
|
|
10531
10599
|
}
|
|
10532
|
-
|
|
10600
|
+
if (Date.now() >= current.refreshExpiresAt) {
|
|
10601
|
+
await clearStoredCredential();
|
|
10602
|
+
throw sessionExpired();
|
|
10603
|
+
}
|
|
10604
|
+
const rotated = await refreshTokens({
|
|
10533
10605
|
apiUrl: current.apiUrl,
|
|
10534
10606
|
clientId: current.clientId,
|
|
10535
10607
|
refreshToken: current.refreshToken
|
|
10536
10608
|
});
|
|
10537
|
-
|
|
10609
|
+
const refreshed = {
|
|
10610
|
+
...rotated,
|
|
10611
|
+
localSessionId: credentialSessionId(current)
|
|
10612
|
+
};
|
|
10613
|
+
const saved = await loadStoredCredential();
|
|
10614
|
+
if (saved?.kind !== "oauth" || credentialSessionId(saved.credential) !== credentialSessionId(current)) {
|
|
10615
|
+
throw authError(
|
|
10616
|
+
"The original session changed or ended during renewal.",
|
|
10617
|
+
"Restart this command with your current connection."
|
|
10618
|
+
);
|
|
10619
|
+
}
|
|
10620
|
+
if (!await saveOAuthCredential(refreshed)) {
|
|
10621
|
+
throw networkError(
|
|
10622
|
+
"Could not persist the renewed session.",
|
|
10623
|
+
"Check your credential storage before retrying."
|
|
10624
|
+
);
|
|
10625
|
+
}
|
|
10538
10626
|
return refreshed;
|
|
10539
10627
|
} catch (err) {
|
|
10540
10628
|
if (err instanceof RefreshRejected) {
|
|
@@ -10678,6 +10766,42 @@ function parseMcpPayload(result) {
|
|
|
10678
10766
|
}
|
|
10679
10767
|
}
|
|
10680
10768
|
|
|
10769
|
+
// ../../src/lib/observability/scrub-pii.ts
|
|
10770
|
+
var EMAIL_RE = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g;
|
|
10771
|
+
var SSN_RE = /\b\d{3}[-.\s]?\d{2}[-.\s]?\d{4}\b/g;
|
|
10772
|
+
var CREDIT_CARD_RE = /\b\d(?:[ -]?\d){12,18}\b/g;
|
|
10773
|
+
var PHONE_RE = /(?:\+?\b1[-.\s]?)?(?:\([2-9]\d{2}\)\s?|\b[2-9]\d{2}[-.\s]?)\d{3}[-.\s]?\d{4}\b/g;
|
|
10774
|
+
function luhnValid(candidate) {
|
|
10775
|
+
const digits2 = candidate.replace(/\D/g, "");
|
|
10776
|
+
if (digits2.length < 13 || digits2.length > 19) return false;
|
|
10777
|
+
let sum = 0;
|
|
10778
|
+
let double = false;
|
|
10779
|
+
for (let i = digits2.length - 1; i >= 0; i--) {
|
|
10780
|
+
let n = digits2.charCodeAt(i) - 48;
|
|
10781
|
+
if (double) {
|
|
10782
|
+
n *= 2;
|
|
10783
|
+
if (n > 9) n -= 9;
|
|
10784
|
+
}
|
|
10785
|
+
sum += n;
|
|
10786
|
+
double = !double;
|
|
10787
|
+
}
|
|
10788
|
+
return sum % 10 === 0;
|
|
10789
|
+
}
|
|
10790
|
+
var SECRET_TOKEN_RE = /\b(?:gad_[A-Za-z0-9_-]{20,}|sk-[A-Za-z0-9-]{20,}|Bearer\s+[A-Za-z0-9._~+/=-]{8,})\b/gi;
|
|
10791
|
+
var SENSITIVE_QUERY_VALUE_RE = /((?:^|[?&])(?:code|token|access_token|refresh_token|id_token|api_key|apikey|api_secret|apisecret|key|secret|client_secret|password|state)=)[^&#\s]+/gi;
|
|
10792
|
+
function scrubPiiFromText(s) {
|
|
10793
|
+
return s.replace(EMAIL_RE, "[redacted-email]").replace(
|
|
10794
|
+
CREDIT_CARD_RE,
|
|
10795
|
+
(m) => luhnValid(m) ? "[redacted-credit-card]" : m
|
|
10796
|
+
).replace(SSN_RE, "[redacted-ssn]").replace(PHONE_RE, "[redacted-phone]");
|
|
10797
|
+
}
|
|
10798
|
+
function scrubTelemetryText(s) {
|
|
10799
|
+
return scrubPiiFromText(s).replace(SENSITIVE_QUERY_VALUE_RE, "$1[redacted]").replace(
|
|
10800
|
+
SECRET_TOKEN_RE,
|
|
10801
|
+
(match) => match.toLowerCase().startsWith("bearer ") ? "Bearer [redacted]" : "[redacted-secret]"
|
|
10802
|
+
);
|
|
10803
|
+
}
|
|
10804
|
+
|
|
10681
10805
|
// src/lib/telemetry.ts
|
|
10682
10806
|
var MAX_EVENTS_PER_PROCESS = 20;
|
|
10683
10807
|
var MAX_STRING = 240;
|
|
@@ -10685,12 +10809,14 @@ var sent = 0;
|
|
|
10685
10809
|
function enabled() {
|
|
10686
10810
|
if (process.env.GAD_TELEMETRY === "0" || process.env.GAD_TELEMETRY === "false")
|
|
10687
10811
|
return false;
|
|
10688
|
-
|
|
10812
|
+
if (process.env.GAD_TELEMETRY === "1" || process.env.GAD_TELEMETRY === "true")
|
|
10813
|
+
return true;
|
|
10814
|
+
return void 0;
|
|
10689
10815
|
}
|
|
10690
10816
|
function redact(value, depth = 0) {
|
|
10691
10817
|
if (depth > 3) return "[redacted]";
|
|
10692
10818
|
if (typeof value === "string") {
|
|
10693
|
-
const scrubbed = value.replace(/Bearer\s+\S+/gi, "Bearer [redacted]").replace(
|
|
10819
|
+
const scrubbed = scrubTelemetryText(value).replace(/Bearer\s+\S+/gi, "Bearer [redacted]").replace(
|
|
10694
10820
|
/(token|secret|password|authorization)[=:]\s*[^\s,]+/gi,
|
|
10695
10821
|
"$1=[redacted]"
|
|
10696
10822
|
);
|
|
@@ -10709,7 +10835,9 @@ function redact(value, depth = 0) {
|
|
|
10709
10835
|
}
|
|
10710
10836
|
async function captureCliEvent(input) {
|
|
10711
10837
|
if (sent >= MAX_EVENTS_PER_PROCESS) return;
|
|
10712
|
-
|
|
10838
|
+
const envConsent = enabled();
|
|
10839
|
+
if (envConsent === false) return;
|
|
10840
|
+
if (envConsent === void 0) {
|
|
10713
10841
|
try {
|
|
10714
10842
|
const config = await loadConfig();
|
|
10715
10843
|
if (config.telemetry_enabled !== true) return;
|
|
@@ -10717,28 +10845,33 @@ async function captureCliEvent(input) {
|
|
|
10717
10845
|
return;
|
|
10718
10846
|
}
|
|
10719
10847
|
}
|
|
10848
|
+
if (sent >= MAX_EVENTS_PER_PROCESS) return;
|
|
10720
10849
|
sent++;
|
|
10721
10850
|
const error = input.error instanceof Error ? { name: input.error.name, message: input.error.message } : input.error;
|
|
10722
10851
|
const payload = {
|
|
10723
10852
|
platform: "cli",
|
|
10724
10853
|
event: input.name,
|
|
10725
10854
|
level: input.error ? "error" : "info",
|
|
10726
|
-
message: error && typeof error === "object" && "message" in error ? String(error.message) : input.name,
|
|
10855
|
+
message: error && typeof error === "object" && "message" in error ? redact(String(error.message)) : redact(input.name),
|
|
10727
10856
|
version: process.env.GAD_CLI_VERSION,
|
|
10728
10857
|
code: input.context?.code,
|
|
10729
10858
|
context: redact(input.context ?? {}),
|
|
10730
10859
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
10731
10860
|
};
|
|
10732
10861
|
try {
|
|
10733
|
-
await fetch(
|
|
10734
|
-
|
|
10735
|
-
|
|
10736
|
-
|
|
10737
|
-
|
|
10738
|
-
|
|
10739
|
-
|
|
10740
|
-
|
|
10741
|
-
|
|
10862
|
+
const response = await fetch(
|
|
10863
|
+
`${input.apiUrl.replace(/\/$/, "")}/api/telemetry`,
|
|
10864
|
+
{
|
|
10865
|
+
method: "POST",
|
|
10866
|
+
headers: {
|
|
10867
|
+
"content-type": "application/json"
|
|
10868
|
+
},
|
|
10869
|
+
body: JSON.stringify(redact(payload)),
|
|
10870
|
+
signal: AbortSignal.timeout(1500)
|
|
10871
|
+
}
|
|
10872
|
+
);
|
|
10873
|
+
if (!response.ok)
|
|
10874
|
+
debugSwallow("telemetry.send", new Error(`HTTP ${response.status}`));
|
|
10742
10875
|
} catch (err) {
|
|
10743
10876
|
debugSwallow("telemetry.send", err);
|
|
10744
10877
|
}
|
|
@@ -10845,12 +10978,14 @@ function sleep(ms) {
|
|
|
10845
10978
|
}
|
|
10846
10979
|
var GadClient = class {
|
|
10847
10980
|
token;
|
|
10981
|
+
getToken;
|
|
10848
10982
|
apiUrl;
|
|
10849
10983
|
repoUrl;
|
|
10850
10984
|
workspaceId;
|
|
10851
10985
|
timeout;
|
|
10852
10986
|
constructor(options) {
|
|
10853
10987
|
this.token = options.token;
|
|
10988
|
+
this.getToken = options.getToken;
|
|
10854
10989
|
this.apiUrl = options.apiUrl.replace(/\/$/, "");
|
|
10855
10990
|
this.repoUrl = options.repoUrl ?? detectGitOrigin();
|
|
10856
10991
|
this.workspaceId = options.workspaceId?.trim() || getCommandWorkspaceTarget({ hasRepo: Boolean(this.repoUrl) }) || null;
|
|
@@ -10886,8 +11021,28 @@ var GadClient = class {
|
|
|
10886
11021
|
const controller = new AbortController();
|
|
10887
11022
|
const timer = setTimeout(() => controller.abort(), effectiveTimeout);
|
|
10888
11023
|
try {
|
|
11024
|
+
const headers = this.getToken ? new Headers(init.headers) : void 0;
|
|
11025
|
+
if (headers && this.getToken) {
|
|
11026
|
+
const token = await Promise.race([
|
|
11027
|
+
this.getToken(),
|
|
11028
|
+
new Promise((_resolve, reject) => {
|
|
11029
|
+
controller.signal.addEventListener(
|
|
11030
|
+
"abort",
|
|
11031
|
+
() => reject(
|
|
11032
|
+
networkError(
|
|
11033
|
+
"Session renewal timed out.",
|
|
11034
|
+
"Retry shortly; your saved session has been kept."
|
|
11035
|
+
)
|
|
11036
|
+
),
|
|
11037
|
+
{ once: true }
|
|
11038
|
+
);
|
|
11039
|
+
})
|
|
11040
|
+
]);
|
|
11041
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
11042
|
+
}
|
|
10889
11043
|
const response = await fetch(url, {
|
|
10890
11044
|
...init,
|
|
11045
|
+
...headers ? { headers: Object.fromEntries(headers) } : {},
|
|
10891
11046
|
signal: controller.signal
|
|
10892
11047
|
});
|
|
10893
11048
|
clearTimeout(timer);
|
|
@@ -11136,6 +11291,7 @@ function whoamiCommand() {
|
|
|
11136
11291
|
const auth = await resolveAuth();
|
|
11137
11292
|
const client = new GadClient({
|
|
11138
11293
|
token: auth.token,
|
|
11294
|
+
getToken: auth.getToken,
|
|
11139
11295
|
apiUrl: auth.apiUrl
|
|
11140
11296
|
});
|
|
11141
11297
|
let result;
|
|
@@ -11246,7 +11402,11 @@ var detailFields = [
|
|
|
11246
11402
|
];
|
|
11247
11403
|
async function buildClient() {
|
|
11248
11404
|
const auth = await resolveAuth();
|
|
11249
|
-
return new GadClient({
|
|
11405
|
+
return new GadClient({
|
|
11406
|
+
token: auth.token,
|
|
11407
|
+
getToken: auth.getToken,
|
|
11408
|
+
apiUrl: auth.apiUrl
|
|
11409
|
+
});
|
|
11250
11410
|
}
|
|
11251
11411
|
function extractPreview(item) {
|
|
11252
11412
|
if (typeof item.content === "string") {
|
|
@@ -11424,7 +11584,11 @@ var memberColumns = [
|
|
|
11424
11584
|
];
|
|
11425
11585
|
async function createClient() {
|
|
11426
11586
|
const auth = await resolveAuth();
|
|
11427
|
-
return new GadClient({
|
|
11587
|
+
return new GadClient({
|
|
11588
|
+
token: auth.token,
|
|
11589
|
+
getToken: auth.getToken,
|
|
11590
|
+
apiUrl: auth.apiUrl
|
|
11591
|
+
});
|
|
11428
11592
|
}
|
|
11429
11593
|
var listCommand = new Command("list").description("List all accessible workspaces").option("--json", "Output as JSON").action(async (options) => {
|
|
11430
11594
|
const jsonFlag = Boolean(
|
|
@@ -11618,7 +11782,11 @@ var listCommand2 = new Command("list").description("List open todos sorted by pr
|
|
|
11618
11782
|
noColor: parentOpts.noColor || false
|
|
11619
11783
|
});
|
|
11620
11784
|
const auth = await resolveAuth();
|
|
11621
|
-
const client = new GadClient({
|
|
11785
|
+
const client = new GadClient({
|
|
11786
|
+
token: auth.token,
|
|
11787
|
+
getToken: auth.getToken,
|
|
11788
|
+
apiUrl: auth.apiUrl
|
|
11789
|
+
});
|
|
11622
11790
|
const args = {
|
|
11623
11791
|
status: options.status ?? "open"
|
|
11624
11792
|
};
|
|
@@ -11644,7 +11812,11 @@ var createCommand = new Command("create").description("Create a new todo card").
|
|
|
11644
11812
|
noColor: false
|
|
11645
11813
|
});
|
|
11646
11814
|
const auth = await resolveAuth();
|
|
11647
|
-
const client = new GadClient({
|
|
11815
|
+
const client = new GadClient({
|
|
11816
|
+
token: auth.token,
|
|
11817
|
+
getToken: auth.getToken,
|
|
11818
|
+
apiUrl: auth.apiUrl
|
|
11819
|
+
});
|
|
11648
11820
|
const args = { title };
|
|
11649
11821
|
if (options.priority) {
|
|
11650
11822
|
args.priority = options.priority;
|
|
@@ -11672,7 +11844,11 @@ var doneCommand = new Command("done").description("Mark a todo as done").argumen
|
|
|
11672
11844
|
noColor: false
|
|
11673
11845
|
});
|
|
11674
11846
|
const auth = await resolveAuth();
|
|
11675
|
-
const client = new GadClient({
|
|
11847
|
+
const client = new GadClient({
|
|
11848
|
+
token: auth.token,
|
|
11849
|
+
getToken: auth.getToken,
|
|
11850
|
+
apiUrl: auth.apiUrl
|
|
11851
|
+
});
|
|
11676
11852
|
await client.mcpCall("todo_update", { id, status: "done" });
|
|
11677
11853
|
fmt.success(`Todo ${id} marked as done.`);
|
|
11678
11854
|
});
|
|
@@ -11691,7 +11867,11 @@ var updateCommand = new Command("update").description("Update a todo's status").
|
|
|
11691
11867
|
process.exit(3);
|
|
11692
11868
|
}
|
|
11693
11869
|
const auth = await resolveAuth();
|
|
11694
|
-
const client = new GadClient({
|
|
11870
|
+
const client = new GadClient({
|
|
11871
|
+
token: auth.token,
|
|
11872
|
+
getToken: auth.getToken,
|
|
11873
|
+
apiUrl: auth.apiUrl
|
|
11874
|
+
});
|
|
11695
11875
|
await client.mcpCall("todo_update", { id, status: options.status });
|
|
11696
11876
|
fmt.success(`Todo ${id} updated to status: ${options.status}`);
|
|
11697
11877
|
});
|
|
@@ -11733,7 +11913,11 @@ var getCommand = new Command("get").description("Show one card's full state (ass
|
|
|
11733
11913
|
noColor: parentOpts.noColor || false
|
|
11734
11914
|
});
|
|
11735
11915
|
const auth = await resolveAuth();
|
|
11736
|
-
const client = new GadClient({
|
|
11916
|
+
const client = new GadClient({
|
|
11917
|
+
token: auth.token,
|
|
11918
|
+
getToken: auth.getToken,
|
|
11919
|
+
apiUrl: auth.apiUrl
|
|
11920
|
+
});
|
|
11737
11921
|
const result = await client.mcpCall("todo_get", { id });
|
|
11738
11922
|
if (!result || typeof result !== "object" || result.error) {
|
|
11739
11923
|
fmt.error(`Todo ${id} not found in this workspace.`);
|
|
@@ -11793,7 +11977,11 @@ var assignCommand = new Command("assign").description("Assign a card to a specia
|
|
|
11793
11977
|
process.exit(3);
|
|
11794
11978
|
}
|
|
11795
11979
|
const auth = await resolveAuth();
|
|
11796
|
-
const client = new GadClient({
|
|
11980
|
+
const client = new GadClient({
|
|
11981
|
+
token: auth.token,
|
|
11982
|
+
getToken: auth.getToken,
|
|
11983
|
+
apiUrl: auth.apiUrl
|
|
11984
|
+
});
|
|
11797
11985
|
const result = await client.mcpCall("todo_assign", built.args);
|
|
11798
11986
|
if (isToolError(result)) {
|
|
11799
11987
|
fmt.error(toolErrorMessage(result));
|
|
@@ -11821,7 +12009,11 @@ var runCommand = new Command("run").description("Start the agent already queued
|
|
|
11821
12009
|
noColor: false
|
|
11822
12010
|
});
|
|
11823
12011
|
const auth = await resolveAuth();
|
|
11824
|
-
const client = new GadClient({
|
|
12012
|
+
const client = new GadClient({
|
|
12013
|
+
token: auth.token,
|
|
12014
|
+
getToken: auth.getToken,
|
|
12015
|
+
apiUrl: auth.apiUrl
|
|
12016
|
+
});
|
|
11825
12017
|
const result = await client.post(
|
|
11826
12018
|
`/api/todos/${encodeURIComponent(id)}/run`,
|
|
11827
12019
|
{}
|
|
@@ -11909,7 +12101,11 @@ var claimCommand = new Command("claim").description("Preflight + atomically clai
|
|
|
11909
12101
|
noColor: parentOpts.noColor || false
|
|
11910
12102
|
});
|
|
11911
12103
|
const auth = await resolveAuth();
|
|
11912
|
-
const client = new GadClient({
|
|
12104
|
+
const client = new GadClient({
|
|
12105
|
+
token: auth.token,
|
|
12106
|
+
getToken: auth.getToken,
|
|
12107
|
+
apiUrl: auth.apiUrl
|
|
12108
|
+
});
|
|
11913
12109
|
if (!options.force) {
|
|
11914
12110
|
tryGit(["fetch", "--quiet", "origin", "main"]);
|
|
11915
12111
|
const log = tryGit(["log", "--format=%s", "-n", "10", "origin/main"]) ?? tryGit(["log", "--format=%s", "-n", "10", "FETCH_HEAD"]) ?? "";
|
|
@@ -12487,6 +12683,7 @@ function workCommand() {
|
|
|
12487
12683
|
}
|
|
12488
12684
|
const client = new GadClient({
|
|
12489
12685
|
token: auth.token,
|
|
12686
|
+
getToken: auth.getToken,
|
|
12490
12687
|
apiUrl: auth.apiUrl
|
|
12491
12688
|
});
|
|
12492
12689
|
const data = await client.get("/api/work/status", {
|
|
@@ -12511,6 +12708,7 @@ function workCommand() {
|
|
|
12511
12708
|
const auth = await resolveAuth();
|
|
12512
12709
|
const client = new GadClient({
|
|
12513
12710
|
token: auth.token,
|
|
12711
|
+
getToken: auth.getToken,
|
|
12514
12712
|
apiUrl: auth.apiUrl
|
|
12515
12713
|
});
|
|
12516
12714
|
const report = options.file ? JSON.parse(readFileSync(options.file, "utf8")) : await collectWorkStatus({
|
|
@@ -13044,7 +13242,11 @@ function normalizeResponse(value) {
|
|
|
13044
13242
|
}
|
|
13045
13243
|
async function createClient2() {
|
|
13046
13244
|
const auth = await resolveAuth();
|
|
13047
|
-
return new GadClient({
|
|
13245
|
+
return new GadClient({
|
|
13246
|
+
token: auth.token,
|
|
13247
|
+
getToken: auth.getToken,
|
|
13248
|
+
apiUrl: auth.apiUrl
|
|
13249
|
+
});
|
|
13048
13250
|
}
|
|
13049
13251
|
function renderGuardrails(data, cmd) {
|
|
13050
13252
|
const output = globalOutputOpts(cmd);
|
|
@@ -14171,7 +14373,7 @@ async function ensureHookCredential(opts) {
|
|
|
14171
14373
|
}
|
|
14172
14374
|
|
|
14173
14375
|
// src/lib/mcp-doctor.ts
|
|
14174
|
-
import { createHash as
|
|
14376
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
14175
14377
|
|
|
14176
14378
|
// src/lib/mcp-target.ts
|
|
14177
14379
|
var GREAT_ARROW_HOSTS = /* @__PURE__ */ new Set([
|
|
@@ -14510,7 +14712,7 @@ function connectorGuidance(entries) {
|
|
|
14510
14712
|
return 'If you ALSO installed the Great Arrow connector on claude.ai, Claude Code counts it as a second server and nags "needs authentication" forever. Silence the duplicate by adding its name to "deniedMcpServers" in ~/.claude/settings.json ("disabledMcpServers" is not a valid key; "disabledMcpjsonServers" only covers .mcp.json servers).';
|
|
14511
14713
|
}
|
|
14512
14714
|
function fingerprint(value) {
|
|
14513
|
-
return
|
|
14715
|
+
return createHash3("sha256").update(value).digest("hex").slice(0, 12);
|
|
14514
14716
|
}
|
|
14515
14717
|
function describeStoredCredential(raw) {
|
|
14516
14718
|
const trimmed = raw?.trim();
|
|
@@ -14784,7 +14986,11 @@ async function checkApi(auth) {
|
|
|
14784
14986
|
hint: "Fix authentication first."
|
|
14785
14987
|
};
|
|
14786
14988
|
}
|
|
14787
|
-
const client = new GadClient({
|
|
14989
|
+
const client = new GadClient({
|
|
14990
|
+
token: auth.token,
|
|
14991
|
+
getToken: auth.getToken,
|
|
14992
|
+
apiUrl: auth.apiUrl
|
|
14993
|
+
});
|
|
14788
14994
|
try {
|
|
14789
14995
|
await client.get("/api/health");
|
|
14790
14996
|
return {
|
|
@@ -14810,7 +15016,11 @@ async function checkCliVersion(auth) {
|
|
|
14810
15016
|
hint: "Fix authentication first, then run 'gad doctor' again."
|
|
14811
15017
|
};
|
|
14812
15018
|
}
|
|
14813
|
-
const client = new GadClient({
|
|
15019
|
+
const client = new GadClient({
|
|
15020
|
+
token: auth.token,
|
|
15021
|
+
getToken: auth.getToken,
|
|
15022
|
+
apiUrl: auth.apiUrl
|
|
15023
|
+
});
|
|
14814
15024
|
try {
|
|
14815
15025
|
const result = await client.get("/api/mcp/version");
|
|
14816
15026
|
const cli = result.updates?.cli ?? result.cli ?? {};
|
|
@@ -14856,7 +15066,11 @@ async function checkIntegrations(auth) {
|
|
|
14856
15066
|
hint: "Fix authentication first."
|
|
14857
15067
|
};
|
|
14858
15068
|
}
|
|
14859
|
-
const client = new GadClient({
|
|
15069
|
+
const client = new GadClient({
|
|
15070
|
+
token: auth.token,
|
|
15071
|
+
getToken: auth.getToken,
|
|
15072
|
+
apiUrl: auth.apiUrl
|
|
15073
|
+
});
|
|
14860
15074
|
try {
|
|
14861
15075
|
const result = await client.mcpCall("integrations_list", {});
|
|
14862
15076
|
const data = result ?? {};
|
|
@@ -14897,7 +15111,11 @@ async function checkMcp(auth) {
|
|
|
14897
15111
|
hint: "Fix authentication first."
|
|
14898
15112
|
};
|
|
14899
15113
|
}
|
|
14900
|
-
const client = new GadClient({
|
|
15114
|
+
const client = new GadClient({
|
|
15115
|
+
token: auth.token,
|
|
15116
|
+
getToken: auth.getToken,
|
|
15117
|
+
apiUrl: auth.apiUrl
|
|
15118
|
+
});
|
|
14901
15119
|
try {
|
|
14902
15120
|
await client.mcpCall("workspace_introspect", {});
|
|
14903
15121
|
return {
|
|
@@ -15505,7 +15723,11 @@ var integrationListColumns = [
|
|
|
15505
15723
|
];
|
|
15506
15724
|
async function createClient3() {
|
|
15507
15725
|
const auth = await resolveAuth();
|
|
15508
|
-
return new GadClient({
|
|
15726
|
+
return new GadClient({
|
|
15727
|
+
token: auth.token,
|
|
15728
|
+
getToken: auth.getToken,
|
|
15729
|
+
apiUrl: auth.apiUrl
|
|
15730
|
+
});
|
|
15509
15731
|
}
|
|
15510
15732
|
function formatErrorDetail(rawError) {
|
|
15511
15733
|
if (rawError === null || rawError === void 0) return null;
|
|
@@ -15616,13 +15838,13 @@ var integrationsCommand = new Command("integrations").description("Manage connec
|
|
|
15616
15838
|
var integrations_default = integrationsCommand;
|
|
15617
15839
|
|
|
15618
15840
|
// src/commands/mcp.ts
|
|
15619
|
-
import { createHash as
|
|
15841
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
15620
15842
|
import { hostname } from "node:os";
|
|
15621
15843
|
|
|
15622
15844
|
// src/lib/mcp-bridge.ts
|
|
15623
15845
|
import { createInterface as createInterface2 } from "node:readline";
|
|
15624
15846
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
15625
|
-
import { randomUUID } from "node:crypto";
|
|
15847
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
15626
15848
|
var BRIDGE_CLIENT_ID = "gad-cli";
|
|
15627
15849
|
var DEFAULT_API_URL2 = "https://www.greatarrow.ai";
|
|
15628
15850
|
var DEFAULT_TIMEOUT_MS3 = 9e4;
|
|
@@ -15785,7 +16007,7 @@ async function runStdioBridge(options) {
|
|
|
15785
16007
|
`));
|
|
15786
16008
|
const endpoint = `${options.auth.apiUrl}/api/mcp`;
|
|
15787
16009
|
const timeoutMs = Number(env4.MEMORY_TIMEOUT_MS ?? DEFAULT_TIMEOUT_MS3);
|
|
15788
|
-
const sessionId = (env4.GAD_SESSION_ID ?? env4.MEMORY_SESSION_ID)?.trim() || `${BRIDGE_CLIENT_ID}:${Date.now()}-${
|
|
16010
|
+
const sessionId = (env4.GAD_SESSION_ID ?? env4.MEMORY_SESSION_ID)?.trim() || `${BRIDGE_CLIENT_ID}:${Date.now()}-${randomUUID2().slice(0, 8)}`;
|
|
15789
16011
|
const repoUrl = (env4.GAD_REPO_URL ?? env4.MEMORY_REPO_URL)?.trim() || detectGitOrigin3();
|
|
15790
16012
|
const workspaceId = (env4.GAD_WORKSPACE_ID ?? env4.GAD_WORKSPACE)?.trim() || getCommandWorkspaceTarget({ hasRepo: Boolean(repoUrl) });
|
|
15791
16013
|
const headers = buildBridgeHeaders({
|
|
@@ -15949,7 +16171,11 @@ async function mcpJsonAtRiskOfCommit(dir) {
|
|
|
15949
16171
|
}
|
|
15950
16172
|
async function createClient4() {
|
|
15951
16173
|
const auth = await resolveAuth();
|
|
15952
|
-
const client = new GadClient({
|
|
16174
|
+
const client = new GadClient({
|
|
16175
|
+
token: auth.token,
|
|
16176
|
+
getToken: auth.getToken,
|
|
16177
|
+
apiUrl: auth.apiUrl
|
|
16178
|
+
});
|
|
15953
16179
|
return { client, apiUrl: auth.apiUrl };
|
|
15954
16180
|
}
|
|
15955
16181
|
function generateMcpConfig(client, apiUrl, token, repoUrl) {
|
|
@@ -15984,7 +16210,7 @@ function generateMcpConfig(client, apiUrl, token, repoUrl) {
|
|
|
15984
16210
|
Authorization: `Bearer ${token}`,
|
|
15985
16211
|
"X-MCP-Client": CLIENT_IDS[client],
|
|
15986
16212
|
"X-Device-Name": deviceName,
|
|
15987
|
-
"X-Machine-Id":
|
|
16213
|
+
"X-Machine-Id": createHash4("sha256").update(rawHost).digest("hex"),
|
|
15988
16214
|
[GAD_INSTALL_HEADER]: GAD_INSTALL_VERSION,
|
|
15989
16215
|
...repoUrl ? { "X-Repo-URL": repoUrl } : {}
|
|
15990
16216
|
};
|
|
@@ -16249,7 +16475,11 @@ var testCommand = new Command("test").description(
|
|
|
16249
16475
|
const c = createColor(false);
|
|
16250
16476
|
const auth = await resolveAuth();
|
|
16251
16477
|
const apiUrl = auth.apiUrl;
|
|
16252
|
-
const client = new GadClient({
|
|
16478
|
+
const client = new GadClient({
|
|
16479
|
+
token: auth.token,
|
|
16480
|
+
getToken: auth.getToken,
|
|
16481
|
+
apiUrl
|
|
16482
|
+
});
|
|
16253
16483
|
const verbose = !jsonFlag;
|
|
16254
16484
|
const checks = [
|
|
16255
16485
|
await checkDns(apiUrl, verbose, c),
|
|
@@ -16788,6 +17018,7 @@ function smokeCommand() {
|
|
|
16788
17018
|
const auth = await resolveAuth();
|
|
16789
17019
|
const client = new GadClient({
|
|
16790
17020
|
token: auth.token,
|
|
17021
|
+
getToken: auth.getToken,
|
|
16791
17022
|
apiUrl: auth.apiUrl
|
|
16792
17023
|
});
|
|
16793
17024
|
if (!isJson && !isQuiet) {
|
|
@@ -16835,7 +17066,11 @@ var agentListColumns = [
|
|
|
16835
17066
|
];
|
|
16836
17067
|
async function buildClient2() {
|
|
16837
17068
|
const auth = await resolveAuth();
|
|
16838
|
-
return new GadClient({
|
|
17069
|
+
return new GadClient({
|
|
17070
|
+
token: auth.token,
|
|
17071
|
+
getToken: auth.getToken,
|
|
17072
|
+
apiUrl: auth.apiUrl
|
|
17073
|
+
});
|
|
16839
17074
|
}
|
|
16840
17075
|
function invokeOutcome(data) {
|
|
16841
17076
|
if (typeof data === "string") {
|
|
@@ -16985,6 +17220,7 @@ function askCommand() {
|
|
|
16985
17220
|
const auth = await resolveAuth();
|
|
16986
17221
|
const client = new GadClient({
|
|
16987
17222
|
token: auth.token,
|
|
17223
|
+
getToken: auth.getToken,
|
|
16988
17224
|
apiUrl: auth.apiUrl
|
|
16989
17225
|
});
|
|
16990
17226
|
const fmt = createFormatter({
|
|
@@ -17977,26 +18213,36 @@ function authHeaders(token) {
|
|
|
17977
18213
|
function origin(apiUrl) {
|
|
17978
18214
|
return apiUrl.replace(/\/+$/, "");
|
|
17979
18215
|
}
|
|
17980
|
-
function appAwareFetch(apiUrl, token, base) {
|
|
17981
|
-
return (input, init) => {
|
|
18216
|
+
function appAwareFetch(apiUrl, token, base, getToken2) {
|
|
18217
|
+
return async (input, init) => {
|
|
17982
18218
|
const target = typeof input === "string" ? input : String(input);
|
|
17983
|
-
|
|
17984
|
-
|
|
18219
|
+
const relative = target.startsWith("/") && !target.startsWith("//");
|
|
18220
|
+
if (!relative && !target.startsWith(`${origin(apiUrl)}/`))
|
|
18221
|
+
return base(input, init);
|
|
18222
|
+
const currentToken = getToken2 ? await withTimeout(15e3, () => getToken2()) : token;
|
|
18223
|
+
return base(relative ? `${origin(apiUrl)}${target}` : target, {
|
|
17985
18224
|
...init,
|
|
17986
18225
|
headers: {
|
|
17987
18226
|
...init?.headers,
|
|
17988
|
-
...authHeaders(
|
|
18227
|
+
...authHeaders(currentToken)
|
|
17989
18228
|
}
|
|
17990
18229
|
});
|
|
17991
18230
|
};
|
|
17992
18231
|
}
|
|
17993
18232
|
async function withTimeout(ms, run2) {
|
|
17994
18233
|
const controller = new AbortController();
|
|
17995
|
-
|
|
18234
|
+
let timer;
|
|
18235
|
+
const deadline = new Promise((_resolve, reject) => {
|
|
18236
|
+
timer = setTimeout(() => {
|
|
18237
|
+
const error = new DOMException("Request timed out", "AbortError");
|
|
18238
|
+
controller.abort(error);
|
|
18239
|
+
reject(error);
|
|
18240
|
+
}, ms);
|
|
18241
|
+
});
|
|
17996
18242
|
try {
|
|
17997
|
-
return await run2(controller.signal);
|
|
18243
|
+
return await Promise.race([run2(controller.signal), deadline]);
|
|
17998
18244
|
} finally {
|
|
17999
|
-
clearTimeout(timer);
|
|
18245
|
+
if (timer) clearTimeout(timer);
|
|
18000
18246
|
}
|
|
18001
18247
|
}
|
|
18002
18248
|
function readHandoff(payload) {
|
|
@@ -18061,7 +18307,7 @@ async function askForTheTurn(opts) {
|
|
|
18061
18307
|
if (!response.ok) {
|
|
18062
18308
|
throw new LocalTurnFailed(
|
|
18063
18309
|
"handoff",
|
|
18064
|
-
response.status === 401
|
|
18310
|
+
response.status === 401 ? "Sign in again \u2014 this computer is not allowed to ask for work." : response.status === 403 ? "This connection needs permission. Review its scopes and workspace access at /account/connections." : `Great Arrow refused that (${response.status}).`,
|
|
18065
18311
|
true
|
|
18066
18312
|
);
|
|
18067
18313
|
}
|
|
@@ -18123,14 +18369,14 @@ async function handBack(opts) {
|
|
|
18123
18369
|
}
|
|
18124
18370
|
async function answerOnThisComputer(opts) {
|
|
18125
18371
|
const base = opts.fetchImpl ?? fetch;
|
|
18126
|
-
const doFetch = appAwareFetch(opts.apiUrl, opts.token, base);
|
|
18372
|
+
const doFetch = appAwareFetch(opts.apiUrl, opts.token, base, opts.getToken);
|
|
18127
18373
|
const handoff = await askForTheTurn({
|
|
18128
18374
|
apiUrl: opts.apiUrl,
|
|
18129
18375
|
token: opts.token,
|
|
18130
18376
|
question: opts.question,
|
|
18131
18377
|
sessionId: opts.sessionId ?? null,
|
|
18132
18378
|
timezone: opts.timezone,
|
|
18133
|
-
doFetch
|
|
18379
|
+
doFetch
|
|
18134
18380
|
});
|
|
18135
18381
|
if (!handoff) {
|
|
18136
18382
|
return { answeredHere: false, reason: "answered_by_great_arrow" };
|
|
@@ -18172,7 +18418,7 @@ async function answerOnThisComputer(opts) {
|
|
|
18172
18418
|
outputTokens: result.outputTokens,
|
|
18173
18419
|
promptCharacters: result.promptCharacters,
|
|
18174
18420
|
latencyMs: Date.now() - startedAt,
|
|
18175
|
-
doFetch
|
|
18421
|
+
doFetch
|
|
18176
18422
|
});
|
|
18177
18423
|
return {
|
|
18178
18424
|
answeredHere: true,
|
|
@@ -18192,7 +18438,7 @@ async function answerOnThisComputer(opts) {
|
|
|
18192
18438
|
outputTokens: void 0,
|
|
18193
18439
|
promptCharacters: 0,
|
|
18194
18440
|
latencyMs: Date.now() - startedAt,
|
|
18195
|
-
doFetch
|
|
18441
|
+
doFetch
|
|
18196
18442
|
});
|
|
18197
18443
|
throw new LocalTurnFailed(
|
|
18198
18444
|
"writing",
|
|
@@ -18425,7 +18671,11 @@ function checkCommand() {
|
|
|
18425
18671
|
const provider = readProvider(options.app);
|
|
18426
18672
|
const baseUrl = typeof options.url === "string" && options.url ? options.url : LOCAL_PROVIDER_PRESETS[provider].baseUrl;
|
|
18427
18673
|
const auth = await resolveAuth();
|
|
18428
|
-
const client = new GadClient({
|
|
18674
|
+
const client = new GadClient({
|
|
18675
|
+
token: auth.token,
|
|
18676
|
+
getToken: auth.getToken,
|
|
18677
|
+
apiUrl: auth.apiUrl
|
|
18678
|
+
});
|
|
18429
18679
|
const fmt = createFormatter({
|
|
18430
18680
|
json: g.json,
|
|
18431
18681
|
quiet: g.quiet,
|
|
@@ -18500,7 +18750,11 @@ function statusCommand2() {
|
|
|
18500
18750
|
return new Command("status").description("Show what is set up for models on this computer").action(async (_options, command) => {
|
|
18501
18751
|
const g = globalOutputOpts(command);
|
|
18502
18752
|
const auth = await resolveAuth();
|
|
18503
|
-
const client = new GadClient({
|
|
18753
|
+
const client = new GadClient({
|
|
18754
|
+
token: auth.token,
|
|
18755
|
+
getToken: auth.getToken,
|
|
18756
|
+
apiUrl: auth.apiUrl
|
|
18757
|
+
});
|
|
18504
18758
|
const payload = await client.mcpCall(
|
|
18505
18759
|
"model_local_get",
|
|
18506
18760
|
{},
|
|
@@ -18568,7 +18822,11 @@ function offCommand() {
|
|
|
18568
18822
|
return new Command("off").description("Stop answering with a model on this computer").action(async (_options, command) => {
|
|
18569
18823
|
const g = globalOutputOpts(command);
|
|
18570
18824
|
const auth = await resolveAuth();
|
|
18571
|
-
const client = new GadClient({
|
|
18825
|
+
const client = new GadClient({
|
|
18826
|
+
token: auth.token,
|
|
18827
|
+
getToken: auth.getToken,
|
|
18828
|
+
apiUrl: auth.apiUrl
|
|
18829
|
+
});
|
|
18572
18830
|
const fmt = createFormatter({
|
|
18573
18831
|
json: g.json,
|
|
18574
18832
|
quiet: g.quiet,
|
|
@@ -18599,6 +18857,7 @@ function askHereCommand() {
|
|
|
18599
18857
|
report = await answerOnThisComputer({
|
|
18600
18858
|
apiUrl: auth.apiUrl,
|
|
18601
18859
|
token: auth.token,
|
|
18860
|
+
getToken: auth.getToken,
|
|
18602
18861
|
question,
|
|
18603
18862
|
sessionId: typeof options.session === "string" ? options.session : null,
|
|
18604
18863
|
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
@@ -18712,6 +18971,7 @@ function statusCommand3() {
|
|
|
18712
18971
|
const auth = await resolveAuth();
|
|
18713
18972
|
const client = new GadClient({
|
|
18714
18973
|
token: auth.token,
|
|
18974
|
+
getToken: auth.getToken,
|
|
18715
18975
|
apiUrl: auth.apiUrl
|
|
18716
18976
|
});
|
|
18717
18977
|
const fmt = createFormatter({
|
|
@@ -18889,7 +19149,11 @@ function openCommand() {
|
|
|
18889
19149
|
).option("--print", "Print the URL instead of opening a browser").option("--json", "Output the resolved surface as JSON").action(async (surface, options, command) => {
|
|
18890
19150
|
const g = globalOutputOpts(command);
|
|
18891
19151
|
const auth = await resolveAuth();
|
|
18892
|
-
const client = new GadClient({
|
|
19152
|
+
const client = new GadClient({
|
|
19153
|
+
token: auth.token,
|
|
19154
|
+
getToken: auth.getToken,
|
|
19155
|
+
apiUrl: auth.apiUrl
|
|
19156
|
+
});
|
|
18893
19157
|
const result = await client.mcpCall("surfaces_list", {
|
|
18894
19158
|
query: surface
|
|
18895
19159
|
});
|
|
@@ -18977,7 +19241,11 @@ function nextCommand() {
|
|
|
18977
19241
|
noColor: g.noColor
|
|
18978
19242
|
});
|
|
18979
19243
|
const auth = await resolveAuth();
|
|
18980
|
-
const client = new GadClient({
|
|
19244
|
+
const client = new GadClient({
|
|
19245
|
+
token: auth.token,
|
|
19246
|
+
getToken: auth.getToken,
|
|
19247
|
+
apiUrl: auth.apiUrl
|
|
19248
|
+
});
|
|
18981
19249
|
let identityStatus = null;
|
|
18982
19250
|
try {
|
|
18983
19251
|
const who = await client.mcpCall("workspace_introspect", {});
|
|
@@ -19040,7 +19308,11 @@ function discoverCommand() {
|
|
|
19040
19308
|
noColor: g.noColor
|
|
19041
19309
|
});
|
|
19042
19310
|
const auth = await resolveAuth();
|
|
19043
|
-
const client = new GadClient({
|
|
19311
|
+
const client = new GadClient({
|
|
19312
|
+
token: auth.token,
|
|
19313
|
+
getToken: auth.getToken,
|
|
19314
|
+
apiUrl: auth.apiUrl
|
|
19315
|
+
});
|
|
19044
19316
|
const parsed = opts.limit ? Number.parseInt(opts.limit, 10) : NaN;
|
|
19045
19317
|
const args = Number.isFinite(parsed) && parsed > 0 ? { limit: parsed } : {};
|
|
19046
19318
|
const result = await client.mcpCall("did_you_know", args);
|