knowledge-rag 4.8.5 → 4.9.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.
Files changed (4) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +739 -716
  3. package/bin/cli.js +254 -254
  4. package/package.json +42 -42
package/bin/cli.js CHANGED
@@ -1,254 +1,254 @@
1
- #!/usr/bin/env node
2
-
3
- "use strict";
4
-
5
- const { execFileSync, spawn } = require("child_process");
6
- const fs = require("fs");
7
- const path = require("path");
8
- const os = require("os");
9
-
10
- // ---------------------------------------------------------------------------
11
- // Constants
12
- // ---------------------------------------------------------------------------
13
-
14
- const PACKAGE_VERSION = require("../package.json").version;
15
- const BASE_DIR = path.join(os.homedir(), ".knowledge-rag");
16
- const VENV_DIR = path.join(BASE_DIR, "venv");
17
- const VERSION_FILE = path.join(BASE_DIR, ".npm-version");
18
- const PYPI_PACKAGE = "knowledge-rag";
19
- const MIN_PYTHON_MAJOR = 3;
20
- const MIN_PYTHON_MINOR = 11;
21
-
22
- // ---------------------------------------------------------------------------
23
- // Helpers — all user-facing output goes to STDERR (MCP uses stdout)
24
- // ---------------------------------------------------------------------------
25
-
26
- function log(msg) {
27
- process.stderr.write(`[knowledge-rag] ${msg}\n`);
28
- }
29
-
30
- function fatal(msg) {
31
- process.stderr.write(`[knowledge-rag] ERROR: ${msg}\n`);
32
- process.exit(1);
33
- }
34
-
35
- // ---------------------------------------------------------------------------
36
- // Python discovery (cross-platform)
37
- // ---------------------------------------------------------------------------
38
-
39
- function tryPython(cmd, args) {
40
- try {
41
- const out = execFileSync(cmd, args, {
42
- encoding: "utf-8",
43
- stdio: ["ignore", "pipe", "ignore"],
44
- timeout: 10000,
45
- }).trim();
46
- return out;
47
- } catch {
48
- return null;
49
- }
50
- }
51
-
52
- function parsePythonVersion(versionStr) {
53
- const match = versionStr && versionStr.match(/(\d+)\.(\d+)\.(\d+)/);
54
- if (!match) return null;
55
- return {
56
- major: parseInt(match[1], 10),
57
- minor: parseInt(match[2], 10),
58
- patch: parseInt(match[3], 10),
59
- raw: match[0],
60
- };
61
- }
62
-
63
- function findPython() {
64
- const isWindows = process.platform === "win32";
65
-
66
- const candidates = isWindows
67
- ? [
68
- { cmd: "python", args: ["--version"] },
69
- { cmd: "py", args: ["-3", "--version"] },
70
- ]
71
- : [
72
- { cmd: "python3", args: ["--version"] },
73
- { cmd: "python", args: ["--version"] },
74
- ];
75
-
76
- for (const { cmd, args } of candidates) {
77
- const raw = tryPython(cmd, args);
78
- const ver = parsePythonVersion(raw);
79
- if (!ver) continue;
80
- if (ver.major < MIN_PYTHON_MAJOR) continue;
81
- if (ver.major === MIN_PYTHON_MAJOR && ver.minor < MIN_PYTHON_MINOR) continue;
82
-
83
- const execCmd = cmd === "py" ? "py" : cmd;
84
- const execArgs = cmd === "py" ? ["-3"] : [];
85
- return { cmd: execCmd, args: execArgs, version: ver };
86
- }
87
-
88
- return null;
89
- }
90
-
91
- // ---------------------------------------------------------------------------
92
- // Venv management
93
- // ---------------------------------------------------------------------------
94
-
95
- function getVenvPython() {
96
- if (process.platform === "win32") {
97
- return path.join(VENV_DIR, "Scripts", "python.exe");
98
- }
99
- return path.join(VENV_DIR, "bin", "python");
100
- }
101
-
102
- function venvExists() {
103
- return fs.existsSync(getVenvPython());
104
- }
105
-
106
- function createVenv(python) {
107
- log(`Creating virtual environment at ${VENV_DIR}`);
108
- fs.mkdirSync(BASE_DIR, { recursive: true });
109
-
110
- const args = [...python.args, "-m", "venv", VENV_DIR];
111
- try {
112
- execFileSync(python.cmd, args, {
113
- stdio: ["ignore", "ignore", "pipe"],
114
- timeout: 120000,
115
- });
116
- } catch (err) {
117
- fatal(
118
- `Failed to create virtual environment.\n` +
119
- ` Command: ${python.cmd} ${args.join(" ")}\n` +
120
- ` ${err.stderr ? err.stderr.toString().trim() : err.message}`
121
- );
122
- }
123
- }
124
-
125
- function installedVersionMatches() {
126
- try {
127
- const stored = fs.readFileSync(VERSION_FILE, "utf-8").trim();
128
- return stored === PACKAGE_VERSION;
129
- } catch {
130
- return false;
131
- }
132
- }
133
-
134
- function writeVersionFile() {
135
- fs.writeFileSync(VERSION_FILE, PACKAGE_VERSION, "utf-8");
136
- }
137
-
138
- function installPackage() {
139
- const venvPython = getVenvPython();
140
- log(`Installing ${PYPI_PACKAGE}==${PACKAGE_VERSION} from PyPI`);
141
-
142
- const args = [
143
- "-m",
144
- "pip",
145
- "install",
146
- "--upgrade",
147
- "--quiet",
148
- `${PYPI_PACKAGE}==${PACKAGE_VERSION}`,
149
- ];
150
-
151
- try {
152
- execFileSync(venvPython, args, {
153
- stdio: ["ignore", "ignore", "pipe"],
154
- timeout: 300000,
155
- });
156
- } catch (err) {
157
- fatal(
158
- `Failed to install ${PYPI_PACKAGE}.\n` +
159
- ` ${err.stderr ? err.stderr.toString().trim() : err.message}`
160
- );
161
- }
162
-
163
- writeVersionFile();
164
- log("Installation complete");
165
- }
166
-
167
- // ---------------------------------------------------------------------------
168
- // Ensure environment is ready
169
- // ---------------------------------------------------------------------------
170
-
171
- function ensureInstalled(python) {
172
- if (!venvExists()) {
173
- createVenv(python);
174
- installPackage();
175
- return;
176
- }
177
-
178
- if (!installedVersionMatches()) {
179
- log("Version changed, updating package");
180
- installPackage();
181
- return;
182
- }
183
- }
184
-
185
- // ---------------------------------------------------------------------------
186
- // Run the MCP server
187
- // ---------------------------------------------------------------------------
188
-
189
- function runServer() {
190
- const venvPython = getVenvPython();
191
-
192
- const child = spawn(venvPython, ["-m", "mcp_server.server"], {
193
- stdio: "inherit",
194
- windowsHide: true,
195
- });
196
-
197
- const forwardSignal = (sig) => {
198
- if (child.pid) {
199
- try {
200
- child.kill(sig);
201
- } catch {
202
- // child may have already exited
203
- }
204
- }
205
- };
206
-
207
- process.on("SIGINT", () => forwardSignal("SIGINT"));
208
- process.on("SIGTERM", () => forwardSignal("SIGTERM"));
209
-
210
- child.on("error", (err) => {
211
- fatal(`Failed to start MCP server: ${err.message}`);
212
- });
213
-
214
- child.on("exit", (code, signal) => {
215
- if (signal) {
216
- process.exit(1);
217
- }
218
- process.exit(code || 0);
219
- });
220
- }
221
-
222
- // ---------------------------------------------------------------------------
223
- // CLI entry point
224
- // ---------------------------------------------------------------------------
225
-
226
- function main() {
227
- const args = process.argv.slice(2);
228
-
229
- if (args.includes("--version")) {
230
- process.stderr.write(`knowledge-rag ${PACKAGE_VERSION}\n`);
231
- process.exit(0);
232
- }
233
-
234
- const python = findPython();
235
- if (!python) {
236
- fatal(
237
- `Python ${MIN_PYTHON_MAJOR}.${MIN_PYTHON_MINOR}+ is required but was not found.\n` +
238
- ` Searched for: ${process.platform === "win32" ? "python, py -3" : "python3, python"}\n` +
239
- ` Install Python from https://www.python.org/downloads/`
240
- );
241
- }
242
-
243
- log(`Found Python ${python.version.raw}`);
244
- ensureInstalled(python);
245
-
246
- if (args.includes("--install-only")) {
247
- log("Install complete (--install-only). Exiting.");
248
- process.exit(0);
249
- }
250
-
251
- runServer();
252
- }
253
-
254
- main();
1
+ #!/usr/bin/env node
2
+
3
+ "use strict";
4
+
5
+ const { execFileSync, spawn } = require("child_process");
6
+ const fs = require("fs");
7
+ const path = require("path");
8
+ const os = require("os");
9
+
10
+ // ---------------------------------------------------------------------------
11
+ // Constants
12
+ // ---------------------------------------------------------------------------
13
+
14
+ const PACKAGE_VERSION = require("../package.json").version;
15
+ const BASE_DIR = path.join(os.homedir(), ".knowledge-rag");
16
+ const VENV_DIR = path.join(BASE_DIR, "venv");
17
+ const VERSION_FILE = path.join(BASE_DIR, ".npm-version");
18
+ const PYPI_PACKAGE = "knowledge-rag";
19
+ const MIN_PYTHON_MAJOR = 3;
20
+ const MIN_PYTHON_MINOR = 11;
21
+
22
+ // ---------------------------------------------------------------------------
23
+ // Helpers — all user-facing output goes to STDERR (MCP uses stdout)
24
+ // ---------------------------------------------------------------------------
25
+
26
+ function log(msg) {
27
+ process.stderr.write(`[knowledge-rag] ${msg}\n`);
28
+ }
29
+
30
+ function fatal(msg) {
31
+ process.stderr.write(`[knowledge-rag] ERROR: ${msg}\n`);
32
+ process.exit(1);
33
+ }
34
+
35
+ // ---------------------------------------------------------------------------
36
+ // Python discovery (cross-platform)
37
+ // ---------------------------------------------------------------------------
38
+
39
+ function tryPython(cmd, args) {
40
+ try {
41
+ const out = execFileSync(cmd, args, {
42
+ encoding: "utf-8",
43
+ stdio: ["ignore", "pipe", "ignore"],
44
+ timeout: 10000,
45
+ }).trim();
46
+ return out;
47
+ } catch {
48
+ return null;
49
+ }
50
+ }
51
+
52
+ function parsePythonVersion(versionStr) {
53
+ const match = versionStr && versionStr.match(/(\d+)\.(\d+)\.(\d+)/);
54
+ if (!match) return null;
55
+ return {
56
+ major: parseInt(match[1], 10),
57
+ minor: parseInt(match[2], 10),
58
+ patch: parseInt(match[3], 10),
59
+ raw: match[0],
60
+ };
61
+ }
62
+
63
+ function findPython() {
64
+ const isWindows = process.platform === "win32";
65
+
66
+ const candidates = isWindows
67
+ ? [
68
+ { cmd: "python", args: ["--version"] },
69
+ { cmd: "py", args: ["-3", "--version"] },
70
+ ]
71
+ : [
72
+ { cmd: "python3", args: ["--version"] },
73
+ { cmd: "python", args: ["--version"] },
74
+ ];
75
+
76
+ for (const { cmd, args } of candidates) {
77
+ const raw = tryPython(cmd, args);
78
+ const ver = parsePythonVersion(raw);
79
+ if (!ver) continue;
80
+ if (ver.major < MIN_PYTHON_MAJOR) continue;
81
+ if (ver.major === MIN_PYTHON_MAJOR && ver.minor < MIN_PYTHON_MINOR) continue;
82
+
83
+ const execCmd = cmd === "py" ? "py" : cmd;
84
+ const execArgs = cmd === "py" ? ["-3"] : [];
85
+ return { cmd: execCmd, args: execArgs, version: ver };
86
+ }
87
+
88
+ return null;
89
+ }
90
+
91
+ // ---------------------------------------------------------------------------
92
+ // Venv management
93
+ // ---------------------------------------------------------------------------
94
+
95
+ function getVenvPython() {
96
+ if (process.platform === "win32") {
97
+ return path.join(VENV_DIR, "Scripts", "python.exe");
98
+ }
99
+ return path.join(VENV_DIR, "bin", "python");
100
+ }
101
+
102
+ function venvExists() {
103
+ return fs.existsSync(getVenvPython());
104
+ }
105
+
106
+ function createVenv(python) {
107
+ log(`Creating virtual environment at ${VENV_DIR}`);
108
+ fs.mkdirSync(BASE_DIR, { recursive: true });
109
+
110
+ const args = [...python.args, "-m", "venv", VENV_DIR];
111
+ try {
112
+ execFileSync(python.cmd, args, {
113
+ stdio: ["ignore", "ignore", "pipe"],
114
+ timeout: 120000,
115
+ });
116
+ } catch (err) {
117
+ fatal(
118
+ `Failed to create virtual environment.\n` +
119
+ ` Command: ${python.cmd} ${args.join(" ")}\n` +
120
+ ` ${err.stderr ? err.stderr.toString().trim() : err.message}`
121
+ );
122
+ }
123
+ }
124
+
125
+ function installedVersionMatches() {
126
+ try {
127
+ const stored = fs.readFileSync(VERSION_FILE, "utf-8").trim();
128
+ return stored === PACKAGE_VERSION;
129
+ } catch {
130
+ return false;
131
+ }
132
+ }
133
+
134
+ function writeVersionFile() {
135
+ fs.writeFileSync(VERSION_FILE, PACKAGE_VERSION, "utf-8");
136
+ }
137
+
138
+ function installPackage() {
139
+ const venvPython = getVenvPython();
140
+ log(`Installing ${PYPI_PACKAGE}==${PACKAGE_VERSION} from PyPI`);
141
+
142
+ const args = [
143
+ "-m",
144
+ "pip",
145
+ "install",
146
+ "--upgrade",
147
+ "--quiet",
148
+ `${PYPI_PACKAGE}==${PACKAGE_VERSION}`,
149
+ ];
150
+
151
+ try {
152
+ execFileSync(venvPython, args, {
153
+ stdio: ["ignore", "ignore", "pipe"],
154
+ timeout: 300000,
155
+ });
156
+ } catch (err) {
157
+ fatal(
158
+ `Failed to install ${PYPI_PACKAGE}.\n` +
159
+ ` ${err.stderr ? err.stderr.toString().trim() : err.message}`
160
+ );
161
+ }
162
+
163
+ writeVersionFile();
164
+ log("Installation complete");
165
+ }
166
+
167
+ // ---------------------------------------------------------------------------
168
+ // Ensure environment is ready
169
+ // ---------------------------------------------------------------------------
170
+
171
+ function ensureInstalled(python) {
172
+ if (!venvExists()) {
173
+ createVenv(python);
174
+ installPackage();
175
+ return;
176
+ }
177
+
178
+ if (!installedVersionMatches()) {
179
+ log("Version changed, updating package");
180
+ installPackage();
181
+ return;
182
+ }
183
+ }
184
+
185
+ // ---------------------------------------------------------------------------
186
+ // Run the MCP server
187
+ // ---------------------------------------------------------------------------
188
+
189
+ function runServer() {
190
+ const venvPython = getVenvPython();
191
+
192
+ const child = spawn(venvPython, ["-m", "mcp_server.server"], {
193
+ stdio: "inherit",
194
+ windowsHide: true,
195
+ });
196
+
197
+ const forwardSignal = (sig) => {
198
+ if (child.pid) {
199
+ try {
200
+ child.kill(sig);
201
+ } catch {
202
+ // child may have already exited
203
+ }
204
+ }
205
+ };
206
+
207
+ process.on("SIGINT", () => forwardSignal("SIGINT"));
208
+ process.on("SIGTERM", () => forwardSignal("SIGTERM"));
209
+
210
+ child.on("error", (err) => {
211
+ fatal(`Failed to start MCP server: ${err.message}`);
212
+ });
213
+
214
+ child.on("exit", (code, signal) => {
215
+ if (signal) {
216
+ process.exit(1);
217
+ }
218
+ process.exit(code || 0);
219
+ });
220
+ }
221
+
222
+ // ---------------------------------------------------------------------------
223
+ // CLI entry point
224
+ // ---------------------------------------------------------------------------
225
+
226
+ function main() {
227
+ const args = process.argv.slice(2);
228
+
229
+ if (args.includes("--version")) {
230
+ process.stderr.write(`knowledge-rag ${PACKAGE_VERSION}\n`);
231
+ process.exit(0);
232
+ }
233
+
234
+ const python = findPython();
235
+ if (!python) {
236
+ fatal(
237
+ `Python ${MIN_PYTHON_MAJOR}.${MIN_PYTHON_MINOR}+ is required but was not found.\n` +
238
+ ` Searched for: ${process.platform === "win32" ? "python, py -3" : "python3, python"}\n` +
239
+ ` Install Python from https://www.python.org/downloads/`
240
+ );
241
+ }
242
+
243
+ log(`Found Python ${python.version.raw}`);
244
+ ensureInstalled(python);
245
+
246
+ if (args.includes("--install-only")) {
247
+ log("Install complete (--install-only). Exiting.");
248
+ process.exit(0);
249
+ }
250
+
251
+ runServer();
252
+ }
253
+
254
+ main();
package/package.json CHANGED
@@ -1,42 +1,42 @@
1
- {
2
- "name": "knowledge-rag",
3
- "version": "4.8.5",
4
- "description": "Local RAG System for Claude Code — Hybrid search + Cross-encoder Reranking + 13 MCP Tools + 20 Format Parsers. Zero external servers.",
5
- "bin": {
6
- "knowledge-rag": "./bin/cli.js"
7
- },
8
- "keywords": [
9
- "rag",
10
- "mcp",
11
- "claude-code",
12
- "semantic-search",
13
- "embeddings",
14
- "knowledge-base",
15
- "local-ai",
16
- "retrieval-augmented-generation",
17
- "hybrid-search",
18
- "claude"
19
- ],
20
- "author": "Lyon. <lyonzin@users.noreply.github.com>",
21
- "license": "MIT",
22
- "homepage": "https://github.com/lyonzin/knowledge-rag",
23
- "repository": {
24
- "type": "git",
25
- "url": "https://github.com/lyonzin/knowledge-rag.git",
26
- "directory": "npm"
27
- },
28
- "bugs": {
29
- "url": "https://github.com/lyonzin/knowledge-rag/issues"
30
- },
31
- "funding": {
32
- "url": "https://github.com/sponsors/lyonzin"
33
- },
34
- "engines": {
35
- "node": ">=16"
36
- },
37
- "files": [
38
- "bin/",
39
- "README.md",
40
- "LICENSE"
41
- ]
42
- }
1
+ {
2
+ "name": "knowledge-rag",
3
+ "version": "4.9.0",
4
+ "description": "Local RAG System for Claude Code \u00e2\u20ac\u201d Hybrid search + Cross-encoder Reranking + 13 MCP Tools + 20 Format Parsers. Zero external servers.",
5
+ "bin": {
6
+ "knowledge-rag": "./bin/cli.js"
7
+ },
8
+ "keywords": [
9
+ "rag",
10
+ "mcp",
11
+ "claude-code",
12
+ "semantic-search",
13
+ "embeddings",
14
+ "knowledge-base",
15
+ "local-ai",
16
+ "retrieval-augmented-generation",
17
+ "hybrid-search",
18
+ "claude"
19
+ ],
20
+ "author": "Lyon. <lyonzin@users.noreply.github.com>",
21
+ "license": "MIT",
22
+ "homepage": "https://github.com/lyonzin/knowledge-rag",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/lyonzin/knowledge-rag.git",
26
+ "directory": "npm"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/lyonzin/knowledge-rag/issues"
30
+ },
31
+ "funding": {
32
+ "url": "https://github.com/sponsors/lyonzin"
33
+ },
34
+ "engines": {
35
+ "node": ">=16"
36
+ },
37
+ "files": [
38
+ "bin/",
39
+ "README.md",
40
+ "LICENSE"
41
+ ]
42
+ }