llm-kb 0.2.0 → 0.4.1

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.
Files changed (41) hide show
  1. package/README.md +322 -60
  2. package/bin/anthropic-5TIU2EED.js +5515 -0
  3. package/bin/azure-openai-responses-ZVUVMK3G.js +190 -0
  4. package/bin/chunk-2WV6TQRI.js +4792 -0
  5. package/bin/chunk-3YMNGUZZ.js +262 -0
  6. package/bin/chunk-5PYKQQLA.js +14295 -0
  7. package/bin/chunk-65KFH7OI.js +31 -0
  8. package/bin/chunk-DHOXVEIR.js +7261 -0
  9. package/bin/chunk-EAQYK3U2.js +41 -0
  10. package/bin/chunk-IFS3OKBN.js +428 -0
  11. package/bin/chunk-LDHOKBJA.js +86 -0
  12. package/bin/chunk-SLYBG6ZQ.js +32681 -0
  13. package/bin/chunk-UEODFF7H.js +17 -0
  14. package/bin/chunk-XCXTZJGO.js +174 -0
  15. package/bin/chunk-XFV534WU.js +7056 -0
  16. package/bin/cli.js +5496 -163
  17. package/bin/dist-3YH7P2QF.js +1244 -0
  18. package/bin/google-JFC43EFJ.js +371 -0
  19. package/bin/google-gemini-cli-K4XNMYDI.js +712 -0
  20. package/bin/google-vertex-Y42F254G.js +414 -0
  21. package/bin/indexer-KSYRIVVN.js +10 -0
  22. package/bin/mistral-ZU2JS5XZ.js +38406 -0
  23. package/bin/multipart-parser-CO464TZY.js +371 -0
  24. package/bin/openai-codex-responses-NW2LELBH.js +712 -0
  25. package/bin/openai-completions-TW3VKTHO.js +662 -0
  26. package/bin/openai-responses-VGL522MK.js +198 -0
  27. package/bin/src-Y22OHE3S.js +1408 -0
  28. package/package.json +16 -6
  29. package/PHASE2_SPEC.md +0 -274
  30. package/SPEC.md +0 -275
  31. package/bin/chunk-MYQ36JJB.js +0 -118
  32. package/bin/indexer-LSYSZXZX.js +0 -6
  33. package/plan.md +0 -55
  34. package/src/cli.ts +0 -132
  35. package/src/indexer.ts +0 -148
  36. package/src/pdf.ts +0 -119
  37. package/src/query.ts +0 -132
  38. package/src/resolve-kb.ts +0 -19
  39. package/src/scan.ts +0 -59
  40. package/src/watcher.ts +0 -84
  41. package/tsconfig.json +0 -14
