bluera-knowledge 0.15.6 → 0.16.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.
@@ -1,5 +1,13 @@
1
1
  {
2
2
  "name": "bluera-knowledge",
3
- "version": "0.15.6",
4
- "description": "Clone repos, crawl docs, search locally. Fast, authoritative answers for AI coding agents."
3
+ "version": "0.16.0",
4
+ "description": "Clone repos, crawl docs, search locally. Fast, authoritative answers for AI coding agents.",
5
+ "prebuiltBinaries": {
6
+ "manifestUrl": "https://github.com/blueraai/bluera-knowledge/releases/latest/download/manifest.json",
7
+ "platforms": [
8
+ "darwin-arm64",
9
+ "darwin-x64",
10
+ "linux-x64"
11
+ ]
12
+ }
5
13
  }
package/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
4
4
 
5
+ ## [0.16.0](https://github.com/blueraai/bluera-knowledge/compare/v0.15.7...v0.16.0) (2026-01-17)
6
+
7
+
8
+ ### Features
9
+
10
+ * **dist:** add multi-platform prebuilt binary distribution ([32be73e](https://github.com/blueraai/bluera-knowledge/commit/32be73e7de962b8245ebe3321e792be854385243))
11
+
12
+ ## [0.15.7](https://github.com/blueraai/bluera-knowledge/compare/v0.15.6...v0.15.7) (2026-01-17)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * **deps:** downgrade LanceDB to 0.22.3 for Intel Mac compatibility ([36f8c03](https://github.com/blueraai/bluera-knowledge/commit/36f8c033f3da4587f1abeb1c1fdf44f65dc67da3))
18
+
5
19
  ## [0.15.6](https://github.com/blueraai/bluera-knowledge/compare/v0.15.4...v0.15.6) (2026-01-17)
6
20
 
7
21
 
@@ -2,18 +2,29 @@
2
2
 
3
3
  // src/mcp/bootstrap.ts
4
4
  import { execSync } from "child_process";
5
- import { appendFileSync, existsSync, mkdirSync } from "fs";
6
- import { homedir } from "os";
5
+ import {
6
+ appendFileSync,
7
+ chmodSync,
8
+ createReadStream,
9
+ createWriteStream,
10
+ existsSync,
11
+ mkdirSync,
12
+ readFileSync,
13
+ unlinkSync
14
+ } from "fs";
15
+ import { get } from "https";
16
+ import { arch, homedir, platform } from "os";
7
17
  import { dirname, join } from "path";
8
18
  import { fileURLToPath } from "url";
19
+ import { createGunzip } from "zlib";
9
20
  var logDir = join(homedir(), ".bluera", "bluera-knowledge", "logs");
10
21
  var logFile = join(logDir, "app.log");
11
- var log = (msg, data) => {
22
+ var log = (level, msg, data) => {
12
23
  try {
13
24
  mkdirSync(logDir, { recursive: true });
14
25
  const entry = {
15
26
  time: (/* @__PURE__ */ new Date()).toISOString(),
16
- level: "info",
27
+ level,
17
28
  module: "bootstrap",
18
29
  msg,
19
30
  ...data
@@ -26,8 +37,226 @@ var log = (msg, data) => {
26
37
  var __filename = fileURLToPath(import.meta.url);
27
38
  var __dirname = dirname(__filename);
28
39
  var pluginRoot = join(__dirname, "..", "..");
29
- log("Bootstrap starting", { pluginRoot });
30
- if (!existsSync(join(pluginRoot, "node_modules"))) {
40
+ var getVersion = () => {
41
+ try {
42
+ const pkg = JSON.parse(readFileSync(join(pluginRoot, "package.json"), "utf-8"));
43
+ if (typeof pkg === "object" && pkg !== null && "version" in pkg && typeof pkg.version === "string") {
44
+ return `v${pkg.version}`;
45
+ }
46
+ return "unknown";
47
+ } catch {
48
+ return "unknown";
49
+ }
50
+ };
51
+ var VERSION = getVersion();
52
+ var MANIFEST_URL = `https://github.com/blueraai/bluera-knowledge/releases/download/${VERSION}/manifest.json`;
53
+ function fetchJSON(url) {
54
+ return new Promise((resolve, reject) => {
55
+ const request = (targetUrl, redirectCount = 0) => {
56
+ if (redirectCount > 5) {
57
+ reject(new Error("Too many redirects"));
58
+ return;
59
+ }
60
+ get(targetUrl, { headers: { "User-Agent": "bluera-knowledge" } }, (res) => {
61
+ const location = res.headers.location;
62
+ if ((res.statusCode === 302 || res.statusCode === 301) && typeof location === "string" && location.length > 0) {
63
+ request(location, redirectCount + 1);
64
+ return;
65
+ }
66
+ const statusCode = res.statusCode ?? 0;
67
+ if (statusCode !== 200) {
68
+ reject(new Error(`HTTP ${String(statusCode)}`));
69
+ return;
70
+ }
71
+ let data = "";
72
+ res.on("data", (chunk) => data += chunk.toString());
73
+ res.on("end", () => {
74
+ try {
75
+ resolve(JSON.parse(data));
76
+ } catch (e) {
77
+ reject(e instanceof Error ? e : new Error(String(e)));
78
+ }
79
+ });
80
+ }).on("error", reject);
81
+ };
82
+ request(url);
83
+ });
84
+ }
85
+ function downloadFile(url, destPath) {
86
+ return new Promise((resolve, reject) => {
87
+ const request = (targetUrl, redirectCount = 0) => {
88
+ if (redirectCount > 10) {
89
+ reject(new Error("Too many redirects"));
90
+ return;
91
+ }
92
+ get(targetUrl, { headers: { "User-Agent": "bluera-knowledge" } }, (res) => {
93
+ const location = res.headers.location;
94
+ if ((res.statusCode === 302 || res.statusCode === 301) && typeof location === "string" && location.length > 0) {
95
+ request(location, redirectCount + 1);
96
+ return;
97
+ }
98
+ const statusCode = res.statusCode ?? 0;
99
+ if (statusCode !== 200) {
100
+ reject(new Error(`HTTP ${String(statusCode)}`));
101
+ return;
102
+ }
103
+ const file = createWriteStream(destPath);
104
+ res.pipe(file);
105
+ file.on("finish", () => {
106
+ file.close();
107
+ resolve();
108
+ });
109
+ file.on("error", (err) => {
110
+ file.close();
111
+ reject(err);
112
+ });
113
+ }).on("error", reject);
114
+ };
115
+ request(url);
116
+ });
117
+ }
118
+ function extractTar(tarPath, destDir) {
119
+ return new Promise((resolve, reject) => {
120
+ const gunzip = createGunzip();
121
+ const input = createReadStream(tarPath);
122
+ let buffer = Buffer.alloc(0);
123
+ let currentFile = null;
124
+ let bytesRemaining = 0;
125
+ let fileStream = null;
126
+ const parseHeader = (header) => {
127
+ if (header.every((b) => b === 0)) {
128
+ return null;
129
+ }
130
+ const name = header.subarray(0, 100).toString("utf-8").replace(/\0/g, "");
131
+ const mode = parseInt(header.subarray(100, 108).toString("utf-8").trim(), 8);
132
+ const size = parseInt(header.subarray(124, 136).toString("utf-8").trim(), 8);
133
+ const typeByte = header[156];
134
+ const typeFlag = typeByte !== void 0 ? String.fromCharCode(typeByte) : "0";
135
+ let type = "file";
136
+ if (typeFlag === "5") type = "directory";
137
+ else if (typeFlag === "2") type = "symlink";
138
+ return { name, size, type, mode: isNaN(mode) ? 420 : mode };
139
+ };
140
+ const processChunk = (chunk) => {
141
+ buffer = Buffer.concat([buffer, chunk]);
142
+ while (buffer.length > 0) {
143
+ if (currentFile === null) {
144
+ if (buffer.length < 512) break;
145
+ const header = buffer.subarray(0, 512);
146
+ buffer = buffer.subarray(512);
147
+ const parsed = parseHeader(header);
148
+ if (parsed === null) {
149
+ continue;
150
+ }
151
+ currentFile = parsed;
152
+ bytesRemaining = currentFile.size;
153
+ let filePath = currentFile.name;
154
+ if (filePath.startsWith("./")) {
155
+ filePath = filePath.slice(2);
156
+ }
157
+ if (filePath.length === 0 || filePath === ".") {
158
+ currentFile = null;
159
+ continue;
160
+ }
161
+ const fullPath = join(destDir, filePath);
162
+ if (currentFile.type === "directory") {
163
+ mkdirSync(fullPath, { recursive: true });
164
+ currentFile = null;
165
+ } else if (currentFile.type === "file" && bytesRemaining > 0) {
166
+ mkdirSync(dirname(fullPath), { recursive: true });
167
+ fileStream = createWriteStream(fullPath, {
168
+ mode: currentFile.mode
169
+ });
170
+ } else if (currentFile.type === "file" && bytesRemaining === 0) {
171
+ mkdirSync(dirname(fullPath), { recursive: true });
172
+ createWriteStream(fullPath, { mode: currentFile.mode }).close();
173
+ currentFile = null;
174
+ } else {
175
+ currentFile = null;
176
+ }
177
+ } else {
178
+ const toRead = Math.min(bytesRemaining, buffer.length);
179
+ if (fileStream !== null && toRead > 0) {
180
+ fileStream.write(buffer.subarray(0, toRead));
181
+ }
182
+ buffer = buffer.subarray(toRead);
183
+ bytesRemaining -= toRead;
184
+ if (bytesRemaining === 0) {
185
+ if (fileStream !== null) {
186
+ const stream = fileStream;
187
+ const file = currentFile;
188
+ stream.end(() => {
189
+ if ((file.mode & 73) !== 0) {
190
+ try {
191
+ const fullPath = join(
192
+ destDir,
193
+ file.name.startsWith("./") ? file.name.slice(2) : file.name
194
+ );
195
+ chmodSync(fullPath, file.mode);
196
+ } catch {
197
+ }
198
+ }
199
+ });
200
+ fileStream = null;
201
+ }
202
+ currentFile = null;
203
+ const padding = (512 - toRead % 512) % 512;
204
+ if (buffer.length >= padding) {
205
+ buffer = buffer.subarray(padding);
206
+ }
207
+ }
208
+ }
209
+ }
210
+ };
211
+ input.pipe(gunzip).on("data", processChunk).on("end", () => {
212
+ if (fileStream !== null) {
213
+ fileStream.end();
214
+ }
215
+ resolve();
216
+ }).on("error", reject);
217
+ });
218
+ }
219
+ function isManifest(value) {
220
+ return typeof value === "object" && value !== null && "version" in value && "platforms" in value && typeof value.platforms === "object";
221
+ }
222
+ async function downloadPrebuilt() {
223
+ const plat = platform();
224
+ const ar = arch();
225
+ const platformKey = `${plat}-${ar}`;
226
+ try {
227
+ log("info", "Checking for prebuilt binary", { platformKey, version: VERSION });
228
+ const manifestData = await fetchJSON(MANIFEST_URL);
229
+ if (!isManifest(manifestData)) {
230
+ log("info", "Invalid manifest format");
231
+ return false;
232
+ }
233
+ const platformInfo = manifestData.platforms[platformKey];
234
+ if (platformInfo === void 0) {
235
+ log("info", "No prebuilt binary available for platform", { platformKey });
236
+ return false;
237
+ }
238
+ log("info", "Downloading prebuilt binary", { url: platformInfo.url });
239
+ const tmpDir = join(homedir(), ".bluera", "tmp");
240
+ mkdirSync(tmpDir, { recursive: true });
241
+ const tarPath = join(tmpDir, `bluera-knowledge-${platformKey}.tar.gz`);
242
+ await downloadFile(platformInfo.url, tarPath);
243
+ log("info", "Download complete, extracting", { tarPath, destDir: pluginRoot });
244
+ await extractTar(tarPath, pluginRoot);
245
+ try {
246
+ unlinkSync(tarPath);
247
+ } catch {
248
+ }
249
+ log("info", "Prebuilt binary installed successfully");
250
+ return true;
251
+ } catch (err) {
252
+ const message = err instanceof Error ? err.message : String(err);
253
+ log("debug", "Prebuilt download failed, will use package manager", {
254
+ error: message
255
+ });
256
+ return false;
257
+ }
258
+ }
259
+ function installWithPackageManager() {
31
260
  const hasBun = (() => {
32
261
  try {
33
262
  execSync("which bun", { stdio: "ignore" });
@@ -37,19 +266,33 @@ if (!existsSync(join(pluginRoot, "node_modules"))) {
37
266
  }
38
267
  })();
39
268
  const cmd = hasBun ? "bun install --frozen-lockfile" : "npm ci --silent";
40
- log("Dependencies missing, installing", { hasBun, cmd });
269
+ log("info", "Installing dependencies with package manager", { hasBun, cmd });
41
270
  execSync(cmd, { cwd: pluginRoot, stdio: "inherit" });
42
- log("Dependencies installed");
43
- } else {
44
- log("Dependencies already installed");
271
+ log("info", "Dependencies installed via package manager");
272
+ }
273
+ async function ensureDependencies() {
274
+ if (existsSync(join(pluginRoot, "node_modules"))) {
275
+ log("info", "Dependencies already installed");
276
+ return;
277
+ }
278
+ const prebuiltSuccess = await downloadPrebuilt();
279
+ if (prebuiltSuccess) {
280
+ return;
281
+ }
282
+ installWithPackageManager();
45
283
  }
46
- log("Loading server module");
284
+ log("info", "Bootstrap starting", { pluginRoot, version: VERSION });
285
+ await ensureDependencies();
286
+ log("info", "Loading server module");
47
287
  var { runMCPServer } = await import("./server.js");
48
288
  var projectRoot = process.env["PROJECT_ROOT"];
49
289
  if (projectRoot === void 0) {
50
290
  throw new Error("PROJECT_ROOT environment variable is required");
51
291
  }
52
- log("Starting MCP server", { projectRoot, dataDir: process.env["DATA_DIR"] });
292
+ log("info", "Starting MCP server", {
293
+ projectRoot,
294
+ dataDir: process.env["DATA_DIR"]
295
+ });
53
296
  await runMCPServer({
54
297
  dataDir: process.env["DATA_DIR"],
55
298
  config: process.env["CONFIG_PATH"],
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/mcp/bootstrap.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * MCP Server Bootstrap - installs dependencies before starting server.\n *\n * Uses only Node.js built-ins (no external dependencies required).\n * Self-locates plugin root via import.meta.url (doesn't rely on CLAUDE_PLUGIN_ROOT).\n *\n * This solves two issues:\n * 1. Bash path resolution broken - ${CLAUDE_PLUGIN_ROOT:-.} not expanded for bash\n * 2. Dependencies not installed - plugins installed via git clone without npm install\n *\n * IMPORTANT: MCP servers must NOT log to stderr - Claude Code treats stderr output\n * as an error and may mark the MCP server as failed. All logging goes to file.\n */\nimport { execSync } from 'node:child_process';\nimport { appendFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n// Logging helper - writes to file since MCP servers must NOT use stderr\n// (Claude Code treats stderr as error and may fail the server)\n// JSON format matches pino output for consistency\nconst logDir = join(homedir(), '.bluera', 'bluera-knowledge', 'logs');\nconst logFile = join(logDir, 'app.log');\n\nconst log = (msg: string, data?: Record<string, unknown>): void => {\n try {\n mkdirSync(logDir, { recursive: true });\n const entry = {\n time: new Date().toISOString(),\n level: 'info',\n module: 'bootstrap',\n msg,\n ...data,\n };\n appendFileSync(logFile, `${JSON.stringify(entry)}\\n`);\n } catch {\n // Silently fail - we cannot use stderr for MCP servers\n }\n};\n\n// Self-locate plugin root from this file's path\n// dist/mcp/bootstrap.js -> plugin root (two directories up)\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst pluginRoot = join(__dirname, '..', '..');\n\nlog('Bootstrap starting', { pluginRoot });\n\n// Install dependencies if node_modules is missing\nif (!existsSync(join(pluginRoot, 'node_modules'))) {\n const hasBun = ((): boolean => {\n try {\n execSync('which bun', { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n })();\n\n const cmd = hasBun ? 'bun install --frozen-lockfile' : 'npm ci --silent';\n log('Dependencies missing, installing', { hasBun, cmd });\n execSync(cmd, { cwd: pluginRoot, stdio: 'inherit' });\n log('Dependencies installed');\n} else {\n log('Dependencies already installed');\n}\n\n// Now that dependencies are installed, import and run the server\n// Dynamic import required because @modelcontextprotocol/sdk wouldn't be available before install\nlog('Loading server module');\nconst { runMCPServer } = await import('./server.js');\n\nconst projectRoot = process.env['PROJECT_ROOT'];\nif (projectRoot === undefined) {\n throw new Error('PROJECT_ROOT environment variable is required');\n}\n\nlog('Starting MCP server', { projectRoot, dataDir: process.env['DATA_DIR'] });\n\nawait runMCPServer({\n dataDir: process.env['DATA_DIR'],\n config: process.env['CONFIG_PATH'],\n projectRoot,\n});\n"],"mappings":";;;AAcA,SAAS,gBAAgB;AACzB,SAAS,gBAAgB,YAAY,iBAAiB;AACtD,SAAS,eAAe;AACxB,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAK9B,IAAM,SAAS,KAAK,QAAQ,GAAG,WAAW,oBAAoB,MAAM;AACpE,IAAM,UAAU,KAAK,QAAQ,SAAS;AAEtC,IAAM,MAAM,CAAC,KAAa,SAAyC;AACjE,MAAI;AACF,cAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AACrC,UAAM,QAAQ;AAAA,MACZ,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC7B,OAAO;AAAA,MACP,QAAQ;AAAA,MACR;AAAA,MACA,GAAG;AAAA,IACL;AACA,mBAAe,SAAS,GAAG,KAAK,UAAU,KAAK,CAAC;AAAA,CAAI;AAAA,EACtD,QAAQ;AAAA,EAER;AACF;AAIA,IAAM,aAAa,cAAc,YAAY,GAAG;AAChD,IAAM,YAAY,QAAQ,UAAU;AACpC,IAAM,aAAa,KAAK,WAAW,MAAM,IAAI;AAE7C,IAAI,sBAAsB,EAAE,WAAW,CAAC;AAGxC,IAAI,CAAC,WAAW,KAAK,YAAY,cAAc,CAAC,GAAG;AACjD,QAAM,UAAU,MAAe;AAC7B,QAAI;AACF,eAAS,aAAa,EAAE,OAAO,SAAS,CAAC;AACzC,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,GAAG;AAEH,QAAM,MAAM,SAAS,kCAAkC;AACvD,MAAI,oCAAoC,EAAE,QAAQ,IAAI,CAAC;AACvD,WAAS,KAAK,EAAE,KAAK,YAAY,OAAO,UAAU,CAAC;AACnD,MAAI,wBAAwB;AAC9B,OAAO;AACL,MAAI,gCAAgC;AACtC;AAIA,IAAI,uBAAuB;AAC3B,IAAM,EAAE,aAAa,IAAI,MAAM,OAAO,aAAa;AAEnD,IAAM,cAAc,QAAQ,IAAI,cAAc;AAC9C,IAAI,gBAAgB,QAAW;AAC7B,QAAM,IAAI,MAAM,+CAA+C;AACjE;AAEA,IAAI,uBAAuB,EAAE,aAAa,SAAS,QAAQ,IAAI,UAAU,EAAE,CAAC;AAE5E,MAAM,aAAa;AAAA,EACjB,SAAS,QAAQ,IAAI,UAAU;AAAA,EAC/B,QAAQ,QAAQ,IAAI,aAAa;AAAA,EACjC;AACF,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../src/mcp/bootstrap.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * MCP Server Bootstrap - installs dependencies before starting server.\n *\n * Uses only Node.js built-ins (no external dependencies required).\n * Self-locates plugin root via import.meta.url (doesn't rely on CLAUDE_PLUGIN_ROOT).\n *\n * Dependency installation strategy:\n * 1. Fast path: node_modules already exists → skip\n * 2. Try prebuilt: Download platform-specific tarball from GitHub release\n * 3. Package manager: Run bun install or npm ci if prebuilt unavailable\n *\n * IMPORTANT: MCP servers must NOT log to stderr - Claude Code treats stderr output\n * as an error and may mark the MCP server as failed. All logging goes to file.\n */\nimport { execSync } from 'node:child_process';\nimport {\n appendFileSync,\n chmodSync,\n createReadStream,\n createWriteStream,\n existsSync,\n mkdirSync,\n readFileSync,\n unlinkSync,\n} from 'node:fs';\nimport { get } from 'node:https';\nimport { arch, homedir, platform } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { createGunzip } from 'node:zlib';\n\n// Logging helper - writes to file since MCP servers must NOT use stderr\n// (Claude Code treats stderr as error and may fail the server)\n// JSON format matches pino output for consistency\nconst logDir = join(homedir(), '.bluera', 'bluera-knowledge', 'logs');\nconst logFile = join(logDir, 'app.log');\n\nconst log = (\n level: 'info' | 'error' | 'debug',\n msg: string,\n data?: Record<string, unknown>\n): void => {\n try {\n mkdirSync(logDir, { recursive: true });\n const entry = {\n time: new Date().toISOString(),\n level,\n module: 'bootstrap',\n msg,\n ...data,\n };\n appendFileSync(logFile, `${JSON.stringify(entry)}\\n`);\n } catch {\n // Silently fail - we cannot use stderr for MCP servers\n }\n};\n\n// Self-locate plugin root from this file's path\n// dist/mcp/bootstrap.js -> plugin root (two directories up)\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst pluginRoot = join(__dirname, '..', '..');\n\n// Get version from package.json\nconst getVersion = (): string => {\n try {\n const pkg: unknown = JSON.parse(readFileSync(join(pluginRoot, 'package.json'), 'utf-8'));\n if (\n typeof pkg === 'object' &&\n pkg !== null &&\n 'version' in pkg &&\n typeof pkg.version === 'string'\n ) {\n return `v${pkg.version}`;\n }\n return 'unknown';\n } catch {\n return 'unknown';\n }\n};\n\nconst VERSION = getVersion();\nconst MANIFEST_URL = `https://github.com/blueraai/bluera-knowledge/releases/download/${VERSION}/manifest.json`;\n\n/**\n * Fetch JSON from URL with redirect handling.\n * Uses only Node.js built-ins.\n */\nfunction fetchJSON(url: string): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const request = (targetUrl: string, redirectCount = 0): void => {\n if (redirectCount > 5) {\n reject(new Error('Too many redirects'));\n return;\n }\n\n get(targetUrl, { headers: { 'User-Agent': 'bluera-knowledge' } }, (res) => {\n // Follow redirects\n const location = res.headers.location;\n if (\n (res.statusCode === 302 || res.statusCode === 301) &&\n typeof location === 'string' &&\n location.length > 0\n ) {\n request(location, redirectCount + 1);\n return;\n }\n const statusCode = res.statusCode ?? 0;\n if (statusCode !== 200) {\n reject(new Error(`HTTP ${String(statusCode)}`));\n return;\n }\n let data = '';\n res.on('data', (chunk: Buffer) => (data += chunk.toString()));\n res.on('end', () => {\n try {\n resolve(JSON.parse(data));\n } catch (e) {\n reject(e instanceof Error ? e : new Error(String(e)));\n }\n });\n }).on('error', reject);\n };\n request(url);\n });\n}\n\n/**\n * Download file from URL to destination path.\n * Uses only Node.js built-ins.\n */\nfunction downloadFile(url: string, destPath: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const request = (targetUrl: string, redirectCount = 0): void => {\n if (redirectCount > 10) {\n reject(new Error('Too many redirects'));\n return;\n }\n\n get(targetUrl, { headers: { 'User-Agent': 'bluera-knowledge' } }, (res) => {\n const location = res.headers.location;\n if (\n (res.statusCode === 302 || res.statusCode === 301) &&\n typeof location === 'string' &&\n location.length > 0\n ) {\n request(location, redirectCount + 1);\n return;\n }\n const statusCode = res.statusCode ?? 0;\n if (statusCode !== 200) {\n reject(new Error(`HTTP ${String(statusCode)}`));\n return;\n }\n const file = createWriteStream(destPath);\n res.pipe(file);\n file.on('finish', () => {\n file.close();\n resolve();\n });\n file.on('error', (err) => {\n file.close();\n reject(err);\n });\n }).on('error', reject);\n };\n request(url);\n });\n}\n\n/**\n * Simple tar parser using Node.js built-ins.\n *\n * TAR format:\n * - 512-byte header blocks\n * - File data follows, padded to 512-byte boundary\n * - Two empty 512-byte blocks at end\n */\nfunction extractTar(tarPath: string, destDir: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const gunzip = createGunzip();\n const input = createReadStream(tarPath);\n\n let buffer = Buffer.alloc(0);\n let currentFile: {\n name: string;\n size: number;\n type: string;\n mode: number;\n } | null = null;\n let bytesRemaining = 0;\n let fileStream: ReturnType<typeof createWriteStream> | null = null;\n\n const parseHeader = (\n header: Buffer\n ): { name: string; size: number; type: string; mode: number } | null => {\n // Check for empty block (end of archive)\n if (header.every((b) => b === 0)) {\n return null;\n }\n\n // Parse tar header fields\n const name = header.subarray(0, 100).toString('utf-8').replace(/\\0/g, '');\n const mode = parseInt(header.subarray(100, 108).toString('utf-8').trim(), 8);\n const size = parseInt(header.subarray(124, 136).toString('utf-8').trim(), 8);\n const typeByte = header[156];\n const typeFlag = typeByte !== undefined ? String.fromCharCode(typeByte) : '0';\n\n // Type: '0' or '' = file, '5' = directory, '2' = symlink\n let type = 'file';\n if (typeFlag === '5') type = 'directory';\n else if (typeFlag === '2') type = 'symlink';\n\n return { name, size, type, mode: isNaN(mode) ? 0o644 : mode };\n };\n\n const processChunk = (chunk: Buffer): void => {\n buffer = Buffer.concat([buffer, chunk]);\n\n while (buffer.length > 0) {\n if (currentFile === null) {\n // Need to read a header\n if (buffer.length < 512) break;\n\n const header = buffer.subarray(0, 512);\n buffer = buffer.subarray(512);\n\n const parsed = parseHeader(header);\n if (parsed === null) {\n // End of archive\n continue;\n }\n\n currentFile = parsed;\n bytesRemaining = currentFile.size;\n\n // Skip ./ prefix and handle path\n let filePath = currentFile.name;\n if (filePath.startsWith('./')) {\n filePath = filePath.slice(2);\n }\n if (filePath.length === 0 || filePath === '.') {\n currentFile = null;\n continue;\n }\n\n const fullPath = join(destDir, filePath);\n\n if (currentFile.type === 'directory') {\n mkdirSync(fullPath, { recursive: true });\n currentFile = null;\n } else if (currentFile.type === 'file' && bytesRemaining > 0) {\n mkdirSync(dirname(fullPath), { recursive: true });\n fileStream = createWriteStream(fullPath, {\n mode: currentFile.mode,\n });\n } else if (currentFile.type === 'file' && bytesRemaining === 0) {\n // Empty file\n mkdirSync(dirname(fullPath), { recursive: true });\n createWriteStream(fullPath, { mode: currentFile.mode }).close();\n currentFile = null;\n } else {\n // Skip symlinks and other types\n currentFile = null;\n }\n } else {\n // Reading file content\n const toRead = Math.min(bytesRemaining, buffer.length);\n if (fileStream !== null && toRead > 0) {\n fileStream.write(buffer.subarray(0, toRead));\n }\n buffer = buffer.subarray(toRead);\n bytesRemaining -= toRead;\n\n if (bytesRemaining === 0) {\n if (fileStream !== null) {\n const stream = fileStream;\n const file = currentFile;\n stream.end(() => {\n // Set executable bit for scripts\n if ((file.mode & 0o111) !== 0) {\n try {\n const fullPath = join(\n destDir,\n file.name.startsWith('./') ? file.name.slice(2) : file.name\n );\n chmodSync(fullPath, file.mode);\n } catch {\n // Ignore chmod errors\n }\n }\n });\n fileStream = null;\n }\n currentFile = null;\n\n // Skip padding to 512-byte boundary\n const padding = (512 - (toRead % 512)) % 512;\n if (buffer.length >= padding) {\n buffer = buffer.subarray(padding);\n }\n }\n }\n }\n };\n\n input\n .pipe(gunzip)\n .on('data', processChunk)\n .on('end', () => {\n if (fileStream !== null) {\n fileStream.end();\n }\n resolve();\n })\n .on('error', reject);\n });\n}\n\ninterface PlatformInfo {\n url: string;\n sha256: string;\n}\n\ninterface Manifest {\n version: string;\n platforms: Record<string, PlatformInfo>;\n}\n\nfunction isManifest(value: unknown): value is Manifest {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'version' in value &&\n 'platforms' in value &&\n typeof value.platforms === 'object'\n );\n}\n\n/**\n * Try to download and extract prebuilt binary for current platform.\n * Returns true if successful, false if prebuilt is not available.\n */\nasync function downloadPrebuilt(): Promise<boolean> {\n const plat = platform(); // 'darwin', 'linux', 'win32'\n const ar = arch(); // 'arm64', 'x64'\n const platformKey = `${plat}-${ar}`;\n\n try {\n log('info', 'Checking for prebuilt binary', { platformKey, version: VERSION });\n\n const manifestData = await fetchJSON(MANIFEST_URL);\n if (!isManifest(manifestData)) {\n log('info', 'Invalid manifest format');\n return false;\n }\n\n const platformInfo = manifestData.platforms[platformKey];\n if (platformInfo === undefined) {\n log('info', 'No prebuilt binary available for platform', { platformKey });\n return false;\n }\n\n log('info', 'Downloading prebuilt binary', { url: platformInfo.url });\n const tmpDir = join(homedir(), '.bluera', 'tmp');\n mkdirSync(tmpDir, { recursive: true });\n const tarPath = join(tmpDir, `bluera-knowledge-${platformKey}.tar.gz`);\n\n await downloadFile(platformInfo.url, tarPath);\n log('info', 'Download complete, extracting', { tarPath, destDir: pluginRoot });\n\n await extractTar(tarPath, pluginRoot);\n\n // Cleanup temp file\n try {\n unlinkSync(tarPath);\n } catch {\n // Ignore cleanup errors\n }\n\n log('info', 'Prebuilt binary installed successfully');\n return true;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n log('debug', 'Prebuilt download failed, will use package manager', {\n error: message,\n });\n return false;\n }\n}\n\n/**\n * Install dependencies using bun or npm.\n */\nfunction installWithPackageManager(): void {\n const hasBun = ((): boolean => {\n try {\n execSync('which bun', { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n })();\n\n const cmd = hasBun ? 'bun install --frozen-lockfile' : 'npm ci --silent';\n log('info', 'Installing dependencies with package manager', { hasBun, cmd });\n execSync(cmd, { cwd: pluginRoot, stdio: 'inherit' });\n log('info', 'Dependencies installed via package manager');\n}\n\n/**\n * Ensure dependencies are available.\n * Tries prebuilt first, falls back to package manager.\n */\nasync function ensureDependencies(): Promise<void> {\n // Fast path: already installed\n if (existsSync(join(pluginRoot, 'node_modules'))) {\n log('info', 'Dependencies already installed');\n return;\n }\n\n // Try prebuilt binary first (faster, no npm install needed)\n const prebuiltSuccess = await downloadPrebuilt();\n if (prebuiltSuccess) {\n return;\n }\n\n // Prebuilt not available, use package manager instead\n installWithPackageManager();\n}\n\n// Main entry point\nlog('info', 'Bootstrap starting', { pluginRoot, version: VERSION });\n\nawait ensureDependencies();\n\n// Now that dependencies are installed, import and run the server\n// Dynamic import required because @modelcontextprotocol/sdk wouldn't be available before install\nlog('info', 'Loading server module');\nconst { runMCPServer } = await import('./server.js');\n\nconst projectRoot = process.env['PROJECT_ROOT'];\nif (projectRoot === undefined) {\n throw new Error('PROJECT_ROOT environment variable is required');\n}\n\nlog('info', 'Starting MCP server', {\n projectRoot,\n dataDir: process.env['DATA_DIR'],\n});\n\nawait runMCPServer({\n dataDir: process.env['DATA_DIR'],\n config: process.env['CONFIG_PATH'],\n projectRoot,\n});\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bluera-knowledge",
3
- "version": "0.15.6",
3
+ "version": "0.16.0",
4
4
  "description": "CLI tool for managing knowledge stores with semantic search",
5
5
  "type": "module",
6
6
  "bin": {
@@ -105,9 +105,9 @@
105
105
  "@extractus/article-extractor": "^8.0.20",
106
106
  "@hono/node-server": "^1.19.7",
107
107
  "@huggingface/transformers": "^3.8.1",
108
- "@lancedb/lancedb": "^0.23.0",
108
+ "@lancedb/lancedb": "0.22.3",
109
109
  "@modelcontextprotocol/sdk": "^1.25.2",
110
- "apache-arrow": "^21.1.0",
110
+ "apache-arrow": "^18.1.0",
111
111
  "axios": "^1.13.2",
112
112
  "chalk": "^5.6.2",
113
113
  "cheerio": "^1.1.2",