@getlore/cli 0.4.0 → 0.5.0
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/dist/cli/commands/ingest.d.ts +8 -0
- package/dist/cli/commands/ingest.js +104 -0
- package/dist/index.js +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ingest Command
|
|
3
|
+
*
|
|
4
|
+
* Push content directly into Lore from the CLI.
|
|
5
|
+
* Accepts inline text, a file path, or piped stdin.
|
|
6
|
+
*/
|
|
7
|
+
import type { Command } from 'commander';
|
|
8
|
+
export declare function registerIngestCommand(program: Command, defaultDataDir: string): void;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ingest Command
|
|
3
|
+
*
|
|
4
|
+
* Push content directly into Lore from the CLI.
|
|
5
|
+
* Accepts inline text, a file path, or piped stdin.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, existsSync } from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
export function registerIngestCommand(program, defaultDataDir) {
|
|
10
|
+
program
|
|
11
|
+
.command('ingest')
|
|
12
|
+
.description('Ingest content into the knowledge base')
|
|
13
|
+
.argument('[content]', 'Content to ingest (or use --file / stdin)')
|
|
14
|
+
.option('-f, --file <path>', 'Read content from a file')
|
|
15
|
+
.option('-t, --title <title>', 'Document title')
|
|
16
|
+
.option('-p, --project <project>', 'Project name', 'default')
|
|
17
|
+
.option('--type <type>', 'Source type (e.g. meeting, notes, article)')
|
|
18
|
+
.option('--url <url>', 'Source URL for citation linking')
|
|
19
|
+
.option('--name <name>', 'Human-readable source name')
|
|
20
|
+
.option('--tags <tags>', 'Comma-separated tags')
|
|
21
|
+
.option('-d, --data-dir <dir>', 'Data directory', defaultDataDir)
|
|
22
|
+
.action(async (contentArg, options) => {
|
|
23
|
+
const { handleIngest } = await import('../../mcp/handlers/ingest.js');
|
|
24
|
+
const dataDir = options.dataDir;
|
|
25
|
+
const dbPath = path.join(dataDir, 'lore.lance');
|
|
26
|
+
// Resolve content from argument, file, or stdin
|
|
27
|
+
let content;
|
|
28
|
+
if (options.file) {
|
|
29
|
+
const filePath = options.file.replace(/^~/, process.env.HOME || '~');
|
|
30
|
+
if (!existsSync(filePath)) {
|
|
31
|
+
console.error(`File not found: ${filePath}`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
content = readFileSync(filePath, 'utf-8');
|
|
35
|
+
}
|
|
36
|
+
else if (contentArg) {
|
|
37
|
+
content = contentArg;
|
|
38
|
+
}
|
|
39
|
+
else if (!process.stdin.isTTY) {
|
|
40
|
+
// Reading from pipe/stdin
|
|
41
|
+
content = readFileSync(0, 'utf-8');
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
console.error('No content provided. Use one of:');
|
|
45
|
+
console.error(' lore ingest "Your content here"');
|
|
46
|
+
console.error(' lore ingest --file ./notes.md');
|
|
47
|
+
console.error(' echo "content" | lore ingest');
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
content = content.trim();
|
|
51
|
+
if (!content) {
|
|
52
|
+
console.error('Content is empty.');
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
// Derive title from file name or content
|
|
56
|
+
let title = options.title;
|
|
57
|
+
if (!title && options.file) {
|
|
58
|
+
title = path.basename(options.file, path.extname(options.file));
|
|
59
|
+
}
|
|
60
|
+
if (!title) {
|
|
61
|
+
// Use first line or first 60 chars
|
|
62
|
+
const firstLine = content.split('\n')[0].replace(/^#+\s*/, '');
|
|
63
|
+
title = firstLine.length > 60 ? firstLine.slice(0, 57) + '...' : firstLine;
|
|
64
|
+
}
|
|
65
|
+
const tags = options.tags ? options.tags.split(',').map((t) => t.trim()) : [];
|
|
66
|
+
console.log(`\nIngesting: ${title}`);
|
|
67
|
+
console.log(`Project: ${options.project}`);
|
|
68
|
+
if (options.type)
|
|
69
|
+
console.log(`Type: ${options.type}`);
|
|
70
|
+
console.log(`Content: ${content.length} chars`);
|
|
71
|
+
console.log('');
|
|
72
|
+
const result = await handleIngest(dbPath, dataDir, {
|
|
73
|
+
content,
|
|
74
|
+
title,
|
|
75
|
+
project: options.project,
|
|
76
|
+
source_type: options.type,
|
|
77
|
+
tags,
|
|
78
|
+
source_url: options.url,
|
|
79
|
+
source_name: options.name,
|
|
80
|
+
}, {
|
|
81
|
+
hookContext: { mode: 'cli' },
|
|
82
|
+
});
|
|
83
|
+
if (result.deduplicated) {
|
|
84
|
+
console.log('Already exists (identical content). Skipped.');
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (result.success) {
|
|
88
|
+
console.log(`Ingested (ID: ${result.id})`);
|
|
89
|
+
if (result.indexed) {
|
|
90
|
+
console.log('Indexed and searchable.');
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
console.log('Saved to disk. Run "lore sync" to index.');
|
|
94
|
+
}
|
|
95
|
+
if (result.synced) {
|
|
96
|
+
console.log('Pushed to git.');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
console.error('Ingestion failed.');
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ import { registerAskCommand } from './cli/commands/ask.js';
|
|
|
30
30
|
import { registerAuthCommands } from './cli/commands/auth.js';
|
|
31
31
|
import { registerSkillsCommand } from './cli/commands/skills.js';
|
|
32
32
|
import { registerUpdateCommand } from './cli/commands/update.js';
|
|
33
|
+
import { registerIngestCommand } from './cli/commands/ingest.js';
|
|
33
34
|
import { getExtensionRegistry, getLoreVersionString } from './extensions/registry.js';
|
|
34
35
|
import { bridgeConfigToEnv } from './core/config.js';
|
|
35
36
|
import { expandPath } from './sync/config.js';
|
|
@@ -78,6 +79,7 @@ registerAskCommand(program, DEFAULT_DATA_DIR);
|
|
|
78
79
|
registerAuthCommands(program);
|
|
79
80
|
registerSkillsCommand(program);
|
|
80
81
|
registerUpdateCommand(program, DEFAULT_DATA_DIR);
|
|
82
|
+
registerIngestCommand(program, DEFAULT_DATA_DIR);
|
|
81
83
|
// Extension system — hidden from top-level help for now
|
|
82
84
|
const extensionCmd = registerExtensionCommands(program);
|
|
83
85
|
extensionCmd._hidden = true;
|