bluera-knowledge 0.14.8 → 0.15.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/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +13 -0
- package/dist/{chunk-SWHYQLSJ.js → chunk-DX5I6U5X.js} +36 -231
- package/dist/chunk-DX5I6U5X.js.map +1 -0
- package/dist/{chunk-TGMFSPTQ.js → chunk-OMC3RAZT.js} +2 -2
- package/dist/{chunk-5VW5DNW4.js → chunk-WYZQUKUD.js} +523 -106
- package/dist/chunk-WYZQUKUD.js.map +1 -0
- package/dist/index.js +7 -7
- package/dist/mcp/server.d.ts +859 -1
- package/dist/mcp/server.js +2 -2
- package/dist/workers/background-worker-cli.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-5VW5DNW4.js.map +0 -1
- package/dist/chunk-SWHYQLSJ.js.map +0 -1
- /package/dist/{chunk-TGMFSPTQ.js.map → chunk-OMC3RAZT.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
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.15.0](https://github.com/blueraai/bluera-knowledge/compare/v0.14.8...v0.15.0) (2026-01-16)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **services:** wire up StoreDefinitionService and GitignoreService ([4d52052](https://github.com/blueraai/bluera-knowledge/commit/4d520523f52b1424f3bf523ad3596227add8fdb9))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **gitignore:** correct patterns to actually track stores.config.json ([7e0dd34](https://github.com/blueraai/bluera-knowledge/commit/7e0dd342610b45f59237ede36c14b5ed124943cd))
|
|
16
|
+
* **mcp:** use default value syntax for dual-mode MCP support ([4f62f5c](https://github.com/blueraai/bluera-knowledge/commit/4f62f5cfe67b24758ba2b198730a674f4b3055d7))
|
|
17
|
+
|
|
5
18
|
## [0.14.8](https://github.com/blueraai/bluera-knowledge/compare/v0.14.7...v0.14.8) (2026-01-16)
|
|
6
19
|
|
|
7
20
|
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AdapterRegistry,
|
|
3
3
|
JobService,
|
|
4
|
-
|
|
4
|
+
StoreDefinitionService,
|
|
5
|
+
createLazyServices,
|
|
5
6
|
createLogger,
|
|
6
|
-
createServices,
|
|
7
7
|
createStoreId,
|
|
8
8
|
destroyServices,
|
|
9
|
+
isFileStoreDefinition,
|
|
10
|
+
isRepoStoreDefinition,
|
|
11
|
+
isWebStoreDefinition,
|
|
9
12
|
summarizePayload
|
|
10
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-WYZQUKUD.js";
|
|
11
14
|
|
|
12
15
|
// src/mcp/server.ts
|
|
13
16
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -1239,213 +1242,7 @@ var storeCommands = [
|
|
|
1239
1242
|
];
|
|
1240
1243
|
|
|
1241
1244
|
// src/mcp/commands/sync.commands.ts
|
|
1242
|
-
import { z as z7 } from "zod";
|
|
1243
|
-
|
|
1244
|
-
// src/services/store-definition.service.ts
|
|
1245
|
-
import { readFile, writeFile, mkdir, access } from "fs/promises";
|
|
1246
|
-
import { dirname, resolve, isAbsolute, join as join2 } from "path";
|
|
1247
|
-
|
|
1248
|
-
// src/types/store-definition.ts
|
|
1249
1245
|
import { z as z6 } from "zod";
|
|
1250
|
-
var BaseStoreDefinitionSchema = z6.object({
|
|
1251
|
-
name: z6.string().min(1, "Store name is required"),
|
|
1252
|
-
description: z6.string().optional(),
|
|
1253
|
-
tags: z6.array(z6.string()).optional()
|
|
1254
|
-
});
|
|
1255
|
-
var FileStoreDefinitionSchema = BaseStoreDefinitionSchema.extend({
|
|
1256
|
-
type: z6.literal("file"),
|
|
1257
|
-
path: z6.string().min(1, "Path is required for file stores")
|
|
1258
|
-
});
|
|
1259
|
-
var RepoStoreDefinitionSchema = BaseStoreDefinitionSchema.extend({
|
|
1260
|
-
type: z6.literal("repo"),
|
|
1261
|
-
url: z6.url("Valid URL is required for repo stores"),
|
|
1262
|
-
branch: z6.string().optional(),
|
|
1263
|
-
depth: z6.number().int().positive("Depth must be a positive integer").optional()
|
|
1264
|
-
});
|
|
1265
|
-
var WebStoreDefinitionSchema = BaseStoreDefinitionSchema.extend({
|
|
1266
|
-
type: z6.literal("web"),
|
|
1267
|
-
url: z6.url("Valid URL is required for web stores"),
|
|
1268
|
-
depth: z6.number().int().min(0, "Depth must be non-negative").default(1),
|
|
1269
|
-
maxPages: z6.number().int().positive("maxPages must be a positive integer").optional(),
|
|
1270
|
-
crawlInstructions: z6.string().optional(),
|
|
1271
|
-
extractInstructions: z6.string().optional()
|
|
1272
|
-
});
|
|
1273
|
-
var StoreDefinitionSchema = z6.discriminatedUnion("type", [
|
|
1274
|
-
FileStoreDefinitionSchema,
|
|
1275
|
-
RepoStoreDefinitionSchema,
|
|
1276
|
-
WebStoreDefinitionSchema
|
|
1277
|
-
]);
|
|
1278
|
-
var StoreDefinitionsConfigSchema = z6.object({
|
|
1279
|
-
version: z6.literal(1),
|
|
1280
|
-
stores: z6.array(StoreDefinitionSchema)
|
|
1281
|
-
});
|
|
1282
|
-
function isFileStoreDefinition(def) {
|
|
1283
|
-
return def.type === "file";
|
|
1284
|
-
}
|
|
1285
|
-
function isRepoStoreDefinition(def) {
|
|
1286
|
-
return def.type === "repo";
|
|
1287
|
-
}
|
|
1288
|
-
function isWebStoreDefinition(def) {
|
|
1289
|
-
return def.type === "web";
|
|
1290
|
-
}
|
|
1291
|
-
var DEFAULT_STORE_DEFINITIONS_CONFIG = {
|
|
1292
|
-
version: 1,
|
|
1293
|
-
stores: []
|
|
1294
|
-
};
|
|
1295
|
-
|
|
1296
|
-
// src/services/store-definition.service.ts
|
|
1297
|
-
async function fileExists(path2) {
|
|
1298
|
-
try {
|
|
1299
|
-
await access(path2);
|
|
1300
|
-
return true;
|
|
1301
|
-
} catch {
|
|
1302
|
-
return false;
|
|
1303
|
-
}
|
|
1304
|
-
}
|
|
1305
|
-
var StoreDefinitionService = class {
|
|
1306
|
-
configPath;
|
|
1307
|
-
projectRoot;
|
|
1308
|
-
config = null;
|
|
1309
|
-
constructor(projectRoot) {
|
|
1310
|
-
this.projectRoot = projectRoot ?? ProjectRootService.resolve();
|
|
1311
|
-
this.configPath = join2(this.projectRoot, ".bluera/bluera-knowledge/stores.config.json");
|
|
1312
|
-
}
|
|
1313
|
-
/**
|
|
1314
|
-
* Load store definitions from config file.
|
|
1315
|
-
* Returns empty config if file doesn't exist.
|
|
1316
|
-
* Throws on parse/validation errors (fail fast per CLAUDE.md).
|
|
1317
|
-
*/
|
|
1318
|
-
async load() {
|
|
1319
|
-
if (this.config !== null) {
|
|
1320
|
-
return this.config;
|
|
1321
|
-
}
|
|
1322
|
-
const exists = await fileExists(this.configPath);
|
|
1323
|
-
if (!exists) {
|
|
1324
|
-
this.config = {
|
|
1325
|
-
...DEFAULT_STORE_DEFINITIONS_CONFIG,
|
|
1326
|
-
stores: [...DEFAULT_STORE_DEFINITIONS_CONFIG.stores]
|
|
1327
|
-
};
|
|
1328
|
-
return this.config;
|
|
1329
|
-
}
|
|
1330
|
-
const content = await readFile(this.configPath, "utf-8");
|
|
1331
|
-
let parsed;
|
|
1332
|
-
try {
|
|
1333
|
-
parsed = JSON.parse(content);
|
|
1334
|
-
} catch (error) {
|
|
1335
|
-
throw new Error(
|
|
1336
|
-
`Failed to parse store definitions at ${this.configPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
1337
|
-
);
|
|
1338
|
-
}
|
|
1339
|
-
const result = StoreDefinitionsConfigSchema.safeParse(parsed);
|
|
1340
|
-
if (!result.success) {
|
|
1341
|
-
throw new Error(`Invalid store definitions at ${this.configPath}: ${result.error.message}`);
|
|
1342
|
-
}
|
|
1343
|
-
this.config = result.data;
|
|
1344
|
-
return this.config;
|
|
1345
|
-
}
|
|
1346
|
-
/**
|
|
1347
|
-
* Save store definitions to config file.
|
|
1348
|
-
*/
|
|
1349
|
-
async save(config) {
|
|
1350
|
-
await mkdir(dirname(this.configPath), { recursive: true });
|
|
1351
|
-
await writeFile(this.configPath, JSON.stringify(config, null, 2));
|
|
1352
|
-
this.config = config;
|
|
1353
|
-
}
|
|
1354
|
-
/**
|
|
1355
|
-
* Add a store definition.
|
|
1356
|
-
* Throws if a definition with the same name already exists.
|
|
1357
|
-
*/
|
|
1358
|
-
async addDefinition(definition) {
|
|
1359
|
-
const config = await this.load();
|
|
1360
|
-
const existing = config.stores.find((s) => s.name === definition.name);
|
|
1361
|
-
if (existing !== void 0) {
|
|
1362
|
-
throw new Error(`Store definition "${definition.name}" already exists`);
|
|
1363
|
-
}
|
|
1364
|
-
config.stores.push(definition);
|
|
1365
|
-
await this.save(config);
|
|
1366
|
-
}
|
|
1367
|
-
/**
|
|
1368
|
-
* Remove a store definition by name.
|
|
1369
|
-
* Returns true if removed, false if not found.
|
|
1370
|
-
*/
|
|
1371
|
-
async removeDefinition(name) {
|
|
1372
|
-
const config = await this.load();
|
|
1373
|
-
const index = config.stores.findIndex((s) => s.name === name);
|
|
1374
|
-
if (index === -1) {
|
|
1375
|
-
return false;
|
|
1376
|
-
}
|
|
1377
|
-
config.stores.splice(index, 1);
|
|
1378
|
-
await this.save(config);
|
|
1379
|
-
return true;
|
|
1380
|
-
}
|
|
1381
|
-
/**
|
|
1382
|
-
* Update an existing store definition.
|
|
1383
|
-
* Only updates the provided fields, preserving others.
|
|
1384
|
-
* Throws if definition not found.
|
|
1385
|
-
*/
|
|
1386
|
-
async updateDefinition(name, updates) {
|
|
1387
|
-
const config = await this.load();
|
|
1388
|
-
const index = config.stores.findIndex((s) => s.name === name);
|
|
1389
|
-
if (index === -1) {
|
|
1390
|
-
throw new Error(`Store definition "${name}" not found`);
|
|
1391
|
-
}
|
|
1392
|
-
const existing = config.stores[index];
|
|
1393
|
-
if (existing === void 0) {
|
|
1394
|
-
throw new Error(`Store definition "${name}" not found at index ${String(index)}`);
|
|
1395
|
-
}
|
|
1396
|
-
if (updates.description !== void 0) {
|
|
1397
|
-
existing.description = updates.description;
|
|
1398
|
-
}
|
|
1399
|
-
if (updates.tags !== void 0) {
|
|
1400
|
-
existing.tags = updates.tags;
|
|
1401
|
-
}
|
|
1402
|
-
await this.save(config);
|
|
1403
|
-
}
|
|
1404
|
-
/**
|
|
1405
|
-
* Get a store definition by name.
|
|
1406
|
-
* Returns undefined if not found.
|
|
1407
|
-
*/
|
|
1408
|
-
async getByName(name) {
|
|
1409
|
-
const config = await this.load();
|
|
1410
|
-
return config.stores.find((s) => s.name === name);
|
|
1411
|
-
}
|
|
1412
|
-
/**
|
|
1413
|
-
* Check if any definitions exist.
|
|
1414
|
-
*/
|
|
1415
|
-
async hasDefinitions() {
|
|
1416
|
-
const config = await this.load();
|
|
1417
|
-
return config.stores.length > 0;
|
|
1418
|
-
}
|
|
1419
|
-
/**
|
|
1420
|
-
* Resolve a file store path relative to project root.
|
|
1421
|
-
*/
|
|
1422
|
-
resolvePath(path2) {
|
|
1423
|
-
if (isAbsolute(path2)) {
|
|
1424
|
-
return path2;
|
|
1425
|
-
}
|
|
1426
|
-
return resolve(this.projectRoot, path2);
|
|
1427
|
-
}
|
|
1428
|
-
/**
|
|
1429
|
-
* Get the config file path.
|
|
1430
|
-
*/
|
|
1431
|
-
getConfigPath() {
|
|
1432
|
-
return this.configPath;
|
|
1433
|
-
}
|
|
1434
|
-
/**
|
|
1435
|
-
* Get the project root.
|
|
1436
|
-
*/
|
|
1437
|
-
getProjectRoot() {
|
|
1438
|
-
return this.projectRoot;
|
|
1439
|
-
}
|
|
1440
|
-
/**
|
|
1441
|
-
* Clear the cached config (useful for testing).
|
|
1442
|
-
*/
|
|
1443
|
-
clearCache() {
|
|
1444
|
-
this.config = null;
|
|
1445
|
-
}
|
|
1446
|
-
};
|
|
1447
|
-
|
|
1448
|
-
// src/mcp/commands/sync.commands.ts
|
|
1449
1246
|
async function handleStoresSync(args, context) {
|
|
1450
1247
|
const { services, options } = context;
|
|
1451
1248
|
const projectRoot = options.projectRoot;
|
|
@@ -1605,10 +1402,10 @@ var syncCommands = [
|
|
|
1605
1402
|
{
|
|
1606
1403
|
name: "stores:sync",
|
|
1607
1404
|
description: "Sync stores from definitions config (bootstrap on fresh clone)",
|
|
1608
|
-
argsSchema:
|
|
1609
|
-
prune:
|
|
1610
|
-
dryRun:
|
|
1611
|
-
reindex:
|
|
1405
|
+
argsSchema: z6.object({
|
|
1406
|
+
prune: z6.boolean().optional().describe("Remove stores not in definitions"),
|
|
1407
|
+
dryRun: z6.boolean().optional().describe("Show what would happen without making changes"),
|
|
1408
|
+
reindex: z6.boolean().optional().describe("Re-index existing stores after sync")
|
|
1612
1409
|
}),
|
|
1613
1410
|
handler: (args, context) => {
|
|
1614
1411
|
const syncArgs = {};
|
|
@@ -1627,13 +1424,13 @@ var syncCommands = [
|
|
|
1627
1424
|
];
|
|
1628
1425
|
|
|
1629
1426
|
// src/mcp/commands/uninstall.commands.ts
|
|
1630
|
-
import { z as
|
|
1427
|
+
import { z as z7 } from "zod";
|
|
1631
1428
|
|
|
1632
1429
|
// src/mcp/handlers/uninstall.handler.ts
|
|
1633
1430
|
import { existsSync } from "fs";
|
|
1634
1431
|
import { readdir, rm as rm2 } from "fs/promises";
|
|
1635
1432
|
import { homedir } from "os";
|
|
1636
|
-
import { join as
|
|
1433
|
+
import { join as join2 } from "path";
|
|
1637
1434
|
var logger2 = createLogger("uninstall-handler");
|
|
1638
1435
|
var handleUninstall = async (args, context) => {
|
|
1639
1436
|
const { global: includeGlobal = false, keepDefinitions = true } = args;
|
|
@@ -1641,14 +1438,14 @@ var handleUninstall = async (args, context) => {
|
|
|
1641
1438
|
const kept = [];
|
|
1642
1439
|
const errors = [];
|
|
1643
1440
|
const projectRoot = context.options.projectRoot ?? process.cwd();
|
|
1644
|
-
const projectDataDir =
|
|
1441
|
+
const projectDataDir = join2(projectRoot, ".bluera", "bluera-knowledge");
|
|
1645
1442
|
logger2.info({ projectDataDir, includeGlobal, keepDefinitions }, "Starting uninstall");
|
|
1646
1443
|
if (existsSync(projectDataDir)) {
|
|
1647
1444
|
if (keepDefinitions) {
|
|
1648
1445
|
try {
|
|
1649
1446
|
const entries = await readdir(projectDataDir, { withFileTypes: true });
|
|
1650
1447
|
for (const entry of entries) {
|
|
1651
|
-
const entryPath =
|
|
1448
|
+
const entryPath = join2(projectDataDir, entry.name);
|
|
1652
1449
|
if (entry.name === "stores.config.json") {
|
|
1653
1450
|
kept.push(entryPath);
|
|
1654
1451
|
continue;
|
|
@@ -1679,7 +1476,7 @@ var handleUninstall = async (args, context) => {
|
|
|
1679
1476
|
}
|
|
1680
1477
|
}
|
|
1681
1478
|
if (includeGlobal) {
|
|
1682
|
-
const globalDir =
|
|
1479
|
+
const globalDir = join2(homedir(), ".local", "share", "bluera-knowledge");
|
|
1683
1480
|
if (existsSync(globalDir)) {
|
|
1684
1481
|
try {
|
|
1685
1482
|
await rm2(globalDir, { recursive: true, force: true });
|
|
@@ -1736,9 +1533,9 @@ var uninstallCommands = [
|
|
|
1736
1533
|
{
|
|
1737
1534
|
name: "uninstall",
|
|
1738
1535
|
description: "Remove Bluera Knowledge data from project (and optionally global data)",
|
|
1739
|
-
argsSchema:
|
|
1740
|
-
global:
|
|
1741
|
-
keepDefinitions:
|
|
1536
|
+
argsSchema: z7.object({
|
|
1537
|
+
global: z7.boolean().optional().describe("Also remove global data (~/.local/share/bluera-knowledge)"),
|
|
1538
|
+
keepDefinitions: z7.boolean().optional().describe("Keep stores.config.json for team sharing (default: true)")
|
|
1742
1539
|
}),
|
|
1743
1540
|
handler: (args, context) => handleUninstall(args, context)
|
|
1744
1541
|
}
|
|
@@ -2080,7 +1877,7 @@ var registry = AdapterRegistry.getInstance();
|
|
|
2080
1877
|
if (!registry.hasExtension(".zil")) {
|
|
2081
1878
|
registry.register(new ZilAdapter());
|
|
2082
1879
|
}
|
|
2083
|
-
function createMCPServer(options) {
|
|
1880
|
+
function createMCPServer(options, services) {
|
|
2084
1881
|
const server = new Server(
|
|
2085
1882
|
{
|
|
2086
1883
|
name: "bluera-knowledge",
|
|
@@ -2192,7 +1989,6 @@ function createMCPServer(options) {
|
|
|
2192
1989
|
const { name, arguments: args } = request.params;
|
|
2193
1990
|
const startTime = Date.now();
|
|
2194
1991
|
logger4.info({ tool: name, args: JSON.stringify(args) }, "Tool invoked");
|
|
2195
|
-
const services = await createServices(options.config, options.dataDir, options.projectRoot);
|
|
2196
1992
|
const context = { services, options };
|
|
2197
1993
|
try {
|
|
2198
1994
|
let result;
|
|
@@ -2221,8 +2017,6 @@ function createMCPServer(options) {
|
|
|
2221
2017
|
"Tool execution failed"
|
|
2222
2018
|
);
|
|
2223
2019
|
throw error;
|
|
2224
|
-
} finally {
|
|
2225
|
-
await destroyServices(services);
|
|
2226
2020
|
}
|
|
2227
2021
|
});
|
|
2228
2022
|
return server;
|
|
@@ -2235,8 +2029,23 @@ async function runMCPServer(options) {
|
|
|
2235
2029
|
},
|
|
2236
2030
|
"MCP server starting"
|
|
2237
2031
|
);
|
|
2238
|
-
const
|
|
2032
|
+
const services = await createLazyServices(options.config, options.dataDir, options.projectRoot);
|
|
2033
|
+
const server = createMCPServer(options, services);
|
|
2239
2034
|
const transport = new StdioServerTransport();
|
|
2035
|
+
const shutdown = async (signal) => {
|
|
2036
|
+
logger4.info({ signal }, "Shutdown signal received");
|
|
2037
|
+
try {
|
|
2038
|
+
await destroyServices(services);
|
|
2039
|
+
logger4.info("Services destroyed, exiting");
|
|
2040
|
+
} catch (error) {
|
|
2041
|
+
logger4.error(
|
|
2042
|
+
{ error: error instanceof Error ? error.message : String(error) },
|
|
2043
|
+
"Error during shutdown"
|
|
2044
|
+
);
|
|
2045
|
+
}
|
|
2046
|
+
};
|
|
2047
|
+
process.on("SIGINT", () => void shutdown("SIGINT"));
|
|
2048
|
+
process.on("SIGTERM", () => void shutdown("SIGTERM"));
|
|
2240
2049
|
await server.connect(transport);
|
|
2241
2050
|
logger4.info("MCP server connected to stdio transport");
|
|
2242
2051
|
}
|
|
@@ -2263,11 +2072,7 @@ if (isMCPServerEntry) {
|
|
|
2263
2072
|
export {
|
|
2264
2073
|
ZilAdapter,
|
|
2265
2074
|
spawnBackgroundWorker,
|
|
2266
|
-
isFileStoreDefinition,
|
|
2267
|
-
isRepoStoreDefinition,
|
|
2268
|
-
isWebStoreDefinition,
|
|
2269
|
-
StoreDefinitionService,
|
|
2270
2075
|
createMCPServer,
|
|
2271
2076
|
runMCPServer
|
|
2272
2077
|
};
|
|
2273
|
-
//# sourceMappingURL=chunk-
|
|
2078
|
+
//# sourceMappingURL=chunk-DX5I6U5X.js.map
|