githits 0.4.10 → 0.4.12

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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  __require,
3
3
  version
4
- } from "./chunk-fvpvx4x4.js";
4
+ } from "./chunk-tmhsq5ft.js";
5
5
 
6
6
  // src/services/app-config-paths.ts
7
7
  var APP_DIR = "githits";
@@ -57,6 +57,7 @@ function getLegacyMacAuthFileStorageDir(fs) {
57
57
  function getLegacyMacAuthFileStorageDirForEnv(fs, env) {
58
58
  return fs.joinPath(getLegacyMacAppConfigDirForEnv(fs, env), "auth");
59
59
  }
60
+
60
61
  // src/services/auth-config.ts
61
62
  import { parse as parseToml } from "smol-toml";
62
63
  import { z } from "zod";
@@ -126,6 +127,7 @@ async function loadAuthConfig(fs) {
126
127
  throw error;
127
128
  }
128
129
  }
130
+
129
131
  // src/services/auth-service.ts
130
132
  import { createServer } from "node:http";
131
133
 
@@ -796,6 +798,7 @@ var HELP_CTA = ctaBlock("Explore available commands with:", [
796
798
  function escapeHtml(text) {
797
799
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
798
800
  }
801
+
799
802
  // src/services/auth-storage.ts
800
803
  var AUTH_FILE = "auth.json";
801
804
  var CLIENT_FILE = "client.json";
@@ -1002,6 +1005,7 @@ function isAuthSessionMetadata(value) {
1002
1005
  return false;
1003
1006
  return typeof value.createdAt === "string" && value.createdAt.length > 0 && typeof value.updatedAt === "string" && value.updatedAt.length > 0 && (value.expiresAt === null || typeof value.expiresAt === "string" && value.expiresAt.length > 0);
1004
1007
  }
1008
+
1005
1009
  // src/services/browser-service.ts
1006
1010
  import open from "open";
1007
1011
 
@@ -1010,6 +1014,7 @@ class BrowserServiceImpl {
1010
1014
  await open(url);
1011
1015
  }
1012
1016
  }
1017
+
1013
1018
  // src/services/chunking-keyring-service.ts
1014
1019
  var WINDOWS_MAX_ENTRY_SIZE = 1200;
1015
1020
  var CHUNKED_PREFIX = "CHUNKED:";
@@ -1121,30 +1126,7 @@ class ChunkingKeyringService {
1121
1126
  }
1122
1127
  }
1123
1128
  }
1124
- // src/services/client-update-required-error.ts
1125
- var CLIENT_UPDATE_REQUIRED_REASON = "Backend protocol changed";
1126
1129
 
1127
- class ClientUpdateRequiredError extends Error {
1128
- reason;
1129
- currentVersion;
1130
- constructor(message = `Update required: ${CLIENT_UPDATE_REQUIRED_REASON}`, reason = CLIENT_UPDATE_REQUIRED_REASON, currentVersion = version) {
1131
- super(message);
1132
- this.reason = reason;
1133
- this.currentVersion = currentVersion;
1134
- this.name = "ClientUpdateRequiredError";
1135
- }
1136
- }
1137
- function isClientUpdateRequiredGraphQLError(input) {
1138
- return input.code === "CLIENT_UPDATE_REQUIRED";
1139
- }
1140
- function isGraphQLSchemaMismatchError(input) {
1141
- if (!isGraphQLSchemaMismatchMessage(input.message))
1142
- return false;
1143
- return !input.code || input.code === "GRAPHQL_VALIDATION_FAILED" || input.code === "BAD_USER_INPUT";
1144
- }
1145
- function isGraphQLSchemaMismatchMessage(message) {
1146
- return /Cannot query field|Field .* does not exist|Unknown argument|Unknown type|Unknown field/i.test(message);
1147
- }
1148
1130
  // src/services/code-navigation-service.ts
1149
1131
  import { z as z2 } from "zod";
1150
1132
 
@@ -1188,158 +1170,6 @@ function isExplicitOnlyArea(area) {
1188
1170
  return area === "code-nav-wire";
1189
1171
  }
1190
1172
 
1191
- // src/shared/request-headers.ts
1192
- import { createHash as createHash2, randomUUID } from "node:crypto";
1193
- var MAX_HEADER_BYTES = 256;
1194
- var SESSION_ENV_VARS = [
1195
- "TERM_SESSION_ID",
1196
- "ITERM_SESSION_ID",
1197
- "WEZTERM_PANE",
1198
- "KITTY_PID",
1199
- "ALACRITTY_SOCKET",
1200
- "WT_SESSION",
1201
- "VSCODE_PID",
1202
- "SUPERSET_PANE_ID",
1203
- "SUPERSET_WORKSPACE_ID",
1204
- "STARSHIP_SESSION_KEY",
1205
- "SSH_CONNECTION"
1206
- ];
1207
- var cachedSessionId;
1208
- function resolveRawSessionId(env = process.env, ppid = process.ppid) {
1209
- for (const key of SESSION_ENV_VARS) {
1210
- const value = env[key];
1211
- if (value && value.trim().length > 0) {
1212
- return value.trim();
1213
- }
1214
- }
1215
- if (typeof ppid === "number" && !Number.isNaN(ppid) && ppid > 0) {
1216
- return String(ppid);
1217
- }
1218
- return randomUUID();
1219
- }
1220
- function getSessionId(env, ppid) {
1221
- if (cachedSessionId !== undefined && env === undefined && ppid === undefined) {
1222
- return cachedSessionId;
1223
- }
1224
- const raw = resolveRawSessionId(env, ppid);
1225
- const hashed = hashValue(raw);
1226
- if (env === undefined && ppid === undefined) {
1227
- cachedSessionId = hashed;
1228
- }
1229
- return hashed;
1230
- }
1231
- function hashValue(input) {
1232
- return createHash2("sha256").update(input).digest("hex").slice(0, 16);
1233
- }
1234
- var AGENT_PROBES = [
1235
- { envVar: "OPENCODE", name: "opencode" },
1236
- { envVar: "CLAUDECODE", name: "claude-code" },
1237
- { envVar: "CURSOR_TRACE_ID", name: "cursor" },
1238
- { envVar: "WINDSURF_CONFIG_DIR", name: "windsurf" },
1239
- { envVar: "ZED_TERM", name: "zed" },
1240
- { envVar: "VSCODE_PID", name: "vscode" }
1241
- ];
1242
- function parseAgentString(raw) {
1243
- const trimmed = raw.trim();
1244
- if (trimmed.length === 0)
1245
- return;
1246
- const slashIndex = trimmed.indexOf("/");
1247
- if (slashIndex === -1)
1248
- return { name: trimmed };
1249
- const name = trimmed.slice(0, slashIndex);
1250
- const ver = trimmed.slice(slashIndex + 1);
1251
- if (name.length === 0)
1252
- return;
1253
- return { name, version: ver || undefined };
1254
- }
1255
- function formatAgentInfo(info) {
1256
- return info.version ? `${info.name}/${info.version}` : info.name;
1257
- }
1258
- function resolveAgentInfo(env = process.env) {
1259
- const explicit = env.GITHITS_AGENT;
1260
- if (explicit && explicit.trim().length > 0) {
1261
- return parseAgentString(explicit);
1262
- }
1263
- for (const probe of AGENT_PROBES) {
1264
- const value = env[probe.envVar];
1265
- if (value && value.trim().length > 0) {
1266
- return { name: probe.name };
1267
- }
1268
- }
1269
- return;
1270
- }
1271
- var currentAgentInfo;
1272
- var agentInfoInitialized = false;
1273
- var agentInfoExplicitlySet = false;
1274
- var mcpClientVersionProvider;
1275
- function setMcpClientVersionProvider(provider) {
1276
- mcpClientVersionProvider = provider;
1277
- }
1278
- function getAgentInfo(env) {
1279
- if (agentInfoExplicitlySet) {
1280
- return currentAgentInfo;
1281
- }
1282
- if (mcpClientVersionProvider) {
1283
- try {
1284
- const fromProvider = mcpClientVersionProvider();
1285
- if (fromProvider && fromProvider.name.trim().length > 0) {
1286
- return fromProvider;
1287
- }
1288
- } catch {}
1289
- }
1290
- if (!agentInfoInitialized || env !== undefined) {
1291
- currentAgentInfo = resolveAgentInfo(env);
1292
- if (env === undefined) {
1293
- agentInfoInitialized = true;
1294
- }
1295
- }
1296
- return currentAgentInfo;
1297
- }
1298
- var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
1299
- function sanitizeHeaderValue(value) {
1300
- if (value === undefined || value === null || typeof value !== "string") {
1301
- return;
1302
- }
1303
- const cleaned = value.replace(CONTROL_CHARS, "").trim();
1304
- if (cleaned.length === 0)
1305
- return;
1306
- if (Buffer.byteLength(cleaned, "utf8") > MAX_HEADER_BYTES)
1307
- return;
1308
- return cleaned;
1309
- }
1310
- var BASE_CLIENT_NAME = "githits-cli";
1311
- var clientName = BASE_CLIENT_NAME;
1312
- function setClientMode(mode) {
1313
- clientName = `${BASE_CLIENT_NAME}/${mode}`;
1314
- }
1315
- function buildClientHeaders(env, ppid) {
1316
- try {
1317
- const headers = {};
1318
- const name = sanitizeHeaderValue(clientName);
1319
- if (name) {
1320
- headers["x-githits-client-name"] = name;
1321
- }
1322
- const clientVersion = sanitizeHeaderValue(version);
1323
- if (clientVersion) {
1324
- headers["x-githits-client-version"] = clientVersion;
1325
- }
1326
- const agentInfo = getAgentInfo(env);
1327
- if (agentInfo) {
1328
- const agentValue = sanitizeHeaderValue(formatAgentInfo(agentInfo));
1329
- if (agentValue) {
1330
- headers["x-githits-agent"] = agentValue;
1331
- }
1332
- }
1333
- const sessionId = sanitizeHeaderValue(getSessionId(env, ppid));
1334
- if (sessionId) {
1335
- headers["x-githits-session-id"] = sessionId;
1336
- }
1337
- return headers;
1338
- } catch {
1339
- return {};
1340
- }
1341
- }
1342
-
1343
1173
  // src/shared/pkgseer-graphql.ts
