@voidwire/lore 0.1.10 → 0.1.12

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/cli.ts CHANGED
@@ -26,6 +26,8 @@ import {
26
26
  listSources,
27
27
  list,
28
28
  listDomains,
29
+ info,
30
+ formatInfoHuman,
29
31
  captureTask,
30
32
  captureKnowledge,
31
33
  captureNote,
@@ -342,6 +344,39 @@ function handleList(args: string[]): void {
342
344
  }
343
345
  }
344
346
 
347
+ // ============================================================================
348
+ // Info Command
349
+ // ============================================================================
350
+
351
+ function handleInfo(args: string[]): void {
352
+ if (hasFlag(args, "help")) {
353
+ showInfoHelp();
354
+ }
355
+
356
+ const human = hasFlag(args, "human");
357
+
358
+ try {
359
+ const result = info();
360
+
361
+ if (human) {
362
+ console.log(formatInfoHuman(result));
363
+ } else {
364
+ output({
365
+ success: true,
366
+ ...result,
367
+ });
368
+ }
369
+
370
+ console.error(
371
+ `✅ ${result.sources.length} sources, ${result.total_entries} total entries`,
372
+ );
373
+ process.exit(0);
374
+ } catch (error) {
375
+ const message = error instanceof Error ? error.message : "Unknown error";
376
+ fail(message, 2);
377
+ }
378
+ }
379
+
345
380
  // ============================================================================
346
381
  // Capture Command
347
382
  // ============================================================================
@@ -512,6 +547,8 @@ Usage:
512
547
  lore search --sources List indexed sources
513
548
  lore list <domain> List domain entries
514
549
  lore list --domains List available domains
550
+ lore info Show indexed sources and counts
551
+ lore info --human Human-readable info
515
552
  lore capture task|knowledge|note|teaching Capture knowledge
516
553
 
517
554
  Search Options:
@@ -649,6 +686,32 @@ Examples:
649
686
  process.exit(0);
650
687
  }
651
688
 
