@olorehq/olore 0.1.3 → 0.1.5

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/cli.js +165 -10
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // src/cli.ts
4
4
  import { createRequire } from "module";
5
5
  import { Command } from "commander";
6
- import pc9 from "picocolors";
6
+ import pc10 from "picocolors";
7
7
 
8
8
  // src/commands/doctor.ts
9
9
  import pc from "picocolors";
@@ -742,6 +742,22 @@ async function fetchWithTimeout(url, timeout = DOWNLOAD_TIMEOUT) {
742
742
  clearTimeout(timeoutId);
743
743
  }
744
744
  }
745
+ async function fetchPackageIndex() {
746
+ const url = `${REGISTRY_URL}/index.json`;
747
+ const response = await fetchWithTimeout(url);
748
+ if (response.status === 404) {
749
+ throw new RegistryError("Registry not found", "NOT_FOUND");
750
+ }
751
+ if (!response.ok) {
752
+ throw new RegistryError(`Failed to fetch registry: ${response.status}`, "NETWORK_ERROR");
753
+ }
754
+ try {
755
+ const data = await response.json();
756
+ return data;
757
+ } catch {
758
+ throw new RegistryError("Invalid registry response", "INVALID_RESPONSE");
759
+ }
760
+ }
745
761
  async function fetchPackageVersions(name) {
746
762
  const url = `${REGISTRY_URL}/packages/${name}.json`;
747
763
  const response = await fetchWithTimeout(url);
@@ -868,6 +884,31 @@ function parsePackageSpec(spec) {
868
884
  }
869
885
  return { name: spec };
870
886
  }
