githits 0.3.0 → 0.3.1

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.
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "GitHits plugins for Claude Code - code examples from global open source",
9
- "version": "0.3.0"
9
+ "version": "0.3.1"
10
10
  },
11
11
  "plugins": [
12
12
  {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githits",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Code examples from global open source for developers and AI assistants",
5
5
  "author": {
6
6
  "name": "GitHits"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githits",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Code examples from global open source for developers and AI assistants",
5
5
  "author": {
6
6
  "name": "GitHits"
package/dist/cli.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  AuthConfigError,
4
+ AuthStorageLockTimeoutError,
4
5
  AuthStoragePolicyError,
5
6
  AuthenticationError,
6
7
  CLIENT_UPDATE_REQUIRED_REASON,
@@ -48,15 +49,59 @@ import {
48
49
  shouldRunUpdateCheck,
49
50
  startTelemetrySpan,
50
51
  withTelemetrySpan
51
- } from "./shared/chunk-5mk9k2gv.js";
52
+ } from "./shared/chunk-0s7mxdt3.js";
52
53
  import {
53
54
  __require,
54
55
  version
55
- } from "./shared/chunk-gxya097b.js";
56
+ } from "./shared/chunk-m1xx8hzw.js";
56
57
 
57
58
  // src/cli.ts
58
59
  import { Command } from "commander";
59
60
 
61
+ // src/shared/require-auth.ts
62
+ class AuthRequiredError extends Error {
63
+ constructor(message) {
64
+ super(message);
65
+ this.name = "AuthRequiredError";
66
+ }
67
+ }
68
+ function requireAuth(deps, context) {
69
+ if (deps.hasValidToken)
70
+ return;
71
+ const suffix = context ? ` ${context}` : "";
72
+ console.log(`Authentication required${suffix}.
73
+ `);
74
+ if (deps.mcpUrl !== "https://mcp.githits.com") {
75
+ console.log(` Environment: ${deps.mcpUrl}`);
76
+ console.log(` You're using a custom environment.
77
+ `);
78
+ }
79
+ console.log("To authenticate:");
80
+ console.log(` githits login
81
+ `);
82
+ console.log("Or set GITHITS_API_TOKEN environment variable.");
83
+ console.log(`
84
+ Need help? support@githits.com`);
85
+ throw new AuthRequiredError(`Authentication required${suffix}`);
86
+ }
87
+
88
+ // src/cli/errors.ts
89
+ function handleCliError(error, deps) {
90
+ if (error instanceof AuthRequiredError) {
91
+ deps.exit(1);
92
+ }
93
+ if (isUserFacingError(error)) {
94
+ deps.stderr.write(`${error.message}
95
+
96
+ `);
97
+ deps.exit(1);
98
+ }
99
+ throw error;
100
+ }
101
+ function isUserFacingError(error) {
102
+ return error instanceof AuthConfigError || error instanceof AuthStorageLockTimeoutError || error instanceof AuthStoragePolicyError;
103
+ }
104
+
60
105
  // src/cli/update-check.ts
61
106
  function startUpdateCheckTask(service) {
62
107
  const controller = new AbortController;
@@ -522,7 +567,8 @@ function classify(error2) {
522
567
  return {
523
568
  code: "AUTH_REQUIRED",
524
569
  message: error2.message,
525
- retryable: false
570
+ retryable: false,
571
+ details: { action: "Run `githits login`, then retry this tool call." }
526
572
  };
527
573
  }
528
574
  if (error2 instanceof CodeNavigationNetworkError) {
@@ -2483,7 +2529,8 @@ function classify2(error2) {
2483
2529
  return {
2484
2530
  code: "AUTH_REQUIRED",
2485
2531
  message: error2.message,
2486
- retryable: false
2532
+ retryable: false,
2533
+ details: { action: "Run `githits login`, then retry this tool call." }
2487
2534
  };
2488
2535
  }
2489
2536
  if (error2 instanceof PackageIntelligenceNetworkError) {
@@ -3807,32 +3854,6 @@ function buildHeader3(envelope, useColors) {
3807
3854
  const prefix = envelope.registry && envelope.name ? `${envelope.registry}:${envelope.name}${envelope.version ? `@${envelope.version}` : ""}` : "documentation";
3808
3855
  return `${colorize(`${prefix} ${badge}`, "bold", useColors)}${title ? ` - ${title}` : ""}`;
3809
3856
  }
3810
- // src/shared/require-auth.ts
3811
- class AuthRequiredError extends Error {
3812
- constructor(message) {
3813
- super(message);
3814
- this.name = "AuthRequiredError";
3815
- }
3816
- }
3817
- function requireAuth(deps, context) {
3818
- if (deps.hasValidToken)
3819
- return;
3820
- const suffix = context ? ` ${context}` : "";
3821
- console.log(`Authentication required${suffix}.
3822
- `);
3823
- if (deps.mcpUrl !== "https://mcp.githits.com") {
3824
- console.log(` Environment: ${deps.mcpUrl}`);
3825
- console.log(` You're using a custom environment.
3826
- `);
3827
- }
3828
- console.log("To authenticate:");
3829
- console.log(` githits login
3830
- `);
3831
- console.log("Or set GITHITS_API_TOKEN environment variable.");
3832
- console.log(`
3833
- Need help? support@githits.com`);
3834
- throw new AuthRequiredError(`Authentication required${suffix}`);
3835
- }
3836
3857
  // src/shared/unified-search-request.ts
3837
3858
  var DEFAULT_UNIFIED_SEARCH_LIMIT = 10;
3838
3859
  function buildUnifiedSearchParams(input) {
@@ -5056,7 +5077,7 @@ grep run. --symbol-field hydrates enclosing symbol metadata (appears under each
5056
5077
  match in --verbose output; full payload in --json).`;
5057
5078
  function registerCodeGrepCommand(pkgCommand) {
5058
5079
  return pkgCommand.command("grep").summary("Deterministic text grep over indexed dependency source").description(PKG_GREP_DESCRIPTION).argument("[spec-or-pattern]", "Spec mode: package spec (e.g. npm:express). Repo mode (with --repo-url): the pattern.").argument("[pattern-or-prefix]", "Spec mode: the pattern. Repo mode: optional path-prefix.").argument("[path-prefix]", "Spec mode only: optional path-prefix. Ignored with --repo-url.").option("--repo-url <url>", "Repository URL addressing (requires --git-ref)").option("--git-ref <ref>", "Tag, commit, branch, or HEAD. Required with --repo-url.").option("--path <path>", "Exact file path to grep").option("--glob <glob>", "Glob scope (repeatable)", collectRepeatable, []).option("--ext <ext>", "Extension filter without leading dot (repeatable)", collectRepeatable, []).option("--regex", "Interpret the pattern as RE2 regex").option("--case-sensitive", "Enable ASCII case-sensitive matching").option("-C, --context <n>", "Context lines before and after each match (0-10)").option("-B, --before-context <n>", "Context lines before each match (0-10)").option("-A, --after-context <n>", "Context lines after each match (0-10)").option("--exclude-docs", "Skip files classified as documentation").option("--exclude-tests", "Skip files classified as tests").option("--limit <n>", "Max matches to return on this page (1-1000, default 50)").option("--per-file-limit <n>", "Cap matches per file within this page (0-1000, 0 = unlimited)").option("--cursor <cursor>", "Opaque nextCursor from a previous grep result").option("--symbol-field <field>", `Repeatable; surfaces in --json and under each --verbose match. ${GREP_REPO_SYMBOL_FIELDS_NOTE}`, collectRepeatable, []).option("--wait <ms>", `Indexing wait timeout (0-${MAX_WAIT_TIMEOUT_MS}, default ${DEFAULT_WAIT_TIMEOUT_MS})`).option("-v, --verbose", "Render grouped output with file headers").option("--json", "Emit the JSON envelope").action(async (arg1, arg2, arg3, options) => {
5059
- const { createContainer: createContainer2 } = await import("./shared/chunk-1gqfte6e.js");
5080
+ const { createContainer: createContainer2 } = await import("./shared/chunk-zg5dnven.js");
5060
5081
  const deps = await createContainer2();
5061
5082
  await pkgGrepAction(arg1, arg2, arg3, options, {
5062
5083
  codeNavigationService: deps.codeNavigationService,
@@ -5575,7 +5596,7 @@ function registerExampleCommand(program) {
5575
5596
  });
5576
5597
  }
5577
5598
  async function loadContainer() {
5578
- const { createContainer: createContainer2 } = await import("./shared/chunk-1gqfte6e.js");
5599
+ const { createContainer: createContainer2 } = await import("./shared/chunk-zg5dnven.js");
5579
5600
  return createContainer2();
5580
5601
  }
5581
5602
  // src/commands/feedback.ts
@@ -6364,14 +6385,11 @@ async function preflightAuthPersistence(authStorage, mcpUrl) {
6364
6385
  createdAt: new Date(0).toISOString()
6365
6386
  };
6366
6387
  try {
6367
- await authStorage.saveClient(probeUrl, probeClient);
6368
- await authStorage.saveTokens(probeUrl, probeTokens);
6369
- await authStorage.clearTokens(probeUrl);
6370
- await authStorage.clearClient(probeUrl);
6388
+ await authStorage.saveAuthSession(probeUrl, probeClient, probeTokens);
6389
+ await authStorage.clearAuthSession(probeUrl);
6371
6390
  return null;
6372
6391
  } catch (error2) {
6373
- await authStorage.clearTokens(probeUrl).catch(() => {});
6374
- await authStorage.clearClient(probeUrl).catch(() => {});
6392
+ await authStorage.clearAuthSession(probeUrl).catch(() => {});
6375
6393
  const message = error2 instanceof Error ? error2.message : String(error2);
6376
6394
  return {
6377
6395
  status: "failed",
@@ -6425,7 +6443,6 @@ async function loginFlow(options, deps) {
6425
6443
  redirectUri,
6426
6444
  registeredAt: new Date().toISOString()
6427
6445
  };
6428
- await authStorage.saveClient(mcpUrl, client);
6429
6446
  }
6430
6447
  port = options.port;
6431
6448
  } else {
@@ -6447,7 +6464,6 @@ async function loginFlow(options, deps) {
6447
6464
  redirectUri,
6448
6465
  registeredAt: new Date().toISOString()
6449
6466
  };
6450
- await authStorage.saveClient(mcpUrl, client);
6451
6467
  }
6452
6468
  const { verifier, challenge, state } = authService.generatePkceParams();
6453
6469
  const authUrl = authService.buildAuthUrl({
@@ -6512,7 +6528,7 @@ async function loginFlow(options, deps) {
6512
6528
  };
6513
6529
  }
6514
6530
  const expiresAt = new Date(Date.now() + tokenResponse.expiresIn * 1000).toISOString();
6515
- await authStorage.saveTokens(mcpUrl, {
6531
+ await authStorage.saveAuthSession(mcpUrl, client, {
6516
6532
  accessToken: tokenResponse.accessToken,
6517
6533
  refreshToken: tokenResponse.refreshToken,
6518
6534
  expiresAt,
@@ -6803,17 +6819,7 @@ function registerLanguagesCommand(program) {
6803
6819
  async function logoutAction(deps) {
6804
6820
  const { authStorage, mcpUrl } = deps;
6805
6821
  const auth = await authStorage.loadTokens(mcpUrl);
6806
- let firstError;
6807
- try {
6808
- await authStorage.clearTokens(mcpUrl);
6809
- } catch (error2) {
6810
- firstError = error2;
6811
- }
6812
- try {
6813
- await authStorage.clearClient(mcpUrl);
6814
- } catch (error2) {
6815
- firstError ??= error2;
6816
- }
6822
+ await authStorage.clearAuthSession(mcpUrl);
6817
6823
  if (!auth) {
6818
6824
  console.log(`Not currently logged in.
6819
6825
  `);
@@ -6823,8 +6829,6 @@ async function logoutAction(deps) {
6823
6829
  `);
6824
6830
  console.log(` Environment: ${mcpUrl}`);
6825
6831
  }
6826
- if (firstError)
6827
- throw firstError;
6828
6832
  }
6829
6833
  var LOGOUT_DESCRIPTION = `Remove stored credentials.
6830
6834
 
@@ -6870,8 +6874,9 @@ function classify3(operation, error2) {
6870
6874
  if (error2 instanceof AuthenticationError) {
6871
6875
  return {
6872
6876
  error: error2.message,
6873
- code: "UNAUTHENTICATED",
6874
- retryable: false
6877
+ code: "AUTH_REQUIRED",
6878
+ retryable: false,
6879
+ details: { action: "Run `githits login`, then retry this tool call." }
6875
6880
  };
6876
6881
  }
6877
6882
  const message = error2 instanceof Error ? error2.message : "Unknown error";
@@ -7318,17 +7323,15 @@ function buildPackageChangelogSuccessPayload(report, options) {
7318
7323
  }
7319
7324
  return lean;
7320
7325
  });
7321
- if (report.source == null) {
7322
- throw new Error("Changelog envelope builder received a null source — should have been promoted to NOT_FOUND at the service boundary.");
7323
- }
7324
7326
  const envelope = {
7325
- source: report.source,
7326
7327
  mode: options.mode,
7327
7328
  entries: {
7328
7329
  count: items.length,
7329
7330
  items
7330
7331
  }
7331
7332
  };
7333
+ if (report.source)
7334
+ envelope.source = report.source;
7332
7335
  if (options.registry)
7333
7336
  envelope.registry = options.registry;
7334
7337
  if (options.name)
@@ -7407,7 +7410,7 @@ function appendBodyLines(lines, body, options) {
7407
7410
  }
7408
7411
  function buildSummaryLine(envelope, options) {
7409
7412
  const identity = envelope.registry && envelope.name ? `${envelope.name} · ${envelope.registry}` : envelope.repoUrl ?? "(unknown)";
7410
- const sourceLabel = humanizeSource(envelope.source);
7413
+ const sourceLabel = envelope.source ? humanizeSource(envelope.source) : "package versions";
7411
7414
  const modeLabel = envelope.mode === "range" ? rangeLabel(envelope) : latestLabel(envelope);
7412
7415
  const countLabel = `${envelope.entries.count} ${plural2("entry", "entries", envelope.entries.count)}`;
7413
7416
  const parts = [identity, `source: ${sourceLabel}`, modeLabel, countLabel];
@@ -7476,7 +7479,7 @@ var schema6 = {
7476
7479
  git_ref: z7.string().optional().describe("Git branch or tag for CHANGELOG.md source (no effect on GitHub Releases or HexDocs). Defaults to the repository's default branch."),
7477
7480
  include_bodies: z7.boolean().optional().describe("When false, each entry in `entries.items[]` omits its `body` field. Default true. Set false when you only need the version / date / URL timeline — drops 10 KB+ per entry on large release notes.")
7478
7481
  };
7479
- var DESCRIPTION6 = "Release notes for a package or GitHub repo, newest-first. Default " + "latest mode returns the ten most recent entries (`limit` 1–50). " + "With `from_version`, returns every entry in the " + "`[from_version, to_version]` range (range mode, no count cap). " + "Address via `registry` + `package_name` or `repo_url` (mutually " + 'exclusive). Response: `source` (`"releases"` / `"changelog_file"` ' + '/ `"hexdocs"`), `mode` (`"latest"` or `"range"`), ' + "`entries: { count, items }` with full markdown bodies. Set " + "`include_bodies: false` for a version / date / URL timeline only. " + "Supports npm, PyPI, Hex, Crates, vcpkg, Zig, NuGet, Maven, " + "Packagist; returns `NOT_FOUND` when a package has no changelog " + "source.";
7482
+ var DESCRIPTION6 = "Release notes for a package or GitHub repo, newest-first. Default " + "latest mode returns the ten most recent entries (`limit` 1–50). " + "With `from_version`, returns every entry in the " + "`[from_version, to_version]` range (range mode, no count cap). " + "Address via `registry` + `package_name` or `repo_url` (mutually " + 'exclusive). Response includes optional `source` (`"releases"` / ' + '`"changelog_file"` / `"hexdocs"`) when a concrete changelog source ' + 'exists, `mode` (`"latest"` or `"range"`), ' + "`entries: { count, items }` with full markdown bodies. Set " + "`include_bodies: false` for a version / date / URL timeline only. " + "Package-version entries without changelog text succeed with `source` " + "omitted; no-source plus no entries returns `NOT_FOUND`. Supports npm, " + "PyPI, Hex, Crates, vcpkg, Zig, NuGet, Maven, Packagist.";
7480
7483
  function createPackageChangelogTool(service) {
7481
7484
  return {
7482
7485
  name: "pkg_changelog",
@@ -8663,7 +8666,7 @@ function requireSearchService(deps) {
8663
8666
  return deps.codeNavigationService;
8664
8667
  }
8665
8668
  async function loadContainer2() {
8666
- const { createContainer: createContainer2 } = await import("./shared/chunk-1gqfte6e.js");
8669
+ const { createContainer: createContainer2 } = await import("./shared/chunk-zg5dnven.js");
8667
8670
  return createContainer2();
8668
8671
  }
8669
8672
  function parseTargetSpecs(specs) {
@@ -9072,15 +9075,10 @@ registerAuthStatusCommand(authCommand);
9072
9075
  try {
9073
9076
  await runWithUpdateCheckFlush(() => withTelemetrySpan("cli.parse", () => program.parseAsync()), updateCheckTask, { stderr: process.stderr, requiredUpdateRefreshTask });
9074
9077
  } catch (error2) {
9075
- if (isUserFacingError(error2)) {
9076
- console.error(`${error2.message}
9077
- `);
9078
- process.exit(1);
9079
- }
9080
- throw error2;
9081
- }
9082
- function isUserFacingError(error2) {
9083
- return error2 instanceof AuthConfigError || error2 instanceof AuthStoragePolicyError;
9078
+ handleCliError(error2, {
9079
+ stderr: process.stderr,
9080
+ exit: process.exit
9081
+ });
9084
9082
  }
9085
9083
  function stripRootRegistrationOptions(args) {
9086
9084
  return args.filter((arg) => arg !== "--no-color");
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  version
3
- } from "./shared/chunk-gxya097b.js";
3
+ } from "./shared/chunk-m1xx8hzw.js";
4
4
  export {
5
5
  version
6
6
  };
@@ -1,6 +1,7 @@
1
1
  import {
2
+ __require,
2
3
  version
3
- } from "./chunk-gxya097b.js";
4
+ } from "./chunk-m1xx8hzw.js";
4
5
 
5
6
  // src/services/app-config-paths.ts
6
7
  var APP_DIR = "githits";
@@ -250,7 +251,7 @@ class AuthServiceImpl {
250
251
  const error = await response.text();
251
252
  throw new Error(`Token refresh failed: ${error}`);
252
253
  }
253
- return parseTokenResponse(await response.json());
254
+ return parseRefreshTokenResponse(await response.json());
254
255
  }
255
256
  }
256
257
  function parseTokenResponse(data) {
@@ -264,6 +265,17 @@ function parseTokenResponse(data) {
264
265
  expiresIn: d.expires_in || 3600
265
266
  };
266
267
  }
268
+ function parseRefreshTokenResponse(data) {
269
+ const d = data;
270
+ if (!d.access_token) {
271
+ throw new Error("Token response missing required fields");
272
+ }
273
+ return {
274
+ accessToken: d.access_token,
275
+ refreshToken: typeof d.refresh_token === "string" ? d.refresh_token : undefined,
276
+ expiresIn: d.expires_in || 3600
277
+ };
278
+ }
267
279
  function successHtml(title = "Authentication successful") {
268
280
  return `<!DOCTYPE html>
269
281
  <html><head><title>GitHits CLI</title>
@@ -429,6 +441,13 @@ class AuthStorageImpl {
429
441
  await this.fs.ensureDir(this.configDir, DIR_MODE);
430
442
  await this.fs.atomicWriteFile(this.authPath, JSON.stringify(stored, null, 2));
431
443
  }
444
+ async saveTokensIfUnchanged(baseUrl, expected, data) {
445
+ const current = await this.loadTokens(baseUrl);
446
+ if (!sameTokenData(current, expected))
447
+ return false;
448
+ await this.saveTokens(baseUrl, data);
449
+ return true;
450
+ }
432
451
  async clearTokens(baseUrl) {
433
452
  const stored = await this.loadAuthFile();
434
453
  if (!stored)
@@ -440,6 +459,13 @@ class AuthStorageImpl {
440
459
  await this.fs.atomicWriteFile(this.authPath, JSON.stringify(stored, null, 2));
441
460
  }
442
461
  }
462
+ async clearTokensIfUnchanged(baseUrl, expected) {
463
+ const current = await this.loadTokens(baseUrl);
464
+ if (!sameTokenData(current, expected))
465
+ return false;
466
+ await this.clearTokens(baseUrl);
467
+ return true;
468
+ }
443
469
  async loadClient(baseUrl) {
444
470
  const stored = await this.loadClientFile();
445
471
  if (!stored)
@@ -466,6 +492,13 @@ class AuthStorageImpl {
466
492
  await this.fs.ensureDir(this.configDir, DIR_MODE);
467
493
  await this.fs.atomicWriteFile(this.clientPath, JSON.stringify(stored, null, 2));
468
494
  }
495
+ async saveAuthSession(baseUrl, client, tokens) {
496
+ await this.saveClient(baseUrl, client);
497
+ await this.saveTokens(baseUrl, tokens);
498
+ }
499
+ async clearAuthSession(baseUrl) {
500
+ await clearAuthSessionBestEffort(() => this.clearTokens(baseUrl), () => this.clearClient(baseUrl));
501
+ }
469
502
  async loadAuthFile() {
470
503
  if (!await this.fs.exists(this.authPath))
471
504
  return null;
@@ -496,6 +529,26 @@ class AuthStorageImpl {
496
529
  function normalizeBaseUrl(url) {
497
530
  return url.replace(/\/+$/, "");
498
531
  }
532
+ function sameTokenData(a, b) {
533
+ if (a === null || b === null)
534
+ return a === b;
535
+ return a.accessToken === b.accessToken && a.refreshToken === b.refreshToken && a.expiresAt === b.expiresAt && a.createdAt === b.createdAt;
536
+ }
537
+ async function clearAuthSessionBestEffort(clearTokens, clearClient) {
538
+ let firstError;
539
+ try {
540
+ await clearTokens();
541
+ } catch (error) {
542
+ firstError = error;
543
+ }
544
+ try {
545
+ await clearClient();
546
+ } catch (error) {
547
+ firstError ??= error;
548
+ }
549
+ if (firstError)
550
+ throw firstError;
551
+ }
499
552
  // src/services/browser-service.ts
500
553
  import open from "open";
501
554
 
@@ -2698,10 +2751,24 @@ class KeychainAuthStorage {
2698
2751
  const key = `${TOKEN_PREFIX}${normalizeBaseUrl(baseUrl2)}`;
2699
2752
  this.keyring.setPassword(SERVICE_NAME, key, JSON.stringify(data));
2700
2753
  }
2754
+ async saveTokensIfUnchanged(baseUrl2, expected, data) {
2755
+ const current = await this.loadTokens(baseUrl2);
2756
+ if (!sameTokenData(current, expected))
2757
+ return false;
2758
+ await this.saveTokens(baseUrl2, data);
2759
+ return true;
2760
+ }
2701
2761
  async clearTokens(baseUrl2) {
2702
2762
  const key = `${TOKEN_PREFIX}${normalizeBaseUrl(baseUrl2)}`;
2703
2763
  this.keyring.deletePassword(SERVICE_NAME, key);
2704
2764
  }
2765
+ async clearTokensIfUnchanged(baseUrl2, expected) {
2766
+ const current = await this.loadTokens(baseUrl2);
2767
+ if (!sameTokenData(current, expected))
2768
+ return false;
2769
+ await this.clearTokens(baseUrl2);
2770
+ return true;
2771
+ }
2705
2772
  async loadClient(baseUrl2) {
2706
2773
  const key = `${CLIENT_PREFIX}${normalizeBaseUrl(baseUrl2)}`;
2707
2774
  const json = this.keyring.getPassword(SERVICE_NAME, key);
@@ -2718,6 +2785,13 @@ class KeychainAuthStorage {
2718
2785
  const key = `${CLIENT_PREFIX}${normalizeBaseUrl(baseUrl2)}`;
2719
2786
  this.keyring.deletePassword(SERVICE_NAME, key);
2720
2787
  }
2788
+ async saveAuthSession(baseUrl2, client, tokens) {
2789
+ await this.saveClient(baseUrl2, client);
2790
+ await this.saveTokens(baseUrl2, tokens);
2791
+ }
2792
+ async clearAuthSession(baseUrl2) {
2793
+ await clearAuthSessionBestEffort(() => this.clearTokens(baseUrl2), () => this.clearClient(baseUrl2));
2794
+ }
2721
2795
  getStorageLocation() {
2722
2796
  switch (process.platform) {
2723
2797
  case "darwin":
@@ -2767,6 +2841,223 @@ class KeyringServiceImpl {
2767
2841
  }
2768
2842
  }
2769
2843
  }
2844
+ // src/services/locked-auth-storage.ts
2845
+ import { execFile } from "node:child_process";
2846
+ import { randomUUID as randomUUID3 } from "node:crypto";
2847
+ import { mkdir as mkdir2, readFile as readFile2, rm, writeFile as writeFile2 } from "node:fs/promises";
2848
+ import { dirname as dirname2 } from "node:path";
2849
+ import { promisify } from "node:util";
2850
+ var LOCK_DIR = "auth.lock";
2851
+ var LOCK_TIMEOUT_MS = 1e4;
2852
+ var LOCK_RETRY_MS = 25;
2853
+ var ORPHANED_LOCK_MS = 5000;
2854
+ var OWNER_FILE = "owner.json";
2855
+ var execFileAsync = promisify(execFile);
2856
+
2857
+ class AuthStorageLockTimeoutError extends Error {
2858
+ constructor(message) {
2859
+ super(message);
2860
+ this.name = "AuthStorageLockTimeoutError";
2861
+ }
2862
+ }
2863
+
2864
+ class LockedAuthStorage {
2865
+ storage;
2866
+ lockPath;
2867
+ lockTimeoutMs;
2868
+ isOwnerAlive;
2869
+ currentOwner = null;
2870
+ constructor(storage, fileSystemService, options = {}) {
2871
+ this.storage = storage;
2872
+ this.lockTimeoutMs = options.lockTimeoutMs ?? LOCK_TIMEOUT_MS;
2873
+ this.isOwnerAlive = options.isOwnerAlive ?? isOriginalProcessAlive;
2874
+ this.lockPath = fileSystemService.joinPath(getAppConfigDir(fileSystemService), LOCK_DIR);
2875
+ }
2876
+ loadTokens(baseUrl2) {
2877
+ return this.storage.loadTokens(baseUrl2);
2878
+ }
2879
+ saveTokens(baseUrl2, data) {
2880
+ return this.withLock(() => this.storage.saveTokens(baseUrl2, data));
2881
+ }
2882
+ saveTokensIfUnchanged(baseUrl2, expected, data) {
2883
+ return this.withLock(() => this.storage.saveTokensIfUnchanged(baseUrl2, expected, data));
2884
+ }
2885
+ clearTokens(baseUrl2) {
2886
+ return this.withLock(() => this.storage.clearTokens(baseUrl2));
2887
+ }
2888
+ clearTokensIfUnchanged(baseUrl2, expected) {
2889
+ return this.withLock(() => this.storage.clearTokensIfUnchanged(baseUrl2, expected));
2890
+ }
2891
+ loadClient(baseUrl2) {
2892
+ return this.storage.loadClient(baseUrl2);
2893
+ }
2894
+ saveClient(baseUrl2, data) {
2895
+ return this.withLock(() => this.storage.saveClient(baseUrl2, data));
2896
+ }
2897
+ clearClient(baseUrl2) {
2898
+ return this.withLock(() => this.storage.clearClient(baseUrl2));
2899
+ }
2900
+ saveAuthSession(baseUrl2, client, tokens) {
2901
+ return this.withLock(() => this.storage.saveAuthSession(baseUrl2, client, tokens));
2902
+ }
2903
+ clearAuthSession(baseUrl2) {
2904
+ return this.withLock(() => this.storage.clearAuthSession(baseUrl2));
2905
+ }
2906
+ getStorageLocation() {
2907
+ return this.storage.getStorageLocation();
2908
+ }
2909
+ async withLock(fn) {
2910
+ await this.acquireLock();
2911
+ try {
2912
+ return await fn();
2913
+ } finally {
2914
+ await this.releaseLock();
2915
+ }
2916
+ }
2917
+ async acquireLock() {
2918
+ const startedAt = Date.now();
2919
+ await mkdir2(dirname2(this.lockPath), { recursive: true, mode: 448 });
2920
+ while (true) {
2921
+ try {
2922
+ await mkdir2(this.lockPath, { recursive: false, mode: 448 });
2923
+ try {
2924
+ await this.writeOwner();
2925
+ } catch (error) {
2926
+ await rm(this.lockPath, { recursive: true, force: true }).catch(() => {
2927
+ return;
2928
+ });
2929
+ throw error;
2930
+ }
2931
+ return;
2932
+ } catch (error) {
2933
+ if (error.code !== "EEXIST")
2934
+ throw error;
2935
+ await this.reclaimStaleLock();
2936
+ if (Date.now() - startedAt >= this.lockTimeoutMs) {
2937
+ throw new AuthStorageLockTimeoutError(`Timed out waiting for GitHits auth storage lock at ${this.lockPath}. If no githits process is running, remove this directory and retry.`);
2938
+ }
2939
+ await sleep(LOCK_RETRY_MS);
2940
+ }
2941
+ }
2942
+ }
2943
+ async writeOwner() {
2944
+ const owner = {
2945
+ id: randomUUID3(),
2946
+ pid: process.pid,
2947
+ createdAt: new Date().toISOString(),
2948
+ processStartedAt: await getProcessStartedAt(process.pid)
2949
+ };
2950
+ this.currentOwner = owner;
2951
+ await writeFile2(this.ownerPath(), JSON.stringify(owner), { mode: 384 });
2952
+ }
2953
+ async reclaimStaleLock() {
2954
+ const owner = await this.readOwner();
2955
+ if (!owner) {
2956
+ await this.reclaimOldOwnerlessLock();
2957
+ return;
2958
+ }
2959
+ const ownerDead = !await this.isOwnerAlive(owner.pid, owner.processStartedAt);
2960
+ if (!ownerDead)
2961
+ return;
2962
+ const currentOwner = await this.readOwner();
2963
+ if (!currentOwner || currentOwner.id !== owner.id)
2964
+ return;
2965
+ await rm(this.lockPath, { recursive: true, force: true }).catch(() => {
2966
+ return;
2967
+ });
2968
+ }
2969
+ async reclaimOldOwnerlessLock() {
2970
+ const createdAtMs = await lockCreatedAtMs(this.lockPath);
2971
+ if (Date.now() - createdAtMs < ORPHANED_LOCK_MS)
2972
+ return;
2973
+ await rm(this.lockPath, { recursive: true, force: true }).catch(() => {
2974
+ return;
2975
+ });
2976
+ }
2977
+ async readOwner() {
2978
+ try {
2979
+ const raw = await readFile2(this.ownerPath(), "utf8");
2980
+ const parsed = JSON.parse(raw);
2981
+ if (typeof parsed.id !== "string" || typeof parsed.pid !== "number" || typeof parsed.createdAt !== "string" || !(typeof parsed.processStartedAt === "string" || parsed.processStartedAt === null)) {
2982
+ return null;
2983
+ }
2984
+ return {
2985
+ id: parsed.id,
2986
+ pid: parsed.pid,
2987
+ createdAt: parsed.createdAt,
2988
+ processStartedAt: parsed.processStartedAt
2989
+ };
2990
+ } catch {
2991
+ return null;
2992
+ }
2993
+ }
2994
+ async releaseLock() {
2995
+ const owner = this.currentOwner;
2996
+ this.currentOwner = null;
2997
+ if (!owner)
2998
+ return;
2999
+ const currentOwner = await this.readOwner();
3000
+ if (!currentOwner || currentOwner.id !== owner.id)
3001
+ return;
3002
+ await rm(this.lockPath, { recursive: true, force: true }).catch(() => {
3003
+ return;
3004
+ });
3005
+ }
3006
+ ownerPath() {
3007
+ return `${this.lockPath}/${OWNER_FILE}`;
3008
+ }
3009
+ }
3010
+ function sleep(ms) {
3011
+ return new Promise((resolve) => setTimeout(resolve, ms));
3012
+ }
3013
+ async function isOriginalProcessAlive(pid, processStartedAt) {
3014
+ if (!isProcessAlive(pid))
3015
+ return false;
3016
+ if (!processStartedAt)
3017
+ return true;
3018
+ return await getProcessStartedAt(pid) === processStartedAt;
3019
+ }
3020
+ function isProcessAlive(pid) {
3021
+ if (pid <= 0)
3022
+ return false;
3023
+ try {
3024
+ process.kill(pid, 0);
3025
+ return true;
3026
+ } catch (error) {
3027
+ const code = error.code;
3028
+ return code === "EPERM";
3029
+ }
3030
+ }
3031
+ async function getProcessStartedAt(pid) {
3032
+ try {
3033
+ if (process.platform === "win32") {
3034
+ const { stdout: stdout2 } = await execFileAsync("powershell.exe", [
3035
+ "-NoProfile",
3036
+ "-Command",
3037
+ `(Get-Process -Id ${pid}).StartTime.ToUniversalTime().ToString('o')`
3038
+ ]);
3039
+ return stdout2.trim() || null;
3040
+ }
3041
+ const { stdout } = await execFileAsync("ps", [
3042
+ "-p",
3043
+ String(pid),
3044
+ "-o",
3045
+ "lstart="
3046
+ ]);
3047
+ const parsed = Date.parse(stdout.trim());
3048
+ return Number.isNaN(parsed) ? null : new Date(parsed).toISOString();
3049
+ } catch {
3050
+ return null;
3051
+ }
3052
+ }
3053
+ async function lockCreatedAtMs(path) {
3054
+ try {
3055
+ const { stat: stat2 } = await import("node:fs/promises");
3056
+ return (await stat2(path)).mtimeMs;
3057
+ } catch {
3058
+ return 0;
3059
+ }
3060
+ }
2770
3061
  // src/services/mode-aware-file-auth-storage.ts
2771
3062
  class AuthStoragePolicyError extends Error {
2772
3063
  constructor(message) {
@@ -2806,9 +3097,16 @@ class ModeAwareFileAuthStorage {
2806
3097
  this.assertFileMode();
2807
3098
  await this.storage.saveTokens(baseUrl2, data);
2808
3099
  }
3100
+ async saveTokensIfUnchanged(baseUrl2, expected, data) {
3101
+ this.assertFileMode();
3102
+ return this.storage.saveTokensIfUnchanged(baseUrl2, expected, data);
3103
+ }
2809
3104
  clearTokens(baseUrl2) {
2810
3105
  return this.storage.clearTokens(baseUrl2);
2811
3106
  }
3107
+ clearTokensIfUnchanged(baseUrl2, expected) {
3108
+ return this.storage.clearTokensIfUnchanged(baseUrl2, expected);
3109
+ }
2812
3110
  loadClient(baseUrl2) {
2813
3111
  return this.storage.loadClient(baseUrl2);
2814
3112
  }
@@ -2819,6 +3117,13 @@ class ModeAwareFileAuthStorage {
2819
3117
  clearClient(baseUrl2) {
2820
3118
  return this.storage.clearClient(baseUrl2);
2821
3119
  }
3120
+ async saveAuthSession(baseUrl2, client, tokens) {
3121
+ this.assertFileMode();
3122
+ await this.storage.saveAuthSession(baseUrl2, client, tokens);
3123
+ }
3124
+ clearAuthSession(baseUrl2) {
3125
+ return this.storage.clearAuthSession(baseUrl2);
3126
+ }
2822
3127
  getStorageLocation() {
2823
3128
  return this.storage.getStorageLocation();
2824
3129
  }
@@ -2864,6 +3169,13 @@ class MigratingAuthStorage {
2864
3169
  throw this.toPolicyError(error);
2865
3170
  }
2866
3171
  }
3172
+ async saveTokensIfUnchanged(baseUrl2, expected, data) {
3173
+ const current = await this.loadTokens(baseUrl2);
3174
+ if (!this.sameTokenData(current, expected))
3175
+ return false;
3176
+ await this.saveTokens(baseUrl2, data);
3177
+ return true;
3178
+ }
2867
3179
  async clearTokens(baseUrl2) {
2868
3180
  const primaryError = await this.clearBestEffort(() => this.primary.clearTokens(baseUrl2));
2869
3181
  await this.clearBestEffort(() => this.file.clearTokens(baseUrl2));
@@ -2872,6 +3184,13 @@ class MigratingAuthStorage {
2872
3184
  throw primaryError;
2873
3185
  }
2874
3186
  }
3187
+ async clearTokensIfUnchanged(baseUrl2, expected) {
3188
+ const current = await this.loadTokens(baseUrl2);
3189
+ if (!this.sameTokenData(current, expected))
3190
+ return false;
3191
+ await this.clearTokens(baseUrl2);
3192
+ return true;
3193
+ }
2875
3194
  async loadClient(baseUrl2) {
2876
3195
  if (this.mode === "file") {
2877
3196
  return this.loadClientFileMode(baseUrl2);
@@ -2897,6 +3216,25 @@ class MigratingAuthStorage {
2897
3216
  throw primaryError;
2898
3217
  }
2899
3218
  }
3219
+ async saveAuthSession(baseUrl2, client, tokens) {
3220
+ if (this.mode === "file") {
3221
+ await this.file.saveAuthSession(baseUrl2, client, tokens);
3222
+ return;
3223
+ }
3224
+ try {
3225
+ await this.primary.saveAuthSession(baseUrl2, client, tokens);
3226
+ } catch (error) {
3227
+ throw this.toPolicyError(error);
3228
+ }
3229
+ }
3230
+ async clearAuthSession(baseUrl2) {
3231
+ const primaryError = await this.clearBestEffort(() => this.primary.clearAuthSession(baseUrl2));
3232
+ await this.clearBestEffort(() => this.file.clearAuthSession(baseUrl2));
3233
+ await this.clearBestEffort(() => this.legacy.clearAuthSession(baseUrl2));
3234
+ if (primaryError && !(primaryError instanceof KeychainUnavailableError)) {
3235
+ throw primaryError;
3236
+ }
3237
+ }
2900
3238
  getStorageLocation() {
2901
3239
  return this.mode === "file" ? this.file.getStorageLocation() : this.primary.getStorageLocation();
2902
3240
  }
@@ -3103,6 +3441,11 @@ class MigratingAuthStorage {
3103
3441
  this.warnedAmbiguousPlaintext = true;
3104
3442
  this.onWarning("Warning: multiple plaintext auth entries exist with ambiguous timestamps; using the new config auth path and leaving the other entry intact.");
3105
3443
  }
3444
+ sameTokenData(a, b) {
3445
+ if (a === null || b === null)
3446
+ return a === b;
3447
+ return a.accessToken === b.accessToken && a.refreshToken === b.refreshToken && a.expiresAt === b.expiresAt && a.createdAt === b.createdAt;
3448
+ }
3106
3449
  }
3107
3450
  // src/services/package-intelligence-service.ts
3108
3451
  import { z as z3 } from "zod";
@@ -4283,12 +4626,12 @@ class PackageIntelligenceServiceImpl {
4283
4626
  return this.normaliseChangelogReport(data, params);
4284
4627
  }
4285
4628
  normaliseChangelogReport(data, params) {
4286
- const source = data.source ?? undefined;
4287
- if (!source) {
4629
+ const source = data.source && data.source.trim() ? data.source : undefined;
4630
+ const rawEntries = data.entries ?? [];
4631
+ if (!source && rawEntries.length === 0) {
4288
4632
  const target = params.repoUrl ?? (params.registry && params.packageName ? `${params.registry.toLowerCase()}:${params.packageName}` : "package");
4289
4633
  throw new PackageIntelligenceChangelogSourceNotFoundError(`No changelog source available for ${target} (tried GitHub Releases, CHANGELOG.md, and HexDocs).`);
4290
4634
  }
4291
- const rawEntries = data.entries ?? [];
4292
4635
  const entries = rawEntries.map((entry) => ({
4293
4636
  version: entry.version ?? undefined,
4294
4637
  normalizedVersion: entry.normalizedVersion ?? undefined,
@@ -4629,24 +4972,62 @@ class TokenManager {
4629
4972
  refreshToken: tokens.refreshToken
4630
4973
  }));
4631
4974
  } catch {
4975
+ const reloadedToken = await this.loadExternallyUpdatedToken(tokens);
4976
+ if (reloadedToken)
4977
+ return reloadedToken.accessToken;
4632
4978
  const isExpired = tokens.expiresAt ? new Date >= new Date(tokens.expiresAt) : false;
4633
4979
  if (isExpired) {
4980
+ const currentStoredTokens = await this.loadExternallyUpdatedToken(tokens);
4981
+ if (currentStoredTokens)
4982
+ return currentStoredTokens.accessToken;
4983
+ const cleared = await withTelemetrySpan("token-manager.clear-tokens-if-unchanged", () => this.authStorage.clearTokensIfUnchanged(this.mcpUrl, tokens));
4984
+ if (!cleared) {
4985
+ const currentToken = await this.authStorage.loadTokens(this.mcpUrl);
4986
+ this.cachedToken = currentToken;
4987
+ return currentToken?.accessToken;
4988
+ }
4634
4989
  this.cachedToken = null;
4635
- await withTelemetrySpan("token-manager.clear-tokens", () => this.authStorage.clearTokens(this.mcpUrl));
4636
4990
  }
4637
4991
  return;
4638
4992
  }
4639
4993
  const newTokenData = {
4640
4994
  accessToken: response.accessToken,
4641
- refreshToken: response.refreshToken,
4995
+ refreshToken: response.refreshToken ?? tokens.refreshToken,
4642
4996
  expiresAt: new Date(Date.now() + response.expiresIn * 1000).toISOString(),
4643
4997
  createdAt: new Date().toISOString()
4644
4998
  };
4645
- await withTelemetrySpan("token-manager.save-tokens", () => this.authStorage.saveTokens(this.mcpUrl, newTokenData));
4999
+ const externallyUpdatedToken = await this.loadExternallyUpdatedToken(tokens, {
5000
+ treatMissingAsExternalUpdate: true
5001
+ });
5002
+ if (externallyUpdatedToken === null)
5003
+ return;
5004
+ if (externallyUpdatedToken)
5005
+ return externallyUpdatedToken.accessToken;
5006
+ const saved = await withTelemetrySpan("token-manager.save-tokens", () => this.authStorage.saveTokensIfUnchanged(this.mcpUrl, tokens, newTokenData));
5007
+ if (!saved) {
5008
+ const currentToken = await this.authStorage.loadTokens(this.mcpUrl);
5009
+ this.cachedToken = currentToken;
5010
+ return currentToken?.accessToken;
5011
+ }
4646
5012
  this.cachedToken = newTokenData;
4647
5013
  return response.accessToken;
4648
5014
  });
4649
5015
  }
5016
+ async loadExternallyUpdatedToken(failedTokens, options = {}) {
5017
+ const storedTokens = await withTelemetrySpan("token-manager.reload-tokens", () => this.authStorage.loadTokens(this.mcpUrl));
5018
+ if (!storedTokens) {
5019
+ if (options.treatMissingAsExternalUpdate)
5020
+ this.cachedToken = null;
5021
+ return options.treatMissingAsExternalUpdate ? null : undefined;
5022
+ }
5023
+ if (areSameTokenData(storedTokens, failedTokens))
5024
+ return;
5025
+ this.cachedToken = storedTokens;
5026
+ return storedTokens;
5027
+ }
5028
+ }
5029
+ function areSameTokenData(a, b) {
5030
+ return a.accessToken === b.accessToken && a.refreshToken === b.refreshToken && a.expiresAt === b.expiresAt && a.createdAt === b.createdAt;
4650
5031
  }
4651
5032
  // src/services/update-check-service.ts
4652
5033
  import semver from "semver";
@@ -4984,7 +5365,7 @@ function createAuthStorageForMode(fileSystemService, mode, configPath = "your Gi
4984
5365
  const rawKeyring = new KeyringServiceImpl;
4985
5366
  const keyring = process.platform === "win32" ? new ChunkingKeyringService(rawKeyring, WINDOWS_MAX_ENTRY_SIZE) : rawKeyring;
4986
5367
  const keychainStorage = new KeychainAuthStorage(keyring);
4987
- return new MigratingAuthStorage(keychainStorage, fileStorage, legacyStorage, mode, configPath, (message) => console.error(message));
5368
+ return new LockedAuthStorage(new MigratingAuthStorage(keychainStorage, fileStorage, legacyStorage, mode, configPath, (message) => console.error(message)), fileSystemService);
4988
5369
  }
4989
5370
  async function createAuthCommandDependencies() {
4990
5371
  return withTelemetrySpan("container.create-auth-command", async () => {
@@ -5076,4 +5457,4 @@ async function createContainer() {
5076
5457
  });
5077
5458
  }
5078
5459
 
5079
- export { AuthConfigError, 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, getCodeNavigationUrl, ExecServiceImpl, FileSystemServiceImpl, AuthStoragePolicyError, PackageIntelligenceAccessError, PackageIntelligenceFeatureFlagRequiredError, PackageIntelligenceNetworkError, PackageIntelligenceBackendError, PackageIntelligenceGraphQLError, PackageIntelligenceTargetNotFoundError, PackageIntelligenceValidationError, PackageIntelligenceVersionNotFoundError, MalformedPackageIntelligenceResponseError, PackageIntelligenceChangelogSourceNotFoundError, PromptServiceImpl, refreshExpiredToken, NpmRegistryUpdateCheckService, shouldRunUpdateCheck, shouldRunRequiredUpdateEnforcement, formatUpdateNotice, formatRequiredUpdateNotice, createAuthCommandDependencies, createAuthStatusDependencies, createContainer };
5460
+ export { AuthConfigError, 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, getCodeNavigationUrl, ExecServiceImpl, FileSystemServiceImpl, AuthStorageLockTimeoutError, AuthStoragePolicyError, PackageIntelligenceAccessError, PackageIntelligenceFeatureFlagRequiredError, PackageIntelligenceNetworkError, PackageIntelligenceBackendError, PackageIntelligenceGraphQLError, PackageIntelligenceTargetNotFoundError, PackageIntelligenceValidationError, PackageIntelligenceVersionNotFoundError, MalformedPackageIntelligenceResponseError, PackageIntelligenceChangelogSourceNotFoundError, PromptServiceImpl, refreshExpiredToken, NpmRegistryUpdateCheckService, shouldRunUpdateCheck, shouldRunRequiredUpdateEnforcement, formatUpdateNotice, formatRequiredUpdateNotice, createAuthCommandDependencies, createAuthStatusDependencies, createContainer };
@@ -1,6 +1,6 @@
1
1
  import { createRequire } from "node:module";
2
2
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
3
  // package.json
4
- var version = "0.3.0";
4
+ var version = "0.3.1";
5
5
 
6
6
  export { __require, version };
@@ -2,8 +2,8 @@ import {
2
2
  createAuthCommandDependencies,
3
3
  createAuthStatusDependencies,
4
4
  createContainer
5
- } from "./chunk-5mk9k2gv.js";
6
- import"./chunk-gxya097b.js";
5
+ } from "./chunk-0s7mxdt3.js";
6
+ import"./chunk-m1xx8hzw.js";
7
7
  export {
8
8
  createContainer,
9
9
  createAuthStatusDependencies,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githits",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Code examples from global open source for developers and AI assistants.",
5
5
  "mcpServers": {
6
6
  "githits": {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "githits",
3
3
  "description": "CLI companion for GitHits - code examples from global open source for developers and AI assistants",
4
- "version": "0.3.0",
4
+ "version": "0.3.1",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githits",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Code examples from global open source for developers and AI assistants",
5
5
  "author": {
6
6
  "name": "GitHits"