bluera-knowledge 0.9.43 → 0.10.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.
Files changed (43) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +75 -0
  3. package/README.md +114 -42
  4. package/commands/sync.md +96 -0
  5. package/dist/{chunk-MQE32YY6.js → chunk-6U45VP5Z.js} +42 -6
  6. package/dist/chunk-6U45VP5Z.js.map +1 -0
  7. package/dist/{chunk-CUHYSPRV.js → chunk-DP5XBPQV.js} +372 -2
  8. package/dist/chunk-DP5XBPQV.js.map +1 -0
  9. package/dist/{chunk-DWAIT2OD.js → chunk-UE4ZIJYA.js} +74 -5
  10. package/dist/{chunk-DWAIT2OD.js.map → chunk-UE4ZIJYA.js.map} +1 -1
  11. package/dist/index.js +216 -7
  12. package/dist/index.js.map +1 -1
  13. package/dist/mcp/server.js +2 -2
  14. package/dist/workers/background-worker-cli.js +4 -3
  15. package/dist/workers/background-worker-cli.js.map +1 -1
  16. package/hooks/check-dependencies.sh +29 -0
  17. package/package.json +1 -1
  18. package/python/crawl_worker.py +6 -1
  19. package/src/cli/commands/crawl.test.ts +43 -3
  20. package/src/cli/commands/crawl.ts +3 -3
  21. package/src/cli/commands/sync.test.ts +54 -0
  22. package/src/cli/commands/sync.ts +264 -0
  23. package/src/cli/index.ts +1 -0
  24. package/src/crawl/claude-client.test.ts +195 -24
  25. package/src/crawl/claude-client.ts +38 -3
  26. package/src/crawl/intelligent-crawler.test.ts +65 -0
  27. package/src/crawl/intelligent-crawler.ts +14 -2
  28. package/src/index.ts +2 -0
  29. package/src/mcp/commands/index.ts +2 -0
  30. package/src/mcp/commands/sync.commands.test.ts +283 -0
  31. package/src/mcp/commands/sync.commands.ts +233 -0
  32. package/src/services/gitignore.service.test.ts +157 -0
  33. package/src/services/gitignore.service.ts +132 -0
  34. package/src/services/store-definition.service.test.ts +440 -0
  35. package/src/services/store-definition.service.ts +198 -0
  36. package/src/services/store.service.test.ts +279 -1
  37. package/src/services/store.service.ts +101 -4
  38. package/src/types/index.ts +18 -0
  39. package/src/types/store-definition.test.ts +492 -0
  40. package/src/types/store-definition.ts +129 -0
  41. package/src/workers/background-worker.ts +1 -1
  42. package/dist/chunk-CUHYSPRV.js.map +0 -1
  43. package/dist/chunk-MQE32YY6.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,10 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ StoreDefinitionService,
4
+ isFileStoreDefinition,
5
+ isRepoStoreDefinition,
6
+ isWebStoreDefinition,
3
7
  runMCPServer
4
- } from "./chunk-CUHYSPRV.js";
8
+ } from "./chunk-DP5XBPQV.js";
5
9
  import {
6
10
  IntelligentCrawler
7
- } from "./chunk-MQE32YY6.js";
11
+ } from "./chunk-6U45VP5Z.js";
8
12
  import {
9
13
  ASTParser,
10
14
  ChunkingService,
@@ -16,7 +20,7 @@ import {
16
20
  err,
17
21
  extractRepoName,
18
22
  ok
19
- } from "./chunk-DWAIT2OD.js";
23
+ } from "./chunk-UE4ZIJYA.js";
20
24
  import "./chunk-6FHWC36B.js";
21
25
 
22
26
  // src/index.ts
