@cortexa/core 1.0.1 → 1.1.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/dist/cli/index.js +332 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +286 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.js +278 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -847,6 +847,7 @@ var init_mongodb_stream = __esm({
|
|
|
847
847
|
var index_exports = {};
|
|
848
848
|
__export(index_exports, {
|
|
849
849
|
Cortexa: () => Cortexa,
|
|
850
|
+
CortexaServer: () => CortexaServer,
|
|
850
851
|
KnowledgeGraph: () => KnowledgeGraph,
|
|
851
852
|
defineConfig: () => defineConfig
|
|
852
853
|
});
|
|
@@ -5423,6 +5424,290 @@ function defineConfig(config) {
|
|
|
5423
5424
|
return config;
|
|
5424
5425
|
}
|
|
5425
5426
|
|
|
5427
|
+
// src/server/index.ts
|
|
5428
|
+
init_cjs_shims();
|
|
5429
|
+
|
|
5430
|
+
// src/server/server.ts
|
|
5431
|
+
init_cjs_shims();
|
|
5432
|
+
var import_node_http = require("http");
|
|
5433
|
+
|
|
5434
|
+
// src/server/router.ts
|
|
5435
|
+
init_cjs_shims();
|
|
5436
|
+
var Router = class {
|
|
5437
|
+
routes = [];
|
|
5438
|
+
get(path3, handler) {
|
|
5439
|
+
this.addRoute("GET", path3, handler);
|
|
5440
|
+
}
|
|
5441
|
+
post(path3, handler) {
|
|
5442
|
+
this.addRoute("POST", path3, handler);
|
|
5443
|
+
}
|
|
5444
|
+
addRoute(method, path3, handler) {
|
|
5445
|
+
const paramNames = [];
|
|
5446
|
+
const patternStr = path3.replace(/:(\w+)/g, (_match, name) => {
|
|
5447
|
+
paramNames.push(name);
|
|
5448
|
+
return "([^/]+)";
|
|
5449
|
+
});
|
|
5450
|
+
this.routes.push({
|
|
5451
|
+
method,
|
|
5452
|
+
pattern: new RegExp(`^${patternStr}$`),
|
|
5453
|
+
paramNames,
|
|
5454
|
+
handler
|
|
5455
|
+
});
|
|
5456
|
+
}
|
|
5457
|
+
async handle(req, res, cors) {
|
|
5458
|
+
if (cors) {
|
|
5459
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
5460
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
5461
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
5462
|
+
}
|
|
5463
|
+
if (req.method === "OPTIONS") {
|
|
5464
|
+
res.writeHead(204);
|
|
5465
|
+
res.end();
|
|
5466
|
+
return;
|
|
5467
|
+
}
|
|
5468
|
+
const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
|
|
5469
|
+
const path3 = url.pathname;
|
|
5470
|
+
const method = req.method ?? "GET";
|
|
5471
|
+
const query = {};
|
|
5472
|
+
url.searchParams.forEach((value, key) => {
|
|
5473
|
+
query[key] = value;
|
|
5474
|
+
});
|
|
5475
|
+
for (const route of this.routes) {
|
|
5476
|
+
if (route.method !== method) continue;
|
|
5477
|
+
const match = route.pattern.exec(path3);
|
|
5478
|
+
if (!match) continue;
|
|
5479
|
+
const pathParams = {};
|
|
5480
|
+
for (let i = 0; i < route.paramNames.length; i++) {
|
|
5481
|
+
pathParams[route.paramNames[i]] = match[i + 1];
|
|
5482
|
+
}
|
|
5483
|
+
let body = void 0;
|
|
5484
|
+
if (method === "POST") {
|
|
5485
|
+
body = await readBody(req);
|
|
5486
|
+
}
|
|
5487
|
+
const params = { path: path3, method, query, body, pathParams };
|
|
5488
|
+
try {
|
|
5489
|
+
const result = await route.handler(params);
|
|
5490
|
+
sendJson(res, result.ok ? 200 : 400, result);
|
|
5491
|
+
} catch (err) {
|
|
5492
|
+
const message = err instanceof Error ? err.message : "Internal server error";
|
|
5493
|
+
sendJson(res, 500, { ok: false, error: message });
|
|
5494
|
+
}
|
|
5495
|
+
return;
|
|
5496
|
+
}
|
|
5497
|
+
sendJson(res, 404, { ok: false, error: `Not found: ${method} ${path3}` });
|
|
5498
|
+
}
|
|
5499
|
+
};
|
|
5500
|
+
function sendJson(res, statusCode, data) {
|
|
5501
|
+
res.writeHead(statusCode, { "Content-Type": "application/json" });
|
|
5502
|
+
res.end(JSON.stringify(data));
|
|
5503
|
+
}
|
|
5504
|
+
function readBody(req) {
|
|
5505
|
+
return new Promise((resolve, reject) => {
|
|
5506
|
+
const chunks = [];
|
|
5507
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
5508
|
+
req.on("end", () => {
|
|
5509
|
+
const raw = Buffer.concat(chunks).toString();
|
|
5510
|
+
if (!raw) {
|
|
5511
|
+
resolve(void 0);
|
|
5512
|
+
return;
|
|
5513
|
+
}
|
|
5514
|
+
try {
|
|
5515
|
+
resolve(JSON.parse(raw));
|
|
5516
|
+
} catch {
|
|
5517
|
+
reject(new Error("Invalid JSON body"));
|
|
5518
|
+
}
|
|
5519
|
+
});
|
|
5520
|
+
req.on("error", reject);
|
|
5521
|
+
});
|
|
5522
|
+
}
|
|
5523
|
+
|
|
5524
|
+
// src/server/handlers.ts
|
|
5525
|
+
init_cjs_shims();
|
|
5526
|
+
function registerHandlers(router, cortexa) {
|
|
5527
|
+
router.get("/api/status", async () => {
|
|
5528
|
+
return { ok: true, data: cortexa.status };
|
|
5529
|
+
});
|
|
5530
|
+
router.get("/api/entities", async () => {
|
|
5531
|
+
const { entities } = cortexa.exportGraph();
|
|
5532
|
+
return { ok: true, data: entities };
|
|
5533
|
+
});
|
|
5534
|
+
router.get("/api/relationships", async () => {
|
|
5535
|
+
const { relationships } = cortexa.exportGraph();
|
|
5536
|
+
return { ok: true, data: relationships };
|
|
5537
|
+
});
|
|
5538
|
+
router.post("/api/discover", async (params) => {
|
|
5539
|
+
const body = params.body ?? {};
|
|
5540
|
+
const result = await cortexa.discover({
|
|
5541
|
+
includeSampleData: body.includeSampleData !== false,
|
|
5542
|
+
excludeTables: body.excludeTables,
|
|
5543
|
+
excludeColumns: body.excludeColumns
|
|
5544
|
+
});
|
|
5545
|
+
return {
|
|
5546
|
+
ok: true,
|
|
5547
|
+
data: {
|
|
5548
|
+
tables: result.raw.tables.length,
|
|
5549
|
+
entities: result.entities.length,
|
|
5550
|
+
relationships: result.relationships.length
|
|
5551
|
+
}
|
|
5552
|
+
};
|
|
5553
|
+
});
|
|
5554
|
+
router.get("/api/events", async (params) => {
|
|
5555
|
+
const filter = {};
|
|
5556
|
+
if (params.query.entity) filter.entity = params.query.entity;
|
|
5557
|
+
if (params.query.last) filter.last = parseInt(params.query.last, 10);
|
|
5558
|
+
if (params.query.operation) filter.operation = params.query.operation;
|
|
5559
|
+
return { ok: true, data: cortexa.getEvents(filter) };
|
|
5560
|
+
});
|
|
5561
|
+
router.get("/api/baselines", async () => {
|
|
5562
|
+
return { ok: true, data: cortexa.getBaselines() };
|
|
5563
|
+
});
|
|
5564
|
+
router.get("/api/anomalies", async (params) => {
|
|
5565
|
+
const filter = {};
|
|
5566
|
+
if (params.query.entity) filter.entity = params.query.entity;
|
|
5567
|
+
if (params.query.last) filter.last = parseInt(params.query.last, 10);
|
|
5568
|
+
if (params.query.severity) filter.severity = params.query.severity;
|
|
5569
|
+
return { ok: true, data: cortexa.getAnomalies(filter) };
|
|
5570
|
+
});
|
|
5571
|
+
router.get("/api/insights", async (params) => {
|
|
5572
|
+
const filter = {};
|
|
5573
|
+
if (params.query.entity) filter.entity = params.query.entity;
|
|
5574
|
+
if (params.query.last) filter.last = parseInt(params.query.last, 10);
|
|
5575
|
+
if (params.query.severity) filter.severity = params.query.severity;
|
|
5576
|
+
return { ok: true, data: cortexa.getInsights(filter) };
|
|
5577
|
+
});
|
|
5578
|
+
router.get("/api/transitions", async (params) => {
|
|
5579
|
+
return { ok: true, data: cortexa.getTransitions(params.query.entity) };
|
|
5580
|
+
});
|
|
5581
|
+
router.get("/api/correlations", async () => {
|
|
5582
|
+
return { ok: true, data: cortexa.getCorrelations() };
|
|
5583
|
+
});
|
|
5584
|
+
router.get("/api/distributions", async (params) => {
|
|
5585
|
+
return { ok: true, data: cortexa.getDistributions(params.query.entity) };
|
|
5586
|
+
});
|
|
5587
|
+
router.get("/api/graph", async () => {
|
|
5588
|
+
return { ok: true, data: cortexa.graph().getSummary() };
|
|
5589
|
+
});
|
|
5590
|
+
router.get("/api/graph/export", async () => {
|
|
5591
|
+
return { ok: true, data: cortexa.graph().export() };
|
|
5592
|
+
});
|
|
5593
|
+
router.get("/api/graph/entity/:name", async (params) => {
|
|
5594
|
+
const intel = cortexa.graph().entity(params.pathParams.name).intelligence();
|
|
5595
|
+
if (!intel) {
|
|
5596
|
+
return { ok: false, error: `Entity "${params.pathParams.name}" not found in knowledge graph` };
|
|
5597
|
+
}
|
|
5598
|
+
return { ok: true, data: intel };
|
|
5599
|
+
});
|
|
5600
|
+
router.get("/api/actions", async (params) => {
|
|
5601
|
+
const filter = {};
|
|
5602
|
+
if (params.query.status) filter.status = params.query.status;
|
|
5603
|
+
if (params.query.action) filter.action = params.query.action;
|
|
5604
|
+
return { ok: true, data: cortexa.getRecommendations(filter) };
|
|
5605
|
+
});
|
|
5606
|
+
router.post("/api/actions/:id/approve", async (params) => {
|
|
5607
|
+
const id = parseInt(params.pathParams.id, 10);
|
|
5608
|
+
if (isNaN(id)) return { ok: false, error: "Invalid id" };
|
|
5609
|
+
cortexa.approveRecommendation(id);
|
|
5610
|
+
return { ok: true, data: { id, status: "approved" } };
|
|
5611
|
+
});
|
|
5612
|
+
router.post("/api/actions/:id/reject", async (params) => {
|
|
5613
|
+
const id = parseInt(params.pathParams.id, 10);
|
|
5614
|
+
if (isNaN(id)) return { ok: false, error: "Invalid id" };
|
|
5615
|
+
cortexa.rejectRecommendation(id);
|
|
5616
|
+
return { ok: true, data: { id, status: "rejected" } };
|
|
5617
|
+
});
|
|
5618
|
+
router.post("/api/explain", async (params) => {
|
|
5619
|
+
const body = params.body;
|
|
5620
|
+
if (!body?.type || !body?.id) {
|
|
5621
|
+
return { ok: false, error: 'Required: { type: "anomaly"|"insight"|"event"|"entity", id: number }' };
|
|
5622
|
+
}
|
|
5623
|
+
const target = {
|
|
5624
|
+
type: body.type,
|
|
5625
|
+
id: body.id
|
|
5626
|
+
};
|
|
5627
|
+
const result = await cortexa.explain(target);
|
|
5628
|
+
return { ok: true, data: result };
|
|
5629
|
+
});
|
|
5630
|
+
router.post("/api/ask", async (params) => {
|
|
5631
|
+
const body = params.body;
|
|
5632
|
+
if (!body?.question || typeof body.question !== "string") {
|
|
5633
|
+
return { ok: false, error: "Required: { question: string }" };
|
|
5634
|
+
}
|
|
5635
|
+
const result = await cortexa.ask(body.question, {
|
|
5636
|
+
entityHint: body.entity
|
|
5637
|
+
});
|
|
5638
|
+
return { ok: true, data: result };
|
|
5639
|
+
});
|
|
5640
|
+
router.post("/api/watch", async (params) => {
|
|
5641
|
+
const body = params.body ?? {};
|
|
5642
|
+
await cortexa.watch({
|
|
5643
|
+
interval: body.interval,
|
|
5644
|
+
once: body.once
|
|
5645
|
+
});
|
|
5646
|
+
return { ok: true, data: { watching: true } };
|
|
5647
|
+
});
|
|
5648
|
+
router.post("/api/unwatch", async () => {
|
|
5649
|
+
cortexa.unwatch();
|
|
5650
|
+
return { ok: true, data: { watching: false } };
|
|
5651
|
+
});
|
|
5652
|
+
}
|
|
5653
|
+
|
|
5654
|
+
// src/server/server.ts
|
|
5655
|
+
init_logger();
|
|
5656
|
+
var CortexaServer = class {
|
|
5657
|
+
cortexa;
|
|
5658
|
+
serverConfig;
|
|
5659
|
+
logger;
|
|
5660
|
+
httpServer = null;
|
|
5661
|
+
constructor(cortexaConfig, serverConfig) {
|
|
5662
|
+
this.cortexa = new Cortexa(cortexaConfig);
|
|
5663
|
+
this.serverConfig = {
|
|
5664
|
+
port: serverConfig?.port ?? 3210,
|
|
5665
|
+
host: serverConfig?.host ?? "127.0.0.1",
|
|
5666
|
+
cors: serverConfig?.cors ?? true
|
|
5667
|
+
};
|
|
5668
|
+
this.logger = createLogger();
|
|
5669
|
+
}
|
|
5670
|
+
async start() {
|
|
5671
|
+
await this.cortexa.connect();
|
|
5672
|
+
const router = new Router();
|
|
5673
|
+
registerHandlers(router, this.cortexa);
|
|
5674
|
+
const cors = this.serverConfig.cors ?? true;
|
|
5675
|
+
this.httpServer = (0, import_node_http.createServer)((req, res) => {
|
|
5676
|
+
router.handle(req, res, cors).catch((err) => {
|
|
5677
|
+
this.logger.error({ err }, "Unhandled request error");
|
|
5678
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
5679
|
+
res.end(JSON.stringify({ ok: false, error: "Internal server error" }));
|
|
5680
|
+
});
|
|
5681
|
+
});
|
|
5682
|
+
const { port, host } = this.serverConfig;
|
|
5683
|
+
await new Promise((resolve) => {
|
|
5684
|
+
this.httpServer.listen(port, host, () => {
|
|
5685
|
+
this.logger.info({ port, host }, "Cortexa REST API server started");
|
|
5686
|
+
resolve();
|
|
5687
|
+
});
|
|
5688
|
+
});
|
|
5689
|
+
}
|
|
5690
|
+
async stop() {
|
|
5691
|
+
if (this.httpServer) {
|
|
5692
|
+
await new Promise((resolve, reject) => {
|
|
5693
|
+
this.httpServer.close((err) => {
|
|
5694
|
+
if (err) reject(err);
|
|
5695
|
+
else resolve();
|
|
5696
|
+
});
|
|
5697
|
+
});
|
|
5698
|
+
this.httpServer = null;
|
|
5699
|
+
}
|
|
5700
|
+
await this.cortexa.disconnect();
|
|
5701
|
+
this.logger.info("Cortexa REST API server stopped");
|
|
5702
|
+
}
|
|
5703
|
+
get address() {
|
|
5704
|
+
return {
|
|
5705
|
+
port: this.serverConfig.port ?? 3210,
|
|
5706
|
+
host: this.serverConfig.host ?? "127.0.0.1"
|
|
5707
|
+
};
|
|
5708
|
+
}
|
|
5709
|
+
};
|
|
5710
|
+
|
|
5426
5711
|
// src/index.ts
|
|
5427
5712
|
var KnowledgeGraph = class {
|
|
5428
5713
|
store;
|
|
@@ -5727,6 +6012,7 @@ var Cortexa = class extends import_node_events2.EventEmitter {
|
|
|
5727
6012
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5728
6013
|
0 && (module.exports = {
|
|
5729
6014
|
Cortexa,
|
|
6015
|
+
CortexaServer,
|
|
5730
6016
|
KnowledgeGraph,
|
|
5731
6017
|
defineConfig
|
|
5732
6018
|
});
|