@voidwire/lore 0.1.11 → 0.1.13
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 +127 -1
- package/index.ts +11 -0
- package/lib/info.ts +114 -0
- package/lib/projects.ts +60 -0
- package/package.json +1 -1
package/cli.ts
CHANGED
|
@@ -26,6 +26,9 @@ import {
|
|
|
26
26
|
listSources,
|
|
27
27
|
list,
|
|
28
28
|
listDomains,
|
|
29
|
+
info,
|
|
30
|
+
formatInfoHuman,
|
|
31
|
+
projects,
|
|
29
32
|
captureTask,
|
|
30
33
|
captureKnowledge,
|
|
31
34
|
captureNote,
|
|
@@ -342,6 +345,64 @@ function handleList(args: string[]): void {
|
|
|
342
345
|
}
|
|
343
346
|
}
|
|
344
347
|
|
|
348
|
+
// ============================================================================
|
|
349
|
+
// Info Command
|
|
350
|
+
// ============================================================================
|
|
351
|
+
|
|
352
|
+
function handleInfo(args: string[]): void {
|
|
353
|
+
if (hasFlag(args, "help")) {
|
|
354
|
+
showInfoHelp();
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const human = hasFlag(args, "human");
|
|
358
|
+
|
|
359
|
+
try {
|
|
360
|
+
const result = info();
|
|
361
|
+
|
|
362
|
+
if (human) {
|
|
363
|
+
console.log(formatInfoHuman(result));
|
|
364
|
+
} else {
|
|
365
|
+
output({
|
|
366
|
+
success: true,
|
|
367
|
+
...result,
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
console.error(
|
|
372
|
+
`✅ ${result.sources.length} sources, ${result.total_entries} total entries`,
|
|
373
|
+
);
|
|
374
|
+
process.exit(0);
|
|
375
|
+
} catch (error) {
|
|
376
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
377
|
+
fail(message, 2);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// ============================================================================
|
|
382
|
+
// Projects Command
|
|
383
|
+
// ============================================================================
|
|
384
|
+
|
|
385
|
+
function handleProjects(args: string[]): void {
|
|
386
|
+
if (hasFlag(args, "help")) {
|
|
387
|
+
showProjectsHelp();
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
try {
|
|
391
|
+
const result = projects();
|
|
392
|
+
|
|
393
|
+
output({
|
|
394
|
+
success: true,
|
|
395
|
+
projects: result,
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
console.error(`✅ ${result.length} projects found`);
|
|
399
|
+
process.exit(0);
|
|
400
|
+
} catch (error) {
|
|
401
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
402
|
+
fail(message, 2);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
345
406
|
// ============================================================================
|
|
346
407
|
// Capture Command
|
|
347
408
|
// ============================================================================
|
|
@@ -512,6 +573,8 @@ Usage:
|
|
|
512
573
|
lore search --sources List indexed sources
|
|
513
574
|
lore list <domain> List domain entries
|
|
514
575
|
lore list --domains List available domains
|
|
576
|
+
lore info Show indexed sources and counts
|
|
577
|
+
lore info --human Human-readable info
|
|
515
578
|
lore capture task|knowledge|note|teaching Capture knowledge
|
|
516
579
|
|
|
517
580
|
Search Options:
|
|
@@ -649,6 +712,61 @@ Examples:
|
|
|
649
712
|
process.exit(0);
|
|
650
713
|
}
|
|
651
714
|
|
|
715
|
+
function showInfoHelp(): void {
|
|
716
|
+
console.log(`
|
|
717
|
+
lore info - Show indexed sources and counts
|
|
718
|
+
|
|
719
|
+
Usage:
|
|
720
|
+
lore info Show all sources and counts
|
|
721
|
+
lore info --human Human-readable format
|
|
722
|
+
|
|
723
|
+
Options:
|
|
724
|
+
--human Human-readable format (default: JSON)
|
|
725
|
+
--help Show this help
|
|
726
|
+
|
|
727
|
+
Output Fields:
|
|
728
|
+
sources Array of {name, count} for each indexed source
|
|
729
|
+
projects Known projects across all sources
|
|
730
|
+
last_indexed Most recent timestamp from indexed data
|
|
731
|
+
total_entries Total number of indexed entries
|
|
732
|
+
|
|
733
|
+
Examples:
|
|
734
|
+
lore info
|
|
735
|
+
lore info | jq '.sources | length'
|
|
736
|
+
lore info --human
|
|
737
|
+
`);
|
|
738
|
+
process.exit(0);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
function showProjectsHelp(): void {
|
|
742
|
+
console.log(`
|
|
743
|
+
lore projects - List all known projects
|
|
744
|
+
|
|
745
|
+
Usage:
|
|
746
|
+
lore projects List all unique project names
|
|
747
|
+
|
|
748
|
+
Options:
|
|
749
|
+
--help Show this help
|
|
750
|
+
|
|
751
|
+
Output:
|
|
752
|
+
JSON array of project names, sorted alphabetically.
|
|
753
|
+
Projects are extracted from metadata fields across all sources.
|
|
754
|
+
|
|
755
|
+
Sources checked:
|
|
756
|
+
commits project field
|
|
757
|
+
sessions project field
|
|
758
|
+
tasks project field
|
|
759
|
+
captures context field
|
|
760
|
+
teachings source field
|
|
761
|
+
|
|
762
|
+
Examples:
|
|
763
|
+
lore projects
|
|
764
|
+
lore projects | jq -r '.projects[]'
|
|
765
|
+
lore projects | jq '.projects | length'
|
|
766
|
+
`);
|
|
767
|
+
process.exit(0);
|
|
768
|
+
}
|
|
769
|
+
|
|
652
770
|
function showCaptureHelp(): void {
|
|
653
771
|
console.log(`
|
|
654
772
|
lore capture - Capture knowledge
|
|
@@ -724,11 +842,19 @@ function main(): void {
|
|
|
724
842
|
case "list":
|
|
725
843
|
handleList(commandArgs);
|
|
726
844
|
break;
|
|
845
|
+
case "info":
|
|
846
|
+
handleInfo(commandArgs);
|
|
847
|
+
break;
|
|
848
|
+
case "projects":
|
|
849
|
+
handleProjects(commandArgs);
|
|
850
|
+
break;
|
|
727
851
|
case "capture":
|
|
728
852
|
handleCapture(commandArgs);
|
|
729
853
|
break;
|
|
730
854
|
default:
|
|
731
|
-
fail(
|
|
855
|
+
fail(
|
|
856
|
+
`Unknown command: ${command}. Use: search, list, info, projects, or capture`,
|
|
857
|
+
);
|
|
732
858
|
}
|
|
733
859
|
}
|
|
734
860
|
|
package/index.ts
CHANGED
|
@@ -27,6 +27,17 @@ 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
|
+
|
|
38
|
+
// Projects
|
|
39
|
+
export { projects } from "./lib/projects";
|
|
40
|
+
|
|
30
41
|
// Prismis integration
|
|
31
42
|
export {
|
|
32
43
|
searchPrismis,
|
package/lib/info.ts
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
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
|
+
import { projects as getProjects } from "./projects.js";
|
|
12
|
+
|
|
13
|
+
export interface SourceInfo {
|
|
14
|
+
name: string;
|
|
15
|
+
count: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface InfoOutput {
|
|
19
|
+
sources: SourceInfo[];
|
|
20
|
+
projects: string[];
|
|
21
|
+
last_indexed: string;
|
|
22
|
+
total_entries: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function getDatabasePath(): string {
|
|
26
|
+
return `${homedir()}/.local/share/lore/lore.db`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get info about indexed sources
|
|
31
|
+
*
|
|
32
|
+
* @returns InfoOutput with sources, counts, and metadata
|
|
33
|
+
* @throws Error if database doesn't exist
|
|
34
|
+
*/
|
|
35
|
+
export function info(): InfoOutput {
|
|
36
|
+
const dbPath = getDatabasePath();
|
|
37
|
+
|
|
38
|
+
if (!existsSync(dbPath)) {
|
|
39
|
+
// Return empty info if database doesn't exist
|
|
40
|
+
return {
|
|
41
|
+
sources: [],
|
|
42
|
+
projects: [],
|
|
43
|
+
last_indexed: new Date().toISOString(),
|
|
44
|
+
total_entries: 0,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const db = new Database(dbPath, { readonly: true });
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
// Get distinct sources with counts
|
|
52
|
+
const sourcesStmt = db.prepare(`
|
|
53
|
+
SELECT source as name, COUNT(*) as count
|
|
54
|
+
FROM search
|
|
55
|
+
GROUP BY source
|
|
56
|
+
ORDER BY count DESC
|
|
57
|
+
`);
|
|
58
|
+
const sources = sourcesStmt.all() as SourceInfo[];
|
|
59
|
+
|
|
60
|
+
// Get total entries
|
|
61
|
+
const totalStmt = db.prepare(`SELECT COUNT(*) as total FROM search`);
|
|
62
|
+
const totalResult = totalStmt.get() as { total: number };
|
|
63
|
+
const total_entries = totalResult?.total ?? 0;
|
|
64
|
+
|
|
65
|
+
// Get last indexed timestamp from metadata
|
|
66
|
+
const tsStmt = db.prepare(`
|
|
67
|
+
SELECT MAX(json_extract(metadata, '$.timestamp')) as ts
|
|
68
|
+
FROM search
|
|
69
|
+
WHERE json_extract(metadata, '$.timestamp') IS NOT NULL
|
|
70
|
+
`);
|
|
71
|
+
const tsResult = tsStmt.get() as { ts: string | null };
|
|
72
|
+
const last_indexed = tsResult?.ts ?? new Date().toISOString();
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
sources,
|
|
76
|
+
projects: getProjects(),
|
|
77
|
+
last_indexed,
|
|
78
|
+
total_entries,
|
|
79
|
+
};
|
|
80
|
+
} finally {
|
|
81
|
+
db.close();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Format info output for human readability
|
|
87
|
+
*/
|
|
88
|
+
export function formatInfoHuman(data: InfoOutput): string {
|
|
89
|
+
const lines: string[] = [
|
|
90
|
+
"Lore Knowledge Index",
|
|
91
|
+
"====================",
|
|
92
|
+
"",
|
|
93
|
+
`Total entries: ${data.total_entries.toLocaleString()}`,
|
|
94
|
+
`Last indexed: ${data.last_indexed}`,
|
|
95
|
+
"",
|
|
96
|
+
"Sources:",
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
for (const source of data.sources) {
|
|
100
|
+
lines.push(
|
|
101
|
+
` ${source.name.padEnd(15)} ${source.count.toLocaleString().padStart(8)} entries`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (data.projects.length > 0) {
|
|
106
|
+
lines.push("");
|
|
107
|
+
lines.push("Projects:");
|
|
108
|
+
for (const project of data.projects) {
|
|
109
|
+
lines.push(` ${project}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return lines.join("\n");
|
|
114
|
+
}
|
package/lib/projects.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/projects.ts - List all known projects across sources
|
|
3
|
+
*
|
|
4
|
+
* Queries distinct project values from metadata fields, handling
|
|
5
|
+
* different field names per source type.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Database } from "bun:sqlite";
|
|
9
|
+
import { homedir } from "os";
|
|
10
|
+
import { existsSync } from "fs";
|
|
11
|
+
|
|
12
|
+
const PROJECT_FIELD: Record<string, string> = {
|
|
13
|
+
commits: "project",
|
|
14
|
+
sessions: "project",
|
|
15
|
+
tasks: "project",
|
|
16
|
+
captures: "context",
|
|
17
|
+
teachings: "source",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
function getDatabasePath(): string {
|
|
21
|
+
return `${homedir()}/.local/share/lore/lore.db`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get all unique project names across sources
|
|
26
|
+
*
|
|
27
|
+
* @returns Sorted array of unique project names
|
|
28
|
+
*/
|
|
29
|
+
export function projects(): string[] {
|
|
30
|
+
const dbPath = getDatabasePath();
|
|
31
|
+
|
|
32
|
+
if (!existsSync(dbPath)) {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const db = new Database(dbPath, { readonly: true });
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const allProjects = new Set<string>();
|
|
40
|
+
|
|
41
|
+
for (const [source, field] of Object.entries(PROJECT_FIELD)) {
|
|
42
|
+
const stmt = db.prepare(`
|
|
43
|
+
SELECT DISTINCT json_extract(metadata, '$.${field}') as proj
|
|
44
|
+
FROM search
|
|
45
|
+
WHERE source = ? AND json_extract(metadata, '$.${field}') IS NOT NULL
|
|
46
|
+
`);
|
|
47
|
+
const results = stmt.all(source) as { proj: string | null }[];
|
|
48
|
+
|
|
49
|
+
for (const r of results) {
|
|
50
|
+
if (r.proj) {
|
|
51
|
+
allProjects.add(r.proj);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return Array.from(allProjects).sort();
|
|
57
|
+
} finally {
|
|
58
|
+
db.close();
|
|
59
|
+
}
|
|
60
|
+
}
|