package/src/query.ts DELETED
@@ -1,132 +0,0 @@
1
- import {
2
- createAgentSession,
3
- createBashTool,
4
- createReadTool,
5
- createWriteTool,
6
- DefaultResourceLoader,
7
- SessionManager,
8
- SettingsManager,
9
- } from "@mariozechner/pi-coding-agent";
10
- import { readdir, mkdir } from "node:fs/promises";
11
- import { join, dirname } from "node:path";
12
- import { fileURLToPath } from "node:url";
13
-
14
- const __dirname = dirname(fileURLToPath(import.meta.url));
15
-
16
- function getNodeModulesPath(): string {
17
- let dir = __dirname;
18
- for (let i = 0; i < 5; i++) {
19
- const candidate = join(dir, "node_modules");
20
- try { return candidate; } catch { dir = dirname(dir); }
21
- }
22
- return join(process.cwd(), "node_modules");
23
- }
24
-
25
- function buildQueryAgents(sourceFiles: string[], save: boolean): string {
26
- const sourceList = sourceFiles.map((f) => ` - ${f}`).join("\n");
27
-
28
- let content = `# llm-kb Knowledge Base — Query Mode
29
-
30
- ## How to answer questions
31
-
32
- 1. FIRST read .llm-kb/wiki/index.md to understand all available sources
33
- 2. Based on the question, select the most relevant source files (usually 2-5)
34
- 3. Read those source files in full from .llm-kb/wiki/sources/
35
- 4. Answer with inline citations: (filename, page number)
36
- 5. If the answer requires cross-referencing multiple files, read additional ones
37
- 6. If you can't find the answer, say so — don't hallucinate
38
-
39
- ## Available parsed sources
40
- ${sourceList}
41
-
42
- ## Non-PDF files
43
- If the user's folder has Excel, Word, or PowerPoint files, these libraries are available:
44
- - **exceljs** — for .xlsx/.xls files
45
- - **mammoth** — for .docx files
46
- - **officeparser** — for .pptx files
47
- Write a quick Node.js script via bash to read them.
48
-
49
- ## Rules
50
- - Always cite sources with filename and page number
51
- - Read the FULL source file, not just the beginning
52
- - Prefer primary sources over previous analyses
53
- `;
54
-
55
- if (save) {
56
- content += `
57
- ## Research Mode
58
- Save your analysis to .llm-kb/wiki/outputs/ with a descriptive filename (e.g., comparison-analysis.md).
59
- Include the question at the top and all citations.
60
- `;
61
- }
62
-
63
- return content;
64
- }
65
-
66
- export async function query(
67
- folder: string,
68
- question: string,
69
- options: { save?: boolean }
70
- ): Promise<void> {
71
- const sourcesDir = join(folder, ".llm-kb", "wiki", "sources");
72
-
73
- const files = await readdir(sourcesDir);
74
- const mdFiles = files.filter((f) => f.endsWith(".md"));
75
-
76
- if (mdFiles.length === 0) {
77
- throw new Error("No sources found. Run 'llm-kb run' first to parse documents.");
78
- }
79
-
80
- if (options.save) {
81
- await mkdir(join(folder, ".llm-kb", "wiki", "outputs"), { recursive: true });
82
- }
83
-
84
- process.env.NODE_PATH = getNodeModulesPath();
85
-
86
- const agentsContent = buildQueryAgents(mdFiles, !!options.save);
87
-
88
- const loader = new DefaultResourceLoader({
89
- cwd: folder,
90
- agentsFilesOverride: (current) => ({
91
- agentsFiles: [
92
- ...current.agentsFiles,
93
- { path: ".llm-kb/AGENTS.md", content: agentsContent },
94
- ],
95
- }),
96
- });
97
- await loader.reload();
98
-
99
- const tools = [createReadTool(folder)];
100
- if (options.save) {
101
- tools.push(createBashTool(folder), createWriteTool(folder));
102
- }
103
-
104
- const { session } = await createAgentSession({
105
- cwd: folder,
106
- resourceLoader: loader,
107
- tools,
108
- sessionManager: SessionManager.inMemory(),
109
- settingsManager: SettingsManager.inMemory({
110
- compaction: { enabled: false },
111
- }),
112
- });
113
-
114
- session.subscribe((event) => {
115
- if (
116
- event.type === "message_update" &&
117
- event.assistantMessageEvent.type === "text_delta"
118
- ) {
119
- process.stdout.write(event.assistantMessageEvent.delta);
120
- }
121
- });
122
-
123
- await session.prompt(question);
124
- console.log();
125
- session.dispose();
126
-
127
- // Re-index after save so the compounding loop works
128
- if (options.save) {
129
- const { buildIndex } = await import("./indexer.js");
130
- await buildIndex(folder, sourcesDir);
131
- }
132
- }
package/src/resolve-kb.ts DELETED
@@ -1,19 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { resolve, join, dirname } from "node:path";
3
-
4
- /**
5
- * Walk up from startDir looking for a .llm-kb/ directory.
6
- * Returns the folder containing .llm-kb/, or null if not found.
7
- */
8
- export function resolveKnowledgeBase(startDir: string): string | null {
9
- let dir = resolve(startDir);
10
-
11
- while (true) {
12
- if (existsSync(join(dir, ".llm-kb"))) {
13
- return dir;
14
- }
15
- const parent = dirname(dir);
16
- if (parent === dir) return null;
17
- dir = parent;
18
- }
19
- }
package/src/scan.ts DELETED
@@ -1,59 +0,0 @@
1
- import { readdir } from "node:fs/promises";
2
- import { resolve, extname, relative } from "node:path";
3
-
4
- export interface ScannedFile {
5
- name: string;
6
- path: string;
7
- ext: string;
8
- }
9
-
10
- const SUPPORTED_EXTENSIONS = new Set([
11
- ".pdf",
12
- ".xlsx",
13
- ".xls",
14
- ".docx",
15
- ".pptx",
16
- ".jpg",
17
- ".jpeg",
18
- ".png",
19
- ".txt",
20
- ".md",
21
- ".csv",
22
- ]);
23
-
24
- export async function scan(folder: string): Promise<ScannedFile[]> {
25
- const root = resolve(folder);
26
- const entries = await readdir(root, { recursive: true, withFileTypes: true });
27
-
28
- const files: ScannedFile[] = [];
29
-
30
- for (const entry of entries) {
31
- if (!entry.isFile()) continue;
32
-
33
- const fullPath = resolve(entry.parentPath, entry.name);
34
- const rel = relative(root, fullPath);
35
-
36
- // Skip .llm-kb internal folder
37
- if (rel.startsWith(".llm-kb")) continue;
38
-
39
- const ext = extname(entry.name).toLowerCase();
40
- if (!SUPPORTED_EXTENSIONS.has(ext)) continue;
41
-
42
- files.push({ name: entry.name, path: rel, ext });
43
- }
44
-
45
- return files;
46
- }
47
-
48
- export function summarize(files: ScannedFile[]): string {
49
- const counts = new Map<string, number>();
50
- for (const f of files) {
51
- counts.set(f.ext, (counts.get(f.ext) || 0) + 1);
52
- }
53
-
54
- const parts = Array.from(counts.entries())
55
- .sort((a, b) => b[1] - a[1])
56
- .map(([ext, count]) => `${count} ${ext.toUpperCase().slice(1)}`);
57
-
58
- return parts.join(", ");
59
- }
package/src/watcher.ts DELETED
@@ -1,84 +0,0 @@
1
- import { watch } from "chokidar";
2
- import { extname, join, basename } from "node:path";
3
- import { parsePDF } from "./pdf.js";
4
- import { buildIndex } from "./indexer.js";
5
- import chalk from "chalk";
6
-
7
- interface WatcherOptions {
8
- folder: string;
9
- sourcesDir: string;
10
- debounceMs?: number;
11
- }
12
-
13
- export function startWatcher({ folder, sourcesDir, debounceMs = 2000 }: WatcherOptions) {
14
- let pendingFiles: string[] = [];
15
- let debounceTimer: ReturnType<typeof setTimeout> | null = null;
16
-
17
- async function processBatch() {
18
- const files = [...pendingFiles];
19
- pendingFiles = [];
20
-
21
- if (files.length === 0) return;
22
-
23
- console.log();
24
- for (const filePath of files) {
25
- const name = basename(filePath);
26
- process.stdout.write(` Parsing ${name}...`);
27
- try {
28
- const result = await parsePDF(filePath, sourcesDir);
29
- if (result.skipped) {
30
- console.log(chalk.dim(` skipped (up to date)`));
31
- } else {
32
- console.log(chalk.green(` ✓ ${result.totalPages} pages`));
33
- }
34
- } catch (err: any) {
35
- console.log(chalk.red(` ✗ ${err.message}`));
36
- }
37
- }
38
-
39
- // Re-index
40
- process.stdout.write(` Re-indexing...`);
41
- try {
42
- await buildIndex(folder, sourcesDir);
43
- console.log(chalk.green(` ✓ index.md updated`));
44
- } catch (err: any) {
45
- console.log(chalk.red(` ✗ ${err.message}`));
46
- }
47
- }
48
-
49
- function queueFile(filePath: string) {
50
- if (!pendingFiles.includes(filePath)) {
51
- pendingFiles.push(filePath);
52
- }
53
- if (debounceTimer) clearTimeout(debounceTimer);
54
- debounceTimer = setTimeout(processBatch, debounceMs);
55
- }
56
-
57
- const watcher = watch(folder, {
58
- ignoreInitial: true,
59
- ignored: [
60
- "**/node_modules/**",
61
- "**/.llm-kb/**",
62
- "**/.git/**",
63
- ],
64
- depth: 10,
65
- });
66
-
67
- watcher.on("add", (filePath) => {
68
- const ext = extname(filePath).toLowerCase();
69
- if (ext === ".pdf") {
70
- console.log(chalk.dim(`\n New file: ${basename(filePath)}`));
71
- queueFile(filePath);
72
- }
73
- });
74
-
75
- watcher.on("change", (filePath) => {
76
- const ext = extname(filePath).toLowerCase();
77
- if (ext === ".pdf") {
78
- console.log(chalk.dim(`\n Changed: ${basename(filePath)}`));
79
- queueFile(filePath);
80
- }
81
- });
82
-
83
- return watcher;
84
- }
package/tsconfig.json DELETED
@@ -1,14 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "ES2022",
5
- "moduleResolution": "bundler",
6
- "strict": true,
7
- "esModuleInterop": true,
8
- "outDir": "dist",
9
- "rootDir": "src",
10
- "declaration": true,
11
- "sourceMap": true
12
- },
13
- "include": ["src"]
14
- }