1344
1174
  class PkgseerTransportError extends Error {
1345
1175
  constructor(message, options) {
@@ -1351,14 +1181,14 @@ function baseUrl(endpointUrl) {
1351
1181
  return endpointUrl.replace(/\/+$/, "");
1352
1182
  }
1353
1183
  async function postPkgseerGraphql(request) {
1354
- const userAgent = request.userAgent ?? `githits-cli/${version}`;
1184
+ const userAgent = request.userAgent ?? "githits-cli";
1355
1185
  const timeoutMs = request.timeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;
1356
1186
  let response;
1357
1187
  try {
1358
1188
  response = await fetchWithTimeout(`${baseUrl(request.endpointUrl)}/api/graphql`, {
1359
1189
  method: "POST",
1360
1190
  headers: {
1361
- ...buildClientHeaders(),
1191
+ ...request.clientHeaders?.(),
1362
1192
  Authorization: `Bearer ${request.token}`,
1363
1193
  "Content-Type": "application/json",
1364
1194
  "User-Agent": userAgent
@@ -1394,6 +1224,31 @@ function parseJsonOrNull(body) {
1394
1224
  }
1395
1225
  }
1396
1226
 
1227
+ // src/services/client-update-required-error.ts
1228
+ var CLIENT_UPDATE_REQUIRED_REASON = "Backend protocol changed";
1229
+
1230
+ class ClientUpdateRequiredError extends Error {
1231
+ reason;
1232
+ currentVersion;
1233
+ constructor(message = `Update required: ${CLIENT_UPDATE_REQUIRED_REASON}`, reason = CLIENT_UPDATE_REQUIRED_REASON, currentVersion) {
1234
+ super(message);
1235
+ this.reason = reason;
1236
+ this.currentVersion = currentVersion;
1237
+ this.name = "ClientUpdateRequiredError";
1238
+ }
1239
+ }
1240
+ function isClientUpdateRequiredGraphQLError(input) {
1241
+ return input.code === "CLIENT_UPDATE_REQUIRED";
1242
+ }
1243
+ function isGraphQLSchemaMismatchError(input) {
1244
+ if (!isGraphQLSchemaMismatchMessage(input.message))
1245
+ return false;
1246
+ return !input.code || input.code === "GRAPHQL_VALIDATION_FAILED" || input.code === "BAD_USER_INPUT";
1247
+ }
1248
+ function isGraphQLSchemaMismatchMessage(message) {
1249
+ return /Cannot query field|Field .* does not exist|Unknown argument|Unknown type|Unknown field/i.test(message);
1250
+ }
1251
+
1397
1252
  // src/shared/telemetry.ts
1398
1253
  import { writeSync } from "node:fs";
1399
1254
  var ENABLED_VALUES = new Set(["1", "true", "yes", "on"]);
@@ -1535,10 +1390,16 @@ function formatMs(value) {
1535
1390
  }
1536
1391
 
1537
1392
  // src/services/githits-service.ts
1393
+ var AUTHENTICATION_REQUIRED_MESSAGE = "Authentication required.";
1394
+ var LOCAL_AUTHENTICATION_MISSING_MESSAGE = "No local GitHits authentication token found.";
1395
+ var SERVER_AUTHENTICATION_REJECTED_MESSAGE = "GitHits could not accept the authentication token.";
1396
+
1538
1397
  class AuthenticationError extends Error {
1539
- constructor(message) {
1398
+ source;
1399
+ constructor(message = AUTHENTICATION_REQUIRED_MESSAGE, source = "local") {
1540
1400
  super(message);
1541
1401
  this.name = "AuthenticationError";
1402
+ this.source = source;
1542
1403
  }
1543
1404
  }
1544
1405
  function parseDetail(body) {
@@ -1559,11 +1420,13 @@ class GitHitsServiceImpl {
1559
1420
  token;
1560
1421
  fetchFn;
1561
1422
  fetchTimeoutMs;
1562
- constructor(apiUrl, token, fetchFn, fetchTimeoutMs = DEFAULT_FETCH_TIMEOUT_MS) {
1423
+ runtime;
1424
+ constructor(apiUrl, token, fetchFn, fetchTimeoutMs = DEFAULT_FETCH_TIMEOUT_MS, runtime = {}) {
1563
1425
  this.apiUrl = apiUrl;
1564
1426
  this.token = token;
1565
1427
  this.fetchFn = fetchFn;
1566
1428
  this.fetchTimeoutMs = fetchTimeoutMs;
1429
+ this.runtime = runtime;
1567
1430
  }
1568
1431
  async search(params) {
1569
1432
  return withTelemetrySpan("githits.search.request", async () => {
@@ -1621,10 +1484,10 @@ class GitHitsServiceImpl {
1621
1484
  }
1622
1485
  headers() {
1623
1486
  return {
1624
- ...buildClientHeaders(),
1487
+ ...this.runtime.clientHeaders?.(),
1625
1488
  Authorization: `Bearer ${this.token}`,
1626
1489
  "Content-Type": "application/json",
1627
- "User-Agent": `githits-cli/${version}`
1490
+ "User-Agent": this.runtime.userAgent ?? "githits-cli"
1628
1491
  };
1629
1492
  }
1630
1493
  fetchOptions() {
@@ -1638,7 +1501,7 @@ class GitHitsServiceImpl {
1638
1501
  const body = await response.text().catch(() => "");
1639
1502
  switch (status) {
1640
1503
  case 401:
1641
- return new AuthenticationError("Authentication required. Run `githits login` to authenticate.");
1504
+ return new AuthenticationError(SERVER_AUTHENTICATION_REJECTED_MESSAGE, "server");
1642
1505
  case 403:
1643
1506
  return new Error("Access denied.");
1644
1507
  case 404:
@@ -1658,7 +1521,7 @@ class GitHitsServiceImpl {
1658
1521
  async function executeWithTokenRefresh(options) {
1659
1522
  const token = await options.getToken();
1660
1523
  if (!token) {
1661
- throw new AuthenticationError("Authentication required. Run `githits login` to authenticate.");
1524
+ throw new AuthenticationError(LOCAL_AUTHENTICATION_MISSING_MESSAGE, "local");
1662
1525
  }
1663
1526
  try {
1664
1527
  return await options.executeWithToken(token);
@@ -2636,10 +2499,12 @@ class CodeNavigationServiceImpl {
2636
2499
  codeNavigationUrl;
2637
2500
  tokenProvider;
2638
2501
  fetchFn;
2639
- constructor(codeNavigationUrl, tokenProvider, fetchFn = globalThis.fetch) {
2502
+ runtime;
2503
+ constructor(codeNavigationUrl, tokenProvider, fetchFn = globalThis.fetch, runtime = {}) {
2640
2504
  this.codeNavigationUrl = codeNavigationUrl;
2641
2505
  this.tokenProvider = tokenProvider;
2642
2506
  this.fetchFn = fetchFn;
2507
+ this.runtime = runtime;
2643
2508
  }
2644
2509
  async postGraphqlWithTargetResolutionFallback(input) {
2645
2510
  const response = await postPkgseerGraphql({
@@ -2647,7 +2512,9 @@ class CodeNavigationServiceImpl {
2647
2512
  token: input.token,
2648
2513
  query: input.query,
2649
2514
  variables: input.variables,
2650
- fetchFn: this.fetchFn
2515
+ fetchFn: this.fetchFn,
2516
+ clientHeaders: this.runtime.clientHeaders,
2517
+ userAgent: this.runtime.userAgent
2651
2518
  });
2652
2519
  if (response.status < 200 || response.status >= 300)
2653
2520
  return response;
@@ -2662,7 +2529,9 @@ class CodeNavigationServiceImpl {
2662
2529
  token: input.token,
2663
2530
  query: fallbackQuery,
2664
2531
  variables: input.variables,
2665
- fetchFn: this.fetchFn
2532
+ fetchFn: this.fetchFn,
2533
+ clientHeaders: this.runtime.clientHeaders,
2534
+ userAgent: this.runtime.userAgent
2666
2535
  });
2667
2536
  if (!hasSchemaMismatchErrors(fallbackResponse.parsedBody)) {
2668
2537
  return fallbackResponse;
@@ -2791,7 +2660,7 @@ class CodeNavigationServiceImpl {
2791
2660
  const status = response.status;
2792
2661
  const detail = parseDetail2(response.responseBody);
2793
2662
  if (status === 401) {
2794
- return new AuthenticationError("Authentication required. Run `githits login` to authenticate.");
2663
+ return new AuthenticationError(SERVER_AUTHENTICATION_REJECTED_MESSAGE, "server");
2795
2664
  }
2796
2665
  if (status === 403) {
2797
2666
  return new CodeNavigationAccessError(detail ?? "Code navigation access denied.");
@@ -2814,7 +2683,7 @@ class CodeNavigationServiceImpl {
2814
2683
  const retryable = typeof extensions?.retryable === "boolean" ? extensions.retryable : undefined;
2815
2684
  const indexingRef = getGraphQLIndexingRef(errors);
2816
2685
  if (isClientUpdateRequiredGraphQLError({ message, code })) {
2817
- return new ClientUpdateRequiredError;
2686
+ return new ClientUpdateRequiredError(undefined, undefined, this.runtime.clientVersion);
2818
2687
  }
2819
2688
  if (isGraphQLSchemaMismatchError({ message, code })) {
2820
2689
  const sanitized = "Backend protocol mismatch. Your CLI may be newer than the server, or the server may require a newer CLI. Run `githits update-check` to verify your installed version. Set GITHITS_DEBUG=code-nav-wire to inspect GraphQL details during local development.";
@@ -2856,7 +2725,7 @@ class CodeNavigationServiceImpl {
2856
2725
  case "FEATURE_FLAG_REQUIRED":
2857
2726
  return new CodeNavigationFeatureFlagRequiredError(message);
2858
2727
  case "UNAUTHORIZED":
2859
- return new AuthenticationError("Authentication required. Run `githits login` to authenticate.");
2728
+ return new AuthenticationError(SERVER_AUTHENTICATION_REJECTED_MESSAGE, "server");
2860
2729
  case "FORBIDDEN":
2861
2730
  return new CodeNavigationAccessError("Code navigation access denied. This feature may not be enabled for your account.");
2862
2731
  case "UPSTREAM_ERROR":
@@ -3459,6 +3328,7 @@ function isUnresolvableMessage(message) {
3459
3328
  const lower = message.toLowerCase();
3460
3329
  return lower.includes("could not resolve") || lower.includes("cannot resolve");
3461
3330
  }
3331
+
3462
3332
  // src/services/config.ts
3463
3333
  var DEFAULT_MCP_URL = "https://mcp.githits.com";
3464
3334
  var DEFAULT_API_URL = "https://api.githits.com";
@@ -3479,53 +3349,9 @@ function getCodeNavigationUrl() {
3479
3349
  function getEnvApiToken() {
3480
3350
  return process.env.GITHITS_API_TOKEN;
3481
3351
  }
3482
- // src/services/exec-service.ts
3483
- import { spawn } from "node:child_process";
3484
- function isWindowsAbsolutePath(command) {
3485
- return /^[a-zA-Z]:[\\/]/.test(command) || command.startsWith("\\\\");
3486
- }
3487
- function normalizeSpawnCommand(command, args, platform = process.platform) {
3488
- if (platform !== "win32") {
3489
- return { command, args };
3490
- }
3491
- if (isWindowsAbsolutePath(command) && /\s/.test(command)) {
3492
- return {
3493
- command: `"${command.replaceAll('"', "\\\"")}"`,
3494
- args,
3495
- shell: true
3496
- };
3497
- }
3498
- return { command, args, shell: true };
3499
- }
3500
3352
 
3501
- class ExecServiceImpl {
3502
- async exec(command, args) {
3503
- return new Promise((resolve, reject) => {
3504
- const spawnCommand = normalizeSpawnCommand(command, args);
3505
- const child = spawn(spawnCommand.command, spawnCommand.args, {
3506
- stdio: ["ignore", "pipe", "pipe"],
3507
- env: { ...process.env },
3508
- ...spawnCommand.shell !== undefined && { shell: spawnCommand.shell }
3509
- });
3510
- const stdoutChunks = [];
3511
- const stderrChunks = [];
3512
- child.stdout.on("data", (chunk) => stdoutChunks.push(chunk));
3513
- child.stderr.on("data", (chunk) => stderrChunks.push(chunk));
3514
- child.on("error", (error) => {
3515
- reject(error);
3516
- });
3517
- child.on("close", (code) => {
3518
- resolve({
3519
- exitCode: code ?? 1,
3520
- stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
3521
- stderr: Buffer.concat(stderrChunks).toString("utf-8")
3522
- });
3523
- });
3524
- });
3525
- }
3526
- }
3527
3353
  // src/services/filesystem-service.ts
3528
- import { randomUUID as randomUUID2 } from "node:crypto";
3354
+ import { randomUUID } from "node:crypto";
3529
3355
  import {
3530
3356
  mkdir,
3531
3357
  readdir,
@@ -3589,7 +3415,7 @@ class FileSystemServiceImpl {
3589
3415
  }
3590
3416
  }
3591
3417
  async atomicWriteFile(path, contents) {
3592
- const tmpPath = `${path}.${process.pid}.${randomUUID2()}.tmp`;
3418
+ const tmpPath = `${path}.${process.pid}.${randomUUID()}.tmp`;
3593
3419
  let mode = 384;
3594
3420
  try {
3595
3421
  const existing = await stat(path);
@@ -3606,6 +3432,7 @@ class FileSystemServiceImpl {
3606
3432
  }
3607
3433
  }
3608
3434
  }
3435
+
3609
3436
  // src/services/keychain-auth-storage.ts
3610
3437
  var SERVICE_NAME = "githits";
3611
3438
  var TOKEN_PREFIX = "v1:tokens:";
@@ -3704,6 +3531,7 @@ class KeychainAuthStorage {
3704
3531
  }
3705
3532
  }
3706
3533
  }
3534
+
3707
3535
  // src/services/keyring-service.ts
3708
3536
  import { Entry } from "@napi-rs/keyring";
3709
3537
 
@@ -3742,14 +3570,16 @@ class KeyringServiceImpl {
3742
3570
  }
3743
3571
  }
3744
3572
  }
3573
+
3745
3574
  // src/services/locked-auth-storage.ts
3575
+ import { AsyncLocalStorage } from "node:async_hooks";
3746
3576
  import { execFile } from "node:child_process";
3747
- import { randomUUID as randomUUID3 } from "node:crypto";
3577
+ import { randomUUID as randomUUID2 } from "node:crypto";
3748
3578
  import { mkdir as mkdir2, readFile as readFile2, rm, writeFile as writeFile2 } from "node:fs/promises";
3749
3579
  import { dirname as dirname2 } from "node:path";
3750
3580
  import { promisify } from "node:util";
3751
3581
  var LOCK_DIR = "auth.lock";
3752
- var LOCK_TIMEOUT_MS = 1e4;
3582
+ var LOCK_TIMEOUT_MS = DEFAULT_FETCH_TIMEOUT_MS * 2 + 1e4;
3753
3583
  var LOCK_RETRY_MS = 25;
3754
3584
  var ORPHANED_LOCK_MS = 5000;
3755
3585
  var OWNER_FILE = "owner.json";
@@ -3761,12 +3591,16 @@ class AuthStorageLockTimeoutError extends Error {
3761
3591
  this.name = "AuthStorageLockTimeoutError";
3762
3592
  }
3763
3593
  }
3594
+ function withAuthStorageLock(storage, fn) {
3595
+ return storage.withAuthStorageLock(fn);
3596
+ }
3764
3597
 
3765
3598
  class LockedAuthStorage {
3766
3599
  storage;
3767
3600
  lockPath;
3768
3601
  lockTimeoutMs;
3769
3602
  isOwnerAlive;
3603
+ lockContext = new AsyncLocalStorage;
3770
3604
  currentOwner = null;
3771
3605
  constructor(storage, fileSystemService, options = {}) {
3772
3606
  this.storage = storage;
@@ -3778,52 +3612,63 @@ class LockedAuthStorage {
3778
3612
  return this.storage.loadTokens(baseUrl2);
3779
3613
  }
3780
3614
  saveTokens(baseUrl2, data) {
3781
- return this.withLock(() => this.storage.saveTokens(baseUrl2, data));
3615
+ return this.withAuthStorageLock(() => this.storage.saveTokens(baseUrl2, data));
3782
3616
  }
3783
3617
  saveTokensIfUnchanged(baseUrl2, expected, data) {
3784
- return this.withLock(() => this.storage.saveTokensIfUnchanged(baseUrl2, expected, data));
3618
+ return this.withAuthStorageLock(() => this.storage.saveTokensIfUnchanged(baseUrl2, expected, data));
3785
3619
  }
3786
3620
  clearTokens(baseUrl2) {
3787
- return this.withLock(() => this.storage.clearTokens(baseUrl2));
3621
+ return this.withAuthStorageLock(() => this.storage.clearTokens(baseUrl2));
3788
3622
  }
3789
3623
  clearTokensIfUnchanged(baseUrl2, expected) {
3790
- return this.withLock(() => this.storage.clearTokensIfUnchanged(baseUrl2, expected));
3624
+ return this.withAuthStorageLock(() => this.storage.clearTokensIfUnchanged(baseUrl2, expected));
3791
3625
  }
3792
3626
  loadClient(baseUrl2) {
3793
3627
  return this.storage.loadClient(baseUrl2);
3794
3628
  }
3795
3629
  saveClient(baseUrl2, data) {
3796
- return this.withLock(() => this.storage.saveClient(baseUrl2, data));
3630
+ return this.withAuthStorageLock(() => this.storage.saveClient(baseUrl2, data));
3797
3631
  }
3798
3632
  clearClient(baseUrl2) {
3799
- return this.withLock(() => this.storage.clearClient(baseUrl2));
3633
+ return this.withAuthStorageLock(() => this.storage.clearClient(baseUrl2));
3800
3634
  }
3801
3635
  saveAuthSession(baseUrl2, client, tokens) {
3802
- return this.withLock(() => this.storage.saveAuthSession(baseUrl2, client, tokens));
3636
+ return this.withAuthStorageLock(() => this.storage.saveAuthSession(baseUrl2, client, tokens));
3803
3637
  }
3804
3638
  clearAuthSession(baseUrl2) {
3805
- return this.withLock(() => this.storage.clearAuthSession(baseUrl2));
3639
+ return this.withAuthStorageLock(() => this.storage.clearAuthSession(baseUrl2));
3806
3640
  }
3807
3641
  getStorageLocation() {
3808
3642
  return this.storage.getStorageLocation();
3809
3643
  }
3810
- async withLock(fn) {
3644
+ async withAuthStorageLock(fn) {
3645
+ const ownerId = this.lockContext.getStore();
3646
+ if (ownerId && this.currentOwner?.id === ownerId) {
3647
+ return fn();
3648
+ }
3811
3649
  await this.acquireLock();
3650
+ const acquiredOwnerId = this.currentOwner?.id;
3812
3651
  try {
3813
- return await fn();
3652
+ return await this.lockContext.run(acquiredOwnerId ?? "", fn);
3814
3653
  } finally {
3815
3654
  await this.releaseLock();
3816
3655
  }
3817
3656
  }
3818
3657
  async acquireLock() {
3658
+ const processStartedAt = await getProcessStartedAt(process.pid);
3819
3659
  const startedAt = Date.now();
3820
3660
  await mkdir2(dirname2(this.lockPath), { recursive: true, mode: 448 });
3821
3661
  while (true) {
3822
3662
  try {
3823
3663
  await mkdir2(this.lockPath, { recursive: false, mode: 448 });
3824
3664
  try {
3825
- await this.writeOwner();
3665
+ await this.writeOwner(processStartedAt);
3826
3666
  } catch (error) {
3667
+ this.currentOwner = null;
3668
+ if (error.code === "EEXIST") {
3669
+ await sleep(LOCK_RETRY_MS);
3670
+ continue;
3671
+ }
3827
3672
  await rm(this.lockPath, { recursive: true, force: true }).catch(() => {
3828
3673
  return;
3829
3674
  });
@@ -3841,15 +3686,18 @@ class LockedAuthStorage {
3841
3686
  }
3842
3687
  }
3843
3688
  }
3844
- async writeOwner() {
3689
+ async writeOwner(processStartedAt) {
3845
3690
  const owner = {
3846
- id: randomUUID3(),
3691
+ id: randomUUID2(),
3847
3692
  pid: process.pid,
3848
3693
  createdAt: new Date().toISOString(),
3849
- processStartedAt: await getProcessStartedAt(process.pid)
3694
+ processStartedAt
3850
3695
  };
3696
+ await writeFile2(this.ownerPath(), JSON.stringify(owner), {
3697
+ mode: 384,
3698
+ flag: "wx"
3699
+ });
3851
3700
  this.currentOwner = owner;
3852
- await writeFile2(this.ownerPath(), JSON.stringify(owner), { mode: 384 });
3853
3701
  }
3854
3702
  async reclaimStaleLock() {
3855
3703
  const owner = await this.readOwner();
@@ -3959,6 +3807,7 @@ async function lockCreatedAtMs(path) {
3959
3807
  return 0;
3960
3808
  }
3961
3809
  }
3810
+
3962
3811
  // src/services/mode-aware-file-auth-storage.ts
3963
3812
  class AuthStoragePolicyError extends Error {
3964
3813
  constructor(message) {
@@ -4390,6 +4239,7 @@ class MigratingAuthStorage {
4390
4239
  return a.accessToken === b.accessToken && a.refreshToken === b.refreshToken && a.expiresAt === b.expiresAt && a.createdAt === b.createdAt;
4391
4240
  }
4392
4241
  }
4242
+
4393
4243
  // src/services/package-intelligence-service.ts
4394
4244
  import { z as z3 } from "zod";
4395
4245
 
@@ -5389,10 +5239,12 @@ class PackageIntelligenceServiceImpl {
5389
5239
  endpointUrl;
5390
5240
  tokenProvider;
5391
5241
  fetchFn;
5392
- constructor(endpointUrl, tokenProvider, fetchFn = globalThis.fetch) {
5242
+ runtime;
5243
+ constructor(endpointUrl, tokenProvider, fetchFn = globalThis.fetch, runtime = {}) {
5393
5244
  this.endpointUrl = endpointUrl;
5394
5245
  this.tokenProvider = tokenProvider;
5395
5246
  this.fetchFn = fetchFn;
5247
+ this.runtime = runtime;
5396
5248
  }
5397
5249
  async packageSummary(params) {
5398
5250
  return withTelemetrySpan("pkg-intel.summary.request", () => executeWithTokenRefresh({
@@ -5413,7 +5265,9 @@ class PackageIntelligenceServiceImpl {
5413
5265
  registry: params.registry,
5414
5266
  name: params.packageName
5415
5267
  },
5416
- fetchFn: this.fetchFn
5268
+ fetchFn: this.fetchFn,
5269
+ clientHeaders: this.runtime.clientHeaders,
5270
+ userAgent: this.runtime.userAgent
5417
5271
  });
5418
5272
  } catch (cause) {
5419
5273
  if (cause instanceof PkgseerTransportError) {
@@ -5441,7 +5295,7 @@ class PackageIntelligenceServiceImpl {
5441
5295
  const status = response.status;
5442
5296
  const detail = parseDetail3(response.responseBody);
5443
5297
  if (status === 401) {
5444
- return new AuthenticationError("Authentication required. Run `githits login` to authenticate.");
5298
+ return new AuthenticationError(SERVER_AUTHENTICATION_REJECTED_MESSAGE, "server");
5445
5299
  }
5446
5300
  if (status === 403) {
5447
5301
  return new PackageIntelligenceAccessError(detail ?? "Access denied.");
@@ -5463,7 +5317,7 @@ class PackageIntelligenceServiceImpl {
5463
5317
  const code = typeof extensions?.code === "string" ? extensions.code : undefined;
5464
5318
  const retryable = typeof extensions?.retryable === "boolean" ? extensions.retryable : undefined;
5465
5319
  if (isClientUpdateRequiredGraphQLError({ message, code })) {
5466
- return new ClientUpdateRequiredError;
5320
+ return new ClientUpdateRequiredError(undefined, undefined, this.runtime.clientVersion);
5467
5321
  }
5468
5322
  if (isGraphQLSchemaMismatchError({ message, code })) {
5469
5323
  const sanitized = "Backend protocol mismatch. Your CLI may be newer than the server, or the server may require a newer CLI. Run `githits update-check` to verify your installed version. Set GITHITS_DEBUG=pkg-graphql to inspect GraphQL details during local development.";
@@ -5486,7 +5340,7 @@ class PackageIntelligenceServiceImpl {
5486
5340
  case "FEATURE_FLAG_REQUIRED":
5487
5341
  return new PackageIntelligenceFeatureFlagRequiredError(message);
5488
5342
  case "UNAUTHORIZED":
5489
- return new AuthenticationError("Authentication required. Run `githits login` to authenticate.");
5343
+ return new AuthenticationError(SERVER_AUTHENTICATION_REJECTED_MESSAGE, "server");
5490
5344
  case "FORBIDDEN":
5491
5345
  return new PackageIntelligenceAccessError("Access denied. This feature may not be enabled for your account.");
5492
5346
  case "UPSTREAM_ERROR":
@@ -5624,7 +5478,9 @@ class PackageIntelligenceServiceImpl {
5624
5478
  scope: params.advisoryScope,
5625
5479
  after
5626
5480
  },
5627
- fetchFn: this.fetchFn
5481
+ fetchFn: this.fetchFn,
5482
+ clientHeaders: this.runtime.clientHeaders,
5483
+ userAgent: this.runtime.userAgent
5628
5484
  });
5629
5485
  } catch (cause) {
5630
5486
  if (cause instanceof PkgseerTransportError) {
@@ -5728,7 +5584,9 @@ class PackageIntelligenceServiceImpl {
5728
5584
  lifecycle: params.includeGroups === true ? ["peer"] : undefined,
5729
5585
  minSeverity: params.minSeverity
5730
5586
  },
5731
- fetchFn: this.fetchFn
5587
+ fetchFn: this.fetchFn,
5588
+ clientHeaders: this.runtime.clientHeaders,
5589
+ userAgent: this.runtime.userAgent
5732
5590
  });
5733
5591
  } catch (cause) {
5734
5592
  if (cause instanceof PkgseerTransportError) {
@@ -5767,7 +5625,9 @@ class PackageIntelligenceServiceImpl {
5767
5625
  maxDepth: params.maxDepth,
5768
5626
  lifecycle: params.lifecycle && params.lifecycle.length > 0 ? params.lifecycle : undefined
5769
5627
  },
5770
- fetchFn: this.fetchFn
5628
+ fetchFn: this.fetchFn,
5629
+ clientHeaders: this.runtime.clientHeaders,
5630
+ userAgent: this.runtime.userAgent
5771
5631
  });
5772
5632
  } catch (cause) {
5773
5633
  if (cause instanceof PkgseerTransportError) {
@@ -6004,7 +5864,9 @@ class PackageIntelligenceServiceImpl {
6004
5864
  toVersion: params.toVersion,
6005
5865
  limit: params.limit
6006
5866
  },
6007
- fetchFn: this.fetchFn
5867
+ fetchFn: this.fetchFn,
5868
+ clientHeaders: this.runtime.clientHeaders,
5869
+ userAgent: this.runtime.userAgent
6008
5870
  });
6009
5871
  } catch (cause) {
6010
5872
  if (cause instanceof PkgseerTransportError) {
@@ -6079,7 +5941,9 @@ class PackageIntelligenceServiceImpl {
6079
5941
  limit: params.limit,
6080
5942
  after: params.after
6081
5943
  },
6082
- fetchFn: this.fetchFn
5944
+ fetchFn: this.fetchFn,
5945
+ clientHeaders: this.runtime.clientHeaders,
5946
+ userAgent: this.runtime.userAgent
6083
5947
  });
6084
5948
  } catch (cause) {
6085
5949
  if (cause instanceof PkgseerTransportError) {
@@ -6148,7 +6012,9 @@ class PackageIntelligenceServiceImpl {
6148
6012
  variables: {
6149
6013
  pageId: params.pageId
6150
6014
  },
6151
- fetchFn: this.fetchFn
6015
+ fetchFn: this.fetchFn,
6016
+ clientHeaders: this.runtime.clientHeaders,
6017
+ userAgent: this.runtime.userAgent
6152
6018
  });
6153
6019
  } catch (cause) {
6154
6020
  if (cause instanceof PkgseerTransportError) {
@@ -6233,40 +6099,18 @@ function parseVersionList(raw) {
6233
6099
  }
6234
6100
  return versions.length > 0 ? versions : undefined;
6235
6101
  }
6236
- // src/services/prompt-service.ts
6237
- import { checkbox, select } from "@inquirer/prompts";
6238
6102
 
6239
- class PromptServiceImpl {
6240
- async select(message, choices, defaultValue) {
6241
- return select({ message, choices, default: defaultValue });
6242
- }
6243
- async checkbox(message, choices) {
6244
- return checkbox({ message, choices });
6245
- }
6246
- async confirm3(message) {
6247
- return select({
6248
- message,
6249
- choices: [
6250
- { value: "yes", name: "Yes" },
6251
- { value: "no", name: "No" },
6252
- {
6253
- value: "always",
6254
- name: "Yes to all",
6255
- description: "Skip confirmation for remaining agents"
6256
- }
6257
- ]
6258
- });
6259
- }
6260
- }
6261
6103
  // src/services/refreshing-githits-service.ts
6262
6104
  class RefreshingGitHitsService {
6263
6105
  apiUrl;
6264
6106
  tokenProvider;
6265
6107
  serviceFactory;
6266
- constructor(apiUrl, tokenProvider, serviceFactory = (url, token) => new GitHitsServiceImpl(url, token)) {
6108
+ runtime;
6109
+ constructor(apiUrl, tokenProvider, serviceFactory, runtime = {}) {
6267
6110
  this.apiUrl = apiUrl;
6268
6111
  this.tokenProvider = tokenProvider;
6269
6112
  this.serviceFactory = serviceFactory;
6113
+ this.runtime = runtime;
6270
6114
  }
6271
6115
  async search(params) {
6272
6116
  return this.withTokenRefresh((service) => service.search(params));
@@ -6283,12 +6127,13 @@ class RefreshingGitHitsService {
6283
6127
  forceRefresh: () => this.tokenProvider.forceRefresh(),
6284
6128
  shouldRefresh: (error) => error instanceof AuthenticationError,
6285
6129
  executeWithToken: async (token) => {
6286
- const service = this.serviceFactory(this.apiUrl, token);
6130
+ const service = this.serviceFactory ? this.serviceFactory(this.apiUrl, token) : new GitHitsServiceImpl(this.apiUrl, token, undefined, undefined, this.runtime);
6287
6131
  return operation(service);
6288
6132
  }
6289
6133
  });
6290
6134
  }
6291
6135
  }
6136
+
6292
6137
  // src/services/token-manager.ts
6293
6138
  var PROACTIVE_REFRESH_RATIO = 0.9;
6294
6139
  function shouldRefreshToken(token, ratio, now) {
@@ -6327,11 +6172,19 @@ class TokenManager {
6327
6172
  }
6328
6173
  async getToken() {
6329
6174
  return withTelemetrySpan("token-manager.get-token", async () => {
6330
- if (this.forceRefreshPromise) {
6331
- return (await this.forceRefreshPromise).accessToken;
6175
+ const activeForceRefresh = this.forceRefreshPromise;
6176
+ if (activeForceRefresh) {
6177
+ return (await activeForceRefresh).accessToken;
6332
6178
  }
6333
6179
  if (!this.cachedToken) {
6334
- this.cachedToken = await withTelemetrySpan("token-manager.load-tokens", () => this.authStorage.loadTokens(this.mcpUrl));
6180
+ const storedToken = await withTelemetrySpan("token-manager.load-tokens", () => this.authStorage.loadTokens(this.mcpUrl));
6181
+ const startedForceRefresh = this.forceRefreshPromise;
6182
+ if (startedForceRefresh) {
6183
+ return (await startedForceRefresh).accessToken;
6184
+ }
6185
+ if (!this.cachedToken) {
6186
+ this.cachedToken = storedToken;
6187
+ }
6335
6188
  if (!this.cachedToken)
6336
6189
  return;
6337
6190
  }
@@ -6340,9 +6193,7 @@ class TokenManager {
6340
6193
  if (!shouldRefresh) {
6341
6194
  return currentToken;
6342
6195
  }
6343
- const refreshedToken = await this.doRefresh({
6344
- allowFreshExternalToken: true
6345
- });
6196
+ const refreshedToken = await this.refreshFromGetToken();
6346
6197
  if (refreshedToken) {
6347
6198
  return refreshedToken;
6348
6199
  }
@@ -6353,48 +6204,52 @@ class TokenManager {
6353
6204
  });
6354
6205
  }
6355
6206
  async forceRefresh() {
6356
- return withTelemetrySpan("token-manager.force-refresh", () => this.doRefresh({ allowFreshExternalToken: false }));
6207
+ return withTelemetrySpan("token-manager.force-refresh", () => this.refreshAfterAuthFailure());
6357
6208
  }
6358
- async doRefresh(options) {
6359
- const result = await this.doRefreshResult(options);
6209
+ async refreshFromGetToken() {
6210
+ const result = await this.softRefresh();
6360
6211
  return result.accessToken;
6361
6212
  }
6362
- async doRefreshResult(options) {
6363
- if (!options.allowFreshExternalToken) {
6364
- if (this.forceRefreshPromise)
6365
- return this.forceRefreshPromise;
6366
- this.forceRefreshPromise = (async () => {
6367
- const softResult = await this.softRefreshPromise?.catch(() => {
6368
- return;
6369
- });
6370
- if (softResult?.accessToken && softResult.refreshedViaEndpoint) {
6371
- return softResult;
6372
- }
6373
- return this.executeRefresh(options);
6374
- })();
6375
- try {
6376
- return await this.forceRefreshPromise;
6377
- } finally {
6378
- this.forceRefreshPromise = null;
6379
- }
6380
- }
6213
+ async softRefresh() {
6381
6214
  if (this.forceRefreshPromise)
6382
6215
  return this.forceRefreshPromise;
6383
6216
  if (this.softRefreshPromise)
6384
6217
  return this.softRefreshPromise;
6385
- this.softRefreshPromise = this.executeRefresh(options);
6218
+ this.softRefreshPromise = this.executeRefresh();
6386
6219
  try {
6387
6220
  return await this.softRefreshPromise;
6388
6221
  } finally {
6389
6222
  this.softRefreshPromise = null;
6390
6223
  }
6391
6224
  }
6392
- async executeRefresh(options) {
6393
- return withTelemetrySpan("token-manager.refresh", async () => {
6225
+ async refreshAfterAuthFailure() {
6226
+ const result = await this.forceEndpointRefresh();
6227
+ return result.accessToken;
6228
+ }
6229
+ async forceEndpointRefresh() {
6230
+ if (this.forceRefreshPromise)
6231
+ return this.forceRefreshPromise;
6232
+ this.forceRefreshPromise = (async () => {
6233
+ const softResult = await this.softRefreshPromise?.catch(() => {
6234
+ return;
6235
+ });
6236
+ if (softResult?.accessToken && softResult.refreshedViaEndpoint) {
6237
+ return softResult;
6238
+ }
6239
+ return this.executeRefresh();
6240
+ })();
6241
+ try {
6242
+ return await this.forceRefreshPromise;
6243
+ } finally {
6244
+ this.forceRefreshPromise = null;
6245
+ }
6246
+ }
6247
+ async executeRefresh() {
6248
+ return withAuthStorageLock(this.authStorage, () => withTelemetrySpan("token-manager.refresh", async () => {
6394
6249
  const candidate = await this.loadRefreshCandidate();
6395
6250
  if (!candidate)
6396
6251
  return refreshResult(undefined, false);
6397
- if (candidate.externallyUpdated && options.allowFreshExternalToken) {
6252
+ if (candidate.externallyUpdated) {
6398
6253
  const { shouldRefresh } = shouldRefreshToken(candidate.tokens, PROACTIVE_REFRESH_RATIO, new Date);
6399
6254
  if (!shouldRefresh)
6400
6255
  return refreshResult(candidate.tokens.accessToken, false);
@@ -6447,7 +6302,7 @@ class TokenManager {
6447
6302
  }
6448
6303
  this.cachedToken = newTokenData;
6449
6304
  return refreshResult(response.accessToken, true);
6450
- });
6305
+ }));
6451
6306
  }
6452
6307
  async resolveSuccessfulRefreshConflict(refreshedFrom, response, newTokenData) {
6453
6308
  const currentToken = await withTelemetrySpan("token-manager.reload-tokens", () => this.authStorage.loadTokens(this.mcpUrl));
@@ -6500,330 +6355,139 @@ function areSameTokenData(a, b) {
6500
6355
  function refreshResult(accessToken, refreshedViaEndpoint) {
6501
6356
  return { accessToken, refreshedViaEndpoint };
6502
6357
  }
6503
- // src/services/update-check-service.ts
6504
- import semver from "semver";
6505
- var NPM_DIST_TAGS_URL = "https://registry.npmjs.org/-/package/githits/dist-tags";
6506
- var NPM_PACKAGE_VERSION_URL = "https://registry.npmjs.org/githits";
6507
- var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
6508
- var FETCH_TIMEOUT_MS = 1000;
6509
- var DIR_MODE3 = 448;
6510
- var UPDATE_COMMAND = "npm i -g githits@latest";
6511
- var MAX_DEPRECATION_REASON_LENGTH = 200;
6512
6358
 
6513
- class NpmRegistryUpdateCheckService {
6514
- currentVersion;
6515
- fs;
6516
- fetcher;
6517
- env;
6518
- now;
6519
- checkIntervalMs;
6520
- fetchTimeoutMs;
6521
- configDir;
6522
- cachePath;
6523
- constructor(options) {
6524
- this.currentVersion = options.currentVersion;
6525
- this.fs = options.fileSystemService;
6526
- this.fetcher = options.fetcher ?? fetch;
6527
- this.env = options.env ?? process.env;
6528
- this.now = options.now ?? (() => new Date);
6529
- this.checkIntervalMs = options.checkIntervalMs ?? CHECK_INTERVAL_MS;
6530
- this.fetchTimeoutMs = options.fetchTimeoutMs ?? FETCH_TIMEOUT_MS;
6531
- this.configDir = this.fs.joinPath(resolveConfigHome(this.env, this.fs), "githits");
6532
- this.cachePath = this.fs.joinPath(this.configDir, "update-check.json");
6533
- }
6534
- async checkForUpdate(signal) {
6535
- const cache = await this.loadCache();
6536
- const latestDue = !cache || this.isCheckDue(cache);
6537
- const currentVersionStatusDue = this.isCurrentVersionStatusDue(cache?.currentVersionStatus);
6538
- const currentVersionStatus = await this.refreshCurrentVersionStatusIfDue(cache?.currentVersionStatus, signal);
6539
- const currentVersionStatusChanged = currentVersionStatusDue && !sameCurrentVersionStatus(currentVersionStatus, cache?.currentVersionStatus);
6540
- if (cache && !latestDue) {
6541
- if (currentVersionStatusChanged) {
6542
- await this.saveCache({
6543
- ...cache,
6544
- currentVersionStatus
6545
- });
6546
- }
6547
- return this.noticeFromLatest(cache.latestVersion);
6548
- }
6549
- const latestVersion = await this.fetchLatestVersion(signal);
6550
- if (!latestVersion) {
6551
- if (currentVersionStatusChanged) {
6552
- await this.saveCache({
6553
- ...cache,
6554
- currentVersionStatus
6555
- });
6556
- }
6557
- return this.noticeFromLatest(cache?.latestVersion);
6558
- }
6559
- await this.saveCache({
6560
- checkedAt: this.now().toISOString(),
6561
- latestVersion,
6562
- currentVersionStatus
6563
- });
6564
- return this.noticeFromLatest(latestVersion);
6565
- }
6566
- async refreshRequiredUpdateStatus(signal) {
6567
- const cache = await this.loadCache();
6568
- const currentVersionStatusDue = this.isCurrentVersionStatusDue(cache?.currentVersionStatus);
6569
- const currentVersionStatus = await this.refreshCurrentVersionStatusIfDue(cache?.currentVersionStatus, signal);
6570
- if (currentVersionStatusDue && !sameCurrentVersionStatus(currentVersionStatus, cache?.currentVersionStatus)) {
6571
- await this.saveCache({
6572
- ...cache,
6573
- currentVersionStatus
6574
- });
6575
- }
6576
- }
6577
- async getRequiredUpdateNotice() {
6578
- const cache = await this.loadCache();
6579
- const status = cache?.currentVersionStatus;
6580
- if (!status || status.version !== this.currentVersion || !status.deprecatedReason) {
6581
- return;
6582
- }
6583
- return {
6584
- currentVersion: this.currentVersion,
6585
- ...cache.latestVersion ? { latestKnownVersion: cache.latestVersion } : {},
6586
- reason: status.deprecatedReason,
6587
- updateCommand: formatUpdateCommand(this.env)
6588
- };
6589
- }
6590
- noticeFromLatest(latestVersion) {
6591
- if (!latestVersion || !semver.valid(latestVersion) || !semver.valid(this.currentVersion) || !semver.gt(latestVersion, this.currentVersion)) {
6592
- return;
6593
- }
6594
- return {
6595
- currentVersion: this.currentVersion,
6596
- latestVersion,
6597
- updateCommand: UPDATE_COMMAND
6598
- };
6599
- }
6600
- isCheckDue(cache) {
6601
- if (!cache.checkedAt || !cache.latestVersion) {
6602
- return true;
6603
- }
6604
- const checkedAtMs = Date.parse(cache.checkedAt);
6605
- if (Number.isNaN(checkedAtMs)) {
6606
- return true;
6607
- }
6608
- return this.now().getTime() - checkedAtMs >= this.checkIntervalMs;
6609
- }
6610
- isCurrentVersionStatusDue(status) {
6611
- if (!status || status.version !== this.currentVersion) {
6612
- return true;
6613
- }
6614
- const checkedAtMs = Date.parse(status.checkedAt);
6615
- if (Number.isNaN(checkedAtMs)) {
6616
- return true;
6617
- }
6618
- return this.now().getTime() - checkedAtMs >= this.checkIntervalMs;
6619
- }
6620
- async refreshCurrentVersionStatusIfDue(cached, signal) {
6621
- const reusableCached = cached?.version === this.currentVersion ? cached : undefined;
6622
- if (!this.isCurrentVersionStatusDue(reusableCached)) {
6623
- return reusableCached;
6624
- }
6625
- const remote = await this.fetchCurrentVersionStatus(signal);
6626
- if (!remote) {
6627
- return reusableCached;
6628
- }
6629
- return remote;
6630
- }
6631
- async fetchLatestVersion(signal) {
6632
- try {
6633
- const timeoutSignal = AbortSignal.timeout(this.fetchTimeoutMs);
6634
- const response = await this.fetcher(NPM_DIST_TAGS_URL, {
6635
- signal: signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal
6636
- });
6637
- if (!response.ok) {
6638
- return;
6639
- }
6640
- const body = await response.json();
6641
- if (!body || typeof body !== "object" || typeof body.latest !== "string") {
6642
- return;
6643
- }
6644
- const latest = body.latest;
6645
- return semver.valid(latest) ? latest : undefined;
6646
- } catch {
6647
- return;
6648
- }
6649
- }
6650
- async fetchCurrentVersionStatus(signal) {
6651
- try {
6652
- const timeoutSignal = AbortSignal.timeout(this.fetchTimeoutMs);
6653
- const response = await this.fetcher(`${NPM_PACKAGE_VERSION_URL}/${this.currentVersion}`, {
6654
- signal: signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal
6655
- });
6656
- if (!response.ok) {
6657
- return;
6658
- }
6659
- const body = await response.json();
6660
- if (!body || typeof body !== "object") {
6661
- return;
6662
- }
6663
- const rawDeprecated = body.deprecated;
6664
- const deprecatedReason = typeof rawDeprecated === "string" ? sanitizeDeprecationReason(rawDeprecated) : undefined;
6665
- return {
6666
- version: this.currentVersion,
6667
- checkedAt: this.now().toISOString(),
6668
- ...deprecatedReason ? { deprecatedReason } : {}
6669
- };
6670
- } catch {
6671
- return;
6672
- }
6673
- }
6674
- async loadCache() {
6675
- try {
6676
- if (!await this.fs.exists(this.cachePath)) {
6677
- return;
6678
- }
6679
- const raw = await this.fs.readFile(this.cachePath);
6680
- const parsed = JSON.parse(raw);
6681
- const currentVersionStatus = parseCurrentVersionStatus(parsed.currentVersionStatus);
6682
- const hasLatest = typeof parsed.checkedAt === "string" && typeof parsed.latestVersion === "string";
6683
- if (!hasLatest && !currentVersionStatus) {
6684
- return;
6685
- }
6686
- return {
6687
- ...hasLatest ? {
6688
- checkedAt: parsed.checkedAt,
6689
- latestVersion: parsed.latestVersion
6690
- } : {},
6691
- currentVersionStatus
6692
- };
6693
- } catch {
6694
- return;
6359
+ // src/shared/request-headers.ts
6360
+ import { createHash as createHash2, randomUUID as randomUUID3 } from "node:crypto";
6361
+ var MAX_HEADER_BYTES = 256;
6362
+ var SESSION_ENV_VARS = [
6363
+ "TERM_SESSION_ID",
6364
+ "ITERM_SESSION_ID",
6365
+ "WEZTERM_PANE",
6366
+ "KITTY_PID",
6367
+ "ALACRITTY_SOCKET",
6368
+ "WT_SESSION",
6369
+ "VSCODE_PID",
6370
+ "SUPERSET_PANE_ID",
6371
+ "SUPERSET_WORKSPACE_ID",
6372
+ "STARSHIP_SESSION_KEY",
6373
+ "SSH_CONNECTION"
6374
+ ];
6375
+ var cachedSessionId;
6376
+ function resolveRawSessionId(env = process.env, ppid = process.ppid) {
6377
+ for (const key of SESSION_ENV_VARS) {
6378
+ const value = env[key];
6379
+ if (value && value.trim().length > 0) {
6380
+ return value.trim();
6695
6381
  }
6696
6382
  }
6697
- async saveCache(cache) {
6698
- try {
6699
- await this.fs.ensureDir(this.configDir, DIR_MODE3);
6700
- if (typeof this.fs.atomicWriteFile === "function") {
6701
- await this.fs.atomicWriteFile(this.cachePath, `${JSON.stringify(cache, null, 2)}
6702
- `);
6703
- return;
6704
- }
6705
- await this.fs.writeFile(this.cachePath, `${JSON.stringify(cache, null, 2)}
6706
- `, 384);
6707
- } catch {}
6708
- }
6709
- }
6710
- function resolveConfigHome(env, fs) {
6711
- const xdgConfigHome = env.XDG_CONFIG_HOME?.trim();
6712
- if (xdgConfigHome) {
6713
- return xdgConfigHome;
6383
+ if (typeof ppid === "number" && !Number.isNaN(ppid) && ppid > 0) {
6384
+ return String(ppid);
6714
6385
  }
6715
- return fs.joinPath(fs.getHomeDir(), ".config");
6386
+ return randomUUID3();
6716
6387
  }
6717
- function shouldRunUpdateCheck(input) {
6718
- if (input.stderrIsTTY !== true) {
6719
- return false;
6720
- }
6721
- const env = input.env ?? process.env;
6722
- if (env.CI || env.GITHITS_DISABLE_UPDATE_CHECK) {
6723
- return false;
6724
- }
6725
- if (isHelpOrVersionInvocation(input.args)) {
6726
- return false;
6727
- }
6728
- if (isLikelyEphemeralPackageRunner(env)) {
6729
- return false;
6388
+ function getSessionId(env, ppid) {
6389
+ if (cachedSessionId !== undefined && env === undefined && ppid === undefined) {
6390
+ return cachedSessionId;
6730
6391
  }
6731
- if (isMcpStdioInvocation(input.args, input.stdinIsTTY === true, input.stdoutIsTTY === true)) {
6732
- return false;
6392
+ const raw = resolveRawSessionId(env, ppid);
6393
+ const hashed = hashValue(raw);
6394
+ if (env === undefined && ppid === undefined) {
6395
+ cachedSessionId = hashed;
6733
6396
  }
6734
- return true;
6397
+ return hashed;
6735
6398
  }
6736
- function shouldRunRequiredUpdateEnforcement(input) {
6737
- if (isHelpOrVersionInvocation(input.args)) {
6738
- return false;
6739
- }
6740
- const env = input.env ?? process.env;
6741
- if (isLikelyEphemeralPackageRunner(env)) {
6742
- return false;
6743
- }
6744
- return true;
6399
+ function hashValue(input) {
6400
+ return createHash2("sha256").update(input).digest("hex").slice(0, 16);
6745
6401
  }
6746
- function formatUpdateNotice(notice) {
6747
- return `Update available: githits ${notice.currentVersion} -> ${notice.latestVersion}
6748
- Run: ${notice.updateCommand}`;
6402
+ var AGENT_PROBES = [
6403
+ { envVar: "OPENCODE", name: "opencode" },
6404
+ { envVar: "CLAUDECODE", name: "claude-code" },
6405
+ { envVar: "CURSOR_TRACE_ID", name: "cursor" },
6406
+ { envVar: "WINDSURF_CONFIG_DIR", name: "windsurf" },
6407
+ { envVar: "ZED_TERM", name: "zed" },
6408
+ { envVar: "VSCODE_PID", name: "vscode" }
6409
+ ];
6410
+ function parseAgentString(raw) {
6411
+ const trimmed = raw.trim();
6412
+ if (trimmed.length === 0)
6413
+ return;
6414
+ const slashIndex = trimmed.indexOf("/");
6415
+ if (slashIndex === -1)
6416
+ return { name: trimmed };
6417
+ const name = trimmed.slice(0, slashIndex);
6418
+ const ver = trimmed.slice(slashIndex + 1);
6419
+ if (name.length === 0)
6420
+ return;
6421
+ return { name, version: ver || undefined };
6749
6422
  }
6750
- function formatRequiredUpdateNotice(notice) {
6751
- const lines = [
6752
- `Update required: ${notice.reason}`,
6753
- "",
6754
- `Installed githits ${notice.currentVersion} is no longer supported.`
6755
- ];
6756
- if (notice.latestKnownVersion) {
6757
- lines.push(`Latest known version: ${notice.latestKnownVersion}`);
6758
- }
6759
- lines.push("Update with:", ` ${notice.updateCommand}`);
6760
- return [...lines].join(`
6761
- `);
6423
+ function formatAgentInfo(info) {
6424
+ return info.version ? `${info.name}/${info.version}` : info.name;
6762
6425
  }
6763
- function formatUpdateCommand(env = process.env) {
6764
- const userAgent = env.npm_config_user_agent ?? "";
6765
- const execPath = env.npm_execpath ?? "";
6766
- const signal = `${userAgent} ${execPath}`.toLowerCase();
6767
- if (signal.includes("pnpm")) {
6768
- return "pnpm add -g githits@latest";
6769
- }
6770
- if (signal.includes("yarn")) {
6771
- return "yarn global add githits@latest";
6426
+ function resolveAgentInfo(env = process.env) {
6427
+ const explicit = env.GITHITS_AGENT;
6428
+ if (explicit && explicit.trim().length > 0) {
6429
+ return parseAgentString(explicit);
6772
6430
  }
6773
- if (signal.includes("bun")) {
6774
- return "bun add -g githits@latest";
6431
+ for (const probe of AGENT_PROBES) {
6432
+ const value = env[probe.envVar];
6433
+ if (value && value.trim().length > 0) {
6434
+ return { name: probe.name };
6435
+ }
6775
6436
  }
6776
- return UPDATE_COMMAND;
6437
+ return;
6777
6438
  }
6778
- function parseCurrentVersionStatus(value) {
6779
- if (!value || typeof value !== "object") {
6439
+ var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
6440
+ function sanitizeHeaderValue(value) {
6441
+ if (value === undefined || value === null || typeof value !== "string") {
6780
6442
  return;
6781
6443
  }
6782
- const status = value;
6783
- if (typeof status.version !== "string") {
6444
+ const cleaned = value.replace(CONTROL_CHARS, "").trim();
6445
+ if (cleaned.length === 0)
6784
6446
  return;
6785
- }
6786
- if (typeof status.checkedAt !== "string") {
6447
+ if (Buffer.byteLength(cleaned, "utf8") > MAX_HEADER_BYTES)
6787
6448
  return;
6788
- }
6789
- const deprecatedReason = typeof status.deprecatedReason === "string" ? sanitizeDeprecationReason(status.deprecatedReason) : undefined;
6790
- return {
6791
- version: status.version,
6792
- checkedAt: status.checkedAt,
6793
- ...deprecatedReason ? { deprecatedReason } : {}
6794
- };
6795
- }
6796
- function sameCurrentVersionStatus(left, right) {
6797
- return left?.version === right?.version && left?.checkedAt === right?.checkedAt && left?.deprecatedReason === right?.deprecatedReason;
6798
- }
6799
- function sanitizeDeprecationReason(value) {
6800
- const sanitized = Array.from(value).map((character) => isControlCharacter(character) ? " " : character).join("").replace(/\s+/g, " ").trim().slice(0, MAX_DEPRECATION_REASON_LENGTH).trim();
6801
- return sanitized.length > 0 ? sanitized : undefined;
6802
- }
6803
- function isControlCharacter(value) {
6804
- const code = value.charCodeAt(0);
6805
- return code <= 31 || code >= 127 && code <= 159;
6806
- }
6807
- function isHelpOrVersionInvocation(args) {
6808
- return args.length === 0 || args[0] === "help" || args.includes("--help") || args.includes("-h") || args.includes("--version") || args.includes("-V");
6449
+ return cleaned;
6809
6450
  }
6810
- function isLikelyEphemeralPackageRunner(env) {
6811
- const lifecycleEvent = env.npm_lifecycle_event;
6812
- if (lifecycleEvent === "npx" || lifecycleEvent === "bunx") {
6813
- return true;
6814
- }
6815
- const userAgent = env.npm_config_user_agent ?? "";
6816
- return env.npm_command === "exec" && (userAgent.startsWith("npm/") || userAgent.startsWith("bun/"));
6451
+ function createClientHeaderBuilder(options) {
6452
+ return () => buildClientHeadersWithContext({
6453
+ clientName: options.clientName,
6454
+ clientVersion: options.clientVersion,
6455
+ agentProvider: options.agentProvider,
6456
+ env: options.env,
6457
+ ppid: options.ppid
6458
+ });
6817
6459
  }
6818
- function isMcpStdioInvocation(args, stdinIsTTY, stdoutIsTTY) {
6819
- const firstTokenIndex = args.findIndex((arg) => !arg.startsWith("-"));
6820
- if (firstTokenIndex === -1 || args[firstTokenIndex] !== "mcp") {
6821
- return false;
6460
+ function buildClientHeadersWithContext(context) {
6461
+ try {
6462
+ const headers = {};
6463
+ const name = sanitizeHeaderValue(context.clientName);
6464
+ if (name) {
6465
+ headers["x-githits-client-name"] = name;
6466
+ }
6467
+ const safeClientVersion = sanitizeHeaderValue(context.clientVersion);
6468
+ if (safeClientVersion) {
6469
+ headers["x-githits-client-version"] = safeClientVersion;
6470
+ }
6471
+ const agentInfo = context.agentProvider?.() ?? resolveAgentInfo(context.env);
6472
+ if (agentInfo) {
6473
+ const agentValue = sanitizeHeaderValue(formatAgentInfo(agentInfo));
6474
+ if (agentValue) {
6475
+ headers["x-githits-agent"] = agentValue;
6476
+ }
6477
+ }
6478
+ const sessionId = sanitizeHeaderValue(getSessionId(context.env, context.ppid));
6479
+ if (sessionId) {
6480
+ headers["x-githits-session-id"] = sessionId;
6481
+ }
6482
+ return headers;
6483
+ } catch {
6484
+ return {};
6822
6485
  }
6823
- const remainingArgs = args.slice(firstTokenIndex + 1);
6824
- return remainingArgs.includes("start") || !stdinIsTTY || !stdoutIsTTY;
6825
6486
  }
6487
+
6826
6488
  // src/container.ts
6489
+ var BASE_CLIENT_NAME = "githits-cli";
6490
+ var USER_AGENT = `${BASE_CLIENT_NAME}/${version}`;
6827
6491
  async function createAuthStorage(fileSystemService) {
6828
6492
  return withTelemetrySpan("container.create-auth-storage", async () => {
6829
6493
  const authConfig = await loadAuthConfig(fileSystemService);
@@ -6903,12 +6567,22 @@ async function createContainer(options = {}) {
6903
6567
  const fileSystemService = new FileSystemServiceImpl;
6904
6568
  const authService = new AuthServiceImpl;
6905
6569
  const browserService = new BrowserServiceImpl;
6570
+ const clientHeaders = createClientHeaderBuilder({
6571
+ clientName: options.clientName ?? BASE_CLIENT_NAME,
6572
+ clientVersion: version,
6573
+ agentProvider: options.agentProvider
6574
+ });
6575
+ const serviceRuntime = {
6576
+ clientHeaders,
6577
+ userAgent: USER_AGENT,
6578
+ clientVersion: version
6579
+ };
6906
6580
  const envToken = getEnvApiToken();
6907
6581
  if (envToken) {
6908
6582
  const authStorage2 = createAuthStorageForMode(fileSystemService, "keychain");
6909
6583
  const tokenProvider = createStaticTokenProvider(envToken);
6910
- const codeNavigationService2 = new CodeNavigationServiceImpl(codeNavigationUrl, tokenProvider);
6911
- const packageIntelligenceService2 = new PackageIntelligenceServiceImpl(codeNavigationUrl, tokenProvider);
6584
+ const codeNavigationService2 = new CodeNavigationServiceImpl(codeNavigationUrl, tokenProvider, globalThis.fetch, serviceRuntime);
6585
+ const packageIntelligenceService2 = new PackageIntelligenceServiceImpl(codeNavigationUrl, tokenProvider, globalThis.fetch, serviceRuntime);
6912
6586
  return {
6913
6587
  authStorage: authStorage2,
6914
6588
  authService,
@@ -6922,7 +6596,7 @@ async function createContainer(options = {}) {
6922
6596
  codeNavigationUrl,
6923
6597
  codeNavigationService: codeNavigationService2,
6924
6598
  packageIntelligenceService: packageIntelligenceService2,
6925
- githitsService: new GitHitsServiceImpl(apiUrl, envToken)
6599
+ githitsService: new GitHitsServiceImpl(apiUrl, envToken, undefined, undefined, serviceRuntime)
6926
6600
  };
6927
6601
  }
6928
6602
  const authStorage = await createAuthStorage(fileSystemService);
@@ -6931,8 +6605,8 @@ async function createContainer(options = {}) {
6931
6605
  if (resolveStoredToken && apiToken === undefined) {
6932
6606
  await new AuthSessionMetadataStorage(fileSystemService).clear(mcpUrl);
6933
6607
  }
6934
- const codeNavigationService = new CodeNavigationServiceImpl(codeNavigationUrl, tokenManager);
6935
- const packageIntelligenceService = new PackageIntelligenceServiceImpl(codeNavigationUrl, tokenManager);
6608
+ const codeNavigationService = new CodeNavigationServiceImpl(codeNavigationUrl, tokenManager, globalThis.fetch, serviceRuntime);
6609
+ const packageIntelligenceService = new PackageIntelligenceServiceImpl(codeNavigationUrl, tokenManager, globalThis.fetch, serviceRuntime);
6936
6610
  return {
6937
6611
  authStorage,
6938
6612
  authService,
@@ -6946,9 +6620,9 @@ async function createContainer(options = {}) {
6946
6620
  codeNavigationUrl,
6947
6621
  codeNavigationService,
6948
6622
  packageIntelligenceService,
6949
- githitsService: new RefreshingGitHitsService(apiUrl, tokenManager)
6623
+ githitsService: new RefreshingGitHitsService(apiUrl, tokenManager, undefined, serviceRuntime)
6950
6624
  };
6951
6625
  });
6952
6626
  }
6953
6627
 
6954
- export { getAppConfigDirForEnv, getAuthConfigPathForEnv, getAuthFileStorageDirForEnv, getLegacyAuthStorageDirForEnv, getLegacyMacAuthConfigPathForEnv, getLegacyMacAuthFileStorageDirForEnv, AuthConfigError, parseAuthStorageMode, normalizeBaseUrl, CLIENT_UPDATE_REQUIRED_REASON, ClientUpdateRequiredError, debugLog, setMcpClientVersionProvider, setClientMode, isTelemetryEnabled, withTelemetrySpan, startTelemetrySpan, endTelemetrySpan, flushTelemetry, AuthenticationError, CodeNavigationAccessError, CodeNavigationGraphQLError, CodeNavigationIndexingError, CodeNavigationUnresolvableError, MalformedCodeNavigationResponseError, CodeNavigationTargetNotFoundError, CodeNavigationFileNotFoundError, CodeNavigationVersionNotFoundError, CodeNavigationValidationError, CodeNavigationFeatureFlagRequiredError, CodeNavigationNetworkError, CodeNavigationBackendError, DEFAULT_MCP_URL, DEFAULT_API_URL, DEFAULT_CODE_NAV_URL, getCodeNavigationUrl, ExecServiceImpl, FileSystemServiceImpl, AuthStorageLockTimeoutError, AuthStoragePolicyError, PackageIntelligenceAccessError, PackageIntelligenceFeatureFlagRequiredError, PackageIntelligenceNetworkError, PackageIntelligenceBackendError, PackageIntelligenceGraphQLError, PackageIntelligenceTargetNotFoundError, PackageIntelligenceValidationError, PackageIntelligenceVersionNotFoundError, MalformedPackageIntelligenceResponseError, PackageIntelligenceChangelogSourceNotFoundError, PromptServiceImpl, refreshExpiredToken, NpmRegistryUpdateCheckService, shouldRunUpdateCheck, shouldRunRequiredUpdateEnforcement, formatUpdateNotice, formatRequiredUpdateNotice, loadAutoLoginAuthSessionMetadata, clearAutoLoginAuthSessionMetadata, createAuthCommandDependencies, createAuthStatusDependencies, createContainer };
6628
+ export { getAppConfigDirForEnv, getAuthConfigPathForEnv, getAuthFileStorageDirForEnv, getLegacyAuthStorageDirForEnv, getLegacyMacAuthConfigPathForEnv, getLegacyMacAuthFileStorageDirForEnv, AuthConfigError, parseAuthStorageMode, AuthStorageLockTimeoutError, AuthStoragePolicyError, isTelemetryEnabled, withTelemetrySpan, startTelemetrySpan, endTelemetrySpan, flushTelemetry, LOCAL_AUTHENTICATION_MISSING_MESSAGE, AuthenticationError, normalizeBaseUrl, debugLog, CLIENT_UPDATE_REQUIRED_REASON, ClientUpdateRequiredError, CodeNavigationAccessError, CodeNavigationGraphQLError, CodeNavigationIndexingError, CodeNavigationUnresolvableError, MalformedCodeNavigationResponseError, CodeNavigationTargetNotFoundError, CodeNavigationFileNotFoundError, CodeNavigationVersionNotFoundError, CodeNavigationValidationError, CodeNavigationFeatureFlagRequiredError, CodeNavigationNetworkError, CodeNavigationBackendError, DEFAULT_MCP_URL, DEFAULT_API_URL, DEFAULT_CODE_NAV_URL, getCodeNavigationUrl, FileSystemServiceImpl, PackageIntelligenceAccessError, PackageIntelligenceFeatureFlagRequiredError, PackageIntelligenceNetworkError, PackageIntelligenceBackendError, PackageIntelligenceGraphQLError, PackageIntelligenceTargetNotFoundError, PackageIntelligenceValidationError, PackageIntelligenceVersionNotFoundError, MalformedPackageIntelligenceResponseError, PackageIntelligenceChangelogSourceNotFoundError, refreshExpiredToken, loadAutoLoginAuthSessionMetadata, clearAutoLoginAuthSessionMetadata, createAuthCommandDependencies, createAuthStatusDependencies, createContainer };