887
+ function levenshtein(a, b) {
888
+ const m = a.length;
889
+ const n = b.length;
890
+ const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
891
+ for (let i = 0; i <= m; i++) dp[i][0] = i;
892
+ for (let j = 0; j <= n; j++) dp[0][j] = j;
893
+ for (let i = 1; i <= m; i++) {
894
+ for (let j = 1; j <= n; j++) {
895
+ dp[i][j] = a[i - 1] === b[j - 1] ? dp[i - 1][j - 1] : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
896
+ }
897
+ }
898
+ return dp[m][n];
899
+ }
900
+ function findSimilarPackages(input, packages, maxResults = 3) {
901
+ const results = [];
902
+ for (const [name, entry] of Object.entries(packages)) {
903
+ const distance = levenshtein(input.toLowerCase(), name.toLowerCase());
904
+ const isSubstring = name.toLowerCase().includes(input.toLowerCase()) || input.toLowerCase().includes(name.toLowerCase());
905
+ if (distance <= 3 || isSubstring) {
906
+ results.push({ name, description: entry.description, distance });
907
+ }
908
+ }
909
+ results.sort((a, b) => a.distance - b.distance);
910
+ return results.slice(0, maxResults).map(({ name, description }) => ({ name, description }));
911
+ }
871
912
  async function installFromRemote(pkg, optionsVersion) {
872
913
  const { name, version: specVersion } = parsePackageSpec(pkg);
873
914
  const requestedVersion = optionsVersion || specVersion || "latest";
@@ -885,6 +926,20 @@ Installing ${name}@${requestedVersion} from registry...
885
926
  if (error.code === "NOT_FOUND") {
886
927
  console.log(pc3.yellow(`
887
928
  Package "${name}" not found in registry.`));
929
+ try {
930
+ const index = await fetchPackageIndex();
931
+ const similar = findSimilarPackages(name, index.packages);
932
+ if (similar.length > 0) {
933
+ console.log(pc3.bold("\nDid you mean?"));
934
+ for (const pkg2 of similar) {
935
+ console.log(` ${pc3.cyan(pkg2.name)} ${pc3.gray("-")} ${pc3.gray(pkg2.description)}`);
936
+ }
937
+ }
938
+ } catch {
939
+ }
940
+ console.log(
941
+ pc3.gray("\nRun ") + pc3.cyan("olore search") + pc3.gray(" to see all available packages.")
942
+ );
888
943
  console.log(pc3.gray("\nFor local packages, use a path:"));
889
944
  console.log(pc3.cyan(` olore install ./vault/packages/${name}/<version>`));
890
945
  console.log("");
@@ -1260,17 +1315,109 @@ Specify version: ${pc8.cyan(`olore remove ${name}@<version>`)}`);
1260
1315
  }
1261
1316
  }
1262
1317
 
1318
+ // src/commands/search.ts
1319
+ import ora5 from "ora";
1320
+ import pc9 from "picocolors";
1321
+ async function search(query, options) {
1322
+ const spinner = ora5("Fetching package registry...").start();
1323
+ let packages;
1324
+ try {
1325
+ const index = await fetchPackageIndex();
1326
+ packages = index.packages;
1327
+ spinner.stop();
1328
+ } catch (error) {
1329
+ spinner.fail("Failed to fetch registry");
1330
+ if (error instanceof RegistryError) {
1331
+ if (error.code === "NETWORK_ERROR" || error.code === "TIMEOUT") {
1332
+ console.log(pc9.red(`
1333
+ Network error: ${error.message}`));
1334
+ console.log(pc9.gray("Please check your internet connection and try again."));
1335
+ } else {
1336
+ console.log(pc9.red(`
1337
+ Error: ${error.message}`));
1338
+ }
1339
+ } else {
1340
+ console.log(pc9.red(`
1341
+ Error: ${error instanceof Error ? error.message : "Unknown error"}`));
1342
+ }
1343
+ process.exit(1);
1344
+ }
1345
+ let entries = Object.entries(packages);
1346
+ if (query) {
1347
+ const q = query.toLowerCase();
1348
+ entries = entries.filter(
1349
+ ([name, info]) => name.toLowerCase().includes(q) || info.description.toLowerCase().includes(q)
1350
+ );
1351
+ }
1352
+ if (entries.length === 0) {
1353
+ if (query) {
1354
+ console.log(pc9.yellow(`
1355
+ No packages matching '${query}'`));
1356
+ } else {
1357
+ console.log(pc9.yellow("\nNo packages available in the registry"));
1358
+ }
1359
+ return;
1360
+ }
1361
+ const installed = await getInstalledPackages();
1362
+ const installedNames = new Set(installed.map((p) => p.name));
1363
+ const installedVersions = /* @__PURE__ */ new Map();
1364
+ for (const pkg of installed) {
1365
+ installedVersions.set(pkg.name, pkg.version);
1366
+ }
1367
+ if (options.json) {
1368
+ const result = {
1369
+ packages: entries.map(([name, info]) => ({
1370
+ name,
1371
+ description: info.description,
1372
+ versions: info.versions,
1373
+ installed: installedNames.has(name),
1374
+ installedVersion: installedVersions.get(name) || null
1375
+ })),
1376
+ ...query ? { query } : {}
1377
+ };
1378
+ console.log(JSON.stringify(result, null, 2));
1379
+ return;
1380
+ }
1381
+ const colName = 20;
1382
+ const colDesc = 44;
1383
+ const colVersions = 12;
1384
+ console.log(pc9.bold("\nAvailable packages:\n"));
1385
+ console.log(
1386
+ pc9.gray(
1387
+ "PACKAGE".padEnd(colName) + "DESCRIPTION".padEnd(colDesc) + "VERSIONS".padEnd(colVersions) + "INSTALLED"
1388
+ )
1389
+ );
1390
+ console.log(pc9.gray("\u2500".repeat(colName + colDesc + colVersions + 12)));
1391
+ for (const [name, info] of entries.sort(([a], [b]) => a.localeCompare(b))) {
1392
+ const desc = truncate(info.description, colDesc - 2);
1393
+ const versions = info.versions.join(", ");
1394
+ const installedVersion = installedVersions.get(name);
1395
+ const status = installedVersion ? pc9.green(`\u2713 ${installedVersion}`) : "";
1396
+ console.log(
1397
+ name.padEnd(colName) + desc.padEnd(colDesc) + versions.padEnd(colVersions) + status
1398
+ );
1399
+ }
1400
+ console.log(pc9.gray("\u2500".repeat(colName + colDesc + colVersions + 12)));
1401
+ console.log(pc9.gray(`${entries.length} package${entries.length === 1 ? "" : "s"} available`));
1402
+ console.log(`
1403
+ Install with: ${pc9.cyan("olore install <package>")}`);
1404
+ }
1405
+ function truncate(str, maxLen) {
1406
+ if (str.length <= maxLen) return str;
1407
+ return str.slice(0, maxLen - 1) + "\u2026";
1408
+ }
1409
+
1263
1410
  // src/cli.ts
1264
1411
  var require2 = createRequire(import.meta.url);
1265
1412
  var { version } = require2("../package.json");
1266
1413
  var program = new Command();
1267
1414
  program.name("olore").description("Universal documentation for any AI coding agent").version(version).addHelpText("after", `
1268
- ${pc9.gray("May the Skill be with you.")}`);
1415
+ ${pc10.gray("May the Skill be with you.")}`);
1269
1416
  program.command("init").description("Initialize a documentation package in the current directory").option("-n, --name <name>", "Package name (default: folder name)").option("-v, --version <version>", "Package version (default: latest)").option("-y, --yes", "Skip prompts, use defaults").action(async (options) => {
1270
1417
  try {
1271
1418
  await init(options);
1272
1419
  } catch (error) {
1273
- console.error(pc9.red(`Error: ${error.message}`));
1420
+ console.error(pc10.red(`Error: ${error.message}`));
1274
1421
  process.exit(1);
1275
1422
  }
1276
1423
  });
@@ -1278,7 +1425,7 @@ program.command("install <package>").alias("i").description("Install a documenta
1278
1425
  try {
1279
1426
  await install(pkg, options);
1280
1427
  } catch (error) {
1281
- console.error(pc9.red(`Error: ${error.message}`));
1428
+ console.error(pc10.red(`Error: ${error.message}`));
1282
1429
  process.exit(1);
1283
1430
  }
1284
1431
  });
