@codevector/cli 0.5.0 → 0.5.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.
package/dist/index.js CHANGED
@@ -17630,7 +17630,7 @@ function skipVoid(str, ptr, banNewLines, banComments) {
17630
17630
  }
17631
17631
  return ptr;
17632
17632
  }
17633
- function skipUntil(str, ptr, sep, end, banNewLines = false) {
17633
+ function skipUntil(str, ptr, sep2, end, banNewLines = false) {
17634
17634
  if (!end) {
17635
17635
  ptr = indexOfNewline(str, ptr);
17636
17636
  return ptr < 0 ? str.length : ptr;
@@ -17639,7 +17639,7 @@ function skipUntil(str, ptr, sep, end, banNewLines = false) {
17639
17639
  let c = str[i];
17640
17640
  if (c === "#") {
17641
17641
  i = indexOfNewline(str, i);
17642
- } else if (c === sep) {
17642
+ } else if (c === sep2) {
17643
17643
  return i + 1;
17644
17644
  } else if (c === end || banNewLines && (c === "\n" || c === "\r" && str[i + 1] === "\n")) {
17645
17645
  return i;
@@ -19109,7 +19109,74 @@ async function pickPinnedModel(models) {
19109
19109
  }
19110
19110
 
19111
19111
  // src/commands/doctor.ts
19112
- import { existsSync as existsSync7, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
19112
+ import { existsSync as existsSync8, readFileSync as readFileSync9, statSync as statSync5 } from "fs";
19113
+
19114
+ // src/lib/install-pref.ts
19115
+ import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync8, realpathSync, renameSync as renameSync4, writeFileSync as writeFileSync7 } from "fs";
19116
+ import { join as join10, sep } from "path";
19117
+ import { fileURLToPath as fileURLToPath2 } from "url";
19118
+ var INSTALL_PREF_FILE = join10(CODEVECTOR_CONFIG_DIR, "install.json");
19119
+ var PACKAGE_MANAGERS = ["npm", "pnpm", "yarn"];
19120
+ function isPackageManager(v2) {
19121
+ return typeof v2 === "string" && PACKAGE_MANAGERS.includes(v2);
19122
+ }
19123
+ function readInstallPref() {
19124
+ if (!existsSync7(INSTALL_PREF_FILE)) return void 0;
19125
+ try {
19126
+ const raw = readFileSync8(INSTALL_PREF_FILE, "utf8");
19127
+ const parsed = JSON.parse(raw);
19128
+ if (!isPackageManager(parsed.packageManager)) return void 0;
19129
+ const source = parsed.source === "user" ? "user" : "auto";
19130
+ return {
19131
+ packageManager: parsed.packageManager,
19132
+ source,
19133
+ detectedAt: typeof parsed.detectedAt === "string" ? parsed.detectedAt : (/* @__PURE__ */ new Date()).toISOString()
19134
+ };
19135
+ } catch {
19136
+ return void 0;
19137
+ }
19138
+ }
19139
+ function writeInstallPref(pref) {
19140
+ mkdirSync6(CODEVECTOR_CONFIG_DIR, { recursive: true, mode: 448 });
19141
+ const tmp = `${INSTALL_PREF_FILE}.${process.pid}.tmp`;
19142
+ writeFileSync7(tmp, JSON.stringify(pref, null, 2));
19143
+ renameSync4(tmp, INSTALL_PREF_FILE);
19144
+ }
19145
+ function packageManagerFromPath(installPath) {
19146
+ if (installPath.includes(`${sep}.pnpm${sep}`)) return "pnpm";
19147
+ if (installPath.includes(`${sep}.config${sep}yarn${sep}global${sep}`) || installPath.includes(`${sep}.yarn${sep}`)) {
19148
+ return "yarn";
19149
+ }
19150
+ if (installPath.includes(`${sep}lib${sep}node_modules${sep}`)) return "npm";
19151
+ return void 0;
19152
+ }
19153
+ function detectPackageManagerFromInstallPath() {
19154
+ try {
19155
+ const real = realpathSync(fileURLToPath2(import.meta.url));
19156
+ return packageManagerFromPath(real);
19157
+ } catch {
19158
+ return void 0;
19159
+ }
19160
+ }
19161
+ function resolveInstallManager() {
19162
+ const pref = readInstallPref();
19163
+ if (pref?.source === "user") return { packageManager: pref.packageManager, source: "user" };
19164
+ const fromPath = detectPackageManagerFromInstallPath();
19165
+ if (fromPath) {
19166
+ if (pref?.packageManager !== fromPath) {
19167
+ writeInstallPref({
19168
+ packageManager: fromPath,
19169
+ source: "auto",
19170
+ detectedAt: (/* @__PURE__ */ new Date()).toISOString()
19171
+ });
19172
+ }
19173
+ return { packageManager: fromPath, source: "path" };
19174
+ }
19175
+ if (pref) return { packageManager: pref.packageManager, source: "auto" };
19176
+ return { packageManager: void 0, source: "unknown" };
19177
+ }
19178
+
19179
+ // src/commands/doctor.ts
19113
19180
  var CLAUDE_SCOPE_ORDER = ["local", "project", "user"];
19114
19181
  var doctorCommand = defineCommand({
19115
19182
  meta: {
@@ -19121,45 +19188,43 @@ var doctorCommand = defineCommand({
19121
19188
  const creds = await readCredentials();
19122
19189
  if (!creds) {
19123
19190
  checks.push({
19124
- level: "fail",
19191
+ level: "warn",
19125
19192
  label: "credentials",
19126
- detail: `no credentials at ${CREDENTIALS_FILE} \u2014 run \`codevector auth login\``
19193
+ detail: `not logged in \u2014 no credentials at ${CREDENTIALS_FILE}. Run \`codevector auth login\`. Local checks still run.`
19127
19194
  });
19128
- emit(checks);
19129
- process.exitCode = 1;
19130
- return;
19131
- }
19132
- checks.push({
19133
- level: "ok",
19134
- label: "credentials",
19135
- detail: `${creds.email} @ ${creds.gatewayUrl} (${maskApiKey(creds.apiKey)})`
19136
- });
19137
- checks.push(
19138
- credentialsFileModeOk() ? { level: "ok", label: "credentials permissions", detail: "chmod 600" } : {
19139
- level: "warn",
19140
- label: "credentials permissions",
19141
- detail: `expected 0600 on ${CREDENTIALS_FILE}`
19142
- }
19143
- );
19144
- const client = gatewayClient(creds.gatewayUrl, creds.apiKey, 1e4);
19145
- try {
19146
- const me2 = await call(parseResponse(client.me.$get()));
19147
- if (me2.user.id !== creds.userId) {
19148
- checks.push({
19195
+ } else {
19196
+ checks.push({
19197
+ level: "ok",
19198
+ label: "credentials",
19199
+ detail: `${creds.email} @ ${creds.gatewayUrl} (${maskApiKey(creds.apiKey)})`
19200
+ });
19201
+ checks.push(
19202
+ credentialsFileModeOk() ? { level: "ok", label: "credentials permissions", detail: "chmod 600" } : {
19149
19203
  level: "warn",
19150
- label: "gateway /me",
19151
- detail: "user id mismatch \u2014 credentials may be stale. Re-run `codevector auth login`."
19152
- });
19153
- } else {
19154
- checks.push({ level: "ok", label: "gateway /me", detail: "200 OK" });
19204
+ label: "credentials permissions",
19205
+ detail: `expected 0600 on ${CREDENTIALS_FILE}`
19206
+ }
19207
+ );
19208
+ const client = gatewayClient(creds.gatewayUrl, creds.apiKey, 1e4);
19209
+ try {
19210
+ const me2 = await call(parseResponse(client.me.$get()));
19211
+ if (me2.user.id !== creds.userId) {
19212
+ checks.push({
19213
+ level: "warn",
19214
+ label: "gateway /me",
19215
+ detail: "user id mismatch \u2014 credentials may be stale. Re-run `codevector auth login`."
19216
+ });
19217
+ } else {
19218
+ checks.push({ level: "ok", label: "gateway /me", detail: "200 OK" });
19219
+ }
19220
+ } catch (err) {
19221
+ const message = err instanceof ApiClientError ? `${err.code}: ${err.message}` : String(err);
19222
+ checks.push({ level: "fail", label: "gateway /me", detail: message });
19155
19223
  }
19156
- } catch (err) {
19157
- const message = err instanceof ApiClientError ? `${err.code}: ${err.message}` : String(err);
19158
- checks.push({ level: "fail", label: "gateway /me", detail: message });
19159
19224
  }
19160
19225
  checks.push(inspectClaudeSettings());
19161
19226
  checks.push(...inspectManifestDrift());
19162
- if (!existsSync7(ACCEPTANCE_HOOK_FILE)) {
19227
+ if (!existsSync8(ACCEPTANCE_HOOK_FILE)) {
19163
19228
  checks.push({
19164
19229
  level: "warn",
19165
19230
  label: "acceptance hook",
@@ -19175,18 +19240,35 @@ var doctorCommand = defineCommand({
19175
19240
  }
19176
19241
  );
19177
19242
  }
19243
+ checks.push(inspectUpdateManager());
19178
19244
  emit(checks);
19179
19245
  if (checks.some((c) => c.level === "fail")) {
19180
19246
  process.exitCode = 1;
19181
19247
  }
19182
19248
  }
19183
19249
  });
19250
+ function inspectUpdateManager() {
19251
+ const resolved = resolveInstallManager();
19252
+ if (!resolved.packageManager) {
19253
+ return {
19254
+ level: "warn",
19255
+ label: "update manager",
19256
+ detail: "couldn't determine which package manager installed the CLI \u2014 `codevector update` will have to guess. Pin it with `codevector update --with <npm|pnpm|yarn>`."
19257
+ };
19258
+ }
19259
+ const how = resolved.source === "user" ? "pinned via --with" : resolved.source === "path" ? "detected from install path" : "auto-detected at install";
19260
+ return {
19261
+ level: "ok",
19262
+ label: "update manager",
19263
+ detail: `${resolved.packageManager} (${how})`
19264
+ };
19265
+ }
19184
19266
  function inspectClaudeSettings() {
19185
19267
  for (const scope of CLAUDE_SCOPE_ORDER) {
19186
19268
  const path = claudeSettingsPath(scope);
19187
- if (!existsSync7(path)) continue;
19269
+ if (!existsSync8(path)) continue;
19188
19270
  try {
19189
- const raw = JSON.parse(readFileSync8(path, "utf8"));
19271
+ const raw = JSON.parse(readFileSync9(path, "utf8"));
19190
19272
  if (typeof raw.env?.ANTHROPIC_BASE_URL === "string") {
19191
19273
  return {
19192
19274
  level: "ok",
@@ -19235,7 +19317,7 @@ function inspectManifestDrift() {
19235
19317
  });
19236
19318
  continue;
19237
19319
  }
19238
- if (!existsSync7(path)) {
19320
+ if (!existsSync8(path)) {
19239
19321
  checks.push({
19240
19322
  level: "fail",
19241
19323
  label: `manifest drift: ${tool.tool}`,
@@ -19245,7 +19327,7 @@ function inspectManifestDrift() {
19245
19327
  }
19246
19328
  let raw;
19247
19329
  try {
19248
- raw = readFileSync8(path, "utf8");
19330
+ raw = readFileSync9(path, "utf8");
19249
19331
  } catch (err) {
19250
19332
  checks.push({
19251
19333
  level: "fail",
@@ -19528,8 +19610,8 @@ _codevector_on_pwd
19528
19610
 
19529
19611
  // src/commands/init.ts
19530
19612
  import { execFileSync as execFileSync2 } from "child_process";
19531
- import { existsSync as existsSync8 } from "fs";
19532
- import { join as join10 } from "path";
19613
+ import { existsSync as existsSync9 } from "fs";
19614
+ import { join as join11 } from "path";
19533
19615
  var DEFAULT_TICKET_PATTERN2 = "[A-Z]+-\\d+";
19534
19616
  var initCommand = defineCommand({
19535
19617
  meta: {
@@ -19560,8 +19642,8 @@ var initCommand = defineCommand({
19560
19642
  },
19561
19643
  async run({ args }) {
19562
19644
  const cwd = userCwd();
19563
- const target = join10(cwd, PROJECT_CONFIG_FILENAME);
19564
- const existing = existsSync8(target) ? readProjectConfigAt(target) : null;
19645
+ const target = join11(cwd, PROJECT_CONFIG_FILENAME);
19646
+ const existing = existsSync9(target) ? readProjectConfigAt(target) : null;
19565
19647
  const interactive = isInteractive(args);
19566
19648
  if (existing && !args.force && !interactive) {
19567
19649
  throw new Error(
@@ -19893,7 +19975,7 @@ var modelsCommand = defineCommand({
19893
19975
  });
19894
19976
 
19895
19977
  // src/commands/profile.ts
19896
- import { existsSync as existsSync9, readFileSync as readFileSync9 } from "fs";
19978
+ import { existsSync as existsSync10, readFileSync as readFileSync10 } from "fs";
19897
19979
  var WRITERS3 = {
19898
19980
  "claude-code": writeClaudeCodeConfig,
19899
19981
  opencode: writeOpencodeConfig,
@@ -20139,10 +20221,10 @@ function pickCodexFallbackModel(reachable) {
20139
20221
  }
20140
20222
  function readCodexNuxRankedModels() {
20141
20223
  const path = codexConfigPath();
20142
- if (!existsSync9(path)) return [];
20224
+ if (!existsSync10(path)) return [];
20143
20225
  let parsed;
20144
20226
  try {
20145
- parsed = parse3(readFileSync9(path, "utf8"));
20227
+ parsed = parse3(readFileSync10(path, "utf8"));
20146
20228
  } catch {
20147
20229
  return [];
20148
20230
  }
@@ -20368,47 +20450,47 @@ Last saved: ${creds.savedAt}`,
20368
20450
  });
20369
20451
 
20370
20452
  // src/commands/system.ts
20371
- import { existsSync as existsSync11 } from "fs";
20453
+ import { existsSync as existsSync12 } from "fs";
20372
20454
 
20373
20455
  // src/lib/backup.ts
20374
20456
  import {
20375
20457
  copyFileSync as copyFileSync2,
20376
- existsSync as existsSync10,
20377
- mkdirSync as mkdirSync6,
20458
+ existsSync as existsSync11,
20459
+ mkdirSync as mkdirSync7,
20378
20460
  readdirSync,
20379
20461
  statSync as statSync6
20380
20462
  } from "fs";
20381
- import { basename, dirname as dirname7, join as join11 } from "path";
20463
+ import { basename, dirname as dirname7, join as join12 } from "path";
20382
20464
  import { homedir as homedir6 } from "os";
20383
- var BACKUP_ROOT = process.env.CODEVECTOR_BACKUP_ROOT ?? join11(homedir6(), ".codevector", "backups");
20465
+ var BACKUP_ROOT = process.env.CODEVECTOR_BACKUP_ROOT ?? join12(homedir6(), ".codevector", "backups");
20384
20466
  function backupTimestamp(d = /* @__PURE__ */ new Date()) {
20385
20467
  return d.toISOString().replace(/:/g, "-");
20386
20468
  }
20387
20469
  function backupFile(sourcePath, tool, timestamp) {
20388
- if (!existsSync10(sourcePath)) return void 0;
20389
- const destDir = join11(BACKUP_ROOT, timestamp, tool);
20390
- mkdirSync6(destDir, { recursive: true, mode: 448 });
20391
- const dest = join11(destDir, basename(sourcePath));
20470
+ if (!existsSync11(sourcePath)) return void 0;
20471
+ const destDir = join12(BACKUP_ROOT, timestamp, tool);
20472
+ mkdirSync7(destDir, { recursive: true, mode: 448 });
20473
+ const dest = join12(destDir, basename(sourcePath));
20392
20474
  copyFileSync2(sourcePath, dest);
20393
20475
  return dest;
20394
20476
  }
20395
20477
  function listBackupRuns() {
20396
- if (!existsSync10(BACKUP_ROOT)) return [];
20478
+ if (!existsSync11(BACKUP_ROOT)) return [];
20397
20479
  const entries = readdirSync(BACKUP_ROOT, { withFileTypes: true }).filter((e2) => e2.isDirectory()).map((e2) => e2.name).sort().reverse();
20398
20480
  const runs = [];
20399
20481
  for (const ts of entries) {
20400
- const dir = join11(BACKUP_ROOT, ts);
20482
+ const dir = join12(BACKUP_ROOT, ts);
20401
20483
  const tools = readdirSync(dir, { withFileTypes: true }).filter((e2) => e2.isDirectory());
20402
20484
  const collected = [];
20403
20485
  for (const toolDir of tools) {
20404
- const toolPath = join11(dir, toolDir.name);
20486
+ const toolPath = join12(dir, toolDir.name);
20405
20487
  for (const file2 of readdirSync(toolPath, { withFileTypes: true })) {
20406
20488
  if (!file2.isFile()) continue;
20407
20489
  collected.push({
20408
20490
  tool: toolDir.name,
20409
20491
  original: "",
20410
20492
  // resolved by caller per tool — see restoreBackup()
20411
- backup: join11(toolPath, file2.name)
20493
+ backup: join12(toolPath, file2.name)
20412
20494
  });
20413
20495
  }
20414
20496
  }
@@ -20418,10 +20500,10 @@ function listBackupRuns() {
20418
20500
  return runs;
20419
20501
  }
20420
20502
  function restoreBackup(backupPath, originalPath) {
20421
- if (!existsSync10(backupPath)) {
20503
+ if (!existsSync11(backupPath)) {
20422
20504
  throw new Error(`Backup file missing: ${backupPath}`);
20423
20505
  }
20424
- mkdirSync6(dirname7(originalPath), { recursive: true });
20506
+ mkdirSync7(dirname7(originalPath), { recursive: true });
20425
20507
  copyFileSync2(backupPath, originalPath);
20426
20508
  }
20427
20509
  function backupRunMtime(dir) {
@@ -20580,7 +20662,7 @@ var systemRestoreCommand = defineCommand({
20580
20662
  }
20581
20663
  const target = userPathFor(e2.tool);
20582
20664
  plan.push({ tool: e2.tool, backup: e2.backup, target });
20583
- R2.info(` ${e2.tool} \u2192 ${target}${existsSync11(target) ? " (will overwrite)" : " (new)"}`);
20665
+ R2.info(` ${e2.tool} \u2192 ${target}${existsSync12(target) ? " (will overwrite)" : " (new)"}`);
20584
20666
  }
20585
20667
  if (plan.length === 0) {
20586
20668
  ye("Nothing to restore.");
@@ -20669,7 +20751,7 @@ import { spawnSync } from "child_process";
20669
20751
  // package.json
20670
20752
  var package_default = {
20671
20753
  name: "@codevector/cli",
20672
- version: "0.5.0",
20754
+ version: "0.5.1",
20673
20755
  description: "CodeVector CLI \u2014 installs and configures first-party coding-tool integrations.",
20674
20756
  license: "UNLICENSED",
20675
20757
  bin: {
@@ -20714,43 +20796,98 @@ var package_default = {
20714
20796
  }
20715
20797
  };
20716
20798
 
20717
- // src/lib/install-pref.ts
20718
- import { existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as readFileSync10, renameSync as renameSync4, writeFileSync as writeFileSync7 } from "fs";
20719
- import { join as join12 } from "path";
20720
- var INSTALL_PREF_FILE = join12(CODEVECTOR_CONFIG_DIR, "install.json");
20721
- var PACKAGE_MANAGERS = ["npm", "pnpm", "yarn"];
20722
- function isPackageManager(v2) {
20723
- return typeof v2 === "string" && PACKAGE_MANAGERS.includes(v2);
20724
- }
20725
- function readInstallPref() {
20726
- if (!existsSync12(INSTALL_PREF_FILE)) return void 0;
20799
+ // src/lib/update-notifier.ts
20800
+ import { existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "fs";
20801
+ import { join as join13 } from "path";
20802
+ var PKG_NAME = "@codevector/cli";
20803
+ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
20804
+ var CHECK_CACHE_FILE = join13(CODEVECTOR_CONFIG_DIR, "update-check.json");
20805
+ var CHECK_TTL_MS = 24 * 60 * 60 * 1e3;
20806
+ var FETCH_TIMEOUT_MS = 2e3;
20807
+ function readCache() {
20808
+ if (!existsSync13(CHECK_CACHE_FILE)) return void 0;
20727
20809
  try {
20728
- const raw = readFileSync10(INSTALL_PREF_FILE, "utf8");
20810
+ const raw = readFileSync11(CHECK_CACHE_FILE, "utf8");
20729
20811
  const parsed = JSON.parse(raw);
20730
- if (!isPackageManager(parsed.packageManager)) return void 0;
20731
- const source = parsed.source === "user" ? "user" : "auto";
20812
+ if (typeof parsed.checkedAt !== "number") return void 0;
20732
20813
  return {
20733
- packageManager: parsed.packageManager,
20734
- source,
20735
- detectedAt: typeof parsed.detectedAt === "string" ? parsed.detectedAt : (/* @__PURE__ */ new Date()).toISOString()
20814
+ latest: typeof parsed.latest === "string" ? parsed.latest : null,
20815
+ checkedAt: parsed.checkedAt
20736
20816
  };
20737
20817
  } catch {
20738
20818
  return void 0;
20739
20819
  }
20740
20820
  }
20741
- function writeInstallPref(pref) {
20742
- mkdirSync7(CODEVECTOR_CONFIG_DIR, { recursive: true, mode: 448 });
20743
- const tmp = `${INSTALL_PREF_FILE}.${process.pid}.tmp`;
20744
- writeFileSync7(tmp, JSON.stringify(pref, null, 2));
20745
- renameSync4(tmp, INSTALL_PREF_FILE);
20821
+ function readCachedLatestVersion() {
20822
+ return readCache()?.latest ?? null;
20823
+ }
20824
+ function writeCache(cache) {
20825
+ try {
20826
+ mkdirSync8(CODEVECTOR_CONFIG_DIR, { recursive: true, mode: 448 });
20827
+ writeFileSync8(CHECK_CACHE_FILE, JSON.stringify(cache));
20828
+ } catch {
20829
+ }
20830
+ }
20831
+ function isNewer(current, latest) {
20832
+ const a = current.split(".").map((p2) => Number.parseInt(p2, 10));
20833
+ const b2 = latest.split(".").map((p2) => Number.parseInt(p2, 10));
20834
+ for (let i = 0; i < Math.max(a.length, b2.length); i++) {
20835
+ const ai = a[i] ?? 0;
20836
+ const bi = b2[i] ?? 0;
20837
+ if (Number.isNaN(ai) || Number.isNaN(bi)) return latest > current;
20838
+ if (bi > ai) return true;
20839
+ if (bi < ai) return false;
20840
+ }
20841
+ return false;
20842
+ }
20843
+ function printUpdateNoticeIfCached(currentVersion) {
20844
+ if (process.env.CODEVECTOR_NO_UPDATE_CHECK === "1") return;
20845
+ try {
20846
+ const cache = readCache();
20847
+ if (!cache || !cache.latest) return;
20848
+ if (isNewer(currentVersion, cache.latest)) {
20849
+ process.stderr.write(
20850
+ `\x1B[33m\u203A\x1B[0m A new version of @codevector/cli is available: ${currentVersion} \u2192 ${cache.latest}. Run \`codevector update\` to install.
20851
+ `
20852
+ );
20853
+ }
20854
+ } catch {
20855
+ }
20856
+ }
20857
+ function scheduleUpdateCheck() {
20858
+ if (process.env.CODEVECTOR_NO_UPDATE_CHECK === "1") return;
20859
+ const cache = readCache();
20860
+ const now = Date.now();
20861
+ if (cache && now - cache.checkedAt < CHECK_TTL_MS) return;
20862
+ void fetchLatestVersion().then((latest) => {
20863
+ writeCache({ latest, checkedAt: Date.now() });
20864
+ }).catch(() => {
20865
+ writeCache({ latest: cache?.latest ?? null, checkedAt: Date.now() });
20866
+ });
20867
+ }
20868
+ async function fetchLatestVersion() {
20869
+ const controller = new AbortController();
20870
+ const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
20871
+ timer.unref?.();
20872
+ try {
20873
+ const res = await fetch(REGISTRY_URL, {
20874
+ signal: controller.signal,
20875
+ headers: { accept: "application/json" }
20876
+ });
20877
+ if (!res.ok) return null;
20878
+ const body = await res.json();
20879
+ return typeof body.version === "string" ? body.version : null;
20880
+ } finally {
20881
+ clearTimeout(timer);
20882
+ }
20746
20883
  }
20747
20884
 
20748
20885
  // src/commands/update.ts
20749
- var PKG_NAME = "@codevector/cli";
20886
+ var PKG_NAME2 = "@codevector/cli";
20750
20887
  var updateCommand = defineCommand({
20751
20888
  meta: {
20752
20889
  name: "update",
20753
- description: `Update ${PKG_NAME} to the latest version on npm. Uses the package manager that installed it (auto-detected on install) unless --with overrides.`
20890
+ description: `Update ${PKG_NAME2} to the latest version on npm. Uses the package manager that installed it (auto-detected on install) unless --with overrides.`
20754
20891
  },
20755
20892
  args: {
20756
20893
  with: {
@@ -20776,10 +20913,35 @@ var updateCommand = defineCommand({
20776
20913
  `${command.cmd} exited with status ${result.status}. The new version was not installed.`
20777
20914
  );
20778
20915
  }
20779
- R2.success("Update complete. Run `codevector --version` to confirm.");
20916
+ verifyOnPathVersion(package_default.version, manager);
20780
20917
  ye("Done.");
20781
20918
  }
20782
20919
  });
20920
+ function verifyOnPathVersion(previousVersion, manager) {
20921
+ const after = readOnPathVersion();
20922
+ if (!after) {
20923
+ R2.success("Update complete. Run `codevector --version` to confirm.");
20924
+ return;
20925
+ }
20926
+ if (after !== previousVersion) {
20927
+ R2.success(`Update complete: ${previousVersion} \u2192 ${after}.`);
20928
+ return;
20929
+ }
20930
+ const latest = readCachedLatestVersion();
20931
+ if (latest && isNewer(previousVersion, latest)) {
20932
+ R2.warn(
20933
+ `The \`codevector\` on your PATH is still ${previousVersion}, but ${latest} is available. ${manager} likely installed into a different global location than the binary on your PATH. Try \`codevector update --with <the manager that owns the binary on your PATH>\`, or reinstall manually.`
20934
+ );
20935
+ return;
20936
+ }
20937
+ R2.success(`Already on the latest version (${previousVersion}).`);
20938
+ }
20939
+ function readOnPathVersion() {
20940
+ const probe = spawnSync("codevector", ["version"], { encoding: "utf8" });
20941
+ if (probe.error || probe.status !== 0) return void 0;
20942
+ const out = probe.stdout?.trim();
20943
+ return out && /^\d+\.\d+\.\d+/.test(out) ? out : void 0;
20944
+ }
20783
20945
  async function resolvePackageManager(raw) {
20784
20946
  if (raw) {
20785
20947
  const pm = parsePackageManager(raw);
@@ -20789,10 +20951,10 @@ async function resolvePackageManager(raw) {
20789
20951
  writeInstallPref({ packageManager: pm, source: "user", detectedAt: (/* @__PURE__ */ new Date()).toISOString() });
20790
20952
  return pm;
20791
20953
  }
20792
- const pref = readInstallPref();
20793
- if (pref) return pref.packageManager;
20794
- R2.info(
20795
- `Couldn't detect which package manager installed ${PKG_NAME} (no record at ${INSTALL_PREF_FILE}).`
20954
+ const resolved = resolveInstallManager();
20955
+ if (resolved.packageManager) return resolved.packageManager;
20956
+ R2.warn(
20957
+ `Couldn't determine which package manager installed ${PKG_NAME2} (no record at ${INSTALL_PREF_FILE}, and the install path didn't reveal it). Picking the wrong one installs into a location that isn't on your PATH.`
20796
20958
  );
20797
20959
  const picked = unwrap(
20798
20960
  await xe({
@@ -20823,7 +20985,7 @@ function parsePackageManager(value) {
20823
20985
  }
20824
20986
  }
20825
20987
  function installCommand(manager) {
20826
- const target = `${PKG_NAME}@latest`;
20988
+ const target = `${PKG_NAME2}@latest`;
20827
20989
  switch (manager) {
20828
20990
  case "npm":
20829
20991
  return { cmd: "npm", args: ["install", "-g", target] };
@@ -20932,89 +21094,6 @@ var versionCommand = defineCommand({
20932
21094
  }
20933
21095
  });
20934
21096
 
20935
- // src/lib/update-notifier.ts
20936
- import { existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "fs";
20937
- import { join as join13 } from "path";
20938
- var PKG_NAME2 = "@codevector/cli";
20939
- var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME2}/latest`;
20940
- var CHECK_CACHE_FILE = join13(CODEVECTOR_CONFIG_DIR, "update-check.json");
20941
- var CHECK_TTL_MS = 24 * 60 * 60 * 1e3;
20942
- var FETCH_TIMEOUT_MS = 2e3;
20943
- function readCache() {
20944
- if (!existsSync13(CHECK_CACHE_FILE)) return void 0;
20945
- try {
20946
- const raw = readFileSync11(CHECK_CACHE_FILE, "utf8");
20947
- const parsed = JSON.parse(raw);
20948
- if (typeof parsed.checkedAt !== "number") return void 0;
20949
- return {
20950
- latest: typeof parsed.latest === "string" ? parsed.latest : null,
20951
- checkedAt: parsed.checkedAt
20952
- };
20953
- } catch {
20954
- return void 0;
20955
- }
20956
- }
20957
- function writeCache(cache) {
20958
- try {
20959
- mkdirSync8(CODEVECTOR_CONFIG_DIR, { recursive: true, mode: 448 });
20960
- writeFileSync8(CHECK_CACHE_FILE, JSON.stringify(cache));
20961
- } catch {
20962
- }
20963
- }
20964
- function isNewer(current, latest) {
20965
- const a = current.split(".").map((p2) => Number.parseInt(p2, 10));
20966
- const b2 = latest.split(".").map((p2) => Number.parseInt(p2, 10));
20967
- for (let i = 0; i < Math.max(a.length, b2.length); i++) {
20968
- const ai = a[i] ?? 0;
20969
- const bi = b2[i] ?? 0;
20970
- if (Number.isNaN(ai) || Number.isNaN(bi)) return latest > current;
20971
- if (bi > ai) return true;
20972
- if (bi < ai) return false;
20973
- }
20974
- return false;
20975
- }
20976
- function printUpdateNoticeIfCached(currentVersion) {
20977
- if (process.env.CODEVECTOR_NO_UPDATE_CHECK === "1") return;
20978
- try {
20979
- const cache = readCache();
20980
- if (!cache || !cache.latest) return;
20981
- if (isNewer(currentVersion, cache.latest)) {
20982
- process.stderr.write(
20983
- `\x1B[33m\u203A\x1B[0m A new version of @codevector/cli is available: ${currentVersion} \u2192 ${cache.latest}. Run \`codevector update\` to install.
20984
- `
20985
- );
20986
- }
20987
- } catch {
20988
- }
20989
- }
20990
- function scheduleUpdateCheck() {
20991
- if (process.env.CODEVECTOR_NO_UPDATE_CHECK === "1") return;
20992
- const cache = readCache();
20993
- const now = Date.now();
20994
- if (cache && now - cache.checkedAt < CHECK_TTL_MS) return;
20995
- void fetchLatestVersion().then((latest) => {
20996
- writeCache({ latest, checkedAt: Date.now() });
20997
- }).catch(() => {
20998
- writeCache({ latest: cache?.latest ?? null, checkedAt: Date.now() });
20999
- });
21000
- }
21001
- async function fetchLatestVersion() {
21002
- const controller = new AbortController();
21003
- const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
21004
- timer.unref?.();
21005
- try {
21006
- const res = await fetch(REGISTRY_URL, {
21007
- signal: controller.signal,
21008
- headers: { accept: "application/json" }
21009
- });
21010
- if (!res.ok) return null;
21011
- const body = await res.json();
21012
- return typeof body.version === "string" ? body.version : null;
21013
- } finally {
21014
- clearTimeout(timer);
21015
- }
21016
- }
21017
-
21018
21097
  // src/index.ts
21019
21098
  var main = defineCommand({
21020
21099
  meta: {