@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/index.d.cts CHANGED
@@ -523,6 +523,31 @@ interface AskResult {
523
523
  generatedAt: string;
524
524
  }
525
525
 
526
+ interface ServerConfig {
527
+ port?: number;
528
+ host?: string;
529
+ cors?: boolean;
530
+ }
531
+ interface ApiResponse<T = unknown> {
532
+ ok: boolean;
533
+ data?: T;
534
+ error?: string;
535
+ }
536
+
537
+ declare class CortexaServer {
538
+ private readonly cortexa;
539
+ private readonly serverConfig;
540
+ private readonly logger;
541
+ private httpServer;
542
+ constructor(cortexaConfig: CortexaOptions, serverConfig?: ServerConfig);
543
+ start(): Promise<void>;
544
+ stop(): Promise<void>;
545
+ get address(): {
546
+ port: number;
547
+ host: string;
548
+ };
549
+ }
550
+
526
551
  interface ChangeStream {
527
552
  start(onChange: (change: RawChange) => void): Promise<void>;
528
553
  stop(): Promise<void>;
@@ -667,4 +692,4 @@ declare class Cortexa extends EventEmitter {
667
692
  get status(): CortexaStatus;
668
693
  }
669
694
 
670
- export { type ActionContext, type ActionHandler, type ActionRule, type ActionsConfig, type AnalyticsConfig, type Anomaly, type AnomalyType, type AskOptions, type AskResult, type Baseline, type BusinessEvent, type CausalStep, type ChangeStream, type ClassifiedEntity, type ConnectionConfig, type CorrelationConfig, type CorrelationStatus, Cortexa, type CortexaConfig, type CortexaOptions, type CortexaStatus, type DiscoveryOptions, type DiscoveryResult, type DistributionConfig, type DistributionSummary, type EdgeType, type EntityGraph, type EntityIntelligenceResult, type Evidence, type ExplainOptions, type ExplainResult, type ExplainTarget, type GovernanceLevel, type GraphExport, type GraphSummary, type Insight, type InsightType, type KnowledgeConfig, type KnowledgeEdge, KnowledgeGraph, type KnowledgeNode, type LLMProvider, type LlmConfig, type NodeType, type NotificationFilter, type NotificationRule, type NotificationTrigger, type NotificationsConfig, type RawSchema, type ReasoningConfig, type Recommendation, type RecommendationStatus, type RecommendationSummary, type RecommendedAction, type Relationship, type Severity, type SignalType, type StateTransition, type StreamCapability, type SupportingSignal, type TransitionStats, type WatchOptions, type WebhookTarget, type WorkflowConfig, defineConfig };
695
+ export { type ActionContext, type ActionHandler, type ActionRule, type ActionsConfig, type AnalyticsConfig, type Anomaly, type AnomalyType, type ApiResponse, type AskOptions, type AskResult, type Baseline, type BusinessEvent, type CausalStep, type ChangeStream, type ClassifiedEntity, type ConnectionConfig, type CorrelationConfig, type CorrelationStatus, Cortexa, type CortexaConfig, type CortexaOptions, CortexaServer, type CortexaStatus, type DiscoveryOptions, type DiscoveryResult, type DistributionConfig, type DistributionSummary, type EdgeType, type EntityGraph, type EntityIntelligenceResult, type Evidence, type ExplainOptions, type ExplainResult, type ExplainTarget, type GovernanceLevel, type GraphExport, type GraphSummary, type Insight, type InsightType, type KnowledgeConfig, type KnowledgeEdge, KnowledgeGraph, type KnowledgeNode, type LLMProvider, type LlmConfig, type NodeType, type NotificationFilter, type NotificationRule, type NotificationTrigger, type NotificationsConfig, type RawSchema, type ReasoningConfig, type Recommendation, type RecommendationStatus, type RecommendationSummary, type RecommendedAction, type Relationship, type ServerConfig, type Severity, type SignalType, type StateTransition, type StreamCapability, type SupportingSignal, type TransitionStats, type WatchOptions, type WebhookTarget, type WorkflowConfig, defineConfig };
package/dist/index.d.ts CHANGED
@@ -523,6 +523,31 @@ interface AskResult {
523
523
  generatedAt: string;
524
524
  }
525
525
 
526
+ interface ServerConfig {
527
+ port?: number;
528
+ host?: string;
529
+ cors?: boolean;
530
+ }
531
+ interface ApiResponse<T = unknown> {
532
+ ok: boolean;
533
+ data?: T;
534
+ error?: string;
535
+ }
536
+
537
+ declare class CortexaServer {
538
+ private readonly cortexa;
539
+ private readonly serverConfig;
540
+ private readonly logger;
541
+ private httpServer;
542
+ constructor(cortexaConfig: CortexaOptions, serverConfig?: ServerConfig);
543
+ start(): Promise<void>;
544
+ stop(): Promise<void>;
545
+ get address(): {
546
+ port: number;
547
+ host: string;
548
+ };
549
+ }
550
+
526
551
  interface ChangeStream {
527
552
  start(onChange: (change: RawChange) => void): Promise<void>;
528
553
  stop(): Promise<void>;
@@ -667,4 +692,4 @@ declare class Cortexa extends EventEmitter {
667
692
  get status(): CortexaStatus;
668
693
  }
669
694
 
670
- export { type ActionContext, type ActionHandler, type ActionRule, type ActionsConfig, type AnalyticsConfig, type Anomaly, type AnomalyType, type AskOptions, type AskResult, type Baseline, type BusinessEvent, type CausalStep, type ChangeStream, type ClassifiedEntity, type ConnectionConfig, type CorrelationConfig, type CorrelationStatus, Cortexa, type CortexaConfig, type CortexaOptions, type CortexaStatus, type DiscoveryOptions, type DiscoveryResult, type DistributionConfig, type DistributionSummary, type EdgeType, type EntityGraph, type EntityIntelligenceResult, type Evidence, type ExplainOptions, type ExplainResult, type ExplainTarget, type GovernanceLevel, type GraphExport, type GraphSummary, type Insight, type InsightType, type KnowledgeConfig, type KnowledgeEdge, KnowledgeGraph, type KnowledgeNode, type LLMProvider, type LlmConfig, type NodeType, type NotificationFilter, type NotificationRule, type NotificationTrigger, type NotificationsConfig, type RawSchema, type ReasoningConfig, type Recommendation, type RecommendationStatus, type RecommendationSummary, type RecommendedAction, type Relationship, type Severity, type SignalType, type StateTransition, type StreamCapability, type SupportingSignal, type TransitionStats, type WatchOptions, type WebhookTarget, type WorkflowConfig, defineConfig };
695
+ export { type ActionContext, type ActionHandler, type ActionRule, type ActionsConfig, type AnalyticsConfig, type Anomaly, type AnomalyType, type ApiResponse, type AskOptions, type AskResult, type Baseline, type BusinessEvent, type CausalStep, type ChangeStream, type ClassifiedEntity, type ConnectionConfig, type CorrelationConfig, type CorrelationStatus, Cortexa, type CortexaConfig, type CortexaOptions, CortexaServer, type CortexaStatus, type DiscoveryOptions, type DiscoveryResult, type DistributionConfig, type DistributionSummary, type EdgeType, type EntityGraph, type EntityIntelligenceResult, type Evidence, type ExplainOptions, type ExplainResult, type ExplainTarget, type GovernanceLevel, type GraphExport, type GraphSummary, type Insight, type InsightType, type KnowledgeConfig, type KnowledgeEdge, KnowledgeGraph, type KnowledgeNode, type LLMProvider, type LlmConfig, type NodeType, type NotificationFilter, type NotificationRule, type NotificationTrigger, type NotificationsConfig, type RawSchema, type ReasoningConfig, type Recommendation, type RecommendationStatus, type RecommendationSummary, type RecommendedAction, type Relationship, type ServerConfig, type Severity, type SignalType, type StateTransition, type StreamCapability, type SupportingSignal, type TransitionStats, type WatchOptions, type WebhookTarget, type WorkflowConfig, defineConfig };
package/dist/index.js CHANGED
@@ -4496,6 +4496,283 @@ function defineConfig(config) {
4496
4496
  return config;
4497
4497
  }
4498
4498
 
4499
+ // src/server/server.ts
4500
+ import { createServer } from "http";
4501
+
4502
+ // src/server/router.ts
4503
+ var Router = class {
4504
+ routes = [];
4505
+ get(path3, handler) {
4506
+ this.addRoute("GET", path3, handler);
4507
+ }
4508
+ post(path3, handler) {
4509
+ this.addRoute("POST", path3, handler);
4510
+ }
4511
+ addRoute(method, path3, handler) {
4512
+ const paramNames = [];
4513
+ const patternStr = path3.replace(/:(\w+)/g, (_match, name) => {
4514
+ paramNames.push(name);
4515
+ return "([^/]+)";
4516
+ });
4517
+ this.routes.push({
4518
+ method,
4519
+ pattern: new RegExp(`^${patternStr}$`),
4520
+ paramNames,
4521
+ handler
4522
+ });
4523
+ }
4524
+ async handle(req, res, cors) {
4525
+ if (cors) {
4526
+ res.setHeader("Access-Control-Allow-Origin", "*");
4527
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
4528
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
4529
+ }
4530
+ if (req.method === "OPTIONS") {
4531
+ res.writeHead(204);
4532
+ res.end();
4533
+ return;
4534
+ }
4535
+ const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
4536
+ const path3 = url.pathname;
4537
+ const method = req.method ?? "GET";
4538
+ const query = {};
4539
+ url.searchParams.forEach((value, key) => {
4540
+ query[key] = value;
4541
+ });
4542
+ for (const route of this.routes) {
4543
+ if (route.method !== method) continue;
4544
+ const match = route.pattern.exec(path3);
4545
+ if (!match) continue;
4546
+ const pathParams = {};
4547
+ for (let i = 0; i < route.paramNames.length; i++) {
4548
+ pathParams[route.paramNames[i]] = match[i + 1];
4549
+ }
4550
+ let body = void 0;
4551
+ if (method === "POST") {
4552
+ body = await readBody(req);
4553
+ }
4554
+ const params = { path: path3, method, query, body, pathParams };
4555
+ try {
4556
+ const result = await route.handler(params);
4557
+ sendJson(res, result.ok ? 200 : 400, result);
4558
+ } catch (err) {
4559
+ const message = err instanceof Error ? err.message : "Internal server error";
4560
+ sendJson(res, 500, { ok: false, error: message });
4561
+ }
4562
+ return;
4563
+ }
4564
+ sendJson(res, 404, { ok: false, error: `Not found: ${method} ${path3}` });
4565
+ }
4566
+ };
4567
+ function sendJson(res, statusCode, data) {
4568
+ res.writeHead(statusCode, { "Content-Type": "application/json" });
4569
+ res.end(JSON.stringify(data));
4570
+ }
4571
+ function readBody(req) {
4572
+ return new Promise((resolve, reject) => {
4573
+ const chunks = [];
4574
+ req.on("data", (chunk) => chunks.push(chunk));
4575
+ req.on("end", () => {
4576
+ const raw = Buffer.concat(chunks).toString();
4577
+ if (!raw) {
4578
+ resolve(void 0);
4579
+ return;
4580
+ }
4581
+ try {
4582
+ resolve(JSON.parse(raw));
4583
+ } catch {
4584
+ reject(new Error("Invalid JSON body"));
4585
+ }
4586
+ });
4587
+ req.on("error", reject);
4588
+ });
4589
+ }
4590
+
4591
+ // src/server/handlers.ts
4592
+ function registerHandlers(router, cortexa) {
4593
+ router.get("/api/status", async () => {
4594
+ return { ok: true, data: cortexa.status };
4595
+ });
4596
+ router.get("/api/entities", async () => {
4597
+ const { entities } = cortexa.exportGraph();
4598
+ return { ok: true, data: entities };
4599
+ });
4600
+ router.get("/api/relationships", async () => {
4601
+ const { relationships } = cortexa.exportGraph();
4602
+ return { ok: true, data: relationships };
4603
+ });
4604
+ router.post("/api/discover", async (params) => {
4605
+ const body = params.body ?? {};
4606
+ const result = await cortexa.discover({
4607
+ includeSampleData: body.includeSampleData !== false,
4608
+ excludeTables: body.excludeTables,
4609
+ excludeColumns: body.excludeColumns
4610
+ });
4611
+ return {
4612
+ ok: true,
4613
+ data: {
4614
+ tables: result.raw.tables.length,
4615
+ entities: result.entities.length,
4616
+ relationships: result.relationships.length
4617
+ }
4618
+ };
4619
+ });
4620
+ router.get("/api/events", async (params) => {
4621
+ const filter = {};
4622
+ if (params.query.entity) filter.entity = params.query.entity;
4623
+ if (params.query.last) filter.last = parseInt(params.query.last, 10);
4624
+ if (params.query.operation) filter.operation = params.query.operation;
4625
+ return { ok: true, data: cortexa.getEvents(filter) };
4626
+ });
4627
+ router.get("/api/baselines", async () => {
4628
+ return { ok: true, data: cortexa.getBaselines() };
4629
+ });
4630
+ router.get("/api/anomalies", async (params) => {
4631
+ const filter = {};
4632
+ if (params.query.entity) filter.entity = params.query.entity;
4633
+ if (params.query.last) filter.last = parseInt(params.query.last, 10);
4634
+ if (params.query.severity) filter.severity = params.query.severity;
4635
+ return { ok: true, data: cortexa.getAnomalies(filter) };
4636
+ });
4637
+ router.get("/api/insights", async (params) => {
4638
+ const filter = {};
4639
+ if (params.query.entity) filter.entity = params.query.entity;
4640
+ if (params.query.last) filter.last = parseInt(params.query.last, 10);
4641
+ if (params.query.severity) filter.severity = params.query.severity;
4642
+ return { ok: true, data: cortexa.getInsights(filter) };
4643
+ });
4644
+ router.get("/api/transitions", async (params) => {
4645
+ return { ok: true, data: cortexa.getTransitions(params.query.entity) };
4646
+ });
4647
+ router.get("/api/correlations", async () => {
4648
+ return { ok: true, data: cortexa.getCorrelations() };
4649
+ });
4650
+ router.get("/api/distributions", async (params) => {
4651
+ return { ok: true, data: cortexa.getDistributions(params.query.entity) };
4652
+ });
4653
+ router.get("/api/graph", async () => {
4654
+ return { ok: true, data: cortexa.graph().getSummary() };
4655
+ });
4656
+ router.get("/api/graph/export", async () => {
4657
+ return { ok: true, data: cortexa.graph().export() };
4658
+ });
4659
+ router.get("/api/graph/entity/:name", async (params) => {
4660
+ const intel = cortexa.graph().entity(params.pathParams.name).intelligence();
4661
+ if (!intel) {
4662
+ return { ok: false, error: `Entity "${params.pathParams.name}" not found in knowledge graph` };
4663
+ }
4664
+ return { ok: true, data: intel };
4665
+ });
4666
+ router.get("/api/actions", async (params) => {
4667
+ const filter = {};
4668
+ if (params.query.status) filter.status = params.query.status;
4669
+ if (params.query.action) filter.action = params.query.action;
4670
+ return { ok: true, data: cortexa.getRecommendations(filter) };
4671
+ });
4672
+ router.post("/api/actions/:id/approve", async (params) => {
4673
+ const id = parseInt(params.pathParams.id, 10);
4674
+ if (isNaN(id)) return { ok: false, error: "Invalid id" };
4675
+ cortexa.approveRecommendation(id);
4676
+ return { ok: true, data: { id, status: "approved" } };
4677
+ });
4678
+ router.post("/api/actions/:id/reject", async (params) => {
4679
+ const id = parseInt(params.pathParams.id, 10);
4680
+ if (isNaN(id)) return { ok: false, error: "Invalid id" };
4681
+ cortexa.rejectRecommendation(id);
4682
+ return { ok: true, data: { id, status: "rejected" } };
4683
+ });
4684
+ router.post("/api/explain", async (params) => {
4685
+ const body = params.body;
4686
+ if (!body?.type || !body?.id) {
4687
+ return { ok: false, error: 'Required: { type: "anomaly"|"insight"|"event"|"entity", id: number }' };
4688
+ }
4689
+ const target = {
4690
+ type: body.type,
4691
+ id: body.id
4692
+ };
4693
+ const result = await cortexa.explain(target);
4694
+ return { ok: true, data: result };
4695
+ });
4696
+ router.post("/api/ask", async (params) => {
4697
+ const body = params.body;
4698
+ if (!body?.question || typeof body.question !== "string") {
4699
+ return { ok: false, error: "Required: { question: string }" };
4700
+ }
4701
+ const result = await cortexa.ask(body.question, {
4702
+ entityHint: body.entity
4703
+ });
4704
+ return { ok: true, data: result };
4705
+ });
4706
+ router.post("/api/watch", async (params) => {
4707
+ const body = params.body ?? {};
4708
+ await cortexa.watch({
4709
+ interval: body.interval,
4710
+ once: body.once
4711
+ });
4712
+ return { ok: true, data: { watching: true } };
4713
+ });
4714
+ router.post("/api/unwatch", async () => {
4715
+ cortexa.unwatch();
4716
+ return { ok: true, data: { watching: false } };
4717
+ });
4718
+ }
4719
+
4720
+ // src/server/server.ts
4721
+ var CortexaServer = class {
4722
+ cortexa;
4723
+ serverConfig;
4724
+ logger;
4725
+ httpServer = null;
4726
+ constructor(cortexaConfig, serverConfig) {
4727
+ this.cortexa = new Cortexa(cortexaConfig);
4728
+ this.serverConfig = {
4729
+ port: serverConfig?.port ?? 3210,
4730
+ host: serverConfig?.host ?? "127.0.0.1",
4731
+ cors: serverConfig?.cors ?? true
4732
+ };
4733
+ this.logger = createLogger();
4734
+ }
4735
+ async start() {
4736
+ await this.cortexa.connect();
4737
+ const router = new Router();
4738
+ registerHandlers(router, this.cortexa);
4739
+ const cors = this.serverConfig.cors ?? true;
4740
+ this.httpServer = createServer((req, res) => {
4741
+ router.handle(req, res, cors).catch((err) => {
4742
+ this.logger.error({ err }, "Unhandled request error");
4743
+ res.writeHead(500, { "Content-Type": "application/json" });
4744
+ res.end(JSON.stringify({ ok: false, error: "Internal server error" }));
4745
+ });
4746
+ });
4747
+ const { port, host } = this.serverConfig;
4748
+ await new Promise((resolve) => {
4749
+ this.httpServer.listen(port, host, () => {
4750
+ this.logger.info({ port, host }, "Cortexa REST API server started");
4751
+ resolve();
4752
+ });
4753
+ });
4754
+ }
4755
+ async stop() {
4756
+ if (this.httpServer) {
4757
+ await new Promise((resolve, reject) => {
4758
+ this.httpServer.close((err) => {
4759
+ if (err) reject(err);
4760
+ else resolve();
4761
+ });
4762
+ });
4763
+ this.httpServer = null;
4764
+ }
4765
+ await this.cortexa.disconnect();
4766
+ this.logger.info("Cortexa REST API server stopped");
4767
+ }
4768
+ get address() {
4769
+ return {
4770
+ port: this.serverConfig.port ?? 3210,
4771
+ host: this.serverConfig.host ?? "127.0.0.1"
4772
+ };
4773
+ }
4774
+ };
4775
+
4499
4776
  // src/index.ts
4500
4777
  var KnowledgeGraph = class {
4501
4778
  store;
@@ -4799,6 +5076,7 @@ var Cortexa = class extends EventEmitter2 {
4799
5076
  };
4800
5077
  export {
4801
5078
  Cortexa,
5079
+ CortexaServer,
4802
5080
  KnowledgeGraph,
4803
5081
  defineConfig
4804
5082
  };