@@ -1286,7 +1433,7 @@ program.command("link <path>").description("Link a local package for development
1286
1433
  try {
1287
1434
  await link(localPath);
1288
1435
  } catch (error) {
1289
- console.error(pc9.red(`Error: ${error.message}`));
1436
+ console.error(pc10.red(`Error: ${error.message}`));
1290
1437
  process.exit(1);
1291
1438
  }
1292
1439
  });
@@ -1294,7 +1441,15 @@ program.command("list").alias("ls").description("List installed documentation pa
1294
1441
  try {
1295
1442
  await list(options);
1296
1443
  } catch (error) {
1297
- console.error(pc9.red(`Error: ${error.message}`));
1444
+ console.error(pc10.red(`Error: ${error.message}`));
1445
+ process.exit(1);
1446
+ }
1447
+ });
1448
+ program.command("search [query]").description("Search available packages in the registry").option("--json", "Output as JSON").action(async (query, options) => {
1449
+ try {
1450
+ await search(query, options);
1451
+ } catch (error) {
1452
+ console.error(pc10.red(`Error: ${error.message}`));
1298
1453
  process.exit(1);
1299
1454
  }
1300
1455
  });
@@ -1302,7 +1457,7 @@ program.command("remove <package>").alias("rm").description("Remove an installed
1302
1457
  try {
1303
1458
  await remove(pkg);
1304
1459
  } catch (error) {
1305
- console.error(pc9.red(`Error: ${error.message}`));
1460
+ console.error(pc10.red(`Error: ${error.message}`));
1306
1461
  process.exit(1);
1307
1462
  }
1308
1463
  });
@@ -1310,7 +1465,7 @@ program.command("doctor").description("Check for issues with installed packages"
1310
1465
  try {
1311
1466
  await doctor(options);
1312
1467
  } catch (error) {
1313
- console.error(pc9.red(`Error: ${error.message}`));
1468
+ console.error(pc10.red(`Error: ${error.message}`));
1314
1469
  process.exit(1);
1315
1470
  }
1316
1471
  });
@@ -1318,7 +1473,7 @@ program.command("prune").description("Remove dangling symlinks, orphaned package
1318
1473
  try {
1319
1474
  await prune(options);
1320
1475
  } catch (error) {
1321
- console.error(pc9.red(`Error: ${error.message}`));
1476
+ console.error(pc10.red(`Error: ${error.message}`));
1322
1477
  process.exit(1);
1323
1478
  }
1324
1479
  });
@@ -1326,7 +1481,7 @@ program.command("order66").description(false).action(async () => {
1326
1481
  try {
1327
1482
  await order66();
1328
1483
  } catch (error) {
1329
- console.error(pc9.red(`Error: ${error.message}`));
1484
+ console.error(pc10.red(`Error: ${error.message}`));
1330
1485
  process.exit(1);
1331
1486
  }
1332
1487
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olorehq/olore",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Universal documentation for any AI coding agent",
5
5
  "keywords": [
6
6
  "ai",