689
+ function showInfoHelp(): void {
690
+ console.log(`
691
+ lore info - Show indexed sources and counts
692
+
693
+ Usage:
694
+ lore info Show all sources and counts
695
+ lore info --human Human-readable format
696
+
697
+ Options:
698
+ --human Human-readable format (default: JSON)
699
+ --help Show this help
700
+
701
+ Output Fields:
702
+ sources Array of {name, count} for each indexed source
703
+ projects Known projects (not yet implemented)
704
+ last_indexed Most recent timestamp from indexed data
705
+ total_entries Total number of indexed entries
706
+
707
+ Examples:
708
+ lore info
709
+ lore info | jq '.sources | length'
710
+ lore info --human
711
+ `);
712
+ process.exit(0);
713
+ }
714
+
652
715
  function showCaptureHelp(): void {
653
716
  console.log(`
654
717
  lore capture - Capture knowledge
@@ -724,11 +787,14 @@ function main(): void {
724
787
  case "list":
725
788
  handleList(commandArgs);
726
789
  break;
790
+ case "info":
791
+ handleInfo(commandArgs);
792
+ break;
727
793
  case "capture":
728
794
  handleCapture(commandArgs);
729
795
  break;
730
796
  default:
731
- fail(`Unknown command: ${command}. Use: search, list, or capture`);
797
+ fail(`Unknown command: ${command}. Use: search, list, info, or capture`);
732
798
  }
733
799
  }
734
800
 
package/index.ts CHANGED
@@ -27,6 +27,14 @@ export {
27
27
  type ListResult,
28
28
  } from "./lib/list";
29
29
 
30
+ // Info
31
+ export {
32
+ info,
33
+ formatInfoHuman,
34
+ type SourceInfo,
35
+ type InfoOutput,
36
+ } from "./lib/info";
37
+
30
38
  // Prismis integration
31
39
  export {
32
40
  searchPrismis,
package/lib/info.ts ADDED
@@ -0,0 +1,113 @@
1
+ /**
2
+ * lib/info.ts - Discovery command for indexed sources
3
+ *
4
+ * Shows what's indexed, counts per source, and last indexed timestamp.
5
+ * Uses Bun's built-in SQLite for zero external dependencies.
6
+ */
7
+
8
+ import { Database } from "bun:sqlite";
9
+ import { homedir } from "os";
10
+ import { existsSync } from "fs";
11
+
12
+ export interface SourceInfo {
13
+ name: string;
14
+ count: number;
15
+ }
16
+
17
+ export interface InfoOutput {
18
+ sources: SourceInfo[];
19
+ projects: string[];
20
+ last_indexed: string;
21
+ total_entries: number;
22
+ }
23
+
24
+ function getDatabasePath(): string {
25
+ return `${homedir()}/.local/share/lore/lore.db`;
26
+ }
27
+
28
+ /**
29
+ * Get info about indexed sources
30
+ *
31
+ * @returns InfoOutput with sources, counts, and metadata
32
+ * @throws Error if database doesn't exist
33
+ */
34
+ export function info(): InfoOutput {
35
+ const dbPath = getDatabasePath();
36
+
37
+ if (!existsSync(dbPath)) {
38
+ // Return empty info if database doesn't exist
39
+ return {
40
+ sources: [],
41
+ projects: [],
42
+ last_indexed: new Date().toISOString(),
43
+ total_entries: 0,
44
+ };
45
+ }
46
+
47
+ const db = new Database(dbPath, { readonly: true });
48
+
49
+ try {
50
+ // Get distinct sources with counts
51
+ const sourcesStmt = db.prepare(`
52
+ SELECT source as name, COUNT(*) as count
53
+ FROM search
54
+ GROUP BY source
55
+ ORDER BY count DESC
56
+ `);
57
+ const sources = sourcesStmt.all() as SourceInfo[];
58
+
59
+ // Get total entries
60
+ const totalStmt = db.prepare(`SELECT COUNT(*) as total FROM search`);
61
+ const totalResult = totalStmt.get() as { total: number };
62
+ const total_entries = totalResult?.total ?? 0;
63
+
64
+ // Get last indexed timestamp from metadata
65
+ const tsStmt = db.prepare(`
66
+ SELECT MAX(json_extract(metadata, '$.timestamp')) as ts
67
+ FROM search
68
+ WHERE json_extract(metadata, '$.timestamp') IS NOT NULL
69
+ `);
70
+ const tsResult = tsStmt.get() as { ts: string | null };
71
+ const last_indexed = tsResult?.ts ?? new Date().toISOString();
72
+
73
+ return {
74
+ sources,
75
+ projects: [], // TODO: implement in task 1.3
76
+ last_indexed,
77
+ total_entries,
78
+ };
79
+ } finally {
80
+ db.close();
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Format info output for human readability
86
+ */
87
+ export function formatInfoHuman(data: InfoOutput): string {
88
+ const lines: string[] = [
89
+ "Lore Knowledge Index",
90
+ "====================",
91
+ "",
92
+ `Total entries: ${data.total_entries.toLocaleString()}`,
93
+ `Last indexed: ${data.last_indexed}`,
94
+ "",
95
+ "Sources:",
96
+ ];
97
+
98
+ for (const source of data.sources) {
99
+ lines.push(
100
+ ` ${source.name.padEnd(15)} ${source.count.toLocaleString().padStart(8)} entries`,
101
+ );
102
+ }
103
+
104
+ if (data.projects.length > 0) {
105
+ lines.push("");
106
+ lines.push("Projects:");
107
+ for (const project of data.projects) {
108
+ lines.push(` ${project}`);
109
+ }
110
+ }
111
+
112
+ return lines.join("\n");
113
+ }
package/lib/list.ts CHANGED
@@ -25,7 +25,9 @@ export type Domain =
25
25
  | "podcasts"
26
26
  | "interests"
27
27
  | "people"
28
- | "habits";
28
+ | "habits"
29
+ | "teachings"
30
+ | "sessions";
29
31
 
30
32
  export const DOMAINS: Domain[] = [
31
33
  "development",
@@ -43,6 +45,8 @@ export const DOMAINS: Domain[] = [
43
45
  "interests",
44
46
  "people",
45
47
  "habits",
48
+ "teachings",
49
+ "sessions",
46
50
  ];
47
51
 
48
52
  // Domains that query the 'personal' source with type filter
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voidwire/lore",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "Unified knowledge CLI - Search, list, and capture your indexed knowledge",
5
5
  "type": "module",
6
6
  "main": "./index.ts",