repowisestage 0.0.51 → 0.0.53

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.
Files changed (2) hide show
  1. package/dist/bin/repowise.js +478 -69
  2. package/package.json +1 -1
@@ -669,6 +669,7 @@ var init_registry = __esm({
669
669
  extensions: [".java"],
670
670
  lspLanguageId: "java",
671
671
  installHint: "brew install jdtls (see https://github.com/eclipse-jdtls/eclipse.jdt.ls)",
672
+ nativeInstallKey: "jdtls",
672
673
  initializationOptions: {
673
674
  bundles: [],
674
675
  extendedClientCapabilities: {
@@ -784,7 +785,8 @@ var init_registry = __esm({
784
785
  args: [],
785
786
  extensions: [".kt", ".kts"],
786
787
  lspLanguageId: "kotlin",
787
- installHint: "brew install kotlin-language-server (or see https://github.com/fwcd/kotlin-language-server)"
788
+ installHint: "brew install kotlin-language-server (or see https://github.com/fwcd/kotlin-language-server)",
789
+ nativeInstallKey: "kotlin-language-server"
788
790
  }
789
791
  ],
790
792
  swift: [
@@ -942,38 +944,99 @@ var init_platforms = __esm({
942
944
  });
943
945
 
944
946
  // ../../packages/shared/src/constants/tiers.ts
945
- var SUBSCRIPTION_TIERS, TIER_LIMITS;
947
+ var SUBSCRIPTION_TIERS, TIER_LIMITS, TIER_FEATURES;
946
948
  var init_tiers = __esm({
947
949
  "../../packages/shared/src/constants/tiers.ts"() {
948
950
  "use strict";
949
951
  SUBSCRIPTION_TIERS = {
952
+ FREE: "free",
953
+ // `starter` is the legacy $15 tier — kept as a migration alias (with its OLD limits)
954
+ // until existing Starter subs are price-swapped to Free (pricing v3). Removed after M7.
950
955
  STARTER: "starter",
951
956
  PRO: "pro",
952
957
  TEAM: "team"
953
958
  };
954
959
  TIER_LIMITS = {
960
+ [SUBSCRIPTION_TIERS.FREE]: {
961
+ maxRepos: 1,
962
+ maxSeats: 1,
963
+ minSeats: 1,
964
+ maxSyncsPerMonth: 4,
965
+ // manual-only, hard cap (no overage)
966
+ maxConcurrentSyncs: 1,
967
+ freeFullScans: 0,
968
+ // graph-only: no LLM full scan
969
+ bedrockEndpoint: "public"
970
+ },
971
+ // Legacy alias — retains the OLD Starter limits until existing Starter subs are
972
+ // migrated to Free, then removed (M7). Do NOT reference for new logic.
955
973
  [SUBSCRIPTION_TIERS.STARTER]: {
956
974
  maxRepos: 1,
957
975
  maxSeats: 1,
976
+ minSeats: 1,
958
977
  maxSyncsPerMonth: 10,
959
978
  maxConcurrentSyncs: 1,
979
+ freeFullScans: 1,
960
980
  bedrockEndpoint: "public"
961
981
  },
962
982
  [SUBSCRIPTION_TIERS.PRO]: {
963
- maxRepos: 2,
983
+ maxRepos: 1,
964
984
  maxSeats: 1,
965
- maxSyncsPerMonth: 30,
985
+ minSeats: 1,
986
+ maxSyncsPerMonth: 20,
966
987
  maxConcurrentSyncs: 2,
988
+ freeFullScans: 1,
967
989
  bedrockEndpoint: "public"
968
990
  },
969
991
  [SUBSCRIPTION_TIERS.TEAM]: {
970
- maxRepos: 3,
992
+ maxRepos: 1,
971
993
  maxSeats: 999999,
994
+ minSeats: 3,
972
995
  maxSyncsPerMonth: 30,
973
996
  maxConcurrentSyncs: 10,
997
+ freeFullScans: 1,
974
998
  bedrockEndpoint: "public"
975
999
  }
976
1000
  };
1001
+ TIER_FEATURES = {
1002
+ [SUBSCRIPTION_TIERS.FREE]: {
1003
+ knowledgeGraph: true,
1004
+ mcp: true,
1005
+ context: false,
1006
+ // LLM-generated narrative context docs
1007
+ docs: false,
1008
+ // RepoWise Docs
1009
+ autoSync: false,
1010
+ // auto-sync on merge (Free is manual-only)
1011
+ overage: false
1012
+ // pay-as-you-go syncs (Free is hard-capped)
1013
+ },
1014
+ // Legacy alias — full features until existing Starter subs migrate to Free.
1015
+ [SUBSCRIPTION_TIERS.STARTER]: {
1016
+ knowledgeGraph: true,
1017
+ mcp: true,
1018
+ context: true,
1019
+ docs: true,
1020
+ autoSync: true,
1021
+ overage: true
1022
+ },
1023
+ [SUBSCRIPTION_TIERS.PRO]: {
1024
+ knowledgeGraph: true,
1025
+ mcp: true,
1026
+ context: true,
1027
+ docs: true,
1028
+ autoSync: true,
1029
+ overage: true
1030
+ },
1031
+ [SUBSCRIPTION_TIERS.TEAM]: {
1032
+ knowledgeGraph: true,
1033
+ mcp: true,
1034
+ context: true,
1035
+ docs: true,
1036
+ autoSync: true,
1037
+ overage: true
1038
+ }
1039
+ };
977
1040
  }
978
1041
  });
979
1042
 
@@ -1070,44 +1133,44 @@ var init_lsp_versions = __esm({
1070
1133
  "use strict";
1071
1134
  NATIVE_LSP_VERSIONS = {
1072
1135
  "rust-analyzer": {
1073
- repo: "rust-lang/rust-analyzer",
1074
- version: "2025-01-09",
1136
+ source: { kind: "github-release", repo: "rust-lang/rust-analyzer" },
1137
+ version: "2026-05-11",
1075
1138
  license: "MIT OR Apache-2.0",
1076
1139
  assets: {
1077
1140
  "darwin-arm64": {
1078
1141
  filename: "rust-analyzer-aarch64-apple-darwin.gz",
1079
- sha256: null,
1142
+ sha256: "eeb6367cd2c6cc9217ae06cea2e0c7e9cf20cdac5e934a1b272b13c76ece5aee",
1080
1143
  binaryPath: "rust-analyzer-aarch64-apple-darwin"
1081
1144
  },
1082
1145
  "darwin-x64": {
1083
1146
  filename: "rust-analyzer-x86_64-apple-darwin.gz",
1084
- sha256: null,
1147
+ sha256: "718398822ec2f282bca36f6f109bbbb33746437e1a63946fe7fd3d84d502a67d",
1085
1148
  binaryPath: "rust-analyzer-x86_64-apple-darwin"
1086
1149
  },
1087
1150
  "linux-x64": {
1088
1151
  filename: "rust-analyzer-x86_64-unknown-linux-gnu.gz",
1089
- sha256: null,
1152
+ sha256: "ede62b8536a37c90d804850d0bed3623e3d6af90a1195e4930a1627e5d8ae33f",
1090
1153
  binaryPath: "rust-analyzer-x86_64-unknown-linux-gnu"
1091
1154
  },
1092
1155
  "linux-arm64": {
1093
1156
  filename: "rust-analyzer-aarch64-unknown-linux-gnu.gz",
1094
- sha256: null,
1157
+ sha256: "dbe8c4c0bed79f36133c9d0a0eb629709d91343e065a179cd4a5f8137817de1c",
1095
1158
  binaryPath: "rust-analyzer-aarch64-unknown-linux-gnu"
1096
1159
  },
1097
1160
  "win32-x64": {
1098
1161
  filename: "rust-analyzer-x86_64-pc-windows-msvc.zip",
1099
- sha256: null,
1162
+ sha256: "1600365f2d8b0e42a811eafb5e129b75b991ddf9d9955d19d8fc2f4f2b9c19ef",
1100
1163
  binaryPath: "rust-analyzer.exe"
1101
1164
  },
1102
1165
  "win32-arm64": {
1103
1166
  filename: "rust-analyzer-aarch64-pc-windows-msvc.zip",
1104
- sha256: null,
1167
+ sha256: "3cd63d31e9abfea89488eebfd2c29d41550af6cb6f6b32f52e455fb783215fd0",
1105
1168
  binaryPath: "rust-analyzer.exe"
1106
1169
  }
1107
1170
  }
1108
1171
  },
1109
1172
  clangd: {
1110
- repo: "clangd/clangd",
1173
+ source: { kind: "github-release", repo: "clangd/clangd" },
1111
1174
  version: "18.1.3",
1112
1175
  license: "Apache-2.0 WITH LLVM-exception",
1113
1176
  assets: {
@@ -1115,22 +1178,22 @@ var init_lsp_versions = __esm({
1115
1178
  // architectures — same filename for darwin-arm64 and darwin-x64.
1116
1179
  "darwin-arm64": {
1117
1180
  filename: "clangd-mac-18.1.3.zip",
1118
- sha256: null,
1181
+ sha256: "442c18d98671d8b5d811b25002ad1f2fd0b9efb07e7905a41502f1f1311dc566",
1119
1182
  binaryPath: "clangd_18.1.3/bin/clangd"
1120
1183
  },
1121
1184
  "darwin-x64": {
1122
1185
  filename: "clangd-mac-18.1.3.zip",
1123
- sha256: null,
1186
+ sha256: "442c18d98671d8b5d811b25002ad1f2fd0b9efb07e7905a41502f1f1311dc566",
1124
1187
  binaryPath: "clangd_18.1.3/bin/clangd"
1125
1188
  },
1126
1189
  "linux-x64": {
1127
1190
  filename: "clangd-linux-18.1.3.zip",
1128
- sha256: null,
1191
+ sha256: "775f6ac798d9c599258e3f4fa14d0af908b1801d38250e72a18fb907b28a1be6",
1129
1192
  binaryPath: "clangd_18.1.3/bin/clangd"
1130
1193
  },
1131
1194
  "win32-x64": {
1132
1195
  filename: "clangd-windows-18.1.3.zip",
1133
- sha256: null,
1196
+ sha256: "3d287d39bab29406f002ff80b939668e59e25ef72346d8f38826305016e45896",
1134
1197
  binaryPath: "clangd_18.1.3/bin/clangd.exe"
1135
1198
  }
1136
1199
  }
@@ -1141,36 +1204,123 @@ var init_lsp_versions = __esm({
1141
1204
  // GitHub-release Tier 1 entry; the magic is what we DO with it after
1142
1205
  // install (see coursier-installer.ts).
1143
1206
  coursier: {
1144
- repo: "coursier/coursier",
1207
+ source: { kind: "github-release", repo: "coursier/coursier" },
1145
1208
  version: "v2.1.24",
1146
1209
  license: "Apache-2.0",
1147
1210
  assets: {
1148
1211
  "darwin-arm64": {
1149
1212
  filename: "cs-aarch64-apple-darwin.gz",
1150
- sha256: null,
1213
+ sha256: "53a5728c2016118c8296fa7d5678ddfe122e22dc6c36deb554d771b3b9295b4f",
1151
1214
  binaryPath: "cs"
1152
1215
  },
1153
1216
  "darwin-x64": {
1154
1217
  filename: "cs-x86_64-apple-darwin.gz",
1155
- sha256: null,
1218
+ sha256: "33913cd6b61658035d9e6fe971e919cb0ef1f659aa7bff7deeded963a2d36385",
1156
1219
  binaryPath: "cs"
1157
1220
  },
1158
1221
  "linux-x64": {
1159
1222
  filename: "cs-x86_64-pc-linux.gz",
1160
- sha256: null,
1161
- binaryPath: "cs"
1162
- },
1163
- "linux-arm64": {
1164
- filename: "cs-aarch64-pc-linux-static.gz",
1165
- sha256: null,
1223
+ sha256: "d2c0572a17fb6146ea65349b59dd216b38beff60ae22bce6e549867c6ed2eda6",
1166
1224
  binaryPath: "cs"
1167
1225
  },
1226
+ // coursier v2.1.24 ships no aarch64-linux build — Scala dev on
1227
+ // ARM Linux falls back to the toolchain-installed Metals path.
1168
1228
  "win32-x64": {
1169
1229
  filename: "cs-x86_64-pc-win32.zip",
1170
- sha256: null,
1230
+ sha256: "c16b4f95b59fbe035cdda4353cfca78befcbbef5a20a3b151c679717c1504c9f",
1171
1231
  binaryPath: "cs.exe"
1172
1232
  }
1173
1233
  }
1234
+ },
1235
+ // Eclipse JDT Language Server — single cross-platform tarball
1236
+ // hosted at download.eclipse.org. Ships as an Equinox launcher jar
1237
+ // that must be invoked via `java -jar`, so the installer generates
1238
+ // a `bin/jdtls` shim that selects the right config_{platform} dir.
1239
+ // Requires JDK 17+ (jdtls 1.51 minimum).
1240
+ jdtls: {
1241
+ source: { kind: "direct-url" },
1242
+ version: "1.51.0",
1243
+ license: "EPL-2.0",
1244
+ requiresJdk: 17,
1245
+ assets: {
1246
+ "darwin-arm64": {
1247
+ url: "https://download.eclipse.org/jdtls/milestones/1.51.0/jdt-language-server-1.51.0-202510022025.tar.gz",
1248
+ filename: "jdt-language-server-1.51.0-202510022025.tar.gz",
1249
+ sha256: "8a59372117881bf5bdc0220f2254472846b88137c058f344b00a7d41427745a1",
1250
+ binaryPath: "plugins/org.eclipse.equinox.launcher_*.jar",
1251
+ launcherJarGlob: "plugins/org.eclipse.equinox.launcher_*.jar",
1252
+ wrapperBinaryName: "jdtls"
1253
+ },
1254
+ "darwin-x64": {
1255
+ url: "https://download.eclipse.org/jdtls/milestones/1.51.0/jdt-language-server-1.51.0-202510022025.tar.gz",
1256
+ filename: "jdt-language-server-1.51.0-202510022025.tar.gz",
1257
+ sha256: "8a59372117881bf5bdc0220f2254472846b88137c058f344b00a7d41427745a1",
1258
+ binaryPath: "plugins/org.eclipse.equinox.launcher_*.jar",
1259
+ launcherJarGlob: "plugins/org.eclipse.equinox.launcher_*.jar",
1260
+ wrapperBinaryName: "jdtls"
1261
+ },
1262
+ "linux-x64": {
1263
+ url: "https://download.eclipse.org/jdtls/milestones/1.51.0/jdt-language-server-1.51.0-202510022025.tar.gz",
1264
+ filename: "jdt-language-server-1.51.0-202510022025.tar.gz",
1265
+ sha256: "8a59372117881bf5bdc0220f2254472846b88137c058f344b00a7d41427745a1",
1266
+ binaryPath: "plugins/org.eclipse.equinox.launcher_*.jar",
1267
+ launcherJarGlob: "plugins/org.eclipse.equinox.launcher_*.jar",
1268
+ wrapperBinaryName: "jdtls"
1269
+ },
1270
+ "linux-arm64": {
1271
+ url: "https://download.eclipse.org/jdtls/milestones/1.51.0/jdt-language-server-1.51.0-202510022025.tar.gz",
1272
+ filename: "jdt-language-server-1.51.0-202510022025.tar.gz",
1273
+ sha256: "8a59372117881bf5bdc0220f2254472846b88137c058f344b00a7d41427745a1",
1274
+ binaryPath: "plugins/org.eclipse.equinox.launcher_*.jar",
1275
+ launcherJarGlob: "plugins/org.eclipse.equinox.launcher_*.jar",
1276
+ wrapperBinaryName: "jdtls"
1277
+ },
1278
+ "win32-x64": {
1279
+ url: "https://download.eclipse.org/jdtls/milestones/1.51.0/jdt-language-server-1.51.0-202510022025.tar.gz",
1280
+ filename: "jdt-language-server-1.51.0-202510022025.tar.gz",
1281
+ sha256: "8a59372117881bf5bdc0220f2254472846b88137c058f344b00a7d41427745a1",
1282
+ binaryPath: "plugins/org.eclipse.equinox.launcher_*.jar",
1283
+ launcherJarGlob: "plugins/org.eclipse.equinox.launcher_*.jar",
1284
+ wrapperBinaryName: "jdtls"
1285
+ }
1286
+ }
1287
+ },
1288
+ // fwcd/kotlin-language-server — single cross-platform zip on GitHub
1289
+ // releases. Ships a `bin/kotlin-language-server` shell script + a
1290
+ // matching `.bat` for Windows — both invoke `java` internally, so
1291
+ // we just chmod+x and symlink (no shim needed). Requires JDK 11+.
1292
+ "kotlin-language-server": {
1293
+ source: { kind: "github-release", repo: "fwcd/kotlin-language-server" },
1294
+ version: "1.3.13",
1295
+ license: "MIT",
1296
+ requiresJdk: 11,
1297
+ assets: {
1298
+ "darwin-arm64": {
1299
+ filename: "server.zip",
1300
+ sha256: "4fe7d71d087b307c7869036171bd9d8c6a4284cd7c25b89098b0a24eb2d9b6d2",
1301
+ binaryPath: "server/bin/kotlin-language-server"
1302
+ },
1303
+ "darwin-x64": {
1304
+ filename: "server.zip",
1305
+ sha256: "4fe7d71d087b307c7869036171bd9d8c6a4284cd7c25b89098b0a24eb2d9b6d2",
1306
+ binaryPath: "server/bin/kotlin-language-server"
1307
+ },
1308
+ "linux-x64": {
1309
+ filename: "server.zip",
1310
+ sha256: "4fe7d71d087b307c7869036171bd9d8c6a4284cd7c25b89098b0a24eb2d9b6d2",
1311
+ binaryPath: "server/bin/kotlin-language-server"
1312
+ },
1313
+ "linux-arm64": {
1314
+ filename: "server.zip",
1315
+ sha256: "4fe7d71d087b307c7869036171bd9d8c6a4284cd7c25b89098b0a24eb2d9b6d2",
1316
+ binaryPath: "server/bin/kotlin-language-server"
1317
+ },
1318
+ "win32-x64": {
1319
+ filename: "server.zip",
1320
+ sha256: "4fe7d71d087b307c7869036171bd9d8c6a4284cd7c25b89098b0a24eb2d9b6d2",
1321
+ binaryPath: "server/bin/kotlin-language-server.bat"
1322
+ }
1323
+ }
1174
1324
  }
1175
1325
  };
1176
1326
  COURSIER_LSPS = {
@@ -1242,11 +1392,79 @@ var init_src = __esm({
1242
1392
  }
1243
1393
  });
1244
1394
 
1395
+ // ../listener/dist/lsp/jdk-probe.js
1396
+ import { spawn as spawn3 } from "child_process";
1397
+ function parseJavaMajorVersion(stderr) {
1398
+ const modernMatch = /\b(?:openjdk|java) version "(\d+)(?:\.\d+)*(?:[._]\w+)?"/.exec(stderr);
1399
+ if (!modernMatch?.[1])
1400
+ return void 0;
1401
+ const first = Number.parseInt(modernMatch[1], 10);
1402
+ if (!Number.isFinite(first))
1403
+ return void 0;
1404
+ if (first === 1) {
1405
+ const legacyMatch = /\b(?:openjdk|java) version "1\.(\d+)/.exec(stderr);
1406
+ if (legacyMatch?.[1]) {
1407
+ const legacy = Number.parseInt(legacyMatch[1], 10);
1408
+ return Number.isFinite(legacy) ? legacy : void 0;
1409
+ }
1410
+ }
1411
+ return first;
1412
+ }
1413
+ async function probeJdk(options = {}) {
1414
+ const timeoutMs = options.timeoutMs ?? 5e3;
1415
+ return new Promise((resolve5) => {
1416
+ let stderr = "";
1417
+ let settled = false;
1418
+ const child = spawn3("java", ["-version"], { stdio: ["ignore", "pipe", "pipe"] });
1419
+ const timer = setTimeout(() => {
1420
+ if (settled)
1421
+ return;
1422
+ settled = true;
1423
+ try {
1424
+ child.kill("SIGKILL");
1425
+ } catch {
1426
+ }
1427
+ resolve5({ present: false });
1428
+ }, timeoutMs);
1429
+ child.stderr.on("data", (chunk) => {
1430
+ stderr += chunk.toString("utf8");
1431
+ });
1432
+ child.on("error", () => {
1433
+ if (settled)
1434
+ return;
1435
+ settled = true;
1436
+ clearTimeout(timer);
1437
+ resolve5({ present: false });
1438
+ });
1439
+ child.on("close", (code) => {
1440
+ if (settled)
1441
+ return;
1442
+ settled = true;
1443
+ clearTimeout(timer);
1444
+ if (code !== 0) {
1445
+ resolve5({ present: false, rawOutput: stderr.trim() });
1446
+ return;
1447
+ }
1448
+ const major = parseJavaMajorVersion(stderr);
1449
+ if (major === void 0) {
1450
+ resolve5({ present: true, rawOutput: stderr.trim() });
1451
+ return;
1452
+ }
1453
+ resolve5({ present: true, majorVersion: major, rawOutput: stderr.trim() });
1454
+ });
1455
+ });
1456
+ }
1457
+ var init_jdk_probe = __esm({
1458
+ "../listener/dist/lsp/jdk-probe.js"() {
1459
+ "use strict";
1460
+ }
1461
+ });
1462
+
1245
1463
  // ../listener/dist/lsp/native-installer.js
1246
1464
  import { createWriteStream } from "fs";
1247
1465
  import { promises as fs } from "fs";
1248
1466
  import { createGunzip } from "zlib";
1249
- import { spawn as spawn3 } from "child_process";
1467
+ import { spawn as spawn4 } from "child_process";
1250
1468
  import { pipeline } from "stream/promises";
1251
1469
  import { createHash as createHash2 } from "crypto";
1252
1470
  import { join as join14, dirname as dirname5 } from "path";
@@ -1268,16 +1486,43 @@ async function ensureNativeLspInstalled(lspKey) {
1268
1486
  if (!asset) {
1269
1487
  return { installed: false, alreadyPresent: false, skipped: "unsupported-platform" };
1270
1488
  }
1489
+ if (entry.requiresJdk !== void 0) {
1490
+ const jdk = await probeJdk();
1491
+ if (!jdk.present || jdk.majorVersion === void 0 || jdk.majorVersion < entry.requiresJdk) {
1492
+ return {
1493
+ installed: false,
1494
+ alreadyPresent: false,
1495
+ skipped: "jvm-missing",
1496
+ error: `${lspKey} requires JDK ${entry.requiresJdk.toString()}+ (found: ${jdk.present ? `Java ${jdk.majorVersion?.toString() ?? "?"}` : "no java on PATH"}). Install with: brew install openjdk@21 (macOS) or apt install openjdk-21-jdk (Linux)`
1497
+ };
1498
+ }
1499
+ }
1500
+ const usesWrapper = Boolean(asset.launcherJarGlob && asset.wrapperBinaryName);
1271
1501
  const versionDir = join14(getNativeLspDir(), lspKey, entry.version);
1272
- const installedBinary = join14(versionDir, asset.binaryPath);
1273
- if (await pathExists(installedBinary)) {
1274
- await ensureSymlinkInBin(lspKey, installedBinary);
1275
- return { installed: false, alreadyPresent: true, binaryPath: installedBinary };
1502
+ if (usesWrapper && asset.launcherJarGlob && asset.wrapperBinaryName) {
1503
+ const jarPath = await resolveGlobInsideDir(versionDir, asset.launcherJarGlob);
1504
+ const shimPath = join14(getNativeLspBinDir(), asset.wrapperBinaryName);
1505
+ if (jarPath && await pathExists(shimPath)) {
1506
+ return { installed: false, alreadyPresent: true, binaryPath: shimPath };
1507
+ }
1508
+ } else {
1509
+ const installedBinary = join14(versionDir, asset.binaryPath);
1510
+ if (await pathExists(installedBinary)) {
1511
+ await ensureSymlinkInBin(lspKey, installedBinary, asset.binaryPath);
1512
+ return { installed: false, alreadyPresent: true, binaryPath: installedBinary };
1513
+ }
1276
1514
  }
1277
1515
  try {
1278
1516
  await fs.mkdir(versionDir, { recursive: true });
1279
1517
  const tmpDownload = join14(versionDir, `.${asset.filename}.download`);
1280
- const downloadUrl = `https://github.com/${entry.repo}/releases/download/${entry.version}/${asset.filename}`;
1518
+ const downloadUrl = entry.source.kind === "github-release" ? `https://github.com/${entry.source.repo}/releases/download/${entry.version}/${asset.filename}` : asset.url ?? "";
1519
+ if (!downloadUrl) {
1520
+ return {
1521
+ installed: false,
1522
+ alreadyPresent: false,
1523
+ error: `direct-url asset for ${lspKey} missing required \`url\` field`
1524
+ };
1525
+ }
1281
1526
  await downloadFile(downloadUrl, tmpDownload);
1282
1527
  if (asset.sha256) {
1283
1528
  const actual = await sha256File(tmpDownload);
@@ -1290,10 +1535,28 @@ async function ensureNativeLspInstalled(lspKey) {
1290
1535
  };
1291
1536
  }
1292
1537
  } else {
1293
- console.warn(`[lsp-install] WARN: SHA256 verification skipped for ${lspKey} (no pin in NATIVE_LSP_VERSIONS) \u2014 please pin in a follow-up commit`);
1538
+ console.warn(`[lsp-install] WARN: SHA256 verification skipped for ${lspKey} (no pin in NATIVE_LSP_VERSIONS) \u2014 run apps/listener/scripts/pin-native-shas.ts to record one`);
1294
1539
  }
1295
1540
  await extractAsset(tmpDownload, versionDir, asset);
1296
1541
  await fs.unlink(tmpDownload).catch(() => void 0);
1542
+ if (usesWrapper && asset.launcherJarGlob && asset.wrapperBinaryName) {
1543
+ const jarPath = await resolveGlobInsideDir(versionDir, asset.launcherJarGlob);
1544
+ if (!jarPath) {
1545
+ return {
1546
+ installed: false,
1547
+ alreadyPresent: false,
1548
+ error: `extract completed but no JAR matched ${asset.launcherJarGlob} in ${versionDir}`
1549
+ };
1550
+ }
1551
+ const shimPath = await writeJdtlsWrapper({
1552
+ binaryName: asset.wrapperBinaryName,
1553
+ versionDir,
1554
+ launcherJarPath: jarPath
1555
+ });
1556
+ await pruneStaleVersions(lspKey, entry.version);
1557
+ return { installed: true, alreadyPresent: false, binaryPath: shimPath };
1558
+ }
1559
+ const installedBinary = join14(versionDir, asset.binaryPath);
1297
1560
  if (!await pathExists(installedBinary)) {
1298
1561
  return {
1299
1562
  installed: false,
@@ -1302,7 +1565,8 @@ async function ensureNativeLspInstalled(lspKey) {
1302
1565
  };
1303
1566
  }
1304
1567
  await fs.chmod(installedBinary, 493).catch(() => void 0);
1305
- await ensureSymlinkInBin(lspKey, installedBinary);
1568
+ await ensureSymlinkInBin(lspKey, installedBinary, asset.binaryPath);
1569
+ await pruneStaleVersions(lspKey, entry.version);
1306
1570
  return { installed: true, alreadyPresent: false, binaryPath: installedBinary };
1307
1571
  } catch (err) {
1308
1572
  return {
@@ -1312,10 +1576,112 @@ async function ensureNativeLspInstalled(lspKey) {
1312
1576
  };
1313
1577
  }
1314
1578
  }
1315
- async function ensureSymlinkInBin(lspKey, target) {
1579
+ async function resolveGlobInsideDir(versionDir, glob) {
1580
+ const parts = glob.split("/");
1581
+ let dir = versionDir;
1582
+ for (let i = 0; i < parts.length - 1; i += 1) {
1583
+ dir = join14(dir, parts[i]);
1584
+ }
1585
+ const pattern = parts[parts.length - 1];
1586
+ const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
1587
+ const re = new RegExp(`^${escaped}$`);
1588
+ let entries;
1589
+ try {
1590
+ entries = await fs.readdir(dir);
1591
+ } catch {
1592
+ return null;
1593
+ }
1594
+ const matches = entries.filter((e) => re.test(e)).sort();
1595
+ const last = matches[matches.length - 1];
1596
+ return last ? join14(dir, last) : null;
1597
+ }
1598
+ async function pruneStaleVersions(lspKey, currentVersion) {
1599
+ const lspDir = join14(getNativeLspDir(), lspKey);
1600
+ let entries;
1601
+ try {
1602
+ entries = await fs.readdir(lspDir);
1603
+ } catch {
1604
+ return;
1605
+ }
1606
+ await Promise.all(entries.filter((name) => name !== currentVersion).map(async (name) => {
1607
+ try {
1608
+ await fs.rm(join14(lspDir, name), { recursive: true, force: true });
1609
+ } catch {
1610
+ }
1611
+ }));
1612
+ }
1613
+ function shQuote(value) {
1614
+ return value.replace(/[\\"$`]/g, (ch) => `\\${ch}`);
1615
+ }
1616
+ function cmdQuote(value) {
1617
+ return value.replace(/"/g, '""').replace(/%/g, "%%");
1618
+ }
1619
+ async function writeJdtlsWrapper(input) {
1620
+ const binDir = getNativeLspBinDir();
1621
+ await fs.mkdir(binDir, { recursive: true });
1622
+ const shimPath = join14(binDir, input.binaryName);
1623
+ const platformCfgDir = process.platform === "darwin" ? "config_mac" : process.platform === "win32" ? "config_win" : "config_linux";
1624
+ const workspaceBase = join14(input.versionDir, "workspaces");
1625
+ const qLauncher = shQuote(input.launcherJarPath);
1626
+ const qConfig = shQuote(`${input.versionDir}/${platformCfgDir}`);
1627
+ const qWorkspaceBase = shQuote(workspaceBase);
1628
+ const unixScript = `#!/usr/bin/env bash
1629
+ # Generated by repowise listener \u2014 do not edit by hand.
1630
+ # Invokes Eclipse JDT.LS via the equinox launcher.
1631
+ set -euo pipefail
1632
+ WS_NAME="\${REPOWISE_JDTLS_WS_NAME:-default}"
1633
+ WS_DIR="${qWorkspaceBase}/\${WS_NAME}"
1634
+ mkdir -p "$WS_DIR"
1635
+ exec java \\
1636
+ -Declipse.application=org.eclipse.jdt.ls.core.id1 \\
1637
+ -Dosgi.bundles.defaultStartLevel=4 \\
1638
+ -Declipse.product=org.eclipse.jdt.ls.core.product \\
1639
+ -Dlog.level=ALL \\
1640
+ -Xms1g \\
1641
+ --add-modules=ALL-SYSTEM \\
1642
+ --add-opens java.base/java.util=ALL-UNNAMED \\
1643
+ --add-opens java.base/java.lang=ALL-UNNAMED \\
1644
+ -jar "${qLauncher}" \\
1645
+ -configuration "${qConfig}" \\
1646
+ -data "$WS_DIR" \\
1647
+ "$@"
1648
+ `;
1649
+ await fs.writeFile(shimPath, unixScript);
1650
+ await fs.chmod(shimPath, 493);
1651
+ if (process.platform === "win32") {
1652
+ const winShim = `${shimPath}.cmd`;
1653
+ const cqLauncher = cmdQuote(input.launcherJarPath);
1654
+ const cqConfig = cmdQuote(`${input.versionDir}\\${platformCfgDir}`);
1655
+ const cqWorkspaceBase = cmdQuote(workspaceBase);
1656
+ const winScript = `@echo off\r
1657
+ rem Generated by repowise listener\r
1658
+ if "%REPOWISE_JDTLS_WS_NAME%"=="" set REPOWISE_JDTLS_WS_NAME=default\r
1659
+ set WS_DIR=${cqWorkspaceBase}\\%REPOWISE_JDTLS_WS_NAME%\r
1660
+ if not exist "%WS_DIR%" mkdir "%WS_DIR%"\r
1661
+ java ^\r
1662
+ -Declipse.application=org.eclipse.jdt.ls.core.id1 ^\r
1663
+ -Dosgi.bundles.defaultStartLevel=4 ^\r
1664
+ -Declipse.product=org.eclipse.jdt.ls.core.product ^\r
1665
+ -Dlog.level=ALL ^\r
1666
+ -Xms1g ^\r
1667
+ --add-modules=ALL-SYSTEM ^\r
1668
+ --add-opens java.base/java.util=ALL-UNNAMED ^\r
1669
+ --add-opens java.base/java.lang=ALL-UNNAMED ^\r
1670
+ -jar "${cqLauncher}" ^\r
1671
+ -configuration "${cqConfig}" ^\r
1672
+ -data "%WS_DIR%" ^\r
1673
+ %*\r
1674
+ `;
1675
+ await fs.writeFile(winShim, winScript);
1676
+ }
1677
+ return shimPath;
1678
+ }
1679
+ async function ensureSymlinkInBin(lspKey, target, sourceAssetPath) {
1316
1680
  const binDir = getNativeLspBinDir();
1317
1681
  await fs.mkdir(binDir, { recursive: true });
1318
- const linkPath = join14(binDir, lspKey);
1682
+ const winExtMatch = process.platform === "win32" && sourceAssetPath ? /\.(exe|bat|cmd|ps1)$/i.exec(sourceAssetPath) : null;
1683
+ const linkName = winExtMatch ? `${lspKey}${winExtMatch[0].toLowerCase()}` : lspKey;
1684
+ const linkPath = join14(binDir, linkName);
1319
1685
  try {
1320
1686
  await fs.unlink(linkPath);
1321
1687
  } catch {
@@ -1373,7 +1739,7 @@ async function extractAsset(source, destDir, asset) {
1373
1739
  }
1374
1740
  async function runExternal(cmd, args) {
1375
1741
  return new Promise((resolve5, reject) => {
1376
- const child = spawn3(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
1742
+ const child = spawn4(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
1377
1743
  let stderr = "";
1378
1744
  child.stderr.on("data", (chunk) => {
1379
1745
  stderr += chunk.toString();
@@ -1400,12 +1766,13 @@ var init_native_installer = __esm({
1400
1766
  "use strict";
1401
1767
  init_src();
1402
1768
  init_installer();
1769
+ init_jdk_probe();
1403
1770
  }
1404
1771
  });
1405
1772
 
1406
1773
  // ../listener/dist/lsp/coursier-installer.js
1407
1774
  import { promises as fs2 } from "fs";
1408
- import { spawn as spawn4 } from "child_process";
1775
+ import { spawn as spawn5 } from "child_process";
1409
1776
  import { join as join15 } from "path";
1410
1777
  function getCoursierBinDir() {
1411
1778
  return join15(getLspInstallDir(), "coursier-bin");
@@ -1462,7 +1829,7 @@ async function ensureCoursierLspInstalled(key) {
1462
1829
  }
1463
1830
  async function runCs(cs, args) {
1464
1831
  return new Promise((resolve5, reject) => {
1465
- const child = spawn4(cs, args, { stdio: ["ignore", "pipe", "pipe"] });
1832
+ const child = spawn5(cs, args, { stdio: ["ignore", "pipe", "pipe"] });
1466
1833
  let stderr = "";
1467
1834
  child.stderr.on("data", (chunk) => {
1468
1835
  stderr += chunk.toString();
@@ -1494,7 +1861,7 @@ var init_coursier_installer = __esm({
1494
1861
  });
1495
1862
 
1496
1863
  // ../listener/dist/lsp/toolchain-installer.js
1497
- import { spawn as spawn5 } from "child_process";
1864
+ import { spawn as spawn6 } from "child_process";
1498
1865
  import { promises as fs3 } from "fs";
1499
1866
  import { homedir as homedir4 } from "os";
1500
1867
  import { join as join16 } from "path";
@@ -1589,7 +1956,7 @@ function getToolchainBinDirs() {
1589
1956
  }
1590
1957
  function runToolchain(cmd, args) {
1591
1958
  return new Promise((resolve5, reject) => {
1592
- const child = spawn5(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
1959
+ const child = spawn6(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
1593
1960
  let stderr = "";
1594
1961
  child.stderr.on("data", (chunk) => {
1595
1962
  stderr += chunk.toString();
@@ -1605,7 +1972,7 @@ function runToolchain(cmd, args) {
1605
1972
  }
1606
1973
  function captureStdout(cmd, args) {
1607
1974
  return new Promise((resolve5, reject) => {
1608
- const child = spawn5(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
1975
+ const child = spawn6(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
1609
1976
  let stdout = "";
1610
1977
  let stderr = "";
1611
1978
  child.stdout.on("data", (chunk) => {
@@ -1628,7 +1995,7 @@ async function isCommandOnPath(command) {
1628
1995
  return false;
1629
1996
  const probeCmd = process.platform === "win32" ? "where" : "which";
1630
1997
  return new Promise((resolve5) => {
1631
- const child = spawn5(probeCmd, [command], { stdio: "ignore", timeout: 5e3 });
1998
+ const child = spawn6(probeCmd, [command], { stdio: "ignore", timeout: 5e3 });
1632
1999
  child.on("error", () => resolve5(false));
1633
2000
  child.on("close", (code) => resolve5(code === 0));
1634
2001
  });
@@ -1651,7 +2018,7 @@ var init_toolchain_installer = __esm({
1651
2018
  // ../listener/dist/lsp/installer.js
1652
2019
  import { promises as fs4 } from "fs";
1653
2020
  import { join as join17, dirname as dirname6 } from "path";
1654
- import { spawn as spawn6 } from "child_process";
2021
+ import { spawn as spawn7 } from "child_process";
1655
2022
  function getLspInstallDir() {
1656
2023
  return join17(getConfigDir(), "lsp-servers");
1657
2024
  }
@@ -1710,7 +2077,7 @@ async function runNpmInstall(cwd, pkg2) {
1710
2077
  const nodeDir = dirname6(process.execPath);
1711
2078
  const augmentedPath = process.env.PATH ? `${nodeDir}:${process.env.PATH}` : nodeDir;
1712
2079
  return new Promise((resolve5, reject) => {
1713
- const child = spawn6(npmCmd, ["install", "--no-audit", "--no-fund", "--silent", pkg2], {
2080
+ const child = spawn7(npmCmd, ["install", "--no-audit", "--no-fund", "--silent", pkg2], {
1714
2081
  cwd,
1715
2082
  stdio: ["ignore", "pipe", "pipe"],
1716
2083
  env: { ...process.env, PATH: augmentedPath }
@@ -1834,6 +2201,7 @@ async function prepareLspServersForRepos(repos, options = {}) {
1834
2201
  alreadyPresent: outcome.alreadyPresent,
1835
2202
  skippedNoNpmPackage: false,
1836
2203
  installMethod: "native",
2204
+ skipped: outcome.skipped,
1837
2205
  hint: outcome.skipped ? nativeConfig.installHint : void 0,
1838
2206
  error: outcome.error
1839
2207
  });
@@ -1848,6 +2216,7 @@ async function prepareLspServersForRepos(repos, options = {}) {
1848
2216
  alreadyPresent: outcome.alreadyPresent,
1849
2217
  skippedNoNpmPackage: false,
1850
2218
  installMethod: "coursier",
2219
+ skipped: outcome.skipped,
1851
2220
  hint: outcome.skipped ? coursierConfig.installHint : void 0,
1852
2221
  error: outcome.error
1853
2222
  });
@@ -1862,6 +2231,7 @@ async function prepareLspServersForRepos(repos, options = {}) {
1862
2231
  alreadyPresent: outcome.alreadyPresent,
1863
2232
  skippedNoNpmPackage: false,
1864
2233
  installMethod: "toolchain",
2234
+ skipped: outcome.skipped,
1865
2235
  // Surface the install hint for any skip reason — toolchain
1866
2236
  // missing means user needs to install it; bundled SDK means
1867
2237
  // user needs the SDK.
@@ -2530,14 +2900,17 @@ __export(telemetry_exports, {
2530
2900
  postLspInstallOutcomes: () => postLspInstallOutcomes
2531
2901
  });
2532
2902
  function toOutcomes(results) {
2533
- return results.map((r) => ({
2534
- language: r.language,
2535
- ...r.installMethod ? { installMethod: r.installMethod } : {},
2536
- installed: r.installed,
2537
- alreadyPresent: r.alreadyPresent,
2538
- ...r.skippedNoNpmPackage ? { skipped: "no-install-method" } : {},
2539
- ...r.error ? { error: r.error.slice(0, 500) } : {}
2540
- }));
2903
+ return results.map((r) => {
2904
+ const skipped = r.skipped ?? (r.skippedNoNpmPackage ? "no-install-method" : void 0);
2905
+ return {
2906
+ language: r.language,
2907
+ ...r.installMethod ? { installMethod: r.installMethod } : {},
2908
+ installed: r.installed,
2909
+ alreadyPresent: r.alreadyPresent,
2910
+ ...skipped ? { skipped } : {},
2911
+ ...r.error ? { error: r.error.slice(0, 500) } : {}
2912
+ };
2913
+ });
2541
2914
  }
2542
2915
  async function postLspInstallOutcomes(input) {
2543
2916
  if (process.env["REPOWISE_LSP_INSTALL_TELEMETRY_DISABLED"] === "true")
@@ -4193,7 +4566,7 @@ init_coursier_installer();
4193
4566
  init_toolchain_installer();
4194
4567
 
4195
4568
  // ../listener/dist/lsp/bloop-lifecycle.js
4196
- import { spawn as spawn7 } from "child_process";
4569
+ import { spawn as spawn8 } from "child_process";
4197
4570
  function createDefaultBloopLauncher() {
4198
4571
  const attachedRepos = /* @__PURE__ */ new Set();
4199
4572
  return {
@@ -4208,7 +4581,7 @@ function createDefaultBloopLauncher() {
4208
4581
  return new Promise((resolveClose) => {
4209
4582
  let child;
4210
4583
  try {
4211
- child = spawn7("bloop", ["exit"], { stdio: "ignore" });
4584
+ child = spawn8("bloop", ["exit"], { stdio: "ignore" });
4212
4585
  } catch {
4213
4586
  resolveClose();
4214
4587
  return;
@@ -7288,7 +7661,7 @@ init_installer();
7288
7661
  // ../listener/dist/lib/workspace-prep.js
7289
7662
  init_config_dir();
7290
7663
  import { promises as fs14 } from "fs";
7291
- import { spawn as spawn8, execFile as execFile4 } from "child_process";
7664
+ import { spawn as spawn9, execFile as execFile4 } from "child_process";
7292
7665
  import { createWriteStream as createWriteStream2 } from "fs";
7293
7666
  import { join as join30 } from "path";
7294
7667
  import { promisify as promisify3 } from "util";
@@ -7574,7 +7947,7 @@ $ ${cmd.join(" ")}
7574
7947
  reject(new Error("spawnSimple called with empty command"));
7575
7948
  return;
7576
7949
  }
7577
- const child = spawn8(head, cmd.slice(1), {
7950
+ const child = spawn9(head, cmd.slice(1), {
7578
7951
  cwd: repoRoot,
7579
7952
  stdio: ["ignore", "pipe", "pipe"]
7580
7953
  });
@@ -9813,7 +10186,7 @@ async function apiRequest(path, options) {
9813
10186
  if (body.error?.code) code = body.error.code;
9814
10187
  } catch {
9815
10188
  }
9816
- if (code === "BILLING_LIMIT_EXCEEDED" || code === "SYNC_LIMIT_EXCEEDED" || code === "BILLING_SUBSCRIPTION_INACTIVE") {
10189
+ if (code === "BILLING_LIMIT_EXCEEDED" || code === "SYNC_LIMIT_EXCEEDED" || code === "SEAT_LIMIT_EXCEEDED" || code === "BILLING_SUBSCRIPTION_INACTIVE") {
9817
10190
  throw new Error(`${message} Visit ${BILLING_URL} to manage your plan.`);
9818
10191
  }
9819
10192
  throw new Error(message);
@@ -10572,7 +10945,7 @@ async function detectMissingDeps(repoRoot, scopedLanguages) {
10572
10945
  }
10573
10946
 
10574
10947
  // src/lib/dep-installer-runner.ts
10575
- import { spawn as spawn9 } from "child_process";
10948
+ import { spawn as spawn10 } from "child_process";
10576
10949
  import { createWriteStream as createWriteStream3 } from "fs";
10577
10950
  import { promises as fs16 } from "fs";
10578
10951
  import { join as join38 } from "path";
@@ -10639,7 +11012,7 @@ $ ${cmd.join(" ")}
10639
11012
  reject(new Error("runSimple called with empty command"));
10640
11013
  return;
10641
11014
  }
10642
- const child = spawn9(head, cmd.slice(1), {
11015
+ const child = spawn10(head, cmd.slice(1), {
10643
11016
  cwd: repoRoot,
10644
11017
  stdio: ["ignore", "pipe", "pipe"]
10645
11018
  });
@@ -11073,16 +11446,30 @@ Files are stored on our servers (not in git). Retry when online.`
11073
11446
  }
11074
11447
  }
11075
11448
  const contextFolder = DEFAULT_CONTEXT_FOLDER;
11449
+ let graphOnly = false;
11450
+ try {
11451
+ const usage = await apiRequest("/v1/account/usage");
11452
+ graphOnly = usage.plan === "free";
11453
+ } catch {
11454
+ }
11076
11455
  let contextFiles = [];
11077
11456
  if (repoRoot) {
11078
11457
  contextFiles = await scanLocalContextFiles(repoRoot, contextFolder);
11079
11458
  }
11080
11459
  if (contextFiles.length === 0) {
11081
- console.log(
11082
- chalk7.yellow(
11083
- ` No context files found in ${contextFolder}/. Try re-running \`repowise create\`.`
11084
- )
11085
- );
11460
+ if (graphOnly) {
11461
+ console.log(
11462
+ chalk7.cyan(
11463
+ ` Knowledge graph + MCP ready (Free plan). Upgrade to Pro for AI-generated context docs.`
11464
+ )
11465
+ );
11466
+ } else {
11467
+ console.log(
11468
+ chalk7.yellow(
11469
+ ` No context files found in ${contextFolder}/. Try re-running \`repowise create\`.`
11470
+ )
11471
+ );
11472
+ }
11086
11473
  }
11087
11474
  if (repoRoot) {
11088
11475
  spinner.start("Configuring AI tools...");
@@ -11180,6 +11567,13 @@ Files are stored on our servers (not in git). Retry when online.`
11180
11567
  ` ${chalk7.green("\u2022")} The RepoWise MCP is Live \u2014 your AI tools can query the knowledge graph directly.`
11181
11568
  );
11182
11569
  }
11570
+ if (graphOnly) {
11571
+ console.log("");
11572
+ console.log(chalk7.cyan(" You\u2019re on the Free plan \u2014 knowledge graph + MCP only."));
11573
+ console.log(
11574
+ chalk7.dim(" Upgrade to Pro for AI-generated context docs and auto-sync on merge.")
11575
+ );
11576
+ }
11183
11577
  console.log("");
11184
11578
  console.log(chalk7.cyan(" Next steps"));
11185
11579
  console.log(
@@ -11238,6 +11632,21 @@ async function member() {
11238
11632
  } else {
11239
11633
  spinner.succeed("Authenticated");
11240
11634
  }
11635
+ try {
11636
+ const usage = await apiRequest("/v1/account/usage");
11637
+ if (usage.plan && usage.plan !== "team") {
11638
+ spinner.fail(
11639
+ chalk8.yellow(
11640
+ `'repowise member' is a Team-plan feature (your account is on the ${usage.plan} plan).`
11641
+ )
11642
+ );
11643
+ console.log(
11644
+ chalk8.dim(" The account owner sets up the repository with `repowise create`.")
11645
+ );
11646
+ return;
11647
+ }
11648
+ } catch {
11649
+ }
11241
11650
  let repoId;
11242
11651
  let repoName;
11243
11652
  let repoRoot;
@@ -13369,7 +13778,7 @@ init_registry();
13369
13778
  init_native_installer();
13370
13779
  init_coursier_installer();
13371
13780
  init_toolchain_installer();
13372
- import { spawn as spawn10 } from "child_process";
13781
+ import { spawn as spawn11 } from "child_process";
13373
13782
  import { resolve as resolve4 } from "path";
13374
13783
  import chalk15 from "chalk";
13375
13784
  async function isOnPath(command) {
@@ -13377,7 +13786,7 @@ async function isOnPath(command) {
13377
13786
  const isWin = process.platform === "win32";
13378
13787
  const probeCmd = isWin ? "where" : "which";
13379
13788
  return new Promise((resolve5) => {
13380
- const child = spawn10(probeCmd, [command], { stdio: "ignore" });
13789
+ const child = spawn11(probeCmd, [command], { stdio: "ignore" });
13381
13790
  child.on("close", (code) => {
13382
13791
  resolve5(code === 0);
13383
13792
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "repowisestage",
3
- "version": "0.0.51",
3
+ "version": "0.0.53",
4
4
  "type": "module",
5
5
  "description": "AI-optimized codebase context generator",
6
6
  "bin": {