githits 0.4.5 → 0.4.6

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-vfyz65v1.js";
4
+ } from "./chunk-a1hzwt2m.js";
5
5
 
6
6
  // src/services/app-config-paths.ts
7
7
  var APP_DIR = "githits";
@@ -195,7 +195,7 @@ class AuthServiceImpl {
195
195
  }
196
196
  if (url.pathname !== "/callback") {
197
197
  if (callbackHandled) {
198
- sendHtmlResponse(res, 200, successHtml("Authentication already completed."));
198
+ sendHtmlResponse(res, 200, successHtml("You're already signed in."));
199
199
  return;
200
200
  }
201
201
  sendHtmlResponse(res, 404, errorHtml("Invalid callback path.", "Run `githits login` to start authentication."));
@@ -303,11 +303,12 @@ function parseRefreshTokenResponse(data) {
303
303
  expiresIn: d.expires_in || 3600
304
304
  };
305
305
  }
306
- function successHtml(title = "Authentication successful") {
306
+ function successHtml(title = "You're signed in") {
307
307
  return `<!DOCTYPE html>
308
308
  <html><head>
309
309
  <title>GitHits CLI</title>
310
310
  <meta charset="utf-8">
311
+ <meta name="viewport" content="width=device-width, initial-scale=1">
311
312
  <link rel="preconnect" href="https://fonts.googleapis.com">
312
313
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
313
314
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&family=Lexend:wght@600&display=swap" rel="stylesheet">
@@ -369,29 +370,7 @@ function successHtml(title = "Authentication successful") {
369
370
  }
370
371
  .text-muted {
371
372
  color: #abb2bf;
372
- }
373
- .tip {
374
- font-family: 'Inter', sans-serif;
375
- font-weight: 400;
376
- font-size: 14px;
377
- line-height: 20px;
378
- color: #abb2bf;
379
- margin: 0;
380
- text-align: center;
381
- text-wrap: pretty;
382
- }
383
- .tip-label {
384
- font-weight: 600;
385
- color: #ffffff;
386
- }
387
- code {
388
- font-family: 'Consolas', monospace;
389
- font-size: 13px;
390
- background: rgba(255, 255, 255, 0.08);
391
- padding: 1px 6px;
392
- border-radius: 4px;
393
- color: #ffffff;
394
- }
373
+ }${COPY_BTN_CSS}
395
374
  </style>
396
375
  </head>
397
376
  <body>
@@ -403,10 +382,10 @@ function successHtml(title = "Authentication successful") {
403
382
  </div>
404
383
  <div class="message">
405
384
  <h1 class="heading">${escapeHtml(title)}</h1>
406
- <p class="text text-muted">You can close this window and return to the terminal.</p>
385
+ <p class="text text-muted">You can close this window and return to your terminal.</p>
407
386
  </div>
408
387
 
409
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 554 129.3" width="103" height="24" role="img" aria-label="GitHits">
388
+ <svg class="wordmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 554 129.3" width="103" height="24" role="img" aria-label="GitHits">
410
389
  <title>GitHits</title>
411
390
  <defs>
412
391
  <linearGradient id="wm-grad" x1="234.9" y1="64.7" x2="555.5" y2="64.7" gradientUnits="userSpaceOnUse">
@@ -419,16 +398,30 @@ function successHtml(title = "Authentication successful") {
419
398
  <path d="M239.1,64.8v-24h-18.8V8.5h-25v32.3h-18.8v24h18.8v62.6h25v-62.6h18.8ZM161.1,40.8h-25v86.6h25V40.8ZM91.6,84.6h-26.8v-24h54s1.2,4.3,1.1,12.1c-.3,30.6-25.3,55.5-55.9,55.7h-.5C27.4,128.4-1.6,98.3,0,61.8,1.5,29.6,27.4,3.4,59.6,1.4c21-1.2,40,7.7,52.4,22.4l-17.2,17.2c-7.7-10.1-20.3-16.4-34.3-15.4-19.4,1.4-35,17.1-36.4,36.5-1.6,23,16.6,42.2,39.3,42.2s28-19.7,28-19.7h.2Z" fill="#ff4fae" />
420
399
  </svg>
421
400
 
422
- <p class="tip"><span class="tip-label">TIP:</span> Run <code>npx githits --help</code> to discover what else you can do.</p>
401
+ ${HELP_CTA}
423
402
  </div>
403
+ ${COPY_SCRIPT_HTML}
424
404
  </body></html>`;
425
405
  }
406
+ var KNOWN_OAUTH_ERROR_MESSAGES = {
407
+ access_denied: "Access was denied."
408
+ };
409
+ function describeOauthError(code, description) {
410
+ const mapped = KNOWN_OAUTH_ERROR_MESSAGES[code];
411
+ if (mapped)
412
+ return mapped;
413
+ if (description) {
414
+ return /[.!?]$/.test(description) ? description : `${description}.`;
415
+ }
416
+ return "Something went wrong while signing in.";
417
+ }
426
418
  function evaluateCallback(input) {
427
419
  if (input.error) {
428
420
  const message = input.errorDescription ? `${input.error}: ${input.errorDescription}` : input.error;
421
+ const browserMessage = describeOauthError(input.error, input.errorDescription);
429
422
  return {
430
423
  statusCode: 200,
431
- html: errorHtml(message, "Run `githits login` to try again."),
424
+ html: errorHtml(browserMessage, input.error, RETRY_CTA),
432
425
  result: { type: "oauth_error", message }
433
426
  };
434
427
  }
@@ -436,7 +429,7 @@ function evaluateCallback(input) {
436
429
  if (input.state !== input.expectedState) {
437
430
  return {
438
431
  statusCode: 400,
439
- html: errorHtml("Authentication failed security validation (state mismatch)", "Run `githits login` to try again."),
432
+ html: errorHtml("Sign-in could not be verified for security reasons.", undefined, RETRY_CTA),
440
433
  result: {
441
434
  type: "state_mismatch",
442
435
  message: "Security validation failed (state mismatch)"
@@ -451,19 +444,20 @@ function evaluateCallback(input) {
451
444
  }
452
445
  return {
453
446
  statusCode: 400,
454
- html: errorHtml("Authentication callback was missing required parameters", "Run `githits login` to try again."),
447
+ html: errorHtml("Sign-in did not complete correctly.", undefined, RETRY_CTA),
455
448
  result: {
456
449
  type: "invalid_callback",
457
450
  message: "Authentication callback missing required parameters"
458
451
  }
459
452
  };
460
453
  }
461
- function errorHtml(error, nextStep) {
462
- const nextStepHtml = nextStep ? `<p>${escapeHtml(nextStep)}</p>` : "";
454
+ function errorHtml(error, errorCode, ctaHtml) {
455
+ const errorCodeHtml = errorCode ? `<p class="error-code">Error code: <code>${escapeHtml(errorCode)}</code></p>` : "";
463
456
  return `<!DOCTYPE html>
464
457
  <html><head>
465
458
  <title>GitHits CLI</title>
466
459
  <meta charset="utf-8">
460
+ <meta name="viewport" content="width=device-width, initial-scale=1">
467
461
  <link rel="preconnect" href="https://fonts.googleapis.com">
468
462
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
469
463
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&family=Lexend:wght@600&display=swap" rel="stylesheet">
@@ -529,21 +523,40 @@ function errorHtml(error, nextStep) {
529
523
  .footer-text {
530
524
  font-family: 'Inter', sans-serif;
531
525
  font-weight: 400;
532
- font-size: 14px;
533
- line-height: 20px;
526
+ font-size: 12px;
527
+ line-height: 16px;
534
528
  color: #abb2bf;
535
529
  margin: 0;
536
530
  text-align: center;
537
531
  text-wrap: pretty;
538
532
  }
539
533
  .footer-link {
540
- color: #ffffff;
534
+ color: inherit;
541
535
  text-decoration: underline;
542
536
  text-underline-offset: 2px;
543
537
  }
544
- .footer-link:hover {
538
+ .error-code {
539
+ font-family: 'Inter', sans-serif;
540
+ font-weight: 400;
541
+ font-size: 12px;
542
+ line-height: 16px;
545
543
  color: #abb2bf;
544
+ opacity: 0.7;
545
+ margin: 4px 0 0;
546
+ text-align: center;
546
547
  }
548
+ .error-code code {
549
+ font-size: 11px;
550
+ padding: 0 5px;
551
+ }
552
+ code {
553
+ font-family: 'Consolas', monospace;
554
+ font-size: 13px;
555
+ background: rgba(255, 255, 255, 0.08);
556
+ padding: 1px 6px;
557
+ border-radius: 4px;
558
+ color: #ffffff;
559
+ }${COPY_BTN_CSS}
547
560
  </style>
548
561
  </head>
549
562
  <body>
@@ -556,13 +569,14 @@ function errorHtml(error, nextStep) {
556
569
  </div>
557
570
 
558
571
  <div class="message">
559
- <h1 class="heading">Authentication failed</h1>
572
+ <h1 class="heading">Sign-in failed</h1>
560
573
  <p class="text text-muted">${escapeHtml(error)}</p>
574
+ ${errorCodeHtml}
561
575
  </div>
562
576
 
563
- ${nextStepHtml}
577
+ ${ctaHtml ?? ""}
564
578
 
565
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 554 129.3" width="103" height="24" role="img" aria-label="GitHits">
579
+ <svg class="wordmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 554 129.3" width="103" height="24" role="img" aria-label="GitHits">
566
580
  <title>GitHits</title>
567
581
  <defs>
568
582
  <linearGradient id="wm-grad" x1="234.9" y1="64.7" x2="555.5" y2="64.7" gradientUnits="userSpaceOnUse">
@@ -577,6 +591,7 @@ function errorHtml(error, nextStep) {
577
591
 
578
592
  <p class="footer-text">Having trouble? Check our <a class="footer-link" href="https://app.githits.com/docs/" target="_blank" rel="noopener noreferrer">documentation</a> or contact <a class="footer-link" href="mailto:support@githits.com">support</a>.</p>
579
593
  </div>
594
+ ${COPY_SCRIPT_HTML}
580
595
  </body></html>`;
581
596
  }
582
597
  function sendHtmlResponse(res, statusCode, html) {
@@ -597,6 +612,108 @@ function closeServer(server) {
597
612
  });
598
613
  });
599
614
  }
615
+ var COPY_ICON_SVG = `<svg class="githits-cli-icon githits-cli-icon-copy" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>`;
616
+ var CHECK_ICON_SVG = `<svg class="githits-cli-icon githits-cli-icon-check" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"></polyline></svg>`;
617
+ function commandButton(cmd) {
618
+ const escaped = escapeHtml(cmd);
619
+ return `<button type="button" class="githits-cli-btn" data-copy="${escaped}" aria-label="Copy command: ${escaped}"><span class="githits-cli-cmd">${escaped}</span>${COPY_ICON_SVG}${CHECK_ICON_SVG}</button>`;
620
+ }
621
+ function ctaBlock(introHtml, commands) {
622
+ const buttons = commands.map(commandButton).join(`
623
+ `);
624
+ return `<div class="cli-cta">
625
+ <p class="tip">${introHtml}</p>
626
+ ${buttons}
627
+ </div>`;
628
+ }
629
+ var COPY_BTN_CSS = `
630
+ .wordmark {
631
+ margin: 16px 0;
632
+ }
633
+ .cli-cta {
634
+ display: flex;
635
+ flex-direction: column;
636
+ align-items: center;
637
+ gap: 12px;
638
+ margin: 16px 0 0;
639
+ }
640
+ .wordmark + .cli-cta {
641
+ margin-top: 0;
642
+ }
643
+ .tip {
644
+ font-family: 'Inter', sans-serif;
645
+ font-weight: 400;
646
+ font-size: 14px;
647
+ line-height: 20px;
648
+ color: #d5d9df;
649
+ margin: 0;
650
+ text-align: center;
651
+ text-wrap: pretty;
652
+ }
653
+ .githits-cli-btn {
654
+ display: inline-flex;
655
+ align-items: center;
656
+ gap: 0.5rem;
657
+ background-color: rgba(255, 255, 255, 0.08);
658
+ border: none;
659
+ border-radius: 0.5rem;
660
+ padding: 1rem 1.25rem;
661
+ font-family: Consolas, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
662
+ font-size: 14px;
663
+ font-weight: 500;
664
+ color: #abb2bf;
665
+ cursor: pointer;
666
+ line-height: 1;
667
+ transition: background-color 0.2s ease, transform 0.1s ease, color 0.2s ease;
668
+ }
669
+ .githits-cli-btn:hover {
670
+ color: #d5d9df;
671
+ }
672
+ .githits-cli-btn:active {
673
+ transform: scale(0.98);
674
+ }
675
+ .githits-cli-btn:focus-visible {
676
+ outline: 2px solid #abb2bf;
677
+ outline-offset: 2px;
678
+ }
679
+ .githits-cli-cmd {
680
+ white-space: nowrap;
681
+ }
682
+ .githits-cli-icon {
683
+ width: 14px;
684
+ height: 14px;
685
+ color: #abb2bf;
686
+ flex-shrink: 0;
687
+ }
688
+ .githits-cli-btn.copied .githits-cli-icon-copy { display: none; }
689
+ .githits-cli-btn:not(.copied) .githits-cli-icon-check { display: none; }
690
+ .githits-cli-btn.copied .githits-cli-icon { color: #abb2bf; }`;
691
+ var COPY_SCRIPT_HTML = `<script>
692
+ (function() {
693
+ var timers = new WeakMap();
694
+ var buttons = document.querySelectorAll('.githits-cli-btn');
695
+ for (var i = 0; i < buttons.length; i++) {
696
+ buttons[i].addEventListener('click', function(e) {
697
+ var target = e.currentTarget;
698
+ var text = target.getAttribute('data-copy');
699
+ if (!text || !navigator.clipboard) return;
700
+ navigator.clipboard.writeText(text).then(function() {
701
+ target.classList.add('copied');
702
+ var existing = timers.get(target);
703
+ if (existing) clearTimeout(existing);
704
+ timers.set(target, setTimeout(function() {
705
+ target.classList.remove('copied');
706
+ timers.delete(target);
707
+ }, 1500));
708
+ });
709
+ });
710
+ }
711
+ })();
712
+ </script>`;
713
+ var RETRY_CTA = ctaBlock("To try again, run these commands in your terminal:", ["npx githits@latest logout", "npx githits@latest login"]);
714
+ var HELP_CTA = ctaBlock("Explore available commands with:", [
715
+ "npx githits@latest --help"
716
+ ]);
600
717
  function escapeHtml(text) {
601
718
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
602
719
  }
@@ -1488,10 +1605,14 @@ class CodeNavigationGraphQLError extends Error {
1488
1605
  class CodeNavigationIndexingError extends Error {
1489
1606
  indexingRef;
1490
1607
  availableVersions;
1491
- constructor(message, indexingRef, availableVersions) {
1608
+ availableRefs;
1609
+ targetResolution;
1610
+ constructor(message, indexingRef, availableVersions, availableRefs, targetResolution) {
1492
1611
  super(message);
1493
1612
  this.indexingRef = indexingRef;
1494
1613
  this.availableVersions = availableVersions;
1614
+ this.availableRefs = availableRefs;
1615
+ this.targetResolution = targetResolution;
1495
1616
  this.name = "CodeNavigationIndexingError";
1496
1617
  }
1497
1618
  }
@@ -1576,6 +1697,63 @@ class CodeNavigationBackendError extends Error {
1576
1697
  this.name = "CodeNavigationBackendError";
1577
1698
  }
1578
1699
  }
1700
+ var TARGET_RESOLUTION_AVAILABLE_REFS_SELECTION = `
1701
+ availableRefs {
1702
+ version
1703
+ ref
1704
+ }`;
1705
+ var TARGET_RESOLUTION_SELECTION = `
1706
+ targetResolution {
1707
+ requested {
1708
+ kind
1709
+ registry
1710
+ packageName
1711
+ version
1712
+ repoUrl
1713
+ gitRef
1714
+ commitSha
1715
+ }
1716
+ resolvedRequested {
1717
+ kind
1718
+ registry
1719
+ packageName
1720
+ version
1721
+ repoUrl
1722
+ gitRef
1723
+ commitSha
1724
+ }
1725
+ served {
1726
+ kind
1727
+ registry
1728
+ packageName
1729
+ version
1730
+ repoUrl
1731
+ gitRef
1732
+ commitSha
1733
+ }
1734
+ freshness
1735
+ freshnessReason
1736
+ indexingRef
1737
+ availableVersions {
1738
+ version
1739
+ ref
1740
+ }
1741
+ ${TARGET_RESOLUTION_AVAILABLE_REFS_SELECTION}
1742
+ }`;
1743
+ var CODE_CONTEXT_AVAILABLE_VERSIONS_SELECTION = `
1744
+ availableVersions {
1745
+ version
1746
+ ref
1747
+ }`;
1748
+ var DISCOVERY_TARGET_PROGRESS_RETRY_SELECTION = `
1749
+ availableVersions {
1750
+ version
1751
+ ref
1752
+ }
1753
+ availableRefs {
1754
+ version
1755
+ ref
1756
+ }`;
1579
1757
  var UNIFIED_SEARCH_QUERY = `
1580
1758
  query UnifiedSearch(
1581
1759
  $targets: [SearchPackageInput!]!
@@ -1652,6 +1830,7 @@ query UnifiedSearch(
1652
1830
  requestedTargetLabel
1653
1831
  freshTargetLabel
1654
1832
  servedTargetLabel
1833
+ ${TARGET_RESOLUTION_SELECTION}
1655
1834
  indexingStatus
1656
1835
  codeIndexState
1657
1836
  resultCount
@@ -1698,6 +1877,8 @@ query UnifiedSearch(
1698
1877
  freshness
1699
1878
  indexingRef
1700
1879
  requestedRefKind
1880
+ ${TARGET_RESOLUTION_SELECTION}
1881
+ ${DISCOVERY_TARGET_PROGRESS_RETRY_SELECTION}
1701
1882
  }
1702
1883
  expiresAt
1703
1884
  }
@@ -1739,6 +1920,8 @@ query UnifiedSearchStatus($searchRef: String!, $includeResults: Boolean!) {
1739
1920
  freshness
1740
1921
  indexingRef
1741
1922
  requestedRefKind
1923
+ ${TARGET_RESOLUTION_SELECTION}
1924
+ ${DISCOVERY_TARGET_PROGRESS_RETRY_SELECTION}
1742
1925
  }
1743
1926
  expiresAt
1744
1927
  results {
@@ -1794,6 +1977,7 @@ query UnifiedSearchStatus($searchRef: String!, $includeResults: Boolean!) {
1794
1977
  requestedTargetLabel
1795
1978
  freshTargetLabel
1796
1979
  servedTargetLabel
1980
+ ${TARGET_RESOLUTION_SELECTION}
1797
1981
  indexingStatus
1798
1982
  codeIndexState
1799
1983
  resultCount
@@ -1859,6 +2043,25 @@ var availableVersionSchema = z2.object({
1859
2043
  version: z2.string().nullable().optional(),
1860
2044
  ref: z2.string()
1861
2045
  });
2046
+ var targetResolutionIdentitySchema = z2.object({
2047
+ kind: z2.string().nullable().optional(),
2048
+ registry: z2.string().nullable().optional(),
2049
+ packageName: z2.string().nullable().optional(),
2050
+ version: z2.string().nullable().optional(),
2051
+ repoUrl: z2.string().nullable().optional(),
2052
+ gitRef: z2.string().nullable().optional(),
2053
+ commitSha: z2.string().nullable().optional()
2054
+ }).nullable().optional();
2055
+ var targetResolutionSchema = z2.object({
2056
+ requested: targetResolutionIdentitySchema,
2057
+ resolvedRequested: targetResolutionIdentitySchema,
2058
+ served: targetResolutionIdentitySchema,
2059
+ freshness: z2.string().nullable().optional(),
2060
+ freshnessReason: z2.string().nullable().optional(),
2061
+ indexingRef: z2.string().nullable().optional(),
2062
+ availableVersions: z2.array(availableVersionSchema).nullable().optional(),
2063
+ availableRefs: z2.array(availableVersionSchema).nullable().optional()
2064
+ }).nullable().optional();
1862
2065
  var unifiedSearchSourceSchema = z2.enum(["AUTO", "DOCS", "CODE", "SYMBOL"]);
1863
2066
  var unifiedSearchResultTypeSchema = z2.enum([
1864
2067
  "DOCUMENTATION_PAGE",
@@ -1915,6 +2118,7 @@ var unifiedSearchSourceStatusSchema = z2.object({
1915
2118
  requestedTargetLabel: z2.string().nullable().optional(),
1916
2119
  freshTargetLabel: z2.string().nullable().optional(),
1917
2120
  servedTargetLabel: z2.string().nullable().optional(),
2121
+ targetResolution: targetResolutionSchema,
1918
2122
  indexingStatus: z2.string().nullable().optional(),
1919
2123
  codeIndexState: z2.string().nullable().optional(),
1920
2124
  resultCount: z2.number().int().nullable().optional(),
@@ -1956,7 +2160,10 @@ var unifiedSearchProgressTargetSchema = z2.object({
1956
2160
  served: z2.string().nullable().optional(),
1957
2161
  freshness: z2.string().nullable().optional(),
1958
2162
  indexingRef: z2.string().nullable().optional(),
1959
- requestedRefKind: z2.string().nullable().optional()
2163
+ requestedRefKind: z2.string().nullable().optional(),
2164
+ targetResolution: targetResolutionSchema,
2165
+ availableVersions: z2.array(availableVersionSchema).nullable().optional(),
2166
+ availableRefs: z2.array(availableVersionSchema).nullable().optional()
1960
2167
  });
1961
2168
  var unifiedSearchRequestedTargetSchema = z2.object({
1962
2169
  registry: z2.string().nullable().optional(),
@@ -2016,6 +2223,7 @@ var listRepoFilesResponseSchema = z2.object({
2016
2223
  hasMore: z2.boolean(),
2017
2224
  indexedVersion: z2.string().nullable().optional(),
2018
2225
  resolution: navigationResolutionSchema,
2226
+ targetResolution: targetResolutionSchema,
2019
2227
  diagnostics: navigationDiagnosticsSchema,
2020
2228
  codeIndexState: z2.string(),
2021
2229
  indexingRef: z2.string().nullable().optional(),
@@ -2084,6 +2292,7 @@ query ListRepoFiles(
2084
2292
  resolvedRef
2085
2293
  commitSha
2086
2294
  }
2295
+ ${TARGET_RESOLUTION_SELECTION}
2087
2296
  diagnostics {
2088
2297
  hint
2089
2298
  }
@@ -2106,7 +2315,9 @@ var codeContextResponseSchema = z2.object({
2106
2315
  gitRef: z2.string().nullable().optional(),
2107
2316
  isBinary: z2.boolean().nullable().optional(),
2108
2317
  codeIndexState: z2.string(),
2109
- indexingRef: z2.string().nullable().optional()
2318
+ indexingRef: z2.string().nullable().optional(),
2319
+ availableVersions: z2.array(availableVersionSchema).nullable().optional(),
2320
+ targetResolution: targetResolutionSchema
2110
2321
  });
2111
2322
  var fetchCodeContextGraphQLResponseSchema = z2.object({
2112
2323
  data: z2.object({
@@ -2148,6 +2359,8 @@ query FetchCodeContext(
2148
2359
  isBinary
2149
2360
  codeIndexState
2150
2361
  indexingRef
2362
+ ${CODE_CONTEXT_AVAILABLE_VERSIONS_SELECTION}
2363
+ ${TARGET_RESOLUTION_SELECTION}
2151
2364
  }
2152
2365
  }`;
2153
2366
  var grepRepoMatchSchema = z2.object({
@@ -2198,6 +2411,7 @@ var grepRepoResponseSchema = z2.object({
2198
2411
  uniqueFilesMatched: z2.number().int(),
2199
2412
  indexedVersion: z2.string().nullable().optional(),
2200
2413
  resolution: navigationResolutionSchema,
2414
+ targetResolution: targetResolutionSchema,
2201
2415
  codeIndexState: z2.string(),
2202
2416
  indexingRef: z2.string().nullable().optional(),
2203
2417
  availableVersions: z2.array(availableVersionSchema).nullable().optional()
@@ -2306,6 +2520,7 @@ query GrepRepo(
2306
2520
  resolvedRef
2307
2521
  commitSha
2308
2522
  }
2523
+ ${TARGET_RESOLUTION_SELECTION}
2309
2524
  codeIndexState
2310
2525
  indexingRef
2311
2526
  availableVersions {
@@ -2337,6 +2552,35 @@ class CodeNavigationServiceImpl {
2337
2552
  this.tokenProvider = tokenProvider;
2338
2553
  this.fetchFn = fetchFn;
2339
2554
  }
2555
+ async postGraphqlWithTargetResolutionFallback(input) {
2556
+ const response = await postPkgseerGraphql({
2557
+ endpointUrl: this.codeNavigationUrl,
2558
+ token: input.token,
2559
+ query: input.query,
2560
+ variables: input.variables,
2561
+ fetchFn: this.fetchFn
2562
+ });
2563
+ if (response.status < 200 || response.status >= 300)
2564
+ return response;
2565
+ if (!hasSchemaMismatchErrors(response.parsedBody))
2566
+ return response;
2567
+ for (const fallbackQuery of buildTargetResolutionFallbackQueries(input.query)) {
2568
+ debugLog("code-nav", {
2569
+ event: "target-resolution-query-fallback"
2570
+ });
2571
+ const fallbackResponse = await postPkgseerGraphql({
2572
+ endpointUrl: this.codeNavigationUrl,
2573
+ token: input.token,
2574
+ query: fallbackQuery,
2575
+ variables: input.variables,
2576
+ fetchFn: this.fetchFn
2577
+ });
2578
+ if (!hasSchemaMismatchErrors(fallbackResponse.parsedBody)) {
2579
+ return fallbackResponse;
2580
+ }
2581
+ }
2582
+ return response;
2583
+ }
2340
2584
  async search(params) {
2341
2585
  return executeWithTokenRefresh({
2342
2586
  getToken: () => this.tokenProvider.getToken(),
@@ -2377,12 +2621,10 @@ class CodeNavigationServiceImpl {
2377
2621
  debugUnifiedSearchRequest(variables);
2378
2622
  debugGraphqlWireRequest("search", UNIFIED_SEARCH_QUERY, variables);
2379
2623
  try {
2380
- response = await postPkgseerGraphql({
2381
- endpointUrl: this.codeNavigationUrl,
2624
+ response = await this.postGraphqlWithTargetResolutionFallback({
2382
2625
  token,
2383
2626
  query: UNIFIED_SEARCH_QUERY,
2384
- variables,
2385
- fetchFn: this.fetchFn
2627
+ variables
2386
2628
  });
2387
2629
  } catch (cause) {
2388
2630
  if (cause instanceof PkgseerTransportError) {
@@ -2409,15 +2651,13 @@ class CodeNavigationServiceImpl {
2409
2651
  async executeUnifiedSearchStatus(token, searchRef) {
2410
2652
  let response;
2411
2653
  try {
2412
- response = await postPkgseerGraphql({
2413
- endpointUrl: this.codeNavigationUrl,
2654
+ response = await this.postGraphqlWithTargetResolutionFallback({
2414
2655
  token,
2415
2656
  query: UNIFIED_SEARCH_STATUS_QUERY,
2416
2657
  variables: {
2417
2658
  searchRef,
2418
2659
  includeResults: true
2419
- },
2420
- fetchFn: this.fetchFn
2660
+ }
2421
2661
  });
2422
2662
  } catch (cause) {
2423
2663
  if (cause instanceof PkgseerTransportError) {
@@ -2492,7 +2732,7 @@ class CodeNavigationServiceImpl {
2492
2732
  }
2493
2733
  switch (code) {
2494
2734
  case "PACKAGE_INDEXING":
2495
- return new CodeNavigationIndexingError(this.createIndexingMessage(indexingRef), indexingRef, parseAvailableVersions(extensions));
2735
+ return new CodeNavigationIndexingError(this.createIndexingMessage(indexingRef), indexingRef, parseAvailableVersions(extensions), parseAvailableRefs(extensions), parseTargetResolution(extensions));
2496
2736
  case "GREP_PATTERN_TOO_SHORT":
2497
2737
  case "GREP_PATTERN_TOO_LONG":
2498
2738
  case "GREP_PATTERN_INVALID":
@@ -2639,6 +2879,7 @@ class CodeNavigationServiceImpl {
2639
2879
  requestedTargetLabel: entry.requestedTargetLabel ?? undefined,
2640
2880
  freshTargetLabel: entry.freshTargetLabel ?? undefined,
2641
2881
  servedTargetLabel: entry.servedTargetLabel ?? undefined,
2882
+ targetResolution: normaliseTargetResolution(entry.targetResolution),
2642
2883
  indexingStatus: entry.indexingStatus ?? undefined,
2643
2884
  codeIndexState: entry.codeIndexState ?? undefined,
2644
2885
  resultCount: entry.resultCount ?? undefined,
@@ -2680,17 +2921,18 @@ class CodeNavigationServiceImpl {
2680
2921
  served: target.served ?? undefined,
2681
2922
  freshness: target.freshness ?? undefined,
2682
2923
  indexingRef: target.indexingRef ?? undefined,
2683
- requestedRefKind: normaliseRequestedRefKind(target.requestedRefKind)
2924
+ requestedRefKind: normaliseRequestedRefKind(target.requestedRefKind),
2925
+ targetResolution: normaliseTargetResolution(target.targetResolution),
2926
+ availableVersions: normaliseAvailableVersions(target.availableVersions),
2927
+ availableRefs: normaliseAvailableVersions(target.availableRefs)
2684
2928
  })),
2685
2929
  expiresAt: progress.expiresAt ?? undefined
2686
2930
  };
2687
2931
  }
2688
2932
  throwIfIndexing(data) {
2689
2933
  if (data.codeIndexState === "INDEXING") {
2690
- throw new CodeNavigationIndexingError(this.createIndexingMessage(data.indexingRef ?? undefined), data.indexingRef ?? undefined, data.availableVersions?.map((entry) => ({
2691
- version: entry.version ?? undefined,
2692
- ref: entry.ref
2693
- })));
2934
+ const targetResolution = normaliseTargetResolution(data.targetResolution);
2935
+ throw new CodeNavigationIndexingError(this.createIndexingMessage(data.indexingRef ?? targetResolution?.indexingRef), data.indexingRef ?? targetResolution?.indexingRef, normaliseAvailableVersions(data.availableVersions) ?? targetResolution?.availableVersions, targetResolution?.availableRefs, targetResolution);
2694
2936
  }
2695
2937
  }
2696
2938
  async listFiles(params) {
@@ -2704,8 +2946,7 @@ class CodeNavigationServiceImpl {
2704
2946
  async executeListFiles(token, params) {
2705
2947
  let response;
2706
2948
  try {
2707
- response = await postPkgseerGraphql({
2708
- endpointUrl: this.codeNavigationUrl,
2949
+ response = await this.postGraphqlWithTargetResolutionFallback({
2709
2950
  token,
2710
2951
  query: LIST_REPO_FILES_QUERY,
2711
2952
  variables: {
@@ -2730,8 +2971,7 @@ class CodeNavigationServiceImpl {
2730
2971
  includeHidden: params.includeHidden,
2731
2972
  limit: params.limit,
2732
2973
  waitTimeoutMs: params.waitTimeoutMs
2733
- },
2734
- fetchFn: this.fetchFn
2974
+ }
2735
2975
  });
2736
2976
  } catch (cause) {
2737
2977
  if (cause instanceof PkgseerTransportError) {
@@ -2771,6 +3011,7 @@ class CodeNavigationServiceImpl {
2771
3011
  resolvedRef: data.resolution.resolvedRef ?? undefined,
2772
3012
  commitSha: data.resolution.commitSha ?? undefined
2773
3013
  } : undefined,
3014
+ targetResolution: normaliseTargetResolution(data.targetResolution),
2774
3015
  hint: data.diagnostics?.hint ?? undefined
2775
3016
  };
2776
3017
  }
@@ -2785,8 +3026,7 @@ class CodeNavigationServiceImpl {
2785
3026
  async executeReadFile(token, params) {
2786
3027
  let response;
2787
3028
  try {
2788
- response = await postPkgseerGraphql({
2789
- endpointUrl: this.codeNavigationUrl,
3029
+ response = await this.postGraphqlWithTargetResolutionFallback({
2790
3030
  token,
2791
3031
  query: FETCH_CODE_CONTEXT_QUERY,
2792
3032
  variables: {
@@ -2799,8 +3039,7 @@ class CodeNavigationServiceImpl {
2799
3039
  startLine: params.startLine,
2800
3040
  endLine: params.endLine,
2801
3041
  waitTimeoutMs: params.waitTimeoutMs
2802
- },
2803
- fetchFn: this.fetchFn
3042
+ }
2804
3043
  });
2805
3044
  } catch (cause) {
2806
3045
  if (cause instanceof PkgseerTransportError) {
@@ -2822,10 +3061,7 @@ class CodeNavigationServiceImpl {
2822
3061
  if (!data) {
2823
3062
  throw new MalformedCodeNavigationResponseError("Malformed response from code navigation service.");
2824
3063
  }
2825
- this.throwIfIndexing({
2826
- codeIndexState: data.codeIndexState,
2827
- indexingRef: data.indexingRef
2828
- });
3064
+ this.throwIfIndexing(data);
2829
3065
  return {
2830
3066
  filePath: data.filePath ?? undefined,
2831
3067
  language: data.language ?? undefined,
@@ -2833,7 +3069,9 @@ class CodeNavigationServiceImpl {
2833
3069
  startLine: data.startLine ?? undefined,
2834
3070
  endLine: data.endLine ?? undefined,
2835
3071
  content: data.content ?? undefined,
2836
- isBinary: data.isBinary ?? undefined
3072
+ isBinary: data.isBinary ?? undefined,
3073
+ targetResolution: normaliseTargetResolution(data.targetResolution),
3074
+ availableVersions: normaliseAvailableVersions(data.availableVersions)
2837
3075
  };
2838
3076
  }
2839
3077
  async grepRepo(params) {
@@ -2847,8 +3085,7 @@ class CodeNavigationServiceImpl {
2847
3085
  async executeGrepRepo(token, params) {
2848
3086
  let response;
2849
3087
  try {
2850
- response = await postPkgseerGraphql({
2851
- endpointUrl: this.codeNavigationUrl,
3088
+ response = await this.postGraphqlWithTargetResolutionFallback({
2852
3089
  token,
2853
3090
  query: buildGrepRepoQuery(params.symbolFields),
2854
3091
  variables: {
@@ -2875,8 +3112,7 @@ class CodeNavigationServiceImpl {
2875
3112
  maxMatchesPerFile: params.maxMatchesPerFile,
2876
3113
  cursor: params.cursor,
2877
3114
  symbolFields: params.symbolFields
2878
- },
2879
- fetchFn: this.fetchFn
3115
+ }
2880
3116
  });
2881
3117
  } catch (cause) {
2882
3118
  if (cause instanceof PkgseerTransportError) {
@@ -2945,7 +3181,8 @@ class CodeNavigationServiceImpl {
2945
3181
  requestedRef: data.resolution.requestedRef ?? undefined,
2946
3182
  resolvedRef: data.resolution.resolvedRef ?? undefined,
2947
3183
  commitSha: data.resolution.commitSha ?? undefined
2948
- } : undefined
3184
+ } : undefined,
3185
+ targetResolution: normaliseTargetResolution(data.targetResolution)
2949
3186
  };
2950
3187
  }
2951
3188
  }
@@ -2963,6 +3200,31 @@ function parseDetail2(body) {
2963
3200
  }
2964
3201
  return;
2965
3202
  }
3203
+ function buildTargetResolutionFallbackQueries(query) {
3204
+ const candidates = [
3205
+ query.replaceAll(TARGET_RESOLUTION_AVAILABLE_REFS_SELECTION, ""),
3206
+ query.replaceAll(DISCOVERY_TARGET_PROGRESS_RETRY_SELECTION, ""),
3207
+ query.replaceAll(CODE_CONTEXT_AVAILABLE_VERSIONS_SELECTION, ""),
3208
+ query.replaceAll(TARGET_RESOLUTION_SELECTION, "").replaceAll(DISCOVERY_TARGET_PROGRESS_RETRY_SELECTION, "").replaceAll(CODE_CONTEXT_AVAILABLE_VERSIONS_SELECTION, "")
3209
+ ];
3210
+ return candidates.filter((candidate, index, all) => candidate !== query && all.indexOf(candidate) === index);
3211
+ }
3212
+ function hasSchemaMismatchErrors(parsedBody) {
3213
+ if (!parsedBody || typeof parsedBody !== "object")
3214
+ return false;
3215
+ const errors = parsedBody.errors;
3216
+ if (!Array.isArray(errors))
3217
+ return false;
3218
+ return errors.some((entry) => {
3219
+ if (!entry || typeof entry !== "object")
3220
+ return false;
3221
+ const error = entry;
3222
+ if (typeof error.message !== "string")
3223
+ return false;
3224
+ const code = typeof error.extensions?.code === "string" ? error.extensions.code : undefined;
3225
+ return isGraphQLSchemaMismatchError({ message: error.message, code });
3226
+ });
3227
+ }
2966
3228
  function getPrimaryExtensions(errors) {
2967
3229
  for (const error of errors) {
2968
3230
  if (error.extensions && Object.keys(error.extensions).length > 0) {
@@ -2981,6 +3243,20 @@ function getGraphQLIndexingRef(errors) {
2981
3243
  }
2982
3244
  function parseAvailableVersions(extensions) {
2983
3245
  const raw = extensions?.available_versions ?? extensions?.availableVersions;
3246
+ return parseAvailableArtifacts(raw);
3247
+ }
3248
+ function parseAvailableRefs(extensions) {
3249
+ const raw = extensions?.available_refs ?? extensions?.availableRefs;
3250
+ return parseAvailableArtifacts(raw);
3251
+ }
3252
+ function parseTargetResolution(extensions) {
3253
+ const raw = extensions?.target_resolution ?? extensions?.targetResolution;
3254
+ const parsed = targetResolutionSchema.safeParse(raw);
3255
+ if (!parsed.success)
3256
+ return;
3257
+ return normaliseTargetResolution(parsed.data);
3258
+ }
3259
+ function parseAvailableArtifacts(raw) {
2984
3260
  if (!Array.isArray(raw))
2985
3261
  return;
2986
3262
  const parsed = [];
@@ -2997,6 +3273,48 @@ function parseAvailableVersions(extensions) {
2997
3273
  }
2998
3274
  return parsed.length > 0 ? parsed : undefined;
2999
3275
  }
3276
+ function normaliseAvailableVersions(entries) {
3277
+ if (!entries || entries.length === 0)
3278
+ return;
3279
+ return entries.map((entry) => ({
3280
+ version: entry.version ?? undefined,
3281
+ ref: entry.ref
3282
+ }));
3283
+ }
3284
+ function normaliseTargetResolution(resolution) {
3285
+ if (!resolution)
3286
+ return;
3287
+ return {
3288
+ requested: normaliseTargetResolutionIdentity(resolution.requested),
3289
+ resolvedRequested: normaliseTargetResolutionIdentity(resolution.resolvedRequested),
3290
+ served: normaliseTargetResolutionIdentity(resolution.served),
3291
+ freshness: resolution.freshness ?? undefined,
3292
+ freshnessReason: resolution.freshnessReason ?? undefined,
3293
+ indexingRef: resolution.indexingRef ?? undefined,
3294
+ availableVersions: normaliseAvailableVersions(resolution.availableVersions) ?? [],
3295
+ availableRefs: normaliseAvailableVersions(resolution.availableRefs) ?? []
3296
+ };
3297
+ }
3298
+ function normaliseTargetResolutionIdentity(identity) {
3299
+ if (!identity)
3300
+ return;
3301
+ const out = {};
3302
+ if (identity.kind)
3303
+ out.kind = identity.kind;
3304
+ if (identity.registry)
3305
+ out.registry = identity.registry;
3306
+ if (identity.packageName)
3307
+ out.packageName = identity.packageName;
3308
+ if (identity.version)
3309
+ out.version = identity.version;
3310
+ if (identity.repoUrl)
3311
+ out.repoUrl = identity.repoUrl;
3312
+ if (identity.gitRef)
3313
+ out.gitRef = identity.gitRef;
3314
+ if (identity.commitSha)
3315
+ out.commitSha = identity.commitSha;
3316
+ return Object.keys(out).length > 0 ? out : undefined;
3317
+ }
3000
3318
  function isAuthMessage(message) {
3001
3319
  const lower = message.toLowerCase();
3002
3320
  return lower.includes("unauthorized") || lower.includes("forbidden") || lower.includes("permission") || lower.includes("authentication");
@@ -3068,14 +3386,31 @@ function getEnvApiToken() {
3068
3386
  }
3069
3387
  // src/services/exec-service.ts
3070
3388
  import { spawn } from "node:child_process";
3389
+ function isWindowsAbsolutePath(command) {
3390
+ return /^[a-zA-Z]:[\\/]/.test(command) || command.startsWith("\\\\");
3391
+ }
3392
+ function normalizeSpawnCommand(command, args, platform = process.platform) {
3393
+ if (platform !== "win32") {
3394
+ return { command, args };
3395
+ }
3396
+ if (isWindowsAbsolutePath(command) && /\s/.test(command)) {
3397
+ return {
3398
+ command: `"${command.replaceAll('"', "\\\"")}"`,
3399
+ args,
3400
+ shell: true
3401
+ };
3402
+ }
3403
+ return { command, args, shell: true };
3404
+ }
3071
3405
 
3072
3406
  class ExecServiceImpl {
3073
3407
  async exec(command, args) {
3074
3408
  return new Promise((resolve, reject) => {
3075
- const child = spawn(command, args, {
3409
+ const spawnCommand = normalizeSpawnCommand(command, args);
3410
+ const child = spawn(spawnCommand.command, spawnCommand.args, {
3076
3411
  stdio: ["ignore", "pipe", "pipe"],
3077
3412
  env: { ...process.env },
3078
- ...process.platform === "win32" && { shell: true }
3413
+ ...spawnCommand.shell !== undefined && { shell: spawnCommand.shell }
3079
3414
  });
3080
3415
  const stdoutChunks = [];
3081
3416
  const stderrChunks = [];