@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 +67 -1
- package/index.ts +8 -0
- package/lib/info.ts +113 -0
- package/lib/list.ts +5 -1
- package/package.json +1 -1
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
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
|