-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcli.ts
More file actions
104 lines (87 loc) · 3.4 KB
/
cli.ts
File metadata and controls
104 lines (87 loc) · 3.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import * as fs from "node:fs/promises";
import * as path from "node:path";
import { parseEnvInt } from "./util.js";
import { FtsIndex } from "./index/ftsIndex.js";
import { indexLibrary } from "./index/indexer.js";
import { RlmEnvironment } from "./env/replEnv.js";
import { runRlm } from "./controller.js";
import { startDaemon } from "./daemon/server.js";
type Args = {
task: string;
contextFile?: string;
contextStdin?: boolean;
libraryDir?: string;
reindex?: boolean;
};
function parseArgs(argv: string[]): Args {
let task = "";
let contextFile: string | undefined;
let contextStdin = false;
let libraryDir: string | undefined;
let reindex = false;
for (let i = 0; i < argv.length; i++) {
const a = argv[i];
if (a === "--task" && i + 1 < argv.length) task = argv[++i];
else if (a === "--context-file" && i + 1 < argv.length) contextFile = argv[++i];
else if (a === "--context-stdin") contextStdin = true;
else if (a === "--library-dir" && i + 1 < argv.length) libraryDir = argv[++i];
else if (a === "--reindex") reindex = true;
else if (!a.startsWith("--") && !task) task = a;
else if (!a.startsWith("--") && task && !contextFile && !contextStdin) task = `${task} ${a}`.trim();
}
if (!task.trim()) {
throw new Error(
`Missing --task.\nExamples:\n bun run quidoris-engine.ts --task "Question" --library-dir ./docs\n bun run quidoris-engine.ts --task "Question" --context-file ./big.txt`
);
}
return { task: task.trim(), contextFile, contextStdin, libraryDir, reindex };
}
async function readAllStdin(): Promise<string> {
const chunks: Uint8Array[] = [];
for await (const chunk of Bun.stdin.stream()) chunks.push(chunk);
const total = chunks.reduce((n, c) => n + c.length, 0);
const buf = new Uint8Array(total);
let off = 0;
for (const c of chunks) {
buf.set(c, off);
off += c.length;
}
return new TextDecoder().decode(buf);
}
export async function main() {
const argv = process.argv.slice(2);
// Subcommand: daemon
if (argv[0] === "daemon") {
const portArgIdx = argv.indexOf("--port");
const port = portArgIdx !== -1 && argv[portArgIdx + 1] ? Number(argv[portArgIdx + 1]) : Number(process.env.PORT ?? "8787");
const engineDbPath = process.env.ENGINE_DB_PATH ?? path.resolve(process.cwd(), "quidoris_engine.sqlite");
const indexDbPath = process.env.INDEX_PATH ?? path.resolve(process.cwd(), "rlm_index.sqlite");
const version = process.env.VERSION ?? "0.1.0";
await startDaemon({
port: Number.isFinite(port) && port > 0 ? port : 8787,
engineDbPath,
indexDbPath,
version,
});
// keep process alive
await new Promise(() => {});
}
const args = parseArgs(argv);
let context = "";
if (args.contextFile) context = await fs.readFile(args.contextFile, "utf8");
else if (args.contextStdin) context = await readAllStdin();
const indexPath = process.env.INDEX_PATH ?? path.resolve(process.cwd(), "rlm_index.sqlite");
let index: FtsIndex | null = null;
if (args.libraryDir) {
index = new FtsIndex(indexPath);
if (args.reindex) {
console.log(`[Index] Forced reindex requested. Clearing existing index...`);
const db = index._raw();
db.exec(`DELETE FROM docs_fts; DELETE FROM doc_chunks; DELETE FROM docs;`);
}
await indexLibrary(index, args.libraryDir);
}
const env = new RlmEnvironment({ context, index });
await runRlm(args.task, env);
index?.close();
}