@@ -34,7 +38,7 @@ function createCrawlCommand(getOptions) {
34
38
  ).option(
35
39
  "--extract <instruction>",
36
40
  'Natural language instruction for what to extract (e.g., "extract API references")'
37
- ).option("--simple", "Use simple BFS mode instead of intelligent crawling").option("--max-pages <number>", "Maximum number of pages to crawl", "50").option("--headless", "Use headless browser for JavaScript-rendered sites").action(
41
+ ).option("--simple", "Use simple BFS mode instead of intelligent crawling").option("--max-pages <number>", "Maximum number of pages to crawl", "50").option("--fast", "Use fast axios-only mode (may fail on JavaScript-heavy sites)").action(
38
42
  async (url, storeIdOrName, cmdOptions) => {
39
43
  const globalOpts = getOptions();
40
44
  const services = await createServices(globalOpts.config, globalOpts.dataDir);
@@ -105,7 +109,8 @@ function createCrawlCommand(getOptions) {
105
109
  ...cmdOptions.extract !== void 0 && { extractInstruction: cmdOptions.extract },
106
110
  maxPages,
107
111
  ...cmdOptions.simple !== void 0 && { simple: cmdOptions.simple },
108
- useHeadless: cmdOptions.headless ?? false
112
+ useHeadless: !(cmdOptions.fast ?? false)
113
+ // Default true (headless), --fast disables
109
114
  })) {
110
115
  const contentToProcess = result.extracted ?? result.markdown;
111
116
  const chunks = webChunker.chunk(contentToProcess, `${result.url}.md`);
@@ -1530,11 +1535,214 @@ Store: ${s.name}`);
1530
1535
  return store;
1531
1536
  }
1532
1537
 
1538
+ // src/cli/commands/sync.ts
1539
+ import { Command as Command9 } from "commander";
1540
+ async function createStoreFromDefinition(def, defService, storeService) {
1541
+ try {
1542
+ if (isFileStoreDefinition(def)) {
1543
+ const resolvedPath = defService.resolvePath(def.path);
1544
+ const createResult = await storeService.create(
1545
+ {
1546
+ name: def.name,
1547
+ type: "file",
1548
+ path: resolvedPath,
1549
+ description: def.description,
1550
+ tags: def.tags
1551
+ },
1552
+ { skipDefinitionSync: true }
1553
+ );
1554
+ if (!createResult.success) {
1555
+ return { success: false, error: createResult.error.message };
1556
+ }
1557
+ return { success: true };
1558
+ }
1559
+ if (isRepoStoreDefinition(def)) {
1560
+ const createResult = await storeService.create(
1561
+ {
1562
+ name: def.name,
1563
+ type: "repo",
1564
+ url: def.url,
1565
+ branch: def.branch,
1566
+ depth: def.depth,
1567
+ description: def.description,
1568
+ tags: def.tags
1569
+ },
1570
+ { skipDefinitionSync: true }
1571
+ );
1572
+ if (!createResult.success) {
1573
+ return { success: false, error: createResult.error.message };
1574
+ }
1575
+ return { success: true };
1576
+ }
1577
+ if (isWebStoreDefinition(def)) {
1578
+ const createResult = await storeService.create(
1579
+ {
1580
+ name: def.name,
1581
+ type: "web",
1582
+ url: def.url,
1583
+ depth: def.depth,
1584
+ description: def.description,
1585
+ tags: def.tags
1586
+ },
1587
+ { skipDefinitionSync: true }
1588
+ );
1589
+ if (!createResult.success) {
1590
+ return { success: false, error: createResult.error.message };
1591
+ }
1592
+ return { success: true };
1593
+ }
1594
+ return { success: false, error: "Unknown store definition type" };
1595
+ } catch (error) {
1596
+ return {
1597
+ success: false,
1598
+ error: error instanceof Error ? error.message : String(error)
1599
+ };
1600
+ }
1601
+ }
1602
+ function createSyncCommand(getOptions) {
1603
+ const sync = new Command9("sync").description(
1604
+ "Sync stores from definitions config (bootstrap on fresh clone)"
1605
+ );
1606
+ sync.option("--dry-run", "Show what would happen without making changes").option("--prune", "Remove stores not in definitions").option("--reindex", "Re-index existing stores after sync").action(async (options) => {
1607
+ const globalOpts = getOptions();
1608
+ const projectRoot = globalOpts.projectRoot ?? process.cwd();
1609
+ const defService = new StoreDefinitionService(projectRoot);
1610
+ const services = await createServices(globalOpts.config, globalOpts.dataDir, projectRoot);
1611
+ try {
1612
+ const config = await defService.load();
1613
+ const existingStores = await services.store.list();
1614
+ const existingNames = new Set(existingStores.map((s) => s.name));
1615
+ const definedNames = new Set(config.stores.map((d) => d.name));
1616
+ const result = {
1617
+ created: [],
1618
+ skipped: [],
1619
+ failed: [],
1620
+ orphans: [],
1621
+ pruned: [],
1622
+ dryRun: options.dryRun === true,
1623
+ wouldCreate: [],
1624
+ wouldPrune: []
1625
+ };
1626
+ for (const def of config.stores) {
1627
+ if (existingNames.has(def.name)) {
1628
+ result.skipped.push(def.name);
1629
+ continue;
1630
+ }
1631
+ if (options.dryRun === true) {
1632
+ result.wouldCreate.push(def.name);
1633
+ continue;
1634
+ }
1635
+ const createResult = await createStoreFromDefinition(def, defService, services.store);
1636
+ if (createResult.success) {
1637
+ result.created.push(def.name);
1638
+ } else {
1639
+ result.failed.push({ name: def.name, error: createResult.error });
1640
+ }
1641
+ }
1642
+ for (const store of existingStores) {
1643
+ if (!definedNames.has(store.name)) {
1644
+ result.orphans.push(store.name);
1645
+ }
1646
+ }
1647
+ if (options.prune === true && result.orphans.length > 0) {
1648
+ if (options.dryRun === true) {
1649
+ result.wouldPrune = [...result.orphans];
1650
+ } else {
1651
+ for (const orphanName of result.orphans) {
1652
+ const store = await services.store.getByName(orphanName);
1653
+ if (store !== void 0) {
1654
+ const deleteResult = await services.store.delete(store.id, {
1655
+ skipDefinitionSync: true
1656
+ });
1657
+ if (deleteResult.success) {
1658
+ result.pruned.push(orphanName);
1659
+ }
1660
+ }
1661
+ }
1662
+ }
1663
+ }
1664
+ if (globalOpts.format === "json") {
1665
+ console.log(JSON.stringify(result, null, 2));
1666
+ } else {
1667
+ printHumanReadable(result, globalOpts.quiet === true);
1668
+ }
1669
+ } finally {
1670
+ await destroyServices(services);
1671
+ }
1672
+ });
1673
+ return sync;
1674
+ }
1675
+ function printHumanReadable(result, quiet) {
1676
+ if (quiet) {
1677
+ for (const name of result.created) {
1678
+ console.log(`created: ${name}`);
1679
+ }
1680
+ for (const name of result.pruned) {
1681
+ console.log(`pruned: ${name}`);
1682
+ }
1683
+ for (const name of result.wouldCreate) {
1684
+ console.log(`would create: ${name}`);
1685
+ }
1686
+ for (const name of result.wouldPrune) {
1687
+ console.log(`would prune: ${name}`);
1688
+ }
1689
+ return;
1690
+ }
1691
+ if (result.dryRun) {
1692
+ console.log("\n[DRY RUN] No changes made.\n");
1693
+ } else {
1694
+ console.log("\nSync completed.\n");
1695
+ }
1696
+ if (result.created.length > 0) {
1697
+ console.log(`Created (${String(result.created.length)}):`);
1698
+ for (const name of result.created) {
1699
+ console.log(` + ${name}`);
1700
+ }
1701
+ }
1702
+ if (result.wouldCreate.length > 0) {
1703
+ console.log(`Would create (${String(result.wouldCreate.length)}):`);
1704
+ for (const name of result.wouldCreate) {
1705
+ console.log(` + ${name}`);
1706
+ }
1707
+ }
1708
+ if (result.skipped.length > 0) {
1709
+ console.log(`Skipped (already exist) (${String(result.skipped.length)}):`);
1710
+ for (const name of result.skipped) {
1711
+ console.log(` - ${name}`);
1712
+ }
1713
+ }
1714
+ if (result.failed.length > 0) {
1715
+ console.log(`Failed (${String(result.failed.length)}):`);
1716
+ for (const { name, error } of result.failed) {
1717
+ console.log(` ! ${name}: ${error}`);
1718
+ }
1719
+ }
1720
+ if (result.orphans.length > 0) {
1721
+ console.log(`Orphans (not in definitions) (${String(result.orphans.length)}):`);
1722
+ for (const name of result.orphans) {
1723
+ console.log(` ? ${name}`);
1724
+ }
1725
+ }
1726
+ if (result.pruned.length > 0) {
1727
+ console.log(`Pruned (${String(result.pruned.length)}):`);
1728
+ for (const name of result.pruned) {
1729
+ console.log(` x ${name}`);
1730
+ }
1731
+ }
1732
+ if (result.wouldPrune.length > 0) {
1733
+ console.log(`Would prune (${String(result.wouldPrune.length)}):`);
1734
+ for (const name of result.wouldPrune) {
1735
+ console.log(` x ${name}`);
1736
+ }
1737
+ }
1738
+ console.log("");
1739
+ }
1740
+
1533
1741
  // src/cli/program.ts
1534
1742
  import { readFileSync } from "fs";
1535
1743
  import { dirname, join as join3 } from "path";
1536
1744
  import { fileURLToPath } from "url";
1537
- import { Command as Command9 } from "commander";
1745
+ import { Command as Command10 } from "commander";
1538
1746
  function getVersion() {
1539
1747
  const __filename2 = fileURLToPath(import.meta.url);
1540
1748
  const __dirname2 = dirname(__filename2);
@@ -1544,7 +1752,7 @@ function getVersion() {
1544
1752
  }
1545
1753
  var version = getVersion();
1546
1754
  function createProgram() {
1547
- const program2 = new Command9();
1755
+ const program2 = new Command10();
1548
1756
  program2.name("bluera-knowledge").description("CLI tool for managing knowledge stores with semantic search").version(version);
1549
1757
  program2.option("-c, --config <path>", "Path to config file").option("-d, --data-dir <path>", "Data directory").option("-p, --project-root <path>", "Project root directory (for resolving relative paths)").option("-f, --format <format>", "Output format: json | table | plain", "table").option("-q, --quiet", "Suppress non-essential output").option("-v, --verbose", "Enable verbose logging");
1550
1758
  return program2;
@@ -1619,6 +1827,7 @@ program.addCommand(createIndexCommand(() => getGlobalOptions(program)));
1619
1827
  program.addCommand(createServeCommand(() => getGlobalOptions(program)));
1620
1828
  program.addCommand(createCrawlCommand(() => getGlobalOptions(program)));
1621
1829
  program.addCommand(createSetupCommand(() => getGlobalOptions(program)));
1830
+ program.addCommand(createSyncCommand(() => getGlobalOptions(program)));
1622
1831
  program.addCommand(createMCPCommand(() => getGlobalOptions(program)));
1623
1832
  if (process.argv.length <= 2) {
1624
1833
  printFullHelp(program);