github / github/copilot-cli

sea-loader.js: lexicographical localeCompare in fi() causes -9 to be selected over -10 / -11 in package cache

Ouverte
#4,611 0 commentaires 2 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

area:installation
Langage dominant
Shell
Étoiles
11.2k
Forks
1.9k
Merge moyen
14 h 16 min
PR mergées (30 j)
6

Description

Summary

In sea-loader.js, the local version comparison helper fi(e, t) uses e.localeCompare(t) to compare prerelease / build tag suffixes when major/minor/patch segments match.

Because "1.0.81-9".localeCompare("1.0.81-11") returns 1 (lexicographical sorting where '9' > '1'), the bootstrap loader determines that 1.0.81-9 is newer than 1.0.81-10 or 1.0.81-11. Consequently, even after copilot update successfully downloads and extracts 1.0.81-11 into the package cache (%LOCALAPPDATA%\copilot\pkg\win32-x64\1.0.81-11), launching copilot continues to execute the cached 1.0.81-9 version.


Root Cause Analysis

In sea-loader.js:

function fi(e, t) {
  let i = kr(e), r = kr(t);
  if (!i && !r) return 0;
  if (!i) return -1;
  if (!r) return 1;
  for (let o = 0; o < 3; o++) {
    if (i[o] !== r[o]) return i[o] - r[o];
  }
  let s = e.includes("-"), n = t.includes("-");
  return s !== n ? (s ? -1 : 1) : e.localeCompare(t);
}
  1. kr() parses the first 3 dot-delimited integer segments [major, minor, patch].
  2. When comparing 1.0.81-9 and 1.0.81-11, the numeric segments [1, 0, 81] match.
  3. Both strings include -, so s !== n is false.
  4. The fallback is e.localeCompare(t).
  5. "1.0.81-9".localeCompare("1.0.81-11") evaluates to 1 (since '9' > '1').
  6. In mi("index.js", ...):
    i.sort((r, s) => {
      let n = fi(basename(s), basename(r));
      return n !== 0 ? n : ...;
    });
    
    The version list is sorted descending using fi(), placing 1.0.81-9 at the top before 1.0.81-11.
  7. hh() finds 1.0.81-9 and executes its index.js.

Steps to Reproduce
  1. Have both 1.0.81-9 and 1.0.81-11 in %LOCALAPPDATA%\copilot\pkg\win32-x64\.
  2. Run copilot --version.
  3. Observed: Outputs GitHub Copilot CLI 1.0.81-9..
  4. Explicitly passing --prefer-version 1.0.81-11 (copilot --prefer-version 1.0.81-11 --version) outputs GitHub Copilot CLI 1.0.81-11..
  5. Renaming/removing 1.0.81-9 immediately allows default copilot --version to output GitHub Copilot CLI 1.0.81-11..

Suggested Fix

Implement SemVer-compliant prerelease identifier comparison in fi() by splitting the prerelease tag (e.g. on . or -) and comparing numeric identifiers as integers and string identifiers lexicographically:

function comparePrerelease(a, b) {
  const parsePart = (p) => /^\d+$/.test(p) ? parseInt(p, 10) : p;
  const partsA = a.replace(/^[^-]*-/, '').split('.').map(parsePart);
  const partsB = b.replace(/^[^-]*-/, '').split('.').map(parsePart);
  const len = Math.max(partsA.length, partsB.length);
  for (let i = 0; i < len; i++) {
    if (partsA[i] === undefined) return -1;
    if (partsB[i] === undefined) return 1;
    if (partsA[i] === partsB[i]) continue;
    if (typeof partsA[i] === 'number' && typeof partsB[i] === 'number') {
      return partsA[i] - partsB[i];
    }
    return String(partsA[i]).localeCompare(String(partsB[i]));
  }
  return 0;
}

Environment
  • Platform: Windows 11 (win32-x64)
  • Copilot CLI: 1.0.81-11 binary loading 1.0.81-9 cached package

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez dans sea-loader.js avec fi(e, t), puis suivez son utilisation dans mi() et hh(). Reproduisez le problème avec les versions mises en cache 1.0.81-9 et 1.0.81-11, et comparez copilot --version avec --prefer-version. Le travail est terminé lorsque le loader par défaut sélectionne 1.0.81-11 plutôt que 1.0.81-9, qui est lexicographiquement supérieure.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
javascript
Domaine
cli
Type d'issue
Bug
Difficulté
3/5
Temps estimé
1-2 jours
Activité
Active
Clarté
Plutôt claire
Accessibilité débutants
72/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.